@lynx-js/react 0.106.5 → 0.107.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/package.json +15 -2
- package/refresh/.turbo/turbo-build.log +1 -1
- package/refresh/package.json +1 -1
- package/runtime/jsx-dev-runtime/index.d.ts +12 -0
- package/runtime/jsx-runtime/index.d.ts +12 -0
- package/runtime/lib/lifecycle/patch/commit.d.ts +7 -1
- package/runtime/lib/lifecycle/patch/commit.js +44 -38
- package/runtime/lib/lifecycle/patch/commit.js.map +1 -1
- package/runtime/lib/lifecycle/patch/updateMainThread.js +6 -4
- package/runtime/lib/lifecycle/patch/updateMainThread.js.map +1 -1
- package/runtime/lib/list.d.ts +13 -6
- package/runtime/lib/list.js.map +1 -1
- package/runtime/lib/lynx/calledByNative.js +2 -2
- package/runtime/lib/lynx/calledByNative.js.map +1 -1
- package/runtime/lib/lynx/component.js +1 -1
- package/runtime/lib/lynx/component.js.map +1 -1
- package/runtime/lib/lynx/performance.d.ts +24 -14
- package/runtime/lib/lynx/performance.js +48 -23
- package/runtime/lib/lynx/performance.js.map +1 -1
- package/runtime/lib/lynx/runWithForce.d.ts +1 -0
- package/runtime/lib/lynx/runWithForce.js +45 -0
- package/runtime/lib/lynx/runWithForce.js.map +1 -0
- package/runtime/lib/lynx/tt.d.ts +2 -1
- package/runtime/lib/lynx/tt.js +27 -61
- package/runtime/lib/lynx/tt.js.map +1 -1
- package/runtime/lib/lynx.d.ts +1 -0
- package/runtime/lib/lynx.js +1 -0
- package/runtime/lib/lynx.js.map +1 -1
- package/runtime/src/lifecycle/patch/commit.ts +54 -41
- package/runtime/src/lifecycle/patch/updateMainThread.ts +6 -4
- package/runtime/src/list.ts +18 -10
- package/runtime/src/lynx/calledByNative.ts +2 -2
- package/runtime/src/lynx/component.ts +1 -1
- package/runtime/src/lynx/performance.ts +53 -22
- package/runtime/src/lynx/runWithForce.ts +52 -0
- package/runtime/src/lynx/tt.ts +42 -70
- package/runtime/src/lynx.ts +1 -0
- package/testing-library/README.md +70 -0
- package/testing-library/dist/env/vitest.js +548 -0
- package/testing-library/dist/index.d.ts +1504 -0
- package/testing-library/dist/index.js +12 -0
- package/testing-library/dist/pure.js +14729 -0
- package/testing-library/dist/pure.js.LICENSE.txt +17 -0
- package/testing-library/dist/vitest-global-setup.js +115 -0
- package/testing-library/dist/vitest.config.js +90 -0
- package/testing-library/types/entry.d.ts +257 -0
- package/testing-library/types/index.d.ts +15 -0
- package/testing-library/types/pure.d.ts +2 -0
- package/testing-library/types/vitest-config.d.ts +12 -0
- package/transform/dist/wasm.cjs +1 -1
- package/types/react.d.ts +31 -0
- package/LICENSE +0 -202
|
@@ -109,7 +109,7 @@ if (__JS__) {
|
|
|
109
109
|
const timingFlag = this[NEXT_STATE][PerfSpecificKey];
|
|
110
110
|
if (timingFlag) {
|
|
111
111
|
globalFlushOptions.__lynx_timing_flag = timingFlag;
|
|
112
|
-
markTimingLegacy(PerformanceTimingKeys.
|
|
112
|
+
markTimingLegacy(PerformanceTimingKeys.updateSetStateTrigger, timingFlag);
|
|
113
113
|
this[NEXT_STATE][PerfSpecificKey] = '';
|
|
114
114
|
}
|
|
115
115
|
};
|
|
@@ -6,24 +6,38 @@ import type { VNode } from 'preact';
|
|
|
6
6
|
|
|
7
7
|
import { DIFF } from '../renderToOpcodes/constants.js';
|
|
8
8
|
import { __globalSnapshotPatch } from '../lifecycle/patch/snapshotPatch.js';
|
|
9
|
+
import { isSdkVersionGt } from '../utils.js';
|
|
9
10
|
|
|
10
11
|
enum PerformanceTimingKeys {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
12
|
+
updateSetStateTrigger,
|
|
13
|
+
updateDiffVdomStart,
|
|
14
|
+
updateDiffVdomEnd,
|
|
15
|
+
// updateSetStateTrigger, updateDiffVdomStart and updateDiffVdomEnd is deprecated
|
|
16
|
+
diffVdomStart,
|
|
17
|
+
diffVdomEnd,
|
|
18
|
+
packChangesStart,
|
|
19
|
+
packChangesEnd,
|
|
20
|
+
parseChangesStart,
|
|
21
|
+
parseChangesEnd,
|
|
22
|
+
patchChangesStart,
|
|
23
|
+
patchChangesEnd,
|
|
24
|
+
hydrateParseSnapshotStart,
|
|
25
|
+
hydrateParseSnapshotEnd,
|
|
26
|
+
mtsRenderStart,
|
|
27
|
+
mtsRenderEnd,
|
|
25
28
|
}
|
|
26
29
|
|
|
30
|
+
const PerformanceTimingFlags = {
|
|
31
|
+
reactLynxHydrate: 'react_lynx_hydrate',
|
|
32
|
+
} as const;
|
|
33
|
+
|
|
34
|
+
const PipelineOrigins = {
|
|
35
|
+
reactLynxHydrate: 'reactLynxHydrate',
|
|
36
|
+
updateTriggeredByBts: 'updateTriggeredByBts',
|
|
37
|
+
} as const;
|
|
38
|
+
|
|
39
|
+
type PipelineOrigin = typeof PipelineOrigins[keyof typeof PipelineOrigins];
|
|
40
|
+
|
|
27
41
|
/**
|
|
28
42
|
* @deprecated used by old timing api(setState timing flag)
|
|
29
43
|
*/
|
|
@@ -39,13 +53,13 @@ let globalPipelineOptions: PipelineOptions | undefined;
|
|
|
39
53
|
*/
|
|
40
54
|
function markTimingLegacy(key: PerformanceTimingKeys, timingFlag_?: string): void {
|
|
41
55
|
switch (key) {
|
|
42
|
-
case PerformanceTimingKeys.
|
|
56
|
+
case PerformanceTimingKeys.updateSetStateTrigger: {
|
|
43
57
|
shouldMarkDiffVdomStart = true;
|
|
44
58
|
shouldMarkDiffVdomEnd = true;
|
|
45
59
|
timingFlag = timingFlag_;
|
|
46
60
|
break;
|
|
47
61
|
}
|
|
48
|
-
case PerformanceTimingKeys.
|
|
62
|
+
case PerformanceTimingKeys.updateDiffVdomStart: {
|
|
49
63
|
/* v8 ignore start */
|
|
50
64
|
if (!shouldMarkDiffVdomStart) {
|
|
51
65
|
return;
|
|
@@ -54,7 +68,7 @@ function markTimingLegacy(key: PerformanceTimingKeys, timingFlag_?: string): voi
|
|
|
54
68
|
shouldMarkDiffVdomStart = false;
|
|
55
69
|
break;
|
|
56
70
|
}
|
|
57
|
-
case PerformanceTimingKeys.
|
|
71
|
+
case PerformanceTimingKeys.updateDiffVdomEnd: {
|
|
58
72
|
if (!shouldMarkDiffVdomEnd) {
|
|
59
73
|
return;
|
|
60
74
|
}
|
|
@@ -65,11 +79,26 @@ function markTimingLegacy(key: PerformanceTimingKeys, timingFlag_?: string): voi
|
|
|
65
79
|
lynx.getNativeApp().markTiming?.(timingFlag!, PerformanceTimingKeys[key]);
|
|
66
80
|
}
|
|
67
81
|
|
|
68
|
-
function beginPipeline(needTimestamps: boolean, timingFlag?: string): void {
|
|
82
|
+
function beginPipeline(needTimestamps: boolean, pipelineOrigin: PipelineOrigin, timingFlag?: string): void {
|
|
69
83
|
globalPipelineOptions = lynx.performance?._generatePipelineOptions?.();
|
|
70
84
|
if (globalPipelineOptions) {
|
|
71
85
|
globalPipelineOptions.needTimestamps = needTimestamps;
|
|
72
|
-
|
|
86
|
+
globalPipelineOptions.pipelineOrigin = pipelineOrigin;
|
|
87
|
+
globalPipelineOptions.dsl = 'reactLynx';
|
|
88
|
+
switch (pipelineOrigin) {
|
|
89
|
+
case PipelineOrigins.reactLynxHydrate:
|
|
90
|
+
globalPipelineOptions.stage = 'hydrate';
|
|
91
|
+
break;
|
|
92
|
+
case PipelineOrigins.updateTriggeredByBts:
|
|
93
|
+
globalPipelineOptions.stage = 'update';
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (isSdkVersionGt(3, 0)) {
|
|
98
|
+
lynx.performance?._onPipelineStart?.(globalPipelineOptions.pipelineID, globalPipelineOptions);
|
|
99
|
+
} else {
|
|
100
|
+
lynx.performance?._onPipelineStart?.(globalPipelineOptions.pipelineID);
|
|
101
|
+
}
|
|
73
102
|
if (timingFlag) {
|
|
74
103
|
lynx.performance?._bindPipelineIdWithTimingFlag?.(globalPipelineOptions.pipelineID, timingFlag);
|
|
75
104
|
}
|
|
@@ -92,11 +121,11 @@ function initTimingAPI(): void {
|
|
|
92
121
|
// check `__globalSnapshotPatch` to make sure this only runs after hydrate
|
|
93
122
|
if (__JS__ && __globalSnapshotPatch) {
|
|
94
123
|
if (!globalPipelineOptions) {
|
|
95
|
-
beginPipeline(false);
|
|
96
|
-
markTiming(PerformanceTimingKeys.
|
|
124
|
+
beginPipeline(false, PipelineOrigins.updateTriggeredByBts);
|
|
125
|
+
markTiming(PerformanceTimingKeys.diffVdomStart, true);
|
|
97
126
|
}
|
|
98
127
|
if (shouldMarkDiffVdomStart) {
|
|
99
|
-
markTimingLegacy(PerformanceTimingKeys.
|
|
128
|
+
markTimingLegacy(PerformanceTimingKeys.updateDiffVdomStart);
|
|
100
129
|
}
|
|
101
130
|
}
|
|
102
131
|
oldDiff?.(vnode);
|
|
@@ -108,6 +137,8 @@ function initTimingAPI(): void {
|
|
|
108
137
|
*/
|
|
109
138
|
export {
|
|
110
139
|
PerformanceTimingKeys,
|
|
140
|
+
PerformanceTimingFlags,
|
|
141
|
+
PipelineOrigins,
|
|
111
142
|
PerfSpecificKey,
|
|
112
143
|
markTimingLegacy,
|
|
113
144
|
initTimingAPI,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { options } from 'preact';
|
|
2
|
+
import type { VNode } from 'preact';
|
|
3
|
+
import { COMPONENT, DIFF, DIFFED, FORCE } from '../renderToOpcodes/constants.js';
|
|
4
|
+
|
|
5
|
+
export function runWithForce(cb: () => void): void {
|
|
6
|
+
// save vnode and its `_component` in WeakMap
|
|
7
|
+
const m = new WeakMap<VNode, any>();
|
|
8
|
+
|
|
9
|
+
const oldDiff = options[DIFF];
|
|
10
|
+
|
|
11
|
+
options[DIFF] = (vnode: VNode) => {
|
|
12
|
+
if (oldDiff) {
|
|
13
|
+
oldDiff(vnode);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// when `options[DIFF]` is called, a newVnode is passed in
|
|
17
|
+
// so its `vnode[COMPONENT]` should be null,
|
|
18
|
+
// but it will be set later
|
|
19
|
+
Object.defineProperty(vnode, COMPONENT, {
|
|
20
|
+
configurable: true,
|
|
21
|
+
set(c) {
|
|
22
|
+
m.set(vnode, c);
|
|
23
|
+
if (c) {
|
|
24
|
+
c[FORCE] = true;
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
get() {
|
|
28
|
+
return m.get(vnode);
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const oldDiffed = options[DIFFED];
|
|
34
|
+
|
|
35
|
+
options[DIFFED] = (vnode: VNode) => {
|
|
36
|
+
if (oldDiffed) {
|
|
37
|
+
oldDiffed(vnode);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// delete is a reverse operation of previous `Object.defineProperty`
|
|
41
|
+
delete vnode[COMPONENT];
|
|
42
|
+
// restore
|
|
43
|
+
vnode[COMPONENT] = m.get(vnode);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
cb();
|
|
48
|
+
} finally {
|
|
49
|
+
options[DIFF] = oldDiff as (vnode: VNode) => void;
|
|
50
|
+
options[DIFFED] = oldDiffed as (vnode: VNode) => void;
|
|
51
|
+
}
|
|
52
|
+
}
|
package/runtime/src/lynx/tt.ts
CHANGED
|
@@ -1,72 +1,35 @@
|
|
|
1
1
|
// Copyright 2024 The Lynx Authors. All rights reserved.
|
|
2
2
|
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
3
|
// LICENSE file in the root directory of this source tree.
|
|
4
|
-
import { options } from 'preact';
|
|
5
|
-
import type { VNode } from 'preact';
|
|
6
|
-
|
|
7
4
|
import { LifecycleConstant, NativeUpdateDataType } from '../lifecycleConstant.js';
|
|
8
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
PerformanceTimingKeys,
|
|
7
|
+
PerformanceTimingFlags,
|
|
8
|
+
PipelineOrigins,
|
|
9
|
+
beginPipeline,
|
|
10
|
+
markTiming,
|
|
11
|
+
} from './performance.js';
|
|
9
12
|
import { BackgroundSnapshotInstance, hydrate } from '../backgroundSnapshot.js';
|
|
10
13
|
import { destroyBackground } from '../lifecycle/destroy.js';
|
|
11
14
|
import { delayedEvents, delayedPublishEvent } from '../lifecycle/event/delayEvents.js';
|
|
12
15
|
import { delayLifecycleEvent, delayedLifecycleEvents } from '../lifecycle/event/delayLifecycleEvents.js';
|
|
13
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
clearPatchesToCommit,
|
|
18
|
+
commitPatchUpdate,
|
|
19
|
+
genCommitTaskId,
|
|
20
|
+
globalCommitTaskMap,
|
|
21
|
+
patchesToCommit,
|
|
22
|
+
type PatchList,
|
|
23
|
+
} from '../lifecycle/patch/commit.js';
|
|
14
24
|
import { reloadBackground } from '../lifecycle/reload.js';
|
|
15
25
|
import { renderBackground } from '../lifecycle/render.js';
|
|
16
|
-
import { CHILDREN
|
|
26
|
+
import { CHILDREN } from '../renderToOpcodes/constants.js';
|
|
17
27
|
import { __root } from '../root.js';
|
|
18
28
|
import { globalRefsToSet, updateBackgroundRefs } from '../snapshot/ref.js';
|
|
19
29
|
import { backgroundSnapshotInstanceManager } from '../snapshot.js';
|
|
20
30
|
import { destroyWorklet } from '../worklet/destroy.js';
|
|
21
|
-
|
|
22
|
-
export
|
|
23
|
-
// save vnode and its `_component` in WeakMap
|
|
24
|
-
const m = new WeakMap<VNode, any>();
|
|
25
|
-
|
|
26
|
-
const oldDiff = options[DIFF];
|
|
27
|
-
|
|
28
|
-
options[DIFF] = (vnode: VNode) => {
|
|
29
|
-
if (oldDiff) {
|
|
30
|
-
oldDiff(vnode);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// when `options[DIFF]` is called, a newVnode is passed in
|
|
34
|
-
// so its `vnode[COMPONENT]` should be null,
|
|
35
|
-
// but it will be set later
|
|
36
|
-
Object.defineProperty(vnode, COMPONENT, {
|
|
37
|
-
configurable: true,
|
|
38
|
-
set(c) {
|
|
39
|
-
m.set(vnode, c);
|
|
40
|
-
if (c) {
|
|
41
|
-
c[FORCE] = true;
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
get() {
|
|
45
|
-
return m.get(vnode);
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const oldDiffed = options[DIFFED];
|
|
51
|
-
|
|
52
|
-
options[DIFFED] = (vnode: VNode) => {
|
|
53
|
-
if (oldDiffed) {
|
|
54
|
-
oldDiffed(vnode);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// delete is a reverse operation of previous `Object.defineProperty`
|
|
58
|
-
delete vnode[COMPONENT];
|
|
59
|
-
// restore
|
|
60
|
-
vnode[COMPONENT] = m.get(vnode);
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
try {
|
|
64
|
-
cb();
|
|
65
|
-
} finally {
|
|
66
|
-
options[DIFF] = oldDiff as (vnode: VNode) => void;
|
|
67
|
-
options[DIFFED] = oldDiffed as (vnode: VNode) => void;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
31
|
+
import { runWithForce } from './runWithForce.js';
|
|
32
|
+
export { runWithForce };
|
|
70
33
|
|
|
71
34
|
function injectTt(): void {
|
|
72
35
|
// @ts-ignore
|
|
@@ -100,7 +63,7 @@ function onLifecycleEvent([type, data]: [string, any]) {
|
|
|
100
63
|
}
|
|
101
64
|
|
|
102
65
|
try {
|
|
103
|
-
|
|
66
|
+
onLifecycleEventImpl(type, data);
|
|
104
67
|
} catch (e) {
|
|
105
68
|
lynx.reportError(e as Error);
|
|
106
69
|
}
|
|
@@ -110,18 +73,18 @@ function onLifecycleEvent([type, data]: [string, any]) {
|
|
|
110
73
|
}
|
|
111
74
|
}
|
|
112
75
|
|
|
113
|
-
|
|
76
|
+
function onLifecycleEventImpl(type: string, data: any): void {
|
|
114
77
|
switch (type) {
|
|
115
78
|
case LifecycleConstant.firstScreen: {
|
|
116
79
|
const { root: lepusSide, refPatch, jsReadyEventIdSwap } = data;
|
|
117
80
|
if (__PROFILE__) {
|
|
118
81
|
console.profile('hydrate');
|
|
119
82
|
}
|
|
120
|
-
beginPipeline(true,
|
|
121
|
-
markTiming(PerformanceTimingKeys.
|
|
83
|
+
beginPipeline(true, PipelineOrigins.reactLynxHydrate, PerformanceTimingFlags.reactLynxHydrate);
|
|
84
|
+
markTiming(PerformanceTimingKeys.hydrateParseSnapshotStart);
|
|
122
85
|
const before = JSON.parse(lepusSide);
|
|
123
|
-
markTiming(PerformanceTimingKeys.
|
|
124
|
-
markTiming(PerformanceTimingKeys.
|
|
86
|
+
markTiming(PerformanceTimingKeys.hydrateParseSnapshotEnd);
|
|
87
|
+
markTiming(PerformanceTimingKeys.diffVdomStart);
|
|
125
88
|
const snapshotPatch = hydrate(
|
|
126
89
|
before,
|
|
127
90
|
__root as BackgroundSnapshotInstance,
|
|
@@ -129,7 +92,7 @@ async function onLifecycleEventImpl(type: string, data: any): Promise<void> {
|
|
|
129
92
|
if (__PROFILE__) {
|
|
130
93
|
console.profileEnd();
|
|
131
94
|
}
|
|
132
|
-
markTiming(PerformanceTimingKeys.
|
|
95
|
+
markTiming(PerformanceTimingKeys.diffVdomEnd);
|
|
133
96
|
|
|
134
97
|
// TODO: It seems `delayedEvents` and `delayedLifecycleEvents` should be merged into one array to ensure the proper order of events.
|
|
135
98
|
flushDelayedLifecycleEvents();
|
|
@@ -166,14 +129,23 @@ async function onLifecycleEventImpl(type: string, data: any): Promise<void> {
|
|
|
166
129
|
console.profile('commitChanges');
|
|
167
130
|
}
|
|
168
131
|
const commitTaskId = genCommitTaskId();
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
132
|
+
patchesToCommit.push(
|
|
133
|
+
{ snapshotPatch, id: commitTaskId },
|
|
134
|
+
);
|
|
135
|
+
const patchList: PatchList = {
|
|
136
|
+
patchList: patchesToCommit,
|
|
137
|
+
};
|
|
138
|
+
clearPatchesToCommit();
|
|
139
|
+
const obj = commitPatchUpdate(patchList, { isHydration: true });
|
|
140
|
+
lynx.getNativeApp().callLepusMethod(LifecycleConstant.patchUpdate, obj, () => {
|
|
141
|
+
updateBackgroundRefs(commitTaskId);
|
|
142
|
+
globalCommitTaskMap.forEach((commitTask, id) => {
|
|
143
|
+
if (id > commitTaskId) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
commitTask();
|
|
147
|
+
globalCommitTaskMap.delete(id);
|
|
148
|
+
});
|
|
177
149
|
});
|
|
178
150
|
break;
|
|
179
151
|
}
|
package/runtime/src/lynx.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { setupLynxEnv } from './lynx/env.js';
|
|
|
15
15
|
import { injectLepusMethods } from './lynx/injectLepusMethods.js';
|
|
16
16
|
import { initTimingAPI } from './lynx/performance.js';
|
|
17
17
|
import { injectTt } from './lynx/tt.js';
|
|
18
|
+
export { runWithForce } from './lynx/runWithForce.js';
|
|
18
19
|
|
|
19
20
|
// @ts-expect-error Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature
|
|
20
21
|
if (__LEPUS__ && typeof globalThis.processEvalResult === 'undefined') {
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# @lynx-js/react/testing-library
|
|
2
|
+
|
|
3
|
+
ReactLynx Testing Library is a simple and complete ReactLynx unit testing library that encourages good testing practices.
|
|
4
|
+
|
|
5
|
+
> Inspired completely by [react-testing-library](https://github.com/testing-library/react-testing-library)
|
|
6
|
+
|
|
7
|
+
Similar to [react-testing-library](https://github.com/testing-library/react-testing-library), this library is designed to test your ReactLynx components in the same way you would test React components using react-testing-library.
|
|
8
|
+
|
|
9
|
+
## Setup
|
|
10
|
+
|
|
11
|
+
Setup vitest:
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
// vitest.config.js
|
|
15
|
+
import { defineConfig, mergeConfig } from 'vitest/config';
|
|
16
|
+
import { createVitestConfig } from '@lynx-js/react/testing-library/vitest-config';
|
|
17
|
+
|
|
18
|
+
const defaultConfig = createVitestConfig();
|
|
19
|
+
const config = defineConfig({
|
|
20
|
+
test: {
|
|
21
|
+
// ...
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export default mergeConfig(defaultConfig, config);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Then you can start writing tests and run them with vitest!
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
import '@testing-library/jest-dom';
|
|
34
|
+
import { test, expect } from 'vitest';
|
|
35
|
+
import { render } from '@lynx-js/react/testing-library';
|
|
36
|
+
|
|
37
|
+
test('renders options.wrapper around node', async () => {
|
|
38
|
+
const WrapperComponent = ({ children }) => (
|
|
39
|
+
<view data-testid='wrapper'>{children}</view>
|
|
40
|
+
);
|
|
41
|
+
const Comp = () => {
|
|
42
|
+
return <view data-testid='inner' style='background-color: yellow;' />;
|
|
43
|
+
};
|
|
44
|
+
const { container, getByTestId } = render(<Comp />, {
|
|
45
|
+
wrapper: WrapperComponent,
|
|
46
|
+
});
|
|
47
|
+
expect(getByTestId('wrapper')).toBeInTheDocument();
|
|
48
|
+
expect(container.firstChild).toMatchInlineSnapshot(`
|
|
49
|
+
<view
|
|
50
|
+
data-testid="wrapper"
|
|
51
|
+
>
|
|
52
|
+
<view
|
|
53
|
+
data-testid="inner"
|
|
54
|
+
style="background-color: yellow;"
|
|
55
|
+
/>
|
|
56
|
+
</view>
|
|
57
|
+
`);
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
💡 Since our testing environment (`@lynx-js/test-environment`) is based on jsdom, You may also be interested in installing `@testing-library/jest-dom` so you can use
|
|
62
|
+
[the custom jest matchers](https://github.com/testing-library/jest-dom).
|
|
63
|
+
|
|
64
|
+
## Examples
|
|
65
|
+
|
|
66
|
+
See our [examples](https://github.com/lynx-family/lynx-stack/tree/main/packages/react/testing-library/src/__tests__) for more usage.
|
|
67
|
+
|
|
68
|
+
## Credits
|
|
69
|
+
|
|
70
|
+
- [Testing Library](https://testing-library.com/) for the testing utilities and good practices for React testing.
|