react-native-harness 1.0.0-alpha.1 → 1.0.0-alpha.11

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 (111) hide show
  1. package/README.md +2 -2
  2. package/bin.js +1 -1
  3. package/dist/babel.d.ts +2 -0
  4. package/dist/babel.d.ts.map +1 -0
  5. package/dist/babel.js +1 -0
  6. package/dist/index.d.ts +1 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1 -37
  9. package/dist/metro.d.ts +2 -0
  10. package/dist/metro.d.ts.map +1 -0
  11. package/dist/metro.js +1 -0
  12. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  13. package/eslint.config.mjs +1 -1
  14. package/package.json +31 -12
  15. package/src/babel.ts +1 -0
  16. package/src/index.ts +1 -52
  17. package/src/metro.ts +1 -0
  18. package/tsconfig.json +9 -3
  19. package/tsconfig.lib.json +8 -14
  20. package/types/index.d.ts +1 -0
  21. package/dist/bundlers/metro.d.ts +0 -5
  22. package/dist/bundlers/metro.d.ts.map +0 -1
  23. package/dist/bundlers/metro.js +0 -52
  24. package/dist/bundlers/webpack.d.ts +0 -2
  25. package/dist/bundlers/webpack.d.ts.map +0 -1
  26. package/dist/bundlers/webpack.js +0 -49
  27. package/dist/commands/test.d.ts +0 -2
  28. package/dist/commands/test.d.ts.map +0 -1
  29. package/dist/commands/test.js +0 -111
  30. package/dist/errors/appNotInstalledError.d.ts +0 -7
  31. package/dist/errors/appNotInstalledError.d.ts.map +0 -1
  32. package/dist/errors/appNotInstalledError.js +0 -12
  33. package/dist/errors/bridgeTimeoutError.d.ts +0 -7
  34. package/dist/errors/bridgeTimeoutError.d.ts.map +0 -1
  35. package/dist/errors/bridgeTimeoutError.js +0 -12
  36. package/dist/errors/errorHandler.d.ts +0 -2
  37. package/dist/errors/errorHandler.d.ts.map +0 -1
  38. package/dist/errors/errorHandler.js +0 -138
  39. package/dist/errors/errors.d.ts +0 -41
  40. package/dist/errors/errors.d.ts.map +0 -1
  41. package/dist/errors/errors.js +0 -83
  42. package/dist/platforms/android/build.d.ts +0 -5
  43. package/dist/platforms/android/build.d.ts.map +0 -1
  44. package/dist/platforms/android/build.js +0 -29
  45. package/dist/platforms/android/device.d.ts +0 -5
  46. package/dist/platforms/android/device.d.ts.map +0 -1
  47. package/dist/platforms/android/device.js +0 -36
  48. package/dist/platforms/android/emulator.d.ts +0 -11
  49. package/dist/platforms/android/emulator.d.ts.map +0 -1
  50. package/dist/platforms/android/emulator.js +0 -110
  51. package/dist/platforms/android/index.d.ts +0 -4
  52. package/dist/platforms/android/index.d.ts.map +0 -1
  53. package/dist/platforms/android/index.js +0 -56
  54. package/dist/platforms/ios/build.d.ts +0 -7
  55. package/dist/platforms/ios/build.d.ts.map +0 -1
  56. package/dist/platforms/ios/build.js +0 -51
  57. package/dist/platforms/ios/device.d.ts +0 -7
  58. package/dist/platforms/ios/device.d.ts.map +0 -1
  59. package/dist/platforms/ios/device.js +0 -51
  60. package/dist/platforms/ios/index.d.ts +0 -4
  61. package/dist/platforms/ios/index.d.ts.map +0 -1
  62. package/dist/platforms/ios/index.js +0 -38
  63. package/dist/platforms/ios/simulator.d.ts +0 -11
  64. package/dist/platforms/ios/simulator.d.ts.map +0 -1
  65. package/dist/platforms/ios/simulator.js +0 -133
  66. package/dist/platforms/platform-adapter.d.ts +0 -10
  67. package/dist/platforms/platform-adapter.d.ts.map +0 -1
  68. package/dist/platforms/platform-adapter.js +0 -1
  69. package/dist/platforms/platform-registry.d.ts +0 -3
  70. package/dist/platforms/platform-registry.d.ts.map +0 -1
  71. package/dist/platforms/platform-registry.js +0 -19
  72. package/dist/platforms/web/index.d.ts +0 -4
  73. package/dist/platforms/web/index.d.ts.map +0 -1
  74. package/dist/platforms/web/index.js +0 -73
  75. package/dist/process.d.ts +0 -3
  76. package/dist/process.d.ts.map +0 -1
  77. package/dist/process.js +0 -28
  78. package/dist/reporters/default-reporter.d.ts +0 -3
  79. package/dist/reporters/default-reporter.d.ts.map +0 -1
  80. package/dist/reporters/default-reporter.js +0 -116
  81. package/dist/reporters/junit-reporter.d.ts +0 -3
  82. package/dist/reporters/junit-reporter.d.ts.map +0 -1
  83. package/dist/reporters/junit-reporter.js +0 -119
  84. package/dist/reporters/live-reporter.d.ts +0 -20
  85. package/dist/reporters/live-reporter.d.ts.map +0 -1
  86. package/dist/reporters/live-reporter.js +0 -176
  87. package/dist/src/reporters/default-reporter.js +0 -135
  88. package/dist/test-reporter-demo.js +0 -95
  89. package/dist/utils.d.ts +0 -5
  90. package/dist/utils.d.ts.map +0 -1
  91. package/dist/utils.js +0 -11
  92. package/src/bundlers/metro.ts +0 -79
  93. package/src/commands/test.ts +0 -189
  94. package/src/errors/errorHandler.ts +0 -184
  95. package/src/errors/errors.ts +0 -109
  96. package/src/platforms/android/build.ts +0 -48
  97. package/src/platforms/android/device.ts +0 -48
  98. package/src/platforms/android/emulator.ts +0 -139
  99. package/src/platforms/android/index.ts +0 -87
  100. package/src/platforms/ios/build.ts +0 -76
  101. package/src/platforms/ios/device.ts +0 -76
  102. package/src/platforms/ios/index.ts +0 -55
  103. package/src/platforms/ios/simulator.ts +0 -177
  104. package/src/platforms/platform-adapter.ts +0 -11
  105. package/src/platforms/platform-registry.ts +0 -24
  106. package/src/platforms/web/index.ts +0 -95
  107. package/src/process.ts +0 -33
  108. package/src/reporters/default-reporter.ts +0 -149
  109. package/src/reporters/junit-reporter.ts +0 -179
  110. package/src/utils.ts +0 -12
  111. package/tsconfig.tsbuildinfo +0 -1
