@react-native-harness/runtime 1.0.0-alpha.2 → 1.0.0-alpha.21

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 (169) hide show
  1. package/README.md +23 -4
  2. package/assets/harness-module-system.js +73 -0
  3. package/dist/bundler/bundle.d.ts.map +1 -1
  4. package/dist/bundler/bundle.js +7 -2
  5. package/dist/bundler/errors.d.ts +5 -0
  6. package/dist/bundler/errors.d.ts.map +1 -1
  7. package/dist/bundler/errors.js +11 -0
  8. package/dist/bundler/evaluate.d.ts.map +1 -1
  9. package/dist/bundler/evaluate.js +7 -7
  10. package/dist/bundler/factory.d.ts +3 -0
  11. package/dist/bundler/factory.d.ts.map +1 -0
  12. package/dist/bundler/factory.js +36 -0
  13. package/dist/bundler/index.d.ts +2 -1
  14. package/dist/bundler/index.d.ts.map +1 -1
  15. package/dist/bundler/index.js +1 -1
  16. package/dist/bundler/types.d.ts +7 -0
  17. package/dist/bundler/types.d.ts.map +1 -0
  18. package/dist/bundler/types.js +1 -0
  19. package/dist/client/factory.d.ts.map +1 -1
  20. package/dist/client/factory.js +34 -6
  21. package/dist/client/getDeviceDescriptor.d.ts +1 -1
  22. package/dist/client/getDeviceDescriptor.d.ts.map +1 -1
  23. package/dist/client/getDeviceDescriptor.js +18 -6
  24. package/dist/client/getWSServer.d.ts.map +1 -1
  25. package/dist/client/getWSServer.js +2 -1
  26. package/dist/client/setup-files.d.ts +12 -0
  27. package/dist/client/setup-files.d.ts.map +1 -0
  28. package/dist/client/setup-files.js +60 -0
  29. package/dist/collector/functions.d.ts +1 -1
  30. package/dist/collector/functions.d.ts.map +1 -1
  31. package/dist/collector/functions.js +10 -2
  32. package/dist/collector/types.d.ts +1 -1
  33. package/dist/collector/types.d.ts.map +1 -1
  34. package/dist/constants.d.ts +0 -1
  35. package/dist/constants.d.ts.map +1 -1
  36. package/dist/constants.js +0 -1
  37. package/dist/disableHMRWhenReady.d.ts +2 -0
  38. package/dist/disableHMRWhenReady.d.ts.map +1 -0
  39. package/dist/disableHMRWhenReady.js +20 -0
  40. package/dist/entry-point.d.ts +2 -0
  41. package/dist/entry-point.d.ts.map +1 -0
  42. package/dist/entry-point.js +4 -0
  43. package/dist/expect/index.d.ts.map +1 -1
  44. package/dist/expect/index.js +2 -0
  45. package/dist/expect/setup.js +2 -0
  46. package/dist/filtering/index.d.ts +2 -0
  47. package/dist/filtering/index.d.ts.map +1 -0
  48. package/dist/filtering/index.js +1 -0
  49. package/dist/filtering/testNameFilter.d.ts +12 -0
  50. package/dist/filtering/testNameFilter.d.ts.map +1 -0
  51. package/dist/filtering/testNameFilter.js +56 -0
  52. package/dist/globals.d.ts +6 -2
  53. package/dist/globals.d.ts.map +1 -1
  54. package/dist/globals.js +7 -1
  55. package/dist/index.d.ts +4 -0
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +4 -0
  58. package/dist/initialize.js +14 -6
  59. package/dist/jest-mock.d.ts +2 -0
  60. package/dist/jest-mock.d.ts.map +1 -0
  61. package/dist/jest-mock.js +25 -0
  62. package/dist/mocker/index.d.ts +1 -1
  63. package/dist/mocker/index.d.ts.map +1 -1
  64. package/dist/mocker/index.js +1 -1
  65. package/dist/mocker/registry.d.ts +2 -3
  66. package/dist/mocker/registry.d.ts.map +1 -1
  67. package/dist/mocker/registry.js +25 -16
  68. package/dist/namespace.d.ts +18 -0
  69. package/dist/namespace.d.ts.map +1 -0
  70. package/dist/namespace.js +19 -0
  71. package/dist/polyfills.d.ts +11 -0
  72. package/dist/polyfills.d.ts.map +1 -0
  73. package/dist/polyfills.js +13 -0
  74. package/dist/render/ErrorBoundary.d.ts +17 -0
  75. package/dist/render/ErrorBoundary.d.ts.map +1 -0
  76. package/dist/render/ErrorBoundary.js +73 -0
  77. package/dist/render/TestComponentOverlay.d.ts +3 -0
  78. package/dist/render/TestComponentOverlay.d.ts.map +1 -0
  79. package/dist/render/TestComponentOverlay.js +36 -0
  80. package/dist/render/cleanup.d.ts +2 -0
  81. package/dist/render/cleanup.d.ts.map +1 -0
  82. package/dist/render/cleanup.js +6 -0
  83. package/dist/render/index.d.ts +6 -0
  84. package/dist/render/index.d.ts.map +1 -0
  85. package/dist/render/index.js +66 -0
  86. package/dist/render/setup.d.ts +2 -0
  87. package/dist/render/setup.d.ts.map +1 -0
  88. package/dist/render/setup.js +7 -0
  89. package/dist/render/types.d.ts +12 -0
  90. package/dist/render/types.d.ts.map +1 -0
  91. package/dist/render/types.js +1 -0
  92. package/dist/runner/errors.d.ts +4 -2
  93. package/dist/runner/errors.d.ts.map +1 -1
  94. package/dist/runner/errors.js +21 -3
  95. package/dist/runner/factory.d.ts.map +1 -1
  96. package/dist/runner/factory.js +6 -1
  97. package/dist/runner/runSuite.d.ts.map +1 -1
  98. package/dist/runner/runSuite.js +59 -7
  99. package/dist/symbolicate.d.ts +3 -0
  100. package/dist/symbolicate.d.ts.map +1 -0
  101. package/dist/symbolicate.js +19 -0
  102. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  103. package/dist/ui/ReadyScreen.d.ts.map +1 -1
  104. package/dist/ui/ReadyScreen.js +3 -10
  105. package/dist/ui/WrongEnvironmentScreen.d.ts.map +1 -1
  106. package/dist/ui/WrongEnvironmentScreen.js +2 -10
  107. package/dist/ui/state.d.ts +14 -1
  108. package/dist/ui/state.d.ts.map +1 -1
  109. package/dist/ui/state.js +22 -0
  110. package/dist/utils/emitter.d.ts.map +1 -1
  111. package/dist/waitFor.d.ts +21 -0
  112. package/dist/waitFor.d.ts.map +1 -0
  113. package/dist/waitFor.js +137 -0
  114. package/eslint.config.mjs +1 -7
  115. package/package.json +22 -14
  116. package/src/__tests__/collector.test.ts +55 -55
  117. package/src/__tests__/error-handling.test.ts +34 -34
  118. package/src/__tests__/expect.test.ts +13 -5
  119. package/src/__tests__/initialize.test.ts +24 -0
  120. package/src/bundler/bundle.ts +9 -2
  121. package/src/bundler/errors.ts +11 -0
  122. package/src/bundler/evaluate.ts +9 -9
  123. package/src/bundler/factory.ts +43 -0
  124. package/src/bundler/index.ts +2 -1
  125. package/src/bundler/types.ts +7 -0
  126. package/src/client/factory.ts +53 -11
  127. package/src/client/getDeviceDescriptor.ts +29 -8
  128. package/src/client/getWSServer.ts +2 -1
  129. package/src/client/setup-files.ts +81 -0
  130. package/src/collector/functions.ts +18 -2
  131. package/src/collector/types.ts +4 -1
  132. package/src/constants.ts +0 -1
  133. package/src/disableHMRWhenReady.ts +27 -0
  134. package/src/entry-point.ts +8 -0
  135. package/src/expect/index.ts +8 -2
  136. package/src/expect/setup.ts +3 -0
  137. package/src/filtering/index.ts +4 -0
  138. package/src/filtering/testNameFilter.ts +82 -0
  139. package/src/globals.ts +15 -2
  140. package/src/index.ts +4 -0
  141. package/src/initialize.ts +21 -8
  142. package/src/jest-mock.ts +32 -0
  143. package/src/mocker/index.ts +6 -1
  144. package/src/mocker/metro-require.d.ts +2 -0
  145. package/src/mocker/registry.ts +29 -18
  146. package/src/namespace.ts +41 -0
  147. package/src/polyfills.ts +14 -0
  148. package/src/react-native.d.ts +35 -6
  149. package/src/render/ErrorBoundary.tsx +108 -0
  150. package/src/render/TestComponentOverlay.tsx +47 -0
  151. package/src/render/cleanup.ts +7 -0
  152. package/src/render/index.ts +96 -0
  153. package/src/render/setup.ts +8 -0
  154. package/src/render/types.ts +11 -0
  155. package/src/runner/errors.ts +35 -5
  156. package/src/runner/factory.ts +8 -1
  157. package/src/runner/runSuite.ts +70 -9
  158. package/src/symbolicate.ts +24 -0
  159. package/src/ui/ReadyScreen.tsx +2 -12
  160. package/src/ui/WrongEnvironmentScreen.tsx +1 -19
  161. package/src/ui/state.ts +39 -0
  162. package/src/utils/emitter.ts +1 -0
  163. package/src/waitFor.ts +199 -0
  164. package/tsconfig.spec.json +7 -3
  165. package/tsconfig.tsbuildinfo +1 -1
  166. package/assets/logo.png +0 -0
  167. package/assets/moduleSystem.flow.js +0 -1062
  168. package/types/global.d.ts +0 -2
  169. package/types/index.d.ts +0 -1
