@nyby/detox-component-testing 1.4.2 → 1.5.1

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.
package/README.md CHANGED
@@ -31,10 +31,17 @@ npm install @nyby/detox-component-testing react-native-launch-arguments
31
31
  Create `app.component-test.js` alongside your app entry:
32
32
 
33
33
  ```js
34
- import { AppRegistry } from 'react-native';
35
- import { ComponentHarness } from '@nyby/detox-component-testing';
34
+ import React from 'react';
35
+ import {AppRegistry, View} from 'react-native';
36
+ import {ComponentHarness, configureHarness} from '@nyby/detox-component-testing';
36
37
  import './component-tests/registry';
37
38
 
39
+ configureHarness({
40
+ wrapper: ({children}) => (
41
+ <View style={{flex: 1}}>{children}</View>
42
+ ),
43
+ });
44
+
38
45
  AppRegistry.registerComponent('example', () => ComponentHarness);
39
46
  ```
40
47
 
@@ -43,16 +50,16 @@ AppRegistry.registerComponent('example', () => ComponentHarness);
43
50
  Create `component-tests/registry.ts` to register components for testing:
44
51
 
45
52
  ```ts
46
- import { registerComponent } from '@nyby/detox-component-testing';
47
- import { Stepper } from '../src/components/Stepper';
48
- import { LoginForm } from '../src/components/LoginForm';
53
+ import {registerComponent} from '@nyby/detox-component-testing';
54
+ import {Stepper} from '../src/components/Stepper';
55
+ import {LoginForm} from '../src/components/LoginForm';
49
56
 
50
57
  // Auto-infer name from Component.name
51
- registerComponent(Stepper, { initial: 0 });
58
+ registerComponent(Stepper, {initial: 0});
52
59
  registerComponent(LoginForm);
53
60
 
54
61
  // Or use an explicit name
55
- registerComponent('MyComponent', MyComponent, { someProp: 'default' });
62
+ registerComponent('MyComponent', MyComponent, {someProp: 'default'});
56
63
  ```
57
64
 
58
65
  ### 4. Switch entry point for component tests
@@ -61,7 +68,7 @@ Update your index file to load the component test entry when running component t
61
68
 
62
69
  ```js
63
70
  // index.js
64
- const { LaunchArguments } = require('react-native-launch-arguments');
71
+ const {LaunchArguments} = require('react-native-launch-arguments');
65
72
 
66
73
  if (LaunchArguments.value().detoxComponentName) {
67
74
  require('./app.component-test');
@@ -81,27 +88,27 @@ module.exports = {
81
88
  // ... existing app and device config
82
89
  configurations: {
83
90
  // ... existing configurations
84
- "ios.sim.component": {
85
- device: "simulator",
86
- app: "ios",
91
+ 'ios.sim.component': {
92
+ device: 'simulator',
93
+ app: 'ios',
87
94
  testRunner: {
88
95
  args: {
89
- config: "component-tests/jest.config.js",
90
- _: ["src/components"]
91
- }
92
- }
96
+ config: 'component-tests/jest.config.js',
97
+ _: ['src/components'],
98
+ },
99
+ },
93
100
  },
94
- "android.emu.component": {
95
- device: "emulator",
96
- app: "android",
101
+ 'android.emu.component': {
102
+ device: 'emulator',
103
+ app: 'android',
97
104
  testRunner: {
98
105
  args: {
99
- config: "component-tests/jest.config.js",
100
- _: ["src/components"]
101
- }
102
- }
103
- }
104
- }
106
+ config: 'component-tests/jest.config.js',
107
+ _: ['src/components'],
108
+ },
109
+ },
110
+ },
111
+ },
105
112
  };
106
113
  ```
107
114
 
