// @ts-nocheck import { createEvent, fireEvent as domFireEvent } from '@testing-library/dom'; const NodesRef = lynx.createSelectorQuery().selectUniqueID(-1).constructor; function getElement(elemOrNodesRef) { if (elemOrNodesRef instanceof NodesRef) { const { type, identifier } = elemOrNodesRef._nodeSelectToken; // type 0 = `select(cssSelector)` — identifier is a CSS selector string; // type 2 = `selectUniqueID(num)` — identifier is the unique id. return type === 0 ? document.querySelector(identifier) : __GetElementByUniqueId(Number(identifier)); } else if ('refAttr' in elemOrNodesRef) { return document.querySelector(`[react-ref-${elemOrNodesRef.refAttr[0]}-${elemOrNodesRef.refAttr[1]}]`); } else if (elemOrNodesRef?.constructor?.name === 'HTMLUnknownElement') { return elemOrNodesRef; } else { throw new Error( 'Invalid element, got: ' + elemOrNodesRef.constructor?.name, ); } } // Similar to RTL we make are own fireEvent helper that just calls DTL's fireEvent with that // we can that any specific behaviors to the helpers we need export const fireEvent: any = (elemOrNodesRef, ...args) => { const isMainThread = __MAIN_THREAD__; // switch to background thread lynxTestingEnv.switchToBackgroundThread(); const elem = getElement(elemOrNodesRef); const ans = domFireEvent(elem, ...args); if (isMainThread) { // switch back to main thread lynxTestingEnv.switchToMainThread(); } return ans; }; export const eventMap = { // LynxBindCatchEvent — TouchEvent family, bubble/capture per // https://lynx.bytedance.net/next/zh/api/lynx-api/event/touch-event.html tap: { defaultInit: { bubbles: true }, }, longtap: { defaultInit: { bubbles: true }, }, // LynxEvent Events bgload: { defaultInit: {}, }, bgerror: { defaultInit: {}, }, // TouchEvent family — every event whose handler signature is // `EventHandler>` in @lynx-js/types bubbles. Other // LynxEvent entries (animation/transition/mouse/wheel/key/focus/blur/ // layout/image) are component-local and do not propagate. touchstart: { defaultInit: { bubbles: true }, }, touchmove: { defaultInit: { bubbles: true }, }, touchcancel: { defaultInit: { bubbles: true }, }, touchend: { defaultInit: { bubbles: true }, }, longpress: { defaultInit: { bubbles: true }, }, transitionstart: { defaultInit: {}, }, transitioncancel: { defaultInit: {}, }, transitionend: { defaultInit: {}, }, animationstart: { defaultInit: {}, }, animationiteration: { defaultInit: {}, }, animationcancel: { defaultInit: {}, }, animationend: { defaultInit: {}, }, mousedown: { defaultInit: {}, }, mouseup: { defaultInit: {}, }, mousemove: { defaultInit: {}, }, mouseclick: { defaultInit: {}, }, mousedblclick: { defaultInit: {}, }, mouselongpress: { defaultInit: {}, }, wheel: { defaultInit: {}, }, keydown: { defaultInit: {}, }, keyup: { defaultInit: {}, }, focus: { defaultInit: {}, }, blur: { defaultInit: {}, }, layoutchange: { defaultInit: {}, }, scrolltoupper: { defaultInit: {}, }, scrolltolower: { defaultInit: {}, }, scroll: { defaultInit: {}, }, scrollend: { defaultInit: {}, }, contentsizechanged: { defaultInit: {}, }, scrolltoupperedge: { defaultInit: {}, }, scrolltoloweredge: { defaultInit: {}, }, scrolltonormalstate: { defaultInit: {}, }, }; Object.keys(eventMap).forEach((key) => { fireEvent[key] = (elemOrNodesRef, init = {}) => { const isMainThread = __MAIN_THREAD__; // switch to background thread lynxTestingEnv.switchToBackgroundThread(); const elem = getElement(elemOrNodesRef); const eventType = init?.eventType || 'bindEvent'; init = { eventType, eventName: key, ...eventMap[key].defaultInit, ...init, }; const event = createEvent( `${eventType}:${key}`, elem, init, ); // `bubbles`, `cancelable`, `composed` are read-only accessors on Event.prototype. // They're already applied via the EventInit dict above; assigning them again // throws in strict mode. const { bubbles, cancelable, composed, ...assignableInit } = init; Object.assign(event, assignableInit); const ans = domFireEvent( elem, event, ); if (isMainThread) { // switch back to main thread lynxTestingEnv.switchToMainThread(); } return ans; }; });