Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions biome.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
"packages/web-platform/**",

"packages/third-party/**",

"packages/testing-library/**",
],
"rules": {
// We are migrating from ESLint to Biome
Expand Down
4 changes: 4 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ export default tseslint.config(
// TODO: enable eslint for web-platform
// web-platform
'packages/web-platform/**',

// TODO: enable eslint for testing-library
// testing-library
'packages/testing-library/**',
],
},
js.configs.recommended,
Expand Down
3 changes: 3 additions & 0 deletions packages/testing-library/lynx-dom/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# @lynx-js/lynx-dom

Lynx equivalent of [jsdom](https://github.com/jsdom/jsdom)
40 changes: 40 additions & 0 deletions packages/testing-library/lynx-dom/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "@lynx-js/lynx-dom",
"version": "0.0.0",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
"./env/vitest": {
"types": "./dist/env/vitest/index.d.ts",
"import": "./dist/env/vitest/index.mjs",
"require": "./dist/env/vitest/index.js"
}
},
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "rslib build",
"dev": "rslib build --watch"
},
"dependencies": {
"css-what": "^6.1.0",
"pretty-format": "^29.7.0"
},
"devDependencies": {
"@rslib/core": "^0.5.4",
"@testing-library/jest-dom": "^6.6.3",
"@types/jsdom": "^21.1.7",
"@types/node": "^22.13.5",
"@vitest/ui": "^3.0.8",
"jsdom": "^26.0.0",
"typescript": "^5.7.3",
"vitest": "^3.0.8"
}
}
25 changes: 25 additions & 0 deletions packages/testing-library/lynx-dom/rslib.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { defineConfig } from '@rslib/core';

export default defineConfig({
source: {
entry: {
index: './src/**',
},
},
lib: [
{
bundle: false,
format: 'esm',
syntax: 'es2021',
dts: true,
},
{
bundle: false,
format: 'cjs',
syntax: 'es2021',
},
],
output: {
sourceMap: true,
},
});
177 changes: 177 additions & 0 deletions packages/testing-library/lynx-dom/src/__tests__/basic.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';

beforeEach(() => {
lynxDOM.resetLynxEnv();
lynxDOM.switchToMainThread();
});

describe('test', () => {
it('basic element API should work', () => {
const page = __CreatePage('0', 0);
expect(elementTree).toMatchInlineSnapshot(`<page />`);
const view0 = __CreateView(0);
expect(view0).toMatchInlineSnapshot(`<view />`);
expect(view0.$$uiSign).toMatchInlineSnapshot(`1`);
expect(elementTree).toMatchInlineSnapshot(`<page />`);
__AppendElement(page, view0);
expect(elementTree).toMatchInlineSnapshot(`
<page>
<view />
</page>
`);
__AddDataset(view0, 'testid', 'view-element');
expect(elementTree).toMatchInlineSnapshot(`
<page>
<view
data-testid="view-element"
/>
</page>
`);

const view1 = __CreateElement('svg', view0.$$uiSign);
__AddDataset(view1, 'testid', 'svg-element');
__AppendElement(page, view1);
expect(elementTree).toMatchInlineSnapshot(`
<page>
<view
data-testid="view-element"
/>
<svg
data-testid="svg-element"
/>
</page>
`);

const element0 = __CreateElement('custom-element', view0.$$uiSign);
__AddDataset(element0, 'testid', 'custom-element');
__AppendElement(page, element0);
expect(elementTree).toMatchInlineSnapshot(`
<page>
<view
data-testid="view-element"
/>
<svg
data-testid="svg-element"
/>
<custom-element
data-testid="custom-element"
/>
</page>
`);

const text0 = __CreateText(view0.$$uiSign);
const rawText0 = __CreateRawText('Text Element', text0.$$uiSign);
__AppendElement(text0, rawText0);
__AppendElement(view0, text0);

expect(elementTree).toMatchInlineSnapshot(`
<page>
<view
data-testid="view-element"
>
<text>
Text Element
</text>
</view>
<svg
data-testid="svg-element"
/>
<custom-element
data-testid="custom-element"
/>
</page>
`);

const queryByTestId = testId =>
elementTree.root.querySelector(`[data-testid="${testId}"]`);

const viewElement = queryByTestId('view-element');
const svgElement = queryByTestId('svg-element');
const customElement = queryByTestId('custom-element');
const detachedElement = __CreateElement('custom-element', -1);
const fakeElement = { thisIsNot: 'a lynx element' };
const undefinedElement = undefined;
const nullElement = null;
expect(viewElement).toMatchInlineSnapshot(`
<view
data-testid="view-element"
>
<text>
Text Element
</text>
</view>
`);
expect(svgElement).toMatchInlineSnapshot(`
<svg
data-testid="svg-element"
/>
`);
expect(customElement).toMatchInlineSnapshot(`
<custom-element
data-testid="custom-element"
/>
`);
expect(detachedElement).toMatchInlineSnapshot(`<custom-element />`);
expect(fakeElement).toMatchInlineSnapshot(`
{
"thisIsNot": "a lynx element",
}
`);
expect(undefinedElement).toMatchInlineSnapshot(`undefined`);
expect(nullElement).toMatchInlineSnapshot(`null`);
});
it('event listener should work', () => {
const page = __CreatePage('0', 0);
expect(elementTree).toMatchInlineSnapshot(`<page />`);
const view0 = __CreateView(0);
expect(view0).toMatchInlineSnapshot(`<view />`);
__AppendElement(page, view0);
expect(page).toMatchInlineSnapshot(`
<page>
<view />
</page>
`);
__AddEvent(
view0,
'bindEvent',
'tap',
'2:0:bindtap',
);
lynxDOM.switchToBackgroundThread();
lynxCoreInject.tt.publishEvent = (eventHandler, data) => {
expect(eventHandler).toMatchInlineSnapshot(`"2:0:bindtap"`);
expect(data).toMatchInlineSnapshot(`
Event {
"eventName": "tap",
"eventType": "bindEvent",
"isTrusted": false,
"key": "value",
}
`);
};
const event = new Event('bindEvent:tap');
Object.assign(
event,
{
eventType: 'bindEvent',
eventName: 'tap',
key: 'value',
},
);
view0.dispatchEvent(event);
});
it('text should works', () => {
const page = __CreatePage('0', 0);
expect(elementTree).toMatchInlineSnapshot(`<page />`);
const text0 = __CreateText(0);
expect(text0).toMatchInlineSnapshot(`<text />`);
const rawText0 = __CreateElement('raw-text', text0.$$uiSign);
expect(rawText0).toMatchInlineSnapshot(``);
__AppendElement(text0, rawText0);
expect(text0).toMatchInlineSnapshot(`
<text>

</text>
`);
});
});
Loading
Loading