Skip to content
This repository has been archived by the owner on Jan 13, 2023. It is now read-only.

Commit

Permalink
chore(tests): Add optional Detox end-to-end tests (#146 by @robinheinze)
Browse files Browse the repository at this point in the history
[skip ci]
  • Loading branch information
robinheinze authored and jamonholmgren committed Mar 11, 2019
1 parent bedf447 commit 77d714b
Show file tree
Hide file tree
Showing 12 changed files with 262 additions and 33 deletions.
55 changes: 55 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ defaults: &defaults
- image: circleci/node:10.11
working_directory: ~/repo

mac: &mac
macos:
xcode: "10.1.0"
working_directory: ~/repo

version: 2
jobs:
setup:
Expand Down Expand Up @@ -50,6 +55,55 @@ jobs:
name: Run tests
command: yarn ci:test # this command will be added to/found in your package.json scripts

detox:
<<: *mac
steps:
- checkout
- restore_cache:
name: Restore node modules
keys:
- v1-dependencies-mac-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-mac-
- run:
name: Install dependencies
command: |
yarn install
- save_cache:
name: Save node modules
paths:
- node_modules
key: v1-dependencies-mac-{{ checksum "package.json" }}
- run:
name: Install React Native CLI and Ignite CLI
command: |
sudo npm i -g ignite-cli react-native-cli detox-cli
- run:
name: Change Permissions
command: sudo chown -R $(whoami) /Users/distiller/.config/
- run:
name: Install applesimutils
command: brew tap wix/brew && brew install applesimutils
- run:
name: Install fbsimctl
command: brew tap facebook/fb
- run:
name: Create temp directory
command: mkdir tempApp
- run:
name: Ignite app
command: cd tempApp && ignite new DetoxTests --detox --skip-git -b ../
- run:
name: Build Detox in ignited app
command: cd tempApp/DetoxTests && yarn ci:build:e2e
- run:
name: Run detox tests in ignited app
command: cd tempApp/DetoxTests && yarn ci:test:e2e
- run:
name: Remove temp directory
command: rm -rf tempApp


publish:
<<: *defaults
steps:
Expand All @@ -74,6 +128,7 @@ workflows:
- tests:
requires:
- setup
- detox
- publish:
requires:
- tests
Expand Down
38 changes: 33 additions & 5 deletions boilerplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ async function install(context) {
reactNative,
print,
system,
template
template,
prompt,
} = context
const { colors } = print
const { red, yellow, bold, gray, blue } = colors
const { red, yellow, bold, gray, blue, cyan } = colors
const isWindows = process.platform === 'win32'
const isMac = process.platform === 'darwin'

const perfStart = (new Date()).getTime()

Expand All @@ -53,12 +56,29 @@ async function install(context) {
const filesToRemove = [
'__tests__',
'App.js',
'.babelrc',
'.flowconfig',
'.buckconfig',
]
filesToRemove.map(filesystem.remove)

let includeDetox = false
if (isMac) {
const askAboutDetox = parameters.options.detox === undefined
includeDetox = askAboutDetox ? await prompt.confirm('Would you like to include Detox end-to-end tests?') : parameters.options.detox === true

if (includeDetox) {
print.info(`You'll love Detox for testing your app! There are some additional requirements to install, so make sure to check out ${cyan('e2e/README.md')}!`)
}
} else {
if (parameters.options.detox === true) {
if (isWindows) {
print.info("Skipping Detox because it is only supported on macOS, but you're running Windows")
} else {
print.info("Skipping Detox because it is only supported on macOS")
}
}
}

// copy our App, Tests & storybook directories
spinner.text = '▸ copying files'
spinner.start()
Expand All @@ -77,6 +97,10 @@ async function install(context) {
filesystem.copy(`${__dirname}/boilerplate/bin`, `${process.cwd()}/bin`, {
overwrite: true,
})
includeDetox && filesystem.copy(`${__dirname}/boilerplate/e2e`, `${process.cwd()}/e2e`, {
overwrite: true,
matching: '!*.ejs'
})
spinner.stop()

// generate some templates
Expand All @@ -88,17 +112,21 @@ async function install(context) {
{ template: '.gitignore', target: '.gitignore' },
{ template: '.prettierignore', target: '.prettierignore' },
{ template: '.solidarity', target: '.solidarity' },
{ template: '.babelrc', target: '.babelrc' },
{ template: 'tsconfig.json', target: 'tsconfig.json' },
{ template: 'tslint.json', target: 'tslint.json' },
{ template: 'app/app.tsx.ejs', target: 'app/app.tsx' }
{ template: 'app/app.tsx.ejs', target: 'app/app.tsx' },
{ template: 'app/screens/first-example-screen/first-example-screen.tsx.ejs', target: 'app/screens/first-example-screen/first-example-screen.tsx' },
{ template: 'app/screens/second-example-screen/second-example-screen.tsx.ejs', target: 'app/screens/second-example-screen/second-example-screen.tsx' },
]
const templateProps = {
name,
igniteVersion: ignite.version,
reactNativeVersion: rnInstall.version,
vectorIcons: false,
animatable: false,
i18n: false
i18n: false,
includeDetox,
}
await ignite.copyBatch(context, templates, templateProps, {
quiet: true,
Expand Down
24 changes: 24 additions & 0 deletions boilerplate/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"presets": ["module:metro-react-native-babel-preset"],
"env": {
"production": {
}
},
"plugins": [
[
"transform-inline-environment-variables",
{
"include": ["NODE_ENV", "API"]
}
],
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
],
[
"@babel/plugin-proposal-optional-catch-binding"
]
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ export class FirstExampleScreen extends React.Component<FirstExampleScreenProps,

render() {
return (
<% if (props.includeDetox) { -%>
<View testID="FirstExampleScreen" style={FULL}>
<% } else { -%>
<View style={FULL}>
<% } -%>
<StatusBar barStyle="light-content" />
<Wallpaper />
<SafeAreaView style={FULL}>
Expand Down Expand Up @@ -113,6 +117,9 @@ export class FirstExampleScreen extends React.Component<FirstExampleScreenProps,
<SafeAreaView style={FOOTER}>
<View style={FOOTER_CONTENT}>
<Button
<% if (props.includeDetox) { -%>
testID="next-screen-button"
<% } -%>
style={CONTINUE}
textStyle={CONTINUE_TEXT}
tx="firstExampleScreen.continue"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,11 @@ export class SecondExampleScreen extends React.Component<SecondExampleScreenProp

render() {
return (
<% if (props.includeDetox) { -%>
<View testID="SecondExampleScreen" style={FULL}>
<% } else { -%>
<View style={FULL}>
<% } -%>
<Wallpaper />
<SafeAreaView style={FULL}>
<Screen style={CONTAINER} backgroundColor={color.transparent} preset="scrollStack">
Expand Down
61 changes: 61 additions & 0 deletions boilerplate/e2e/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Detox End-To-End Testing

## Setup

To get your Detox tests up and running, you'll need to install some global dependencies:

1. Install the latest version of [Homebrew](https://brew.sh/)
2. Make sure you have Node installed (at least 8.6.0). If you don't:

If you use NVM:
```bash
nvm install node
```

Or if you'd prefer to install directly from Homebrew
```bash
brew update && brew install node
```


3. Install `applesimutils, which will allow Detox to communicate with the iOS simulator:

```bash
brew tap wix/brew && brew install applesimutils
```

4. Install the Detox CLI

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

## Adding tests

We've gotten you started with `./e2e/firstTest.spec.js`, which tests that the two main example screens render properly.

Note that in order to pick up elements by ID, we've added the `testID` prop to the component.

## Running tests

1. Start the packager

```
yarn start
```

2. Run the app

In a separate terminal window from the packager:

```
yarn build:e2e
```

3. Run the tests

```
yarn test:e2e
```

For more information, make sure to check out the official [Detox Docs](https://github.com/wix/Detox/blob/master/docs/README.md)
4 changes: 4 additions & 0 deletions boilerplate/e2e/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"setupFilesAfterEnv": ["./init.js"],
"testEnvironment": "node"
}
17 changes: 17 additions & 0 deletions boilerplate/e2e/firstTest.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// For more info on how to write Detox tests, see the official docs:
// https://github.com/wix/Detox/blob/master/docs/README.md

describe('Example', () => {
beforeEach(async () => {
await device.reloadReactNative();
});

it('should have welcome screen', async () => {
await expect(element(by.id("FirstExampleScreen"))).toBeVisible();
});

it('should go to next screen after tap', async () => {
await element(by.id('next-screen-button')).tap();
await expect(element(by.id('SecondExampleScreen'))).toBeVisible();
});
});
19 changes: 19 additions & 0 deletions boilerplate/e2e/init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const detox = require('detox');
const config = require('../package.json').detox;
const adapter = require('detox/runners/jest/adapter');

jest.setTimeout(120000);
jasmine.getEnv().addReporter(adapter);

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

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

afterAll(async () => {
await adapter.afterAll();
await detox.cleanup();
});
Loading

0 comments on commit 77d714b

Please sign in to comment.