microsoft/vscode-react-native

Public

mirrored fromhttps://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
0.6.1

Branches

Tags

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

Clone

HTTPS

Download ZIP

test/extension/android/androidPlatform.test.ts

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