Skip to content

Feature/android e2e tests #78

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

Merged
merged 1 commit into from
Mar 19, 2020
Merged
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
10 changes: 5 additions & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ jobs:
test-ios-vanilla:
<<: *job
macos:
xcode: "9.4.0"
xcode: '10.0.0'
steps:
- checkout
# macOS VMs doesn't support Docker based caches
Expand All @@ -107,7 +107,7 @@ jobs:
test-ios-cocoapods:
<<: *job
macos:
xcode: "9.4.0"
xcode: '10.0.0'
steps:
- checkout
# macOS VMs doesn't support Docker based caches
Expand Down Expand Up @@ -169,19 +169,19 @@ workflows:
only: /.*/
- test-android:
requires:
- build-test-app
- build-test-app
filters:
tags:
only: /.*/
- test-ios-vanilla:
requires:
- build-test-app
- build-test-app
filters:
tags:
only: /.*/
- test-ios-cocoapods:
requires:
- build-test-app
- build-test-app
filters:
tags:
only: /.*/
Expand Down
53 changes: 53 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,59 @@ $ yarn
$ yarn test
```

### End-to-end testing

End-to-end testing is done using [Detox](https://github.com/wix/Detox).

These tests are primarily built to be run on CI. The following instructions describe how to run them locally.

Tested on Mac only.

#### iOS

First, install your dependencies as described in [Step 1: Install dependencies](https://github.com/wix/Detox/blob/master/docs/Introduction.GettingStarted.md#step-1-install-dependencies).

```bash
yarn # install project dependencies
yarn build # build project and integrations
cd packages/test-app
yarn test:ios:cocoapods # or test:ios:vanilla
```

For subsequent runs, you may need to do `rm -rf project && ./generate.sh` before running the test command.

### Android

Set up an Android emulator locally. The easiest way to do this is to install and launch Android Studio, and [manage your virtual devices](https://developer.android.com/studio/run/managing-avds) through the UI.

Check you have at least one emulator installed with `emulator -list-avds`. Now open `./packages/test-app/package.json` and ensure that the `name` under `"android.emu.release"` is one of the emulators in your list (change it if not, but do not commit this change).

```bash
yarn # install project dependencies
yarn build # build project and integrations
cd packages/test-app
SEGMENT_WRITE_TOKEN=test yarn test:android
```

**Note:** A non-empty value of SEGMENT_WRITE_TOKEN is required for Android (but not iOS), because the native library will do a not null check for it and your application will crash.

**Note:** you can also run the emulator in debug mode, but you'll have to start the packager manually. Assuming you've already installed dependencies and built the project:

Build the android project and start the packager:

```bash
cd packages/test-app
SEGMENT_WRITE_TOKEN=test detox build -c android.emu.debug
cd project
yarn start
```

In a new terminal window, run:

```bash
detox test -c android.emu.debug
```

### Architecture

- `packages/core`: the `@segment/analytics-react-native` module
Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,9 @@ await analytics.setup('writeKey', {
| [Firebase](https://www.npmjs.com/package/@segment/analytics-react-native-firebase) | :white_check_mark: | :white_check_mark: | `@segment/analytics-react-native-firebase` |
| [Flurry](https://www.npmjs.com/package/@segment/analytics-react-native-flurry) | :white_check_mark: | :white_check_mark: | `@segment/analytics-react-native-flurry` |
| [Google Analytics](https://www.npmjs.com/package/@segment/analytics-react-native-google-analytics) | :white_check_mark: | :white_check_mark: | `@segment/analytics-react-native-google-analytics` |
| [Intercom](https://www.npmjs.com/package/@segment/analytics-react-native-intercom) | :white_check_mark: | :white_check_mark: | `@segment/analytics-react-native-intercom` |
| [Intercom](https://www.npmjs.com/package/@segment/analytics-react-native-intercom-ios) | :white_check_mark: | :x: | `@segment/analytics-react-native-intercom-ios` |
| [Localytics](https://www.npmjs.com/package/@segment/analytics-react-native-localytics) | :white_check_mark: | :white_check_mark: | `@segment/analytics-react-native-localytics` |
| [Mixpanel](https://www.npmjs.com/package/@segment/analytics-react-native-mixpanel) | :white_check_mark: | :white_check_mark: | `@segment/analytics-react-native-mixpanel` |
| [Quantcast](https://www.npmjs.com/package/@segment/analytics-react-native-quantcast-android) | :x: | :white_check_mark: | `@segment/analytics-react-native-quantcast-android` |
| [Taplytics](https://www.npmjs.com/package/@segment/analytics-react-native-taplytics-ios) | :white_check_mark: | :x: | `@segment/analytics-react-native-taplytics-ios` |
| [Tapstream](https://www.npmjs.com/package/@segment/analytics-react-native-tapstream-android) | :x: | :white_check_mark: | `@segment/analytics-react-native-tapstream-android` |

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"npm-run-all": "^4.1.3",
"prettier": "^1.14.2",
"react": "16.8.3",
"react-native": "0.59.2",
"react-native": "0.59.9",
"rimraf": "^2.6.2"
}
}
4 changes: 4 additions & 0 deletions packages/integrations/integrations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@
ios:
# Only compatible 3.0.x
disabled: true
android:
disabled: true

- name: Intercom
ios:
pod:
version: 1.0.0-beta
android:
disabled: true

- name: Tapstream
ios:
Expand Down
3 changes: 3 additions & 0 deletions packages/integrations/template/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ android {
versionName '1.0'

}
packagingOptions {
pickFirst "META-INF/*"
}
}

repositories {
Expand Down
2 changes: 1 addition & 1 deletion packages/test-app/e2e/main.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ it('sends events and does not crash', async () => {
await sleep(5 * 1000)
})

if (CIRCLE_WORKFLOW_ID) {
if (CIRCLE_WORKFLOW_ID && E2E_TOKEN) {
it('sends events to the webhook', async () => {
await element(by.text('Launch test suite')).tap()
await element(by.text('Flush')).tap()
Expand Down
16 changes: 10 additions & 6 deletions packages/test-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,14 @@
"test:ios:cocoapods": "COCOAPODS=yes ./test_ios.sh",
"test:ios:vanilla": "COCOAPODS=no ./test_ios.sh",
"test:android": "./test_android.sh",
"test": "run-s test:{ios,android}",
"detox:build": "detox build",
"detox:test": "detox test"
"test": "run-s test:{ios,android}"
},
"devDependencies": {
"jest": "^24.5.0",
"react-native-cli": "^2.0.1"
},
"dependencies": {
"detox": "^12.1.1",
"detox": "^12.11.0",
"isomorphic-fetch": "^2.2.1"
},
"detox": {
Expand All @@ -41,11 +39,17 @@
"type": "ios.simulator",
"name": "iPhone X"
},
"android": {
"android.emu.release": {
"binaryPath": "project/android/app/build/outputs/apk/release/app-release.apk",
"build": "cd project/android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release",
"type": "android.emulator",
"name": "Nexus_5X_API_28"
},
"android.emu.debug": {
"binaryPath": "project/android/app/build/outputs/apk/debug/app-debug.apk",
"build": "cd project/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug",
"type": "android.emulator",
"name": "Nexus_5X_API_27"
"name": "Nexus_5X_API_28"
}
}
}
Expand Down
1 change: 0 additions & 1 deletion packages/test-app/seed/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ yarn-error.log
# BUCK
buck-out/
\.buckd/
*.keystore

# fastlane
#
Expand Down
14 changes: 0 additions & 14 deletions packages/test-app/seed/__tests__/App-test.js

This file was deleted.

Binary file not shown.
94 changes: 23 additions & 71 deletions packages/test-app/seed/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,76 +2,6 @@ apply plugin: "com.android.application"

import com.android.build.OutputFile

/**
* The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
* and bundleReleaseJsAndAssets).
* These basically call `react-native bundle` with the correct arguments during the Android build
* cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
* bundle directly from the development server. Below you can see all the possible configurations
* and their defaults. If you decide to add a configuration block, make sure to add it before the
* `apply from: "../../node_modules/react-native/react.gradle"` line.
*
* project.ext.react = [
* // the name of the generated asset file containing your JS bundle
* bundleAssetName: "index.android.bundle",
*
* // the entry file for bundle generation
* entryFile: "index.android.js",
*
* // whether to bundle JS and assets in debug mode
* bundleInDebug: false,
*
* // whether to bundle JS and assets in release mode
* bundleInRelease: true,
*
* // whether to bundle JS and assets in another build variant (if configured).
* // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
* // The configuration property can be in the following formats
* // 'bundleIn${productFlavor}${buildType}'
* // 'bundleIn${buildType}'
* // bundleInFreeDebug: true,
* // bundleInPaidRelease: true,
* // bundleInBeta: true,
*
* // whether to disable dev mode in custom build variants (by default only disabled in release)
* // for example: to disable dev mode in the staging build type (if configured)
* devDisabledInStaging: true,
* // The configuration property can be in the following formats
* // 'devDisabledIn${productFlavor}${buildType}'
* // 'devDisabledIn${buildType}'
*
* // the root of your project, i.e. where "package.json" lives
* root: "../../",
*
* // where to put the JS bundle asset in debug mode
* jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
*
* // where to put the JS bundle asset in release mode
* jsBundleDirRelease: "$buildDir/intermediates/assets/release",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in debug mode
* resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in release mode
* resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
*
* // by default the gradle tasks are skipped if none of the JS files or assets change; this means
* // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
* // date; if you have any other folders that you want to ignore for performance reasons (gradle
* // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
* // for example, you might want to remove it from here.
* inputExcludes: ["android/**", "ios/**"],
*
* // override which node gets called and with what additional arguments
* nodeExecutableAndArgs: ["node"],
*
* // supply additional arguments to the packager
* extraPackagerArgs: []
* ]
*/

project.ext.react = [
entryFile: "index.js"
]
Expand All @@ -96,6 +26,16 @@ def enableProguardInReleaseBuilds = false
android {
compileSdkVersion rootProject.ext.compileSdkVersion

signingConfigs {

release {
storeFile file("android.keystore")
storePassword "notSecret"
keyAlias "segmentTesting"
keyPassword "notSecret"
}
}

packagingOptions {
pickFirst "META-INF/*"
}
Expand All @@ -111,6 +51,9 @@ android {
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
testBuildType System.getProperty("testBuildType", "debug") // This will later be used to control the test apk build type
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
splits {
abi {
Expand All @@ -122,8 +65,10 @@ android {
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
proguardFile "${rootProject.projectDir}/../../node_modules/detox/android/detox/proguard-rules-app.pro"
}
}
// applicationVariants are e.g. debug, release
Expand All @@ -139,17 +84,24 @@ android {
}
}
}
lintOptions {
checkReleaseBuilds false
}
}

dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
implementation "com.facebook.react:react-native:+" // From node_modules
implementation "com.android.support:design:27.1.0"
implementation 'com.android.support:multidex:1.0.3'
androidTestImplementation("com.wix:detox:+") { transitive = true }
androidTestImplementation "junit:junit:4.12"
}

// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile
into 'libs'
into "libs"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.testapp;

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);
}
}
Loading