TST: jest27, remove jasmine, bump detox, split circleci

Co-authored-by: Ivan Vershigora <ivan.vershigora@gmail.com>
This commit is contained in:
Overtorment 2022-06-03 17:54:05 +01:00 committed by GitHub
parent 6ac594785e
commit 5d4a25840b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 3189 additions and 8933 deletions

View File

@ -1,8 +1,9 @@
version: 2 version: 2.1
jobs: jobs:
build:
lint:
docker: docker:
- image: circleci/node:16.13.1 - image: cimg/node:16.15.0
working_directory: ~/repo working_directory: ~/repo
@ -20,4 +21,60 @@ jobs:
- node_modules - node_modules
# run tests! # run tests!
- run: npm t || npm t || npm t - run:
command: npm run tslint && npm run lint
unit:
docker:
- image: cimg/node:16.15.0
working_directory: ~/repo
steps:
- checkout
- restore_cache:
key: node_modules-{{ checksum "package-lock.json" }}
- run: test -d node_modules || npm i
- save_cache:
key: node_modules-{{ checksum "package-lock.json" }}
paths:
- node_modules
# run tests!
- run:
command: npm run unit
integration:
docker:
- image: cimg/node:16.15.0
working_directory: ~/repo
steps:
- checkout
- restore_cache:
key: node_modules-{{ checksum "package-lock.json" }}
- run: test -d node_modules || npm i
- save_cache:
key: node_modules-{{ checksum "package-lock.json" }}
paths:
- node_modules
# run tests!
- run:
command: npm run jest || npm run jest || npm run jest
# Orchestrate our job run sequence
workflows:
build_and_test:
jobs:
- lint
- unit
- integration

51
.detoxrc.json Normal file
View File

@ -0,0 +1,51 @@
{
"testRunner": "jest",
"runnerConfig": "tests/e2e/config.json",
"skipLegacyWorkersInjection": true,
"apps": {
"ios": {
"type": "ios.app",
"binaryPath": "SPECIFY_PATH_TO_YOUR_APP_BINARY",
"build": "xcodebuild clean build -workspace ios/BlueWallet.xcworkspace -scheme BlueWallet -configuration Release -derivedDataPath ios/build -sdk iphonesimulator13.2"
},
"android.debug": {
"type": "android.apk",
"binaryPath": "android/app/build/outputs/apk/debug/app-debug.apk",
"build": "cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && cd .."
},
"android.release": {
"type": "android.apk",
"testBinaryPath": "android/app/build/outputs/apk/androidTest/release/app-release-androidTest.apk",
"binaryPath": "android/app/build/outputs/apk/release/app-release.apk",
"build": "find android | grep '\\.apk' --color=never | xargs -l rm\n\n# creating fresh keystore\nrm detox.keystore\nkeytool -genkeypair -v -keystore detox.keystore -alias detox -keyalg RSA -keysize 2048 -validity 10000 -storepass 123456 -keypass 123456 -dname 'cn=Unknown, ou=Unknown, o=Unknown, c=Unknown'\n\n# building release APK\ncd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd ..\n\n# wip\nfind $ANDROID_HOME | grep apksigner\n\n# signing\nmv ./android/app/build/outputs/apk/release/app-release-unsigned.apk ./android/app/build/outputs/apk/release/app-release.apk\n$ANDROID_HOME/build-tools/30.0.2/apksigner sign --ks detox.keystore --ks-pass=pass:123456 ./android/app/build/outputs/apk/release/app-release.apk\n$ANDROID_HOME/build-tools/30.0.2/apksigner sign --ks detox.keystore --ks-pass=pass:123456 ./android/app/build/outputs/apk/androidTest/release/app-release-androidTest.apk"
}
},
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "iPhone 11"
}
},
"emulator": {
"type": "android.emulator",
"device": {
"avdName": "Pixel_API_29_AOSP"
}
}
},
"configurations": {
"ios": {
"device": "simulator",
"app": "ios"
},
"android.debug": {
"device": "emulator",
"app": "android.debug"
},
"android.release": {
"device": "emulator",
"app": "android.release"
}
}
}

View File

@ -50,9 +50,8 @@ jobs:
e2e: e2e:
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- name: Checkout project - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Specify node version - name: Specify node version
@ -76,26 +75,25 @@ jobs:
restore-keys: | restore-keys: |
${{ runner.os }}-npm- ${{ runner.os }}-npm-
- name: Install node_modules
run: npm install
- name: Use specific Java version for sdkmanager to work - name: Use specific Java version for sdkmanager to work
uses: joschi/setup-jdk@v2 uses: joschi/setup-jdk@v2
with: with:
java-version: '8' java-version: '11'
architecture: 'x64' architecture: 'x64'
- name: Install node_modules
run: npm install
- name: Build - name: Build
run: npm run e2e:release-build run: npm run e2e:release-build
- name: Run tests - name: run tests
uses: reactivecircus/android-emulator-runner@v2 uses: reactivecircus/android-emulator-runner@v2
with: with:
api-level: 29 api-level: 31
emulator-build: 6885378 # tmp fix for https://github.com/ReactiveCircus/android-emulator-runner/issues/160
target: google_apis
avd-name: Pixel_API_29_AOSP avd-name: Pixel_API_29_AOSP
emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none -camera-front none -partition-size 2047 emulator-options: -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim -camera-back none -camera-front none -partition-size 2047
arch: x86_64
script: npm run e2e:release-test || npm run e2e:release-test || npm run e2e:release-test script: npm run e2e:release-test || npm run e2e:release-test || npm run e2e:release-test
env: env:
TRAVIS: 1 TRAVIS: 1

View File

@ -148,6 +148,10 @@ android {
ndk { ndk {
abiFilters 'arm64-v8a', 'x86_64', 'x86', 'armeabi-v7a' abiFilters 'arm64-v8a', 'x86_64', 'x86', 'armeabi-v7a'
} }
testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
missingDimensionStrategy 'detox', 'full'
} }
splits { splits {
abi { abi {
@ -205,10 +209,6 @@ dependencies {
exclude group:'com.facebook.flipper' exclude group:'com.facebook.flipper'
} }
androidTestImplementation('com.wix:detox:+') {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
}
if (enableHermes) { if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/"; def hermesPath = "../../node_modules/hermes-engine/android/";
debugImplementation files(hermesPath + "hermes-debug.aar") debugImplementation files(hermesPath + "hermes-debug.aar")
@ -216,6 +216,8 @@ dependencies {
} else { } else {
implementation jscFlavor implementation jscFlavor
} }
androidTestImplementation(project(path: ":detox"))
} }
// Run this once to be able to run the application with BUCK // Run this once to be able to run the application with BUCK

View File

@ -1,24 +1,35 @@
package io.bluewallet.bluewallet; package io.bluewallet.bluewallet;
import com.wix.detox.Detox; import com.wix.detox.Detox;
import com.wix.detox.config.DetoxConfig;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest; import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule; import androidx.test.rule.ActivityTestRule;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@LargeTest @LargeTest
public class DetoxTest { public class DetoxTest {
// Replace 'MainActivity' with the value of android:name entry in
// <activity> in AndroidManifest.xml
@Rule @Rule
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false); public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false);
@Test @Test
public void runDetoxTests() { public void runDetoxTests() {
Detox.runTests(mActivityRule); // This is optional - in case you've decided to integrate TestButler
// See https://github.com/wix/Detox/blob/master/docs/Introduction.Android.md#8-test-butler-support-optional
// TestButlerProbe.assertReadyIfInstalled();
DetoxConfig detoxConfig = new DetoxConfig();
detoxConfig.idlePolicyConfig.masterTimeoutSec = 90;
detoxConfig.idlePolicyConfig.idleResourceTimeoutSec = 60;
detoxConfig.rnContextLoadTimeoutSec = (io.bluewallet.bluewallet.BuildConfig.DEBUG ? 180 : 60);
Detox.runTests(mActivityRule, detoxConfig);
} }
} }

View File

