Skip to content

Commit 883deb2

Browse files
authored
feature: add reload method to easily reset app state during tests (#114)
* refactor: move adb and xcrun commands into separate utils * feat: add `reload` support * docs: add `reload` method to docs * tests: fix tests * docs: update `reload` docs and example tests * chore: dep version updates * ci: update example package link to try to fix CI
1 parent e0d3631 commit 883deb2

15 files changed

Lines changed: 1068 additions & 247 deletions

File tree

docs/api/methods.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,36 @@ describe('App.tsx', () => {
235235
});
236236
});
237237
```
238+
239+
### reload()
240+
241+
Terminates the app in the emulator/simulator, and restarts it.
242+
243+
This is useful when you want to complete a set of tests and nove onto a new set of tests.
244+
245+
Depending on your use-case, you could call `reload` in a `beforeAll`, or `beforeEach` callback, or within a test case, to get the app into a clean state before each set of tests for example.
246+
247+
248+
#### Example
249+
250+
251+
```js title="__tests__/App.owl.tsx"
252+
import { reload } from 'react-native-owl';
253+
254+
describe('App.tsx', () => {
255+
describe('the checkout flow', () => {
256+
beforeAll(async () => {
257+
// highlight-next-line
258+
await reload();
259+
}),
260+
261+
it('adds product to cart', async () => {
262+
...
263+
});
264+
265+
it('starts checkout flow', async () => {
266+
...
267+
});
268+
});
269+
});
270+
```
199 KB
Loading
318 KB
Loading

example/__tests__/App.owl.tsx

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,56 +6,71 @@ import {
66
scrollTo,
77
scrollToEnd,
88
longPress,
9+
reload,
910
} from 'react-native-owl';
1011

1112
jest.setTimeout(30000);
1213

1314
describe('App.tsx', () => {
14-
it('takes a screenshot of the initial screen', async () => {
15-
const screen = await takeScreenshot('initial');
15+
describe('Basic navigation', () => {
16+
it('takes a screenshot of the initial screen', async () => {
17+
const screen = await takeScreenshot('initial');
1618

17-
expect(screen).toMatchBaseline();
18-
});
19+
expect(screen).toMatchBaseline();
20+
});
1921

20-
it('longPress a Pressable, then takes a screenshot', async () => {
21-
await longPress('Pressable');
22+
it('longPress a Pressable, then takes a screenshot', async () => {
23+
await longPress('Pressable');
2224

23-
const screen = await takeScreenshot('long-press');
25+
const screen = await takeScreenshot('long-press');
2426

25-
expect(screen).toMatchBaseline();
26-
});
27+
expect(screen).toMatchBaseline();
28+
});
2729

28-
it('press a Pressable, waits for an element then takes a screenshot', async () => {
29-
await press('Pressable');
30+
it('press a Pressable, waits for an element then takes a screenshot', async () => {
31+
await press('Pressable');
3032

31-
await toExist('TextInput');
33+
await toExist('TextInput');
3234

33-
const screen = await takeScreenshot('test-input');
35+
const screen = await takeScreenshot('test-input');
3436

35-
expect(screen).toMatchBaseline();
36-
});
37+
expect(screen).toMatchBaseline();
38+
});
3739

38-
it('enters some text and takes a screenshot', async () => {
39-
await changeText('TextInput', 'Entered text');
40+
it('enters some text and takes a screenshot', async () => {
41+
await changeText('TextInput', 'Entered text');
4042

41-
const screen = await takeScreenshot('entered-text');
43+
const screen = await takeScreenshot('entered-text');
4244

43-
expect(screen).toMatchBaseline();
44-
});
45+
expect(screen).toMatchBaseline();
46+
});
47+
48+
it('scrolls a bit and takes a screenshot', async () => {
49+
await scrollTo('ScrollView', { y: 50 });
50+
51+
const screen = await takeScreenshot('scroll-to');
52+
53+
expect(screen).toMatchBaseline();
54+
});
4555

46-
it('scrolls a bit and takes a screenshot', async () => {
47-
await scrollTo('ScrollView', { y: 50 });
56+
it('scrolls to end and takes a screenshot', async () => {
57+
await scrollToEnd('ScrollView');
4858

49-
const screen = await takeScreenshot('scroll-to');
59+
const screen = await takeScreenshot('scroll-to-end');
5060

51-
expect(screen).toMatchBaseline();
61+
expect(screen).toMatchBaseline();
62+
});
5263
});
5364

54-
it('scrolls to end and takes a screenshot', async () => {
55-
await scrollToEnd('ScrollView');
65+
describe('Reload example', () => {
66+
beforeAll(async () => {
67+
await reload();
68+
});
5669

57-
const screen = await takeScreenshot('scroll-to-end');
70+
it('takes a screenshot of the welcome screen', async () => {
71+
const screen = await takeScreenshot('after-reload');
5872

59-
expect(screen).toMatchBaseline();
73+
expect(screen).toMatchBaseline();
74+
});
6075
});
6176
});

example/ios/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,4 +523,4 @@ SPEC CHECKSUMS:
523523

524524
PODFILE CHECKSUM: 3190b6d7739c1a0f98e11d88f08dd49936f770e0
525525

526-
COCOAPODS: 1.11.2
526+
COCOAPODS: 1.11.3

example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"dependencies": {
1818
"react": "17.0.2",
1919
"react-native": "0.66.0",
20-
"react-native-owl": "link:../"
20+
"react-native-owl": "link:.."
2121
},
2222
"devDependencies": {
2323
"@babel/core": "^7.12.9",

lib/actions.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1+
import { getConfig } from './cli/config';
2+
13
import { Logger } from './logger';
4+
import { CliRunOptions } from './types';
5+
import { adbLaunch, adbTerminate } from './utils/adb';
6+
import { waitFor } from './utils/wait-for';
7+
import { xcrunLaunch, xcrunTerminate, xcrunUi } from './utils/xcrun';
28
import { createWebSocketClient } from './websocket';
39
import {
410
SOCKET_TEST_REQUEST,
@@ -57,3 +63,62 @@ export const scrollToEnd = (testID: string) =>
5763

5864
export const toExist = (testID: string) =>
5965
sendEvent({ type: 'LAYOUT', action: 'EXISTS', testID });
66+
67+
export const reload = async () => {
68+
const args = (global as any).OWL_CLI_ARGS as CliRunOptions;
69+
70+
if (!args) {
71+
return;
72+
}
73+
74+
const config = await getConfig(args.config);
75+
76+
if (args.platform === 'ios') {
77+
if (!config.ios?.device) {
78+
return Promise.reject('Missing device name');
79+
}
80+
81+
await xcrunTerminate({
82+
debug: config.debug,
83+
binaryPath: config.ios?.binaryPath,
84+
device: config.ios.device,
85+
scheme: config.ios?.scheme,
86+
configuration: config.ios?.configuration,
87+
});
88+
89+
await xcrunLaunch({
90+
debug: config.debug,
91+
binaryPath: config.ios?.binaryPath,
92+
device: config.ios.device,
93+
scheme: config.ios?.scheme,
94+
configuration: config.ios?.configuration,
95+
});
96+
97+
await waitFor(1000);
98+
99+
await xcrunUi({
100+
debug: config.debug,
101+
device: config.ios.device,
102+
configuration: config.ios.configuration,
103+
binaryPath: config.ios.binaryPath,
104+
});
105+
}
106+
107+
if (args.platform === 'android') {
108+
if (!config.android?.packageName) {
109+
return Promise.reject('Missing package name');
110+
}
111+
112+
await adbTerminate({
113+
debug: config.debug,
114+
packageName: config.android.packageName,
115+
});
116+
117+
await adbLaunch({
118+
debug: config.debug,
119+
packageName: config.android.packageName,
120+
});
121+
122+
await waitFor(500);
123+
}
124+
};

0 commit comments

Comments
 (0)