@react-native-harness/runtime 1.0.0-alpha.15 → 1.0.0-alpha.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/assets/moduleSystem.flow.js +15 -98
  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 -6
  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/filtering/index.d.ts +1 -1
  18. package/dist/filtering/index.d.ts.map +1 -1
  19. package/dist/filtering/index.js +1 -1
  20. package/dist/filtering/testNameFilter.d.ts +6 -0
  21. package/dist/filtering/testNameFilter.d.ts.map +1 -1
  22. package/dist/filtering/testNameFilter.js +36 -5
  23. package/dist/globals.d.ts +5 -2
  24. package/dist/globals.d.ts.map +1 -1
  25. package/dist/globals.js +7 -1
  26. package/dist/index.d.ts +1 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +1 -0
  29. package/dist/initialize.js +7 -0
  30. package/dist/jest-mock.d.ts +2 -0
  31. package/dist/jest-mock.d.ts.map +1 -0
  32. package/dist/jest-mock.js +25 -0
  33. package/dist/render/ErrorBoundary.d.ts +17 -0
  34. package/dist/render/ErrorBoundary.d.ts.map +1 -0
  35. package/dist/render/ErrorBoundary.js +73 -0
  36. package/dist/render/TestComponentOverlay.d.ts +3 -0
  37. package/dist/render/TestComponentOverlay.d.ts.map +1 -0
  38. package/dist/render/TestComponentOverlay.js +36 -0
  39. package/dist/render/cleanup.d.ts +2 -0
  40. package/dist/render/cleanup.d.ts.map +1 -0
  41. package/dist/render/cleanup.js +6 -0
  42. package/dist/render/index.d.ts +6 -0
  43. package/dist/render/index.d.ts.map +1 -0
  44. package/dist/render/index.js +66 -0
  45. package/dist/render/setup.d.ts +2 -0
  46. package/dist/render/setup.d.ts.map +1 -0
  47. package/dist/render/setup.js +7 -0
  48. package/dist/render/types.d.ts +12 -0
  49. package/dist/render/types.d.ts.map +1 -0
  50. package/dist/render/types.js +1 -0
  51. package/dist/runner/factory.d.ts.map +1 -1
  52. package/dist/runner/factory.js +6 -1
  53. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  54. package/dist/ui/ReadyScreen.d.ts.map +1 -1
  55. package/dist/ui/ReadyScreen.js +2 -1
  56. package/dist/ui/state.d.ts +14 -1
  57. package/dist/ui/state.d.ts.map +1 -1
  58. package/dist/ui/state.js +22 -0
  59. package/out-tsc/vitest/src/client/factory.d.ts.map +1 -1
  60. package/out-tsc/vitest/src/entry-point.d.ts +2 -0
  61. package/out-tsc/vitest/src/entry-point.d.ts.map +1 -0
  62. package/out-tsc/vitest/src/filtering/index.d.ts +1 -1
  63. package/out-tsc/vitest/src/filtering/index.d.ts.map +1 -1
  64. package/out-tsc/vitest/src/filtering/testNameFilter.d.ts +6 -0
  65. package/out-tsc/vitest/src/filtering/testNameFilter.d.ts.map +1 -1
  66. package/out-tsc/vitest/src/globals.d.ts +5 -2
  67. package/out-tsc/vitest/src/globals.d.ts.map +1 -1
  68. package/out-tsc/vitest/src/ui/state.d.ts +1 -1
  69. package/out-tsc/vitest/tsconfig.spec.tsbuildinfo +1 -1
  70. package/package.json +10 -4
  71. package/src/__tests__/collector.test.ts +55 -55
  72. package/src/__tests__/error-handling.test.ts +34 -34
  73. package/src/bundler/bundle.ts +1 -2
  74. package/src/bundler/evaluate.ts +9 -9
  75. package/src/client/factory.ts +31 -9
  76. package/src/client/setup-files.ts +81 -0
  77. package/src/collector/functions.ts +4 -2
  78. package/src/collector/types.ts +4 -1
  79. package/src/entry-point.ts +8 -0
  80. package/src/filtering/index.ts +4 -1
  81. package/src/filtering/testNameFilter.ts +53 -8
  82. package/src/globals.ts +14 -2
  83. package/src/index.ts +1 -0
  84. package/src/initialize.ts +11 -1
  85. package/src/jest-mock.ts +32 -0
  86. package/src/mocker/metro-require.d.ts +1 -0
  87. package/src/react-native.d.ts +0 -8
  88. package/src/render/ErrorBoundary.tsx +108 -0
  89. package/src/render/TestComponentOverlay.tsx +47 -0
  90. package/src/render/cleanup.ts +7 -0
  91. package/src/render/index.ts +96 -0
  92. package/src/render/setup.ts +8 -0
  93. package/src/render/types.ts +11 -0
  94. package/src/runner/factory.ts +8 -1
  95. package/src/ui/ReadyScreen.tsx +2 -0
  96. package/src/ui/state.ts +39 -0
  97. package/out-tsc/tsconfig.spec.tsbuildinfo +0 -1
  98. package/types/global.d.ts +0 -2
  99. package/types/index.d.ts +0 -1
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/render/cleanup.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO,QAAO,IAI1B,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { store } from '../ui/state.js';
2
+ export const cleanup = () => {
3
+ store.getState().setRenderedElement(null);
4
+ store.getState().setOnLayoutCallback(null);
5
+ store.getState().setOnRenderCallback(null);
6
+ };
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import type { RenderResult, RenderOptions } from './types.js';
3
+ export declare const render: (element: React.ReactElement, options?: RenderOptions) => Promise<RenderResult>;
4
+ export { cleanup } from './cleanup.js';
5
+ export type { RenderResult, RenderOptions } from './types.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAY9D,eAAO,MAAM,MAAM,GACjB,SAAS,KAAK,CAAC,YAAY,EAC3B,UAAS,aAAkB,KAC1B,OAAO,CAAC,YAAY,CA2EtB,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,66 @@
1
+ import React from 'react';
2
+ import { store } from '../ui/state.js';
3
+ const wrapElement = (element, wrapper) => {
4
+ if (!wrapper) {
5
+ return element;
6
+ }
7
+ return React.createElement(wrapper, { children: element });
8
+ };
9
+ export const render = async (element, options = {}) => {
10
+ const { timeout = 1000, wrapper } = options;
11
+ // If an element is already rendered, unmount it first
12
+ if (store.getState().renderedElement !== null) {
13
+ store.getState().setRenderedElement(null);
14
+ store.getState().setOnLayoutCallback(null);
15
+ store.getState().setOnRenderCallback(null);
16
+ }
17
+ // Create a promise that resolves when the element is laid out
18
+ const layoutPromise = new Promise((resolve, reject) => {
19
+ const timeoutId = setTimeout(() => {
20
+ store.getState().setOnLayoutCallback(null);
21
+ reject(new Error(`Render timeout: Element did not mount within ${timeout}ms`));
22
+ }, timeout);
23
+ store.getState().setOnLayoutCallback(() => {
24
+ clearTimeout(timeoutId);
25
+ resolve();
26
+ });
27
+ });
28
+ // Wrap and set the element in state (key is generated automatically)
29
+ const wrappedElement = wrapElement(element, wrapper);
30
+ store.getState().setRenderedElement(wrappedElement);
31
+ // Wait for layout
32
+ await layoutPromise;
33
+ const rerender = async (newElement) => {
34
+ if (store.getState().renderedElement === null) {
35
+ throw new Error('No element is currently rendered. Call render() first.');
36
+ }
37
+ // Create a promise that resolves when the element is re-rendered
38
+ const renderPromise = new Promise((resolve, reject) => {
39
+ const timeoutId = setTimeout(() => {
40
+ store.getState().setOnRenderCallback(null);
41
+ reject(new Error(`Rerender timeout: Element did not update within ${timeout}ms`));
42
+ }, timeout);
43
+ store.getState().setOnRenderCallback(() => {
44
+ clearTimeout(timeoutId);
45
+ resolve();
46
+ });
47
+ });
48
+ const wrappedNewElement = wrapElement(newElement, wrapper);
49
+ store.getState().updateRenderedElement(wrappedNewElement);
50
+ // Wait for render
51
+ await renderPromise;
52
+ };
53
+ const unmount = () => {
54
+ if (store.getState().renderedElement === null) {
55
+ return;
56
+ }
57
+ store.getState().setRenderedElement(null);
58
+ store.getState().setOnLayoutCallback(null);
59
+ store.getState().setOnRenderCallback(null);
60
+ };
61
+ return {
62
+ rerender,
63
+ unmount,
64
+ };
65
+ };
66
+ export { cleanup } from './cleanup.js';
@@ -0,0 +1,2 @@
1
+ export declare const setup: () => void;
2
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/render/setup.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,KAAK,YAIjB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { afterEach } from '../collector/functions.js';
2
+ import { cleanup } from './cleanup.js';
3
+ export const setup = () => {
4
+ afterEach(() => {
5
+ cleanup();
6
+ });
7
+ };
@@ -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 +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();