From 5cf736eb88b1922dbc276083545728791e7ba828 Mon Sep 17 00:00:00 2001 From: Overtorment Date: Wed, 18 Mar 2020 15:38:52 +0000 Subject: [PATCH] OPS: improve CI (#894) * OPS: improve CI --- .circleci/config.yml | 2 +- .travis.yml | 51 +++++++------------ BlueComponents.js | 4 ++ README.md | 1 + android/app/build.gradle | 1 - package-lock.json | 28 +++++----- package.json | 8 +-- screen/settings/settings.js | 7 ++- screen/wallets/add.js | 3 ++ screen/wallets/list.js | 6 ++- screen/wallets/pleaseBackup.js | 10 ++-- tests/e2e/addWallet.spec.js | 51 +++++++++++++++++-- tests/e2e/android-wait-for-emulator.sh | 2 +- tests/e2e/detox-prepare-android-emu.sh | 4 +- tests/e2e/init.js | 1 - tests/e2e/upload-artifacts.sh | 16 ++++++ .../hd-segwit-bech32-transaction.test.js | 7 +-- 17 files changed, 128 insertions(+), 74 deletions(-) mode change 100644 => 100755 tests/e2e/detox-prepare-android-emu.sh create mode 100755 tests/e2e/upload-artifacts.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index 275b4bda..54e9d6a1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,7 +12,7 @@ jobs: - restore_cache: key: node_modules-{{ checksum "package-lock.json" }} - - run: npm i + - run: test -d node_modules || npm i - save_cache: key: node_modules-{{ checksum "package-lock.json" }} diff --git a/.travis.yml b/.travis.yml index f7b1ecd0..84315606 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,12 @@ -# stolen from https://github.com/andstatus/todoagenda/blob/master/.travis.yml +# stolen from: +# https://github.com/andstatus/todoagenda/blob/master/.travis.yml +# https://travis-ci.org/github/andstatus/todoagenda/jobs/662342170/config -# Based on https://travis-ci.org/ankidroid/Anki-Android/builds/624268367 -# See also https://travis-ci.community/t/is-android-28-emulator-supported/1718/6 sudo: true language: bash # ignored on non-linux platforms, but bionic is required for nested virtualization dist: bionic -stages: - - install - - unit_test # custom stage defined in jobs::include section - - test - - finalize_coverage # custom stage defined in jobs::include section - - cache - env: global: - NODE_VERSION=stable @@ -29,36 +22,29 @@ env: - TOOLS=${ANDROID_HOME}/tools # PATH order is incredibly important. e.g. the 'emulator' script exists in more than one place! - PATH=${ANDROID_HOME}:${ANDROID_HOME}/emulator:${TOOLS}:${TOOLS}/bin:${ANDROID_HOME}/platform-tools:${PATH} - - UNIT_TEST=FALSE # by default we don't run the unit tests, they are run only in specific builds - - FINALIZE_COVERAGE=FALSE # by default we don't finalize coverage, it is done in one specific build matrix: - API=28 before_install: - # This section may run on all platforms, and may run for unit tests or for coverage finalization - # It should not make assumptions about os platform or desired tool installation - - # Set up JDK 8 for Android SDK - Java is universally needed: codacy, unit tests, emulators + # Set up JDK 8 for Android SDK - curl "${GRAVIS}.install-jdk-travis.sh" --output ~/.install-jdk-travis.sh - export TARGET_JDK="${JDK}" - JDK="1.8" - source ~/.install-jdk-travis.sh - # Set up Android SDK - this is needed everywhere but coverage finalization, so toggle on that - - if [ "$FINALIZE_COVERAGE" = "FALSE" ]; then wget -q "${ANDROID_TOOLS_URL}" -O android-sdk-tools.zip; fi - - if [ "$FINALIZE_COVERAGE" = "FALSE" ]; then unzip -q android-sdk-tools.zip -d ${ANDROID_HOME}; fi - - if [ "$FINALIZE_COVERAGE" = "FALSE" ]; then rm android-sdk-tools.zip; fi - - if [ "$FINALIZE_COVERAGE" = "FALSE" ]; then mkdir ~/.android; fi # avoid harmless sdkmanager warning - - if [ "$FINALIZE_COVERAGE" = "FALSE" ]; then echo 'count=0' > ~/.android/repositories.cfg; fi # avoid harmless sdkmanager warning - - if [ "$FINALIZE_COVERAGE" = "FALSE" ]; then yes | sdkmanager --licenses >/dev/null; fi # accept all sdkmanager warnings - - if [ "$FINALIZE_COVERAGE" = "FALSE" ]; then echo y | sdkmanager --no_https "platform-tools" >/dev/null; fi - - if [ "$FINALIZE_COVERAGE" = "FALSE" ]; then echo y | sdkmanager --no_https "tools" >/dev/null; fi # A second time per Travis docs, gets latest versions - - if [ "$FINALIZE_COVERAGE" = "FALSE" ]; then echo y | sdkmanager --no_https "build-tools;${ANDROID_BUILD_TOOLS}" >/dev/null; fi # Implicit gradle dependency - gradle drives changes - - if [ "$FINALIZE_COVERAGE" = "FALSE" ]; then echo y | sdkmanager --no_https "platforms;android-${COMPILE_API}" >/dev/null; fi # We need the API of the current compileSdkVersion from gradle.properties + # Set up Android SDK + - wget -q "${ANDROID_TOOLS_URL}" -O android-sdk-tools.zip + - unzip -q android-sdk-tools.zip -d ${ANDROID_HOME} + - rm android-sdk-tools.zip + - mkdir ~/.android # avoid harmless sdkmanager warning + - echo 'count=0' > ~/.android/repositories.cfg # avoid harmless sdkmanager warning + - yes | sdkmanager --licenses >/dev/null # accept all sdkmanager warnings + - echo y | sdkmanager --no_https "platform-tools" >/dev/null + - echo y | sdkmanager --no_https "tools" >/dev/null # A second time per Travis docs, gets latest versions + - echo y | sdkmanager --no_https "build-tools;${ANDROID_BUILD_TOOLS}" >/dev/null # Implicit gradle dependency - gradle drives changes + - echo y | sdkmanager --no_https "platforms;android-${COMPILE_API}" >/dev/null # We need the API of the current compileSdkVersion from gradle.properties install: - # In our setup, install only runs on matrix entries we want full emulator tests on - # That only happens currently on linux, so this section can assume linux + emulator is desired # Download required emulator tools - echo y | sdkmanager --no_https "platforms;android-$API" >/dev/null # We need the API of the emulator we will run - echo y | sdkmanager --no_https "emulator" >/dev/null @@ -70,14 +56,14 @@ install: - sudo adduser $USER kvm # Create an Android emulator - - echo no | avdmanager create avd --force -n Pixel_API_28_AOSP -k "system-images;android-$API;$EMU_FLAVOR;$ABI" -c 10M + - echo no | avdmanager create avd --force -n Pixel_API_29_AOSP -k "system-images;android-$API;$EMU_FLAVOR;$ABI" -c 10M - | EMU_PARAMS="-verbose -no-snapshot -no-window -camera-back none -camera-front none -selinux permissive -qemu -m 2048" EMU_COMMAND="emulator" # This double "sudo" monstrosity is used to have Travis execute the # emulator with its new group permissions and help preserve the rule # of least privilege. - sudo -E sudo -u $USER -E bash -c "${ANDROID_HOME}/emulator/${EMU_COMMAND} -avd Pixel_API_28_AOSP ${AUDIO} ${EMU_PARAMS} &" + sudo -E sudo -u $USER -E bash -c "${ANDROID_HOME}/emulator/${EMU_COMMAND} -avd Pixel_API_29_AOSP ${AUDIO} ${EMU_PARAMS} &" # Wait for emulator to be ready - chmod +x ./tests/e2e/android-wait-for-emulator.sh @@ -96,11 +82,12 @@ install: script: - echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p - - printf "\nhw.lcd.height=1920\nhw.lcd.width=1080\nhw.lcd.density=161\nskin.name=240x426" >> /home/travis/.android/avd/Pixel_API_28_AOSP.avd/config.ini + - printf "\nhw.lcd.height=1920\nhw.lcd.width=1080\nhw.lcd.density=320\nskin.name=1080x1920" >> /home/travis/.android/avd/Pixel_API_29_AOSP.avd/config.ini - npm i - npm i -g detox-cli - npm run e2e:release +after_failure: ./tests/e2e/upload-artifacts.sh before_cache: - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock diff --git a/BlueComponents.js b/BlueComponents.js index 79a89091..debb06c7 100644 --- a/BlueComponents.js +++ b/BlueComponents.js @@ -88,6 +88,7 @@ export class BitcoinButton extends Component { render() { return ( { // eslint-disable-next-line if (this.props.onPress) this.props.onPress(); @@ -576,6 +577,7 @@ export class BlueListItem extends Component { render() { return ( { if (this.handleClick) { @@ -1924,6 +1927,7 @@ export class WalletsCarousel extends Component { shadowRadius={5} > { {BlueApp.getWallets().length > 1 && ( navigate('DefaultView')} title="On Launch" /> )} - navigate('EncryptStorage')} component={TouchableOpacity} /> + navigate('EncryptStorage')} + component={TouchableOpacity} + /> {biometrics.isDeviceBiometricCapable && ( { Keyboard.dismiss(); @@ -225,6 +227,7 @@ export default class WalletsAdd extends Component { > {!this.state.isLoading ? ( { diff --git a/screen/wallets/list.js b/screen/wallets/list.js index 82ff981c..fcfc7ac2 100644 --- a/screen/wallets/list.js +++ b/screen/wallets/list.js @@ -315,7 +315,11 @@ export default class WalletsList extends Component { renderNavigationHeader = () => { return ( - this.props.navigation.navigate('Settings')}> + this.props.navigation.navigate('Settings')} + > diff --git a/screen/wallets/pleaseBackup.js b/screen/wallets/pleaseBackup.js index a45be68c..3138d552 100644 --- a/screen/wallets/pleaseBackup.js +++ b/screen/wallets/pleaseBackup.js @@ -53,10 +53,10 @@ export default class PleaseBackup extends Component { return ( - + {loc.pleasebackup.success} - {loc.pleasebackup.text} + {loc.pleasebackup.text} @@ -405,10 +405,10 @@ export default class PleaseBackup extends Component { - + - this.props.navigation.dismiss()} title={loc.pleasebackup.ok} /> + this.props.navigation.dismiss()} title={loc.pleasebackup.ok} /> diff --git a/tests/e2e/addWallet.spec.js b/tests/e2e/addWallet.spec.js index 96febed5..1bb1bad7 100644 --- a/tests/e2e/addWallet.spec.js +++ b/tests/e2e/addWallet.spec.js @@ -1,11 +1,54 @@ -/* global it, describe, expect, element, by */ +/* global it, describe, expect, element, by, waitFor, device */ describe('BlueWallet UI Tests', () => { - it('Shows Wallets List screen', async () => { - await expect(element(by.id('WalletsList'))).toBeVisible(); + it('can launch', async () => { + await waitFor(element(by.id('WalletsList'))) + .toBeVisible() + .withTimeout(4000); + }); + + it.skip('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 + + await expect(element(by.id('EncryptStorageButton'))).toBeVisible(); }); - it('Shows Wallets List screen', async () => { + 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 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 device.terminateApp(); + await device.launchApp({ newInstance: true }); + await waitFor(element(by.id('WalletsList'))) + .toBeVisible() + .withTimeout(10000); + await expect(element(by.id('cr34t3d'))).toBeVisible(); }); }); diff --git a/tests/e2e/android-wait-for-emulator.sh b/tests/e2e/android-wait-for-emulator.sh index 6c4ee960..cc645b21 100644 --- a/tests/e2e/android-wait-for-emulator.sh +++ b/tests/e2e/android-wait-for-emulator.sh @@ -6,7 +6,7 @@ set +e bootanim="" failcounter=0 -timeout_in_sec=600 # 10 minutes +timeout_in_sec=300 # 5 minutes until [[ "$bootanim" =~ "stopped" ]]; do bootanim=`adb -e shell getprop init.svc.bootanim 2>&1 &` diff --git a/tests/e2e/detox-prepare-android-emu.sh b/tests/e2e/detox-prepare-android-emu.sh old mode 100644 new mode 100755 index a7d983dc..cef78ee9 --- a/tests/e2e/detox-prepare-android-emu.sh +++ b/tests/e2e/detox-prepare-android-emu.sh @@ -1,2 +1,4 @@ $ANDROID_HOME/tools/bin/sdkmanager "system-images;android-28;default;x86_64" -$ANDROID_HOME/tools/bin/avdmanager create avd -n Pixel_API_28_AOSP -d pixel --package "system-images;android-28;default;x86_64" \ No newline at end of file +echo no | $ANDROID_HOME/tools/bin/sdkmanager --licenses +echo no | $ANDROID_HOME/tools/bin/avdmanager create avd -n Pixel_API_29_AOSP --force --package "system-images;android-28;default;x86_64" +printf "\nhw.lcd.height=1920\nhw.lcd.width=1080\nhw.lcd.density=320\nskin.name=1080x1920" >> ~/.android/avd/Pixel_API_29_AOSP.avd/config.ini \ No newline at end of file diff --git a/tests/e2e/init.js b/tests/e2e/init.js index 3da3dc1b..04167f10 100644 --- a/tests/e2e/init.js +++ b/tests/e2e/init.js @@ -25,7 +25,6 @@ beforeAll(async () => { beforeEach(async () => { await device.launchApp({ newInstance: true }); - console.log('sleeping for logo animation...'); await sleep(2000); await adapter.beforeEach(); }); diff --git a/tests/e2e/upload-artifacts.sh b/tests/e2e/upload-artifacts.sh new file mode 100755 index 00000000..ffb0f75b --- /dev/null +++ b/tests/e2e/upload-artifacts.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +echo uploading artifacts... +cp ./android/app/build/outputs/apk/release/app-release.apk ./artifacts/ +cp ./android/app/build/outputs/apk/androidTest/release/app-release-androidTest.apk ./artifacts/ +cp ~/.android/avd/Pixel_API_29_AOSP.avd/config.ini ./artifacts/ +tar -cvzf artifacts.tar.gz artifacts +FILENAME="artifacts.tar.gz" +HASH=`date +%s` +FILENAME_UNIQ="$HASH.tar.gz" +cp "$FILENAME" "$FILENAME_UNIQ" +curl "http://filestorage.bluewallet.io:1488/upload.php" -F "fileToUpload=@$FILENAME_UNIQ" +rm "$FILENAME_UNIQ" +DLOAD="http://filestorage.bluewallet.io:1488/$HASH.tar.gz" +echo artifacts download link: +echo $DLOAD \ No newline at end of file diff --git a/tests/integration/hd-segwit-bech32-transaction.test.js b/tests/integration/hd-segwit-bech32-transaction.test.js index 148c4358..6ff4851e 100644 --- a/tests/integration/hd-segwit-bech32-transaction.test.js +++ b/tests/integration/hd-segwit-bech32-transaction.test.js @@ -5,6 +5,7 @@ global.crypto = require('crypto'); // shall be used by tests under nodejs CLI, b let assert = require('assert'); global.net = require('net'); // needed by Electrum client. For RN it is proviced in shim.js let BlueElectrum = require('../../BlueElectrum'); +jasmine.DEFAULT_TIMEOUT_INTERVAL = 150 * 1000; afterAll(async () => { // after all tests we close socket so the test suite can actually terminate @@ -20,7 +21,6 @@ beforeAll(async () => { describe('HDSegwitBech32Transaction', () => { it('can decode & check sequence', async function() { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000; let T = new HDSegwitBech32Transaction(null, 'e9ef58baf4cff3ad55913a360c2fa1fd124309c59dcd720cdb172ce46582097b'); assert.strictEqual(await T.getMaxUsedSequence(), 0xffffffff); assert.strictEqual(await T.isSequenceReplaceable(), false); @@ -36,7 +36,6 @@ describe('HDSegwitBech32Transaction', () => { }); it('can tell if its our transaction', async function() { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000; if (!process.env.HD_MNEMONIC_BIP84) { console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); return; @@ -57,7 +56,6 @@ describe('HDSegwitBech32Transaction', () => { }); it('can tell tx info', async function() { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000; if (!process.env.HD_MNEMONIC_BIP84) { console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); return; @@ -97,7 +95,6 @@ describe('HDSegwitBech32Transaction', () => { }); it('can do RBF - cancel tx', async function() { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000; if (!process.env.HD_MNEMONIC_BIP84) { console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); return; @@ -128,7 +125,6 @@ describe('HDSegwitBech32Transaction', () => { }); it('can do RBF - bumpfees tx', async function() { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000; if (!process.env.HD_MNEMONIC_BIP84) { console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); return; @@ -162,7 +158,6 @@ describe('HDSegwitBech32Transaction', () => { }); it('can do CPFP - bump fees', async function() { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000; if (!process.env.HD_MNEMONIC_BIP84) { console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); return;