@ -18,7 +18,8 @@
android:requestLegacyExternalStorage="true" android:requestLegacyExternalStorage="true"
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme"
android:networkSecurityConfig="@xml/network_security_config">
<meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_name" <meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_name"
android:value="BlueWallet notifications"/> <!-- YOUR NOTIFICATION CHANNEL NAME --> android:value="BlueWallet notifications"/> <!-- YOUR NOTIFICATION CHANNEL NAME -->

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">10.0.2.2</domain>
<domain includeSubdomains="true">localhost</domain>
</domain-config>
</network-security-config>

View File

@ -22,6 +22,7 @@ buildscript {
classpath("com.bugsnag:bugsnag-android-gradle-plugin:5.+") classpath("com.bugsnag:bugsnag-android-gradle-plugin:5.+")
classpath 'com.google.gms:google-services:4.3.10' // Google Services plugin classpath 'com.google.gms:google-services:4.3.10' // Google Services plugin
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21")
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
@ -63,10 +64,6 @@ allprojects {
// Android JSC is installed from npm // Android JSC is installed from npm
url("$rootDir/../node_modules/jsc-android/dist") url("$rootDir/../node_modules/jsc-android/dist")
} }
maven {
// All of Detox' artifacts are provided via the npm module
url "$rootDir/../node_modules/detox/Detox-android"
}
google() google()
maven { url 'https://www.jitpack.io' } maven { url 'https://www.jitpack.io' }
} }

View File

@ -1,3 +1,6 @@
rootProject.name = 'BlueWallet' rootProject.name = 'BlueWallet'
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app' include ':app'
include ':detox'
project(':detox').projectDir = new File(rootProject.projectDir, '../node_modules/detox/android/detox')

View File

