mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-01-19 05:45:15 +01:00
TST: e2e tests for storage encryption
This commit is contained in:
parent
8df2a8d64b
commit
b1e7378e02
@ -47,6 +47,7 @@ export default class PlausibleDeniability extends Component {
|
||||
<BlueSpacing20 />
|
||||
|
||||
<BlueButton
|
||||
testID="CreateFakeStorageButton"
|
||||
icon={{
|
||||
name: 'shield',
|
||||
type: 'font-awesome',
|
||||
|
@ -304,7 +304,9 @@ export default class Selftest extends Component {
|
||||
if (this.state.isOk) {
|
||||
return (
|
||||
<View style={{ alignItems: 'center' }}>
|
||||
<BlueText h4>OK</BlueText>
|
||||
<BlueText testID="SelfTestOk" h4>
|
||||
OK
|
||||
</BlueText>
|
||||
</View>
|
||||
);
|
||||
} else {
|
||||
|
@ -66,7 +66,7 @@ const About = () => {
|
||||
<BlueLoading />
|
||||
) : (
|
||||
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={{ flex: 1 }}>
|
||||
<ScrollView>
|
||||
<ScrollView testID="AboutScrollView">
|
||||
<BlueCard>
|
||||
<BlueTextCentered h4>BlueWallet is a free and open source Bitcoin wallet. Licensed MIT.</BlueTextCentered>
|
||||
<BlueSpacing20 />
|
||||
@ -130,7 +130,7 @@ const About = () => {
|
||||
<BlueButton onPress={handleOnReleaseNotesPress} title="Release notes" />
|
||||
<BlueSpacing20 />
|
||||
|
||||
<BlueButton onPress={handleOnSelfTestPress} title="Run self test" />
|
||||
<BlueButton onPress={handleOnSelfTestPress} title="Run self test" testID="RunSelfTestButton" />
|
||||
<BlueTextCentered />
|
||||
<BlueTextCentered>
|
||||
{getApplicationName()} ver {getVersion()} (build {getBuildNumber()})
|
||||
|
@ -181,7 +181,11 @@ export default class EncryptStorage extends Component {
|
||||
disabled={!this.state.storageIsEncrypted}
|
||||
onPress={() => this.props.navigation.navigate('PlausibleDeniability')}
|
||||
>
|
||||
<BlueListItem disabled={!this.state.storageIsEncrypted} title={loc.settings.plausible_deniability} />
|
||||
<BlueListItem
|
||||
disabled={!this.state.storageIsEncrypted}
|
||||
title={loc.settings.plausible_deniability}
|
||||
testID="PlausibleDeniabilityButton"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</ScrollView>
|
||||
|
@ -70,7 +70,7 @@ const Settings = () => {
|
||||
</BlueCard>
|
||||
)}
|
||||
|
||||
<BlueListItem title={loc.settings.about} component={TouchableOpacity} onPress={() => navigate('About')} />
|
||||
<BlueListItem title={loc.settings.about} component={TouchableOpacity} onPress={() => navigate('About')} testID="AboutButton" />
|
||||
</ScrollView>
|
||||
</SafeBlueArea>
|
||||
);
|
||||
|
@ -2,72 +2,200 @@
|
||||
|
||||
describe('BlueWallet UI Tests', () => {
|
||||
it('can launch', async () => {
|
||||
await waitFor(element(by.id('WalletsList')))
|
||||
.toBeVisible()
|
||||
.withTimeout(4000);
|
||||
await yo('WalletsList');
|
||||
});
|
||||
|
||||
it('can encrypt storage', async () => {
|
||||
await waitFor(element(by.id('WalletsList')))
|
||||
.toBeVisible()
|
||||
.withTimeout(4000);
|
||||
await expect(element(by.id('SettingsButton'))).toBeVisible();
|
||||
await element(by.id('SettingsButton')).tap(); // detox hanges here
|
||||
it('selftest passes', async () => {
|
||||
await yo('WalletsList');
|
||||
|
||||
// go to settings, press SelfTest and wait for OK
|
||||
await element(by.id('SettingsButton')).tap();
|
||||
await element(by.id('AboutButton')).tap();
|
||||
await element(by.id('AboutScrollView')).swipe('up', 'fast', 1); // in case emu screen is small and it doesnt fit
|
||||
await element(by.id('RunSelfTestButton')).tap();
|
||||
await yo('SelfTestOk', 120 * 1000);
|
||||
});
|
||||
|
||||
it('can encrypt storage, with plausible deniability', async () => {
|
||||
await yo('WalletsList');
|
||||
|
||||
// lets create a wallet
|
||||
await helperCreateWallet();
|
||||
|
||||
// go to settings
|
||||
await expect(element(by.id('SettingsButton'))).toBeVisible();
|
||||
await element(by.id('SettingsButton')).tap();
|
||||
await expect(element(by.id('EncryptStorageButton'))).toBeVisible();
|
||||
// now go to Security page where we will enable encryption
|
||||
|
||||
// go to Security page where we will enable encryption
|
||||
await element(by.id('EncryptStorageButton')).tap();
|
||||
await expect(element(by.id('EncyptedAndPasswordProtected'))).toBeVisible();
|
||||
await expect(element(by.id('PlausibleDeniabilityButton'))).toBeNotVisible();
|
||||
|
||||
if (device.getPlatform() === 'ios') {
|
||||
console.warn('Android only test skipped');
|
||||
return;
|
||||
}
|
||||
|
||||
// lets encrypt the storage.
|
||||
// first, trying to mistype second password:
|
||||
await element(by.type('android.widget.CompoundButton')).tap(); // thats a switch lol
|
||||
await element(by.type('android.widget.EditText')).typeText('08902\n');
|
||||
await element(by.type('android.widget.CompoundButton')).tap(); // thats a switch lol. lets tap it
|
||||
await element(by.type('android.widget.EditText')).typeText('08902');
|
||||
await element(by.text('OK')).tap();
|
||||
await element(by.type('android.widget.EditText')).typeText('666\n');
|
||||
await element(by.type('android.widget.EditText')).typeText('666');
|
||||
await element(by.text('OK')).tap();
|
||||
await expect(element(by.text('Passwords do not match'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
|
||||
// TODO: finish writing this test
|
||||
// now, lets put correct passwords and encrypt the storage
|
||||
await element(by.type('android.widget.CompoundButton')).tap(); // thats a switch lol
|
||||
await element(by.type('android.widget.EditText')).typeText('qqq');
|
||||
await element(by.text('OK')).tap();
|
||||
await element(by.type('android.widget.EditText')).typeText('qqq');
|
||||
await element(by.text('OK')).tap();
|
||||
|
||||
// relaunch app
|
||||
await device.terminateApp();
|
||||
await device.launchApp({ newInstance: true });
|
||||
await sleep(2000);
|
||||
await waitFor(element(by.text('OK')))
|
||||
.toBeVisible()
|
||||
.withTimeout(4000);
|
||||
|
||||
// trying to decrypt with wrong password
|
||||
await expect(element(by.text('Your storage is encrypted. Password is required to decrypt it'))).toBeVisible();
|
||||
await element(by.type('android.widget.EditText')).typeText('wrong');
|
||||
await element(by.text('OK')).tap();
|
||||
await expect(element(by.text('Wrong password, please try again.'))).toBeVisible();
|
||||
|
||||
// correct password
|
||||
await element(by.type('android.widget.EditText')).typeText('qqq');
|
||||
await element(by.text('OK')).tap();
|
||||
await yo('WalletsList');
|
||||
|
||||
// previously created wallet should be visible
|
||||
await expect(element(by.id('cr34t3d'))).toBeVisible();
|
||||
|
||||
// now lets enable plausible deniability feature
|
||||
|
||||
// go to settings -> security screen -> plausible deniability screen
|
||||
await element(by.id('SettingsButton')).tap();
|
||||
await expect(element(by.id('EncryptStorageButton'))).toBeVisible();
|
||||
await element(by.id('EncryptStorageButton')).tap();
|
||||
await expect(element(by.id('EncyptedAndPasswordProtected'))).toBeVisible();
|
||||
await expect(element(by.id('PlausibleDeniabilityButton'))).toBeVisible();
|
||||
await element(by.id('PlausibleDeniabilityButton')).tap();
|
||||
|
||||
// trying to enable plausible denability
|
||||
await element(by.id('CreateFakeStorageButton')).tap();
|
||||
await expect(element(by.text('Password for fake storage should not match password for your main storage'))).toBeVisible();
|
||||
|
||||
// trying MAIN password: should fail, obviously
|
||||
await element(by.type('android.widget.EditText')).typeText('qqq');
|
||||
await element(by.text('OK')).tap();
|
||||
await expect(element(by.text('Password is currently in use. Please, try a different password.'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
|
||||
// trying new password, but will mistype
|
||||
await element(by.id('CreateFakeStorageButton')).tap();
|
||||
await element(by.type('android.widget.EditText')).typeText('passwordForFakeStorage');
|
||||
await element(by.text('OK')).tap();
|
||||
await expect(element(by.text('Retype password'))).toBeVisible();
|
||||
await element(by.type('android.widget.EditText')).typeText('passwordForFakeStorageWithTypo'); // retyping with typo
|
||||
await element(by.text('OK')).tap();
|
||||
await expect(element(by.text('Passwords do not match, try again'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
|
||||
// trying new password
|
||||
await element(by.id('CreateFakeStorageButton')).tap();
|
||||
await element(by.type('android.widget.EditText')).typeText('passwordForFakeStorage');
|
||||
await element(by.text('OK')).tap();
|
||||
await expect(element(by.text('Retype password'))).toBeVisible();
|
||||
await element(by.type('android.widget.EditText')).typeText('passwordForFakeStorage'); // retyping
|
||||
await element(by.text('OK')).tap();
|
||||
|
||||
await expect(element(by.text('Success'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
|
||||
// created fake storage.
|
||||
// creating a wallet inside this fake storage
|
||||
await helperCreateWallet('fake_wallet');
|
||||
|
||||
// relaunch the app, unlock with fake password, expect to see fake wallet
|
||||
|
||||
// relaunch app
|
||||
await device.terminateApp();
|
||||
await device.launchApp({ newInstance: true });
|
||||
await sleep(2000);
|
||||
await waitFor(element(by.text('OK')))
|
||||
.toBeVisible()
|
||||
.withTimeout(4000);
|
||||
//
|
||||
await expect(element(by.text('Your storage is encrypted. Password is required to decrypt it'))).toBeVisible();
|
||||
await element(by.type('android.widget.EditText')).typeText('qqq');
|
||||
await element(by.text('OK')).tap();
|
||||
await yo('WalletsList');
|
||||
|
||||
// previously created wallet IN MAIN STORAGE should be visible
|
||||
await expect(element(by.id('cr34t3d'))).toBeVisible();
|
||||
|
||||
// relaunch app
|
||||
await device.terminateApp();
|
||||
await device.launchApp({ newInstance: true });
|
||||
await sleep(3000);
|
||||
//
|
||||
await expect(element(by.text('Your storage is encrypted. Password is required to decrypt it'))).toBeVisible();
|
||||
await element(by.type('android.widget.EditText')).typeText('passwordForFakeStorage');
|
||||
await element(by.text('OK')).tap();
|
||||
await yo('WalletsList');
|
||||
|
||||
// previously created wallet in FAKE storage should be visible
|
||||
await expect(element(by.id('fake_wallet'))).toBeVisible();
|
||||
});
|
||||
|
||||
it('can create wallet, reload app and it persists', async () => {
|
||||
await waitFor(element(by.id('WalletsList')))
|
||||
.toBeVisible()
|
||||
.withTimeout(4000);
|
||||
await element(by.id('CreateAWallet')).tap();
|
||||
await element(by.id('WalletNameInput')).typeText('cr34t3d\n');
|
||||
await waitFor(element(by.id('ActivateBitcoinButton')))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000);
|
||||
await element(by.id('ActivateBitcoinButton')).tap();
|
||||
await element(by.id('ActivateBitcoinButton')).tap();
|
||||
// why tf we need 2 taps for it to work..? mystery
|
||||
await element(by.id('Create')).tap();
|
||||
await yo('WalletsList');
|
||||
|
||||
await waitFor(element(by.id('PleaseBackupScrollView')))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000);
|
||||
|
||||
await element(by.id('PleaseBackupScrollView')).swipe('up', 'fast', 1); // in case emu screen is small and it doesnt fit
|
||||
|
||||
await waitFor(element(by.id('PleasebackupOk')))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000);
|
||||
await element(by.id('PleasebackupOk')).tap();
|
||||
await expect(element(by.id('WalletsList'))).toBeVisible();
|
||||
await expect(element(by.id('cr34t3d'))).toBeVisible();
|
||||
await helperCreateWallet();
|
||||
|
||||
await device.terminateApp();
|
||||
await device.launchApp({ newInstance: true });
|
||||
await waitFor(element(by.id('WalletsList')))
|
||||
.toBeVisible()
|
||||
.withTimeout(10000);
|
||||
await yo('WalletsList');
|
||||
await expect(element(by.id('cr34t3d'))).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
async function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function yo(id, timeout = 10000) {
|
||||
return waitFor(element(by.id(id)))
|
||||
.toBeVisible()
|
||||
.withTimeout(timeout);
|
||||
}
|
||||
|
||||
async function helperCreateWallet(walletName) {
|
||||
await element(by.id('CreateAWallet')).tap();
|
||||
await element(by.id('WalletNameInput')).typeText(walletName || 'cr34t3d');
|
||||
await waitFor(element(by.id('ActivateBitcoinButton')))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000);
|
||||
await element(by.id('ActivateBitcoinButton')).tap();
|
||||
await element(by.id('ActivateBitcoinButton')).tap();
|
||||
// why tf we need 2 taps for it to work..? mystery
|
||||
await element(by.id('Create')).tap();
|
||||
|
||||
await waitFor(element(by.id('PleaseBackupScrollView')))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000);
|
||||
|
||||
await element(by.id('PleaseBackupScrollView')).swipe('up', 'fast', 1); // in case emu screen is small and it doesnt fit
|
||||
|
||||
await waitFor(element(by.id('PleasebackupOk')))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000);
|
||||
await element(by.id('PleasebackupOk')).tap();
|
||||
await expect(element(by.id('WalletsList'))).toBeVisible();
|
||||
await expect(element(by.id(walletName || 'cr34t3d'))).toBeVisible();
|
||||
}
|
||||
|
@ -17,13 +17,15 @@ jasmine.getEnv().addReporter(specReporter);
|
||||
jasmine.getEnv().addReporter(assignReporter);
|
||||
|
||||
// Set the default timeout
|
||||
jest.setTimeout(90000);
|
||||
jest.setTimeout(180000);
|
||||
|
||||
beforeAll(async () => {
|
||||
await detox.init(config, { launchApp: false });
|
||||
}, 300000);
|
||||
|
||||
beforeEach(async () => {
|
||||
await device.uninstallApp();
|
||||
await device.installApp();
|
||||
await device.launchApp({ newInstance: true });
|
||||
await sleep(2000);
|
||||
await adapter.beforeEach();
|
||||
|
Loading…
Reference in New Issue
Block a user