@@ -0,0 +1,12 @@
1
+ import type React from 'react';
2
+ export type RenderResult = {
3
+ rerender: (element: React.ReactElement) => Promise<void>;
4
+ unmount: () => void;
5
+ };
6
+ export type RenderOptions = {
7
+ timeout?: number;
8
+ wrapper?: React.ComponentType<{
9
+ children: React.ReactNode;
10
+ }>;
11
+ };
12
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/render/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;KAAE,CAAC,CAAC;CAC9D,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -1,9 +1,11 @@
1
- import type { SerializedError } from '@react-native-harness/bridge';
1
+ import type { SerializedError, CodeFrame } from '@react-native-harness/bridge';
2
2
  export declare class TestExecutionError extends Error {
3
3
  file: string;
4
4
  suite: string;
5
5
  test: string;
6
- constructor(error: unknown, file: string, suite: string, test: string);
6
+ codeFrame?: CodeFrame;
7
+ constructor(error: unknown, file: string, suite: string, test: string, codeFrame?: CodeFrame);
7
8
  toSerializedJSON(): SerializedError;
8
9
  }
10
+ export declare const getTestExecutionError: (error: unknown, file: string, suite: string, test: string) => Promise<TestExecutionError>;
9
11
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/runner/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEpE,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;gBAED,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IASrE,gBAAgB,IAAI,eAAe;CAcpC"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/runner/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAG/E,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,SAAS,CAAC;gBAGpB,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,SAAS;IAWvB,gBAAgB,IAAI,eAAe;CAapC;AAED,eAAO,MAAM,qBAAqB,GAChC,OAAO,OAAO,EACd,MAAM,MAAM,EACZ,OAAO,MAAM,EACb,MAAM,MAAM,KACX,OAAO,CAAC,kBAAkB,CAe5B,CAAC"}
@@ -1,23 +1,41 @@
1
+ import { getCodeFrame } from '../symbolicate.js';
1
2
  export class TestExecutionError extends Error {
2
3
  file;
3
4
  suite;
4
5
  test;
5
- constructor(error, file, suite, test) {
6
+ codeFrame;
7
+ constructor(error, file, suite, test, codeFrame) {
6
8
  super('Test execution error');
7
9
  this.name = 'TestExecutionError';
8
10
  this.file = file;
9
11
  this.suite = suite;
10
12
  this.test = test;
11
13
  this.cause = error;
14
+ this.codeFrame = codeFrame;
12
15
  }
13
16
  toSerializedJSON() {
14
17
  const causeName = this.cause instanceof Error ? this.cause.name : 'Unknown name';
15
18
  const causeMessage = this.cause instanceof Error ? this.cause.message : 'Unknown message';
16
- const causeStack = this.cause instanceof Error ? this.cause.stack : undefined;
19
+ const causeCodeFrame = this.codeFrame;
17
20
  return {
18
21
  name: causeName,
19
22
  message: causeMessage,
20
- stack: causeStack,
23
+ codeFrame: causeCodeFrame,
21
24
  };
22
25
  }
23
26
  }
27
+ export const getTestExecutionError = async (error, file, suite, test) => {
28
+ try {
29
+ if (error instanceof Error) {
30
+ const codeFrame = await getCodeFrame(error);
31
+ if (codeFrame) {
32
+ return new TestExecutionError(error, file, suite, test, codeFrame);
33
+ }
34
+ }
35
+ return new TestExecutionError(error, file, suite, test);
36
+ }
37
+ catch (error) {
38
+ // If the stack cannot be symbolicated, return the original error
39
+ return new TestExecutionError(error, file, suite, test);
40
+ }
41
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/runner/factory.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,eAAO,MAAM,aAAa,QAAO,UAehC,CAAC"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/runner/factory.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,eAAO,MAAM,aAAa,QAAO,UAsBhC,CAAC"}
@@ -5,10 +5,15 @@ export const getTestRunner = () => {
5
5
  return {
6
6
  events,
7
7
  run: async (testSuite, testFilePath) => {
8
- return runSuite(testSuite, {
8
+ const result = await runSuite(testSuite, {
9
9
  events,
10
10
  testFilePath,
11
11
  });
12
+ // If coverage is enabled, there will be a global variable called __coverage__
13
+ if ('__coverage__' in global && !!global.__coverage__) {
14
+ result.coverage = global.__coverage__;
15
+ }
16
+ return result;
12
17
  },
13
18
  dispose: () => {
14
19
  events.clearAllListeners();
@@ -1 +1 @@
1
- {"version":3,"file":"runSuite.d.ts","sourceRoot":"","sources":["../../src/runner/runSuite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,SAAS,EACT,eAAe,EAChB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAsH/C,eAAO,MAAM,QAAQ,GACnB,OAAO,SAAS,EAChB,SAAS,iBAAiB,KACzB,OAAO,CAAC,eAAe,CAuEzB,CAAC"}
1
+ {"version":3,"file":"runSuite.d.ts","sourceRoot":"","sources":["../../src/runner/runSuite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,SAAS,EACT,eAAe,EAChB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAsH/C,eAAO,MAAM,QAAQ,GACnB,OAAO,SAAS,EAChB,SAAS,iBAAiB,KACzB,OAAO,CAAC,eAAe,CAoIzB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { runHooks } from './hooks.js';
2
- import { TestExecutionError } from './errors.js';
2
+ import { getTestExecutionError } from './errors.js';
3
3
  const runTest = async (test, suite, context) => {
4
4
  const startTime = Date.now();
5
5
  // Emit test-started event
@@ -69,7 +69,7 @@ const runTest = async (test, suite, context) => {
69
69
  return result;
70
70
  }
71
71
  catch (error) {
72
- const testError = new TestExecutionError(error, context.testFilePath, suite.name, test.name);
72
+ const testError = await getTestExecutionError(error, context.testFilePath, suite.name, test.name);
73
73
  const duration = Date.now() - startTime;
74
74
  const result = {
75
75
  name: test.name,
@@ -98,6 +98,43 @@ export const runSuite = async (suite, context) => {
98
98
  name: suite.name,
99
99
  file: context.testFilePath,
100
100
  });
101
+ // Check if suite should be skipped or is todo
102
+ if (suite.status === 'skipped') {
103
+ const result = {
104
+ name: suite.name,
105
+ tests: [],
106
+ suites: [],
107
+ status: 'skipped',
108
+ duration: 0,
109
+ };
110
+ // Emit suite-finished event
111
+ context.events.emit({
112
+ type: 'suite-finished',
113
+ file: context.testFilePath,
114
+ name: suite.name,
115
+ duration: 0,
116
+ status: 'skipped',
117
+ });
118
+ return result;
119
+ }
120
+ if (suite.status === 'todo') {
121
+ const result = {
122
+ name: suite.name,
123
+ tests: [],
124
+ suites: [],
125
+ status: 'todo',
126
+ duration: 0,
127
+ };
128
+ // Emit suite-finished event
129
+ context.events.emit({
130
+ type: 'suite-finished',
131
+ file: context.testFilePath,
132
+ name: suite.name,
133
+ duration: 0,
134
+ status: 'todo',
135
+ });
136
+ return result;
137
+ }
101
138
  const testResults = [];
102
139
  const suiteResults = [];
103
140
  // Run beforeAll hooks
@@ -123,11 +160,26 @@ export const runSuite = async (suite, context) => {
123
160
  if (hasFailedTests || hasFailedSuites) {
124
161
  status = 'failed';
125
162
  }
126
- else if ((testResults.every((result) => result.status === 'skipped') &&
127
- suiteResults.every((result) => result.status === 'skipped') &&
128
- testResults.length > 0) ||
129
- suiteResults.length > 0) {
130
- status = 'skipped';
163
+ else {
164
+ // Check if all tests and suites are skipped (and there are some tests/suites to check)
165
+ const allTestsSkipped = testResults.length > 0 &&
166
+ testResults.every((result) => result.status === 'skipped');
167
+ const allSuitesSkipped = suiteResults.length > 0 &&
168
+ suiteResults.every((result) => result.status === 'skipped');
169
+ const hasAnyContent = testResults.length > 0 || suiteResults.length > 0;
170
+ if (hasAnyContent &&
171
+ ((testResults.length > 0 &&
172
+ allTestsSkipped &&
173
+ suiteResults.length === 0) ||
174
+ (suiteResults.length > 0 &&
175
+ allSuitesSkipped &&
176
+ testResults.length === 0) ||
177
+ (testResults.length > 0 &&
178
+ suiteResults.length > 0 &&
179
+ allTestsSkipped &&
180
+ allSuitesSkipped))) {
181
+ status = 'skipped';
182
+ }
131
183
  }
132
184
  // Emit suite-finished event
133
185
  context.events.emit({
@@ -0,0 +1,3 @@
1
+ import type { CodeFrame } from '@react-native-harness/bridge';
2
+ export declare const getCodeFrame: (error: Error) => Promise<CodeFrame | null>;
3
+ //# sourceMappingURL=symbolicate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbolicate.d.ts","sourceRoot":"","sources":["../src/symbolicate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAI9D,eAAO,MAAM,YAAY,GAAU,OAAO,KAAK,KAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAmBzE,CAAC"}
@@ -0,0 +1,19 @@
1
+ import parseErrorStack from 'react-native/Libraries/Core/Devtools/parseErrorStack';
2
+ import symbolicateStackTrace from 'react-native/Libraries/Core/Devtools/symbolicateStackTrace';
3
+ export const getCodeFrame = async (error) => {
4
+ const parsedStack = parseErrorStack(error.stack);
5
+ const symbolicatedStack = await symbolicateStackTrace(parsedStack);
6
+ if (!('codeFrame' in symbolicatedStack) || !symbolicatedStack.codeFrame) {
7
+ return null;
8
+ }
9
+ const codeFrame = symbolicatedStack.codeFrame;
10
+ // Normalize optionality (null -> undefined)
11
+ return {
12
+ ...codeFrame,
13
+ location: codeFrame.location
14
+ ? {
15
+ ...codeFrame.location,
16
+ }
17
+ : undefined,
18
+ };
19
+ };