@@ -112,19 +119,19 @@ Create `component-tests/jest.config.js`:
112
119
  ```js
113
120
  module.exports = {
114
121
  maxWorkers: 1,
115
- globalSetup: "detox/runners/jest/globalSetup",
116
- globalTeardown: "detox/runners/jest/globalTeardown",
117
- testEnvironment: "detox/runners/jest/testEnvironment",
118
- setupFilesAfterEnv: ["./setup.ts"],
119
- testRunner: "jest-circus/runner",
122
+ globalSetup: 'detox/runners/jest/globalSetup',
123
+ globalTeardown: 'detox/runners/jest/globalTeardown',
124
+ testEnvironment: '@nyby/detox-component-testing/environment',
125
+ setupFilesAfterEnv: ['./setup.ts'],
126
+ testRunner: 'jest-circus/runner',
120
127
  testTimeout: 120000,
121
- roots: ["<rootDir>/../src"],
122
- testMatch: ["**/*.component.test.ts"],
128
+ roots: ['<rootDir>/../src'],
129
+ testMatch: ['**/*.component.test.ts'],
123
130
  transform: {
124
- "\\.tsx?$": ["ts-jest", { tsconfig: "<rootDir>/../tsconfig.json" }]
131
+ '\\.tsx?$': ['ts-jest', {tsconfig: '<rootDir>/../tsconfig.json'}],
125
132
  },
126
- reporters: ["detox/runners/jest/reporter"],
127
- verbose: true
133
+ reporters: ['detox/runners/jest/reporter'],
134
+ verbose: true,
128
135
  };
129
136
  ```
130
137
 
