@nyby/detox-component-testing 1.5.0 → 1.6.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 (44) hide show
  1. package/README.md +5 -50
  2. package/dist/ComponentHarness.d.ts +1 -1
  3. package/dist/ComponentHarness.d.ts.map +1 -1
  4. package/dist/ComponentHarness.js +10 -12
  5. package/dist/ComponentHarness.js.map +1 -1
  6. package/dist/ComponentRegistry.d.ts +1 -1
  7. package/dist/ComponentRegistry.d.ts.map +1 -1
  8. package/dist/ComponentRegistry.js +2 -2
  9. package/dist/ComponentRegistry.js.map +1 -1
  10. package/dist/configureHarness.d.ts +1 -4
  11. package/dist/configureHarness.d.ts.map +1 -1
  12. package/dist/configureHarness.js +0 -12
  13. package/dist/configureHarness.js.map +1 -1
  14. package/dist/debug.d.ts +8 -0
  15. package/dist/debug.d.ts.map +1 -1
  16. package/dist/debug.js +26 -32
  17. package/dist/debug.js.map +1 -1
  18. package/dist/environment.js +7 -37
  19. package/dist/index.d.ts +3 -4
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +1 -3
  22. package/dist/index.js.map +1 -1
  23. package/dist/mount.d.ts +0 -1
  24. package/dist/mount.d.ts.map +1 -1
  25. package/dist/mount.js +9 -10
  26. package/dist/mount.js.map +1 -1
  27. package/dist/test.d.ts +2 -2
  28. package/dist/test.d.ts.map +1 -1
  29. package/dist/test.js.map +1 -1
  30. package/package.json +3 -3
  31. package/src/ComponentHarness.tsx +46 -37
  32. package/src/ComponentRegistry.ts +7 -4
  33. package/src/configureHarness.ts +2 -14
  34. package/src/debug.ts +34 -34
  35. package/src/detox-env.d.ts +1 -1
  36. package/src/environment.js +7 -37
  37. package/src/index.ts +7 -4
  38. package/src/mount.ts +26 -15
  39. package/src/test.ts +2 -2
  40. package/dist/DebugTree.d.ts +0 -20
  41. package/dist/DebugTree.d.ts.map +0 -1
  42. package/dist/DebugTree.js +0 -239
  43. package/dist/DebugTree.js.map +0 -1
  44. package/src/DebugTree.tsx +0 -280
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nyby/detox-component-testing",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Component testing support for Detox and React Native",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -42,10 +42,10 @@
42
42
  "react-native-launch-arguments": "*"
43
43
  },
44
44
  "devDependencies": {
45
+ "@types/node": "^25.5.0",
45
46
  "@types/react": "^19.2.14",
46
47
  "@types/react-native": "^0.72.8",
47
48
  "prettier": "^3.8.1",
48
49
  "typescript": "^5.9.3"
49
- },
50
- "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
50
+ }
51
51
  }
@@ -1,26 +1,36 @@
1
- import React, {Component as ReactComponent, useState, useRef, useCallback, ReactNode} from 'react';
2
- import {View, Text, TextInput, ScrollView} from 'react-native';
3
- import {LaunchArguments} from 'react-native-launch-arguments';
4
- import {getComponent} from './ComponentRegistry';
5
- import {getWrapper, getDebugTreeConfig} from './configureHarness';
6
- import {DebugTree} from './DebugTree';
1
+ import React, {
2
+ Component as ReactComponent,
3
+ useState,
4
+ useRef,
5
+ useCallback,
6
+ ReactNode,
7
+ } from "react";
8
+ import { View, Text, TextInput, ScrollView } from "react-native";
9
+ import { LaunchArguments } from "react-native-launch-arguments";
10
+ import { getComponent } from "./ComponentRegistry";
11
+ import { getWrapper } from "./configureHarness";
7
12
 
8
13
  interface ErrorBoundaryState {
9
14
  error: Error | null;
10
15
  }
11
16
 
