├── .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 |
--------------------------------------------------------------------------------