@react-native-harness/runtime 1.3.0 → 1.4.0-rc.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/dist/collector/functions.d.ts.map +1 -1
- package/dist/collector/functions.js +8 -0
- package/dist/runner/runSuite.d.ts.map +1 -1
- package/dist/runner/runSuite.js +84 -35
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/out-tsc/vitest/src/collector/functions.d.ts.map +1 -1
- package/out-tsc/vitest/src/runner/runSuite.d.ts.map +1 -1
- package/out-tsc/vitest/src/ui/state.d.ts +1 -1
- package/out-tsc/vitest/tsconfig.spec.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/__tests__/runner-context.test.ts +49 -0
- package/src/collector/functions.ts +9 -0
- package/src/runner/runSuite.ts +109 -35
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-native-harness/runtime",
|
|
3
3
|
"description": "The core test runtime that executes on React Native devices, providing Jest-compatible APIs (describe, it, expect) and managing test collection, execution, and result reporting in native environments.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.4.0-rc.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"react-native-url-polyfill": "^3.0.0",
|
|
48
48
|
"use-sync-external-store": "^1.6.0",
|
|
49
49
|
"zustand": "^5.0.5",
|
|
50
|
-
"@react-native-harness/bridge": "1.
|
|
50
|
+
"@react-native-harness/bridge": "1.4.0-rc.1"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/chai": "^5.2.2"
|
|
@@ -439,6 +439,55 @@ describe('runner task context', () => {
|
|
|
439
439
|
}
|
|
440
440
|
});
|
|
441
441
|
|
|
442
|
+
it('returns skipped descendants for describe.skip()', async () => {
|
|
443
|
+
const collector = getTestCollector();
|
|
444
|
+
const runner = getTestRunner();
|
|
445
|
+
|
|
446
|
+
try {
|
|
447
|
+
const collection = await collector.collect(() => {
|
|
448
|
+
harnessDescribe.skip('Skipped Suite', () => {
|
|
449
|
+
harnessIt('skipped test', () => undefined);
|
|
450
|
+
|
|
451
|
+
harnessDescribe('Nested Suite', () => {
|
|
452
|
+
harnessIt('nested skipped test', () => undefined);
|
|
453
|
+
});
|
|
454
|
+
});
|
|
455
|
+
}, 'runtime/describe-skip-descendants.test.ts');
|
|
456
|
+
|
|
457
|
+
const result = await runner.run({
|
|
458
|
+
testSuite: collection.testSuite,
|
|
459
|
+
testFilePath: 'runtime/describe-skip-descendants.test.ts',
|
|
460
|
+
runner: 'ios',
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
expect(result.suites[0]).toMatchObject({
|
|
464
|
+
name: 'Skipped Suite',
|
|
465
|
+
status: 'skipped',
|
|
466
|
+
tests: [
|
|
467
|
+
{
|
|
468
|
+
name: 'skipped test',
|
|
469
|
+
status: 'skipped',
|
|
470
|
+
},
|
|
471
|
+
],
|
|
472
|
+
suites: [
|
|
473
|
+
{
|
|
474
|
+
name: 'Nested Suite',
|
|
475
|
+
status: 'skipped',
|
|
476
|
+
tests: [
|
|
477
|
+
{
|
|
478
|
+
name: 'nested skipped test',
|
|
479
|
+
status: 'skipped',
|
|
480
|
+
},
|
|
481
|
+
],
|
|
482
|
+
},
|
|
483
|
+
],
|
|
484
|
+
});
|
|
485
|
+
} finally {
|
|
486
|
+
collector.dispose();
|
|
487
|
+
runner.dispose();
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
|
|
442
491
|
it('runs onTestFailed when afterEach fails', async () => {
|
|
443
492
|
const calls: string[] = [];
|
|
444
493
|
const collector = getTestCollector();
|
|
@@ -76,10 +76,19 @@ const convertRawTestCaseToTestCase = (
|
|
|
76
76
|
rawTest: RawTestCase,
|
|
77
77
|
suiteContext: { hasFocusedTests: boolean }
|
|
78
78
|
): TestCase => {
|
|
79
|
+
const declarationMode = rawTest.options.todo
|
|
80
|
+
? 'todo'
|
|
81
|
+
: rawTest.options.skip
|
|
82
|
+
? 'skip'
|
|
83
|
+
: rawTest.options.only
|
|
84
|
+
? 'only'
|
|
85
|
+
: undefined;
|
|
86
|
+
|
|
79
87
|
return {
|
|
80
88
|
name: rawTest.name,
|
|
81
89
|
fn: rawTest.fn,
|
|
82
90
|
status: computeTestStatus(rawTest, suiteContext),
|
|
91
|
+
declarationMode,
|
|
83
92
|
};
|
|
84
93
|
};
|
|
85
94
|
|
package/src/runner/runSuite.ts
CHANGED
|
@@ -21,6 +21,55 @@ import {
|
|
|
21
21
|
runOnTestFinished,
|
|
22
22
|
} from './test-context.js';
|
|
23
23
|
|
|
24
|
+
const getAncestorTitles = (suite: TestSuite): string[] => {
|
|
25
|
+
const ancestorTitles: string[] = [];
|
|
26
|
+
let currentSuite = suite.parent;
|
|
27
|
+
|
|
28
|
+
while (currentSuite) {
|
|
29
|
+
if (currentSuite.name !== 'root') {
|
|
30
|
+
ancestorTitles.unshift(currentSuite.name);
|
|
31
|
+
}
|
|
32
|
+
currentSuite = currentSuite.parent;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (suite.name !== 'root') {
|
|
36
|
+
ancestorTitles.push(suite.name);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return ancestorTitles;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const getFullName = (ancestorTitles: string[], testName: string): string =>
|
|
43
|
+
[...ancestorTitles, testName].join(' ');
|
|
44
|
+
|
|
45
|
+
const emitTestFinished = (
|
|
46
|
+
context: TestRunnerContext,
|
|
47
|
+
options: {
|
|
48
|
+
test: TestCase;
|
|
49
|
+
suite: TestSuite;
|
|
50
|
+
startedAt: number;
|
|
51
|
+
duration: number;
|
|
52
|
+
status: 'passed' | 'failed' | 'skipped' | 'todo';
|
|
53
|
+
error?: TestResult['error'];
|
|
54
|
+
},
|
|
55
|
+
) => {
|
|
56
|
+
const ancestorTitles = getAncestorTitles(options.suite);
|
|
57
|
+
|
|
58
|
+
context.events.emit({
|
|
59
|
+
type: 'test-finished',
|
|
60
|
+
file: context.testFilePath,
|
|
61
|
+
suite: options.suite.name,
|
|
62
|
+
name: options.test.name,
|
|
63
|
+
ancestorTitles,
|
|
64
|
+
fullName: getFullName(ancestorTitles, options.test.name),
|
|
65
|
+
startedAt: options.startedAt,
|
|
66
|
+
declarationMode: options.test.declarationMode,
|
|
67
|
+
duration: options.duration,
|
|
68
|
+
error: options.error,
|
|
69
|
+
status: options.status,
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
|
|
24
73
|
declare global {
|
|
25
74
|
var HARNESS_TEST_PATH: string;
|
|
26
75
|
}
|
|
@@ -30,7 +79,7 @@ const runTest = async (
|
|
|
30
79
|
suite: TestSuite,
|
|
31
80
|
context: TestRunnerContext,
|
|
32
81
|
): Promise<TestResult> => {
|
|
33
|
-
const
|
|
82
|
+
const startedAt = Date.now();
|
|
34
83
|
const task: HarnessTaskContext = {
|
|
35
84
|
name: test.name,
|
|
36
85
|
type: 'test',
|
|
@@ -54,11 +103,16 @@ const runTest = async (
|
|
|
54
103
|
);
|
|
55
104
|
|
|
56
105
|
// Emit test-started event
|
|
106
|
+
const ancestorTitles = getAncestorTitles(suite);
|
|
57
107
|
context.events.emit({
|
|
58
108
|
type: 'test-started',
|
|
59
109
|
name: test.name,
|
|
60
110
|
suite: suite.name,
|
|
61
111
|
file: context.testFilePath,
|
|
112
|
+
ancestorTitles,
|
|
113
|
+
fullName: getFullName(ancestorTitles, test.name),
|
|
114
|
+
startedAt,
|
|
115
|
+
declarationMode: test.declarationMode,
|
|
62
116
|
});
|
|
63
117
|
|
|
64
118
|
try {
|
|
@@ -67,14 +121,16 @@ const runTest = async (
|
|
|
67
121
|
name: test.name,
|
|
68
122
|
status: 'skipped' as const,
|
|
69
123
|
duration: 0,
|
|
124
|
+
ancestorTitles,
|
|
125
|
+
fullName: getFullName(ancestorTitles, test.name),
|
|
126
|
+
startedAt,
|
|
127
|
+
declarationMode: test.declarationMode,
|
|
70
128
|
};
|
|
71
129
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
suite: suite.name,
|
|
77
|
-
file: context.testFilePath,
|
|
130
|
+
emitTestFinished(context, {
|
|
131
|
+
test,
|
|
132
|
+
suite,
|
|
133
|
+
startedAt,
|
|
78
134
|
duration: 0,
|
|
79
135
|
status: 'skipped',
|
|
80
136
|
});
|
|
@@ -88,14 +144,16 @@ const runTest = async (
|
|
|
88
144
|
name: test.name,
|
|
89
145
|
status: 'todo' as const,
|
|
90
146
|
duration: 0,
|
|
147
|
+
ancestorTitles,
|
|
148
|
+
fullName: getFullName(ancestorTitles, test.name),
|
|
149
|
+
startedAt,
|
|
150
|
+
declarationMode: test.declarationMode,
|
|
91
151
|
};
|
|
92
152
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
suite: suite.name,
|
|
98
|
-
file: context.testFilePath,
|
|
153
|
+
emitTestFinished(context, {
|
|
154
|
+
test,
|
|
155
|
+
suite,
|
|
156
|
+
startedAt,
|
|
99
157
|
duration: 0,
|
|
100
158
|
status: 'todo',
|
|
101
159
|
});
|
|
@@ -127,7 +185,7 @@ const runTest = async (
|
|
|
127
185
|
}
|
|
128
186
|
|
|
129
187
|
if (didSkip) {
|
|
130
|
-
const duration = Date.now() -
|
|
188
|
+
const duration = Date.now() - startedAt;
|
|
131
189
|
|
|
132
190
|
await runOnTestFinished(lifecycleState);
|
|
133
191
|
|
|
@@ -135,13 +193,16 @@ const runTest = async (
|
|
|
135
193
|
name: test.name,
|
|
136
194
|
status: 'skipped' as const,
|
|
137
195
|
duration,
|
|
196
|
+
ancestorTitles,
|
|
197
|
+
fullName: getFullName(ancestorTitles, test.name),
|
|
198
|
+
startedAt,
|
|
199
|
+
declarationMode: test.declarationMode,
|
|
138
200
|
};
|
|
139
201
|
|
|
140
|
-
context
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
name: test.name,
|
|
202
|
+
emitTestFinished(context, {
|
|
203
|
+
test,
|
|
204
|
+
suite,
|
|
205
|
+
startedAt,
|
|
145
206
|
duration,
|
|
146
207
|
status: 'skipped',
|
|
147
208
|
});
|
|
@@ -155,20 +216,22 @@ const runTest = async (
|
|
|
155
216
|
setCurrentExpectTestState(undefined);
|
|
156
217
|
}
|
|
157
218
|
|
|
158
|
-
const duration = Date.now() -
|
|
219
|
+
const duration = Date.now() - startedAt;
|
|
159
220
|
|
|
160
221
|
const result = {
|
|
161
222
|
name: test.name,
|
|
162
223
|
status: 'passed' as const,
|
|
163
224
|
duration,
|
|
225
|
+
ancestorTitles,
|
|
226
|
+
fullName: getFullName(ancestorTitles, test.name),
|
|
227
|
+
startedAt,
|
|
228
|
+
declarationMode: test.declarationMode,
|
|
164
229
|
};
|
|
165
230
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
suite: suite.name,
|
|
171
|
-
name: test.name,
|
|
231
|
+
emitTestFinished(context, {
|
|
232
|
+
test,
|
|
233
|
+
suite,
|
|
234
|
+
startedAt,
|
|
172
235
|
duration,
|
|
173
236
|
status: 'passed',
|
|
174
237
|
});
|
|
@@ -184,21 +247,23 @@ const runTest = async (
|
|
|
184
247
|
suite.name,
|
|
185
248
|
test.name,
|
|
186
249
|
);
|
|
187
|
-
const duration = Date.now() -
|
|
250
|
+
const duration = Date.now() - startedAt;
|
|
188
251
|
|
|
189
252
|
const result = {
|
|
190
253
|
name: test.name,
|
|
191
254
|
status: 'failed' as const,
|
|
192
255
|
error: testError.toSerializedJSON(),
|
|
193
256
|
duration,
|
|
257
|
+
ancestorTitles,
|
|
258
|
+
fullName: getFullName(ancestorTitles, test.name),
|
|
259
|
+
startedAt,
|
|
260
|
+
declarationMode: test.declarationMode,
|
|
194
261
|
};
|
|
195
262
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
suite: suite.name,
|
|
201
|
-
name: test.name,
|
|
263
|
+
emitTestFinished(context, {
|
|
264
|
+
test,
|
|
265
|
+
suite,
|
|
266
|
+
startedAt,
|
|
202
267
|
duration,
|
|
203
268
|
error: testError.toSerializedJSON(),
|
|
204
269
|
status: 'failed',
|
|
@@ -223,10 +288,19 @@ export const runSuite = async (
|
|
|
223
288
|
|
|
224
289
|
// Check if suite should be skipped or is todo
|
|
225
290
|
if (suite.status === 'skipped') {
|
|
291
|
+
const testResults = await Promise.all(
|
|
292
|
+
suite.tests.map((test) => runTest({ ...test, status: 'skipped' }, suite, context)),
|
|
293
|
+
);
|
|
294
|
+
const suiteResults = await Promise.all(
|
|
295
|
+
suite.suites.map((childSuite) =>
|
|
296
|
+
runSuite({ ...childSuite, status: 'skipped' }, context),
|
|
297
|
+
),
|
|
298
|
+
);
|
|
299
|
+
|
|
226
300
|
const result = {
|
|
227
301
|
name: suite.name,
|
|
228
|
-
tests:
|
|
229
|
-
suites:
|
|
302
|
+
tests: testResults,
|
|
303
|
+
suites: suiteResults,
|
|
230
304
|
status: 'skipped' as const,
|
|
231
305
|
duration: 0,
|
|
232
306
|
};
|