/* globals document */ import { tmpl, domBackend } from '../base/env' import * as glassEasel from '../../src' const componentSpace = new glassEasel.ComponentSpace() componentSpace.updateComponentOptions({ writeFieldsToNode: true, writeIdToDOM: true, }) componentSpace.defineComponent({ is: '', }) describe('domlike backend', () => { beforeAll(() => { domBackend.onEvent(glassEasel.Event.triggerBackendEvent) }) describe('events', () => { it('tap event', () => { const ops: number[] = [] let touch: Touch const Comp = componentSpace .define() .template( tmpl(`
`), ) .init(({ listener }) => { const onTapWrapper = listener<{ x: number; y: number }>((e) => { ops.push(1) expect(e.bubbles).toBe(true) expect(e.detail).toEqual({ x: -1, y: -1 }) }) const onTapButton = listener<{ x: number; y: number }>((e) => { ops.push(2) expect(e.bubbles).toBe(true) expect(e.detail).toEqual({ x: -1, y: -1 }) }) const onTouchStartWrapper = listener((e) => { ops.push(3) expect(e.bubbles).toBe(true) expect(e.detail).toEqual({ altKey: false, changedTouches: [touch], ctrlKey: false, isTrusted: false, metaKey: false, shiftKey: false, targetTouches: [], touches: [touch], }) }) const onTouchStartButton = listener((e) => { ops.push(4) expect(e.bubbles).toBe(true) expect(e.detail).toEqual({ altKey: false, changedTouches: [touch], ctrlKey: false, isTrusted: false, metaKey: false, shiftKey: false, targetTouches: [], touches: [touch], }) }) return { onTapWrapper, onTapButton, onTouchStartWrapper, onTouchStartButton, } }) .registerComponent() const comp = glassEasel.Component.createWithContext('root', Comp, domBackend) const placeholder = document.createElement('span') document.body.appendChild(placeholder) glassEasel.Element.replaceDocumentElement( comp, document.body as any as glassEasel.GeneralBackendElement, placeholder as any as glassEasel.GeneralBackendElement, ) const button = (comp.$.button as glassEasel.Element).$$ as any as HTMLSpanElement touch = { identifier: 0, clientX: -1, clientY: -1, pageX: -1, pageY: -1, screenX: -1, screenY: -1, force: 1, radiusX: 1, radiusY: 1, rotationAngle: 0, target: button, } const touchstart = new TouchEvent('touchstart', { touches: [touch], changedTouches: [touch], bubbles: true, composed: true, }) button.dispatchEvent(touchstart) const touchend = new TouchEvent('touchend', { touches: [], changedTouches: [touch], bubbles: true, composed: true, }) button.dispatchEvent(touchend) expect(ops).toEqual([4, 3, 2, 1]) }) it('non-delegate event', () => { const ops: number[] = [] const Comp = componentSpace .define() .template( tmpl(`
`), ) .init(({ listener }) => { const onKeydownWrapper = listener((e) => { ops.push(5) expect(e.bubbles).toBe(true) }) const onKeydownButton = listener((e) => { ops.push(6) expect(e.bubbles).toBe(true) }) return { onKeydownWrapper, onKeydownButton, } }) .registerComponent() const comp = glassEasel.Component.createWithContext('root', Comp, domBackend) const placeholder = document.createElement('span') document.body.appendChild(placeholder) glassEasel.Element.replaceDocumentElement( comp, document.body as any as glassEasel.GeneralBackendElement, placeholder as any as glassEasel.GeneralBackendElement, ) const button = (comp.$.button as glassEasel.Element).$$ as any as HTMLSpanElement const keydown = new Event('keydown', { bubbles: true, composed: true, }) button.dispatchEvent(keydown) expect(ops).toEqual([6, 5]) }) it('non-bubble event', () => { const ops: number[] = [] const Comp = componentSpace .define() .template( tmpl(`
`), ) .init(({ listener }) => { const onFocusWrapper = listener((e) => { ops.push(5) expect(e.bubbles).toBe(false) }) const onFocusButton = listener((e) => { ops.push(6) expect(e.bubbles).toBe(false) }) return { onFocusWrapper, onFocusButton, } }) .registerComponent() const comp = glassEasel.Component.createWithContext('root', Comp, domBackend) const placeholder = document.createElement('span') document.body.appendChild(placeholder) glassEasel.Element.replaceDocumentElement( comp, document.body as any as glassEasel.GeneralBackendElement, placeholder as any as glassEasel.GeneralBackendElement, ) const button = (comp.$.button as glassEasel.Element).$$ as any as HTMLSpanElement const focus = new Event('focus', { bubbles: false, composed: false, }) button.dispatchEvent(focus) expect(ops).toEqual([6]) }) it('native-rendering event', () => { let ops: number[] = [] const Native = componentSpace .define() .options({ externalComponent: true, }) .template( tmpl(`
`), ) .init(({ listener }) => { const onClick = listener(() => { ops.push(1) }) return { onClick, } }) .registerComponent() const Comp = componentSpace .define() .template( tmpl(`
`), ) .init(({ listener }) => { const onClick = listener(() => { ops.push(2) }) return { onClick, } }) .registerComponent() const Root = componentSpace .define() .usingComponents({ native: Native, comp: Comp, }) .template( tmpl(` `), ) .init(({ listener }) => { const onClick = listener(() => { ops.push(3) }) return { onClick, } }) .registerComponent() const comp = glassEasel.Component.createWithContext('root', Root, domBackend) const placeholder = document.createElement('span') document.body.appendChild(placeholder) glassEasel.Element.replaceDocumentElement( comp, document.body as any as glassEasel.GeneralBackendElement, placeholder as any as glassEasel.GeneralBackendElement, ) const button = (comp.$.button as glassEasel.Element).$$ as any as HTMLButtonElement const native = (comp.$.native as glassEasel.GeneralComponent).$$ as any as HTMLElement const nativeDiv = (comp.$.native as glassEasel.GeneralComponent).$.div as any as HTMLElement const click = new MouseEvent('click', { bubbles: true, composed: true, }) button.dispatchEvent(click) expect(ops).toEqual([1, 2, 3]) ops = [] nativeDiv.dispatchEvent(click) expect(ops).toEqual([1, 2, 3]) ops = [] native.dispatchEvent(click) expect(ops).toEqual([2, 3]) }) }) describe('render', () => { it('render should work', async () => { let renderCallback = false await new Promise((resolve) => { domBackend.render(() => { renderCallback = true resolve() }) }) expect(renderCallback).toBe(true) }) }) })