@react-native-harness/runtime 1.0.0-alpha.15 → 1.0.0-alpha.17
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/assets/moduleSystem.flow.js +15 -98
- package/dist/bundler/evaluate.d.ts.map +1 -1
- package/dist/bundler/evaluate.js +7 -7
- package/dist/client/factory.d.ts.map +1 -1
- package/dist/client/factory.js +26 -6
- package/dist/client/setup-files.d.ts +12 -0
- package/dist/client/setup-files.d.ts.map +1 -0
- package/dist/client/setup-files.js +60 -0
- package/dist/collector/functions.d.ts +1 -1
- package/dist/collector/functions.d.ts.map +1 -1
- package/dist/collector/functions.js +2 -2
- package/dist/collector/types.d.ts +1 -1
- package/dist/collector/types.d.ts.map +1 -1
- package/dist/entry-point.d.ts +2 -0
- package/dist/entry-point.d.ts.map +1 -0
- package/dist/entry-point.js +4 -0
- package/dist/filtering/index.d.ts +1 -1
- package/dist/filtering/index.d.ts.map +1 -1
- package/dist/filtering/index.js +1 -1
- package/dist/filtering/testNameFilter.d.ts +6 -0
- package/dist/filtering/testNameFilter.d.ts.map +1 -1
- package/dist/filtering/testNameFilter.js +36 -5
- package/dist/globals.d.ts +5 -2
- package/dist/globals.d.ts.map +1 -1
- package/dist/globals.js +7 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/initialize.js +7 -0
- package/dist/jest-mock.d.ts +2 -0
- package/dist/jest-mock.d.ts.map +1 -0
- package/dist/jest-mock.js +25 -0
- package/dist/render/ErrorBoundary.d.ts +17 -0
- package/dist/render/ErrorBoundary.d.ts.map +1 -0
- package/dist/render/ErrorBoundary.js +73 -0
- package/dist/render/TestComponentOverlay.d.ts +3 -0
- package/dist/render/TestComponentOverlay.d.ts.map +1 -0
- package/dist/render/TestComponentOverlay.js +36 -0
- package/dist/render/cleanup.d.ts +2 -0
- package/dist/render/cleanup.d.ts.map +1 -0
- package/dist/render/cleanup.js +6 -0
- package/dist/render/index.d.ts +6 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +66 -0
- package/dist/render/setup.d.ts +2 -0
- package/dist/render/setup.d.ts.map +1 -0
- package/dist/render/setup.js +7 -0
- package/dist/render/types.d.ts +12 -0
- package/dist/render/types.d.ts.map +1 -0
- package/dist/render/types.js +1 -0
- package/dist/runner/factory.d.ts.map +1 -1
- package/dist/runner/factory.js +6 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/ui/ReadyScreen.d.ts.map +1 -1
- package/dist/ui/ReadyScreen.js +2 -1
- package/dist/ui/state.d.ts +14 -1
- package/dist/ui/state.d.ts.map +1 -1
- package/dist/ui/state.js +22 -0
- package/out-tsc/vitest/src/client/factory.d.ts.map +1 -1
- package/out-tsc/vitest/src/entry-point.d.ts +2 -0
- package/out-tsc/vitest/src/entry-point.d.ts.map +1 -0
- package/out-tsc/vitest/src/filtering/index.d.ts +1 -1
- package/out-tsc/vitest/src/filtering/index.d.ts.map +1 -1
- package/out-tsc/vitest/src/filtering/testNameFilter.d.ts +6 -0
- package/out-tsc/vitest/src/filtering/testNameFilter.d.ts.map +1 -1
- package/out-tsc/vitest/src/globals.d.ts +5 -2
- package/out-tsc/vitest/src/globals.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 +10 -4
- package/src/__tests__/collector.test.ts +55 -55
- package/src/__tests__/error-handling.test.ts +34 -34
- package/src/bundler/bundle.ts +1 -2
- package/src/bundler/evaluate.ts +9 -9
- package/src/client/factory.ts +31 -9
- package/src/client/setup-files.ts +81 -0
- package/src/collector/functions.ts +4 -2
- package/src/collector/types.ts +4 -1
- package/src/entry-point.ts +8 -0
- package/src/filtering/index.ts +4 -1
- package/src/filtering/testNameFilter.ts +53 -8
- package/src/globals.ts +14 -2
- package/src/index.ts +1 -0
- package/src/initialize.ts +11 -1
- package/src/jest-mock.ts +32 -0
- package/src/mocker/metro-require.d.ts +1 -0
- package/src/react-native.d.ts +0 -8
- package/src/render/ErrorBoundary.tsx +108 -0
- package/src/render/TestComponentOverlay.tsx +47 -0
- package/src/render/cleanup.ts +7 -0
- package/src/render/index.ts +96 -0
- package/src/render/setup.ts +8 -0
- package/src/render/types.ts +11 -0
- package/src/runner/factory.ts +8 -1
- package/src/ui/ReadyScreen.tsx +2 -0
- package/src/ui/state.ts +39 -0
- package/out-tsc/tsconfig.spec.tsbuildinfo +0 -1
- package/types/global.d.ts +0 -2
- package/types/index.d.ts +0 -1
|
@@ -85,6 +85,7 @@ global[`${__METRO_GLOBAL_PREFIX__}__d`] = (define: DefineFn);
|
|
|
85
85
|
global.__c = clear;
|
|
86
86
|
global.__registerSegment = registerSegment;
|
|
87
87
|
global.__resetAllModules = resetAllModules;
|
|
88
|
+
global.__clearModule = clearModule;
|
|
88
89
|
|
|
89
90
|
var modules = clear();
|
|
90
91
|
|
|
@@ -95,6 +96,14 @@ function resetAllModules() {
|
|
|
95
96
|
});
|
|
96
97
|
}
|
|
97
98
|
|
|
99
|
+
function clearModule(moduleId: ModuleID) {
|
|
100
|
+
if (!modules.has(moduleId)) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
modules.delete(moduleId);
|
|
105
|
+
}
|
|
106
|
+
|
|
98
107
|
// Don't use a Symbol here, it would pull in an extra polyfill with all sorts of
|
|
99
108
|
// additional stuff (e.g. Array.from).
|
|
100
109
|
const EMPTY = {};
|
|
@@ -223,15 +232,6 @@ function metroRequire(
|
|
|
223
232
|
|
|
224
233
|
const module = modules.get(moduleIdReallyIsNumber);
|
|
225
234
|
|
|
226
|
-
// Optionally return a lazy proxy that triggers evaluation on first access.
|
|
227
|
-
if (
|
|
228
|
-
module &&
|
|
229
|
-
!module.isInitialized &&
|
|
230
|
-
shouldUseLazyModuleProxy(moduleIdReallyIsNumber, module)
|
|
231
|
-
) {
|
|
232
|
-
return createModuleEvaluationProxy(moduleIdReallyIsNumber);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
235
|
return module && module.isInitialized
|
|
236
236
|
? module.publicModule.exports
|
|
237
237
|
: guardedLoadModule(moduleIdReallyIsNumber, module);
|
|
@@ -398,92 +398,6 @@ function packModuleId(value: {
|
|
|
398
398
|
}
|
|
399
399
|
metroRequire.packModuleId = packModuleId;
|
|
400
400
|
|
|
401
|
-
// ------------------------------
|
|
402
|
-
// Lazy evaluation via Proxy (opt-in)
|
|
403
|
-
// ------------------------------
|
|
404
|
-
const LAZY_REQUIRE_FLAG_KEY =
|
|
405
|
-
__METRO_GLOBAL_PREFIX__ + '__LAZY_REQUIRE_BY_ACCESS';
|
|
406
|
-
const LAZY_REQUIRE_ALLOW_DEV_KEY =
|
|
407
|
-
__METRO_GLOBAL_PREFIX__ + '__LAZY_REQUIRE_ALLOW_DEV';
|
|
408
|
-
const LAZY_REQUIRE_WHITELIST_KEY =
|
|
409
|
-
__METRO_GLOBAL_PREFIX__ + '__LAZY_REQUIRE_WHITELIST';
|
|
410
|
-
|
|
411
|
-
function isLazyRequireEnabled(): boolean {
|
|
412
|
-
// const enabled = global[LAZY_REQUIRE_FLAG_KEY];
|
|
413
|
-
// if (!enabled) {
|
|
414
|
-
// return false;
|
|
415
|
-
// }
|
|
416
|
-
// // In DEV, require explicit opt-in due to HMR/export inspection.
|
|
417
|
-
// return __DEV__ ? !!global[LAZY_REQUIRE_ALLOW_DEV_KEY] : true;
|
|
418
|
-
return true;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
function isModuleWhitelisted(moduleId: ModuleID): boolean {
|
|
422
|
-
const list = global[LAZY_REQUIRE_WHITELIST_KEY];
|
|
423
|
-
if (list == null) {
|
|
424
|
-
// No whitelist provided -> treat as disabled for safety unless explicitly enabled
|
|
425
|
-
// at call site (we still require shouldUseLazyModuleProxy to decide).
|
|
426
|
-
return false;
|
|
427
|
-
}
|
|
428
|
-
return Array.isArray(list) && list.indexOf(moduleId) !== -1;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
function shouldUseLazyModuleProxy(
|
|
432
|
-
moduleId: ModuleID,
|
|
433
|
-
module: ?ModuleDefinition
|
|
434
|
-
): boolean {
|
|
435
|
-
if (!isLazyRequireEnabled()) {
|
|
436
|
-
return false;
|
|
437
|
-
}
|
|
438
|
-
if (!module || module.isInitialized) {
|
|
439
|
-
return false;
|
|
440
|
-
}
|
|
441
|
-
// Only enable for explicitly whitelisted modules to avoid changing semantics
|
|
442
|
-
// of side-effect-only requires.
|
|
443
|
-
return isModuleWhitelisted(moduleId);
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
function createModuleEvaluationProxy(moduleId: ModuleID): Exports {
|
|
447
|
-
let evaluated = false;
|
|
448
|
-
const ensure = (): Exports => {
|
|
449
|
-
if (!evaluated) {
|
|
450
|
-
// Evaluate the module using the same guarded path used by metroRequire.
|
|
451
|
-
// Pass the current (possibly undefined) ModuleDefinition for better error messages.
|
|
452
|
-
const existing = modules.get(moduleId);
|
|
453
|
-
// guardedLoadModule will throw appropriately if unknown or failing.
|
|
454
|
-
// It will also set module.isInitialized and publicModule.exports.
|
|
455
|
-
// $FlowFixMe[incompatible-call]
|
|
456
|
-
guardedLoadModule(moduleId, existing);
|
|
457
|
-
console.log('evaluated module', moduleId);
|
|
458
|
-
evaluated = true;
|
|
459
|
-
}
|
|
460
|
-
// $FlowFixMe[incompatible-type]
|
|
461
|
-
const initializedModule: ModuleDefinition | void = modules.get(moduleId);
|
|
462
|
-
// $FlowFixMe[incompatible-use]
|
|
463
|
-
return initializedModule
|
|
464
|
-
? initializedModule.publicModule.exports
|
|
465
|
-
: undefined;
|
|
466
|
-
};
|
|
467
|
-
|
|
468
|
-
// Use an object target since CommonJS exports are objects in Metro.
|
|
469
|
-
const target = {};
|
|
470
|
-
return new Proxy(target, {
|
|
471
|
-
get: (_t, prop) => Reflect.get(ensure(), prop),
|
|
472
|
-
set: (_t, prop, value) => Reflect.set(ensure(), prop, value),
|
|
473
|
-
has: (_t, prop) => Reflect.has(ensure(), prop),
|
|
474
|
-
ownKeys: () => Reflect.ownKeys(ensure()),
|
|
475
|
-
getOwnPropertyDescriptor: (_t, prop) =>
|
|
476
|
-
Reflect.getOwnPropertyDescriptor(ensure(), prop),
|
|
477
|
-
getPrototypeOf: () => Reflect.getPrototypeOf(ensure()),
|
|
478
|
-
setPrototypeOf: (_t, proto) => Reflect.setPrototypeOf(ensure(), proto),
|
|
479
|
-
isExtensible: () => Reflect.isExtensible(ensure()),
|
|
480
|
-
preventExtensions: () => Reflect.preventExtensions(ensure()),
|
|
481
|
-
defineProperty: (_t, prop, desc) =>
|
|
482
|
-
Reflect.defineProperty(ensure(), prop, desc),
|
|
483
|
-
deleteProperty: (_t, prop) => Reflect.deleteProperty(ensure(), prop),
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
|
|
487
401
|
const moduleDefinersBySegmentID: Array<?ModuleDefiner> = [];
|
|
488
402
|
const definingSegmentByModuleID: Map<ModuleID, number> = new Map();
|
|
489
403
|
|
|
@@ -588,11 +502,14 @@ function loadModuleImplementation(
|
|
|
588
502
|
// keep args in sync with with defineModuleCode in
|
|
589
503
|
// metro/src/Resolver/index.js
|
|
590
504
|
// and metro/src/ModuleGraph/worker.js
|
|
505
|
+
const capturedRequire = (...args) => global.__r(...args);
|
|
506
|
+
Object.assign(capturedRequire, global.__r);
|
|
507
|
+
|
|
591
508
|
factory(
|
|
592
509
|
global,
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
510
|
+
capturedRequire,
|
|
511
|
+
capturedRequire.importDefault,
|
|
512
|
+
capturedRequire.importAll,
|
|
596
513
|
moduleObject,
|
|
597
514
|
moduleObject.exports,
|
|
598
515
|
dependencyMap
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/bundler/evaluate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/bundler/evaluate.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,GAAI,UAAU,MAAM,EAAE,YAAY,MAAM,KAAG,IAsBrE,CAAC"}
|
package/dist/bundler/evaluate.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { MalformedModuleError } from './errors.js';
|
|
2
|
-
import { EnvironmentError } from '../errors.js';
|
|
3
2
|
export const evaluateModule = (moduleJs, modulePath) => {
|
|
4
|
-
const
|
|
5
|
-
if (
|
|
3
|
+
const __rMatches = Array.from(moduleJs.matchAll(/__r\((\d+)\)/g));
|
|
4
|
+
if (__rMatches.length === 0) {
|
|
6
5
|
throw new MalformedModuleError(modulePath, 'No __r function found');
|
|
7
6
|
}
|
|
7
|
+
// Get the last match as there may be many require calls
|
|
8
|
+
const __rMatch = __rMatches[__rMatches.length - 1];
|
|
8
9
|
const __rParam = __rMatch[1];
|
|
9
10
|
if (!__rParam) {
|
|
10
11
|
throw new MalformedModuleError(modulePath, 'No __r parameter found');
|
|
11
12
|
}
|
|
13
|
+
const moduleId = Number(__rParam);
|
|
14
|
+
// This is important as if module was already initialized, it would not be re-initialized
|
|
15
|
+
global.__clearModule(moduleId);
|
|
12
16
|
// eslint-disable-next-line no-eval
|
|
13
17
|
eval(moduleJs);
|
|
14
|
-
if (!__r) {
|
|
15
|
-
throw new EnvironmentError('module evaluation', '__r is not defined');
|
|
16
|
-
}
|
|
17
|
-
__r(Number(__rParam));
|
|
18
18
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/client/factory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/client/factory.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,SAAS,2EAgFrB,CAAC"}
|
package/dist/client/factory.js
CHANGED
|
@@ -5,7 +5,9 @@ import { getTestCollector } from '../collector/index.js';
|
|
|
5
5
|
import { combineEventEmitters } from '../utils/emitter.js';
|
|
6
6
|
import { getWSServer } from './getWSServer.js';
|
|
7
7
|
import { getBundler, evaluateModule } from '../bundler/index.js';
|
|
8
|
-
import {
|
|
8
|
+
import { markTestsAsSkippedByName } from '../filtering/index.js';
|
|
9
|
+
import { setup } from '../render/setup.js';
|
|
10
|
+
import { runSetupFiles } from './setup-files.js';
|
|
9
11
|
export const getClient = async () => {
|
|
10
12
|
const client = await getBridgeClient(getWSServer(), {
|
|
11
13
|
runTests: async () => {
|
|
@@ -29,13 +31,31 @@ export const getClient = async () => {
|
|
|
29
31
|
events.addListener((event) => {
|
|
30
32
|
client.rpc.emitEvent(event.type, event);
|
|
31
33
|
});
|
|
34
|
+
await runSetupFiles({
|
|
35
|
+
setupFiles: options.setupFiles ?? [],
|
|
36
|
+
setupFilesAfterEnv: [],
|
|
37
|
+
events: events,
|
|
38
|
+
bundler: bundler,
|
|
39
|
+
evaluateModule,
|
|
40
|
+
});
|
|
32
41
|
const moduleJs = await bundler.getModule(path);
|
|
33
|
-
const collectionResult = await collector.collect(() =>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
42
|
+
const collectionResult = await collector.collect(async () => {
|
|
43
|
+
await runSetupFiles({
|
|
44
|
+
setupFiles: [],
|
|
45
|
+
setupFilesAfterEnv: options.setupFilesAfterEnv ?? [],
|
|
46
|
+
events: events,
|
|
47
|
+
bundler: bundler,
|
|
48
|
+
evaluateModule,
|
|
49
|
+
});
|
|
50
|
+
// Setup automatic cleanup for rendered components
|
|
51
|
+
setup();
|
|
52
|
+
evaluateModule(moduleJs, path);
|
|
53
|
+
}, path);
|
|
54
|
+
// Apply test name pattern by marking non-matching tests as skipped
|
|
55
|
+
const processedTestSuite = options.testNamePattern
|
|
56
|
+
? markTestsAsSkippedByName(collectionResult.testSuite, options.testNamePattern)
|
|
37
57
|
: collectionResult.testSuite;
|
|
38
|
-
const result = await runner.run(
|
|
58
|
+
const result = await runner.run(processedTestSuite, path);
|
|
39
59
|
return result;
|
|
40
60
|
}
|
|
41
61
|
finally {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { EventEmitter } from '../utils/emitter.js';
|
|
2
|
+
import { Bundler } from '../bundler/index.js';
|
|
3
|
+
import { BundlerEvents } from '@react-native-harness/bridge';
|
|
4
|
+
export type RunSetupFilesOptions = {
|
|
5
|
+
setupFiles: string[];
|
|
6
|
+
setupFilesAfterEnv: string[];
|
|
7
|
+
events: EventEmitter<BundlerEvents>;
|
|
8
|
+
bundler: Bundler;
|
|
9
|
+
evaluateModule: (moduleJs: string, filePath: string) => void;
|
|
10
|
+
};
|
|
11
|
+
export declare const runSetupFiles: ({ setupFiles, setupFilesAfterEnv, events, bundler, evaluateModule, }: RunSetupFilesOptions) => Promise<void>;
|
|
12
|
+
//# sourceMappingURL=setup-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-files.d.ts","sourceRoot":"","sources":["../../src/client/setup-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,MAAM,MAAM,oBAAoB,GAAG;IACjC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,MAAM,EAAE,YAAY,CAAC,aAAa,CAAC,CAAC;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9D,CAAC;AAEF,eAAO,MAAM,aAAa,GAAU,sEAMjC,oBAAoB,kBA8DtB,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export const runSetupFiles = async ({ setupFiles, setupFilesAfterEnv, events, bundler, evaluateModule, }) => {
|
|
2
|
+
for (const setupFile of setupFiles) {
|
|
3
|
+
const startTime = Date.now();
|
|
4
|
+
events.emit({
|
|
5
|
+
type: 'setup-file-bundling-started',
|
|
6
|
+
file: setupFile,
|
|
7
|
+
setupType: 'setupFiles',
|
|
8
|
+
});
|
|
9
|
+
try {
|
|
10
|
+
const setupModuleJs = await bundler.getModule(setupFile);
|
|
11
|
+
events.emit({
|
|
12
|
+
type: 'setup-file-bundling-finished',
|
|
13
|
+
file: setupFile,
|
|
14
|
+
setupType: 'setupFiles',
|
|
15
|
+
duration: Date.now() - startTime,
|
|
16
|
+
});
|
|
17
|
+
evaluateModule(setupModuleJs, setupFile);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
21
|
+
events.emit({
|
|
22
|
+
type: 'setup-file-bundling-failed',
|
|
23
|
+
file: setupFile,
|
|
24
|
+
setupType: 'setupFiles',
|
|
25
|
+
duration: Date.now() - startTime,
|
|
26
|
+
error: errorMessage,
|
|
27
|
+
});
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
for (const setupFile of setupFilesAfterEnv) {
|
|
32
|
+
const startTime = Date.now();
|
|
33
|
+
events.emit({
|
|
34
|
+
type: 'setup-file-bundling-started',
|
|
35
|
+
file: setupFile,
|
|
36
|
+
setupType: 'setupFilesAfterEnv',
|
|
37
|
+
});
|
|
38
|
+
try {
|
|
39
|
+
const setupModuleJs = await bundler.getModule(setupFile);
|
|
40
|
+
events.emit({
|
|
41
|
+
type: 'setup-file-bundling-finished',
|
|
42
|
+
file: setupFile,
|
|
43
|
+
setupType: 'setupFilesAfterEnv',
|
|
44
|
+
duration: Date.now() - startTime,
|
|
45
|
+
});
|
|
46
|
+
evaluateModule(setupModuleJs, setupFile);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
50
|
+
events.emit({
|
|
51
|
+
type: 'setup-file-bundling-failed',
|
|
52
|
+
file: setupFile,
|
|
53
|
+
setupType: 'setupFilesAfterEnv',
|
|
54
|
+
duration: Date.now() - startTime,
|
|
55
|
+
error: errorMessage,
|
|
56
|
+
});
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
@@ -18,5 +18,5 @@ export declare function beforeAll(fn: TestFn): void;
|
|
|
18
18
|
export declare function afterAll(fn: TestFn): void;
|
|
19
19
|
export declare function beforeEach(fn: TestFn): void;
|
|
20
20
|
export declare function afterEach(fn: TestFn): void;
|
|
21
|
-
export declare const collectTests: (fn: () => void) => CollectionResult
|
|
21
|
+
export declare const collectTests: (fn: () => void | Promise<void>) => Promise<CollectionResult>;
|
|
22
22
|
//# sourceMappingURL=functions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../src/collector/functions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AA4LzC,eAAO,MAAM,QAAQ,UACZ,MAAM,MAAM,MAAM,IAAI;iBAsBd,MAAM,MAAM,MAAM,IAAI;iBAqBtB,MAAM,MAAM,MAAM,IAAI;CAsBtC,CAAC;AAEF,eAAO,MAAM,IAAI,UACR,MAAM,MAAM,MAAM;iBAaV,MAAM,MAAM,MAAM;iBAWlB,MAAM,MAAM,MAAM;iBAWlB,MAAM;CAiBtB,CAAC;AAEF,eAAO,MAAM,EAAE,UAtDN,MAAM,MAAM,MAAM;iBAaV,MAAM,MAAM,MAAM;iBAWlB,MAAM,MAAM,MAAM;iBAWlB,MAAM;CAmBD,CAAC;AAEvB,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,QAQnC;AAED,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,QAQlC;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,QAQpC;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,QAQnC;AAgBD,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../src/collector/functions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AA4LzC,eAAO,MAAM,QAAQ,UACZ,MAAM,MAAM,MAAM,IAAI;iBAsBd,MAAM,MAAM,MAAM,IAAI;iBAqBtB,MAAM,MAAM,MAAM,IAAI;CAsBtC,CAAC;AAEF,eAAO,MAAM,IAAI,UACR,MAAM,MAAM,MAAM;iBAaV,MAAM,MAAM,MAAM;iBAWlB,MAAM,MAAM,MAAM;iBAWlB,MAAM;CAiBtB,CAAC;AAEF,eAAO,MAAM,EAAE,UAtDN,MAAM,MAAM,MAAM;iBAaV,MAAM,MAAM,MAAM;iBAWlB,MAAM,MAAM,MAAM;iBAWlB,MAAM;CAmBD,CAAC;AAEvB,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,QAQnC;AAED,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,QAQlC;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,QAQpC;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,QAQnC;AAgBD,eAAO,MAAM,YAAY,GACvB,IAAI,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAC7B,OAAO,CAAC,gBAAgB,CAiB1B,CAAC"}
|
|
@@ -261,10 +261,10 @@ const countTests = (suite) => {
|
|
|
261
261
|
}
|
|
262
262
|
return count;
|
|
263
263
|
};
|
|
264
|
-
export const collectTests = (fn) => {
|
|
264
|
+
export const collectTests = async (fn) => {
|
|
265
265
|
currentContext = clearState();
|
|
266
266
|
try {
|
|
267
|
-
fn();
|
|
267
|
+
await fn();
|
|
268
268
|
// Convert raw structure to final structure using computation phase
|
|
269
269
|
const testSuite = convertRawTestSuiteToTestSuite(getRootSuite());
|
|
270
270
|
const totalTests = countTests(testSuite);
|
|
@@ -4,7 +4,7 @@ export type TestFn = () => void | Promise<void>;
|
|
|
4
4
|
export type TestCollectorEventsEmitter = EventEmitter<TestCollectorEvents>;
|
|
5
5
|
export type TestCollector = {
|
|
6
6
|
events: TestCollectorEventsEmitter;
|
|
7
|
-
collect: (fn: () => void
|
|
7
|
+
collect: (fn: () => void | Promise<void>, testFilePath: string) => Promise<CollectionResult>;
|
|
8
8
|
dispose: () => void;
|
|
9
9
|
};
|
|
10
10
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/collector/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AAEtC,MAAM,MAAM,MAAM,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEhD,MAAM,MAAM,0BAA0B,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAC;AAE3E,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,0BAA0B,CAAC;IACnC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/collector/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AAEtC,MAAM,MAAM,MAAM,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEhD,MAAM,MAAM,0BAA0B,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAC;AAE3E,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,0BAA0B,CAAC;IACnC,OAAO,EAAE,CACP,EAAE,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC9B,YAAY,EAAE,MAAM,KACjB,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry-point.d.ts","sourceRoot":"","sources":["../src/entry-point.ts"],"names":[],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { filterTestsByName } from './testNameFilter.js';
|
|
1
|
+
export { filterTestsByName, markTestsAsSkippedByName, } from './testNameFilter.js';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/filtering/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/filtering/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC"}
|
package/dist/filtering/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { filterTestsByName } from './testNameFilter.js';
|
|
1
|
+
export { filterTestsByName, markTestsAsSkippedByName, } from './testNameFilter.js';
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { TestSuite } from '@react-native-harness/bridge';
|
|
2
2
|
/**
|
|
3
3
|
* Filters tests by name pattern, matching against test names and suite+test combinations
|
|
4
|
+
* @deprecated Use markTestsAsSkippedByName instead - this function will be removed in a future version
|
|
4
5
|
*/
|
|
5
6
|
export declare const filterTestsByName: (suite: TestSuite, testNamePattern: string) => TestSuite;
|
|
7
|
+
/**
|
|
8
|
+
* Marks tests as skipped based on name pattern, keeping all tests in the structure
|
|
9
|
+
* but setting non-matching tests to 'skipped' status
|
|
10
|
+
*/
|
|
11
|
+
export declare const markTestsAsSkippedByName: (suite: TestSuite, testNamePattern: string) => TestSuite;
|
|
6
12
|
//# sourceMappingURL=testNameFilter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testNameFilter.d.ts","sourceRoot":"","sources":["../../src/filtering/testNameFilter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEzD
|
|
1
|
+
{"version":3,"file":"testNameFilter.d.ts","sourceRoot":"","sources":["../../src/filtering/testNameFilter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,OAAO,SAAS,EAChB,iBAAiB,MAAM,KACtB,SAGF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GACnC,OAAO,SAAS,EAChB,iBAAiB,MAAM,KACtB,SAGF,CAAC"}
|
|
@@ -1,17 +1,48 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Filters tests by name pattern, matching against test names and suite+test combinations
|
|
3
|
+
* @deprecated Use markTestsAsSkippedByName instead - this function will be removed in a future version
|
|
3
4
|
*/
|
|
4
5
|
export const filterTestsByName = (suite, testNamePattern) => {
|
|
5
6
|
const regex = new RegExp(testNamePattern);
|
|
6
7
|
return filterSuiteRecursively(suite, regex);
|
|
7
8
|
};
|
|
9
|
+
/**
|
|
10
|
+
* Marks tests as skipped based on name pattern, keeping all tests in the structure
|
|
11
|
+
* but setting non-matching tests to 'skipped' status
|
|
12
|
+
*/
|
|
13
|
+
export const markTestsAsSkippedByName = (suite, testNamePattern) => {
|
|
14
|
+
const regex = new RegExp(testNamePattern);
|
|
15
|
+
return markTestsRecursively(suite, regex);
|
|
16
|
+
};
|
|
17
|
+
const markTestsRecursively = (suite, regex) => {
|
|
18
|
+
// Mark tests in current suite - skip tests that don't match the pattern
|
|
19
|
+
const updatedTests = suite.tests.map((test) => {
|
|
20
|
+
const matches = regex.test(test.name) || regex.test(`${suite.name} ${test.name}`);
|
|
21
|
+
// If test doesn't match pattern and is currently active, mark it as skipped
|
|
22
|
+
if (!matches && test.status === 'active') {
|
|
23
|
+
return {
|
|
24
|
+
...test,
|
|
25
|
+
status: 'skipped',
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
// Keep original status for matching tests or already skipped/todo tests
|
|
29
|
+
return test;
|
|
30
|
+
});
|
|
31
|
+
// Recursively process child suites
|
|
32
|
+
const updatedChildSuites = suite.suites.map((childSuite) => markTestsRecursively(childSuite, regex));
|
|
33
|
+
return {
|
|
34
|
+
...suite,
|
|
35
|
+
tests: updatedTests,
|
|
36
|
+
suites: updatedChildSuites,
|
|
37
|
+
};
|
|
38
|
+
};
|
|
8
39
|
const filterSuiteRecursively = (suite, regex) => {
|
|
9
40
|
// Filter tests in current suite - match against test name or "suite test" combination
|
|
10
|
-
const filteredTests = suite.tests.filter(test => regex.test(test.name) || regex.test(`${suite.name} ${test.name}`));
|
|
41
|
+
const filteredTests = suite.tests.filter((test) => regex.test(test.name) || regex.test(`${suite.name} ${test.name}`));
|
|
11
42
|
// Recursively filter child suites
|
|
12
43
|
const filteredChildSuites = suite.suites
|
|
13
|
-
.map(childSuite => filterSuiteRecursively(childSuite, regex))
|
|
14
|
-
.filter(childSuite => hasAnyActiveTests(childSuite));
|
|
44
|
+
.map((childSuite) => filterSuiteRecursively(childSuite, regex))
|
|
45
|
+
.filter((childSuite) => hasAnyActiveTests(childSuite));
|
|
15
46
|
return {
|
|
16
47
|
...suite,
|
|
17
48
|
tests: filteredTests,
|
|
@@ -19,7 +50,7 @@ const filterSuiteRecursively = (suite, regex) => {
|
|
|
19
50
|
};
|
|
20
51
|
};
|
|
21
52
|
const hasAnyActiveTests = (suite) => {
|
|
22
|
-
const hasDirectTests = suite.tests.some(test => test.status === 'active');
|
|
23
|
-
const hasChildTests = suite.suites.some(childSuite => hasAnyActiveTests(childSuite));
|
|
53
|
+
const hasDirectTests = suite.tests.some((test) => test.status === 'active');
|
|
54
|
+
const hasChildTests = suite.suites.some((childSuite) => hasAnyActiveTests(childSuite));
|
|
24
55
|
return hasDirectTests || hasChildTests;
|
|
25
56
|
};
|
package/dist/globals.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
export type HarnessGlobal = {
|
|
2
|
+
appRegistryComponentName: string;
|
|
3
|
+
};
|
|
1
4
|
declare global {
|
|
2
|
-
var RN_HARNESS:
|
|
5
|
+
var RN_HARNESS: HarnessGlobal | undefined;
|
|
3
6
|
}
|
|
4
|
-
export
|
|
7
|
+
export declare const getHarnessGlobal: () => HarnessGlobal;
|
|
5
8
|
//# sourceMappingURL=globals.d.ts.map
|
package/dist/globals.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"globals.d.ts","sourceRoot":"","sources":["../src/globals.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"globals.d.ts","sourceRoot":"","sources":["../src/globals.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG;IAC1B,wBAAwB,EAAE,MAAM,CAAC;CAClC,CAAC;AAEF,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,UAAU,EAAE,aAAa,GAAG,SAAS,CAAC;CAC3C;AAED,eAAO,MAAM,gBAAgB,QAAO,aAQnC,CAAC"}
|
package/dist/globals.js
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,CAAC;AAExB,OAAO,EAAE,EAAE,IAAI,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACzD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,CAAC;AAExB,OAAO,EAAE,EAAE,IAAI,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACzD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/initialize.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { getDeviceDescriptor } from './client/getDeviceDescriptor.js';
|
|
2
2
|
import { getClient } from './client/index.js';
|
|
3
|
+
import { setupJestMock } from './jest-mock.js';
|
|
3
4
|
// Polyfill for EventTarget
|
|
4
5
|
const Shim = require('event-target-shim');
|
|
5
6
|
globalThis.Event = Shim.Event;
|
|
6
7
|
globalThis.EventTarget = Shim.EventTarget;
|
|
8
|
+
// Setup jest mock to warn users about using Jest APIs
|
|
9
|
+
setupJestMock();
|
|
7
10
|
// Turn off LogBox
|
|
8
11
|
const { LogBox } = require('react-native');
|
|
9
12
|
LogBox.ignoreAllLogs(true);
|
|
@@ -16,3 +19,7 @@ setTimeout(() => {
|
|
|
16
19
|
// Initialize the React Native Harness
|
|
17
20
|
void getClient().then((client) => client.rpc.reportReady(getDeviceDescriptor()));
|
|
18
21
|
});
|
|
22
|
+
// Re-throw fatal errors
|
|
23
|
+
ErrorUtils.setGlobalHandler((error) => {
|
|
24
|
+
throw error;
|
|
25
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jest-mock.d.ts","sourceRoot":"","sources":["../src/jest-mock.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,aAAa,QAAO,IA8BhC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Mock jest global to warn users about using Jest APIs in Harness tests
|
|
2
|
+
export const setupJestMock = () => {
|
|
3
|
+
function throwError() {
|
|
4
|
+
throw new Error(`Jest globals are not available in Harness tests. Import from 'react-native-harness' instead (e.g., import { harness } from 'react-native-harness'; harness.fn())`);
|
|
5
|
+
}
|
|
6
|
+
const jestMock = new Proxy({}, {
|
|
7
|
+
get() {
|
|
8
|
+
throwError();
|
|
9
|
+
},
|
|
10
|
+
set() {
|
|
11
|
+
throwError();
|
|
12
|
+
},
|
|
13
|
+
has() {
|
|
14
|
+
throwError();
|
|
15
|
+
},
|
|
16
|
+
ownKeys() {
|
|
17
|
+
throwError();
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
Object.defineProperty(globalThis, 'jest', {
|
|
21
|
+
value: jestMock,
|
|
22
|
+
writable: false,
|
|
23
|
+
configurable: false,
|
|
24
|
+
});
|
|
25
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
type ErrorBoundaryProps = {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
};
|
|
5
|
+
type ErrorBoundaryState = {
|
|
6
|
+
hasError: boolean;
|
|
7
|
+
error: Error | null;
|
|
8
|
+
};
|
|
9
|
+
export declare class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
|
10
|
+
constructor(props: ErrorBoundaryProps);
|
|
11
|
+
static getDerivedStateFromError(error: Error): ErrorBoundaryState;
|
|
12
|
+
componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void;
|
|
13
|
+
componentDidUpdate(prevProps: ErrorBoundaryProps): void;
|
|
14
|
+
render(): React.ReactNode;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=ErrorBoundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../../src/render/ErrorBoundary.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,KAAK,kBAAkB,GAAG;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB,CAAC;AAEF,qBAAa,aAAc,SAAQ,KAAK,CAAC,SAAS,CAChD,kBAAkB,EAClB,kBAAkB,CACnB;gBACa,KAAK,EAAE,kBAAkB;IAKrC,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,kBAAkB;IAIxD,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI;IAIjE,kBAAkB,CAAC,SAAS,EAAE,kBAAkB,GAAG,IAAI;IAOvD,MAAM,IAAI,KAAK,CAAC,SAAS;CAwBnC"}
|