diff --git a/.travis.yml b/.travis.yml
index ac5343c0ef..3e29dd2de6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -56,6 +56,16 @@ matrix:
- ./scripts/install.android.sh
script:
- ./scripts/ci.android.sh
+ # Example Projects
+ - language: objective-c
+ os: osx
+ osx_image: xcode9
+ env:
+ - REACT_NATIVE_VERSION=0.49.3
+ install:
+ - ./scripts/install.ios.sh
+ script:
+ - ./scripts/demo-projects.ios.sh
branches:
only:
diff --git a/detox/local-cli/detox-test.js b/detox/local-cli/detox-test.js
index d18b39657d..8eeb1b2e2a 100644
--- a/detox/local-cli/detox-test.js
+++ b/detox/local-cli/detox-test.js
@@ -4,13 +4,12 @@ const program = require('commander');
const path = require('path');
const cp = require('child_process');
program
- .option('-r, --runner [runner]', 'Test runner (supports mocha and jest)')
- .option('-o, --runner-config [config]', 'Test runner config file', 'mocha.opts')
+ .option('-o, --runner-config [config]', `Test runner config file, defaults to e2e/mocha.opts for mocha and e2e/config.json' for jest`)
.option('-l, --loglevel [value]', 'info, debug, verbose, silly, wss')
.option('-c, --configuration [device configuration]', 'Select a device configuration from your defined configurations,'
+ 'if not supplied, and there\'s only one configuration, detox will default to it')
- .option('-r, --reuse', 'Reuse existing installed app (do not delete and re-install) for a faster run.', false)
- .option('-u, --cleanup', 'Shutdown simulator when test is over, useful for CI scripts, to make sure detox exists cleanly with no residue', false)
+ .option('-r, --reuse', 'Reuse existing installed app (do not delete and re-install) for a faster run.')
+ .option('-u, --cleanup', 'Shutdown simulator when test is over, useful for CI scripts, to make sure detox exists cleanly with no residue')
.option('-d, --debug-synchronization [value]',
'When an action/expectation takes a significant amount of time use this option to print device synchronization status. '
+ 'The status will be printed if the action takes more than [value]ms to complete')
@@ -19,13 +18,10 @@ program
.parse(process.argv);
const config = require(path.join(process.cwd(), 'package.json')).detox;
-const testFolder = config.specs || 'e2e';
-
-let runner = config.runner || 'mocha';
-if (program.runner) {
- runner = program.runner;
-}
+const testFolder = config.specs || 'e2e';
+const runner = config['test-runner'] || 'mocha';
+const runnerConfig = program.runnerConfig || config['runner-config'] || getDefaultRunnerConfig();
if (typeof program.debugSynchronization === "boolean") {
program.debugSynchronization = 3000;
@@ -48,18 +44,19 @@ function runMocha() {
const cleanup = program.cleanup ? `--cleanup` : '';
const reuse = program.reuse ? `--reuse` : '';
const artifactsLocation = program.artifactsLocation ? `--artifacts-location ${program.artifactsLocation}` : '';
+ const configFile = runnerConfig ? `--opts ${runnerConfig}` : '';
const debugSynchronization = program.debugSynchronization ? `--debug-synchronization ${program.debugSynchronization}` : '';
- const command = `node_modules/.bin/mocha ${testFolder} --opts ${testFolder}/${program.runnerConfig} ${configuration} ${loglevel} ${cleanup} ${reuse} ${debugSynchronization} ${artifactsLocation}`;
+ const command = `node_modules/.bin/mocha ${testFolder} ${configFile} ${configuration} ${loglevel} ${cleanup} ${reuse} ${debugSynchronization} ${artifactsLocation}`;
console.log(command);
cp.execSync(command, {stdio: 'inherit'});
}
function runJest() {
- const command = `node_modules/.bin/jest ${testFolder} --runInBand`;
+ const configFile = runnerConfig ? `--config=${runnerConfig}` : '';
+ const command = `node_modules/.bin/jest ${testFolder} ${configFile} --runInBand`;
console.log(command);
-
cp.execSync(command, {
stdio: 'inherit',
env: Object.assign({}, process.env, {
@@ -72,3 +69,17 @@ function runJest() {
})
});
}
+
+
+function getDefaultRunnerConfig() {
+ let defaultConfig;
+ switch (runner) {
+ case 'mocha':
+ defaultConfig = 'e2e/mocha.opts';
+ break;
+ case 'jest':
+ defaultConfig = 'e2e/config.json'
+ }
+ console.log(`Missing 'runner-config' value in detox config in package.json, using '${defaultConfig}' as default for ${runner}`);
+ return defaultConfig;
+}
\ No newline at end of file
diff --git a/detox/src/ios/earlgreyapi/GREYMatchers.js b/detox/src/ios/earlgreyapi/GREYMatchers.js
index 2b8ab723e5..5786930b81 100644
--- a/detox/src/ios/earlgreyapi/GREYMatchers.js
+++ b/detox/src/ios/earlgreyapi/GREYMatchers.js
@@ -274,8 +274,8 @@ to a minimum value.
}
/*Matcher for UI element that is sufficiently visible to the user. EarlGrey considers elements
-with visible area percentage greater than @c kElementSufficientlyVisiblePercentage (0.75)
-to be sufficiently visible.
+that are more than @c kElementSufficientlyVisiblePercentage (75 %) visible areawise to be
+sufficiently visible.
@return A matcher intialized with a visibility percentage that confirms an element is
sufficiently visible.
@@ -290,7 +290,7 @@ sufficiently visible.
};
}
- /*Matcher for UI element that are not visible to the user i.e. has a zero visible area.
+ /*Matcher for UI element that is not visible to the user at all i.e. it has a zero visible area.
@return A matcher for verifying if an element is not visible.
*/static matcherForNotVisible() {
@@ -304,13 +304,11 @@ sufficiently visible.
};
}
- /*Matcher for UI element that matches EarlGrey's criteria for user interaction currently it must
+ /*Matcher for UI element that matches EarlGrey's criteria for user interaction. Currently it must
satisfy at least the following criteria:
-
-- At least a few pixels of the element's UI are visible.
-- The element's accessibility activation point OR the center of the element's visible area
-is visible.
-
+1) At least a few pixels of the element are visible to the user.
+2) The element's accessibility activation point OR the center of the element's visible area
+is completely visible.
@return A matcher that checks if a UI element is interactable.
*/static matcherForInteractable() {
diff --git a/detox/src/utils/argparse.js b/detox/src/utils/argparse.js
index a2f1408d51..c40ddbc9ea 100644
--- a/detox/src/utils/argparse.js
+++ b/detox/src/utils/argparse.js
@@ -8,6 +8,9 @@ function getArgValue(key) {
} else {
const camelCasedKey = key.replace(/(\-\w)/g, (m) => m[1].toUpperCase());
value = process.env[camelCasedKey];
+ if (value === 'undefined') {
+ value = undefined;
+ }
}
return value;
diff --git a/detox/src/utils/argparse.test.js b/detox/src/utils/argparse.test.js
index b230418279..cce7ffeb94 100644
--- a/detox/src/utils/argparse.test.js
+++ b/detox/src/utils/argparse.test.js
@@ -6,6 +6,7 @@ describe('argparse', () => {
beforeEach(() => {
process.env.fooBar = 'a value';
+ process.env.testUndefinedProp = 'undefined';
argparse = require('./argparse');
});
@@ -16,6 +17,10 @@ describe('argparse', () => {
it(`existing key should return a result`, () => {
expect(argparse.getArgValue('foo-bar')).toBe('a value');
});
+
+ it('should return undefiend if process.env contain something with a string of undefiend' ,() => {
+ expect(argparse.getArgValue('testUndefinedProp')).toBe(undefined);
+ });
});
describe('using arguments', () => {
diff --git a/docs/APIRef.Configuration.md b/docs/APIRef.Configuration.md
index b3ccb63b23..51100b56c4 100644
--- a/docs/APIRef.Configuration.md
+++ b/docs/APIRef.Configuration.md
@@ -43,6 +43,7 @@ Detox can either initialize a server using a generated configuration, or can be
```
Session can also be set per configuration:
+
```json
"detox": {
...
@@ -58,19 +59,30 @@ Session can also be set per configuration:
}
```
-### Test Root Folder
-
+### Test Runner Configuration
-##### Optional: setting a custom test root folder
-Applies when using `detox-cli` by running `detox test` command, default is `e2e`.
-
+##### Optional: setting a test runner (Mocha as default, Jest is supported)
+##### Mocha
```json
"detox": {
...
- "specs": "path/to/tests"
+ "test-runner": "mocha"
+ "runner-config": "path/to/mocha.opts"
+ "specs": "path/to/tests/root"
}
```
+`mocha.opts` refers to `--opts` in https://mochajs.org/#mochaopts
+##### Jest
+```json
+ "detox": {
+ ...
+ "test-runner": "jest"
+ "runner-config": "path/to/config.json"
+ }
+```
+`config.json` refers to `--config` in https://facebook.github.io/jest/docs/en/configuration.html
+>NOTE: jest tests will run in band, as Detox does not currently supports parallelization.
## detox-cli
### Build Configuration
diff --git a/docs/APIRef.DetoxCLI.md b/docs/APIRef.DetoxCLI.md
index 5023576cff..9a7bec74af 100644
--- a/docs/APIRef.DetoxCLI.md
+++ b/docs/APIRef.DetoxCLI.md
@@ -43,8 +43,7 @@ Initiating your test suite
| Option| Description |
| --- | --- |
| -h, --help | output usage information |
-| -r, --runner [runner] | Test runner (supports mocha and jest) |
-| -o, --runner-config \ | Test runner config file |
+| -o, --runner-config \ | Test runner config file, defaults to 'e2e/mocha.opts' for mocha and 'e2e/config.json' for jest |
| -l, --loglevel [value] | info, debug, verbose, silly, wss |
| -c, -configuration \ | Select a device configuration from your defined figurations,if not supplied, and there's only one configuration, detox will default to it |
| -r, --reuse | Reuse existing installed app (do not delete and re-tall) for a faster run. |
diff --git a/docs/Guide.Jest.md b/docs/Guide.Jest.md
index 18fbc35c98..e0ada524ae 100644
--- a/docs/Guide.Jest.md
+++ b/docs/Guide.Jest.md
@@ -32,25 +32,29 @@ beforeAll(async () => {
afterAll(async () => {
await detox.cleanup();
});
+```
-beforeEach(async () => {
- await device.reloadReactNative();
-});
+### 4. Configure Detox to run with Jest
+
+Add a Jest config file `e2e/config.json`:
+
+```json
+{
+ "setupTestFrameworkScriptFile" : "./init.js"
+}
```
-### 4. Run jest
-Add this part to your `package.json`:
+In `package.json`:
+
```json
-"jest": {
- "setupTestFrameworkScriptFile": "./e2e/init.js"
-},
"scripts": {
"test:e2e": "detox test -c ios.sim.debug",
"test:e2e:build": "detox build"
},
"detox": {
- "runner": "jest",
+ "test-runner": "jest",
+ "runner-config": "e2e/config.json"
...
}
```
@@ -65,4 +69,4 @@ There are some things you should notice:
## How to run unit test and E2E tests in the same project
- If you have a setup file for the unit tests pass `./jest/setup` implementation into your unit setup.
-- Call your E2E tests like mentioned above
+- Call your E2E tests using `detox-cli`: `detox test`
diff --git a/examples/demo-react-native-jest/e2e/config.json b/examples/demo-react-native-jest/e2e/config.json
new file mode 100644
index 0000000000..13f1a82b7a
--- /dev/null
+++ b/examples/demo-react-native-jest/e2e/config.json
@@ -0,0 +1,3 @@
+{
+ "setupTestFrameworkScriptFile" : "./init.js"
+}
\ No newline at end of file
diff --git a/examples/demo-react-native-jest/e2e/init.js b/examples/demo-react-native-jest/e2e/init.js
index 429a53580d..32bdb2e81a 100644
--- a/examples/demo-react-native-jest/e2e/init.js
+++ b/examples/demo-react-native-jest/e2e/init.js
@@ -11,7 +11,3 @@ beforeAll(async () => {
afterAll(async () => {
await detox.cleanup();
});
-
-beforeEach(async () => {
- await device.reloadReactNative();
-});
diff --git a/examples/demo-react-native-jest/package.json b/examples/demo-react-native-jest/package.json
index 7a4d2a43be..476bb6ff60 100644
--- a/examples/demo-react-native-jest/package.json
+++ b/examples/demo-react-native-jest/package.json
@@ -1,12 +1,11 @@
{
- "name": "DemoReactNativeJest",
+ "name": "demo-react-native-jest",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
- "test": "jest",
"test-ios": "detox build --configuration ios.sim.debug && detox test --configuration ios.sim.debug",
- "test-android": "detox build --configuration android.emu.debug && detox test --configuration android.emu.debug"
+ "test-android": "detox build --configuration android.emu.debug && detox test --configuration android.emu.debug -l verbose"
},
"dependencies": {
"react": "16.0.0-beta.5",
@@ -19,11 +18,9 @@
"jest": "21.2.1",
"react-test-renderer": "16.0.0-beta.5"
},
- "jest": {
- "setupTestFrameworkScriptFile": "./e2e/init.js"
- },
"detox": {
- "runner": "jest",
+ "test-runner": "jest",
+
"specs": "e2e",
"configurations": {
"ios.sim.release": {
diff --git a/examples/demo-react-native-jest/rn-cli.config.js b/examples/demo-react-native-jest/rn-cli.config.js
new file mode 100644
index 0000000000..804c94f44f
--- /dev/null
+++ b/examples/demo-react-native-jest/rn-cli.config.js
@@ -0,0 +1,7 @@
+const metroBundler = require('metro-bundler');
+
+module.exports = {
+ getBlacklistRE: function() {
+ return metroBundler.createBlacklist([/test\/.*/]);
+ }
+};
\ No newline at end of file
diff --git a/examples/demo-react-native/package.json b/examples/demo-react-native/package.json
index 1ddc1fcf19..c81f414706 100644
--- a/examples/demo-react-native/package.json
+++ b/examples/demo-react-native/package.json
@@ -10,11 +10,13 @@
"react-native": "0.44.0"
},
"devDependencies": {
- "mocha": "^3.2.0",
+ "mocha": "^4.0.1",
"detox": "^5.0.0"
},
"detox": {
+ "test-runner": "mocha",
"specs": "e2e",
+ "runner-config": "e2e/mocha.opts",
"configurations": {
"ios.sim.release": {
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app",
diff --git a/lerna.json b/lerna.json
index bfecd76541..e691baad37 100644
--- a/lerna.json
+++ b/lerna.json
@@ -7,12 +7,14 @@
"examples/demo-native-android",
"examples/demo-native-ios",
"examples/demo-react-native",
+ "examples/demo-react-native-jest",
"detox/test",
"generation"
],
"commands": {
"publish": {
"ignore": [
+ "demo-react-native-jest",
"detox-demo-native-android",
"detox-demo-native-ios",
"detox-demo-react-native",
diff --git a/scripts/demo-projects.ios.sh b/scripts/demo-projects.ios.sh
new file mode 100755
index 0000000000..7226cf0a7d
--- /dev/null
+++ b/scripts/demo-projects.ios.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+
+$(dirname "$0")/bootstrap.sh
+
+cd examples/demo-react-native
+detox build -c ios.sim.release
+detox test -c ios.sim.release
+
+cd examples/demo-react-native-jest
+detox build -c ios.sim.release
+detox test -c ios.sim.release
\ No newline at end of file