microsoft/vscode-react-native

Public

mirrored from https://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
11abbbd360e4ec727f835e113d2f672d57939ecf

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

test/extension/android/androidPlatform.test.ts

301lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import * as Q from "q";
5import * as fs from "fs";
6import * as path from "path";
7import * as mockFs from "mock-fs";
8
9import {AndroidPlatform} from "../../../src/extension/android/androidPlatform";
10import {IAndroidRunOptions} from "../../../src/extension/launchArgs";
11import {FileSystem} from "../../../src/common/node/fileSystem";
12import {ReactNative022} from "../../resources/reactNative022";
13import * as adb from "../../../src/extension/android/adb";
14import {RecordingsHelper} from "../../resources/recordingsHelper";
15import {CommandExecutor} from "../../../src/common/commandExecutor";
16import * as rnHelper from "../../../src/common/reactNativeProjectHelper";
17
18import "should";
19import * as sinon from "sinon";
20
21// TODO: Launch the extension server
22
23suite("androidPlatform", function () {
24 suite("extensionContext", function () {
25 const projectRoot = "C:/projects/SampleApplication_21/";
26 const androidProjectPath = path.join(projectRoot, "android");
27 const applicationName = "SampleApplication";
28 const androidPackageName = "com.sampleapplication";
29 const genericRunOptions: IAndroidRunOptions = { platform: "android", workspaceRoot: projectRoot, projectRoot: projectRoot };
30
31 const rnProjectContent = fs.readFileSync(ReactNative022.DEFAULT_PROJECT_FILE, "utf8");
32
33 let fileSystem: FileSystem;
34 let reactNative: ReactNative022;
35 let androidPlatform: AndroidPlatform;
36 let sandbox: Sinon.SinonSandbox;
37 let devices: any;
38
39 function createAndroidPlatform(runOptions: IAndroidRunOptions): AndroidPlatform {
40 return new AndroidPlatform(runOptions);
41 }
42
43 setup(() => {
44 mockFs();
45 sandbox = sinon.sandbox.create();
46
47 // Configure all the dependencies we'll use in our tests
48 fileSystem = new FileSystem();
49 reactNative = new ReactNative022(fileSystem);
50 androidPlatform = createAndroidPlatform(genericRunOptions);
51
52 sandbox.stub(CommandExecutor.prototype, "spawnReactCommand", function () {
53 return reactNative.runAndroid(genericRunOptions);
54 });
55
56 sandbox.stub(rnHelper.ReactNativeProjectHelper, "getReactNativeVersion", function () {
57 return Q.resolve("0.0.1");
58 });
59
60 sandbox.stub(adb.AdbHelper, "launchApp", function (projectRoot_: string, packageName: string, debugTarget?: string) {
61 devices = devices.map((device: any) => {
62 if (!debugTarget) {
63 device.installedApplications[androidPackageName] = { isInDebugMode: false };
64 }
65
66 if (debugTarget && debugTarget === device.id) {
67 device.installedApplications[androidPackageName] = { isInDebugMode: false };
68 }
69
70 return device;
71 });
72
73 return Q.resolve(void 0);
74 });
75 sandbox.stub(adb.AdbHelper, "getConnectedDevices", function () {
76 return Q.resolve(devices);
77 });
78 sandbox.stub(adb.AdbHelper, "getOnlineDevices", function () {
79 return Q.resolve(devices.filter((device: any) => {
80 return device.isOnline;
81 }));
82 });
83 sandbox.stub(adb.AdbHelper, "apiVersion", function () {
84 return Q.resolve(adb.AndroidAPILevel.LOLLIPOP);
85 });
86 sandbox.stub(adb.AdbHelper, "reverseAdb", function () {
87 return Q.resolve(void 0);
88 });
89
90 sandbox.stub(reactNative, "installAppInDevice", function (deviceId: string) {
91 devices = devices.map((device: any) => {
92 if (deviceId && deviceId === device.id) {
93 device.installedApplications[androidPackageName] = {};
94 }
95
96 return device;
97 });
98 return Q.resolve(void 0);
99 });
100
101 // Create a React-Native project we'll use in our tests
102 return reactNative
103 .fromProjectFileContent(rnProjectContent)
104 .createProject(projectRoot, applicationName);
105 });
106
107 teardown(() => {
108 mockFs.restore();
109 sandbox.restore();
110 devices = [];
111 });
112
113 const testWithRecordings = new RecordingsHelper(() => reactNative).test;
114
115 testWithRecordings("runApp launches the app when a single emulator is connected",
116 [
117 "react-native/run-android/win10-rn0.21.0/succeedsWithOneVSEmulator",
118 "react-native/run-android/win10-rn0.22.2/succeedsWithOneVSEmulator",
119 "react-native/run-android/osx10.10-rn0.21.0/succeedsWithOneVSEmulator",
120 ], () => {
121 devices = fillDevices(["Nexus_5"]);
122
123 return Q({})
124 .then(() => {
125 return androidPlatform.runApp();
126 }).then(() => {
127 return devices[0].installedApplications[androidPackageName].isInDebugMode === false;
128 }).then(isRunning => {
129 isRunning.should.be.true();
130 });
131 });
132
133 testWithRecordings("runApp launches the app when two emulators are connected",
134 ["react-native/run-android/win10-rn0.21.0/succeedsWithTwoVSEmulators"], () => {
135 devices = fillDevices(["Nexus_5", "Nexus_6"]);
136
137 return Q({})
138 .then(() => {
139 return androidPlatform.runApp();
140 }).then(() => {
141 return Q.all([
142 Q.resolve(devices[0].installedApplications[androidPackageName].isInDebugMode === false),
143 Q.resolve(devices[1].installedApplications[androidPackageName].isInDebugMode === false),
144 ]);
145 }).spread((isRunningOnNexus5, isRunningOnNexus6) => {
146 // It should be running in exactly one of these two devices
147 isRunningOnNexus5.should.not.eql(isRunningOnNexus6);
148 });
149 });
150
151 testWithRecordings("runApp launches the app when three emulators are connected",
152 ["react-native/run-android/win10-rn0.21.0/succeedsWithThreeVSEmulators"], () => {
153 devices = fillDevices(["Nexus_5", "Nexus_6", "Nexus_7"]);
154 return Q({})
155 .then(() => {
156 return androidPlatform.runApp();
157 }).then(() => {
158 return Q.all([
159 Q.resolve(devices[0].installedApplications[androidPackageName].isInDebugMode === false),
160 Q.resolve(devices[1].installedApplications[androidPackageName].isInDebugMode === false),
161 Q.resolve(devices[2].installedApplications[androidPackageName].isInDebugMode === false),
162 ]);
163 }).then(isRunningList => {
164 // It should be running in exactly one of these three devices
165 isRunningList.filter(v => v).should.eql([true]);
166 });
167 });
168
169 testWithRecordings("runApp fails if no devices are connected",
170 ["react-native/run-android/win10-rn0.21.0/failsDueToNoDevicesConnected"], () => {
171 return Q({})
172 .then(() => {
173 return androidPlatform.runApp();
174 }).then(() => {
175 should.assert(false, "runApp should've exited with an error");
176 }, reason => {
177 reason.message.should.eql("Unknown error");
178 });
179 });
180
181 testWithRecordings("runApp launches the app in an online emulator only",
182 ["react-native/run-android/win10-rn0.21.0/succeedsWithFiveVSEmulators"], () => {
183 devices = fillDevices(["Nexus_5", "Nexus_6", "Nexus_7", "Nexus_8", "Nexus_9"]);
184 devices[4].isOnline = false;
185
186 return Q({})
187 .then(() => {
188 return androidPlatform.runApp();
189 }).then(() => {
190 return devices[4].installedApplications[androidPackageName].isInDebugMode === false;
191 }).then((isRunningOnOfflineDevice) => {
192 isRunningOnOfflineDevice.should.be.false();
193 });
194 });
195
196 testWithRecordings("runApp launches the app in the device specified as target",
197 ["react-native/run-android/win10-rn0.21.0/succeedsWithFiveVSEmulators"], () => {
198 devices = fillDevices(["Nexus_5", "Nexus_6", "Nexus_10", "Nexus_11", "Nexus_12"]);
199
200 return Q({})
201 .then(() => {
202 const runOptions: any = { platform: "android", workspaceRoot: projectRoot, projectRoot: projectRoot, target: "Nexus_12" };
203 return createAndroidPlatform(runOptions).runApp();
204 }).then(() => {
205 return devices[4].installedApplications[androidPackageName].isInDebugMode === false;
206 }).then((isRunningOnNexus12) => {
207 isRunningOnNexus12.should.be.true();
208 });
209 });
210
211 testWithRecordings("runApp launches the app in a random online device if the target is offline",
212 ["react-native/run-android/win10-rn0.21.0/succeedsWithTenVSEmulators"], () => {
213 const onlineDevicesIds = ["Nexus_11", "Nexus_13", "Nexus_14", "Nexus_15", "Nexus_16", "Nexus_17"];
214 const offineDevicesIds = ["Nexus_5", "Nexus_6", "Nexus_10", "Nexus_12"];
215 devices = fillDevices(offineDevicesIds.concat(onlineDevicesIds));
216 devices[0].isOnline = false;
217 devices[1].isOnline = false;
218 devices[2].isOnline = false;
219 devices[3].isOnline = false;
220
221 return Q({})
222 .then(() => {
223 const runOptions: any = { platform: "android", workspaceRoot: projectRoot, projectRoot: projectRoot, target: "Nexus_12" };
224 return createAndroidPlatform(runOptions).runApp();
225 }).then(() => {
226 return devices.filter((device: any) => device.installedApplications[androidPackageName].isInDebugMode === false);
227 }).then((devicesRunningAppId) => {
228 devicesRunningAppId.length.should.eql(1);
229 onlineDevicesIds.should.containEql(devicesRunningAppId[0].id);
230 });
231 });
232
233 testWithRecordings("runApp doesn't fail even if the call to start the LogCat does fail",
234 [
235 "react-native/run-android/win10-rn0.21.0/succeedsWithOneVSEmulator",
236 "react-native/run-android/win10-rn0.22.2/succeedsWithOneVSEmulator",
237 "react-native/run-android/osx10.10-rn0.21.0/succeedsWithOneVSEmulator",
238 ], () => {
239 devices = fillDevices(["Nexus_5"]);
240
241 return Q({})
242 .then(() => {
243 return androidPlatform.runApp();
244 }).then(() => {
245 return devices[0].installedApplications[androidPackageName].isInDebugMode === false;
246 }).then(isRunning => {
247 isRunning.should.be.true();
248 });
249 });
250
251 testWithRecordings("runApp fails when the android project doesn't exist, and shows a nice error message",
252 [
253 "react-native/run-android/win10-rn0.21.0/failsDueToAndroidFolderMissing",
254 "react-native/run-android/win10-rn0.22.2/failsDueToAndroidFolderMissing",
255 ], () => {
256 devices = fillDevices(["Nexus_5"]);
257
258 return Q({})
259 .then(() => {
260 return fileSystem.rmdir(androidProjectPath);
261 }).then(() => {
262 return androidPlatform.runApp();
263 }).then(() => {
264 should.assert(false, "Expected runApp to end up with an error");
265 return false;
266 }, reason => {
267 reason.message.should.eql("Android project not found.");
268 return !!devices[0].installedApplications[androidPackageName];
269 }).then(isRunning => {
270 isRunning.should.be.false();
271 });
272 });
273
274 testWithRecordings("runApp fails when the android emulator shell is unresponsive, and shows a nice error message",
275 ["react-native/run-android/osx10.10-rn0.21.0/failsDueToAdbCommandTimeout"], () => {
276 devices = fillDevices(["Nexus_5"]);
277
278 return Q({})
279 .then(() => {
280 return androidPlatform.runApp();
281 }).then(() => {
282 should.assert(false, "Expected runApp to end up with an error");
283 return false;
284 }, reason => {
285 "An Android shell command timed-out. Please retry the operation.".should.eql(reason.message);
286 return !!devices[0].installedApplications[androidPackageName];
287 }).then(isRunning => {
288 isRunning.should.be.false();
289 });
290 });
291 });
292});
293
294function fillDevices(ids: string[]): any[] {
295 let devices: any[] = [];
296 ids.forEach(id => {
297 devices.push({ isOnline: true, installedApplications: {}, runningApplications: {}, type: adb.DeviceType.AndroidSdkEmulator, id: id });
298 });
299
300 return devices;
301}