microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
7ef94dcec53e3855b735c2023711fb53cc5764af

Branches

Tags

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

Clone

HTTPS

Download ZIP

test/extension/android/androidPlatform.test.ts

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