diff --git a/detox/local-cli/detox-build-framework-cache.js b/detox/local-cli/detox-build-framework-cache.js new file mode 100644 index 0000000000..ddb83081de --- /dev/null +++ b/detox/local-cli/detox-build-framework-cache.js @@ -0,0 +1,6 @@ +#!/usr/bin/env node + +const path = require('path'); +const cp = require('child_process'); + +cp.execSync(path.join(__dirname, '../scripts/build_framework.ios.sh'), {stdio: 'inherit'}); diff --git a/detox/local-cli/detox.js b/detox/local-cli/detox.js index 5e51bd63e0..808b50e9eb 100755 --- a/detox/local-cli/detox.js +++ b/detox/local-cli/detox.js @@ -8,5 +8,6 @@ program .command('build', `[convince method] Run the command defined in 'configuration.build'`) .command('run-server', 'Starts a standalone detox server') .command('init', 'Create initial e2e tests folder') - .command('clean-framework-cache', `Delete all compiled framework binaries from ~/Library/Detox, they will be rebuilt when running 'detox test'`) + .command('clean-framework-cache', `Delete all compiled framework binaries from ~/Library/Detox, they will be rebuilt on 'npm install' or when running 'build-framework-cache'`) + .command('build-framework-cache', `Build Detox.framework to ~/Library/Detox. The framework cache is specific for each combination of Xcode and Detox versions`) .parse(process.argv); diff --git a/detox/package.json b/detox/package.json index e41d2bcc05..1efcffa330 100644 --- a/detox/package.json +++ b/detox/package.json @@ -26,7 +26,8 @@ "unit": "jest --coverage --verbose", "test": "npm run unit", "unit:watch": "jest --watch", - "prepublish": "npm run build" + "prepublish": "npm run build", + "postinstall": "scripts/postinstall.sh" }, "devDependencies": { "babel-cli": "^6.8.0", diff --git a/detox/scripts/build.sh b/detox/scripts/build.sh index 310ec256e2..2fa759f98c 100755 --- a/detox/scripts/build.sh +++ b/detox/scripts/build.sh @@ -3,16 +3,17 @@ echo -e "\nTranspiling JavaScript sources" BABEL_ENV=test babel src -d lib -echo -e "\nPackaging Detox iOS sources" -rm -fr Detox-ios-src.tbz -#Prepare Earl Grey without building -ios/EarlGrey/Scripts/setup-earlgrey.sh > /dev/null -find ./ios -name Build -type d -exec rm -rf {} \; > /dev/null - -cd ios -tar -cjf ../Detox-ios-src.tbz . -cd .. +if [ `uname` == "Darwin" ]; then + echo -e "\nPackaging Detox iOS sources" + rm -fr Detox-ios-src.tbz + #Prepare Earl Grey without building + ios/EarlGrey/Scripts/setup-earlgrey.sh > /dev/null + find ./ios -name Build -type d -exec rm -rf {} \; > /dev/null + cd ios + tar -cjf ../Detox-ios-src.tbz . + cd .. +fi if [ "$1" == "android" -o "$2" == "android" ] ; then echo -e "\nBuilding Detox aars" diff --git a/detox/scripts/build_framework.ios.sh b/detox/scripts/build_framework.ios.sh index 4e09d0a695..6b835ca9e4 100755 --- a/detox/scripts/build_framework.ios.sh +++ b/detox/scripts/build_framework.ios.sh @@ -1,30 +1,42 @@ #!/bin/bash -e -if [ $# -ne 2 ]; then - echo "usage: build_framework_ios.sh detoxIosSourceTarballDirPath detoxFrameworkDirPath" - exit 1 -fi - -detoxIosSourceTarballDirPath="${1}" -detoxFrameworkDirPath="${2}" +detoxVersion=`node -p "require('./package.json').version"` +detoxIosSourceTarballDirPath="$(dirname $(dirname ${0}))" +sha1=`(echo "${detoxVersion}" && xcodebuild -version) | shasum | awk '{print $1}' #"${2}"` +detoxFrameworkDirPath="$HOME/Library/Detox/ios/${sha1}" +detoxFrameworkPath="${detoxFrameworkDirPath}/Detox.framework" detoxSourcePath="${detoxIosSourceTarballDirPath}"/ios_src +function buildFramework { + echo "Extracting Detox sources..." -echo "###############################" -echo "Extracting Detox sources..." + mkdir -p "${detoxSourcePath}" + tar -xjf "${detoxIosSourceTarballDirPath}"/Detox-ios-src.tbz -C "${detoxSourcePath}" -mkdir -p "${detoxSourcePath}" -tar -xjf "${detoxIosSourceTarballDirPath}"/Detox-ios-src.tbz -C "${detoxSourcePath}" + echo "Building Detox.framework..." -echo "###############################" + mkdir -p "${detoxFrameworkDirPath}" + xcodebuild build -project "${detoxSourcePath}"/Detox.xcodeproj -scheme DetoxFramework -configuration Release -derivedDataPath "${detoxFrameworkDirPath}"/DetoxBuild BUILD_DIR="${detoxFrameworkDirPath}"/DetoxBuild/Build/Products &> "${detoxFrameworkDirPath}"/detox_ios.log + mv "${detoxFrameworkDirPath}"/DetoxBuild/Build/Products/Release-universal/Detox.framework "${detoxFrameworkDirPath}" + rm -fr "${detoxFrameworkDirPath}"/DetoxBuild + echo "Done" +} -echo "###############################" -echo "Extracting Detox sources..." -mkdir -p "${detoxFrameworkDirPath}" -xcodebuild build -project "${detoxSourcePath}"/Detox.xcodeproj -scheme DetoxFramework -configuration Release -derivedDataPath "${detoxFrameworkDirPath}"/DetoxBuild BUILD_DIR="${detoxFrameworkDirPath}"/DetoxBuild/Build/Products &> "${detoxFrameworkDirPath}"/detox_ios.log -mv "${detoxFrameworkDirPath}"/DetoxBuild/Build/Products/Release-universal/Detox.framework "${detoxFrameworkDirPath}" -rm -fr "${detoxFrameworkDirPath}"/DetoxBuild +function main { + if [ -d "${detoxFrameworkDirPath}" ]; then + if [ ! -d "${detoxFrameworkPath}" ]; then + echo "${detoxFrameworkDirPath} was found, but could not find Detox.framework inside it. This means that the Detox framework build process was interrupted. + deleting ${detoxFrameworkDirPath} and trying to rebuild." + rm -rf "${detoxFrameworkDirPath}" + buildFramework + else + echo "Detox.framework was previously compiled, skipping..." + fi + else + buildFramework + fi +} -echo "###############################" +main diff --git a/detox/scripts/postinstall.sh b/detox/scripts/postinstall.sh new file mode 100755 index 0000000000..e21c7007ea --- /dev/null +++ b/detox/scripts/postinstall.sh @@ -0,0 +1,10 @@ +#!/bin/bash -e + +if [ "$__DETOX_DEV" = true ]; then + echo "Running postinstall for detox dev mode, exiting" + exit 0 +fi + +if [ `uname` == "Darwin" ]; then + source "$(dirname ${0})/build_framework.ios.sh" +fi diff --git a/detox/src/devices/IosDriver.js b/detox/src/devices/IosDriver.js index 5600b9a417..49671389bf 100644 --- a/detox/src/devices/IosDriver.js +++ b/detox/src/devices/IosDriver.js @@ -25,22 +25,12 @@ class IosDriver extends DeviceDriverBase { return notificationFilePath; } - //TODO:In order to support sharding, we need to create a device factory, and move prepare() - // to that factory, to only have a single instance of it. async prepare() { - const detoxIosSourceTarballDirPath = path.join(__dirname, '../..'); const detoxFrameworkPath = await environment.getFrameworkPath(); - const detoxFrameworkDirPath = path.parse(detoxFrameworkPath).dir; - - if (fs.existsSync(detoxFrameworkDirPath)) { - if(!fs.existsSync(`${detoxFrameworkPath}`)) { - throw new Error(`${detoxFrameworkDirPath} was found, but could not find Detox.framework inside it. This means that the Detox framework build process was interrupted. - To solve this, either delete ${detoxFrameworkDirPath} or run 'detox clean-framework-cache'`); - } - } else { - log.info(`Building Detox.framework (${environment.getDetoxVersion()}) into ${detoxFrameworkDirPath}...`); - await exec.execAsync(path.join(__dirname, `../../scripts/build_framework.ios.sh "${detoxIosSourceTarballDirPath}" "${detoxFrameworkDirPath}"`)); + if (!fs.existsSync(detoxFrameworkPath)) { + throw new Error(`${detoxFrameworkPath} could not be found, this means either you changed a version of Xcode or Detox postinstall script was unsuccessful. + To attempt a fix try running 'detox clean-framework-cache && detox build-framework-cache'`); } } diff --git a/docs/APIRef.DetoxCLI.md b/docs/APIRef.DetoxCLI.md index 7ab7a38819..5023576cff 100644 --- a/docs/APIRef.DetoxCLI.md +++ b/docs/APIRef.DetoxCLI.md @@ -21,7 +21,8 @@ detox [options] [command] | [build](#build) | Run the command defined in `configuration.build` | | [run-server](#run-server) | Starts a standalone detox server | | [init](#init) | Create initial e2e tests folder | -| clean-framework-cache | Delete all compiled framework binaries from ~/Library/Detox, they will be rebuilt when running 'detox test' +| clean-framework-cache | Delete all compiled framework binaries from ~/Library/Detox, they will be rebuilt on 'npm install' or when running 'build-framework-cache' +| build-framework-cache | Build Detox.framework to ~/Library/Detox. The framework cache is specific for each combination of Xcode and Detox versions | [help](#help) | Display help for specific command | ## Options: diff --git a/docs/Guide.Contributing.md b/docs/Guide.Contributing.md index e4bdfc5c2b..6046a8078f 100644 --- a/docs/Guide.Contributing.md +++ b/docs/Guide.Contributing.md @@ -1,14 +1,6 @@ -# Contributing to detox - -### Clone detox and submodules - -```sh -git clone git@github.com:wix/detox.git -cd detox -git submodule update --init --recursive -``` -(this makes sure all git submodule dependencies are properly checked out) +# Contributing to Detox +## Prerequisites ### Install `node` v7.6 or higher (to support async-await natively) @@ -30,10 +22,24 @@ For all the internal projects (detox, detox-server, detox-cli, demos, test) `ler ```sh gem install xcpretty ``` -### Installing + +Alternatively, run `scripts/install.ios.sh` / `scripts/android.sh` to install all prerequisites. + +## Detox + +### Clone Detox and submodules ```sh -lerna bootstrap +git clone git@github.com:wix/detox.git +cd detox +git submodule update --init --recursive +``` +(this makes sure all git submodule dependencies are properly checked out) + +### Installing and linking internal projects + +```sh +scripts/bootstrap.sh ``` ### Building @@ -66,8 +72,8 @@ cd detox open coverage/lcov-report/index.html ``` -### Running detox e2e covarage tests -Detox has a suite of e2e tests to test its own API while developing (and for regression). The way we do is is by maintaining a special application that is "tested" against detox's API, but essentially, it's the API that is tested, not the app. +### Running Detox e2e covarage tests +Detox has a suite of e2e tests to test its own API while developing (and for regression). The way we do is is by maintaining a special application that is "tested" against Detox's API, but essentially, it's the API that is tested, not the app. To run the e2e tests, go to `detox/detox/test` ```sh @@ -83,14 +89,11 @@ npm run build To run the e2e tests, after the application was built. ```sh -npm run e2e +npm run build:ios +npm run e2e:ios ``` -### Native Tests - -We got native tests for our client code, here is how you execute it - -#### Android +### Android Native tests 0. Install Java and Android SDK 25 1. In `detox/android` run `./gradlew install` diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh new file mode 100755 index 0000000000..f5f73775e3 --- /dev/null +++ b/scripts/bootstrap.sh @@ -0,0 +1,8 @@ +#!/bin/bash -e + +# Detox package runs a postinstall script when installed as a dependency in order to compile Detox.framework (iOS). +# In order to install it, the framework sources must be already packaged in Detox-ios-src.tbz. An issue arises when developing Detox, +# since postinstall runs before prepublish, causing the compilation script to start running before the sources are available, +# so we had to add a hack :( to the dev process, skipping postinstall and then manually triggering it. +__DETOX_DEV=true lerna bootstrap +npm run postinstall --prefix detox diff --git a/scripts/ci.sh b/scripts/ci.sh index c760b90bcd..0f36de8603 100755 --- a/scripts/ci.sh +++ b/scripts/ci.sh @@ -7,6 +7,7 @@ case "$REACT_NATIVE_VERSION" in ;; esac -lerna bootstrap +$(dirname "$0")/bootstrap.sh + lerna run --ignore detox-demo* build lerna run --ignore detox-demo* test