Skip to content

Commit

Permalink
test: Add integration(e2e) test (#424)
Browse files Browse the repository at this point in the history
* init detox e2e test

* Add first e2e test

* add android configurations

* fix detox rn-camera problem

* add CI integration

* update ci settings

* update xcode version

* use legacy build in CI

* prettier xcode output

* update with android

* revert back to origin CI test

* add E2E test in readme

* Update .travis.yml

* update detox guide

* renaming

* update readme

* Update README.md

Co-Authored-By: Thibaut Sardan <33178835+Tbaut@users.noreply.github.com>

* Update .travis.yml

* Update README.md

* fix binary path problem

* remove before each reloading

* rephrase
  • Loading branch information
hanwencheng authored Oct 28, 2019
1 parent 66428c9 commit 0ba9966
Show file tree
Hide file tree
Showing 15 changed files with 629 additions and 22 deletions.
85 changes: 83 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
language: node_js
node_js:
- 8
node_js: 8

cache:
directories:
Expand All @@ -13,3 +12,85 @@ install:
script:
- yarn run lint
- yarn run test

# TODO complete following part to Integrate E2E test

#matrix:
# include:
# - language: objective-c
# osx_image: xcode10.3
#
# branches:
# only:
# - master
#
# cache:
# directories:
# - node_modules
#
# install:
# - brew tap wix/brew
# - brew install applesimutils
# - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash
# - export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
# - nvm install 8
# - nvm use 8
# - nvm alias default 8
# - npm install -g yarn
# - npm install -g react-native-cli
# - npm install -g detox-cli
# - gem install xcpretty
# - yarn
#
# script:
# - detox build -c ios.sim.release
# - detox test -c ios.sim.release
#
# - language: android
## env:
## - REACT_NATIVE_VERSION=0.60.5
# android:
# components:
# - tools
# - platform-tools
# - build-tools-28.0.3
# - android-28
# - extra-google-google_play_services
# - extra-google-m2repository
# - extra-android-m2repository
## - sys-img-x86-android-26
# - sys-img-x86-android-28
#
# cache:
# directories:
# - node_modules
#
# install:
# - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash
# - export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
# - nvm install 8
# - nvm use 8
# - nvm alias default 8
# - npm install -g yarn
# - npm install -g react-native-cli
# - npm install -g detox-cli
# - yes | sdkmanager "build-tools;28.0.3"
# - yarn
#
# script:
# - detox build -c android.emu.release
# - detox test -c android.emu.release
#
# - language: node_js
# node_js: 8
#
# cache:
# directories:
# - node_modules
#
# install:
# - yarn
#
# script:
# - yarn run lint
# - yarn run test
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,44 @@ Corresponding data:
}
```

#### Integration Test

Parity Signer is integrated with [Detox](https://github.com/wix/Detox) E2E testing. Detox has very detailed [documentation](https://github.com/wix/Detox/blob/master/docs/README.md).

First make sure `detox-cli` is installed as global dependency with

```
yarn global add detox-cli
```

##### Complete Test

1. run react native server with `yarn start`

2. run `yarn e2e:ios` or `yarn e2e:android`.

##### Develop and Test
Details please refer to Detox official guide [here](https://github.com/wix/Detox/blob/master/docs/Guide.DevelopingWhileWritingTests.md)

Once you have run `yarn ios` you do not need to build it, just run:
```shell
yarn test-e2e:ios
```
This command will open another simulator with the pre-defined configurations.

Re-run tests without re-installing the app
```
yarn test-e2e:ios --reuse
```

If you want to use another specific emulator/simulator than those defined in the configuration, add `--device-name` flag (on Android API version is needed), for example:
```
yarn test-e2e:ios --device-name iPhone X
yarn test-e2e:android --device-name Pixel_2_API_28
```

On Android please replace `ios` with `android`, currently Detox's Android 0.60.x support is in progress, if there is an error, try to build it again with `yarn build-e2e:android`

### Troubleshooting

#### `No dimension set for key window` on Android < 5.0
Expand Down
19 changes: 17 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ def enableSeparateBuildPerCPUArchitecture = false
def enableProguardInReleaseBuilds = false

android {
compileSdkVersion 28
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
Expand All @@ -107,7 +108,7 @@ android {

defaultConfig {
applicationId "io.parity.signer"
minSdkVersion 16
minSdkVersion 18
missingDimensionStrategy 'react-native-camera', 'general'
targetSdkVersion 28
versionCode 309
Expand All @@ -119,6 +120,8 @@ android {
pickFirst 'lib/x86_64/libjsc.so'
pickFirst 'lib/arm64-v8a/libjsc.so'
}
testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
signingConfigs {
release {
Expand Down Expand Up @@ -146,6 +149,8 @@ android {
release {
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
// Detox-specific additions to pro-guard
// proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro"
}
}
// applicationVariants are e.g. debug, release
Expand Down Expand Up @@ -179,6 +184,16 @@ dependencies {
} else {
implementation 'org.webkit:android-jsc:+'
}
androidTestImplementation('com.wix:detox:+') { transitive = true }
androidTestImplementation 'junit:junit:4.12'
}

configurations.all {
resolutionStrategy {
// the line below is required for Detox since version 14.5.0;
// it should removed as soon as the project compiles without it
force 'androidx.annotation:annotation:1.0.0'
}
}

// Run this once to be able to run the application with BUCK
Expand Down
24 changes: 24 additions & 0 deletions android/app/src/androidTest/java/io/parity/signer/DetoxTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.parity.signer;

import com.wix.detox.Detox;

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<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false);

@Test
public void runDetoxTests() {
Detox.runTests(mActivityRule);
}
}
20 changes: 16 additions & 4 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
buildscript {
ext {
buildToolsVersion = "28.0.3"
minSdkVersion = 16
minSdkVersion = 18
compileSdkVersion = 28
targetSdkVersion = 28
supportLibVersion = "28.0.0"
kotlinVersion = '1.3.41'
}

repositories {
google()
jcenter()
}
dependencies {
classpath('com.android.tools.build:gradle:3.4.2')

classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
Expand All @@ -35,6 +35,10 @@ allprojects {
// Android JSC is installed from npm
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"
}
}
}

Expand All @@ -47,4 +51,12 @@ subprojects {
}
}
}
}
afterEvaluate {project ->
if (project.hasProperty("android")) {
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
}
}
}
}
6 changes: 6 additions & 0 deletions e2e/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"setupFilesAfterEnv": ["./init.js"],
"testEnvironment": "node",
"reporters": ["detox/runners/jest/streamlineReporter"],
"verbose": true
}
11 changes: 11 additions & 0 deletions e2e/firstTest.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import testIDs from "./testIDs";

describe('Load test', () => {
it('should have account list screen', async () => {
await expect(element(by.id(testIDs.TacScreen.tacView))).toBeVisible();
await element(by.id(testIDs.TacScreen.agreePrivacyButton)).tap();
await element(by.id(testIDs.TacScreen.agreeTacButton)).tap();
await element(by.id(testIDs.TacScreen.nextButton)).tap();
await expect(element(by.id(testIDs.AccountListScreen.accountList))).toBeVisible();
});
});
25 changes: 25 additions & 0 deletions e2e/init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const detox = require('detox');
const config = require('../package.json').detox;
const adapter = require('detox/runners/jest/adapter');
const specReporter = require('detox/runners/jest/specReporter');

// Set the default timeout
jest.setTimeout(120000);
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);

beforeAll(async () => {
await detox.init(config);
});

beforeEach(async () => {
await adapter.beforeEach();
});

afterAll(async () => {
await adapter.afterAll();
await detox.cleanup();
});
13 changes: 13 additions & 0 deletions e2e/testIDs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const testIDs = {
TacScreen: {
tacView: 'tac_view',
agreeTacButton: 'tac_agree',
agreePrivacyButton: 'tac_privacy',
nextButton: 'tac_next'
},
AccountListScreen: {
accountList: 'accountList',
}
};

export default testIDs;
50 changes: 48 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@
"ios": "yarn run build-rust-ios && react-native run-ios",
"lint": "npx eslint ./src/ --ext .js,.jsx",
"lint:fix": "npx eslint ./src/ --ext .js,.jsx --fix",
"postinstall": "npx jetify",
"postinstall": "npx jetify && chmod +x ./scripts/fix-rn-camera-path.sh && ./scripts/fix-rn-camera-path.sh ./node_modules/react-native-camera/ios/RNCamera.xcodeproj/project.pbxproj",
"start": "NODE_OPTIONS=--max_old_space_size=8192 react-native start",
"test": "jest"
"test": "jest",
"build-e2e:android": "detox build -c android.emu.debug",
"test-e2e:android": "detox test -c android.emu.debug",
"e2e:android": "yarn run build-e2e:android && yarn run test-e2e:android",
"build-e2e:ios": "detox build -c ios.sim.debug",
"test-e2e:ios": "detox test -c ios.sim.debug",
"e2e:ios": "yarn run build-e2e:ios && yarn run test-e2e:ios"
},
"husky": {
"hooks": {
Expand Down Expand Up @@ -67,6 +73,7 @@
"babel-eslint": "10.0.3",
"babel-jest": "^24.9.0",
"babel-plugin-rewrite-require": "^1.14.5",
"detox": "^14.5.0",
"eslint": "^6.3.0",
"eslint-config-prettier": "^6.2.0",
"eslint-plugin-prettier": "^3.1.0",
Expand All @@ -80,5 +87,44 @@
},
"resolutions": {
"@react-native-community/eslint-config/babel-eslint": "10.0.3"
},
"detox": {
"configurations": {
"ios.sim.debug": {
"binaryPath": "ios/build/NativeSigner/Build/Products/Debug-iphonesimulator/NativeSigner.app",
"build": "xcodebuild -project ios/NativeSigner.xcodeproj -scheme NativeSigner -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build/NativeSigner",
"type": "ios.simulator",
"device": {
"type": "iPhone SE"
}
},
"ios.sim.release": {
"binaryPath": "ios/build/NativeSigner/Build/Products/Release-iphonesimulator/NativeSigner.app",
"build": "xcodebuild -project ios/NativeSigner.xcodeproj -scheme NativeSigner -configuration Release -sdk iphonesimulator -derivedDataPath ios/build/NativeSigner -UseModernBuildSystem=NO | xcpretty -t && exit ${PIPESTATUS[0]}",
"type": "ios.simulator",
"device": {
"type": "iPhone SE"
}
},
"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": "Nexus_5_API_28"
}
},
"android.emu.release": {
"binaryPath": "android/app/build/outputs/apk/release/app-release.apk",
"build": "cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd ..",
"type": "android.emulator",
"device": {
"avdName": "Nexus_5_API_28"
}
}
},
"runner-config": "e2e/config.json",
"test-runner": "jest"
}
}
Loading

0 comments on commit 0ba9966

Please sign in to comment.