Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: detox #244

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .detoxrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"testRunner": "jest",
"runnerConfig": "e2e/config.json",
"skipLegacyWorkersInjection": true,
"apps": {
"ios.debug": {
"type": "ios.app",
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/bitkit.app",
"build": "xcodebuild -workspace ios/bitkit.xcworkspace -scheme bitkit -sdk iphonesimulator -derivedDataPath ios/build"
},
"ios.release": {
"type": "ios.app",
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/bitkit.app",
"build": "xcodebuild -configuration Release -workspace ios/bitkit.xcworkspace -scheme bitkit -sdk iphonesimulator -derivedDataPath ios/build"
},
"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",
"binaryPath": "android/app/build/outputs/apk/release/app-release.apk",
"build": "cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd .."
}
},
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "iPhone 13"
}
},
"emulator": {
"type": "android.emulator",
"device": {
"avdName": "Pixel_API_29_AOSP"
}
}
},
"configurations": {
"ios.debug": {
"device": "simulator",
"app": "ios.debug"
},
"ios.release": {
"device": "simulator",
"app": "ios.release"
},
"android.debug": {
"device": "emulator",
"app": "android.debug"
},
"android.release": {
"device": "emulator",
"app": "android.release"
}
}
}
5 changes: 3 additions & 2 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ about: Create a report to help us improve
title: ''
labels: bug
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:

1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
Expand All @@ -24,7 +24,8 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.

**Smartphone (please complete the following information):**
- OS: [e.g. iOS, Android]

- OS: [e.g. iOS, Android]

**Additional context**
Add any other context about the problem here.
81 changes: 81 additions & 0 deletions .github/workflows/e2e-ios.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: e2e-ios

on:
pull_request:
branches:
- 'master'
push:
branches:
- 'master'

jobs:
build:
runs-on: macos-12
# timeout-minutes: 15

# env:
# DEVELOPER_DIR: /Applications/Xcode_11.2.app

steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 1

# - name: Xcode
# uses: devbotsxyz/xcode-select@v1

- name: Install SSH key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.TEST_USER_SSH_KEY }}
known_hosts: ${{ secrets.TEST_USER_KNOWN_HOSTS }}

- name: Use NPM Token with organization read access
uses: dkershner6/use-npm-token-action@v1
with:
token: '${{ secrets.NPMJS_READ }}'

- name: Node
uses: actions/setup-node@v3
with:
node-version: 16
cache: 'yarn' # cache packages, but not node_modules

- name: Cache node modules
uses: actions/cache@v3
id: cache-nm
with:
path: node_modules
key: node-modules-${{ hashFiles('**/yarn.lock') }}

- name: Rebuild detox
if: steps.cache-nm.outputs.cache-hit == 'true'
run: yarn detox clean-framework-cache && yarn detox build-framework-cache

- name: Install Dependencies
if: steps.cache-nm.outputs.cache-hit != 'true'
run: yarn install

- name: Cache Pods
uses: actions/cache@v3
id: podcache
with:
path: ios/Pods
key: pods-${{ hashFiles('**/Podfile.lock') }}

- name: Update Pods
run: |
gem update cocoapods xcodeproj
cd ios && pod install && cd ..

- run: brew tap wix/brew
- run: brew install applesimutils
- run: yarn detox build e2e --configuration ios.release
- run: yarn detox test e2e --configuration ios.release --cleanup --debug-synchronization 500 --record-videos all --take-screenshots all --record-logs all

- uses: actions/upload-artifact@v3
if: failure()
with:
name: e2e-test-videos
path: ./artifacts/
2 changes: 1 addition & 1 deletion .github/workflows/lint-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Use NPM Token with organization read access
uses: dkershner6/use-npm-token-action@v1
with:
token: "${{ secrets.NPMJS_READ }}"
token: '${{ secrets.NPMJS_READ }}'

- name: Install Node.js dependencies
run: yarn install
Expand Down
7 changes: 7 additions & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ import org.apache.tools.ant.taskdefs.condition.Os

project.ext.react = [
enableHermes: true, // clean and rebuild if changing
bundleInDebug: true,
]

