@nyby/detox-component-testing 1.0.0 → 1.2.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.
- package/dist/ComponentHarness.d.ts +3 -0
- package/dist/ComponentHarness.d.ts.map +1 -0
- package/dist/ComponentHarness.js +120 -0
- package/dist/ComponentHarness.js.map +1 -0
- package/dist/ComponentRegistry.d.ts +10 -0
- package/dist/ComponentRegistry.d.ts.map +1 -0
- package/dist/ComponentRegistry.js +36 -0
- package/dist/ComponentRegistry.js.map +1 -0
- package/dist/configureHarness.d.ts +11 -0
- package/dist/configureHarness.d.ts.map +1 -0
- package/dist/configureHarness.js +13 -0
- package/dist/configureHarness.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/mount.d.ts +15 -0
- package/dist/mount.d.ts.map +1 -0
- package/dist/mount.js +60 -0
- package/dist/mount.js.map +1 -0
- package/dist/test.d.ts +2 -0
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +8 -0
- package/dist/test.js.map +1 -0
- package/package.json +33 -6
- package/src/detox-env.d.ts +6 -0
- package/src/mount.ts +6 -7
- package/tsconfig.json +0 -17
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComponentHarness.d.ts","sourceRoot":"","sources":["../src/ComponentHarness.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAwC,MAAM,OAAO,CAAC;AA6B7D,wBAAgB,gBAAgB,sBAmC/B"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ComponentHarness = ComponentHarness;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const react_native_1 = require("react-native");
|
|
39
|
+
const react_native_launch_arguments_1 = require("react-native-launch-arguments");
|
|
40
|
+
const ComponentRegistry_1 = require("./ComponentRegistry");
|
|
41
|
+
const configureHarness_1 = require("./configureHarness");
|
|
42
|
+
const PROP_PREFIX = 'detoxProp_';
|
|
43
|
+
const SPY_PREFIX = 'detoxSpy_';
|
|
44
|
+
function parseLaunchArgs(args) {
|
|
45
|
+
const props = {};
|
|
46
|
+
const spies = [];
|
|
47
|
+
Object.entries(args).forEach(([key, value]) => {
|
|
48
|
+
if (key.startsWith(PROP_PREFIX)) {
|
|
49
|
+
props[key.slice(PROP_PREFIX.length)] = value;
|
|
50
|
+
}
|
|
51
|
+
else if (key.startsWith(SPY_PREFIX)) {
|
|
52
|
+
spies.push(key.slice(SPY_PREFIX.length));
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return { props, spies };
|
|
56
|
+
}
|
|
57
|
+
function ComponentHarness() {
|
|
58
|
+
const launchArgs = react_native_launch_arguments_1.LaunchArguments.value();
|
|
59
|
+
const [mountPayload, setMountPayload] = (0, react_1.useState)(null);
|
|
60
|
+
const handleControl = (0, react_1.useCallback)((text) => {
|
|
61
|
+
try {
|
|
62
|
+
setMountPayload(JSON.parse(text));
|
|
63
|
+
}
|
|
64
|
+
catch (_e) { }
|
|
65
|
+
}, []);
|
|
66
|
+
let activeMount = null;
|
|
67
|
+
if (mountPayload) {
|
|
68
|
+
activeMount = mountPayload;
|
|
69
|
+
}
|
|
70
|
+
else if (launchArgs.detoxComponentName) {
|
|
71
|
+
const { props, spies } = parseLaunchArgs(launchArgs);
|
|
72
|
+
activeMount = {
|
|
73
|
+
id: '0',
|
|
74
|
+
name: launchArgs.detoxComponentName,
|
|
75
|
+
props,
|
|
76
|
+
spies,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return (react_1.default.createElement(react_native_1.View, { style: { flex: 1 } },
|
|
80
|
+
react_1.default.createElement(react_native_1.TextInput, { testID: "detox-harness-control", onChangeText: handleControl, style: { height: 1 } }),
|
|
81
|
+
activeMount && (react_1.default.createElement(ComponentRenderer, { key: activeMount.id, mount: activeMount }))));
|
|
82
|
+
}
|
|
83
|
+
function ComponentRenderer({ mount }) {
|
|
84
|
+
const { Component, defaultProps } = (0, ComponentRegistry_1.getComponent)(mount.name);
|
|
85
|
+
const spyNames = mount.spies || [];
|
|
86
|
+
const initialData = {};
|
|
87
|
+
spyNames.forEach(name => {
|
|
88
|
+
initialData[name] = { count: 0, lastArgs: [] };
|
|
89
|
+
});
|
|
90
|
+
const [spyData, setSpyData] = (0, react_1.useState)(initialData);
|
|
91
|
+
const spyFnsRef = (0, react_1.useRef)({});
|
|
92
|
+
const spyProps = {};
|
|
93
|
+
spyNames.forEach(name => {
|
|
94
|
+
if (!spyFnsRef.current[name]) {
|
|
95
|
+
spyFnsRef.current[name] = (...callArgs) => {
|
|
96
|
+
setSpyData(prev => {
|
|
97
|
+
var _a;
|
|
98
|
+
return ({
|
|
99
|
+
...prev,
|
|
100
|
+
[name]: {
|
|
101
|
+
count: (((_a = prev[name]) === null || _a === void 0 ? void 0 : _a.count) || 0) + 1,
|
|
102
|
+
lastArgs: callArgs,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
spyProps[name] = spyFnsRef.current[name];
|
|
109
|
+
});
|
|
110
|
+
const props = { ...defaultProps, ...(mount.props || {}), ...spyProps };
|
|
111
|
+
const Wrapper = (0, configureHarness_1.getWrapper)();
|
|
112
|
+
return (react_1.default.createElement(Wrapper, { launchArgs: mount.props || {} },
|
|
113
|
+
react_1.default.createElement(react_native_1.View, { testID: "component-harness-root", style: { flex: 1 } },
|
|
114
|
+
react_1.default.createElement(react_native_1.Text, { testID: "detox-mount-id", style: { height: 1 } }, mount.id),
|
|
115
|
+
react_1.default.createElement(Component, { ...props }),
|
|
116
|
+
spyNames.map(name => (react_1.default.createElement(react_native_1.View, { key: name },
|
|
117
|
+
react_1.default.createElement(react_native_1.Text, { testID: `spy-${name}-count` }, String(spyData[name].count)),
|
|
118
|
+
react_1.default.createElement(react_native_1.Text, { testID: `spy-${name}-lastArgs` }, JSON.stringify(spyData[name].lastArgs))))))));
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=ComponentHarness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComponentHarness.js","sourceRoot":"","sources":["../src/ComponentHarness.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ComponentType } from 'react';
|
|
2
|
+
export interface ComponentEntry<P = any> {
|
|
3
|
+
Component: ComponentType<P>;
|
|
4
|
+
defaultProps: Partial<P>;
|
|
5
|
+
}
|
|
6
|
+
export declare function registerComponent<P>(name: string, Component: ComponentType<P>, defaultProps?: Partial<P>): void;
|
|
7
|
+
export declare function registerComponent<P>(Component: ComponentType<P>, defaultProps?: Partial<P>): void;
|
|
8
|
+
export declare function getComponent(name: string): ComponentEntry;
|
|
9
|
+
export declare function getAll(): Record<string, ComponentEntry>;
|
|
10
|
+
//# sourceMappingURL=ComponentRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComponentRegistry.d.ts","sourceRoot":"","sources":["../src/ComponentRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,GAAG;IACrC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;CAC1B;AAID,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GACxB,IAAI,CAAC;AACR,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GACxB,IAAI,CAAC;AA0BR,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAQzD;AAED,wBAAgB,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAEvD"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerComponent = registerComponent;
|
|
4
|
+
exports.getComponent = getComponent;
|
|
5
|
+
exports.getAll = getAll;
|
|
6
|
+
const registry = new Map();
|
|
7
|
+
function registerComponent(nameOrComponent, componentOrProps, defaultProps) {
|
|
8
|
+
if (typeof nameOrComponent === 'string') {
|
|
9
|
+
registry.set(nameOrComponent, {
|
|
10
|
+
Component: componentOrProps,
|
|
11
|
+
defaultProps: (defaultProps || {}),
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
const Component = nameOrComponent;
|
|
16
|
+
const name = Component.displayName || Component.name;
|
|
17
|
+
if (!name) {
|
|
18
|
+
throw new Error('[detox-component-testing] Component must have a name or displayName to register without an explicit name.');
|
|
19
|
+
}
|
|
20
|
+
registry.set(name, {
|
|
21
|
+
Component,
|
|
22
|
+
defaultProps: (componentOrProps || {}),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function getComponent(name) {
|
|
27
|
+
const entry = registry.get(name);
|
|
28
|
+
if (!entry) {
|
|
29
|
+
throw new Error(`[detox-component-testing] Component "${name}" not found in registry. Did you call registerComponent()?`);
|
|
30
|
+
}
|
|
31
|
+
return entry;
|
|
32
|
+
}
|
|
33
|
+
function getAll() {
|
|
34
|
+
return Object.fromEntries(registry);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=ComponentRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComponentRegistry.js","sourceRoot":"","sources":["../src/ComponentRegistry.ts"],"names":[],"mappings":";;AAkBA,8CAuBC;AAED,oCAQC;AAED,wBAEC;AAhDD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;AAWnD,SAAgB,iBAAiB,CAC/B,eAA0C,EAC1C,gBAAgD,EAChD,YAAyB;IAEzB,IAAI,OAAO,eAAe,KAAK,QAAQ,EAAE,CAAC;QACxC,QAAQ,CAAC,GAAG,CAAC,eAAe,EAAE;YAC5B,SAAS,EAAE,gBAAoC;YAC/C,YAAY,EAAE,CAAC,YAAY,IAAI,EAAE,CAAe;SACjD,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,GAAG,eAAe,CAAC;QAClC,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,IAAI,SAAS,CAAC,IAAI,CAAC;QACrD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CACb,2GAA2G,CAC5G,CAAC;QACJ,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE;YACjB,SAAS;YACT,YAAY,EAAE,CAAE,gBAA+B,IAAI,EAAE,CAAe;SACrE,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,SAAgB,YAAY,CAAC,IAAY;IACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,wCAAwC,IAAI,4DAA4D,CACzG,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAgB,MAAM;IACpB,OAAO,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ComponentType, ReactNode } from 'react';
|
|
2
|
+
export interface WrapperProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
launchArgs: Record<string, any>;
|
|
5
|
+
}
|
|
6
|
+
export interface HarnessConfig {
|
|
7
|
+
wrapper: ComponentType<WrapperProps>;
|
|
8
|
+
}
|
|
9
|
+
export declare function configureHarness(config: HarnessConfig): void;
|
|
10
|
+
export declare function getWrapper(): ComponentType<WrapperProps>;
|
|
11
|
+
//# sourceMappingURL=configureHarness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configureHarness.d.ts","sourceRoot":"","sources":["../src/configureHarness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEjD,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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.configureHarness = configureHarness;
|
|
4
|
+
exports.getWrapper = getWrapper;
|
|
5
|
+
const DefaultWrapper = ({ children }) => children;
|
|
6
|
+
let globalWrapper = null;
|
|
7
|
+
function configureHarness(config) {
|
|
8
|
+
globalWrapper = config.wrapper;
|
|
9
|
+
}
|
|
10
|
+
function getWrapper() {
|
|
11
|
+
return globalWrapper || DefaultWrapper;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=configureHarness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configureHarness.js","sourceRoot":"","sources":["../src/configureHarness.ts"],"names":[],"mappings":";;AAeA,4CAEC;AAED,gCAEC;AAVD,MAAM,cAAc,GAAG,CAAC,EAAE,QAAQ,EAAgB,EAAE,EAAE,CAAC,QAAQ,CAAC;AAEhE,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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { registerComponent, getComponent, getAll, ComponentEntry } from './ComponentRegistry';
|
|
2
|
+
export { ComponentHarness } from './ComponentHarness';
|
|
3
|
+
export { configureHarness, WrapperProps, HarnessConfig } from './configureHarness';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC9F,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.configureHarness = exports.ComponentHarness = exports.getAll = exports.getComponent = exports.registerComponent = void 0;
|
|
4
|
+
var ComponentRegistry_1 = require("./ComponentRegistry");
|
|
5
|
+
Object.defineProperty(exports, "registerComponent", { enumerable: true, get: function () { return ComponentRegistry_1.registerComponent; } });
|
|
6
|
+
Object.defineProperty(exports, "getComponent", { enumerable: true, get: function () { return ComponentRegistry_1.getComponent; } });
|
|
7
|
+
Object.defineProperty(exports, "getAll", { enumerable: true, get: function () { return ComponentRegistry_1.getAll; } });
|
|
8
|
+
var ComponentHarness_1 = require("./ComponentHarness");
|
|
9
|
+
Object.defineProperty(exports, "ComponentHarness", { enumerable: true, get: function () { return ComponentHarness_1.ComponentHarness; } });
|
|
10
|
+
var configureHarness_1 = require("./configureHarness");
|
|
11
|
+
Object.defineProperty(exports, "configureHarness", { enumerable: true, get: function () { return configureHarness_1.configureHarness; } });
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yDAA8F;AAArF,sHAAA,iBAAiB,OAAA;AAAE,iHAAA,YAAY,OAAA;AAAE,2GAAA,MAAM,OAAA;AAChD,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA;AACzB,uDAAmF;AAA1E,oHAAA,gBAAgB,OAAA"}
|
package/dist/mount.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface SpyMarker {
|
|
2
|
+
readonly __detoxSpy__: true;
|
|
3
|
+
readonly name: string;
|
|
4
|
+
}
|
|
5
|
+
export interface SpyExpectation {
|
|
6
|
+
toHaveBeenCalled(): Promise<void>;
|
|
7
|
+
toHaveBeenCalledTimes(n: number): Promise<void>;
|
|
8
|
+
lastCalledWith(...args: any[]): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export declare function spy(name: string): SpyMarker;
|
|
11
|
+
type MountProps = Record<string, string | number | boolean | SpyMarker>;
|
|
12
|
+
export declare function mount(componentName: string, props?: MountProps): Promise<void>;
|
|
13
|
+
export declare function expectSpy(name: string): SpyExpectation;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=mount.d.ts.map
|
|
@@ -0,0 +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,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAkCpF;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAetD"}
|
package/dist/mount.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.spy = spy;
|
|
4
|
+
exports.mount = mount;
|
|
5
|
+
exports.expectSpy = expectSpy;
|
|
6
|
+
const SPY_MARKER = '__detoxSpy__';
|
|
7
|
+
let mountCounter = 0;
|
|
8
|
+
let appLaunched = false;
|
|
9
|
+
function spy(name) {
|
|
10
|
+
return { [SPY_MARKER]: true, name };
|
|
11
|
+
}
|
|
12
|
+
async function mount(componentName, props) {
|
|
13
|
+
const payload = {
|
|
14
|
+
id: String(++mountCounter),
|
|
15
|
+
name: componentName,
|
|
16
|
+
props: {},
|
|
17
|
+
spies: [],
|
|
18
|
+
};
|
|
19
|
+
if (props) {
|
|
20
|
+
Object.entries(props).forEach(([key, value]) => {
|
|
21
|
+
if (value && typeof value === 'object' && SPY_MARKER in value) {
|
|
22
|
+
payload.spies.push(key);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
payload.props[key] = value;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (!appLaunched) {
|
|
30
|
+
const launchArgs = { detoxComponentName: componentName };
|
|
31
|
+
Object.entries(payload.props).forEach(([key, value]) => {
|
|
32
|
+
launchArgs[`detoxProp_${key}`] = value;
|
|
33
|
+
});
|
|
34
|
+
payload.spies.forEach(name => {
|
|
35
|
+
launchArgs[`detoxSpy_${name}`] = true;
|
|
36
|
+
});
|
|
37
|
+
await device.launchApp({ newInstance: true, launchArgs });
|
|
38
|
+
appLaunched = true;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
await element(by.id('detox-harness-control')).replaceText(JSON.stringify(payload));
|
|
42
|
+
await waitFor(element(by.id('detox-mount-id'))).toHaveText(payload.id).withTimeout(5000);
|
|
43
|
+
}
|
|
44
|
+
function expectSpy(name) {
|
|
45
|
+
// Detox's expect is injected as a global by the test environment.
|
|
46
|
+
// Resolve lazily to avoid ReferenceError at module load time.
|
|
47
|
+
const getExpect = () => expect;
|
|
48
|
+
return {
|
|
49
|
+
async toHaveBeenCalled() {
|
|
50
|
+
await getExpect()(element(by.id(`spy-${name}-count`))).not.toHaveText('0');
|
|
51
|
+
},
|
|
52
|
+
async toHaveBeenCalledTimes(n) {
|
|
53
|
+
await getExpect()(element(by.id(`spy-${name}-count`))).toHaveText(String(n));
|
|
54
|
+
},
|
|
55
|
+
async lastCalledWith(...args) {
|
|
56
|
+
await getExpect()(element(by.id(`spy-${name}-lastArgs`))).toHaveText(JSON.stringify(args));
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=mount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"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"}
|
package/dist/test.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/test.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.expectSpy = exports.spy = exports.mount = void 0;
|
|
4
|
+
var mount_1 = require("./mount");
|
|
5
|
+
Object.defineProperty(exports, "mount", { enumerable: true, get: function () { return mount_1.mount; } });
|
|
6
|
+
Object.defineProperty(exports, "spy", { enumerable: true, get: function () { return mount_1.spy; } });
|
|
7
|
+
Object.defineProperty(exports, "expectSpy", { enumerable: true, get: function () { return mount_1.expectSpy; } });
|
|
8
|
+
//# sourceMappingURL=test.js.map
|
package/dist/test.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":";;;AAAA,iCAA2E;AAAlE,8FAAA,KAAK,OAAA;AAAE,4FAAA,GAAG,OAAA;AAAE,kGAAA,SAAS,OAAA"}
|
package/package.json
CHANGED
|
@@ -1,16 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nyby/detox-component-testing",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Component testing support for Detox and React Native",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
6
7
|
"exports": {
|
|
7
|
-
".":
|
|
8
|
-
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./test": {
|
|
13
|
+
"types": "./dist/test.d.ts",
|
|
14
|
+
"default": "./dist/test.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"typesVersions": {
|
|
18
|
+
"*": {
|
|
19
|
+
"test": ["dist/test.d.ts"]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"src"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc",
|
|
28
|
+
"clean": "rm -rf dist",
|
|
29
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
30
|
+
"publish:public": "npm publish --access public"
|
|
9
31
|
},
|
|
10
32
|
"peerDependencies": {
|
|
33
|
+
"detox": "*",
|
|
11
34
|
"react": "*",
|
|
12
35
|
"react-native": "*",
|
|
13
|
-
"react-native-launch-arguments": "*"
|
|
14
|
-
|
|
36
|
+
"react-native-launch-arguments": "*"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/react": "^19.2.14",
|
|
40
|
+
"@types/react-native": "^0.72.8",
|
|
41
|
+
"typescript": "^5.9.3"
|
|
15
42
|
}
|
|
16
43
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Ambient declarations for Detox globals injected by the test runner at runtime.
|
|
2
|
+
declare const device: { launchApp(config?: any): Promise<void> };
|
|
3
|
+
declare function element(matcher: any): any;
|
|
4
|
+
declare const by: { id(id: string): any };
|
|
5
|
+
declare function waitFor(e: any): any;
|
|
6
|
+
declare function expect(e: any): any;
|
package/src/mount.ts
CHANGED
|
@@ -56,20 +56,19 @@ export async function mount(componentName: string, props?: MountProps): Promise<
|
|
|
56
56
|
await waitFor(element(by.id('detox-mount-id'))).toHaveText(payload.id).withTimeout(5000);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
// Detox's expect is injected as a global by the test environment.
|
|
60
|
-
// Cast to any since the library can't import 'detox' directly (peer dep).
|
|
61
|
-
const detoxExpect = expect as unknown as (e: any) => any;
|
|
62
|
-
|
|
63
59
|
export function expectSpy(name: string): SpyExpectation {
|
|
60
|
+
// Detox's expect is injected as a global by the test environment.
|
|
61
|
+
// Resolve lazily to avoid ReferenceError at module load time.
|
|
62
|
+
const getExpect = () => expect as unknown as (e: any) => any;
|
|
64
63
|
return {
|
|
65
64
|
async toHaveBeenCalled() {
|
|
66
|
-
await
|
|
65
|
+
await getExpect()(element(by.id(`spy-${name}-count`))).not.toHaveText('0');
|
|
67
66
|
},
|
|
68
67
|
async toHaveBeenCalledTimes(n: number) {
|
|
69
|
-
await
|
|
68
|
+
await getExpect()(element(by.id(`spy-${name}-count`))).toHaveText(String(n));
|
|
70
69
|
},
|
|
71
70
|
async lastCalledWith(...args: any[]) {
|
|
72
|
-
await
|
|
71
|
+
await getExpect()(element(by.id(`spy-${name}-lastArgs`))).toHaveText(JSON.stringify(args));
|
|
73
72
|
},
|
|
74
73
|
};
|
|
75
74
|
}
|
package/tsconfig.json
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es2018",
|
|
4
|
-
"module": "commonjs",
|
|
5
|
-
"jsx": "react",
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"declarationMap": true,
|
|
8
|
-
"sourceMap": true,
|
|
9
|
-
"outDir": "dist",
|
|
10
|
-
"strict": true,
|
|
11
|
-
"moduleResolution": "node",
|
|
12
|
-
"esModuleInterop": true,
|
|
13
|
-
"skipLibCheck": true,
|
|
14
|
-
"forceConsistentCasingInFileNames": true
|
|
15
|
-
},
|
|
16
|
-
"include": ["src"]
|
|
17
|
-
}
|