@@ -133,8 +140,8 @@ module.exports = {
133
140
  ### Basic mounting
134
141
 
135
142
  ```ts
136
- import { by, element, expect } from 'detox';
137
- import { mount } from '@nyby/detox-component-testing/test';
143
+ import {by, element, expect} from 'detox';
144
+ import {mount} from '@nyby/detox-component-testing/test';
138
145
 
139
146
  describe('Stepper', () => {
140
147
  it('renders with default props', async () => {
@@ -143,7 +150,7 @@ describe('Stepper', () => {
143
150
  });
144
151
 
145
152
  it('renders with custom props', async () => {
146
- await mount('Stepper', { initial: 100 });
153
+ await mount('Stepper', {initial: 100});
147
154
  await expect(element(by.id('counter'))).toHaveText('100');
148
155
  });
149
156
  });
@@ -154,10 +161,10 @@ describe('Stepper', () => {
154
161
  Use `spy()` to create a recording function for callback props, and `expectSpy()` to assert on it:
155
162
 
156
163
  ```ts
157
- import { mount, spy, expectSpy } from '@nyby/detox-component-testing/test';
164
+ import {mount, spy, expectSpy} from '@nyby/detox-component-testing/test';
158
165
 
159
166
  it('fires onChange when incremented', async () => {
160
- await mount('Stepper', { initial: 0, onChange: spy('onChange') });
167
+ await mount('Stepper', {initial: 0, onChange: spy('onChange')});
161
168
  await element(by.id('increment')).tap();
162
169
 
163
170
  await expectSpy('onChange').toHaveBeenCalled();
@@ -182,6 +189,7 @@ Subsequent mounts: ~100ms (in-place swap)
182
189
  ### App-side (import from `@nyby/detox-component-testing`)
183
190
 
184
191
  #### `registerComponent(Component, defaultProps?)`
192
+
185
193
  #### `registerComponent(name, Component, defaultProps?)`
186
194
 
187
195
  Register a component for testing. When called with just a component, the name is inferred from `Component.name` or `Component.displayName`.
@@ -190,17 +198,17 @@ Register a component for testing. When called with just a component, the name is
190
198
 
191
199
  Root component for the test harness. Register as your app's root component in the component test entry point.
192
200
 
193
- #### `configureHarness({ wrapper })`
201
+ #### `configureHarness({ wrapper? })`
194
202
 
195
- Set a global wrapper component for all mounted components (e.g. Redux Provider, theme provider):
203
+ Set a global wrapper component for all mounted components:
196
204
 
197
205
  ```js
198
- import { Provider } from 'react-redux';
199
- import { configureHarness } from '@nyby/detox-component-testing';
200
- import { createStore } from './store';
206
+ import {Provider} from 'react-redux';
207
+ import {configureHarness} from '@nyby/detox-component-testing';
208
+ import {createStore} from './store';
201
209
 
202
210
  configureHarness({
203
- wrapper: ({ children, launchArgs }) => {
211
+ wrapper: ({children, launchArgs}) => {
204
212
  const store = createStore();
205
213
  if (launchArgs.reduxState) {
206
214
  store.dispatch(loadState(JSON.parse(launchArgs.reduxState)));
@@ -230,9 +238,46 @@ Returns an assertion object for a spy:
230
238
  - `.toHaveBeenCalledTimes(n)` — spy was called exactly `n` times
231
239
  - `.lastCalledWith(...args)` — the last call's arguments match
232
240
 
233
- #### `assertNoRenderError()`
241
+ #### `debug(label?, outputDir?)`
242
+
243
+ Capture a screenshot and native view hierarchy for the current screen state. Useful for debugging test failures or inspecting what's on screen at any point in a test.
244
+
245
+ ```ts
246
+ import {mount, debug} from '@nyby/detox-component-testing/test';
247
+
248
+ it('renders the event screen', async () => {
249
+ await mount('EventScreen', {eventId: 'event_1'});
250
+ await debug('after-mount'); // writes to artifacts/debug-after-mount.{png,xml}
251
+ });
252
+ ```
253
+
254
+ Each call writes up to two files to the output directory (defaults to `<cwd>/artifacts`):
255
+
256
+ - `debug-<label>.png` — screenshot
257
+ - `debug-<label>-view.xml` — native view hierarchy
258
+
259
+ If no label is provided, calls are numbered automatically (`1`, `2`, `3`, ...).
260
+
261
+ ### Debugging
262
+
263
+ #### Custom test environment
264
+
265
+ A Detox Jest environment that automatically captures debug artifacts when a test fails. Use it instead of the default Detox environment:
266
+
267
+ ```js
268
+ // jest.config.js
269
+ module.exports = {
270
+ testEnvironment: '@nyby/detox-component-testing/environment',
271
+ // ...
272
+ };
273
+ ```
274
+
275
+ On test failure, it captures:
276
+
277
+ - A screenshot
278
+ - The native view hierarchy
234
279
 
235
- Check whether the mounted component threw a render error. Called automatically by `mount()`, but can be used standalone after interactions that may trigger a re-render error.
280
+ All artifacts are written to `<cwd>/artifacts/`.
236
281
 
237
282
  ## Limitations
238
283
 
@@ -1 +1 @@
1
- {"version":3,"file":"ComponentHarness.d.ts","sourceRoot":"","sources":["../src/ComponentHarness.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8E,MAAM,OAAO,CAAC;AAuDnG,wBAAgB,gBAAgB,sBAsC/B"}
1
+ {"version":3,"file":"ComponentHarness.d.ts","sourceRoot":"","sources":["../src/ComponentHarness.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8E,MAAM,OAAO,CAAC;AAuDnG,wBAAgB,gBAAgB,sBAkD/B"}
@@ -73,9 +73,9 @@ function parseLaunchArgs(args) {
73
73
  function ComponentHarness() {
74
74
  const launchArgs = react_native_launch_arguments_1.LaunchArguments.value();
75
75
  const [mountPayload, setMountPayload] = (0, react_1.useState)(null);
76
- const handleControl = (0, react_1.useCallback)((text) => {
76
+ const handleControl = (0, react_1.useCallback)((e) => {
77
77
  try {
78
- setMountPayload(JSON.parse(text));
78
+ setMountPayload(JSON.parse(e.nativeEvent.text));
79
79
  }
80
80
  catch (_e) { }
81
81
  }, []);
@@ -93,7 +93,15 @@ function ComponentHarness() {
93
93
  };
94
94
  }
95
95
  return (react_1.default.createElement(react_native_1.View, { style: { flex: 1 } },
96
- react_1.default.createElement(react_native_1.TextInput, { testID: "detox-harness-control", onChangeText: handleControl, style: { height: 1 } }),
96
+ react_1.default.createElement(react_native_1.TextInput, { testID: "detox-harness-control", onEndEditing: handleControl, style: {
97
+ position: 'absolute',
98
+ bottom: 0,
99
+ left: 0,
100
+ right: 0,
101
+ height: 44,
102
+ opacity: 0.01,
103
+ zIndex: 9999,
104
+ } }),
97
105
  activeMount && (react_1.default.createElement(react_1.default.Fragment, null,
98
106
  react_1.default.createElement(react_native_1.Text, { testID: "detox-mount-id", style: { height: 1 } }, activeMount.id),
99
107
  react_1.default.createElement(RenderErrorBoundary, null,
@@ -1 +1 @@
1
- {"version":3,"file":"ComponentHarness.js","sourceRoot":"","sources":["../src/ComponentHarness.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ComponentHarness.js","sourceRoot":"","sources":["../src/ComponentHarness.tsx"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@ export interface WrapperProps {
4
4
  launchArgs: Record<string, any>;
5
5
  }
6
6
  export interface HarnessConfig {
7
- wrapper: ComponentType<WrapperProps>;
7
+ wrapper?: ComponentType<WrapperProps>;
8
8
  }
9
9
  export declare function configureHarness(config: HarnessConfig): void;
10
10
  export declare function getWrapper(): ComponentType<WrapperProps>;
@@ -1 +1 @@
1
- {"version":3,"file":"configureHarness.d.ts","sourceRoot":"","sources":["../src/configureHarness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAE,SAAS,EAAC,MAAM,OAAO,CAAC;AAE/C,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;CACtC;AAMD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAE5D;AAED,wBAAgB,UAAU,IAAI,aAAa,CAAC,YAAY,CAAC,CAExD"}
1
+ {"version":3,"file":"configureHarness.d.ts","sourceRoot":"","sources":["../src/configureHarness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAE,SAAS,EAAC,MAAM,OAAO,CAAC;AAE/C,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,SAAS,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;CACvC;AAMD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAI5D;AAED,wBAAgB,UAAU,IAAI,aAAa,CAAC,YAAY,CAAC,CAExD"}
@@ -5,7 +5,9 @@ exports.getWrapper = getWrapper;
5
5
  const DefaultWrapper = ({ children }) => children;
6
6
  let globalWrapper = null;
7
7
  function configureHarness(config) {
8
- globalWrapper = config.wrapper;
8
+ if (config.wrapper) {
9
+ globalWrapper = config.wrapper;
10
+ }
9
11
  }
10
12
  function getWrapper() {
11
13
  return globalWrapper || DefaultWrapper;
@@ -1 +1 @@
1
- {"version":3,"file":"configureHarness.js","sourceRoot":"","sources":["../src/configureHarness.ts"],"names":[],"mappings":";;AAeA,4CAEC;AAED,gCAEC;AAVD,MAAM,cAAc,GAAG,CAAC,EAAC,QAAQ,EAAe,EAAE,EAAE,CAAC,QAAQ,CAAC;AAE9D,IAAI,aAAa,GAAuC,IAAI,CAAC;AAE7D,SAAgB,gBAAgB,CAAC,MAAqB;IACpD,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC;AACjC,CAAC;AAED,SAAgB,UAAU;IACxB,OAAO,aAAa,IAAI,cAAc,CAAC;AACzC,CAAC"}
1
+ {"version":3,"file":"configureHarness.js","sourceRoot":"","sources":["../src/configureHarness.ts"],"names":[],"mappings":";;AAeA,4CAIC;AAED,gCAEC;AAZD,MAAM,cAAc,GAAG,CAAC,EAAC,QAAQ,EAAe,EAAE,EAAE,CAAC,QAAQ,CAAC;AAE9D,IAAI,aAAa,GAAuC,IAAI,CAAC;AAE7D,SAAgB,gBAAgB,CAAC,MAAqB;IACpD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC;IACjC,CAAC;AACH,CAAC;AAED,SAAgB,UAAU;IACxB,OAAO,aAAa,IAAI,cAAc,CAAC;AACzC,CAAC"}
package/dist/debug.d.ts CHANGED
@@ -1,2 +1,10 @@
1
+ /**
2
+ * Capture a screenshot and native view hierarchy to the given directory.
3
+ * Used by both the `debug()` helper and the custom test environment.
4
+ */
5
+ export declare function captureArtifacts(name: string, outputDir: string, deviceRef: {
6
+ takeScreenshot: (n: string) => Promise<string>;
7
+ generateViewHierarchyXml: () => Promise<string>;
8
+ }): Promise<void>;
1
9
  export declare function debug(label?: string, outputDir?: string): Promise<void>;
2
10
  //# sourceMappingURL=debug.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"AAcA,wBAAsB,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,iBAiC7D"}
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE;IAAC,cAAc,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAAC,wBAAwB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CAAC,iBAiB7G;AAaD,wBAAsB,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,iBAI7D"}
package/dist/debug.js CHANGED
@@ -1,49 +1,43 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.captureArtifacts = captureArtifacts;
3
4
  exports.debug = debug;
4
5
  const fs_1 = require("fs");
5
6
  const path_1 = require("path");
6
7
  /**
7
- * Capture a screenshot, React component tree, and native view hierarchy.
8
- * Drop this anywhere in a test to inspect the current screen state.
9
- *
10
- * Usage:
11
- * import { debug } from '@nyby/detox-component-testing/test';
12
- * await debug(); // artifacts/debug-1.png, debug-1-tree.json, debug-1-view.xml
13
- * await debug('after-tap'); // artifacts/debug-after-tap.png, etc.
8
+ * Capture a screenshot and native view hierarchy to the given directory.
9
+ * Used by both the `debug()` helper and the custom test environment.
14
10
  */
15
- let counter = 0;
16
- async function debug(label, outputDir) {
17
- const name = label || String(++counter);
18
- const dir = outputDir || (0, path_1.join)(process.cwd(), 'artifacts');
19
- (0, fs_1.mkdirSync)(dir, { recursive: true });
20
- const screenshotPath = (0, path_1.join)(dir, `debug-${name}.png`);
21
- const treePath = (0, path_1.join)(dir, `debug-${name}-tree.json`);
22
- const viewPath = (0, path_1.join)(dir, `debug-${name}-view.xml`);
11
+ async function captureArtifacts(name, outputDir, deviceRef) {
12
+ (0, fs_1.mkdirSync)(outputDir, { recursive: true });
23
13
  // Screenshot via Detox, then move to our artifacts dir
24
14
  try {
25
- const tempPath = await device.takeScreenshot(`debug-${name}`);
15
+ const tempPath = await deviceRef.takeScreenshot(`debug-${name}`);
26
16
  if (tempPath) {
27
- (0, fs_1.renameSync)(tempPath, screenshotPath);
17
+ (0, fs_1.renameSync)(tempPath, (0, path_1.join)(outputDir, `debug-${name}.png`));
28
18
  }
29
19
  }
30
20
  catch (_a) { }
31
- // React component tree via DebugTree harness
32
- try {
33
- await element(by.id('debug-tree-control')).replaceText('dump');
34
- await waitFor(element(by.id('debug-tree-output')))
35
- .toExist()
36
- .withTimeout(3000);
37
- const attrs = await element(by.id('debug-tree-output')).getAttributes();
38
- const tree = attrs.text || attrs.label || '[]';
39
- (0, fs_1.writeFileSync)(treePath, tree, 'utf8');
40
- }
41
- catch (_b) { }
42
21
  // Native view hierarchy
43
22
  try {
44
- const xml = await device.generateViewHierarchyXml();
45
- (0, fs_1.writeFileSync)(viewPath, xml, 'utf8');
23
+ const xml = await deviceRef.generateViewHierarchyXml();
24
+ (0, fs_1.writeFileSync)((0, path_1.join)(outputDir, `debug-${name}-view.xml`), xml, 'utf8');
46
25
  }
47
- catch (_c) { }
26
+ catch (_b) { }
27
+ }
28
+ /**
29
+ * Capture a screenshot and native view hierarchy.
30
+ * Drop this anywhere in a test to inspect the current screen state.
31
+ *
32
+ * Usage:
33
+ * import { debug } from '@nyby/detox-component-testing/test';
34
+ * await debug(); // artifacts/debug-1.png, debug-1-view.xml
35
+ * await debug('after-tap'); // artifacts/debug-after-tap.png, etc.
36
+ */
37
+ let counter = 0;
38
+ async function debug(label, outputDir) {
39
+ const name = label || String(++counter);
40
+ const dir = outputDir || (0, path_1.join)(process.cwd(), 'artifacts');
41
+ await captureArtifacts(name, dir, device);
48
42
  }
49
43
  //# sourceMappingURL=debug.js.map
package/dist/debug.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"debug.js","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":";;AAcA,sBAiCC;AA/CD,2BAAwD;AACxD,+BAA0B;AAE1B;;;;;;;;GAQG;AACH,IAAI,OAAO,GAAG,CAAC,CAAC;AAET,KAAK,UAAU,KAAK,CAAC,KAAc,EAAE,SAAkB;IAC5D,MAAM,IAAI,GAAG,KAAK,IAAI,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,SAAS,IAAI,IAAA,WAAI,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;IAC1D,IAAA,cAAS,EAAC,GAAG,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IAElC,MAAM,cAAc,GAAG,IAAA,WAAI,EAAC,GAAG,EAAE,SAAS,IAAI,MAAM,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,GAAG,EAAE,SAAS,IAAI,YAAY,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,GAAG,EAAE,SAAS,IAAI,WAAW,CAAC,CAAC;IAErD,uDAAuD;IACvD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QAC9D,IAAI,QAAQ,EAAE,CAAC;YACb,IAAA,eAAU,EAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAAC,WAAM,CAAC,CAAA,CAAC;IAEV,6CAA6C;IAC7C,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC/D,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC;aAC/C,OAAO,EAAE;aACT,WAAW,CAAC,IAAI,CAAC,CAAC;QACrB,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACxE,MAAM,IAAI,GAAI,KAAa,CAAC,IAAI,IAAK,KAAa,CAAC,KAAK,IAAI,IAAI,CAAC;QACjE,IAAA,kBAAa,EAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAAC,WAAM,CAAC,CAAA,CAAC;IAEV,wBAAwB;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,wBAAwB,EAAE,CAAC;QACpD,IAAA,kBAAa,EAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAAC,WAAM,CAAC,CAAA,CAAC;AACZ,CAAC"}
1
+ {"version":3,"file":"debug.js","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":";;AAOA,4CAoBC;AAaD,sBAIC;AA5CD,2BAAwD;AACxD,+BAA0B;AAE1B;;;GAGG;AACI,KAAK,UAAU,gBAAgB,CACpC,IAAY,EACZ,SAAiB,EACjB,SAA4G;IAE5G,IAAA,cAAS,EAAC,SAAS,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IAExC,uDAAuD;IACvD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,cAAc,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QACjE,IAAI,QAAQ,EAAE,CAAC;YACb,IAAA,eAAU,EAAC,QAAQ,EAAE,IAAA,WAAI,EAAC,SAAS,EAAE,SAAS,IAAI,MAAM,CAAC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAAC,WAAM,CAAC,CAAA,CAAC;IAEV,wBAAwB;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,wBAAwB,EAAE,CAAC;QACvD,IAAA,kBAAa,EAAC,IAAA,WAAI,EAAC,SAAS,EAAE,SAAS,IAAI,WAAW,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IACxE,CAAC;IAAC,WAAM,CAAC,CAAA,CAAC;AACZ,CAAC;AAED;;;;;;;;GAQG;AACH,IAAI,OAAO,GAAG,CAAC,CAAC;AAET,KAAK,UAAU,KAAK,CAAC,KAAc,EAAE,SAAkB;IAC5D,MAAM,IAAI,GAAG,KAAK,IAAI,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,SAAS,IAAI,IAAA,WAAI,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;IAC1D,MAAM,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;AAC5C,CAAC"}
@@ -1,45 +1,17 @@
1
1
  const DetoxCircusEnvironment = require('detox/runners/jest/testEnvironment');
2
- const {mkdirSync, writeFileSync} = require('fs');
3
2
  const {join} = require('path');
3
+ const {captureArtifacts} = require('./debug');
4
4
 
5
5
  class CustomDetoxEnvironment extends DetoxCircusEnvironment {
6
6
  async handleTestEvent(event, state) {
7
7
  await super.handleTestEvent(event, state);
8
8
 
9
9
  if (event.name === 'test_done' && event.test.errors.length > 0) {
10
- await this._dumpDebugInfo(event.test);
10
+ const safeName = event.test.name.replace(/[^a-zA-Z0-9_-]/g, '_');
11
+ const outputDir = join(process.cwd(), 'artifacts');
12
+ await captureArtifacts(safeName, outputDir, this.global.device);
11
13
  }
12
14
  }
13
-
14
- async _dumpDebugInfo(test) {
15
- const outputDir = join(process.cwd(), 'artifacts');
16
- const safeName = test.name.replace(/[^a-zA-Z0-9_-]/g, '_');
17
-
18
- mkdirSync(outputDir, {recursive: true});
19
-
20
- // Screenshot (saved by Detox into its own artifacts folder)
21
- try {
22
- await this.global.device.takeScreenshot(`debug-${safeName}`);
23
- } catch (_e) {}
24
-
25
- // Component tree via DebugTree
26
- try {
27
- const {element, by, waitFor} = this.global;
28
-
29
- await element(by.id('debug-tree-control')).replaceText('dump');
30
- await waitFor(element(by.id('debug-tree-output'))).toExist().withTimeout(3000);
31
-
32
- const attrs = await element(by.id('debug-tree-output')).getAttributes();
33
- const tree = attrs.text || attrs.label || '[]';
34
- writeFileSync(join(outputDir, `componenttree-${safeName}.json`), tree, 'utf8');
35
- } catch (_e) {}
36
-
37
- // Native view hierarchy
38
- try {
39
- const xml = await this.global.device.generateViewHierarchyXml();
40
- writeFileSync(join(outputDir, `viewhierarchy-${safeName}.xml`), xml, 'utf8');
41
- } catch (_e) {}
42
- }
43
15
  }
44
16
 
45
17
  module.exports = CustomDetoxEnvironment;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export { registerComponent } from './ComponentRegistry';
2
2
  export { ComponentHarness } from './ComponentHarness';
3
- export { configureHarness, WrapperProps } from './configureHarness';
4
- export { DebugTree } from './DebugTree';
3
+ export { configureHarness, WrapperProps, HarnessConfig } from './configureHarness';
5
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAC,gBAAgB,EAAE,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAC,gBAAgB,EAAE,YAAY,EAAE,aAAa,EAAC,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -1,12 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DebugTree = exports.configureHarness = exports.ComponentHarness = exports.registerComponent = void 0;
3
+ exports.configureHarness = exports.ComponentHarness = exports.registerComponent = void 0;
4
4
  var ComponentRegistry_1 = require("./ComponentRegistry");
5
5
  Object.defineProperty(exports, "registerComponent", { enumerable: true, get: function () { return ComponentRegistry_1.registerComponent; } });
6
6
  var ComponentHarness_1 = require("./ComponentHarness");
7
7
  Object.defineProperty(exports, "ComponentHarness", { enumerable: true, get: function () { return ComponentHarness_1.ComponentHarness; } });
8
8
  var configureHarness_1 = require("./configureHarness");
9
9
  Object.defineProperty(exports, "configureHarness", { enumerable: true, get: function () { return configureHarness_1.configureHarness; } });
10
- var DebugTree_1 = require("./DebugTree");
11
- Object.defineProperty(exports, "DebugTree", { enumerable: true, get: function () { return DebugTree_1.DebugTree; } });
12
10
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yDAAsD;AAA9C,sHAAA,iBAAiB,OAAA;AACzB,uDAAoD;AAA5C,oHAAA,gBAAgB,OAAA;AACxB,uDAAkE;AAA1D,oHAAA,gBAAgB,OAAA;AACxB,yCAAsC;AAA9B,sGAAA,SAAS,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yDAAsD;AAA9C,sHAAA,iBAAiB,OAAA;AACzB,uDAAoD;AAA5C,oHAAA,gBAAgB,OAAA;AACxB,uDAAiF;AAAzE,oHAAA,gBAAgB,OAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,qBAAqB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,cAAc,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C;AAOD,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAE3C;AAED,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;AAExE,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAYzD;AAED,wBAAsB,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAmDpF;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAetD"}
1
+ {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,qBAAqB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,cAAc,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C;AAOD,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAE3C;AAED,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;AAExE,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAYzD;AAED,wBAAsB,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCpF;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAetD"}
package/dist/mount.js CHANGED
@@ -41,38 +41,24 @@ async function mount(componentName, props) {
41
41
  }
42
42
  });
43
43
  }
44
- if (!appLaunched) {
45
- const launchArgs = { detoxComponentName: componentName };
46
- Object.entries(payload.props).forEach(([key, value]) => {
47
- launchArgs[`detoxProp_${key}`] = value;
48
- });
49
- payload.spies.forEach((name) => {
50
- launchArgs[`detoxSpy_${name}`] = true;
51
- });
52
- await device.launchApp({ newInstance: true, launchArgs });
53
- appLaunched = true;
54
- // Harness sets id '0' for the initial launch-args mount
55
- try {
56
- await waitFor(element(by.id('detox-mount-id')))
57
- .toHaveText('0')
58
- .withTimeout(5000);
59
- }
60
- catch (e) {
61
- await assertNoRenderError(); // Throws with the actual error if one exists
62
- throw e; // Re-throw original timeout if no render error found
63
- }
64
- await assertNoRenderError();
65
- return;
66
- }
67
- await element(by.id('detox-harness-control')).replaceText(JSON.stringify(payload));
44
+ const launchArgs = { detoxComponentName: componentName };
45
+ Object.entries(payload.props).forEach(([key, value]) => {
46
+ launchArgs[`detoxProp_${key}`] = value;
47
+ });
48
+ payload.spies.forEach((name) => {
49
+ launchArgs[`detoxSpy_${name}`] = true;
50
+ });
51
+ await device.launchApp({ newInstance: true, launchArgs });
52
+ appLaunched = true;
53
+ // Harness sets id '0' for the initial launch-args mount
68
54
  try {
69
55
  await waitFor(element(by.id('detox-mount-id')))
70
- .toHaveText(payload.id)
56
+ .toHaveText('0')
71
57
  .withTimeout(5000);
72
58
  }
73
59
  catch (e) {
74
- await assertNoRenderError();
75
- throw e;
60
+ await assertNoRenderError(); // Throws with the actual error if one exists
61
+ throw e; // Re-throw original timeout if no render error found
76
62
  }
77
63
  await assertNoRenderError();
78
64
  }
package/dist/mount.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nyby/detox-component-testing",
3
- "version": "1.4.2",
3
+ "version": "1.5.1",
4
4
  "description": "Component testing support for Detox and React Native",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -57,9 +57,9 @@ export function ComponentHarness() {
57
57
  const launchArgs = LaunchArguments.value() as Record<string, any>;
58
58
  const [mountPayload, setMountPayload] = useState<MountPayload | null>(null);
59
59
 
60
- const handleControl = useCallback((text: string) => {
60
+ const handleControl = useCallback((e: {nativeEvent: {text: string}}) => {
61
61
  try {
62
- setMountPayload(JSON.parse(text));
62
+ setMountPayload(JSON.parse(e.nativeEvent.text));
63
63
  } catch (_e) {}
64
64
  }, []);
65
65
 
@@ -78,7 +78,19 @@ export function ComponentHarness() {
78
78
 
79
79
  return (
80
80
  <View style={{flex: 1}}>
81
- <TextInput testID="detox-harness-control" onChangeText={handleControl} style={{height: 1}} />
81
+ <TextInput
82
+ testID="detox-harness-control"
83
+ onEndEditing={handleControl}
84
+ style={{
85
+ position: 'absolute',
86
+ bottom: 0,
87
+ left: 0,
88
+ right: 0,
89
+ height: 44,
90
+ opacity: 0.01,
91
+ zIndex: 9999,
92
+ }}
93
+ />
82
94
  {activeMount && (
83
95
  <>
84
96
  <Text testID="detox-mount-id" style={{height: 1}}>