12
- class RenderErrorBoundary extends ReactComponent<{children: ReactNode}, ErrorBoundaryState> {
13
- state: ErrorBoundaryState = {error: null};
17
+ class RenderErrorBoundary extends ReactComponent<
18
+ { children: ReactNode },
19
+ ErrorBoundaryState
20
+ > {
21
+ state: ErrorBoundaryState = { error: null };
14
22
 
15
23
  static getDerivedStateFromError(error: Error) {
16
- return {error};
24
+ return { error };
17
25
  }
18
26
 
19
27
  render() {
20
28
  if (this.state.error) {
21
29
  return (
22
30
  <ScrollView testID="detox-render-error">
23
- <Text testID="detox-render-error-message">{this.state.error.message}</Text>
31
+ <Text testID="detox-render-error-message">
32
+ {this.state.error.message}
33
+ </Text>
24
34
  </ScrollView>
25
35
  );
26
36
  }
@@ -28,8 +38,8 @@ class RenderErrorBoundary extends ReactComponent<{children: ReactNode}, ErrorBou
28
38
  }
29
39
  }
30
40
 
31
- const PROP_PREFIX = 'detoxProp_';
32
- const SPY_PREFIX = 'detoxSpy_';
41
+ const PROP_PREFIX = "detoxProp_";
42
+ const SPY_PREFIX = "detoxSpy_";
33
43
 
34
44
  interface MountPayload {
35
45
  id: string;
@@ -51,14 +61,14 @@ function parseLaunchArgs(args: Record<string, any>): {
51
61
  spies.push(key.slice(SPY_PREFIX.length));
52
62
  }
53
63
  });
54
- return {props, spies};
64
+ return { props, spies };
55
65
  }
56
66
 