package/dist/process.js DELETED
@@ -1,28 +0,0 @@
1
- export const killWithAwait = (child) => {
2
- return new Promise((resolve) => {
3
- const timeout = setTimeout(() => {
4
- child.kill('SIGTERM');
5
- resolve();
6
- }, 10000);
7
- if (child.killed || child.exitCode !== null) {
8
- clearTimeout(timeout);
9
- resolve();
10
- return;
11
- }
12
- child.on('exit', () => {
13
- clearTimeout(timeout);
14
- resolve();
15
- });
16
- child.on('error', () => {
17
- clearTimeout(timeout);
18
- resolve();
19
- });
20
- try {
21
- child.kill();
22
- }
23
- catch (error) {
24
- clearTimeout(timeout);
25
- resolve();
26
- }
27
- });
28
- };
@@ -1,3 +0,0 @@
1
- import { Reporter } from '@react-native-harness/config';
2
- export declare const defaultReporter: Reporter;
3
- //# sourceMappingURL=default-reporter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"default-reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/default-reporter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAExD,eAAO,MAAM,eAAe,EAAE,QAmC7B,CAAC"}
@@ -1,116 +0,0 @@
1
- import { color, spinner } from '@react-native-harness/tools';
2
- export const defaultReporter = {
3
- report: async (results) => {
4
- const resultsSpinner = spinner();
5
- resultsSpinner.start('Test Results');
6
- for (const suite of results) {
7
- resultsSpinner.message(formatSuiteResult(suite));
8
- }
9
- // Summary
10
- let totalPassed = 0, totalFailed = 0, totalSkipped = 0, totalTodo = 0;
11
- let totalDuration = 0;
12
- for (const suite of results) {
13
- const summary = getTestSummary(suite);
14
- totalPassed += summary.passed;
15
- totalFailed += summary.failed;
16
- totalSkipped += summary.skipped;
17
- totalTodo += summary.todo;
18
- totalDuration += suite.duration || 0;
19
- }
20
- const summaryText = [
21
- color.green(`${totalPassed} passed`),
22
- color.red(`${totalFailed} failed`),
23
- color.yellow(`${totalSkipped} skipped`),
24
- color.blue(`${totalTodo} todo`),
25
- ].join(', ');
26
- resultsSpinner.message(`Summary: ${summaryText}`);
27
- resultsSpinner.message(`Total time: ${formatDuration(totalDuration)}`);
28
- },
29
- };
30
- const formatDuration = (duration) => {
31
- if (duration == null)
32
- return '';
33
- return color.dim(` (${duration}ms)`);
34
- };
35
- const getStatusIcon = (status) => {
36
- switch (status) {
37
- case 'passed':
38
- return color.green('āœ“');
39
- case 'failed':
40
- return color.red('āœ—');
41
- case 'skipped':
42
- return color.yellow('ā—‹');
43
- case 'todo':
44
- return color.blue('◐');
45
- default:
46
- return '?';
47
- }
48
- };
49
- const formatTestResult = (test, indent = '') => {
50
- const icon = getStatusIcon(test.status);
51
- const name = test.status === 'failed' ? color.red(test.name) : test.name;
52
- const duration = formatDuration(test.duration);
53
- let result = `${indent}${icon} ${name}${duration}`;
54
- if (test.error) {
55
- const errorLines = test.error.message?.split('\n') || [];
56
- result +=
57
- '\n' +
58
- errorLines
59
- .map((line) => `${indent} ${color.red(line)}`)
60
- .join('\n');
61
- }
62
- return result;
63
- };
64
- const formatSuiteResult = (suite, indent = '') => {
65
- const icon = getStatusIcon(suite.status);
66
- const name = suite.status === 'failed' ? color.red(suite.name) : color.bold(suite.name);
67
- const duration = formatDuration(suite.duration);
68
- let result = `${indent}${icon} ${name}${duration}`;
69
- if (suite.error) {
70
- const errorLines = suite.error.message.split('\n');
71
- result +=
72
- '\n' +
73
- errorLines
74
- .map((line) => `${indent} ${color.red(line)}`)
75
- .join('\n');
76
- }
77
- const childIndent = indent + ' ';
78
- // Format tests
79
- for (const test of suite.tests) {
80
- result += '\n' + formatTestResult(test, childIndent);
81
- }
82
- // Format nested suites
83
- for (const childSuite of suite.suites) {
84
- result += '\n' + formatSuiteResult(childSuite, childIndent);
85
- }
86
- return result;
87
- };
88
- const getTestSummary = (suite) => {
89
- let passed = 0, failed = 0, skipped = 0, todo = 0;
90
- // Count tests in current suite
91
- for (const test of suite.tests) {
92
- switch (test.status) {
93
- case 'passed':
94
- passed++;
95
- break;
96
- case 'failed':
97
- failed++;
98
- break;
99
- case 'skipped':
100
- skipped++;
101
- break;
102
- case 'todo':
103
- todo++;
104
- break;
105
- }
106
- }
107
- // Count tests in nested suites
108
- for (const childSuite of suite.suites) {
109
- const childSummary = getTestSummary(childSuite);
110
- passed += childSummary.passed;
111
- failed += childSummary.failed;
112
- skipped += childSummary.skipped;
113
- todo += childSummary.todo;
114
- }
115
- return { passed, failed, skipped, todo };
116
- };
@@ -1,3 +0,0 @@
1
- import { Reporter } from '@react-native-harness/config';
2
- export declare const junitReporter: Reporter;
3
- //# sourceMappingURL=junit-reporter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"junit-reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/junit-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAKxD,eAAO,MAAM,aAAa,EAAE,QAU3B,CAAC"}
@@ -1,119 +0,0 @@
1
- import { writeFileSync } from 'fs';
2
- import { join } from 'path';
3
- export const junitReporter = {
4
- report: async (results) => {
5
- const xml = generateJUnitXML(results);
6
- // Write to junit.xml file
7
- const outputPath = join(process.cwd(), 'junit.xml');
8
- writeFileSync(outputPath, xml, 'utf8');
9
- console.log(`šŸ“„ JUnit report written to: ${outputPath}`);
10
- },
11
- };
12
- const generateJUnitXML = (results) => {
13
- const { totalTests, totalFailures, totalSkipped, totalTime } = calculateTotals(results);
14
- let xml = '<?xml version="1.0" encoding="UTF-8"?>\n';
15
- xml += `<testsuites tests="${totalTests}" failures="${totalFailures}" skipped="${totalSkipped}" time="${totalTime / 1000}">\n`;
16
- for (const suite of results) {
17
- xml += generateTestSuiteXML(suite, ' ');
18
- }
19
- xml += '</testsuites>\n';
20
- return xml;
21
- };
22
- const generateTestSuiteXML = (suite, indent) => {
23
- const { tests, failures, skipped, time } = getSuiteStats(suite);
24
- let xml = `${indent}<testsuite name="${escapeXML(suite.name)}" tests="${tests}" failures="${failures}" skipped="${skipped}" time="${time / 1000}"`;
25
- if (suite.error) {
26
- xml += ` errors="1"`;
27
- }
28
- xml += '>\n';
29
- // Add suite-level error if present
30
- if (suite.error) {
31
- xml += `${indent} <error message="${escapeXML(suite.error.message || 'Suite failed')}"`;
32
- if (suite.error.name) {
33
- xml += ` type="${escapeXML(suite.error.name)}"`;
34
- }
35
- xml += '>';
36
- if (suite.error.stack) {
37
- xml += escapeXML(suite.error.stack);
38
- }
39
- xml += '</error>\n';
40
- }
41
- // Add individual test cases
42
- for (const test of suite.tests) {
43
- xml += generateTestCaseXML(test, indent + ' ');
44
- }
45
- // Add nested suites
46
- for (const nestedSuite of suite.suites) {
47
- xml += generateTestSuiteXML(nestedSuite, indent + ' ');
48
- }
49
- xml += `${indent}</testsuite>\n`;
50
- return xml;
51
- };
52
- const generateTestCaseXML = (test, indent) => {
53
- const time = (test.duration || 0) / 1000;
54
- let xml = `${indent}<testcase name="${escapeXML(test.name)}" time="${time}"`;
55
- if (test.status === 'passed') {
56
- xml += '/>\n';
57
- }
58
- else {
59
- xml += '>\n';
60
- switch (test.status) {
61
- case 'failed':
62
- xml += `${indent} <failure message="${escapeXML(test.error?.message || 'Test failed')}"`;
63
- if (test.error?.name) {
64
- xml += ` type="${escapeXML(test.error.name)}"`;
65
- }
66
- xml += '>';
67
- if (test.error?.stack) {
68
- xml += escapeXML(test.error.stack);
69
- }
70
- xml += '</failure>\n';
71
- break;
72
- case 'skipped':
73
- xml += `${indent} <skipped/>\n`;
74
- break;
75
- case 'todo':
76
- xml += `${indent} <skipped message="TODO: Test not implemented"/>\n`;
77
- break;
78
- }
79
- xml += `${indent}</testcase>\n`;
80
- }
81
- return xml;
82
- };
83
- const calculateTotals = (results) => {
84
- let totalTests = 0;
85
- let totalFailures = 0;
86
- let totalSkipped = 0;
87
- let totalTime = 0;
88
- for (const suite of results) {
89
- const stats = getSuiteStats(suite);
90
- totalTests += stats.tests;
91
- totalFailures += stats.failures;
92
- totalSkipped += stats.skipped;
93
- totalTime += stats.time;
94
- }
95
- return { totalTests, totalFailures, totalSkipped, totalTime };
96
- };
97
- const getSuiteStats = (suite) => {
98
- let tests = suite.tests.length;
99
- let failures = suite.tests.filter((t) => t.status === 'failed').length;
100
- let skipped = suite.tests.filter((t) => t.status === 'skipped' || t.status === 'todo').length;
101
- let time = suite.duration || 0;
102
- // Add stats from nested suites
103
- for (const nestedSuite of suite.suites) {
104
- const nestedStats = getSuiteStats(nestedSuite);
105
- tests += nestedStats.tests;
106
- failures += nestedStats.failures;
107
- skipped += nestedStats.skipped;
108
- time += nestedStats.time;
109
- }
110
- return { tests, failures, skipped, time };
111
- };
112
- const escapeXML = (str) => {
113
- return str
114
- .replace(/&/g, '&amp;')
115
- .replace(/</g, '&lt;')
116
- .replace(/>/g, '&gt;')
117
- .replace(/"/g, '&quot;')
118
- .replace(/'/g, '&apos;');
119
- };
@@ -1,20 +0,0 @@
1
- import type { SuiteResult, LiveReportingEvent } from '@react-native-harness/bridge';
2
- import { Reporter } from '@react-native-harness/config';
3
- export declare class LiveReporter {
4
- private state;
5
- private progressSpinner;
6
- constructor();
7
- start(): void;
8
- handleLiveEvent(event: LiveReportingEvent): void;
9
- private getStatusSymbol;
10
- private updateProgress;
11
- private formatDuration;
12
- stop(message: string): void;
13
- countTests(suite: SuiteResult): number;
14
- setTotalTests(results: SuiteResult[]): void;
15
- }
16
- export declare const createLiveReporter: () => {
17
- reporter: Reporter;
18
- liveReporter: LiveReporter;
19
- };
20
- //# sourceMappingURL=live-reporter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"live-reporter.d.ts","sourceRoot":"","sources":["../../src/reporters/live-reporter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EAEX,kBAAkB,EACnB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAcxD,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,eAAe,CAA6B;;IAiBpD,KAAK;IAKL,eAAe,CAAC,KAAK,EAAE,kBAAkB;IA4DzC,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,cAAc;IA6BtB,OAAO,CAAC,cAAc;IAMtB,IAAI,CAAC,OAAO,EAAE,MAAM;IAKpB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM;IAQtC,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE;CAMrC;AAED,eAAO,MAAM,kBAAkB,QAAO;IACpC,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,YAAY,CAAC;CA0C5B,CAAC"}
@@ -1,176 +0,0 @@
1
- import { color, spinner } from '@react-native-harness/tools';
2
- export class LiveReporter {
3
- state;
4
- progressSpinner;
5
- constructor() {
6
- this.state = {
7
- totalTests: 0,
8
- completedTests: 0,
9
- passedTests: 0,
10
- failedTests: 0,
11
- skippedTests: 0,
12
- todoTests: 0,
13
- currentTest: null,
14
- currentSuite: null,
15
- startTime: Date.now(),
16
- };
17
- this.progressSpinner = spinner();
18
- }
19
- start() {
20
- this.state.startTime = Date.now();
21
- this.progressSpinner.start('Initializing tests...');
22
- }
23
- handleLiveEvent(event) {
24
- switch (event.type) {
25
- case 'suite_started':
26
- this.state.currentSuite = event.suiteHierarchy.join(' > ');
27
- this.updateProgress(`Starting suite: ${this.state.currentSuite}`);
28
- break;
29
- case 'test_started':
30
- this.state.currentTest = `${event.suiteHierarchy.join(' > ')} > ${event.testName}`;
31
- this.updateProgress(`Running: ${event.testName}`);
32
- break;
33
- case 'test_completed':
34
- this.state.completedTests++;
35
- switch (event.result.status) {
36
- case 'passed':
37
- this.state.passedTests++;
38
- break;
39
- case 'failed':
40
- this.state.failedTests++;
41
- break;
42
- case 'skipped':
43
- this.state.skippedTests++;
44
- break;
45
- case 'todo':
46
- this.state.todoTests++;
47
- break;
48
- }
49
- const statusSymbol = this.getStatusSymbol(event.result.status);
50
- const duration = event.result.duration
51
- ? ` (${event.result.duration}ms)`
52
- : '';
53
- this.updateProgress(`${statusSymbol} ${event.testName}${duration}`, event.result.status === 'failed'
54
- ? event.result.error?.message
55
- : undefined);
56
- break;
57
- case 'suite_completed':
58
- const suiteStatusSymbol = this.getStatusSymbol(event.result.status);
59
- const suiteDuration = event.result.duration
60
- ? ` (${event.result.duration}ms)`
61
- : '';
62
- this.updateProgress(`${suiteStatusSymbol} Suite completed: ${event.suiteHierarchy.join(' > ')}${suiteDuration}`);
63
- break;
64
- }
65
- }
66
- getStatusSymbol(status) {
67
- switch (status) {
68
- case 'passed':
69
- return color.green('āœ“');
70
- case 'failed':
71
- return color.red('āœ—');
72
- case 'skipped':
73
- return color.yellow('-');
74
- case 'todo':
75
- return color.blue('ā—‹');
76
- default:
77
- return '?';
78
- }
79
- }
80
- updateProgress(message, error) {
81
- const elapsed = Date.now() - this.state.startTime;
82
- const elapsedFormatted = this.formatDuration(elapsed);
83
- const progress = this.state.totalTests > 0
84
- ? ` [${this.state.completedTests}/${this.state.totalTests}]`
85
- : ` [${this.state.completedTests} completed]`;
86
- const summary = [
87
- color.green(`${this.state.passedTests} passed`),
88
- ...(this.state.failedTests > 0
89
- ? [color.red(`${this.state.failedTests} failed`)]
90
- : []),
91
- ...(this.state.skippedTests > 0
92
- ? [color.yellow(`${this.state.skippedTests} skipped`)]
93
- : []),
94
- ...(this.state.todoTests > 0
95
- ? [color.blue(`${this.state.todoTests} todo`)]
96
- : []),
97
- ].join(', ');
98
- this.progressSpinner.message(`${message}${progress} | ${summary} | ${elapsedFormatted}${error ? `\n ${color.red('Error:')} ${error}` : ''}`);
99
- }
100
- formatDuration(ms) {
101
- if (ms < 1000)
102
- return `${ms}ms`;
103
- if (ms < 60000)
104
- return `${(ms / 1000).toFixed(1)}s`;
105
- return `${Math.floor(ms / 60000)}m ${Math.floor((ms % 60000) / 1000)}s`;
106
- }
107
- stop(message) {
108
- this.progressSpinner.stop(message);
109
- }
110
- // Count total tests in suite hierarchy
111
- countTests(suite) {
112
- let count = suite.tests.length;
113
- for (const childSuite of suite.suites) {
114
- count += this.countTests(childSuite);
115
- }
116
- return count;
117
- }
118
- setTotalTests(results) {
119
- this.state.totalTests = results.reduce((sum, suite) => sum + this.countTests(suite), 0);
120
- }
121
- }
122
- export const createLiveReporter = () => {
123
- const liveReporter = new LiveReporter();
124
- const reporter = {
125
- report: async (results) => {
126
- // Final summary is handled by the existing default reporter logic
127
- const totalPassed = results.reduce((sum, suite) => sum + getTestSummary(suite).passed, 0);
128
- const totalFailed = results.reduce((sum, suite) => sum + getTestSummary(suite).failed, 0);
129
- const totalSkipped = results.reduce((sum, suite) => sum + getTestSummary(suite).skipped, 0);
130
- const totalTodo = results.reduce((sum, suite) => sum + getTestSummary(suite).todo, 0);
131
- const totalDuration = results.reduce((sum, suite) => sum + (suite.duration || 0), 0);
132
- const summaryText = [
133
- color.green(`${totalPassed} passed`),
134
- color.red(`${totalFailed} failed`),
135
- color.yellow(`${totalSkipped} skipped`),
136
- color.blue(`${totalTodo} todo`),
137
- ].join(', ');
138
- liveReporter.stop(`Summary: ${summaryText} | Total time: ${formatDuration(totalDuration)}`);
139
- },
140
- };
141
- return { reporter, liveReporter };
142
- };
143
- const getTestSummary = (suite) => {
144
- let passed = 0, failed = 0, skipped = 0, todo = 0;
145
- // Count tests in current suite
146
- for (const test of suite.tests) {
147
- switch (test.status) {
148
- case 'passed':
149
- passed++;
150
- break;
151
- case 'failed':
152
- failed++;
153
- break;
154
- case 'skipped':
155
- skipped++;
156
- break;
157
- case 'todo':
158
- todo++;
159
- break;
160
- }
161
- }
162
- // Count tests in nested suites
163
- for (const childSuite of suite.suites) {
164
- const childSummary = getTestSummary(childSuite);
165
- passed += childSummary.passed;
166
- failed += childSummary.failed;
167
- skipped += childSummary.skipped;
168
- todo += childSummary.todo;
169
- }
170
- return { passed, failed, skipped, todo };
171
- };
172
- const formatDuration = (duration) => duration
173
- ? duration < 1000
174
- ? `${duration}ms`
175
- : `${(duration / 1000).toFixed(2)}s`
176
- : '0ms';
@@ -1,135 +0,0 @@
1
- import { color, logger } from '@react-native-harness/tools';
2
- export const defaultReporter = {
3
- report: async (results) => {
4
- logger.log('\nšŸ“‹ Test Results');
5
- console.log(color.dim('━'.repeat(60)));
6
- for (const suite of results) {
7
- console.log(formatSuiteResult(suite));
8
- }
9
- console.log(color.dim('━'.repeat(60)));
10
- // Summary
11
- let totalPassed = 0, totalFailed = 0, totalSkipped = 0, totalTodo = 0;
12
- let totalDuration = 0;
13
- for (const suite of results) {
14
- const summary = getTestSummary(suite);
15
- totalPassed += summary.passed;
16
- totalFailed += summary.failed;
17
- totalSkipped += summary.skipped;
18
- totalTodo += summary.todo;
19
- totalDuration += suite.duration || 0;
20
- }
21
- // Create summary with modern styling
22
- const summaryParts = [];
23
- if (totalPassed > 0) {
24
- summaryParts.push(color.green(`${totalPassed} passed`));
25
- }
26
- if (totalFailed > 0) {
27
- summaryParts.push(color.red(`${totalFailed} failed`));
28
- }
29
- if (totalSkipped > 0) {
30
- summaryParts.push(color.yellow(`${totalSkipped} skipped`));
31
- }
32
- if (totalTodo > 0) {
33
- summaryParts.push(color.blue(`${totalTodo} todo`));
34
- }
35
- const summaryText = summaryParts.join(color.dim(' • '));
36
- const durationText = formatDuration(totalDuration);
37
- logger.info(`šŸ“Š Summary: ${summaryText}${durationText}`);
38
- // Show appropriate final message
39
- if (totalFailed === 0 && totalPassed > 0) {
40
- logger.success('All tests passed! šŸŽ‰');
41
- }
42
- else if (totalFailed > 0) {
43
- logger.error(`${totalFailed} test${totalFailed === 1 ? '' : 's'} failed`);
44
- }
45
- },
46
- };
47
- const formatDuration = (duration) => {
48
- if (!duration)
49
- return '';
50
- return color.dim(` (${duration}ms)`);
51
- };
52
- const getStatusIcon = (status) => {
53
- switch (status) {
54
- case 'passed':
55
- return color.green('āœ“');
56
- case 'failed':
57
- return color.red('āœ—');
58
- case 'skipped':
59
- return color.yellow('ā—‹');
60
- case 'todo':
61
- return color.blue('◐');
62
- default:
63
- return '?';
64
- }
65
- };
66
- const formatTestResult = (test, indent = '') => {
67
- const icon = getStatusIcon(test.status);
68
- const name = test.status === 'failed' ? color.red(test.name) : test.name;
69
- const duration = formatDuration(test.duration);
70
- let result = `${indent}${icon} ${name}${duration}`;
71
- if (test.error) {
72
- const errorLines = test.error.message?.split('\n') || [];
73
- result +=
74
- '\n' +
75
- errorLines
76
- .map((line) => `${indent} ${color.red(line)}`)
77
- .join('\n');
78
- }
79
- return result;
80
- };
81
- const formatSuiteResult = (suite, indent = '') => {
82
- const icon = getStatusIcon(suite.status);
83
- const name = suite.status === 'failed'
84
- ? color.red(color.bold(suite.name))
85
- : color.bold(color.cyan(suite.name));
86
- const duration = formatDuration(suite.duration);
87
- let result = `${indent}${icon} ${name}${duration}`;
88
- if (suite.error) {
89
- const errorLines = suite.error.message.split('\n');
90
- result +=
91
- '\n' +
92
- errorLines
93
- .map((line) => `${indent} ${color.red(line)}`)
94
- .join('\n');
95
- }
96
- const childIndent = indent + ' ';
97
- // Format tests
98
- for (const test of suite.tests) {
99
- result += '\n' + formatTestResult(test, childIndent);
100
- }
101
- // Format nested suites
102
- for (const childSuite of suite.suites) {
103
- result += '\n' + formatSuiteResult(childSuite, childIndent);
104
- }
105
- return result;
106
- };
107
- const getTestSummary = (suite) => {
108
- let passed = 0, failed = 0, skipped = 0, todo = 0;
109
- // Count tests in current suite
110
- for (const test of suite.tests) {
111
- switch (test.status) {
112
- case 'passed':
113
- passed++;
114
- break;
115
- case 'failed':
116
- failed++;
117
- break;
118
- case 'skipped':
119
- skipped++;
120
- break;
121
- case 'todo':
122
- todo++;
123
- break;
124
- }
125
- }
126
- // Count tests in nested suites
127
- for (const childSuite of suite.suites) {
128
- const childSummary = getTestSummary(childSuite);
129
- passed += childSummary.passed;
130
- failed += childSummary.failed;
131
- skipped += childSummary.skipped;
132
- todo += childSummary.todo;
133
- }
134
- return { passed, failed, skipped, todo };
135
- };