@react-native-harness/runtime 1.0.0-alpha.14 → 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.
Files changed (209) hide show
  1. package/assets/moduleSystem.flow.js +15 -3
  2. package/dist/bundler/evaluate.d.ts.map +1 -1
  3. package/dist/bundler/evaluate.js +7 -7
  4. package/dist/client/factory.d.ts.map +1 -1
  5. package/dist/client/factory.js +26 -12
  6. package/dist/client/setup-files.d.ts +12 -0
  7. package/dist/client/setup-files.d.ts.map +1 -0
  8. package/dist/client/setup-files.js +60 -0
  9. package/dist/collector/functions.d.ts +1 -1
  10. package/dist/collector/functions.d.ts.map +1 -1
  11. package/dist/collector/functions.js +2 -2
  12. package/dist/collector/types.d.ts +1 -1
  13. package/dist/collector/types.d.ts.map +1 -1
  14. package/dist/entry-point.d.ts +2 -0
  15. package/dist/entry-point.d.ts.map +1 -0
  16. package/dist/entry-point.js +4 -0
  17. package/dist/expect/index.d.ts.map +1 -1
  18. package/dist/expect/index.js +2 -0
  19. package/dist/expect/setup.js +2 -0
  20. package/dist/filtering/index.d.ts +1 -1
  21. package/dist/filtering/index.d.ts.map +1 -1
  22. package/dist/filtering/index.js +1 -1
  23. package/dist/filtering/testNameFilter.d.ts +6 -0
  24. package/dist/filtering/testNameFilter.d.ts.map +1 -1
  25. package/dist/filtering/testNameFilter.js +36 -5
  26. package/dist/globals.d.ts +5 -2
  27. package/dist/globals.d.ts.map +1 -1
  28. package/dist/globals.js +7 -1
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +1 -0
  32. package/dist/initialize.js +7 -0
  33. package/dist/jest-mock.d.ts +2 -0
  34. package/dist/jest-mock.d.ts.map +1 -0
  35. package/dist/jest-mock.js +25 -0
  36. package/dist/render/ErrorBoundary.d.ts +17 -0
  37. package/dist/render/ErrorBoundary.d.ts.map +1 -0
  38. package/dist/render/ErrorBoundary.js +73 -0
  39. package/dist/render/TestComponentOverlay.d.ts +3 -0
  40. package/dist/render/TestComponentOverlay.d.ts.map +1 -0
  41. package/dist/render/TestComponentOverlay.js +36 -0
  42. package/dist/render/cleanup.d.ts +2 -0
  43. package/dist/render/cleanup.d.ts.map +1 -0
  44. package/dist/render/cleanup.js +6 -0
  45. package/dist/render/index.d.ts +6 -0
  46. package/dist/render/index.d.ts.map +1 -0
  47. package/dist/render/index.js +66 -0
  48. package/dist/render/setup.d.ts +2 -0
  49. package/dist/render/setup.d.ts.map +1 -0
  50. package/dist/render/setup.js +7 -0
  51. package/dist/render/types.d.ts +12 -0
  52. package/dist/render/types.d.ts.map +1 -0
  53. package/dist/render/types.js +1 -0
  54. package/dist/runner/factory.d.ts.map +1 -1
  55. package/dist/runner/factory.js +6 -1
  56. package/dist/symbolicate.d.ts.map +1 -1
  57. package/dist/symbolicate.js +5 -4
  58. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  59. package/dist/ui/ReadyScreen.d.ts.map +1 -1
  60. package/dist/ui/ReadyScreen.js +2 -1
  61. package/dist/ui/state.d.ts +14 -1
  62. package/dist/ui/state.d.ts.map +1 -1
  63. package/dist/ui/state.js +22 -0
  64. package/dist/utils/emitter.d.ts.map +1 -1
  65. package/dist/waitFor.d.ts.map +1 -1
  66. package/dist/waitFor.js +4 -0
  67. package/eslint.config.mjs +1 -7
  68. package/out-tsc/vitest/src/__tests__/collector.test.d.ts +2 -0
  69. package/out-tsc/vitest/src/__tests__/collector.test.d.ts.map +1 -0
  70. package/out-tsc/vitest/src/__tests__/error-handling.test.d.ts +2 -0
  71. package/out-tsc/vitest/src/__tests__/error-handling.test.d.ts.map +1 -0
  72. package/out-tsc/vitest/src/__tests__/expect.test.d.ts +2 -0
  73. package/out-tsc/vitest/src/__tests__/expect.test.d.ts.map +1 -0
  74. package/out-tsc/vitest/src/__tests__/spy.test.d.ts +2 -0
  75. package/out-tsc/vitest/src/__tests__/spy.test.d.ts.map +1 -0
  76. package/out-tsc/vitest/src/bundler/bundle.d.ts +2 -0
  77. package/out-tsc/vitest/src/bundler/bundle.d.ts.map +1 -0
  78. package/out-tsc/vitest/src/bundler/errors.d.ts +15 -0
  79. package/out-tsc/vitest/src/bundler/errors.d.ts.map +1 -0
  80. package/out-tsc/vitest/src/bundler/evaluate.d.ts +2 -0
  81. package/out-tsc/vitest/src/bundler/evaluate.d.ts.map +1 -0
  82. package/out-tsc/vitest/src/bundler/factory.d.ts +3 -0
  83. package/out-tsc/vitest/src/bundler/factory.d.ts.map +1 -0
  84. package/out-tsc/vitest/src/bundler/index.d.ts +4 -0
  85. package/out-tsc/vitest/src/bundler/index.d.ts.map +1 -0
  86. package/out-tsc/vitest/src/bundler/types.d.ts +7 -0
  87. package/out-tsc/vitest/src/bundler/types.d.ts.map +1 -0
  88. package/out-tsc/vitest/src/client/factory.d.ts +2 -0
  89. package/out-tsc/vitest/src/client/factory.d.ts.map +1 -0
  90. package/out-tsc/vitest/src/client/getDeviceDescriptor.d.ts +8 -0
  91. package/out-tsc/vitest/src/client/getDeviceDescriptor.d.ts.map +1 -0
  92. package/out-tsc/vitest/src/client/getWSServer.d.ts +2 -0
  93. package/out-tsc/vitest/src/client/getWSServer.d.ts.map +1 -0
  94. package/out-tsc/vitest/src/client/index.d.ts +2 -0
  95. package/out-tsc/vitest/src/client/index.d.ts.map +1 -0
  96. package/out-tsc/vitest/src/collector/errors.d.ts +8 -0
  97. package/out-tsc/vitest/src/collector/errors.d.ts.map +1 -0
  98. package/out-tsc/vitest/src/collector/factory.d.ts +3 -0
  99. package/out-tsc/vitest/src/collector/factory.d.ts.map +1 -0
  100. package/out-tsc/vitest/src/collector/functions.d.ts +22 -0
  101. package/out-tsc/vitest/src/collector/functions.d.ts.map +1 -0
  102. package/out-tsc/vitest/src/collector/index.d.ts +5 -0
  103. package/out-tsc/vitest/src/collector/index.d.ts.map +1 -0
  104. package/out-tsc/vitest/src/collector/types.d.ts +10 -0
  105. package/out-tsc/vitest/src/collector/types.d.ts.map +1 -0
  106. package/out-tsc/vitest/src/collector/validation.d.ts +4 -0
  107. package/out-tsc/vitest/src/collector/validation.d.ts.map +1 -0
  108. package/out-tsc/vitest/src/constants.d.ts +3 -0
  109. package/out-tsc/vitest/src/constants.d.ts.map +1 -0
  110. package/out-tsc/vitest/src/entry-point.d.ts +2 -0
  111. package/out-tsc/vitest/src/entry-point.d.ts.map +1 -0
  112. package/out-tsc/vitest/src/errors.d.ts +6 -0
  113. package/out-tsc/vitest/src/errors.d.ts.map +1 -0
  114. package/out-tsc/vitest/src/expect/index.d.ts +9 -0
  115. package/out-tsc/vitest/src/expect/index.d.ts.map +1 -0
  116. package/out-tsc/vitest/src/expect/setup.d.ts +2 -0
  117. package/out-tsc/vitest/src/expect/setup.d.ts.map +1 -0
  118. package/out-tsc/vitest/src/filtering/index.d.ts +2 -0
  119. package/out-tsc/vitest/src/filtering/index.d.ts.map +1 -0
  120. package/out-tsc/vitest/src/filtering/testNameFilter.d.ts +12 -0
  121. package/out-tsc/vitest/src/filtering/testNameFilter.d.ts.map +1 -0
  122. package/out-tsc/vitest/src/globals.d.ts +8 -0
  123. package/out-tsc/vitest/src/globals.d.ts.map +1 -0
  124. package/out-tsc/vitest/src/index.d.ts +9 -0
  125. package/out-tsc/vitest/src/index.d.ts.map +1 -0
  126. package/out-tsc/vitest/src/initialize.d.ts +2 -0
  127. package/out-tsc/vitest/src/initialize.d.ts.map +1 -0
  128. package/out-tsc/vitest/src/mocker/index.d.ts +2 -0
  129. package/out-tsc/vitest/src/mocker/index.d.ts.map +1 -0
  130. package/out-tsc/vitest/src/mocker/registry.d.ts +7 -0
  131. package/out-tsc/vitest/src/mocker/registry.d.ts.map +1 -0
  132. package/out-tsc/vitest/src/mocker/types.d.ts +6 -0
  133. package/out-tsc/vitest/src/mocker/types.d.ts.map +1 -0
  134. package/out-tsc/vitest/src/namespace.d.ts +18 -0
  135. package/out-tsc/vitest/src/namespace.d.ts.map +1 -0
  136. package/out-tsc/vitest/src/runner/errors.d.ts +11 -0
  137. package/out-tsc/vitest/src/runner/errors.d.ts.map +1 -0
  138. package/out-tsc/vitest/src/runner/factory.d.ts +3 -0
  139. package/out-tsc/vitest/src/runner/factory.d.ts.map +1 -0
  140. package/out-tsc/vitest/src/runner/hooks.d.ts +4 -0
  141. package/out-tsc/vitest/src/runner/hooks.d.ts.map +1 -0
  142. package/out-tsc/vitest/src/runner/index.d.ts +4 -0
  143. package/out-tsc/vitest/src/runner/index.d.ts.map +1 -0
  144. package/out-tsc/vitest/src/runner/runSuite.d.ts +4 -0
  145. package/out-tsc/vitest/src/runner/runSuite.d.ts.map +1 -0
  146. package/out-tsc/vitest/src/runner/types.d.ts +13 -0
  147. package/out-tsc/vitest/src/runner/types.d.ts.map +1 -0
  148. package/out-tsc/vitest/src/spy/index.d.ts +2 -0
  149. package/out-tsc/vitest/src/spy/index.d.ts.map +1 -0
  150. package/out-tsc/vitest/src/symbolicate.d.ts +3 -0
  151. package/out-tsc/vitest/src/symbolicate.d.ts.map +1 -0
  152. package/out-tsc/vitest/src/ui/ReadyScreen.d.ts +2 -0
  153. package/out-tsc/vitest/src/ui/ReadyScreen.d.ts.map +1 -0
  154. package/out-tsc/vitest/src/ui/WrongEnvironmentScreen.d.ts +2 -0
  155. package/out-tsc/vitest/src/ui/WrongEnvironmentScreen.d.ts.map +1 -0
  156. package/out-tsc/vitest/src/ui/index.d.ts +2 -0
  157. package/out-tsc/vitest/src/ui/index.d.ts.map +1 -0
  158. package/out-tsc/vitest/src/ui/state.d.ts +7 -0
  159. package/out-tsc/vitest/src/ui/state.d.ts.map +1 -0
  160. package/out-tsc/vitest/src/utils/dev-server.d.ts +2 -0
  161. package/out-tsc/vitest/src/utils/dev-server.d.ts.map +1 -0
  162. package/out-tsc/vitest/src/utils/emitter.d.ts +16 -0
  163. package/out-tsc/vitest/src/utils/emitter.d.ts.map +1 -0
  164. package/out-tsc/vitest/src/waitFor.d.ts +21 -0
  165. package/out-tsc/vitest/src/waitFor.d.ts.map +1 -0
  166. package/out-tsc/vitest/tsconfig.spec.tsbuildinfo +1 -0
  167. package/out-tsc/vitest/vite.config.d.ts +3 -0
  168. package/out-tsc/vitest/vite.config.d.ts.map +1 -0
  169. package/package.json +10 -4
  170. package/src/__tests__/collector.test.ts +55 -55
  171. package/src/__tests__/error-handling.test.ts +34 -34
  172. package/src/__tests__/expect.test.ts +13 -5
  173. package/src/bundler/bundle.ts +1 -2
  174. package/src/bundler/evaluate.ts +9 -9
  175. package/src/client/factory.ts +30 -14
  176. package/src/client/setup-files.ts +81 -0
  177. package/src/collector/functions.ts +4 -2
  178. package/src/collector/types.ts +4 -1
  179. package/src/entry-point.ts +8 -0
  180. package/src/expect/index.ts +8 -2
  181. package/src/expect/setup.ts +3 -0
  182. package/src/filtering/index.ts +4 -1
  183. package/src/filtering/testNameFilter.ts +53 -8
  184. package/src/globals.ts +14 -2
  185. package/src/index.ts +1 -0
  186. package/src/initialize.ts +11 -1
  187. package/src/jest-mock.ts +32 -0
  188. package/src/mocker/metro-require.d.ts +1 -0
  189. package/src/react-native.d.ts +2 -10
  190. package/src/render/ErrorBoundary.tsx +108 -0
  191. package/src/render/TestComponentOverlay.tsx +47 -0
  192. package/src/render/cleanup.ts +7 -0
  193. package/src/render/index.ts +96 -0
  194. package/src/render/setup.ts +8 -0
  195. package/src/render/types.ts +11 -0
  196. package/src/runner/factory.ts +8 -1
  197. package/src/symbolicate.ts +6 -4
  198. package/src/ui/ReadyScreen.tsx +2 -0
  199. package/src/ui/state.ts +39 -0
  200. package/src/utils/emitter.ts +1 -0
  201. package/src/waitFor.ts +6 -1
  202. package/tsconfig.spec.json +7 -3
  203. package/tsconfig.tsbuildinfo +1 -1
  204. package/dist/utils/progressLogger.d.ts +0 -8
  205. package/dist/utils/progressLogger.d.ts.map +0 -1
  206. package/dist/utils/progressLogger.js +0 -79
  207. package/src/utils/progressLogger.ts +0 -98
  208. package/types/global.d.ts +0 -2
  209. 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 = {};