apply from: "../../node_modules/react-native/react.gradle"
Expand Down Expand Up @@ -143,6 +144,8 @@ android {
multiDexEnabled true
missingDimensionStrategy 'react-native-camera', 'general'
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
testBuildType System.getProperty('testBuildType', 'debug')
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'

if (isNewArchitectureEnabled()) {
// We configure the NDK build only if you decide to opt-in for the New Architecture.
Expand Down Expand Up @@ -269,6 +272,7 @@ dependencies {
implementation "com.facebook.react:react-native:+" // From node_modules
implementation "androidx.multidex:multidex:2.0.1"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation "com.facebook.soloader:soloader:0.10.4+"

debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
Expand All @@ -290,6 +294,9 @@ dependencies {
} else {
implementation jscFlavor
}

androidTestImplementation('com.wix:detox:+')
implementation 'androidx.appcompat:appcompat:1.4.2'
}

if (isNewArchitectureEnabled()) {
Expand Down
33 changes: 33 additions & 0 deletions android/app/src/androidTest/java/com/bitkit/DetoxTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.bitkit;

import com.wix.detox.Detox;
import com.wix.detox.config.DetoxConfig;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;

@RunWith(AndroidJUnit4.class)
@LargeTest
public class DetoxTest {
@Rule
public ActivityTestRule<com.facebook.react.devsupport.DevSettingsActivity> mActivityRule = new ActivityTestRule<>(com.facebook.react.devsupport.DevSettingsActivity.class, false, false);

@Test
public void runDetoxTests() {
// 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 = (BuildConfig.DEBUG ? 180 : 60);

Detox.runTests(mActivityRule, detoxConfig);
}
}
3 changes: 2 additions & 1 deletion android/app/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
<application
android:usesCleartextTraffic="true"
tools:targetApi="28"
tools:ignore="GoogleAppIndexingWarning">
tools:ignore="GoogleAppIndexingWarning"
android:networkSecurityConfig="@xml/network_security_config">
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false" />
</application>
</manifest>
7 changes: 7 additions & 0 deletions android/app/src/main/res/xml/network_security_config.xml
Original file line number Diff line number Diff line change
@@ -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>
31 changes: 31 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,36 @@ allprojects {
google()
jcenter() // needed for @react-native-community/blur
maven { url 'https://www.jitpack.io' }
maven {
// All of Detox' artifacts are provided via the npm module
url "$rootDir/../node_modules/detox/Detox-android"
}
}
}

// adding this section to fix "npx detox build --configuration android.debug" command
// https://stackoverflow.com/questions/71153204
subprojects {
ext {
compileSdk = rootProject.ext.compileSdkVersion
minSdk = rootProject.ext.minSdkVersion
targetSdk = rootProject.ext.targetSdkVersion
}
afterEvaluate { subproject ->
if((subproject.plugins.hasPlugin('android') || subproject.plugins.hasPlugin('android-library'))) {
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
}

// https://github.com/Shopify/react-native-skia/issues/728
packagingOptions {
resources.excludes.add("META-INF/*")
}
}
}
}
}
9 changes: 9 additions & 0 deletions e2e/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"maxWorkers": 1,
"testEnvironment": "./environment",
"testRunner": "jest-circus/runner",
"testTimeout": 120000,
"testRegex": "\\.e2e\\.js$",
"reporters": ["detox/runners/jest/streamlineReporter"],
"verbose": true
}
23 changes: 23 additions & 0 deletions e2e/environment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
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;
18 changes: 18 additions & 0 deletions e2e/newWallet.e2e.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
describe('New Wallet', () => {
beforeAll(async () => {
await device.launchApp();
});

beforeEach(async () => {
await device.reloadReactNative();
});

it('should create new wallet', async () => {
await expect(element(by.id('GetStarted'))).toBeVisible();
await expect(element(by.id('SkipIntro'))).toBeVisible();
await element(by.id('SkipIntro')).tap();
await waitFor(element(by.id('NewWallet'))).toBeVisible();
await element(by.id('NewWallet')).tap();
await waitFor(element(by.id('EmptyWallet'))).toBeVisible();
});
});
4 changes: 2 additions & 2 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ PODS:
- React-Core
- react-native-flipper (0.162.0):
- React-Core
- react-native-image-picker (4.10.0):
- react-native-image-picker (4.8.5):
- React-Core
- react-native-ldk (0.0.53):
- React
Expand Down Expand Up @@ -792,7 +792,7 @@ SPEC CHECKSUMS:
react-native-camera: 3eae183c1d111103963f3dd913b65d01aef8110f
react-native-document-picker: f68191637788994baed5f57d12994aa32cf8bf88
react-native-flipper: 7eeb9b59b667dd0619372c7349cf7c78032d1de2
react-native-image-picker: 4bc9ed38c8be255b515d8c88babbaf74973f91a8
react-native-image-picker: cd420f97f6ed6ff74fc4686d27dbcfdbd051db91
react-native-ldk: 19c21a681ad35c1e236dda7ffbdeaa745fb1a789
react-native-libsodium: f4eba037c4ddf73f86b08075452cacb957256147
react-native-mmkv: 1265a348a4711097ba29c8bcefd5971f48220f2b
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "^2.6.0",
"react-native-haptic-feedback": "^1.13.1",
"react-native-image-picker": "^4.8.4",
"react-native-image-picker": "4.8.5",
"react-native-keyboard-accessory": "^0.1.16",
"react-native-keychain": "^8.0.0",
"react-native-mmkv": "^2.4.1",
Expand Down Expand Up @@ -130,6 +130,7 @@
"babel-jest": "^27.0.0",
"babel-plugin-transform-remove-console": "^6.9.4",
"browserify-zlib": "^0.2.0",
"detox": "19.12.1",
"dns.js": "^1.0.1",
"esbuild": "^0.15.7",
"eslint": "^8.22.0",
Expand Down
2 changes: 1 addition & 1 deletion src/screens/Activity/EmptyWallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const EmptyWallet = (): ReactElement => {
}, [height]);

return (
<View style={root}>
<View style={root} testID="EmptyWallet">
<Headline>
To get started send <Headline color="brand">Bitcoin</Headline> to your
wallet.
Expand Down
Loading