57
67
  export function ComponentHarness() {
58
68
  const launchArgs = LaunchArguments.value() as Record<string, any>;
59
69
  const [mountPayload, setMountPayload] = useState<MountPayload | null>(null);
60
70
 
61
- const handleControl = useCallback((e: {nativeEvent: {text: string}}) => {
71
+ const handleControl = useCallback((e: { nativeEvent: { text: string } }) => {
62
72
  try {
63
73
  setMountPayload(JSON.parse(e.nativeEvent.text));
64
74
  } catch (_e) {}
@@ -68,9 +78,9 @@ export function ComponentHarness() {
68
78
  if (mountPayload) {
69
79
  activeMount = mountPayload;
70
80
  } else if (launchArgs.detoxComponentName) {
71
- const {props, spies} = parseLaunchArgs(launchArgs);
81
+ const { props, spies } = parseLaunchArgs(launchArgs);
72
82
  activeMount = {
73
- id: '0',
83
+ id: "0",
74
84
  name: launchArgs.detoxComponentName as string,
75
85
  props,
76
86
  spies,
@@ -78,12 +88,12 @@ export function ComponentHarness() {
78
88
  }
79
89
 
80
90
  return (
81
- <View style={{flex: 1}}>
91
+ <View style={{ flex: 1 }}>
82
92
  <TextInput
83
93
  testID="detox-harness-control"
84
94
  onEndEditing={handleControl}
85
95
  style={{
86
- position: 'absolute',
96
+ position: "absolute",
87
97
  bottom: 0,
88
98
  left: 0,
89
99
  right: 0,
@@ -94,7 +104,7 @@ export function ComponentHarness() {
94
104
  />
95
105
  {activeMount && (
96
106
  <>
97
- <Text testID="detox-mount-id" style={{height: 1}}>
107
+ <Text testID="detox-mount-id" style={{ height: 1 }}>
98
108
  {activeMount.id}
99
109
  </Text>
100
110
  <RenderErrorBoundary>
@@ -111,13 +121,13 @@ interface SpyData {
111
121
  lastArgs: any[];
112
122
  }
113
123
 
114
- function ComponentRenderer({mount}: {mount: MountPayload}) {
115
- const {Component, defaultProps} = getComponent(mount.name);
124
+ function ComponentRenderer({ mount }: { mount: MountPayload }) {
125
+ const { Component, defaultProps } = getComponent(mount.name);
116
126
  const spyNames = mount.spies || [];
117
127
 
118
128
  const initialData: Record<string, SpyData> = {};
119
129
  spyNames.forEach((name) => {
120
- initialData[name] = {count: 0, lastArgs: []};
130
+ initialData[name] = { count: 0, lastArgs: [] };
121
131
  });
122
132
 
123
133
  const [spyData, setSpyData] = useState(initialData);
@@ -139,25 +149,24 @@ function ComponentRenderer({mount}: {mount: MountPayload}) {
139
149
  spyProps[name] = spyFnsRef.current[name];
140
150
  });
141
151
 
142
- const props = {...defaultProps, ...(mount.props || {}), ...spyProps};
152
+ const props = { ...defaultProps, ...(mount.props || {}), ...spyProps };
143
153
  const Wrapper = getWrapper();
144
- const debugTreeConfig = getDebugTreeConfig();
145
-
146
- const content = (
147
- <View testID="component-harness-root" style={{flex: 1}}>
148
- <Component {...props} />
149
- {spyNames.map((name) => (
150
- <View key={name}>
151
- <Text testID={`spy-${name}-count`}>{String(spyData[name].count)}</Text>
152
- <Text testID={`spy-${name}-lastArgs`}>{JSON.stringify(spyData[name].lastArgs)}</Text>
153
- </View>
154
- ))}
155
- </View>
156
- );
157
154
 
158
155
  return (
159
156
  <Wrapper launchArgs={mount.props || {}}>
160
- {debugTreeConfig ? <DebugTree {...debugTreeConfig}>{content}</DebugTree> : content}
157
+ <View testID="component-harness-root" style={{ flex: 1 }}>
158
+ <Component {...props} />
159
+ {spyNames.map((name) => (
160
+ <View key={name}>
161
+ <Text testID={`spy-${name}-count`}>
162
+ {String(spyData[name].count)}
163
+ </Text>
164
+ <Text testID={`spy-${name}-lastArgs`}>
165
+ {JSON.stringify(spyData[name].lastArgs)}
166
+ </Text>
167
+ </View>
168
+ ))}
169
+ </View>
161
170
  </Wrapper>
162
171
  );
163
172
  }
@@ -1,4 +1,4 @@
1
- import {ComponentType} from 'react';
1
+ import { ComponentType } from "react";
2
2
 
3
3
  export interface ComponentEntry<P = any> {
4
4
  Component: ComponentType<P>;
@@ -12,13 +12,16 @@ export function registerComponent<P>(
12
12
  Component: ComponentType<P>,
13
13
  defaultProps?: Partial<P>,
14
14
  ): void;
15
- export function registerComponent<P>(Component: ComponentType<P>, defaultProps?: Partial<P>): void;
15
+ export function registerComponent<P>(
16
+ Component: ComponentType<P>,
17
+ defaultProps?: Partial<P>,
18
+ ): void;
16
19
  export function registerComponent<P>(
17
20
  nameOrComponent: string | ComponentType<P>,
18
21
  componentOrProps?: ComponentType<P> | Partial<P>,
19
22
  defaultProps?: Partial<P>,
20
23
  ): void {
21
- if (typeof nameOrComponent === 'string') {
24
+ if (typeof nameOrComponent === "string") {
22
25
  registry.set(nameOrComponent, {
23
26
  Component: componentOrProps as ComponentType<P>,
24
27
  defaultProps: (defaultProps || {}) as Partial<P>,
@@ -28,7 +31,7 @@ export function registerComponent<P>(
28
31
  const name = Component.displayName || Component.name;
29
32
  if (!name) {
30
33
  throw new Error(
31
- '[detox-component-testing] Component must have a name or displayName to register without an explicit name.',
34
+ "[detox-component-testing] Component must have a name or displayName to register without an explicit name.",
32
35
  );
33
36
  }
34
37
  registry.set(name, {
@@ -1,5 +1,4 @@
1
- import {ComponentType, ReactNode} from 'react';
2
- import {DebugTreeProps} from './DebugTree';
1
+ import { ComponentType, ReactNode } from "react";
3
2
 
4
3
  export interface WrapperProps {
5
4
  children: ReactNode;
@@ -8,29 +7,18 @@ export interface WrapperProps {
8
7
 
9
8
  export interface HarnessConfig {
10
9
  wrapper?: ComponentType<WrapperProps>;
11
- debugTree?: boolean | Omit<DebugTreeProps, 'children'>;
12
10
  }
13
11
 
14
- const DefaultWrapper = ({children}: WrapperProps) => children;
12
+ const DefaultWrapper = ({ children }: WrapperProps) => children;
15
13
 
16
14
  let globalWrapper: ComponentType<WrapperProps> | null = null;
17
- let globalDebugTree: boolean | Omit<DebugTreeProps, 'children'> | null = null;
18
15
 
19
16
  export function configureHarness(config: HarnessConfig): void {
20
17
  if (config.wrapper) {
21
18
  globalWrapper = config.wrapper;
22
19
  }
23
- if (config.debugTree !== undefined) {
24
- globalDebugTree = config.debugTree;
25
- }
26
20
  }
27
21
 
28
22
  export function getWrapper(): ComponentType<WrapperProps> {
29
23
  return globalWrapper || DefaultWrapper;
30
24
  }
31
-
32
- export function getDebugTreeConfig(): Omit<DebugTreeProps, 'children'> | null {
33
- if (!globalDebugTree) return null;
34
- if (globalDebugTree === true) return {};
35
- return globalDebugTree;
36
- }
package/src/debug.ts CHANGED
@@ -1,48 +1,48 @@
1
- import {mkdirSync, renameSync, writeFileSync} from 'fs';
2
- import {join} from 'path';
1
+ import { mkdirSync, renameSync, writeFileSync } from "fs";
2
+ import { join } from "path";
3
3
 
4
4
  /**
5
- * Capture a screenshot, React component tree, and native view hierarchy.
6
- * Drop this anywhere in a test to inspect the current screen state.
7
- *
8
- * Usage:
9
- * import { debug } from '@nyby/detox-component-testing/test';
10
- * await debug(); // artifacts/debug-1.png, debug-1-tree.json, debug-1-view.xml
11
- * await debug('after-tap'); // artifacts/debug-after-tap.png, etc.
5
+ * Capture a screenshot and native view hierarchy to the given directory.
6
+ * Used by both the `debug()` helper and the custom test environment.
12
7
  */
13
- let counter = 0;
14
-
15
- export async function debug(label?: string, outputDir?: string) {
16
- const name = label || String(++counter);
17
- const dir = outputDir || join(process.cwd(), 'artifacts');
18
- mkdirSync(dir, {recursive: true});
19
-
20
- const screenshotPath = join(dir, `debug-${name}.png`);
21
- const treePath = join(dir, `debug-${name}-tree.json`);
22
- const viewPath = join(dir, `debug-${name}-view.xml`);
8
+ export async function captureArtifacts(
9
+ name: string,
10
+ outputDir: string,
11
+ deviceRef: {
12
+ takeScreenshot: (n: string) => Promise<string>;
13
+ generateViewHierarchyXml: () => Promise<string>;
14
+ },
15
+ ) {
16
+ mkdirSync(outputDir, { recursive: true });
23
17
 
24
18
  // Screenshot via Detox, then move to our artifacts dir
25
19
  try {
26
- const tempPath = await device.takeScreenshot(`debug-${name}`);
20
+ const tempPath = await deviceRef.takeScreenshot(`debug-${name}`);
27
21
  if (tempPath) {
28
- renameSync(tempPath, screenshotPath);
22
+ renameSync(tempPath, join(outputDir, `debug-${name}.png`));
29
23
  }
30
24
  } catch {}
31
25
 
32
- // React component tree via DebugTree harness
33
- try {
34
- await element(by.id('debug-tree-control')).replaceText('dump');
35
- await waitFor(element(by.id('debug-tree-output')))
36
- .toExist()
37
- .withTimeout(3000);
38
- const attrs = await element(by.id('debug-tree-output')).getAttributes();
39
- const tree = (attrs as any).text || (attrs as any).label || '[]';
40
- writeFileSync(treePath, tree, 'utf8');
41
- } catch {}
42
-
43
26
  // Native view hierarchy
44
27
  try {
45
- const xml = await device.generateViewHierarchyXml();
46
- writeFileSync(viewPath, xml, 'utf8');
28
+ const xml = await deviceRef.generateViewHierarchyXml();
29
+ writeFileSync(join(outputDir, `debug-${name}-view.xml`), xml, "utf8");
47
30
  } catch {}
48
31
  }
32
+
33
+ /**
34
+ * Capture a screenshot and native view hierarchy.
35
+ * Drop this anywhere in a test to inspect the current screen state.
36
+ *
37
+ * Usage:
38
+ * import { debug } from '@nyby/detox-component-testing/test';
39
+ * await debug(); // artifacts/debug-1.png, debug-1-view.xml
40
+ * await debug('after-tap'); // artifacts/debug-after-tap.png, etc.
41
+ */
42
+ let counter = 0;
43
+
44
+ export async function debug(label?: string, outputDir?: string) {
45
+ const name = label || String(++counter);
46
+ const dir = outputDir || join(process.cwd(), "artifacts");
47
+ await captureArtifacts(name, dir, device);
48
+ }
@@ -5,6 +5,6 @@ declare const device: {
5
5
  generateViewHierarchyXml(): Promise<string>;
6
6
  };
7
7
  declare function element(matcher: any): any;
8
- declare const by: {id(id: string): any};
8
+ declare const by: { id(id: string): any };
9
9
  declare function waitFor(e: any): any;
10
10
  declare function expect(e: any): any;
@@ -1,47 +1,17 @@
1
- const DetoxCircusEnvironment = require('detox/runners/jest/testEnvironment');
2
- const {mkdirSync, writeFileSync} = require('fs');
3
- const {join} = require('path');
1
+ const DetoxCircusEnvironment = require("detox/runners/jest/testEnvironment");
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
- if (event.name === 'test_done' && event.test.errors.length > 0) {
10
- await this._dumpDebugInfo(event.test);
9
+ if (event.name === "test_done" && event.test.errors.length > 0) {
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')))
31
- .toExist()
32
- .withTimeout(3000);
33
-
34
- const attrs = await element(by.id('debug-tree-output')).getAttributes();
35
- const tree = attrs.text || attrs.label || '[]';
36
- writeFileSync(join(outputDir, `componenttree-${safeName}.json`), tree, 'utf8');
37
- } catch (_e) {}
38
-
39
- // Native view hierarchy
40
- try {
41
- const xml = await this.global.device.generateViewHierarchyXml();
42
- writeFileSync(join(outputDir, `viewhierarchy-${safeName}.xml`), xml, 'utf8');
43
- } catch (_e) {}
44
- }
45
15
  }
46
16
 
47
17
  module.exports = CustomDetoxEnvironment;
package/src/index.ts CHANGED
@@ -1,4 +1,7 @@
1
- export {registerComponent} from './ComponentRegistry';
2
- export {ComponentHarness} from './ComponentHarness';
3
- export {configureHarness, WrapperProps, HarnessConfig} from './configureHarness';
4
- export {DebugTree, DebugTreeProps} from './DebugTree';
1
+ export { registerComponent } from "./ComponentRegistry";
2
+ export { ComponentHarness } from "./ComponentHarness";
3
+ export {
4
+ configureHarness,
5
+ WrapperProps,
6
+ HarnessConfig,
7
+ } from "./configureHarness";
package/src/mount.ts CHANGED
@@ -9,32 +9,37 @@ export interface SpyExpectation {
9
9
  lastCalledWith(...args: any[]): Promise<void>;
10
10
  }
11
11
 
12
- const SPY_MARKER = '__detoxSpy__' as const;
12
+ const SPY_MARKER = "__detoxSpy__" as const;
13
13
 
14
14
  let mountCounter = 0;
15
15
  let appLaunched = false;
16
16
 
17
17
  export function spy(name: string): SpyMarker {
18
- return {[SPY_MARKER]: true, name};
18
+ return { [SPY_MARKER]: true, name };
19
19
  }
20
20
 
21
21
  type MountProps = Record<string, string | number | boolean | SpyMarker>;
22
22
 
23
- export async function assertNoRenderError(): Promise<void> {
23
+ async function assertNoRenderError(): Promise<void> {
24
24
  try {
25
- await waitFor(element(by.id('detox-render-error')))
25
+ await waitFor(element(by.id("detox-render-error")))
26
26
  .toExist()
27
27
  .withTimeout(500);
28
28
  } catch {
29
29
  return; // Element not found — no render error, all good
30
30
  }
31
31
  // Element exists — read the error message and throw
32
- const attrs = (await element(by.id('detox-render-error-message')).getAttributes()) as any;
33
- const message = attrs.text || attrs.label || 'Unknown render error';
32
+ const attrs = (await element(
33
+ by.id("detox-render-error-message"),
34
+ ).getAttributes()) as any;
35
+ const message = attrs.text || attrs.label || "Unknown render error";
34
36
  throw new Error(`Component render error: ${message}`);
35
37
  }
36
38
 
37
- export async function mount(componentName: string, props?: MountProps): Promise<void> {
39
+ export async function mount(
40
+ componentName: string,
41
+ props?: MountProps,
42
+ ): Promise<void> {
38
43
  const payload = {
39
44
  id: String(++mountCounter),
40
45
  name: componentName,
@@ -44,7 +49,7 @@ export async function mount(componentName: string, props?: MountProps): Promise<
44
49
 
45
50
  if (props) {
46
51
  Object.entries(props).forEach(([key, value]) => {
47
- if (value && typeof value === 'object' && SPY_MARKER in value) {
52
+ if (value && typeof value === "object" && SPY_MARKER in value) {
48
53
  payload.spies.push(key);
49
54
  } else {
50
55
  payload.props[key] = value;
@@ -52,19 +57,19 @@ export async function mount(componentName: string, props?: MountProps): Promise<
52
57
  });
53
58
  }
54
59
 
55
- const launchArgs: Record<string, any> = {detoxComponentName: componentName};
60
+ const launchArgs: Record<string, any> = { detoxComponentName: componentName };
56
61
  Object.entries(payload.props).forEach(([key, value]) => {
57
62
  launchArgs[`detoxProp_${key}`] = value;
58
63
  });
59
64
  payload.spies.forEach((name) => {
60
65
  launchArgs[`detoxSpy_${name}`] = true;
61
66
  });
62
- await device.launchApp({newInstance: true, launchArgs});
67
+ await device.launchApp({ newInstance: true, launchArgs });
63
68
  appLaunched = true;
64
69
  // Harness sets id '0' for the initial launch-args mount
65
70
  try {
66
- await waitFor(element(by.id('detox-mount-id')))
67
- .toHaveText('0')
71
+ await waitFor(element(by.id("detox-mount-id")))
72
+ .toHaveText("0")
68
73
  .withTimeout(5000);
69
74
  } catch (e) {
70
75
  await assertNoRenderError(); // Throws with the actual error if one exists
@@ -79,13 +84,19 @@ export function expectSpy(name: string): SpyExpectation {
79
84
  const getExpect = () => expect as unknown as (e: any) => any;
80
85
  return {
81
86
  async toHaveBeenCalled() {
82
- await getExpect()(element(by.id(`spy-${name}-count`))).not.toHaveText('0');
87
+ await getExpect()(element(by.id(`spy-${name}-count`))).not.toHaveText(
88
+ "0",
89
+ );
83
90
  },
84
91
  async toHaveBeenCalledTimes(n: number) {
85
- await getExpect()(element(by.id(`spy-${name}-count`))).toHaveText(String(n));
92
+ await getExpect()(element(by.id(`spy-${name}-count`))).toHaveText(
93
+ String(n),
94
+ );
86
95
  },
87
96
  async lastCalledWith(...args: any[]) {
88
- await getExpect()(element(by.id(`spy-${name}-lastArgs`))).toHaveText(JSON.stringify(args));
97
+ await getExpect()(element(by.id(`spy-${name}-lastArgs`))).toHaveText(
98
+ JSON.stringify(args),
99
+ );
89
100
  },
90
101
  };
91
102
  }
package/src/test.ts CHANGED
@@ -1,2 +1,2 @@
1
- export {mount, spy, expectSpy} from './mount';
2
- export {debug} from './debug';
1
+ export { mount, spy, expectSpy } from "./mount";
2
+ export { debug } from "./debug";
@@ -1,20 +0,0 @@
1
- import React from 'react';
2
- export declare function captureTree(ref: any, usefulProps?: Set<string>, skipNames?: Set<string>, nativeDuplicates?: Set<string>): string;
3
- export interface DebugTreeProps {
4
- children: React.ReactNode;
5
- /** Props to include in tree output. Defaults to testID, accessibilityLabel, etc. */
6
- usefulProps?: string[];
7
- /** Component names to skip (internal wrappers that add noise). */
8
- skipNames?: string[];
9
- /** Native component names that duplicate their parent (e.g. RCTText inside Text). */
10
- nativeDuplicates?: string[];
11
- }
12
- /**
13
- * Debug component that captures the React component tree on demand.
14
- * Wrap your test content with this. Trigger via Detox:
15
- *
16
- * await element(by.id('debug-tree-control')).replaceText('dump');
17
- * const attrs = await element(by.id('debug-tree-output')).getAttributes();
18
- */
19
- export declare function DebugTree({ children, usefulProps, skipNames, nativeDuplicates }: DebugTreeProps): React.JSX.Element;
20
- //# sourceMappingURL=DebugTree.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DebugTree.d.ts","sourceRoot":"","sources":["../src/DebugTree.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAiN3D,wBAAgB,WAAW,CACzB,GAAG,EAAE,GAAG,EACR,WAAW,GAAE,GAAG,CAAC,MAAM,CAAwB,EAC/C,SAAS,GAAE,GAAG,CAAC,MAAM,CAAsB,EAC3C,gBAAgB,GAAE,GAAG,CAAC,MAAM,CAA6B,GACxD,MAAM,CAQR;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,EAAC,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAC,EAAE,cAAc,qBAsC7F"}