@react-native-harness/jest 1.3.0 → 1.4.0

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 (98) hide show
  1. package/dist/__tests__/bridge.test.js +29 -4
  2. package/dist/__tests__/crash-monitor.test.js +194 -176
  3. package/dist/__tests__/environment-reset.test.d.ts +2 -0
  4. package/dist/__tests__/environment-reset.test.d.ts.map +1 -0
  5. package/dist/__tests__/environment-reset.test.js +238 -0
  6. package/dist/__tests__/errors.test.js +39 -0
  7. package/dist/__tests__/execute-run.test.js +439 -29
  8. package/dist/__tests__/format-harness-error.test.d.ts +2 -0
  9. package/dist/__tests__/format-harness-error.test.d.ts.map +1 -0
  10. package/dist/__tests__/format-harness-error.test.js +27 -0
  11. package/dist/__tests__/harness-cache.test.js +62 -41
  12. package/dist/__tests__/harness-session-signal.test.d.ts +2 -0
  13. package/dist/__tests__/harness-session-signal.test.d.ts.map +1 -0
  14. package/dist/__tests__/harness-session-signal.test.js +298 -0
  15. package/dist/__tests__/harness-session.test.js +217 -234
  16. package/dist/__tests__/index.test.js +62 -11
  17. package/dist/__tests__/metro-port.test.js +2 -0
  18. package/dist/__tests__/run.test.d.ts +2 -0
  19. package/dist/__tests__/run.test.d.ts.map +1 -0
  20. package/dist/__tests__/run.test.js +48 -0
  21. package/dist/__tests__/test-file-platform-filter.test.d.ts +2 -0
  22. package/dist/__tests__/test-file-platform-filter.test.d.ts.map +1 -0
  23. package/dist/__tests__/test-file-platform-filter.test.js +47 -0
  24. package/dist/crash-monitor.d.ts +12 -4
  25. package/dist/crash-monitor.d.ts.map +1 -1
  26. package/dist/crash-monitor.js +135 -102
  27. package/dist/diagnostics/__tests__/derivers.test.d.ts +2 -0
  28. package/dist/diagnostics/__tests__/derivers.test.d.ts.map +1 -0
  29. package/dist/diagnostics/__tests__/derivers.test.js +248 -0
  30. package/dist/diagnostics/__tests__/report.test.d.ts +2 -0
  31. package/dist/diagnostics/__tests__/report.test.d.ts.map +1 -0
  32. package/dist/diagnostics/__tests__/report.test.js +97 -0
  33. package/dist/diagnostics/derivers.d.ts +24 -0
  34. package/dist/diagnostics/derivers.d.ts.map +1 -0
  35. package/dist/diagnostics/derivers.js +146 -0
  36. package/dist/diagnostics/index.d.ts +3 -0
  37. package/dist/diagnostics/index.d.ts.map +1 -0
  38. package/dist/diagnostics/index.js +2 -0
  39. package/dist/diagnostics/report.d.ts +7 -0
  40. package/dist/diagnostics/report.d.ts.map +1 -0
  41. package/dist/diagnostics/report.js +84 -0
  42. package/dist/environment-reset.d.ts +51 -0
  43. package/dist/environment-reset.d.ts.map +1 -0
  44. package/dist/environment-reset.js +83 -0
  45. package/dist/errors.d.ts +10 -0
  46. package/dist/errors.d.ts.map +1 -1
  47. package/dist/errors.js +41 -2
  48. package/dist/execute-run.d.ts +4 -2
  49. package/dist/execute-run.d.ts.map +1 -1
  50. package/dist/execute-run.js +179 -49
  51. package/dist/format-harness-error.d.ts +5 -0
  52. package/dist/format-harness-error.d.ts.map +1 -0
  53. package/dist/format-harness-error.js +43 -0
  54. package/dist/harness-session.d.ts +46 -1
  55. package/dist/harness-session.d.ts.map +1 -1
  56. package/dist/harness-session.js +386 -118
  57. package/dist/index.d.ts +7 -3
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +24 -2
  60. package/dist/run.d.ts.map +1 -1
  61. package/dist/run.js +22 -4
  62. package/dist/test-file-platform-filter.d.ts +5 -0
  63. package/dist/test-file-platform-filter.d.ts.map +1 -0
  64. package/dist/test-file-platform-filter.js +40 -0
  65. package/dist/toTestResult.d.ts +1 -0
  66. package/dist/toTestResult.d.ts.map +1 -1
  67. package/dist/toTestResult.js +2 -2
  68. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  69. package/package.json +8 -7
  70. package/src/__tests__/bridge.test.ts +45 -5
  71. package/src/__tests__/crash-monitor.test.ts +234 -199
  72. package/src/__tests__/environment-reset.test.ts +308 -0
  73. package/src/__tests__/errors.test.ts +75 -0
  74. package/src/__tests__/execute-run.test.ts +561 -37
  75. package/src/__tests__/format-harness-error.test.ts +32 -0
  76. package/src/__tests__/harness-cache.test.ts +91 -0
  77. package/src/__tests__/harness-session.test.ts +303 -0
  78. package/src/__tests__/index.test.ts +92 -12
  79. package/src/__tests__/metro-port.test.ts +2 -0
  80. package/src/__tests__/run.test.ts +74 -0
  81. package/src/__tests__/test-file-platform-filter.test.ts +83 -0
  82. package/src/crash-monitor.ts +220 -131
  83. package/src/diagnostics/__tests__/derivers.test.ts +300 -0
  84. package/src/diagnostics/__tests__/report.test.ts +128 -0
  85. package/src/diagnostics/derivers.ts +170 -0
  86. package/src/diagnostics/index.ts +2 -0
  87. package/src/diagnostics/report.ts +124 -0
  88. package/src/environment-reset.ts +138 -0
  89. package/src/errors.ts +62 -1
  90. package/src/execute-run.ts +230 -57
  91. package/src/format-harness-error.ts +73 -0
  92. package/src/harness-session.ts +535 -162
  93. package/src/index.ts +40 -11
  94. package/src/run.ts +24 -4
  95. package/src/test-file-platform-filter.ts +57 -0
  96. package/src/toTestResult.ts +3 -2
  97. package/tsconfig.json +3 -0
  98. package/tsconfig.lib.json +3 -0
