Skip to content

Commit

Permalink
test: add new e2e test scenarios
Browse files Browse the repository at this point in the history
  • Loading branch information
DorianMazur committed Oct 23, 2024
1 parent 24a0fd7 commit f846420
Show file tree
Hide file tree
Showing 14 changed files with 445 additions and 237 deletions.
1 change: 1 addition & 0 deletions .github/workflows/e2e_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ jobs:
avd-name: TestingAVD
script: |
cd KeychainExample
./e2e/utils/enrollFingerprintAndroid.sh
yarn test:android:run
env:
API_LEVEL: ${{ matrix.api-level }}
Expand Down
3 changes: 2 additions & 1 deletion KeychainExample/e2e/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ module.exports = {
maxWorkers: 1,
globalSetup: 'detox/runners/jest/globalSetup',
globalTeardown: 'detox/runners/jest/globalTeardown',
testEnvironment: 'detox/runners/jest/testEnvironment',
setupFilesAfterEnv: ['<rootDir>/e2e/setup.ts'],
reporters: [
'detox/runners/jest/reporter',
['jest-junit', { outputDirectory: 'e2e/output', outputName: 'report.xml' }],
],
testEnvironment: 'detox/runners/jest/testEnvironment',
verbose: true,
};
12 changes: 12 additions & 0 deletions KeychainExample/e2e/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { device } from 'detox';

beforeAll(async () => {
if (device.getPlatform() === 'ios') {
await device.setBiometricEnrollment(true);
}
});

afterAll(async () => {
await device.uninstallApp();
await device.installApp();
});
154 changes: 154 additions & 0 deletions KeychainExample/e2e/testCases/acessControlTest.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { by, device, element, expect } from 'detox';
import { matchLoadInfo } from '../utils/matchLoadInfo';
import cp from 'child_process';

describe('Access Control', () => {
beforeEach(async () => {
await device.launchApp({ newInstance: true });
});
['genericPassword', 'internetCredentials'].forEach((type) => {
it(
' should save and retrieve username and password with biometrics - ' +
type,
async () => {
await expect(element(by.text('Keychain Example'))).toExist();
await element(by.id('usernameInput')).typeText(
'testUsernameBiometrics'
);
await element(by.id('passwordInput')).typeText(
'testPasswordBiometrics'
);
// Hide keyboard
await element(by.text('Keychain Example')).tap();

if (device.getPlatform() === 'android') {
await element(by.text('Fingerprint')).tap();
await element(by.text('Software')).tap();
} else {
await element(by.text('FaceID')).tap();
}

await expect(element(by.text('Save'))).toBeVisible();
await element(by.text('Save')).tap();
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
// Biometric prompt is not available in the IOS simulator
// https://github.com/oblador/react-native-keychain/issues/340
if (device.getPlatform() === 'android') {
setTimeout(() => {
cp.spawnSync('adb', ['-e', 'emu', 'finger', 'touch', '1']);
}, 1000);
}
await element(by.text('Load')).tap();
await matchLoadInfo('testUsernameBiometrics', 'testPasswordBiometrics');
}
);

it(
'should retrieve username and password after app launch with biometrics - ' +
type,
async () => {
await expect(element(by.text('Keychain Example'))).toExist();
await expect(
element(by.text('hasGenericPassword: true'))
).toBeVisible();
// Biometric prompt is not available in the IOS simulator
// https://github.com/oblador/react-native-keychain/issues/340
if (device.getPlatform() === 'android') {
setTimeout(() => {
cp.spawnSync('adb', ['-e', 'emu', 'finger', 'touch', '1']);
}, 1000);
}
await element(by.text('Load')).tap();
await matchLoadInfo('testUsernameBiometrics', 'testPasswordBiometrics');
}
);

it(
':android:should save and retrieve username and password with biometrics for hardware security level - ' +
type,
async () => {
await expect(element(by.text('Keychain Example'))).toExist();
await element(by.id('usernameInput')).typeText('testUsernameHardware');
await element(by.id('passwordInput')).typeText('testPasswordHardware');
// Hide keyboard
await element(by.text('Keychain Example')).tap();
await element(by.text('Fingerprint')).tap();
await element(by.text('Hardware')).tap();

await expect(element(by.text('Save'))).toBeVisible();
await element(by.text('Save')).tap();
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();

setTimeout(() => {
cp.spawnSync('adb', ['-e', 'emu', 'finger', 'touch', '1']);
}, 1000);

await element(by.text('Load')).tap();
await matchLoadInfo('testUsernameHardware', 'testPasswordHardware');
}
);

it(
':android:should save and retrieve username and password with biometrics for software security level - ' +
type,
async () => {
await expect(element(by.text('Keychain Example'))).toExist();
await element(by.id('usernameInput')).typeText('testUsernameSoftware');
await element(by.id('passwordInput')).typeText('testPasswordSoftware');
// Hide keyboard
await element(by.text('Keychain Example')).tap();
await element(by.text('Fingerprint')).tap();
await element(by.text('Software')).tap();

await expect(element(by.text('Save'))).toBeVisible();
await element(by.text('Save')).tap();
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();

setTimeout(() => {
cp.spawnSync('adb', ['-e', 'emu', 'finger', 'touch', '1']);
}, 1000);

await element(by.text('Load')).tap();
await matchLoadInfo('testUsernameSoftware', 'testPasswordSoftware');
}
);

it(
'should save and retrieve username and password without biometrics' +
type,
async () => {
await expect(element(by.text('Keychain Example'))).toExist();
await element(by.id('usernameInput')).typeText('testUsernameAny');
await element(by.id('passwordInput')).typeText('testPasswordAny');
// Hide keyboard
await element(by.text('Keychain Example')).tap();
await element(by.text('None')).tap();

if (device.getPlatform() === 'android') {
await element(by.text('Software')).tap();
}

await expect(element(by.text('Save'))).toBeVisible();
await element(by.text('Save')).tap();
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
await element(by.text('Load')).tap();
await matchLoadInfo('testUsernameAny', 'testPasswordAny');
}
);

it('should retrieve username and password after app launch without biometrics', async () => {
await expect(element(by.text('Keychain Example'))).toExist();
await expect(element(by.text('hasGenericPassword: true'))).toBeVisible();
await element(by.text('Load')).tap();
await matchLoadInfo('testUsernameAny', 'testPasswordAny');
});
});

it('should reset all credentials', async () => {
await expect(element(by.text('Keychain Example'))).toExist();
// Hide keyboard

await element(by.text('Reset')).tap();
await expect(element(by.text(/^Credentials Reset!$/))).toBeVisible();
});
});
77 changes: 0 additions & 77 deletions KeychainExample/e2e/testCases/biometricsAccessControlTest.spec.js