@@ -493,11 +502,14 @@ function loadModuleImplementation(
493
502
  // keep args in sync with with defineModuleCode in
494
503
  // metro/src/Resolver/index.js
495
504
  // and metro/src/ModuleGraph/worker.js
505
+ const capturedRequire = (...args) => global.__r(...args);
506
+ Object.assign(capturedRequire, global.__r);
507
+
496
508
  factory(
497
509
  global,
498
- (...args) => global.__r(...args),
499
- (...args) => global.__r.importDefault(...args),
500
- (...args) => global.__r.importAll(...args),
510
+ capturedRequire,
511
+ capturedRequire.importDefault,
512
+ capturedRequire.importAll,
501
513
  moduleObject,
502
514
  moduleObject.exports,
503
515
  dependencyMap
@@ -1 +1 @@
1
- {"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/bundler/evaluate.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc,GAAI,UAAU,MAAM,EAAE,YAAY,MAAM,KAAG,IAqBrE,CAAC"}
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"}
@@ -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 __rMatch = moduleJs.match(/__r\((\d+)\)/);
5
- if (!__rMatch) {
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":"AAgBA,eAAO,MAAM,SAAS,2EAiErB,CAAC"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/client/factory.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,SAAS,2EAgFrB,CAAC"}
@@ -3,10 +3,11 @@ import { store } from '../ui/state.js';
3
3
  import { getTestRunner } from '../runner/index.js';
4
4
  import { getTestCollector } from '../collector/index.js';
5
5
  import { combineEventEmitters } from '../utils/emitter.js';
6
- import { attachProgressLogger } from '../utils/progressLogger.js';
7
6
  import { getWSServer } from './getWSServer.js';
8
7
  import { getBundler, evaluateModule } from '../bundler/index.js';
9
- import { filterTestsByName } from '../filtering/index.js';
8
+ import { markTestsAsSkippedByName } from '../filtering/index.js';
9
+ import { setup } from '../render/setup.js';
10
+ import { runSetupFiles } from './setup-files.js';
10
11
  export const getClient = async () => {
11
12
  const client = await getBridgeClient(getWSServer(), {
12
13
  runTests: async () => {
@@ -30,20 +31,33 @@ export const getClient = async () => {
30
31
  events.addListener((event) => {
31
32
  client.rpc.emitEvent(event.type, event);
32
33
  });
33
- // Add console logging for progress information
34
- attachProgressLogger(events, path);
34
+ await runSetupFiles({
35
+ setupFiles: options.setupFiles ?? [],
36
+ setupFilesAfterEnv: [],
37
+ events: events,
38
+ bundler: bundler,
39
+ evaluateModule,
40
+ });
35
41
  const moduleJs = await bundler.getModule(path);
36
- const collectionResult = await collector.collect(() => evaluateModule(moduleJs, path), path);
37
- // Apply test name filtering if specified
38
- const filteredTestSuite = options.testNamePattern
39
- ? filterTestsByName(collectionResult.testSuite, options.testNamePattern)
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)
40
57
  : collectionResult.testSuite;
41
- const result = await runner.run(filteredTestSuite, path);
58
+ const result = await runner.run(processedTestSuite, path);
42
59
  return result;
43
60
  }
44
- catch (error) {
45
- throw error;
46
- }
47
61
  finally {
48
62
  collector?.dispose();
49
63
  runner?.dispose();
@@ -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,GAAI,IAAI,MAAM,IAAI,KAAG,gBAiB7C,CAAC"}
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, testFilePath: string) => Promise<CollectionResult>;
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,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC7E,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC"}
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=entry-point.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry-point.d.ts","sourceRoot":"","sources":["../src/entry-point.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import { AppRegistry } from 'react-native';
2
+ import { getHarnessGlobal } from './globals.js';
3
+ import { UI } from './ui/index.js';
4
+ AppRegistry.registerComponent(getHarnessGlobal().appRegistryComponentName, () => UI);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/expect/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,YAAY,EAAgB,MAAM,gBAAgB,CAAC;AAS5E,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,OAAO,YAAY,CAAC;AAEpB,wBAAgB,YAAY,IAAI,YAAY,CAkF3C;AAED,QAAA,MAAM,YAAY,EAAE,YAA6B,CAAC;AAQlD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,YAAY,IAAI,MAAM,EAAE,CAAC;AAExC,YAAY,EACV,SAAS,EACT,4BAA4B,EAC5B,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,QAAQ,GACT,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/expect/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAa,YAAY,EAAgB,MAAM,gBAAgB,CAAC;AAS5E,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,OAAO,YAAY,CAAC;AAEpB,wBAAgB,YAAY,IAAI,YAAY,CAqF3C;AAED,QAAA,MAAM,YAAY,EAAE,YAA6B,CAAC;AAQlD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,YAAY,IAAI,MAAM,EAAE,CAAC;AAExC,YAAY,EACV,SAAS,EACT,4BAA4B,EAC5B,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,QAAQ,GACT,MAAM,gBAAgB,CAAC"}
@@ -1,3 +1,5 @@
1
+ // This is adapted version of https://github.com/vitest-dev/vitest/blob/main/packages/vitest/src/integrations/chai/index.ts
2
+ // Credits to Vitest team for the original implementation.
1
3
  import { addCustomEqualityTesters, ASYMMETRIC_MATCHERS_OBJECT, customMatchers, getState, GLOBAL_EXPECT, setState, } from '@vitest/expect';
2
4
  import * as chai from 'chai';
3
5
  // Setup additional matchers
@@ -1,3 +1,5 @@
1
+ // This is adapted version of https://github.com/vitest-dev/vitest/blob/main/packages/vitest/src/integrations/chai/setup.ts
2
+ // Credits to Vitest team for the original implementation.
1
3
  import { JestAsymmetricMatchers, JestChaiExpect, JestExtend, } from '@vitest/expect';
2
4
  import * as chai from 'chai';
3
5
  chai.use(JestExtend);
@@ -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,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
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"}
@@ -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;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAC5B,OAAO,SAAS,EAChB,iBAAiB,MAAM,KACtB,SAGF,CAAC"}
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: boolean | undefined;
5
+ var RN_HARNESS: HarnessGlobal | undefined;
3
6
  }
4
- export {};
7
+ export declare const getHarnessGlobal: () => HarnessGlobal;
5
8
  //# sourceMappingURL=globals.d.ts.map
@@ -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,OAAO,GAAG,SAAS,CAAC;CACrC;AAED,OAAO,EAAE,CAAC"}
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
@@ -1 +1,7 @@
1
- export {};
1
+ export const getHarnessGlobal = () => {
2
+ const harnessGlobal = global.RN_HARNESS;
3
+ if (!harnessGlobal) {
4
+ throw new Error('RN_HARNESS global is not set');
5
+ }
6
+ return harnessGlobal;
7
+ };
package/dist/index.d.ts CHANGED
@@ -6,4 +6,5 @@ export * from './collector/index.js';
6
6
  export * from './mocker/index.js';
7
7
  export * from './namespace.js';
8
8
  export * from './waitFor.js';
9
+ export * from './render/index.js';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -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
@@ -6,3 +6,4 @@ export * from './collector/index.js';
6
6
  export * from './mocker/index.js';
7
7
  export * from './namespace.js';
8
8
  export * from './waitFor.js';
9
+ export * from './render/index.js';
@@ -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,2 @@
1
+ export declare const setupJestMock: () => void;
2
+ //# sourceMappingURL=jest-mock.d.ts.map
@@ -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"}
@@ -0,0 +1,73 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { View, Text, StyleSheet, ScrollView } from 'react-native';
4
+ export class ErrorBoundary extends React.Component {
5
+ constructor(props) {
6
+ super(props);
7
+ this.state = { hasError: false, error: null };
8
+ }
9
+ static getDerivedStateFromError(error) {
10
+ return { hasError: true, error };
11
+ }
12
+ componentDidCatch(error, errorInfo) {
13
+ console.error('Error caught by ErrorBoundary:', error, errorInfo);
14
+ }
15
+ componentDidUpdate(prevProps) {
16
+ // Reset error state when children change (new component rendered)
17
+ if (prevProps.children !== this.props.children && this.state.hasError) {
18
+ this.setState({ hasError: false, error: null });
19
+ }
20
+ }
21
+ render() {
22
+ if (this.state.hasError && this.state.error) {
23
+ return (_jsx(View, { style: styles.errorContainer, children: _jsxs(View, { style: styles.errorContent, children: [_jsx(Text, { style: styles.errorTitle, children: "Component Error" }), _jsx(Text, { style: styles.errorSubtitle, children: "The rendered component threw an error:" }), _jsxs(ScrollView, { style: styles.errorScrollView, children: [_jsx(Text, { style: styles.errorMessage, children: this.state.error.message }), this.state.error.stack && (_jsx(Text, { style: styles.errorStack, children: this.state.error.stack }))] })] }) }));
24
+ }
25
+ return this.props.children;
26
+ }
27
+ }
28
+ const styles = StyleSheet.create({
29
+ errorContainer: {
30
+ flex: 1,
31
+ backgroundColor: 'rgba(220, 38, 38, 0.1)',
32
+ justifyContent: 'center',
33
+ alignItems: 'center',
34
+ padding: 20,
35
+ },
36
+ errorContent: {
37
+ backgroundColor: '#1f2937',
38
+ borderRadius: 12,
39
+ padding: 20,
40
+ maxWidth: 500,
41
+ width: '100%',
42
+ maxHeight: '80%',
43
+ borderWidth: 2,
44
+ borderColor: '#dc2626',
45
+ },
46
+ errorTitle: {
47
+ fontSize: 24,
48
+ fontWeight: '700',
49
+ color: '#dc2626',
50
+ marginBottom: 8,
51
+ },
52
+ errorSubtitle: {
53
+ fontSize: 14,
54
+ color: '#9ca3af',
55
+ marginBottom: 16,
56
+ },
57
+ errorScrollView: {
58
+ maxHeight: 400,
59
+ },
60
+ errorMessage: {
61
+ fontSize: 16,
62
+ fontWeight: '600',
63
+ color: '#fca5a5',
64
+ marginBottom: 12,
65
+ fontFamily: 'Courier',
66
+ },
67
+ errorStack: {
68
+ fontSize: 12,
69
+ color: '#d1d5db',
70
+ fontFamily: 'Courier',
71
+ lineHeight: 18,
72
+ },
73
+ });
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export declare const TestComponentOverlay: () => React.ReactElement | null;
3
+ //# sourceMappingURL=TestComponentOverlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestComponentOverlay.d.ts","sourceRoot":"","sources":["../../src/render/TestComponentOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAMzC,eAAO,MAAM,oBAAoB,QAAO,KAAK,CAAC,YAAY,GAAG,IAgC5D,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect } from 'react';
3
+ import { View, StyleSheet } from 'react-native';
4
+ import { useRenderedElement } from '../ui/state.js';
5
+ import { store } from '../ui/state.js';
6
+ import { ErrorBoundary } from './ErrorBoundary.js';
7
+ export const TestComponentOverlay = () => {
8
+ const { element, key } = useRenderedElement();
9
+ useEffect(() => {
10
+ // Call onRenderCallback when element changes
11
+ const callback = store.getState().onRenderCallback;
12
+ if (callback) {
13
+ callback();
14
+ store.getState().setOnRenderCallback(null);
15
+ }
16
+ }, [element]);
17
+ if (!element) {
18
+ return null;
19
+ }
20
+ const handleLayout = () => {
21
+ const callback = store.getState().onLayoutCallback;
22
+ if (callback) {
23
+ callback();
24
+ // Clear the callback after calling it
25
+ store.getState().setOnLayoutCallback(null);
26
+ }
27
+ };
28
+ return (_jsx(View, { style: styles.overlay, onLayout: handleLayout, children: _jsx(ErrorBoundary, { children: element }) }, key));
29
+ };
30
+ const styles = StyleSheet.create({
31
+ overlay: {
32
+ ...StyleSheet.absoluteFillObject,
33
+ backgroundColor: '#0a1628',
34
+ zIndex: 1000,
35
+ },
36
+ });
@@ -0,0 +1,2 @@
1
+ export declare const cleanup: () => void;
2
+ //# sourceMappingURL=cleanup.d.ts.map