package/src/index.ts CHANGED
@@ -1,10 +1,8 @@
1
1
  import type {
2
- CallbackTestRunnerInterface,
3
2
  Config,
4
- OnTestFailure,
5
- OnTestStart,
6
- OnTestSuccess,
3
+ EmittingTestRunnerInterface,
7
4
  Test,
5
+ TestEvents,
8
6
  TestRunnerOptions,
9
7
  TestWatcher,
10
8
  } from 'jest-runner';
@@ -13,22 +11,41 @@ import { executeRun } from './execute-run.js';
13
11
  import { HarnessError } from '@react-native-harness/tools';
14
12
  import { getErrorMessage } from './logs.js';
15
13
 
16
- export default class JestHarness implements CallbackTestRunnerInterface {
14
+ type TestEventListener<Name extends keyof TestEvents> = (
15
+ eventData: TestEvents[Name],
16
+ ) => void | Promise<void>;
17
+
18
+ export default class JestHarness implements EmittingTestRunnerInterface {
17
19
  readonly isSerial = true;
20
+ readonly supportsEventEmitters = true as const;
18
21
 
19
22
  #globalConfig: Config.GlobalConfig;
20
23
  #session: HarnessSession | null = null;
24
+ #listeners = new Map<keyof TestEvents, Set<TestEventListener<keyof TestEvents>>>();
21
25
 
22
26
  constructor(globalConfig: Config.GlobalConfig) {
23
27
  this.#globalConfig = globalConfig;
24
28
  }
25
29
 
30
+ on<Name extends keyof TestEvents>(
31
+ eventName: Name,
32
+ listener: TestEventListener<Name>,
33
+ ): () => void {
34
+ const listeners = this.#listeners.get(eventName) ?? new Set();
35
+ listeners.add(listener as TestEventListener<keyof TestEvents>);
36
+ this.#listeners.set(eventName, listeners);
37
+
38
+ return () => {
39
+ listeners.delete(listener as TestEventListener<keyof TestEvents>);
40
+ if (listeners.size === 0) {
41
+ this.#listeners.delete(eventName);
42
+ }
43
+ };
44
+ }
45
+
26
46
  async runTests(
27
47
  tests: Array<Test>,
28
48
  watcher: TestWatcher,
29
- onStart: OnTestStart,
30
- onResult: OnTestSuccess,
31
- onFailure: OnTestFailure,
32
49
  options: TestRunnerOptions,
33
50
  ): Promise<void> {
34
51
  if (!options.serial) {
@@ -46,9 +63,7 @@ export default class JestHarness implements CallbackTestRunnerInterface {
46
63
  this.#session,
47
64
  tests,
48
65
  watcher,
49
- onStart,
50
- onResult,
51
- onFailure,
66
+ this.#emit,
52
67
  this.#globalConfig,
53
68
  );
54
69
  } catch (error) {
@@ -63,4 +78,18 @@ export default class JestHarness implements CallbackTestRunnerInterface {
63
78
  }
64
79
  }
65
80
  }
81
+
82
+ #emit = async <Name extends keyof TestEvents>(
83
+ eventName: Name,
84
+ ...eventData: TestEvents[Name]
85
+ ): Promise<void> => {
86
+ const listeners = this.#listeners.get(eventName);
87
+ if (!listeners) {
88
+ return;
89
+ }
90
+
91
+ for (const listener of listeners) {
92
+ await listener(eventData);
93
+ }
94
+ };
66
95
  }
