├── .gitignore ├── README.md ├── index.js ├── lib ├── detoxInit.js ├── index.js ├── installPackages.js ├── reactNativeConfig.js └── updateFiles.js ├── package-lock.json ├── package.json └── templates ├── .detoxrc.json ├── AndroidManifest.xml ├── DetoxTest.java ├── app └── build.gradle ├── build.gradle └── network_security_config.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # node.js 6 | # 7 | node_modules/ 8 | npm-debug.log 9 | yarn-error.log -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | This package was created to simplify setting up Detox testing framework for React Native mobile apps. It is recommended that 4 | you run this package right after you initialize your react native app. 5 | 6 | ## Step 1: Setup 7 | 8 | ```sh 9 | npm install -g react-native-setup-detox 10 | ``` 11 | 12 | Go to your React Native app folder and run: 13 | 14 | ```sh 15 | react-native-setup-detox 16 | ``` 17 | 18 | ## Step 2: Configure emulator 19 | 20 | After successful installation you have to setup an emulator to run the tests. Please follow these steps: 21 | 22 | * [Android](https://github.com/wix/Detox/blob/4fadc000b63f9039c0432b07d709518f95ff9f23/docs/Introduction.AndroidDevEnv.md) 23 | 24 | 25 | ## Step 3: Use emulator 26 | 27 | Once you setup an emulator from step 2 you have to update the emulator name in your `.detoxrc.json` `avdName` property. 28 | 29 | ## TODO: 30 | 31 | - [x] Android 32 | - [ ] iOS (in progress) 33 | 34 | Currently on tested on Mac and Android. 35 | 36 | ## Feedback 37 | 38 | Please log bugs or features in the issues section -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | 4 | const clear = require("clear"); 5 | const chalk = require("chalk"); 6 | const figlet = require("figlet"); 7 | const { updateFiles, installPackages, detoxInit } = require("./lib"); 8 | const reactNativeConfig = require("./lib/reactNativeConfig"); 9 | 10 | clear(); 11 | 12 | console.log( 13 | chalk.green(figlet.textSync("Setting up Detox", { horizontalLayout: "full" })) 14 | ); 15 | 16 | async function init() { 17 | const config = await reactNativeConfig(); 18 | installPackages(); 19 | detoxInit(config.project.android); 20 | await updateFiles(config.project.android); 21 | } 22 | 23 | init() 24 | .then(() => console.log(chalk.green("Installation complete"))) 25 | .catch(console.error); 26 | -------------------------------------------------------------------------------- /lib/detoxInit.js: -------------------------------------------------------------------------------- 1 | const execa = require("execa"); 2 | const chalk = require("chalk"); 3 | const fs = require("fs"); 4 | const path = require("path"); 5 | 6 | module.exports = function detoxInit() { 7 | console.log(chalk.yellow("Initializing Detox")); 8 | 9 | if (!fs.existsSync(path.join(process.cwd(), "e2e"))) { 10 | try { 11 | execa.sync("detox", ["init", "-r", "jest"], { 12 | cwd: process.cwd(), 13 | stdio: "inherit", 14 | }); 15 | } catch (error) { 16 | console.log(error); 17 | } 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | const updateFiles = require("./updateFiles"); 2 | const installPackages = require("./installPackages"); 3 | const detoxInit = require("./detoxInit"); 4 | 5 | module.exports = { 6 | updateFiles, 7 | installPackages, 8 | detoxInit, 9 | }; 10 | -------------------------------------------------------------------------------- /lib/installPackages.js: -------------------------------------------------------------------------------- 1 | const execa = require("execa"); 2 | const chalk = require("chalk"); 3 | 4 | const DONE = chalk.reset.inverse.bold.green(" DONE "); 5 | const cwd = process.cwd(); 6 | 7 | module.exports = function installPackages() { 8 | console.log(chalk.yellow("Installing required packages!")); 9 | // global installs 10 | execa.sync("npm", ["install", "detox-cli", "-g"], { 11 | cwd, 12 | stdio: "inherit", 13 | }); 14 | 15 | // dev dependecies 16 | execa.sync( 17 | "npm", 18 | ["install", "jest@^26.6.1", "jest-circus@^26.6.1", "detox", "--save-dev"], 19 | { 20 | cwd, 21 | stdio: "inherit", 22 | } 23 | ); 24 | 25 | console.log(DONE); 26 | }; 27 | -------------------------------------------------------------------------------- /lib/reactNativeConfig.js: -------------------------------------------------------------------------------- 1 | const execa = require("execa"); 2 | 3 | module.exports = async function reactNativeConfig() { 4 | const { stdout } = await execa("npx", ["react-native", "config"], { 5 | cwd: process.cwd(), 6 | }); 7 | 8 | return JSON.parse(stdout); 9 | }; 10 | -------------------------------------------------------------------------------- /lib/updateFiles.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const mergeFiles = require("merge-files"); 3 | const fs = require("fs"); 4 | const copyFileSync = require("fs-copy-file-sync"); 5 | const chalk = require("chalk"); 6 | const replace = require("replace-in-file"); 7 | 8 | const DONE = chalk.reset.inverse.bold.green(" DONE "); 9 | const templatesPath = path.join(__dirname, "../templates"); 10 | 11 | /** 12 | * Update various build files with detox configuration 13 | * 14 | * @param {Object} config react native config from `react-native config` 15 | */ 16 | module.exports = async function updateFiles(config) { 17 | console.log(chalk.yellow("Updating files!")); 18 | 19 | const PATHS = { 20 | "build.gradle": config.buildGradlePath, 21 | "AndroidManifest.xml": config.manifestPath, 22 | "app/build.gradle": path.join(config.sourceDir, "app/build.gradle"), 23 | ".detoxrc.json": path.join(config.folder, ".detoxrc.json"), 24 | }; 25 | 26 | const testFileDestination = path.join( 27 | config.sourceDir, 28 | `app/src/androidTest/java/${config.packageFolder}` 29 | ); 30 | 31 | const detoxTestJavaPath = path.join(testFileDestination, "DetoxTest.java"); 32 | 33 | // update all files 34 | const promises = Object.keys(PATHS).map((p) => { 35 | let targetPath = PATHS[p]; 36 | let sourcePath = path.join(templatesPath, p); 37 | return mergeFiles([sourcePath, targetPath], targetPath); 38 | }); 39 | await Promise.all(promises); 40 | 41 | // create directory for security configuration 42 | let dest = path.join(config.sourceDir, "app/src/main/res/xml"); 43 | if (!fs.existsSync(dest)) { 44 | fs.mkdirSync(dest); 45 | copyFileSync( 46 | path.join(templatesPath, "network_security_config.xml"), 47 | path.join(dest, "network_security_config.xml") 48 | ); 49 | } 50 | 51 | // copy DetoxTest.java 52 | if (!fs.existsSync(testFileDestination)) { 53 | fs.mkdirSync(testFileDestination, { recursive: true }); 54 | copyFileSync(path.join(templatesPath, "DetoxTest.java"), detoxTestJavaPath); 55 | } 56 | 57 | // update AndroidManifest.xml, DetoxTest.java, app/build.gradle and settings.gradle app name 58 | replace.sync({ 59 | files: [ 60 | config.manifestPath, 61 | config.settingsGradlePath, 62 | detoxTestJavaPath, 63 | PATHS["app/build.gradle"], 64 | ], 65 | from: /com.example/g, 66 | to: config.packageName, 67 | }); 68 | 69 | // gradle.settings 70 | fs.appendFileSync(config.settingsGradlePath, "include ':detox'\n"); 71 | fs.appendFileSync( 72 | config.settingsGradlePath, 73 | "project(':detox').projectDir = new File(rootProject.projectDir, '../node_modules/detox/android/detox')" 74 | ); 75 | 76 | console.log(DONE); 77 | }; 78 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-setup-detox", 3 | "version": "0.0.3", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ansi-regex": { 8 | "version": "5.0.0", 9 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 10 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" 11 | }, 12 | "ansi-styles": { 13 | "version": "4.3.0", 14 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 15 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 16 | "requires": { 17 | "color-convert": "^2.0.1" 18 | } 19 | }, 20 | "balanced-match": { 21 | "version": "1.0.0", 22 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 23 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 24 | }, 25 | "brace-expansion": { 26 | "version": "1.1.11", 27 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 28 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 29 | "requires": { 30 | "balanced-match": "^1.0.0", 31 | "concat-map": "0.0.1" 32 | } 33 | }, 34 | "camelcase": { 35 | "version": "5.3.1", 36 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 37 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" 38 | }, 39 | "chalk": { 40 | "version": "4.1.0", 41 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 42 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 43 | "requires": { 44 | "ansi-styles": "^4.1.0", 45 | "supports-color": "^7.1.0" 46 | } 47 | }, 48 | "clear": { 49 | "version": "0.1.0", 50 | "resolved": "https://registry.npmjs.org/clear/-/clear-0.1.0.tgz", 51 | "integrity": "sha512-qMjRnoL+JDPJHeLePZJuao6+8orzHMGP04A8CdwCNsKhRbOnKRjefxONR7bwILT3MHecxKBjHkKL/tkZ8r4Uzw==" 52 | }, 53 | "cliui": { 54 | "version": "6.0.0", 55 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", 56 | "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", 57 | "requires": { 58 | "string-width": "^4.2.0", 59 | "strip-ansi": "^6.0.0", 60 | "wrap-ansi": "^6.2.0" 61 | } 62 | }, 63 | "color-convert": { 64 | "version": "2.0.1", 65 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 66 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 67 | "requires": { 68 | "color-name": "~1.1.4" 69 | } 70 | }, 71 | "color-name": { 72 | "version": "1.1.4", 73 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 74 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 75 | }, 76 | "concat-map": { 77 | "version": "0.0.1", 78 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 79 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 80 | }, 81 | "core-util-is": { 82 | "version": "1.0.2", 83 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 84 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 85 | }, 86 | "cross-spawn": { 87 | "version": "7.0.3", 88 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 89 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 90 | "requires": { 91 | "path-key": "^3.1.0", 92 | "shebang-command": "^2.0.0", 93 | "which": "^2.0.1" 94 | }, 95 | "dependencies": { 96 | "which": { 97 | "version": "2.0.2", 98 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 99 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 100 | "requires": { 101 | "isexe": "^2.0.0" 102 | } 103 | } 104 | } 105 | }, 106 | "decamelize": { 107 | "version": "1.2.0", 108 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 109 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 110 | }, 111 | "emoji-regex": { 112 | "version": "8.0.0", 113 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 114 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 115 | }, 116 | "end-of-stream": { 117 | "version": "1.4.4", 118 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 119 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 120 | "requires": { 121 | "once": "^1.4.0" 122 | } 123 | }, 124 | "execa": { 125 | "version": "4.0.3", 126 | "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz", 127 | "integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==", 128 | "requires": { 129 | "cross-spawn": "^7.0.0", 130 | "get-stream": "^5.0.0", 131 | "human-signals": "^1.1.1", 132 | "is-stream": "^2.0.0", 133 | "merge-stream": "^2.0.0", 134 | "npm-run-path": "^4.0.0", 135 | "onetime": "^5.1.0", 136 | "signal-exit": "^3.0.2", 137 | "strip-final-newline": "^2.0.0" 138 | } 139 | }, 140 | "figlet": { 141 | "version": "1.5.0", 142 | "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.5.0.tgz", 143 | "integrity": "sha512-ZQJM4aifMpz6H19AW1VqvZ7l4pOE9p7i/3LyxgO2kp+PO/VcDYNqIHEMtkccqIhTXMKci4kjueJr/iCQEaT/Ww==" 144 | }, 145 | "find-up": { 146 | "version": "4.1.0", 147 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 148 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 149 | "requires": { 150 | "locate-path": "^5.0.0", 151 | "path-exists": "^4.0.0" 152 | } 153 | }, 154 | "fs-copy-file-sync": { 155 | "version": "1.1.1", 156 | "resolved": "https://registry.npmjs.org/fs-copy-file-sync/-/fs-copy-file-sync-1.1.1.tgz", 157 | "integrity": "sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ==" 158 | }, 159 | "fs.realpath": { 160 | "version": "1.0.0", 161 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 162 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 163 | }, 164 | "get-caller-file": { 165 | "version": "2.0.5", 166 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 167 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" 168 | }, 169 | "get-stream": { 170 | "version": "5.2.0", 171 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 172 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 173 | "requires": { 174 | "pump": "^3.0.0" 175 | } 176 | }, 177 | "glob": { 178 | "version": "7.1.6", 179 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 180 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 181 | "requires": { 182 | "fs.realpath": "^1.0.0", 183 | "inflight": "^1.0.4", 184 | "inherits": "2", 185 | "minimatch": "^3.0.4", 186 | "once": "^1.3.0", 187 | "path-is-absolute": "^1.0.0" 188 | } 189 | }, 190 | "has-flag": { 191 | "version": "4.0.0", 192 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 193 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" 194 | }, 195 | "human-signals": { 196 | "version": "1.1.1", 197 | "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", 198 | "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==" 199 | }, 200 | "inflight": { 201 | "version": "1.0.6", 202 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 203 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 204 | "requires": { 205 | "once": "^1.3.0", 206 | "wrappy": "1" 207 | } 208 | }, 209 | "inherits": { 210 | "version": "2.0.4", 211 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 212 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 213 | }, 214 | "is-fullwidth-code-point": { 215 | "version": "3.0.0", 216 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 217 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" 218 | }, 219 | "is-stream": { 220 | "version": "2.0.0", 221 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", 222 | "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" 223 | }, 224 | "isarray": { 225 | "version": "1.0.0", 226 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 227 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 228 | }, 229 | "isexe": { 230 | "version": "2.0.0", 231 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 232 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 233 | }, 234 | "locate-path": { 235 | "version": "5.0.0", 236 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 237 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 238 | "requires": { 239 | "p-locate": "^4.1.0" 240 | } 241 | }, 242 | "merge-files": { 243 | "version": "0.1.2", 244 | "resolved": "https://registry.npmjs.org/merge-files/-/merge-files-0.1.2.tgz", 245 | "integrity": "sha512-WTvtH6ZwVy1/scvp1M+Re6PVni87QTjpSLAwxh0L+PlYIxc4VGFFpLjvP7jdJ43gaJ5n+RUIriJ6wKqmqvVVmg==", 246 | "requires": { 247 | "multistream": "^2.1.0" 248 | } 249 | }, 250 | "merge-stream": { 251 | "version": "2.0.0", 252 | "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", 253 | "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" 254 | }, 255 | "mimic-fn": { 256 | "version": "2.1.0", 257 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 258 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" 259 | }, 260 | "minimatch": { 261 | "version": "3.0.4", 262 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 263 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 264 | "requires": { 265 | "brace-expansion": "^1.1.7" 266 | } 267 | }, 268 | "multistream": { 269 | "version": "2.1.1", 270 | "resolved": "https://registry.npmjs.org/multistream/-/multistream-2.1.1.tgz", 271 | "integrity": "sha512-xasv76hl6nr1dEy3lPvy7Ej7K/Lx3O/FCvwge8PeVJpciPPoNCbaANcNiBug3IpdvTveZUcAV0DJzdnUDMesNQ==", 272 | "requires": { 273 | "inherits": "^2.0.1", 274 | "readable-stream": "^2.0.5" 275 | } 276 | }, 277 | "npm-run-path": { 278 | "version": "4.0.1", 279 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", 280 | "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", 281 | "requires": { 282 | "path-key": "^3.0.0" 283 | } 284 | }, 285 | "once": { 286 | "version": "1.4.0", 287 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 288 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 289 | "requires": { 290 | "wrappy": "1" 291 | } 292 | }, 293 | "onetime": { 294 | "version": "5.1.2", 295 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", 296 | "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", 297 | "requires": { 298 | "mimic-fn": "^2.1.0" 299 | } 300 | }, 301 | "p-limit": { 302 | "version": "2.3.0", 303 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 304 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 305 | "requires": { 306 | "p-try": "^2.0.0" 307 | } 308 | }, 309 | "p-locate": { 310 | "version": "4.1.0", 311 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 312 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 313 | "requires": { 314 | "p-limit": "^2.2.0" 315 | } 316 | }, 317 | "p-try": { 318 | "version": "2.2.0", 319 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 320 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" 321 | }, 322 | "path-exists": { 323 | "version": "4.0.0", 324 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 325 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" 326 | }, 327 | "path-is-absolute": { 328 | "version": "1.0.1", 329 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 330 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 331 | }, 332 | "path-key": { 333 | "version": "3.1.1", 334 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 335 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" 336 | }, 337 | "process-nextick-args": { 338 | "version": "2.0.1", 339 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 340 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 341 | }, 342 | "pump": { 343 | "version": "3.0.0", 344 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 345 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 346 | "requires": { 347 | "end-of-stream": "^1.1.0", 348 | "once": "^1.3.1" 349 | } 350 | }, 351 | "readable-stream": { 352 | "version": "2.3.7", 353 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 354 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 355 | "requires": { 356 | "core-util-is": "~1.0.0", 357 | "inherits": "~2.0.3", 358 | "isarray": "~1.0.0", 359 | "process-nextick-args": "~2.0.0", 360 | "safe-buffer": "~5.1.1", 361 | "string_decoder": "~1.1.1", 362 | "util-deprecate": "~1.0.1" 363 | }, 364 | "dependencies": { 365 | "safe-buffer": { 366 | "version": "5.1.2", 367 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 368 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 369 | } 370 | } 371 | }, 372 | "replace-in-file": { 373 | "version": "6.1.0", 374 | "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-6.1.0.tgz", 375 | "integrity": "sha512-URzjyF3nucvejuY13HFd7O+Q6tFJRLKGHLYVvSh+LiZj3gFXzSYGnIkQflnJJulCAI2/RTZaZkpOtdVdW0EhQA==", 376 | "requires": { 377 | "chalk": "^4.0.0", 378 | "glob": "^7.1.6", 379 | "yargs": "^15.3.1" 380 | } 381 | }, 382 | "require-directory": { 383 | "version": "2.1.1", 384 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 385 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" 386 | }, 387 | "require-main-filename": { 388 | "version": "2.0.0", 389 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 390 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" 391 | }, 392 | "set-blocking": { 393 | "version": "2.0.0", 394 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 395 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" 396 | }, 397 | "shebang-command": { 398 | "version": "2.0.0", 399 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 400 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 401 | "requires": { 402 | "shebang-regex": "^3.0.0" 403 | } 404 | }, 405 | "shebang-regex": { 406 | "version": "3.0.0", 407 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 408 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" 409 | }, 410 | "signal-exit": { 411 | "version": "3.0.3", 412 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", 413 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" 414 | }, 415 | "string-width": { 416 | "version": "4.2.0", 417 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 418 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 419 | "requires": { 420 | "emoji-regex": "^8.0.0", 421 | "is-fullwidth-code-point": "^3.0.0", 422 | "strip-ansi": "^6.0.0" 423 | } 424 | }, 425 | "string_decoder": { 426 | "version": "1.1.1", 427 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 428 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 429 | "requires": { 430 | "safe-buffer": "~5.1.0" 431 | }, 432 | "dependencies": { 433 | "safe-buffer": { 434 | "version": "5.1.2", 435 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 436 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 437 | } 438 | } 439 | }, 440 | "strip-ansi": { 441 | "version": "6.0.0", 442 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 443 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 444 | "requires": { 445 | "ansi-regex": "^5.0.0" 446 | } 447 | }, 448 | "strip-final-newline": { 449 | "version": "2.0.0", 450 | "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", 451 | "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" 452 | }, 453 | "supports-color": { 454 | "version": "7.2.0", 455 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 456 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 457 | "requires": { 458 | "has-flag": "^4.0.0" 459 | } 460 | }, 461 | "util-deprecate": { 462 | "version": "1.0.2", 463 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 464 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 465 | }, 466 | "which-module": { 467 | "version": "2.0.0", 468 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 469 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" 470 | }, 471 | "wrap-ansi": { 472 | "version": "6.2.0", 473 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", 474 | "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", 475 | "requires": { 476 | "ansi-styles": "^4.0.0", 477 | "string-width": "^4.1.0", 478 | "strip-ansi": "^6.0.0" 479 | } 480 | }, 481 | "wrappy": { 482 | "version": "1.0.2", 483 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 484 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 485 | }, 486 | "y18n": { 487 | "version": "4.0.0", 488 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", 489 | "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" 490 | }, 491 | "yargs": { 492 | "version": "15.4.1", 493 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", 494 | "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", 495 | "requires": { 496 | "cliui": "^6.0.0", 497 | "decamelize": "^1.2.0", 498 | "find-up": "^4.1.0", 499 | "get-caller-file": "^2.0.1", 500 | "require-directory": "^2.1.1", 501 | "require-main-filename": "^2.0.0", 502 | "set-blocking": "^2.0.0", 503 | "string-width": "^4.2.0", 504 | "which-module": "^2.0.0", 505 | "y18n": "^4.0.0", 506 | "yargs-parser": "^18.1.2" 507 | } 508 | }, 509 | "yargs-parser": { 510 | "version": "18.1.3", 511 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", 512 | "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", 513 | "requires": { 514 | "camelcase": "^5.0.0", 515 | "decamelize": "^1.2.0" 516 | } 517 | } 518 | } 519 | } 520 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-setup-detox", 3 | "version": "0.0.3", 4 | "description": "setup react native detox automation testing framework", 5 | "main": "./index.js", 6 | "bin": { 7 | "react-native-setup-detox": "./index.js" 8 | }, 9 | "scripts": { 10 | "test": "echo \"No test specified\"" 11 | }, 12 | "homepage": "https://github.com/tsvetann/react-native-setup-detox#readme", 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/tsvetann/react-native-setup-detox" 16 | }, 17 | "keywords": [ 18 | "react", 19 | "native", 20 | "detox", 21 | "automation", 22 | "testing" 23 | ], 24 | "files": [ 25 | "lib", 26 | "templates", 27 | "index.js" 28 | ], 29 | "author": "Tsvetan Nikolov", 30 | "license": "MIT", 31 | "bugs": { 32 | "url": "https://github.com/tsvetann/react-native-setup-detox/issues" 33 | }, 34 | "dependencies": { 35 | "chalk": "^4.1.0", 36 | "clear": "^0.1.0", 37 | "execa": "^4.0.3", 38 | "figlet": "^1.5.0", 39 | "fs-copy-file-sync": "^1.1.1", 40 | "merge-files": "^0.1.2", 41 | "replace-in-file": "^6.1.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /templates/.detoxrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "testRunner": "jest", 3 | "runnerConfig": "e2e/config.json", 4 | "configurations": { 5 | "android.emu.debug": { 6 | "binaryPath": "android/app/build/outputs/apk/debug/app-debug.apk", 7 | "build": "cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && cd ..", 8 | "type": "android.emulator", 9 | "device": { 10 | "avdName": "change_me" 11 | } 12 | }, 13 | "android.emu.release": { 14 | "binaryPath": "android/app/build/outputs/apk/release/app-release-unsigned.apk", 15 | "build": "cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd ..", 16 | "type": "android.emulator", 17 | "device": { 18 | "avdName": "change_me" 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /templates/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /templates/DetoxTest.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import com.wix.detox.Detox; 4 | import com.wix.detox.config.DetoxConfig; 5 | 6 | import org.junit.Rule; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import androidx.test.ext.junit.runners.AndroidJUnit4; 11 | import androidx.test.filters.LargeTest; 12 | import androidx.test.rule.ActivityTestRule; 13 | 14 | @RunWith(AndroidJUnit4.class) 15 | @LargeTest 16 | public class DetoxTest { 17 | @Rule 18 | // Replace 'MainActivity' with the value of android:name entry in 19 | // in AndroidManifest.xml 20 | public ActivityTestRule mActivityRule = new ActivityTestRule<>(MainActivity.class, false, false); 21 | 22 | @Test 23 | public void runDetoxTests() { 24 | DetoxConfig detoxConfig = new DetoxConfig(); 25 | detoxConfig.idlePolicyConfig.masterTimeoutSec = 90; 26 | detoxConfig.idlePolicyConfig.idleResourceTimeoutSec = 60; 27 | detoxConfig.rnContextLoadTimeoutSec = (com.example.BuildConfig.DEBUG ? 180 : 60); 28 | 29 | Detox.runTests(mActivityRule, detoxConfig); 30 | } 31 | } -------------------------------------------------------------------------------- /templates/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | 3 | import com.android.build.OutputFile 4 | 5 | /** 6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets 7 | * and bundleReleaseJsAndAssets). 8 | * These basically call `react-native bundle` with the correct arguments during the Android build 9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the 10 | * bundle directly from the development server. Below you can see all the possible configurations 11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the 12 | * `apply from: "../../node_modules/react-native/react.gradle"` line. 13 | * 14 | * project.ext.react = [ 15 | * // the name of the generated asset file containing your JS bundle 16 | * bundleAssetName: "index.android.bundle", 17 | * 18 | * // the entry file for bundle generation. If none specified and 19 | * // "index.android.js" exists, it will be used. Otherwise "index.js" is 20 | * // default. Can be overridden with ENTRY_FILE environment variable. 21 | * entryFile: "index.android.js", 22 | * 23 | * // https://reactnative.dev/docs/performance#enable-the-ram-format 24 | * bundleCommand: "ram-bundle", 25 | * 26 | * // whether to bundle JS and assets in debug mode 27 | * bundleInDebug: false, 28 | * 29 | * // whether to bundle JS and assets in release mode 30 | * bundleInRelease: true, 31 | * 32 | * // whether to bundle JS and assets in another build variant (if configured). 33 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants 34 | * // The configuration property can be in the following formats 35 | * // 'bundleIn${productFlavor}${buildType}' 36 | * // 'bundleIn${buildType}' 37 | * // bundleInFreeDebug: true, 38 | * // bundleInPaidRelease: true, 39 | * // bundleInBeta: true, 40 | * 41 | * // whether to disable dev mode in custom build variants (by default only disabled in release) 42 | * // for example: to disable dev mode in the staging build type (if configured) 43 | * devDisabledInStaging: true, 44 | * // The configuration property can be in the following formats 45 | * // 'devDisabledIn${productFlavor}${buildType}' 46 | * // 'devDisabledIn${buildType}' 47 | * 48 | * // the root of your project, i.e. where "package.json" lives 49 | * root: "../../", 50 | * 51 | * // where to put the JS bundle asset in debug mode 52 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", 53 | * 54 | * // where to put the JS bundle asset in release mode 55 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release", 56 | * 57 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 58 | * // require('./image.png')), in debug mode 59 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", 60 | * 61 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 62 | * // require('./image.png')), in release mode 63 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", 64 | * 65 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means 66 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to 67 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle 68 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ 69 | * // for example, you might want to remove it from here. 70 | * inputExcludes: ["android/**", "ios/**"], 71 | * 72 | * // override which node gets called and with what additional arguments 73 | * nodeExecutableAndArgs: ["node"], 74 | * 75 | * // supply additional arguments to the packager 76 | * extraPackagerArgs: [] 77 | * ] 78 | */ 79 | 80 | project.ext.react = [ 81 | enableHermes: false, // clean and rebuild if changing 82 | ] 83 | 84 | apply from: "../../node_modules/react-native/react.gradle" 85 | 86 | /** 87 | * Set this to true to create two separate APKs instead of one: 88 | * - An APK that only works on ARM devices 89 | * - An APK that only works on x86 devices 90 | * The advantage is the size of the APK is reduced by about 4MB. 91 | * Upload all the APKs to the Play Store and people will download 92 | * the correct one based on the CPU architecture of their device. 93 | */ 94 | def enableSeparateBuildPerCPUArchitecture = false 95 | 96 | /** 97 | * Run Proguard to shrink the Java bytecode in release builds. 98 | */ 99 | def enableProguardInReleaseBuilds = false 100 | 101 | /** 102 | * The preferred build flavor of JavaScriptCore. 103 | * 104 | * For example, to use the international variant, you can use: 105 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 106 | * 107 | * The international variant includes ICU i18n library and necessary data 108 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 109 | * give correct results when using with locales other than en-US. Note that 110 | * this variant is about 6MiB larger per architecture than default. 111 | */ 112 | def jscFlavor = 'org.webkit:android-jsc:+' 113 | 114 | /** 115 | * Whether to enable the Hermes VM. 116 | * 117 | * This should be set on project.ext.react and mirrored here. If it is not set 118 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode 119 | * and the benefits of using Hermes will therefore be sharply reduced. 120 | */ 121 | def enableHermes = project.ext.react.get("enableHermes", false); 122 | 123 | android { 124 | compileSdkVersion rootProject.ext.compileSdkVersion 125 | 126 | compileOptions { 127 | sourceCompatibility JavaVersion.VERSION_1_8 128 | targetCompatibility JavaVersion.VERSION_1_8 129 | } 130 | 131 | defaultConfig { 132 | applicationId "com.example" 133 | minSdkVersion rootProject.ext.minSdkVersion 134 | targetSdkVersion rootProject.ext.targetSdkVersion 135 | versionCode 1 136 | versionName "1.0" 137 | testBuildType System.getProperty('testBuildType', 'debug') 138 | testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' 139 | } 140 | splits { 141 | abi { 142 | reset() 143 | enable enableSeparateBuildPerCPUArchitecture 144 | universalApk false // If true, also generate a universal APK 145 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" 146 | } 147 | } 148 | signingConfigs { 149 | debug { 150 | storeFile file('debug.keystore') 151 | storePassword 'android' 152 | keyAlias 'androiddebugkey' 153 | keyPassword 'android' 154 | } 155 | } 156 | buildTypes { 157 | debug { 158 | signingConfig signingConfigs.debug 159 | } 160 | release { 161 | // Caution! In production, you need to generate your own keystore file. 162 | // see https://reactnative.dev/docs/signed-apk-android. 163 | signingConfig signingConfigs.debug 164 | minifyEnabled enableProguardInReleaseBuilds 165 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 166 | // Detox-specific additions to pro-guard 167 | proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro" 168 | } 169 | } 170 | 171 | // applicationVariants are e.g. debug, release 172 | applicationVariants.all { variant -> 173 | variant.outputs.each { output -> 174 | // For each separate APK per architecture, set a unique version code as described here: 175 | // https://developer.android.com/studio/build/configure-apk-splits.html 176 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] 177 | def abi = output.getFilter(OutputFile.ABI) 178 | if (abi != null) { // null for the universal-debug, universal-release variants 179 | output.versionCodeOverride = 180 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode 181 | } 182 | 183 | } 184 | } 185 | } 186 | 187 | dependencies { 188 | implementation fileTree(dir: "libs", include: ["*.jar"]) 189 | //noinspection GradleDynamicVersion 190 | implementation "com.facebook.react:react-native:+" // From node_modules 191 | 192 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" 193 | 194 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { 195 | exclude group:'com.facebook.fbjni' 196 | } 197 | 198 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { 199 | exclude group:'com.facebook.flipper' 200 | exclude group:'com.squareup.okhttp3', module:'okhttp' 201 | } 202 | 203 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { 204 | exclude group:'com.facebook.flipper' 205 | } 206 | 207 | androidTestImplementation(project(path: ":detox")) 208 | 209 | if (enableHermes) { 210 | def hermesPath = "../../node_modules/hermes-engine/android/"; 211 | debugImplementation files(hermesPath + "hermes-debug.aar") 212 | releaseImplementation files(hermesPath + "hermes-release.aar") 213 | } else { 214 | implementation jscFlavor 215 | } 216 | } 217 | 218 | // Run this once to be able to run the application with BUCK 219 | // puts all compile dependencies into folder libs for BUCK to use 220 | task copyDownloadableDepsToLibs(type: Copy) { 221 | from configurations.compile 222 | into 'libs' 223 | } 224 | 225 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) 226 | -------------------------------------------------------------------------------- /templates/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = "29.0.2" 6 | minSdkVersion = 18 7 | compileSdkVersion = 29 8 | targetSdkVersion = 29 9 | kotlinVersion = '1.4.10' 10 | } 11 | repositories { 12 | google() 13 | jcenter() 14 | } 15 | dependencies { 16 | classpath("com.android.tools.build:gradle:3.5.3") 17 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" 18 | // NOTE: Do not place your application dependencies here; they belong 19 | // in the individual module build.gradle files 20 | } 21 | } 22 | 23 | allprojects { 24 | repositories { 25 | mavenLocal() 26 | maven { 27 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 28 | url("$rootDir/../node_modules/react-native/android") 29 | } 30 | maven { 31 | // Android JSC is installed from npm 32 | url("$rootDir/../node_modules/jsc-android/dist") 33 | } 34 | 35 | google() 36 | jcenter() 37 | maven { url 'https://www.jitpack.io' } 38 | maven { 39 | // All of Detox' artifacts are provided via the npm module 40 | url "$rootDir/../node_modules/detox/Detox-android" 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /templates/network_security_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10.0.2.2 5 | localhost 6 | 7 | --------------------------------------------------------------------------------