This file was deleted.

34 changes: 0 additions & 34 deletions KeychainExample/e2e/testCases/noneAccessControTest.spec.js

This file was deleted.

92 changes: 92 additions & 0 deletions KeychainExample/e2e/testCases/securityLevelTest.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { by, device, element, expect } from 'detox';
import { matchLoadInfo } from '../utils/matchLoadInfo';

describe(':android:Security Level', () => {
beforeEach(async () => {
await device.launchApp({ newInstance: true });
});
['genericPassword', 'internetCredentials'].forEach((type) => {
it(':android:should save with Any security level - ' + type, async () => {
await expect(element(by.text('Keychain Example'))).toExist();
await element(by.id('usernameInput')).typeText('testUsernameAny');
await element(by.id('passwordInput')).typeText('testPasswordAny');
// Hide keyboard
await element(by.text('Keychain Example')).tap();

await element(by.text(type)).tap();
await element(by.text('None')).tap();
await element(by.text('Any')).tap();

await expect(element(by.text('Save'))).toBeVisible();
await element(by.text('Save')).tap();
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
await element(by.text('Load')).tap();
await matchLoadInfo(
'testUsernameAny',
'testPasswordAny',
undefined,
type === 'internetCredentials' ? 'https://example.com' : undefined
);
});

it(
':android:should save with Software security level - ' + type,
async () => {
await expect(element(by.text('Keychain Example'))).toExist();
await element(by.id('usernameInput')).typeText('testUsernameSoftware');
await element(by.id('passwordInput')).typeText('testPasswordSoftware');
// Hide keyboard
await element(by.text('Keychain Example')).tap();

await element(by.text(type)).tap();
await element(by.text('None')).tap();
await element(by.text('Software')).tap();

await expect(element(by.text('Save'))).toBeVisible();
await element(by.text('Save')).tap();
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
await element(by.text('Load')).tap();
await matchLoadInfo(
'testUsernameSoftware',
'testPasswordSoftware',
undefined,
type === 'internetCredentials' ? 'https://example.com' : undefined
);
}
);

it(
':android:should save with Hardware security level - ' + type,
async () => {
await expect(element(by.text('Keychain Example'))).toExist();
await element(by.id('usernameInput')).typeText('testUsernameHardware');
await element(by.id('passwordInput')).typeText('testPasswordHardware');
// Hide keyboard
await element(by.text('Keychain Example')).tap();

await element(by.text(type)).tap();
await element(by.text('None')).tap();
await element(by.text('Hardware')).tap();

await expect(element(by.text('Save'))).toBeVisible();
await element(by.text('Save')).tap();
await expect(element(by.text(/^Credentials saved! .*$/))).toBeVisible();
await element(by.text('Load')).tap();
await matchLoadInfo(
'testUsernameHardware',
'testPasswordHardware',
undefined,
type === 'internetCredentials' ? 'https://example.com' : undefined
);
}
);
});

it(':android:should reset all credentials', async () => {
await expect(element(by.text('Keychain Example'))).toExist();
// Hide keyboard

await element(by.text('Reset')).tap();
await expect(element(by.text(/^Credentials Reset!$/))).toBeVisible();
});
});
Loading

0 comments on commit f846420

Please sign in to comment.