package/src/run.ts CHANGED
@@ -8,6 +8,7 @@ import type {
8
8
  import type { HarnessSession } from './harness-session.js';
9
9
  import { formatResultsErrors } from 'jest-message-util';
10
10
  import { toTestResult } from './toTestResult.js';
11
+ import { formatHarnessErrorMessage } from './format-harness-error.js';
11
12
 
12
13
  // Helper function to flatten nested test suites into a flat array of tests with hierarchy
13
14
  const flattenTests = (
@@ -16,6 +17,17 @@ const flattenTests = (
16
17
  ): Array<HarnessTestResult & { ancestorTitles: string[] }> => {
17
18
  const tests: Array<HarnessTestResult & { ancestorTitles: string[] }> = [];
18
19
 
20
+ if (suiteResult.error) {
21
+ tests.push({
22
+ name: suiteResult.name,
23
+ status: 'failed',
24
+ duration: suiteResult.duration,
25
+ error: suiteResult.error,
26
+ ancestorTitles: [...ancestorTitles],
27
+ fullName: [...ancestorTitles, suiteResult.name].join(' '),
28
+ });
29
+ }
30
+
19
31
  // Add tests from current suite with current hierarchy
20
32
  for (const test of suiteResult.tests) {
21
33
  tests.push({
@@ -88,11 +100,18 @@ export const runHarnessTestFile: RunHarnessTestFile = async ({
88
100
  const setupFilesAfterEnv = projectConfig.setupFilesAfterEnv?.map(
89
101
  (setupFile) => path.relative(globalConfig.rootDir, setupFile)
90
102
  );
103
+ const testTimeout =
104
+ session.config.testTimeout ??
105
+ (projectConfig as JestConfig.ProjectConfig & { testTimeout?: number })
106
+ .testTimeout ??
107
+ (globalConfig as JestConfig.GlobalConfig & { testTimeout?: number })
108
+ .testTimeout;
91
109
 
92
110
  const harnessResult = await session.runTestFile(relativeTestPath, {
93
111
  testNamePattern: globalConfig.testNamePattern,
94
112
  setupFiles,
95
113
  setupFilesAfterEnv,
114
+ testTimeout,
96
115
  runner: session.context.platform.runner,
97
116
  });
98
117
  const end = Date.now();
@@ -102,15 +121,16 @@ export const runHarnessTestFile: RunHarnessTestFile = async ({
102
121
 
103
122
  // Convert TestResult[] to the format expected by toTestResult
104
123
  const tests = allTests.map((test) => {
105
- const errorMessage = test.error?.message;
106
124
  const codeFrame = test.error?.codeFrame;
125
+ const errorMessage = formatHarnessErrorMessage(test.error, {
126
+ testStartedAt: test.startedAt,
127
+ });
107
128
 
108
129
  return {
109
130
  duration: test.duration,
110
- errorMessage: errorMessage
111
- ? `${errorMessage}${codeFrame ? `\n\n${codeFrame.content}` : ''}`
112
- : undefined,
131
+ errorMessage,
113
132
  title: test.name,
133
+ fullName: test.fullName,
114
134
  status: test.status,
115
135
  location: codeFrame?.location
116
136
  ? { column: codeFrame.location.column, line: codeFrame.location.row }
@@ -0,0 +1,57 @@
1
+ import path from 'node:path';
2
+ import type { TestResult as JestTestResult } from '@jest/test-result';
3
+ import { toTestResult } from './toTestResult.js';
4
+
5
+ const PLATFORM_SPECIFIC_HARNESS_FILE =
6
+ /\.([^.]+)\.harness\.(?:[mc]?[jt]sx?)$/;
7
+
8
+ export const getHarnessTestFilePlatform = (
9
+ testPath: string,
10
+ knownPlatformIds: ReadonlySet<string>,
11
+ ): string | null => {
12
+ const match = path.basename(testPath).match(PLATFORM_SPECIFIC_HARNESS_FILE);
13
+ if (!match) {
14
+ return null;
15
+ }
16
+
17
+ const candidate = match[1];
18
+ return knownPlatformIds.has(candidate) ? candidate : null;
19
+ };
20
+
21
+ export const shouldRunHarnessTestFile = (
22
+ testPath: string,
23
+ platformId: string,
24
+ knownPlatformIds: ReadonlySet<string>,
25
+ ): boolean => {
26
+ const filePlatform = getHarnessTestFilePlatform(testPath, knownPlatformIds);
27
+ return filePlatform == null || filePlatform === platformId;
28
+ };
29
+
30
+ export const createPlatformSkippedTestResult = (
31
+ testPath: string,
32
+ ): JestTestResult => {
33
+ const now = Date.now();
34
+ const title = path.basename(testPath);
35
+
36
+ return toTestResult({
37
+ stats: {
38
+ failures: 0,
39
+ passes: 0,
40
+ pending: 1,
41
+ todo: 0,
42
+ start: now,
43
+ end: now,
44
+ },
45
+ skipped: true,
46
+ errorMessage: null,
47
+ tests: [
48
+ {
49
+ status: 'skipped',
50
+ title,
51
+ fullName: title,
52
+ testPath,
53
+ },
54
+ ],
55
+ jestTestPath: testPath,
56
+ });
57
+ };
@@ -16,6 +16,7 @@ export type Options = {
16
16
  errorMessage?: string;
17
17
  testPath?: string;
18
18
  title?: string;
19
+ fullName?: string;
19
20
  status: Status;
20
21
  location?: {
21
22
  column: number;
@@ -72,8 +73,8 @@ const getTestResults = ({
72
73
  duration: test.duration,
73
74
  failureDetails: [],
74
75
  failureMessages: actualErrorMessage ? [actualErrorMessage] : [],
75
- fullName: jestTestPath || test.testPath || '',
76
- numPassingAsserts: test.errorMessage ? 1 : 0,
76
+ fullName: test.fullName || test.testPath || jestTestPath || '',
77
+ numPassingAsserts: test.status === 'passed' ? 1 : 0,
77
78
  status: test.status,
78
79
  title: test.title || '',
79
80
  location: test.location,
package/tsconfig.json CHANGED
@@ -6,6 +6,9 @@
6
6
  {
7
7
  "path": "../tools"
8
8
  },
9
+ {
10
+ "path": "../cache"
11
+ },
9
12
  {
10
13
  "path": "../platforms"
11
14
  },
package/tsconfig.lib.json CHANGED
@@ -15,6 +15,9 @@
15
15
  {
16
16
  "path": "../tools/tsconfig.lib.json"
17
17
  },
18
+ {
19
+ "path": "../cache/tsconfig.lib.json"
20
+ },
18
21
  {
19
22
  "path": "../platforms/tsconfig.lib.json"
20
23
  },