@ -11,6 +11,7 @@ const EXCHANGE_RATES_STORAGE_KEY = 'currency';
let preferredFiatCurrency = FiatUnit.USD; let preferredFiatCurrency = FiatUnit.USD;
let exchangeRates = { LAST_UPDATED_ERROR: false }; let exchangeRates = { LAST_UPDATED_ERROR: false };
let lastTimeUpdateExchangeRateWasCalled = 0; let lastTimeUpdateExchangeRateWasCalled = 0;
let skipUpdateExchangeRate = false;
const LAST_UPDATED = 'LAST_UPDATED'; const LAST_UPDATED = 'LAST_UPDATED';
@ -70,6 +71,7 @@ async function _restoreSavedPreferredFiatCurrencyFromStorage() {
* @return {Promise<void>} * @return {Promise<void>}
*/ */
async function updateExchangeRate() { async function updateExchangeRate() {
if (skipUpdateExchangeRate) return;
if (+new Date() - lastTimeUpdateExchangeRateWasCalled <= 10 * 1000) { if (+new Date() - lastTimeUpdateExchangeRateWasCalled <= 10 * 1000) {
// simple debounce so theres no race conditions // simple debounce so theres no race conditions
return; return;
@ -228,6 +230,13 @@ function _setExchangeRate(pair, rate) {
exchangeRates[pair] = rate; exchangeRates[pair] = rate;
} }
/**
* Used in unit tests, so the `currency` module wont launch actual http request
*/
function _setSkipUpdateExchangeRate() {
skipUpdateExchangeRate = true;
}
module.exports.updateExchangeRate = updateExchangeRate; module.exports.updateExchangeRate = updateExchangeRate;
module.exports.init = init; module.exports.init = init;
module.exports.satoshiToLocalCurrency = satoshiToLocalCurrency; module.exports.satoshiToLocalCurrency = satoshiToLocalCurrency;
@ -240,6 +249,7 @@ module.exports.btcToSatoshi = btcToSatoshi;
module.exports.getCurrencySymbol = getCurrencySymbol; module.exports.getCurrencySymbol = getCurrencySymbol;
module.exports._setPreferredFiatCurrency = _setPreferredFiatCurrency; // export it to mock data in tests module.exports._setPreferredFiatCurrency = _setPreferredFiatCurrency; // export it to mock data in tests
module.exports._setExchangeRate = _setExchangeRate; // export it to mock data in tests module.exports._setExchangeRate = _setExchangeRate; // export it to mock data in tests
module.exports._setSkipUpdateExchangeRate = _setSkipUpdateExchangeRate; // export it to mock data in tests
module.exports.PREFERRED_CURRENCY = PREFERRED_CURRENCY_STORAGE_KEY; module.exports.PREFERRED_CURRENCY = PREFERRED_CURRENCY_STORAGE_KEY;
module.exports.EXCHANGE_RATES = EXCHANGE_RATES_STORAGE_KEY; module.exports.EXCHANGE_RATES = EXCHANGE_RATES_STORAGE_KEY;
module.exports.LAST_UPDATED = LAST_UPDATED; module.exports.LAST_UPDATED = LAST_UPDATED;

View File

@ -20,7 +20,7 @@ export default class PayjoinTransaction {
async getPsbt() { async getPsbt() {
// Nasty hack to get this working for now // Nasty hack to get this working for now
const unfinalized = this._psbt.clone(); const unfinalized = this._psbt.clone();
unfinalized.data.inputs.forEach((input, index) => { for (const [index, input] of unfinalized.data.inputs.entries()) {
delete input.finalScriptWitness; delete input.finalScriptWitness;
const address = bitcoin.address.fromOutputScript(input.witnessUtxo.script); const address = bitcoin.address.fromOutputScript(input.witnessUtxo.script);
@ -28,7 +28,7 @@ export default class PayjoinTransaction {
const keyPair = ECPair.fromWIF(wif); const keyPair = ECPair.fromWIF(wif);
unfinalized.signInput(index, keyPair); unfinalized.signInput(index, keyPair);
}); }
return unfinalized; return unfinalized;
} }
@ -44,15 +44,15 @@ export default class PayjoinTransaction {
async signPsbt(payjoinPsbt) { async signPsbt(payjoinPsbt) {
// Do this without relying on private methods // Do this without relying on private methods
payjoinPsbt.data.inputs.forEach((input, index) => {
for (const [index, input] of payjoinPsbt.data.inputs.entries()) {
const address = bitcoin.address.fromOutputScript(input.witnessUtxo.script); const address = bitcoin.address.fromOutputScript(input.witnessUtxo.script);
try { try {
const wif = this._wallet._getWifForAddress(address); const wif = this._wallet._getWifForAddress(address);
const keyPair = ECPair.fromWIF(wif); const keyPair = ECPair.fromWIF(wif);
payjoinPsbt.signInput(index, keyPair).finalizeInput(index); payjoinPsbt.signInput(index, keyPair).finalizeInput(index);
} catch (e) {} } catch (e) {}
}); }
this._payjoinPsbt = payjoinPsbt; this._payjoinPsbt = payjoinPsbt;
return this._payjoinPsbt; return this._payjoinPsbt;
} }

View File

@ -422,7 +422,7 @@ export class AbstractWallet {
getMasterFingerprintFromHex(hexValue: string): number { getMasterFingerprintFromHex(hexValue: string): number {
if (hexValue.length < 8) hexValue = '0' + hexValue; if (hexValue.length < 8) hexValue = '0' + hexValue;
const b = Buffer.from(hexValue, 'hex') const b = Buffer.from(hexValue, 'hex');
if (b.length !== 4) throw new Error('invalid fingerprint hex'); if (b.length !== 4) throw new Error('invalid fingerprint hex');
hexValue = hexValue[6] + hexValue[7] + hexValue[4] + hexValue[5] + hexValue[2] + hexValue[3] + hexValue[0] + hexValue[1]; hexValue = hexValue[6] + hexValue[7] + hexValue[4] + hexValue[5] + hexValue[2] + hexValue[3] + hexValue[0] + hexValue[1];

11603
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -9,11 +9,11 @@
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.9", "@babel/core": "^7.12.9",
"@babel/runtime": "^7.14.6", "@babel/runtime": "^7.14.6",
"@jest/reporters": "^26.4.1", "@jest/reporters": "^27.5.1",
"@react-native-community/eslint-config": "^3.0.0", "@react-native-community/eslint-config": "^3.0.0",
"@types/bs58check": "^2.1.0", "@types/bs58check": "^2.1.0",
"@types/create-hash": "^1.2.2", "@types/create-hash": "^1.2.2",
"@types/jest": "^26.0.24", "@types/jest": "^27.5.1",
"@types/react": "^17.0.14", "@types/react": "^17.0.14",
"@types/react-native": "^0.67.0", "@types/react-native": "^0.67.0",
"@types/react-test-renderer": "^17.0.1", "@types/react-test-renderer": "^17.0.1",
@ -21,7 +21,7 @@
"@typescript-eslint/parser": "^4.28.3", "@typescript-eslint/parser": "^4.28.3",
"babel-cli": "^6.26.0", "babel-cli": "^6.26.0",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3", "babel-jest": "^27.5.1",
"eslint": "^7.30.0", "eslint": "^7.30.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-config-standard": "^16.0.2", "eslint-config-standard": "^16.0.2",
@ -34,7 +34,7 @@
"eslint-plugin-promise": "^6.0.0", "eslint-plugin-promise": "^6.0.0",
"eslint-plugin-react": "^7.23.2", "eslint-plugin-react": "^7.23.2",
"eslint-plugin-standard": "^4.1.0", "eslint-plugin-standard": "^4.1.0",
"jest": "^26.1.0", "jest": "^27.5.1",
"node-fetch": "^2.6.2", "node-fetch": "^2.6.2",
"prettier": "^2.2.1", "prettier": "^2.2.1",
"react-test-renderer": "17.0.2", "react-test-renderer": "17.0.2",
@ -59,16 +59,16 @@
"jest": "jest -b tests/integration/*", "jest": "jest -b tests/integration/*",
"windowspatches": "./scripts/windows-patches.sh", "windowspatches": "./scripts/windows-patches.sh",
"maccatalystpatches": "./scripts/maccatalystpatches/applypatchesformaccatalyst.sh", "maccatalystpatches": "./scripts/maccatalystpatches/applypatchesformaccatalyst.sh",
"e2e:debug-build": "detox build -c android.emu.debug", "e2e:debug-build": "detox build -c android.debug",
"e2e:debug-test": "detox test -c android.emu.debug -d 200000 -l info", "e2e:debug-test": "detox test -c android.debug -d 200000 -l info",
"e2e:debug": "(test -f android/app/build/outputs/apk/debug/app-debug.apk && test -f android/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk) || npm run e2e:debug-build; npm run e2e:debug-test", "e2e:debug": "(test -f android/app/build/outputs/apk/debug/app-debug.apk && test -f android/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk) || npm run e2e:debug-build; npm run e2e:debug-test",
"e2e:release-build": "detox build -c android.emu.release", "e2e:release-build": "detox build -c android.release",
"e2e:release-test": "detox test -c android.emu.release --record-videos all --take-screenshots all --headless -d 200000 --loglevel info", "e2e:release-test": "detox test -c android.release --record-videos all --record-logs all --take-screenshots all --headless -d 200000",
"tslint": "tsc", "tslint": "tsc",
"lint": "eslint --ext .js,.ts,.tsx '*.@(js|ts|tsx)' screen 'blue_modules/*.@(js|ts|tsx)' class models loc tests components", "lint": "eslint --ext .js,.ts,.tsx '*.@(js|ts|tsx)' screen 'blue_modules/*.@(js|ts|tsx)' class models loc tests components",
"lint:fix": "npm run lint -- --fix", "lint:fix": "npm run lint -- --fix",
"lint:quickfix": "git status --porcelain | grep -v '\\.json' | grep -E '\\.js|\\.ts' --color=never | awk '{print $2}' | xargs eslint --fix; exit 0", "lint:quickfix": "git status --porcelain | grep -v '\\.json' | grep -E '\\.js|\\.ts' --color=never | awk '{print $2}' | xargs eslint --fix; exit 0",
"unit": "jest -b tests/unit/*", "unit": "jest -b -i tests/unit/*",
"windows": "react-native run-windows" "windows": "react-native run-windows"
}, },
"jest": { "jest": {
@ -125,7 +125,7 @@
"coinselect": "3.1.12", "coinselect": "3.1.12",
"crypto-js": "4.1.1", "crypto-js": "4.1.1",
"dayjs": "1.11.2", "dayjs": "1.11.2",
"detox": "19.4.4", "detox": "19.6.9",
"ecpair": "2.0.1", "ecpair": "2.0.1",
"ecurve": "1.0.6", "ecurve": "1.0.6",
"electrum-client": "https://github.com/BlueWallet/rn-electrum-client#99ebcc649d91a8dc39bea7964b02dd9ead464aa4", "electrum-client": "https://github.com/BlueWallet/rn-electrum-client#99ebcc649d91a8dc39bea7964b02dd9ead464aa4",
@ -210,36 +210,6 @@
"_stream_passthrough": "readable-stream/passthrough", "_stream_passthrough": "readable-stream/passthrough",
"stream": "stream-browserify" "stream": "stream-browserify"
}, },
"detox": {
"configurations": {
"ios.sim.release": {
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/BlueWallet.app",
"build": "xcodebuild clean build -workspace ios/BlueWallet.xcworkspace -scheme BlueWallet -configuration Release -derivedDataPath ios/build -sdk iphonesimulator13.2",
"type": "ios.simulator",
"device": {
"type": "iPhone 11"
}
},
"android.emu.debug": {
"binaryPath": "android/app/build/outputs/apk/debug/app-debug.apk",
"build": "cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && cd ..",
"type": "android.emulator",
"device": {
"avdName": "Pixel_API_29_AOSP"
}
},
"android.emu.release": {
"binaryPath": "android/app/build/outputs/apk/release/app-release.apk",
"build": "# deleting old artifacts\nfind | grep '\\.apk' --color=never | grep -v node_modules | xargs -l rm\n\n# creating fresh keystore\nrm detox.keystore\nkeytool -genkeypair -v -keystore detox.keystore -alias detox -keyalg RSA -keysize 2048 -validity 10000 -storepass 123456 -keypass 123456 -dname 'cn=Unknown, ou=Unknown, o=Unknown, c=Unknown'\n\n# building release APK\ncd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd ..\n\n# backup & sign apk1\ncp ./android/app/build/outputs/apk/release/app-release-unsigned.apk ./android/app/build/outputs/apk/release/app-release-unsigned.apk.bak\njarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore detox.keystore ./android/app/build/outputs/apk/release/app-release-unsigned.apk detox -storepass 123456\n\n# move apk1 to expected filename\nmv ./android/app/build/outputs/apk/release/app-release-unsigned.apk ./android/app/build/outputs/apk/release/app-release.apk\n\n# backup and sign apk2\ncp android/app/build/outputs/apk/androidTest/release/app-release-androidTest.apk android/app/build/outputs/apk/androidTest/release/app-release-androidTest.apk.bak\njarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore detox.keystore android/app/build/outputs/apk/androidTest/release/app-release-androidTest.apk detox -storepass 123456",
"type": "android.emulator",
"device": {
"avdName": "Pixel_API_29_AOSP"
}
}
},
"test-runner": "jest",
"runner-config": "tests/e2e/config.json"
},
"browser": { "browser": {
"crypto": "react-native-crypto", "crypto": "react-native-crypto",
"path": "path-browserify", "path": "path-browserify",

View File

@ -1,7 +1,6 @@
{ {
"env": { "env": {
"es6": true, "es6": true,
"jasmine": true,
"jest": true "jest": true
}, },
"globals": { "globals": {

View File

@ -12,17 +12,11 @@ import {
const bitcoin = require('bitcoinjs-lib'); const bitcoin = require('bitcoinjs-lib');
const assert = require('assert'); const assert = require('assert');
jasmine.getEnv().addReporter({
specStarted: result => (jasmine.currentTest = result),
specDone: result => (jasmine.currentTest = result),
});
describe('BlueWallet UI Tests - no wallets', () => { describe('BlueWallet UI Tests - no wallets', () => {
it('selftest passes', async () => { it('selftest passes', async () => {
const lockFile = '/tmp/travislock.' + hashIt(jasmine.currentTest.fullName); const lockFile = '/tmp/travislock.' + hashIt('t1');
if (process.env.TRAVIS) { if (process.env.TRAVIS) {
if (require('fs').existsSync(lockFile)) if (require('fs').existsSync(lockFile)) return console.warn('skipping', JSON.stringify('t1'), 'as it previously passed on Travis');
return console.warn('skipping', JSON.stringify(jasmine.currentTest.fullName), 'as it previously passed on Travis');
} }
await waitFor(element(by.id('WalletsList'))) await waitFor(element(by.id('WalletsList')))
.toBeVisible() .toBeVisible()
@ -43,10 +37,9 @@ describe('BlueWallet UI Tests - no wallets', () => {
}); });
it('all settings screens work', async () => { it('all settings screens work', async () => {
const lockFile = '/tmp/travislock.' + hashIt(jasmine.currentTest.fullName); const lockFile = '/tmp/travislock.' + hashIt('t2');
if (process.env.TRAVIS) { if (process.env.TRAVIS) {
if (require('fs').existsSync(lockFile)) if (require('fs').existsSync(lockFile)) return console.warn('skipping', JSON.stringify('t2'), 'as it previously passed on Travis');
return console.warn('skipping', JSON.stringify(jasmine.currentTest.fullName), 'as it previously passed on Travis');
} }
await yo('WalletsList'); await yo('WalletsList');
@ -179,10 +172,9 @@ describe('BlueWallet UI Tests - no wallets', () => {
}); });
it('can create wallet, reload app and it persists. then go to receive screen, set custom amount and label. Dismiss modal and go to WalletsList.', async () => { it('can create wallet, reload app and it persists. then go to receive screen, set custom amount and label. Dismiss modal and go to WalletsList.', async () => {
const lockFile = '/tmp/travislock.' + hashIt(jasmine.currentTest.fullName); const lockFile = '/tmp/travislock.' + hashIt('t3');
if (process.env.TRAVIS) { if (process.env.TRAVIS) {
if (require('fs').existsSync(lockFile)) if (require('fs').existsSync(lockFile)) return console.warn('skipping', JSON.stringify('t3'), 'as it previously passed on Travis');
return console.warn('skipping', JSON.stringify(jasmine.currentTest.fullName), 'as it previously passed on Travis');
} }
await yo('WalletsList'); await yo('WalletsList');
@ -216,10 +208,9 @@ describe('BlueWallet UI Tests - no wallets', () => {
}); });
it('can encrypt storage, with plausible deniabilityl decrypt fake storage', async () => { it('can encrypt storage, with plausible deniabilityl decrypt fake storage', async () => {
const lockFile = '/tmp/travislock.' + hashIt(jasmine.currentTest.fullName); const lockFile = '/tmp/travislock.' + hashIt('t4');
if (process.env.TRAVIS) { if (process.env.TRAVIS) {
if (require('fs').existsSync(lockFile)) if (require('fs').existsSync(lockFile)) return console.warn('skipping', JSON.stringify('t4'), 'as it previously passed on Travis');
return console.warn('skipping', JSON.stringify(jasmine.currentTest.fullName), 'as it previously passed on Travis');
} }
await yo('WalletsList'); await yo('WalletsList');
@ -370,10 +361,9 @@ describe('BlueWallet UI Tests - no wallets', () => {
}); });
it('can encrypt storage, and decrypt storage works', async () => { it('can encrypt storage, and decrypt storage works', async () => {
const lockFile = '/tmp/travislock.' + hashIt(jasmine.currentTest.fullName); const lockFile = '/tmp/travislock.' + hashIt('t5');
if (process.env.TRAVIS) { if (process.env.TRAVIS) {
if (require('fs').existsSync(lockFile)) if (require('fs').existsSync(lockFile)) return console.warn('skipping', JSON.stringify('t5'), 'as it previously passed on Travis');
return console.warn('skipping', JSON.stringify(jasmine.currentTest.fullName), 'as it previously passed on Travis');
} }
await yo('WalletsList'); await yo('WalletsList');
await helperCreateWallet(); await helperCreateWallet();
@ -447,10 +437,9 @@ describe('BlueWallet UI Tests - no wallets', () => {
}); });
it('can import multisig setup from UR, and create tx, and sign on hw devices', async () => { it('can import multisig setup from UR, and create tx, and sign on hw devices', async () => {
const lockFile = '/tmp/travislock.' + hashIt(jasmine.currentTest.fullName); const lockFile = '/tmp/travislock.' + hashIt('t6');
if (process.env.TRAVIS) { if (process.env.TRAVIS) {
if (require('fs').existsSync(lockFile)) if (require('fs').existsSync(lockFile)) return console.warn('skipping', JSON.stringify('t6'), 'as it previously passed on Travis');
return console.warn('skipping', JSON.stringify(jasmine.currentTest.fullName), 'as it previously passed on Travis');
} }
await yo('WalletsList'); await yo('WalletsList');
@ -575,10 +564,9 @@ describe('BlueWallet UI Tests - no wallets', () => {
}); });
it('can discover wallet account and import it', async () => { it('can discover wallet account and import it', async () => {
const lockFile = '/tmp/travislock.' + hashIt(jasmine.currentTest.fullName); const lockFile = '/tmp/travislock.' + hashIt('t6');
if (process.env.TRAVIS) { if (process.env.TRAVIS) {
if (require('fs').existsSync(lockFile)) if (require('fs').existsSync(lockFile)) return console.warn('skipping', JSON.stringify('t6'), 'as it previously passed on Travis');
return console.warn('skipping', JSON.stringify(jasmine.currentTest.fullName), 'as it previously passed on Travis');
} }
await yo('WalletsList'); await yo('WalletsList');

View File

@ -2,11 +2,6 @@ import { helperDeleteWallet, sleep, hashIt, sup, helperImportWallet, yo, extract
const bitcoin = require('bitcoinjs-lib'); const bitcoin = require('bitcoinjs-lib');
const assert = require('assert'); const assert = require('assert');
jasmine.getEnv().addReporter({
specStarted: result => (jasmine.currentTest = result),
specDone: result => (jasmine.currentTest = result),
});
beforeAll(async () => { beforeAll(async () => {
if (!process.env.HD_MNEMONIC_BIP84) { if (!process.env.HD_MNEMONIC_BIP84) {
console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped');
@ -31,10 +26,9 @@ afterAll(async () => {
describe('BlueWallet UI Tests - import BIP84 wallet', () => { describe('BlueWallet UI Tests - import BIP84 wallet', () => {
it('can import BIP84 mnemonic, fetch balance & transactions, then create a transaction; then cosign', async () => { it('can import BIP84 mnemonic, fetch balance & transactions, then create a transaction; then cosign', async () => {
const lockFile = '/tmp/travislock.' + hashIt(jasmine.currentTest.fullName); const lockFile = '/tmp/travislock.' + hashIt('t21');
if (process.env.TRAVIS) { if (process.env.TRAVIS) {
if (require('fs').existsSync(lockFile)) if (require('fs').existsSync(lockFile)) return console.warn('skipping', JSON.stringify('t21'), 'as it previously passed on Travis');
return console.warn('skipping', JSON.stringify(jasmine.currentTest.fullName), 'as it previously passed on Travis');
} }
if (!process.env.HD_MNEMONIC_BIP84) { if (!process.env.HD_MNEMONIC_BIP84) {
console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped');
@ -344,10 +338,9 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
}); });
it('should handle URL successfully', async () => { it('should handle URL successfully', async () => {
const lockFile = '/tmp/travislock.' + hashIt(jasmine.currentTest.fullName); const lockFile = '/tmp/travislock.' + hashIt('t22');
if (process.env.TRAVIS) { if (process.env.TRAVIS) {
if (require('fs').existsSync(lockFile)) if (require('fs').existsSync(lockFile)) return console.warn('skipping', JSON.stringify('t22'), 'as it previously passed on Travis');
return console.warn('skipping', JSON.stringify(jasmine.currentTest.fullName), 'as it previously passed on Travis');
} }
if (!process.env.HD_MNEMONIC_BIP84) { if (!process.env.HD_MNEMONIC_BIP84) {
console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped');
@ -384,10 +377,9 @@ describe('BlueWallet UI Tests - import BIP84 wallet', () => {
}); });
it('can manage UTXO', async () => { it('can manage UTXO', async () => {
const lockFile = '/tmp/travislock.' + hashIt(jasmine.currentTest.fullName); const lockFile = '/tmp/travislock.' + hashIt('t23');
if (process.env.TRAVIS) { if (process.env.TRAVIS) {
if (require('fs').existsSync(lockFile)) if (require('fs').existsSync(lockFile)) return console.warn('skipping', JSON.stringify('t23'), 'as it previously passed on Travis');
return console.warn('skipping', JSON.stringify(jasmine.currentTest.fullName), 'as it previously passed on Travis');
} }
if (!process.env.HD_MNEMONIC_BIP84) { if (!process.env.HD_MNEMONIC_BIP84) {
console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped'); console.error('process.env.HD_MNEMONIC_BIP84 not set, skipped');

View File

@ -1,10 +1,5 @@
import { helperDeleteWallet, sleep, hashIt, sup, helperImportWallet, yo } from './helperz'; import { helperDeleteWallet, sleep, hashIt, sup, helperImportWallet, yo } from './helperz';
jasmine.getEnv().addReporter({
specStarted: result => (jasmine.currentTest = result),
specDone: result => (jasmine.currentTest = result),
});
describe('BlueWallet UI Tests - import Watch-only wallet (zpub)', () => { describe('BlueWallet UI Tests - import Watch-only wallet (zpub)', () => {
/** /**
* test plan: * test plan:
@ -16,10 +11,9 @@ describe('BlueWallet UI Tests - import Watch-only wallet (zpub)', () => {
* 6. verify that we can see broadcast button and camera backdorr button is NOT visible * 6. verify that we can see broadcast button and camera backdorr button is NOT visible
*/ */
it('can import zpub as watch-only, import psbt, and then scan signed psbt', async () => { it('can import zpub as watch-only, import psbt, and then scan signed psbt', async () => {
const lockFile = '/tmp/travislock.' + hashIt(jasmine.currentTest.fullName); const lockFile = '/tmp/travislock.' + hashIt('t31');
if (process.env.TRAVIS) { if (process.env.TRAVIS) {
if (require('fs').existsSync(lockFile)) if (require('fs').existsSync(lockFile)) return console.warn('skipping', JSON.stringify('t31'), 'as it previously passed on Travis');
return console.warn('skipping', JSON.stringify(jasmine.currentTest.fullName), 'as it previously passed on Travis');
} }
await helperImportWallet( await helperImportWallet(
'zpub6rDWXE4wbwefeCrHWehXJheXnti5F9PbpamDUeB5eFbqaY89x3jq86JADBuXpnJnSvRVwqkaTnyMaZERUg4BpxD9V4tSZfKeYh1ozPdL1xK', 'zpub6rDWXE4wbwefeCrHWehXJheXnti5F9PbpamDUeB5eFbqaY89x3jq86JADBuXpnJnSvRVwqkaTnyMaZERUg4BpxD9V4tSZfKeYh1ozPdL1xK',

View File

@ -1,6 +1,10 @@
{ {
"maxWorkers": 1,
"testEnvironment": "./environment",
"testRunner": "jest-circus/runner",
"testTimeout": 321000,
"testRegex": "\\.spec\\.js$",
"setupFilesAfterEnv": ["./init.js"], "setupFilesAfterEnv": ["./init.js"],
"testEnvironment": "node",
"reporters": ["detox/runners/jest/streamlineReporter"], "reporters": ["detox/runners/jest/streamlineReporter"],
"verbose": true "verbose": true
} }

View File

@ -1,8 +1,8 @@
# script thats used to build & sign release APK in preparation for Detox e2e testing. # script thats used to build & sign release APK in preparation for Detox e2e testing.
# should be copied in package.json - detox - configurations - android.emu.release - build # should be copied in .detoxrc.json - apps - android.release - build
# deleting old artifacts # deleting old artifacts
find | grep '\.apk' --color=never | grep -v node_modules | xargs -l rm find android | grep '\.apk' --color=never | xargs -l rm
# creating fresh keystore # creating fresh keystore
rm detox.keystore rm detox.keystore
@ -11,17 +11,7 @@ keytool -genkeypair -v -keystore detox.keystore -alias detox -keyalg RSA -keysi
# building release APK # building release APK
cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd .. cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd ..
# backup & sign apk1 # signing
cp ./android/app/build/outputs/apk/release/app-release-unsigned.apk ./android/app/build/outputs/apk/release/app-release-unsigned.apk.bak
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore detox.keystore ./android/app/build/outputs/apk/release/app-release-unsigned.apk detox -storepass 123456
# move apk1 to expected filename
mv ./android/app/build/outputs/apk/release/app-release-unsigned.apk ./android/app/build/outputs/apk/release/app-release.apk mv ./android/app/build/outputs/apk/release/app-release-unsigned.apk ./android/app/build/outputs/apk/release/app-release.apk
$ANDROID_HOME/build-tools/30.0.2/apksigner sign --ks detox.keystore --ks-pass=pass:123456 ./android/app/build/outputs/apk/release/app-release.apk
# backup and sign apk2 $ANDROID_HOME/build-tools/30.0.2/apksigner sign --ks detox.keystore --ks-pass=pass:123456 ./android/app/build/outputs/apk/androidTest/release/app-release-androidTest.apk
cp android/app/build/outputs/apk/androidTest/release/app-release-androidTest.apk android/app/build/outputs/apk/androidTest/release/app-release-androidTest.apk.bak
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore detox.keystore android/app/build/outputs/apk/androidTest/release/app-release-androidTest.apk detox -storepass 123456
# why the fuck there are 2 apks..? oh well, if it works - dont touch

19
tests/e2e/environment.js Normal file
View File

@ -0,0 +1,19 @@
const { DetoxCircusEnvironment, SpecReporter, WorkerAssignReporter } = require('detox/runners/jest-circus');
class CustomDetoxEnvironment extends DetoxCircusEnvironment {
constructor(config, context) {
super(config, context);
// Can be safely removed, if you are content with the default value (=300000ms)
this.initTimeout = 300000;
// This takes care of generating status logs on a per-spec basis. By default, Jest only reports at file-level.
// This is strictly optional.
this.registerListeners({
SpecReporter,
WorkerAssignReporter,
});
}
}
module.exports = CustomDetoxEnvironment;

View File

@ -1,43 +1,3 @@
const detox = require('detox');
const config = require('../../package.json').detox;
const adapter = require('detox/runners/jest/adapter');
const specReporter = require('detox/runners/jest/specReporter');
const assignReporter = require('detox/runners/jest/assignReporter');
jasmine.getEnv().addReporter(adapter);
// This takes care of generating status logs on a per-spec basis. By default, jest only reports at file-level.
// This is strictly optional.
jasmine.getEnv().addReporter(specReporter);
// This will post which device has assigned to run a suite, which can be useful in a multiple-worker tests run.
// This is strictly optional.
jasmine.getEnv().addReporter(assignReporter);
// Set the default timeout
jest.setTimeout(1200000); // 20 min
beforeAll(async () => { beforeAll(async () => {
await detox.init(config);
await device.launchApp(); await device.launchApp();
}, 1200000);
beforeEach(async () => {
const lockFile = '/tmp/travislock.' + hashIt(jasmine.currentTest.fullName);
if (process.env.TRAVIS) {
if (require('fs').existsSync(lockFile))
// speeds up test pass
return;
}
await adapter.beforeEach();
}); });
afterAll(async () => {
await adapter.afterAll();
await detox.cleanup();
});
function hashIt(s) {
const createHash = require('create-hash');
return createHash('sha256').update(s).digest().toString('hex');
}

View File

@ -2,7 +2,7 @@ import assert from 'assert';
import * as BlueElectrum from '../../blue_modules/BlueElectrum'; import * as BlueElectrum from '../../blue_modules/BlueElectrum';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 150 * 1000; jest.setTimeout(150 * 1000);
afterAll(() => { afterAll(() => {
// after all tests we close socket so the test suite can actually terminate // after all tests we close socket so the test suite can actually terminate

View File

@ -3,9 +3,10 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
import { FiatUnit } from '../../models/fiatUnit'; import { FiatUnit } from '../../models/fiatUnit';
jest.setTimeout(15 * 1000);
describe('currency', () => { describe('currency', () => {
it('fetches exchange rate and saves to AsyncStorage', async () => { it('fetches exchange rate and saves to AsyncStorage', async () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 15000;
const currency = require('../../blue_modules/currency'); const currency = require('../../blue_modules/currency');
await currency.init(); await currency.init();
let cur = await AsyncStorage.getItem(currency.EXCHANGE_RATES); let cur = await AsyncStorage.getItem(currency.EXCHANGE_RATES);

View File

@ -2,7 +2,7 @@ import * as bitcoin from 'bitcoinjs-lib';
import assert from 'assert'; import assert from 'assert';
import ElectrumClient from 'electrum-client'; import ElectrumClient from 'electrum-client';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 150 * 1000; jest.setTimeout(150 * 1000);
const hardcodedPeers = [ const hardcodedPeers = [
{ host: 'electrum1.bluewallet.io', ssl: '443' }, { host: 'electrum1.bluewallet.io', ssl: '443' },

View File

@ -4,7 +4,7 @@ import * as bitcoin from 'bitcoinjs-lib';
import { HDLegacyBreadwalletWallet } from '../../class'; import { HDLegacyBreadwalletWallet } from '../../class';
import * as BlueElectrum from '../../blue_modules/BlueElectrum'; import * as BlueElectrum from '../../blue_modules/BlueElectrum';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300 * 1000; jest.setTimeout(300 * 1000);
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
afterAll(async () => { afterAll(async () => {

View File

@ -4,7 +4,7 @@ import * as bitcoin from 'bitcoinjs-lib';
import { HDSegwitBech32Wallet, SegwitP2SHWallet, HDSegwitBech32Transaction, SegwitBech32Wallet } from '../../class'; import { HDSegwitBech32Wallet, SegwitP2SHWallet, HDSegwitBech32Transaction, SegwitBech32Wallet } from '../../class';
import * as BlueElectrum from '../../blue_modules/BlueElectrum'; import * as BlueElectrum from '../../blue_modules/BlueElectrum';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 150 * 1000; jest.setTimeout(150 * 1000);
afterAll(async () => { afterAll(async () => {
// after all tests we close socket so the test suite can actually terminate // after all tests we close socket so the test suite can actually terminate

View File

@ -3,7 +3,7 @@ import assert from 'assert';
import { HDSegwitBech32Wallet } from '../../class'; import { HDSegwitBech32Wallet } from '../../class';
import * as BlueElectrum from '../../blue_modules/BlueElectrum'; import * as BlueElectrum from '../../blue_modules/BlueElectrum';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300 * 1000; jest.setTimeout(30 * 1000);
afterAll(async () => { afterAll(async () => {
// after all tests we close socket so the test suite can actually terminate // after all tests we close socket so the test suite can actually terminate

View File

@ -4,7 +4,7 @@ import * as bitcoin from 'bitcoinjs-lib';
import { HDSegwitP2SHWallet } from '../../class'; import { HDSegwitP2SHWallet } from '../../class';
import * as BlueElectrum from '../../blue_modules/BlueElectrum'; import * as BlueElectrum from '../../blue_modules/BlueElectrum';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300 * 1000; jest.setTimeout(300 * 1000);
afterAll(() => { afterAll(() => {
// after all tests we close socket so the test suite can actually terminate // after all tests we close socket so the test suite can actually terminate

View File

@ -1,11 +1,12 @@
import assert from 'assert';
import * as bitcoin from 'bitcoinjs-lib';
import { LegacyWallet, SegwitBech32Wallet, SegwitP2SHWallet } from '../../class'; import { LegacyWallet, SegwitBech32Wallet, SegwitP2SHWallet } from '../../class';
import { HodlHodlApi } from '../../class/hodl-hodl-api'; import { HodlHodlApi } from '../../class/hodl-hodl-api';
import { ECPairFactory } from 'ecpair'; import { ECPairFactory } from 'ecpair';
const ecc = require('tiny-secp256k1'); const ecc = require('tiny-secp256k1');
const ECPair = ECPairFactory(ecc); const ECPair = ECPairFactory(ecc);
const bitcoin = require('bitcoinjs-lib'); jest.setTimeout(200 * 1000);
const assert = require('assert');
it.skip('can verify escrow address', () => { it.skip('can verify escrow address', () => {
const encryptedSeed = const encryptedSeed =
@ -93,7 +94,6 @@ describe.skip('HodlHodl API', function () {
// dont run here as it always fails // dont run here as it always fails
return; return;
} }
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
const Hodl = new HodlHodlApi(); const Hodl = new HodlHodlApi();
const countries = await Hodl.getCountries(); const countries = await Hodl.getCountries();
assert.ok(countries[0]); assert.ok(countries[0]);
@ -154,7 +154,6 @@ describe.skip('HodlHodl API', function () {
// dont run here as it always fails // dont run here as it always fails
return; return;
} }
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
if (!process.env.HODLHODL_OFFER_ID) return; if (!process.env.HODLHODL_OFFER_ID) return;
const Hodl = new HodlHodlApi(); const Hodl = new HodlHodlApi();
const offer = await Hodl.getOffer(process.env.HODLHODL_OFFER_ID); const offer = await Hodl.getOffer(process.env.HODLHODL_OFFER_ID);
@ -177,7 +176,6 @@ describe.skip('HodlHodl API', function () {
// dont run here as it always fails // dont run here as it always fails
return; return;
} }
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
if (!process.env.HODLHODL_CONTRACT_ID) return; if (!process.env.HODLHODL_CONTRACT_ID) return;
const Hodl = new HodlHodlApi(); const Hodl = new HodlHodlApi();
const contract = await Hodl.getContract(process.env.HODLHODL_CONTRACT_ID); const contract = await Hodl.getContract(process.env.HODLHODL_CONTRACT_ID);
@ -191,7 +189,6 @@ describe.skip('HodlHodl API', function () {
// dont run here as it always fails // dont run here as it always fails
return; return;
} }
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
if (!process.env.HODLHODL_CONTRACT_ID) return; if (!process.env.HODLHODL_CONTRACT_ID) return;
const Hodl = new HodlHodlApi(); const Hodl = new HodlHodlApi();
const result = await Hodl.markContractAsConfirmed(process.env.HODLHODL_CONTRACT_ID); const result = await Hodl.markContractAsConfirmed(process.env.HODLHODL_CONTRACT_ID);

View File

@ -17,7 +17,7 @@ import {
import startImport from '../../class/wallet-import'; import startImport from '../../class/wallet-import';
import * as BlueElectrum from '../../blue_modules/BlueElectrum'; import * as BlueElectrum from '../../blue_modules/BlueElectrum';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000; jest.setTimeout(90 * 1000);
afterAll(async () => { afterAll(async () => {
// after all tests we close socket so the test suite can actually terminate // after all tests we close socket so the test suite can actually terminate

View File

@ -3,7 +3,7 @@ import assert from 'assert';
import { LegacyWallet, SegwitP2SHWallet, SegwitBech32Wallet } from '../../class'; import { LegacyWallet, SegwitP2SHWallet, SegwitBech32Wallet } from '../../class';
import * as BlueElectrum from '../../blue_modules/BlueElectrum'; import * as BlueElectrum from '../../blue_modules/BlueElectrum';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; jest.setTimeout(30 * 1000);
afterAll(async () => { afterAll(async () => {
// after all tests we close socket so the test suite can actually terminate // after all tests we close socket so the test suite can actually terminate

View File

@ -1,7 +1,8 @@
import assert from 'assert';
import Frisbee from 'frisbee'; import Frisbee from 'frisbee';
import { LightningCustodianWallet } from '../../class'; import { LightningCustodianWallet } from '../../class';
const assert = require('assert');
jest.setTimeout(200 * 1000);
const baseUri = 'https://lndhub-staging.herokuapp.com'; const baseUri = 'https://lndhub-staging.herokuapp.com';
describe.skip('LightningCustodianWallet', () => { describe.skip('LightningCustodianWallet', () => {
@ -10,7 +11,6 @@ describe.skip('LightningCustodianWallet', () => {
l1.init(); l1.init();
it.skip('issue credentials', async () => { it.skip('issue credentials', async () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
assert.ok(l1.refill_addressess.length === 0); assert.ok(l1.refill_addressess.length === 0);
assert.ok(l1._refresh_token_created_ts === 0); assert.ok(l1._refresh_token_created_ts === 0);
assert.ok(l1._access_token_created_ts === 0); assert.ok(l1._access_token_created_ts === 0);
@ -27,7 +27,6 @@ describe.skip('LightningCustodianWallet', () => {
}); });
it('can create, auth and getbtc', async () => { it('can create, auth and getbtc', async () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
assert.ok(l1.refill_addressess.length === 0); assert.ok(l1.refill_addressess.length === 0);
assert.ok(l1._refresh_token_created_ts === 0); assert.ok(l1._refresh_token_created_ts === 0);
assert.ok(l1._access_token_created_ts === 0); assert.ok(l1._access_token_created_ts === 0);
@ -54,7 +53,6 @@ describe.skip('LightningCustodianWallet', () => {
}); });
it('can refresh token', async () => { it('can refresh token', async () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
const oldRefreshToken = l1.refresh_token; const oldRefreshToken = l1.refresh_token;
const oldAccessToken = l1.access_token; const oldAccessToken = l1.access_token;
await l1.refreshAcessToken(); await l1.refreshAcessToken();
@ -65,7 +63,6 @@ describe.skip('LightningCustodianWallet', () => {
}); });
it('can use existing login/pass', async () => { it('can use existing login/pass', async () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
if (!process.env.BLITZHUB) { if (!process.env.BLITZHUB) {
console.error('process.env.BLITZHUB not set, skipped'); console.error('process.env.BLITZHUB not set, skipped');
return; return;
@ -98,7 +95,6 @@ describe.skip('LightningCustodianWallet', () => {
console.error('process.env.BLITZHUB not set, skipped'); console.error('process.env.BLITZHUB not set, skipped');
return; return;
} }
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30 * 1000;
const l2 = new LightningCustodianWallet(); const l2 = new LightningCustodianWallet();
l2.setSecret(process.env.BLITZHUB); l2.setSecret(process.env.BLITZHUB);
l2.setBaseURI(baseUri); l2.setBaseURI(baseUri);
@ -157,7 +153,6 @@ describe.skip('LightningCustodianWallet', () => {
}); });
it('can pay invoice from opennode', async () => { it('can pay invoice from opennode', async () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
if (!process.env.BLITZHUB) { if (!process.env.BLITZHUB) {
console.error('process.env.BLITZHUB not set, skipped'); console.error('process.env.BLITZHUB not set, skipped');
return; return;
@ -208,7 +203,6 @@ describe.skip('LightningCustodianWallet', () => {
// turned off because acinq strike is shutting down // turned off because acinq strike is shutting down
it.skip('can pay invoice (acinq)', async () => { it.skip('can pay invoice (acinq)', async () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
if (!process.env.BLITZHUB) { if (!process.env.BLITZHUB) {
console.error('process.env.BLITZHUB not set, skipped'); console.error('process.env.BLITZHUB not set, skipped');
return; return;
@ -283,7 +277,6 @@ describe.skip('LightningCustodianWallet', () => {
}); });
it('can pay invoice (bitrefill)', async () => { it('can pay invoice (bitrefill)', async () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
if (!process.env.BLITZHUB) { if (!process.env.BLITZHUB) {
console.error('process.env.BLITZHUB not set, skipped'); console.error('process.env.BLITZHUB not set, skipped');
return; return;
@ -350,7 +343,6 @@ describe.skip('LightningCustodianWallet', () => {
}); });
it('can create invoice and pay other blitzhub invoice', async () => { it('can create invoice and pay other blitzhub invoice', async () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
if (!process.env.BLITZHUB) { if (!process.env.BLITZHUB) {
console.error('process.env.BLITZHUB not set, skipped'); console.error('process.env.BLITZHUB not set, skipped');
return; return;
@ -456,7 +448,6 @@ describe.skip('LightningCustodianWallet', () => {
}); });
it('can pay invoice with free amount (tippin.me)', async function () { it('can pay invoice with free amount (tippin.me)', async function () {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
if (!process.env.BLITZHUB) { if (!process.env.BLITZHUB) {
console.error('process.env.BLITZHUB not set, skipped'); console.error('process.env.BLITZHUB not set, skipped');
return; return;
@ -536,7 +527,6 @@ describe.skip('LightningCustodianWallet', () => {
const l1 = new LightningCustodianWallet(); const l1 = new LightningCustodianWallet();
l1.setBaseURI(baseUri); l1.setBaseURI(baseUri);
l1.init(); l1.init();
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
assert.ok(l1.refill_addressess.length === 0); assert.ok(l1.refill_addressess.length === 0);
assert.ok(l1._refresh_token_created_ts === 0); assert.ok(l1._refresh_token_created_ts === 0);
assert.ok(l1._access_token_created_ts === 0); assert.ok(l1._access_token_created_ts === 0);
@ -570,7 +560,6 @@ describe.skip('LightningCustodianWallet', () => {
}); });
it('cant pay negative free amount', async () => { it('cant pay negative free amount', async () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200 * 1000;
if (!process.env.BLITZHUB) { if (!process.env.BLITZHUB) {
console.error('process.env.BLITZHUB not set, skipped'); console.error('process.env.BLITZHUB not set, skipped');
return; return;

View File

@ -2,7 +2,7 @@ import assert from 'assert';
import { MultisigHDWallet } from '../../class/'; import { MultisigHDWallet } from '../../class/';
import * as BlueElectrum from '../../blue_modules/BlueElectrum'; import * as BlueElectrum from '../../blue_modules/BlueElectrum';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300 * 1000; jest.setTimeout(300 * 1000);
afterAll(() => { afterAll(() => {
// after all tests we close socket so the test suite can actually terminate // after all tests we close socket so the test suite can actually terminate

View File

@ -1,7 +1,7 @@
import assert from 'assert'; import assert from 'assert';
import Notifications from '../../blue_modules/notifications'; import Notifications from '../../blue_modules/notifications';
Notifications.default = new Notifications(); // Notifications.default = new Notifications();
describe('notifications', () => { describe('notifications', () => {
// yeah, lets rely less on external services... // yeah, lets rely less on external services...

View File

@ -3,6 +3,8 @@ import assert from 'assert';
import { WatchOnlyWallet } from '../../class'; import { WatchOnlyWallet } from '../../class';
import * as BlueElectrum from '../../blue_modules/BlueElectrum'; import * as BlueElectrum from '../../blue_modules/BlueElectrum';
jest.setTimeout(500 * 1000);
afterAll(async () => { afterAll(async () => {
// after all tests we close socket so the test suite can actually terminate // after all tests we close socket so the test suite can actually terminate
BlueElectrum.forceDisconnect(); BlueElectrum.forceDisconnect();
@ -14,8 +16,6 @@ beforeAll(async () => {
await BlueElectrum.connectMain(); await BlueElectrum.connectMain();
}); });
jasmine.DEFAULT_TIMEOUT_INTERVAL = 500 * 1000;
describe('Watch only wallet', () => { describe('Watch only wallet', () => {
it('can fetch balance', async () => { it('can fetch balance', async () => {
const w = new WatchOnlyWallet(); const w = new WatchOnlyWallet();

View File

@ -1,18 +0,0 @@
global.beforeEach(() => {
if (process.env.TRAVIS || process.env.CI) return;
process.stdout.write(jasmine.currentTest.fullName + '...\r');
});
global.afterEach(() => {
if (process.env.TRAVIS || process.env.CI) return;
if (jasmine.currentTest.failedExpectations.length) {
process.stdout.write(jasmine.currentTest.fullName + '...FAIL\n');
} else {
process.stdout.write(jasmine.currentTest.fullName + '...OK\n');
}
});
jasmine.getEnv().addReporter({
specStarted: result => (jasmine.currentTest = result),
specDone: result => (jasmine.currentTest = result),
});

View File

@ -2,6 +2,8 @@ import assert from 'assert';
import wif from 'wif'; import wif from 'wif';
import bip38 from 'bip38'; import bip38 from 'bip38';
jest.setTimeout(180 * 1000);
it('bip38 decodes', async () => { it('bip38 decodes', async () => {
const encryptedKey = '6PRVWUbkzq2VVjRuv58jpwVjTeN46MeNmzUHqUjQptBJUHGcBakduhrUNc'; const encryptedKey = '6PRVWUbkzq2VVjRuv58jpwVjTeN46MeNmzUHqUjQptBJUHGcBakduhrUNc';
const decryptedKey = await bip38.decryptAsync( const decryptedKey = await bip38.decryptAsync(
@ -23,7 +25,6 @@ it.skip('bip38 decodes slow', async () => {
// run only on CI // run only on CI
return; return;
} }
jasmine.DEFAULT_TIMEOUT_INTERVAL = 3 * 60 * 1000;
const encryptedKey = '6PnU5voARjBBykwSddwCdcn6Eu9EcsK24Gs5zWxbJbPZYW7eiYQP8XgKbN'; const encryptedKey = '6PnU5voARjBBykwSddwCdcn6Eu9EcsK24Gs5zWxbJbPZYW7eiYQP8XgKbN';
let callbackWasCalled = false; let callbackWasCalled = false;

View File

@ -1,6 +1,5 @@
import assert from 'assert';
import DeeplinkSchemaMatch from '../../class/deeplink-schema-match'; import DeeplinkSchemaMatch from '../../class/deeplink-schema-match';
const assert = require('assert');
jest.useFakeTimers();
describe('unit - DeepLinkSchemaMatch', function () { describe('unit - DeepLinkSchemaMatch', function () {
it('hasSchema', () => { it('hasSchema', () => {

View File

@ -5,6 +5,12 @@ const ECPair = ECPairFactory(ecc);
const bitcoin = require('bitcoinjs-lib'); const bitcoin = require('bitcoinjs-lib');
const assert = require('assert'); const assert = require('assert');
const consoleWarnOrig = console.warn;
console.warn = function () {
if (arguments[0].startsWith('WARNING: Sending to a future segwit version address can lead to loss of funds')) return;
return consoleWarnOrig.apply(arguments);
};
describe('Legacy wallet', () => { describe('Legacy wallet', () => {
it('can validate addresses', () => { it('can validate addresses', () => {
const w = new LegacyWallet(); const w = new LegacyWallet();

View File

@ -1,9 +1,8 @@
import assert from 'assert';
import { BitcoinUnit } from '../../models/bitcoinUnits'; import { BitcoinUnit } from '../../models/bitcoinUnits';
import { FiatUnit } from '../../models/fiatUnit'; import { FiatUnit } from '../../models/fiatUnit';
import { _leaveNumbersAndDots, formatBalanceWithoutSuffix, formatBalancePlain, formatBalance } from '../../loc'; import { _leaveNumbersAndDots, formatBalanceWithoutSuffix, formatBalancePlain, formatBalance } from '../../loc';
const assert = require('assert');
const currency = require('../../blue_modules/currency'); const currency = require('../../blue_modules/currency');
jest.useFakeTimers();
describe('Localization', () => { describe('Localization', () => {
it('internal formatter', () => { it('internal formatter', () => {
@ -60,6 +59,7 @@ describe('Localization', () => {
currency._setPreferredFiatCurrency(FiatUnit.USD); currency._setPreferredFiatCurrency(FiatUnit.USD);
if (shouldResetRate) { if (shouldResetRate) {
currency._setExchangeRate('BTC_USD', false); currency._setExchangeRate('BTC_USD', false);
currency._setSkipUpdateExchangeRate();
} }
const actualResult = formatBalanceWithoutSuffix(balance, toUnit, withFormatting); const actualResult = formatBalanceWithoutSuffix(balance, toUnit, withFormatting);
assert.strictEqual(actualResult, expectedResult); assert.strictEqual(actualResult, expectedResult);

View File

@ -1,9 +1,8 @@
import assert from 'assert';
import * as bitcoin from 'bitcoinjs-lib';
import { PayjoinClient } from 'payjoin-client';
import { HDSegwitBech32Wallet } from '../../class'; import { HDSegwitBech32Wallet } from '../../class';
import PayjoinTransaction from '../../class/payjoin-transaction'; import PayjoinTransaction from '../../class/payjoin-transaction';
import { PayjoinClient } from 'payjoin-client';
const bitcoin = require('bitcoinjs-lib');
const assert = require('assert');
jest.useFakeTimers();
const utxos = [ const utxos = [
{ {
@ -105,6 +104,8 @@ describe('PayjoinTransaction', () => {
w, w,
); );
wallet.scheduleBroadcastTx = async function () {}; // mock so no real timers are called
const payjoinRequesterMock = { const payjoinRequesterMock = {
requestPayjoin: async function () { requestPayjoin: async function () {
// should return payjoined PSBT (real result obtained from btcpayserver) // should return payjoined PSBT (real result obtained from btcpayserver)

View File

@ -245,7 +245,7 @@ describe('Watch only wallet', () => {
it('can import Electrum compatible backup wallet, and create a tx with master fingerprint hex with a length of 7', async () => { it('can import Electrum compatible backup wallet, and create a tx with master fingerprint hex with a length of 7', async () => {
const w = new WatchOnlyWallet(); const w = new WatchOnlyWallet();
let str = require('fs').readFileSync('./tests/unit/fixtures/skeleton-electrum-hex-only.txt', 'ascii'); let str = require('fs').readFileSync('./tests/unit/fixtures/skeleton-electrum-hex-only.txt', 'ascii');
str = str.replace('b616be56', '616be56') str = str.replace('b616be56', '616be56');
// console.log(str) // console.log(str)
w.setSecret(str); w.setSecret(str);
w.init(); w.init();
@ -263,7 +263,7 @@ describe('Watch only wallet', () => {
it('will fail to import Electrum compatible backup wallet when fingerprint hex is less than 7', async () => { it('will fail to import Electrum compatible backup wallet when fingerprint hex is less than 7', async () => {
const w = new WatchOnlyWallet(); const w = new WatchOnlyWallet();
let str = require('fs').readFileSync('./tests/unit/fixtures/skeleton-electrum-hex-only.txt', 'ascii'); let str = require('fs').readFileSync('./tests/unit/fixtures/skeleton-electrum-hex-only.txt', 'ascii');
str = str.replace('b616be56', '16be56') str = str.replace('b616be56', '16be56');
w.setSecret(str); w.setSecret(str);
w.init(); w.init();
assert.throws(w.valid, 'invalid fingerprint hex'); assert.throws(w.valid, 'invalid fingerprint hex');
@ -272,7 +272,7 @@ describe('Watch only wallet', () => {
it('will fail to import Electrum compatible backup wallet when fingerprint is an invalid hex value', async () => { it('will fail to import Electrum compatible backup wallet when fingerprint is an invalid hex value', async () => {
const w = new WatchOnlyWallet(); const w = new WatchOnlyWallet();
let str = require('fs').readFileSync('./tests/unit/fixtures/skeleton-electrum-hex-only.txt', 'ascii'); let str = require('fs').readFileSync('./tests/unit/fixtures/skeleton-electrum-hex-only.txt', 'ascii');
str = str.replace('b616be56', 'j16be56') str = str.replace('b616be56', 'j16be56');
w.setSecret(str); w.setSecret(str);
w.init(); w.init();
assert.throws(w.valid, 'invalid fingerprint hex'); assert.throws(w.valid, 'invalid fingerprint hex');