Skip to content

Commit f484248

Browse files
authored
test: improve e2e tests (#741)
* test: improve e2e tests * chore: change detox configuration * upload avd snapshots * upload avd snapshots always * change emulator-options * save snapshot * another try * fix * test * zip * test * download avd snapshots from repository * fix: add waitFor * use .toExist()
1 parent 97717e7 commit f484248

File tree

5 files changed

+68
-44
lines changed

5 files changed

+68
-44
lines changed

.github/workflows/e2e_tests.yaml

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ jobs:
7777
fail-fast: false
7878
matrix:
7979
api-level:
80-
- 31
81-
- 32
8280
- 33
8381
- 34
8482
- 35
@@ -93,6 +91,27 @@ jobs:
9391
9492
- uses: actions/checkout@v4
9593

94+
- name: Checkout AVD snapshots
95+
uses: actions/checkout@v4
96+
with:
97+
repository: DorianMazur/react-native-keychain-avds
98+
sparse-checkout: |
99+
${{ matrix.api-level }}
100+
path: avd-snapshots
101+
lfs: true
102+
103+
- name: Setup AVD snapshots
104+
run: |
105+
mkdir -p ~/.android/avd
106+
if [ -d "avd-snapshots/${{ matrix.api-level }}" ]; then
107+
echo "Found AVD snapshot for API ${{ matrix.api-level }}"
108+
cp -r avd-snapshots/${{ matrix.api-level }}/* ~/.android/avd/
109+
else
110+
echo "ERROR: No pre-configured AVD snapshot found for API ${{ matrix.api-level }}"
111+
echo "Please ensure the required snapshot exists in the repository."
112+
exit 1
113+
fi
114+
96115
- name: Setup Node.js
97116
uses: actions/setup-node@v4
98117
with:
@@ -124,34 +143,11 @@ jobs:
124143
api-level: ${{ matrix.api-level }}
125144
arch: x86_64
126145
profile: pixel_6
146+
force-avd-creation: false
147+
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
127148
disable-animations: true
128149
avd-name: TestingAVD
129150
script: |
130-
echo "Starting the screen recording..."
131-
sleep 3
132-
adb shell "screenrecord --bugreport /data/local/tmp/screenrecord.mp4 & echo \$! > /data/local/tmp/screenrecord_pid.txt" &
133-
adb shell settings put system pointer_location 1
134-
adb shell locksettings set-pin 1111
135-
sleep 3
136-
adb shell am start -a android.settings.BIOMETRIC_ENROLL
137-
sleep 3
138-
adb shell input text 1111
139-
adb shell input keyevent 66
140-
sleep 3
141-
adb shell input tap 900 2200
142-
sleep 3
143-
adb shell input tap 900 2200
144-
sleep 3
145-
adb -e emu finger touch 1
146-
sleep 3
147-
adb -e emu finger touch 1
148-
sleep 3
149-
adb -e emu finger touch 1
150-
sleep 3
151-
adb shell input keyevent KEYCODE_HOME
152-
adb shell "kill -2 \$(cat /data/local/tmp/screenrecord_pid.txt)"
153-
sleep 1
154-
adb pull /data/local/tmp/screenrecord.mp4 .
155151
cd KeychainExample
156152
yarn test:android:run
157153
- name: Upload test artifacts
@@ -162,7 +158,6 @@ jobs:
162158
path: |
163159
KeychainExample/artifacts
164160
screenrecord.mp4
165-
166161
build-ios:
167162
name: Build and Test iOS
168163
runs-on: macos-latest

KeychainExample/.detoxrc.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ module.exports = {
6262
},
6363
artifacts: {
6464
plugins: {
65+
log: { enabled: true },
6566
screenshot: {
6667
enabled: true,
6768
shouldTakeAutomaticSnapshots: true,
@@ -72,6 +73,14 @@ module.exports = {
7273
appNotReady: true,
7374
},
7475
},
76+
video: {
77+
android: {
78+
bitRate: 4000000,
79+
},
80+
simulator: {
81+
codec: 'hevc',
82+
},
83+
},
7584
},
7685
},
7786
configurations: {

KeychainExample/e2e/testCases/acessControlTest.spec.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { by, device, element, expect } from 'detox';
1+
import { by, device, element, expect, waitFor } from 'detox';
22
import { matchLoadInfo } from '../utils/matchLoadInfo';
33
import cp from 'child_process';
44

@@ -35,7 +35,9 @@ describe('Access Control', () => {
3535
}, 1000);
3636
}
3737
await element(by.text('Save')).tap();
38-
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
38+
await waitFor(element(by.text(/^Credentials saved! .*$/)))
39+
.toExist()
40+
.withTimeout(3000);
3941
// Biometric prompt is not available in the IOS simulator
4042
// https://github.com/oblador/react-native-keychain/issues/340
4143
if (device.getPlatform() === 'android') {
@@ -85,9 +87,11 @@ describe('Access Control', () => {
8587
}, 1500);
8688
setTimeout(() => {
8789
cp.spawnSync('adb', ['shell', 'input', 'keyevent', '66']);
88-
}, 3000);
90+
}, 3500);
8991
await element(by.text('Save')).tap();
90-
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
92+
await waitFor(element(by.text(/^Credentials saved! .*$/)))
93+
.toExist()
94+
.withTimeout(4000);
9195

9296
setTimeout(() => {
9397
cp.spawnSync('adb', ['shell', 'input', 'text', '1111']);
@@ -122,7 +126,9 @@ describe('Access Control', () => {
122126

123127
await expect(element(by.text('Save'))).toBeVisible();
124128
await element(by.text('Save')).tap();
125-
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
129+
await waitFor(element(by.text(/^Credentials saved! .*$/)))
130+
.toExist()
131+
.withTimeout(3000);
126132
await element(by.text('Load')).tap();
127133
await matchLoadInfo('testUsernameAny', 'testPasswordAny');
128134
}

KeychainExample/e2e/testCases/securityLevelTest.spec.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { by, device, element, expect } from 'detox';
1+
import { by, device, element, expect, waitFor } from 'detox';
22
import { matchLoadInfo } from '../utils/matchLoadInfo';
33

44
describe(':android:Security Level', () => {
@@ -19,7 +19,9 @@ describe(':android:Security Level', () => {
1919

2020
await expect(element(by.text('Save'))).toBeVisible();
2121
await element(by.text('Save')).tap();
22-
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
22+
await waitFor(element(by.text(/^Credentials saved! .*$/)))
23+
.toExist()
24+
.withTimeout(3000);
2325
await element(by.text('Load')).tap();
2426
await matchLoadInfo(
2527
'testUsernameAny',
@@ -44,7 +46,9 @@ describe(':android:Security Level', () => {
4446

4547
await expect(element(by.text('Save'))).toBeVisible();
4648
await element(by.text('Save')).tap();
47-
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
49+
await waitFor(element(by.text(/^Credentials saved! .*$/)))
50+
.toExist()
51+
.withTimeout(3000);
4852
await element(by.text('Load')).tap();
4953
await matchLoadInfo(
5054
'testUsernameSoftware',
@@ -70,7 +74,9 @@ describe(':android:Security Level', () => {
7074

7175
await expect(element(by.text('Save'))).toBeVisible();
7276
await element(by.text('Save')).tap();
73-
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
77+
await waitFor(element(by.text(/^Credentials saved! .*$/)))
78+
.toExist()
79+
.withTimeout(3000);
7480
await element(by.text('Load')).tap();
7581
await matchLoadInfo(
7682
'testUsernameHardware',

KeychainExample/e2e/testCases/storageTypesTest.spec.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { by, device, element, expect } from 'detox';
1+
import { by, device, element, expect, waitFor } from 'detox';
22
import { matchLoadInfo } from '../utils/matchLoadInfo';
33
import cp from 'child_process';
44

@@ -20,7 +20,9 @@ describe(':android:Storage Types', () => {
2020

2121
await expect(element(by.text('Save'))).toBeVisible();
2222
await element(by.text('Save')).tap();
23-
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
23+
await waitFor(element(by.text(/^Credentials saved! .*$/)))
24+
.toExist()
25+
.withTimeout(3000);
2426
await element(by.text('Load')).tap();
2527
await matchLoadInfo(
2628
'testUsernameAESCBC',
@@ -46,7 +48,9 @@ describe(':android:Storage Types', () => {
4648
cp.spawnSync('adb', ['-e', 'emu', 'finger', 'touch', '1']);
4749
}, 1000);
4850
await element(by.text('Save')).tap();
49-
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
51+
await waitFor(element(by.text(/^Credentials saved! .*$/)))
52+
.toExist()
53+
.withTimeout(3000);
5054
setTimeout(() => {
5155
cp.spawnSync('adb', ['-e', 'emu', 'finger', 'touch', '1']);
5256
}, 1000);
@@ -78,7 +82,9 @@ describe(':android:Storage Types', () => {
7882

7983
await expect(element(by.text('Save'))).toBeVisible();
8084
await element(by.text('Save')).tap();
81-
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
85+
await waitFor(element(by.text(/^Credentials saved! .*$/)))
86+
.toExist()
87+
.withTimeout(3000);
8288
await element(by.text('Load')).tap();
8389
await matchLoadInfo(
8490
'testUsernameAESGCMNoAuth',
@@ -102,12 +108,14 @@ describe(':android:Storage Types', () => {
102108

103109
await expect(element(by.text('Save'))).toBeVisible();
104110
await element(by.text('Save')).tap();
105-
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
111+
await waitFor(element(by.text(/^Credentials saved! .*$/)))
112+
.toExist()
113+
.withTimeout(3000);
106114
setTimeout(() => {
107115
cp.spawnSync('adb', ['-e', 'emu', 'finger', 'touch', '1']);
108116
}, 1000);
109117
await element(by.text('Load')).tap();
110-
await expect(element(by.text(/^Credentials loaded! .*$/))).toBeVisible();
118+
await expect(element(by.text(/^Credentials loaded! .*$/))).toExist();
111119
await matchLoadInfo(
112120
'testUsernameRSA',
113121
'testPasswordRSA',
@@ -122,6 +130,6 @@ describe(':android:Storage Types', () => {
122130
// Hide keyboard
123131

124132
await element(by.text('Reset')).tap();
125-
await expect(element(by.text(/^Credentials Reset!$/))).toBeVisible();
133+
await expect(element(by.text(/^Credentials Reset!$/))).toExist();
126134
});
127135
});

0 commit comments

Comments
 (0)