microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
0.6.15

Branches

Tags

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

Clone

HTTPS

Download ZIP

test/extension/android/androidPlatform.test.ts

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