microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
b2b5d016a126b337e01405c6006a069da028e0bf

Branches

Tags

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

Clone

HTTPS

Download ZIP

test/smoke/package/src/debugAndroid.test.ts

226lines · 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 assert from "assert";
5import * as path from "path";
6import { AppiumHelper, Platform, AppiumClient } from "./helpers/appiumHelper";
7import { AndroidEmulatorHelper } from "./helpers/androidEmulatorHelper";
8import { sleep, findStringInFile, findExpoURLInLogFile, ExpoLaunch, findExpoSuccessAndFailurePatterns } from "./helpers/utilities";
9import { SmokeTestsConstants } from "./helpers/smokeTestsConstants";
10import { ExpoWorkspacePath, pureRNWorkspacePath, RNworkspacePath, prepareReactNativeProjectForHermesTesting, runVSCode } from "./main";
11import { SetupEnvironmentHelper } from "./helpers/setupEnvironmentHelper";
12import { TestRunArguments } from "./helpers/configHelper";
13import { Application } from "../../automation";
14
15const RN_APP_PACKAGE_NAME = "com.latestrnapp";
16const RN_APP_ACTIVITY_NAME = "com.latestrnapp.MainActivity";
17const EXPO_APP_PACKAGE_NAME = SetupEnvironmentHelper.expoPackageName;
18const EXPO_APP_ACTIVITY_NAME = `${EXPO_APP_PACKAGE_NAME}.experience.HomeActivity`;
19const RNDebugConfigName = "Debug Android";
20const RNHermesDebugConfigName = "Debug Android (Hermes) - Experimental";
21const RNHermesAttachConfigName = "Attach to Hermes application - Experimental";
22const ExpoDebugConfigName = "Debug in Exponent";
23const ExpoLanDebugConfigName = "Debug in Exponent (LAN)";
24const ExpoLocalDebugConfigName = "Debug in Exponent (Local)";
25
26
27const RNSetBreakpointOnLine = 1;
28const RNHermesSetBreakpointOnLine = 11;
29const ExpoSetBreakpointOnLine = 1;
30// Time for Android Debug Test before it reaches timeout
31const debugAndroidTestTime = SmokeTestsConstants.androidAppBuildAndInstallTimeout + 100 * 1000;
32// Time for Android Expo Debug Test before it reaches timeout
33const debugExpoTestTime = SmokeTestsConstants.expoAppBuildAndInstallTimeout + 400 * 1000;
34
35export function setup(testParameters?: TestRunArguments) {
36
37 describe("Debugging Android", () => {
38 let app: Application;
39 let clientInited: AppiumClient;
40
41 afterEach(async () => {
42 if (app) {
43 await app.stop();
44 }
45 if (clientInited) {
46 clientInited.closeApp();
47 clientInited.endAll();
48 }
49 });
50
51 async function expoTest(testName: string, workspacePath: string, debugConfigName: string, triesToLaunchApp: number) {
52 app = await runVSCode(workspacePath);
53 console.log(`${testName}: ${workspacePath} directory is opened in VS Code`);
54 await app.workbench.quickopen.openFile("App.js");
55 await app.workbench.editors.scrollTop();
56 console.log(`${testName}: App.js file is opened`);
57 await app.workbench.debug.setBreakpointOnLine(ExpoSetBreakpointOnLine);
58 console.log(`${testName}: Breakpoint is set on line ${ExpoSetBreakpointOnLine}`);
59 console.log(`${testName}: Chosen debug configuration: ${debugConfigName}`);
60 console.log(`${testName}: Starting debugging`);
61 // Scan logs only if launch retries provided (Expo Tunnel scenarios)
62 if (triesToLaunchApp <= 1) {
63 await app.workbench.quickopen.runDebugScenario(debugConfigName);
64 } else {
65 if (process.env.REACT_NATIVE_TOOLS_LOGS_DIR) {
66 for (let retry = 1; retry <= triesToLaunchApp; retry++) {
67 let expoLaunchStatus: ExpoLaunch;
68 await app.workbench.quickopen.runDebugScenario(debugConfigName);
69 expoLaunchStatus = await findExpoSuccessAndFailurePatterns(path.join(process.env.REACT_NATIVE_TOOLS_LOGS_DIR, SmokeTestsConstants.ReactNativeLogFileName), SmokeTestsConstants.ExpoSuccessPattern, SmokeTestsConstants.ExpoFailurePattern);
70 if (expoLaunchStatus.successful) {
71 break;
72 } else {
73 if (retry === triesToLaunchApp) {
74 assert.fail(`App start has failed after ${retry} retries`);
75 }
76 console.log(`Attempt to start #${retry} failed, retrying...`);
77 }
78 }
79 } else {
80 assert.fail("REACT_NATIVE_TOOLS_LOGS_DIR is not defined");
81 }
82 }
83
84 await app.workbench.editors.waitForTab("Expo QR Code");
85 await app.workbench.editors.waitForActiveTab("Expo QR Code");
86 console.log(`${testName}: 'Expo QR Code' tab found`);
87
88 let expoURL;
89 if (process.env.REACT_NATIVE_TOOLS_LOGS_DIR) {
90 expoURL = findExpoURLInLogFile(path.join(process.env.REACT_NATIVE_TOOLS_LOGS_DIR, SmokeTestsConstants.ReactNativeRunExpoLogFileName));
91 }
92 assert.notStrictEqual(expoURL, null, "Expo URL pattern is not found");
93 expoURL = expoURL as string;
94 const opts = AppiumHelper.prepareAttachOptsForAndroidActivity(EXPO_APP_PACKAGE_NAME, EXPO_APP_ACTIVITY_NAME, AndroidEmulatorHelper.androidEmulatorName);
95 let client = AppiumHelper.webdriverAttach(opts);
96 clientInited = client.init();
97 // TODO Add listener to trigger that main expo app has been ran
98 await AppiumHelper.openExpoApplication(Platform.Android, clientInited, expoURL, workspacePath);
99 // TODO Add listener to trigger that child expo app has been ran instead of using timeout
100 console.log(`${testName}: Waiting ${SmokeTestsConstants.expoAppBuildAndInstallTimeout}ms until Expo app is ready...`);
101 await sleep(SmokeTestsConstants.expoAppBuildAndInstallTimeout);
102 await AppiumHelper.enableRemoteDebugJS(clientInited, Platform.Android);
103 await app.workbench.debug.waitForDebuggingToStart();
104 console.log(`${testName}: Debugging started`);
105 await app.workbench.debug.waitForStackFrame(sf => sf.name === "App.js" && sf.lineNumber === ExpoSetBreakpointOnLine, `looking for App.js and line ${ExpoSetBreakpointOnLine}`);
106 console.log(`${testName}: Stack frame found`);
107 await app.workbench.debug.stepOver();
108 // Wait for debug string to be rendered in debug console
109 await sleep(SmokeTestsConstants.debugConsoleSearchTimeout);
110 console.log(`${testName}: Searching for \"Test output from debuggee\" string in console`);
111 let found = await app.workbench.debug.waitForOutput(output => output.some(line => line.indexOf("Test output from debuggee") >= 0));
112 assert.notStrictEqual(found, false, "\"Test output from debuggee\" string is missing in debug console");
113 console.log(`${testName}: \"Test output from debuggee\" string is found`);
114 await app.workbench.debug.stopDebugging();
115 console.log(`${testName}: Debugging is stopped`);
116 }
117
118 it("RN app Debug test", async function () {
119 this.timeout(debugAndroidTestTime);
120 app = await runVSCode(RNworkspacePath);
121 await app.workbench.quickopen.openFile("App.js");
122 await app.workbench.editors.scrollTop();
123 console.log("Android Debug test: App.js file is opened");
124 await app.workbench.debug.setBreakpointOnLine(RNSetBreakpointOnLine);
125 console.log(`Android Debug test: Breakpoint is set on line ${RNSetBreakpointOnLine}`);
126 console.log(`Android Debug test: Chosen debug configuration: ${RNDebugConfigName}`);
127 console.log("Android Debug test: Starting debugging");
128 await app.workbench.quickopen.runDebugScenario(RNDebugConfigName);
129 const opts = AppiumHelper.prepareAttachOptsForAndroidActivity(RN_APP_PACKAGE_NAME, RN_APP_ACTIVITY_NAME, AndroidEmulatorHelper.androidEmulatorName);
130 await AndroidEmulatorHelper.checkIfAppIsInstalled(RN_APP_PACKAGE_NAME, SmokeTestsConstants.androidAppBuildAndInstallTimeout);
131 let client = AppiumHelper.webdriverAttach(opts);
132 clientInited = client.init();
133 await AppiumHelper.enableRemoteDebugJS(clientInited, Platform.Android);
134 await app.workbench.debug.waitForDebuggingToStart();
135 console.log("Android Debug test: Debugging started");
136 await app.workbench.debug.waitForStackFrame(sf => sf.name === "App.js" && sf.lineNumber === RNSetBreakpointOnLine, `looking for App.js and line ${RNSetBreakpointOnLine}`);
137 console.log("Android Debug test: Stack frame found");
138 await app.workbench.debug.stepOver();
139 // await for our debug string renders in debug console
140 await sleep(SmokeTestsConstants.debugConsoleSearchTimeout);
141 console.log("Android Debug test: Searching for \"Test output from debuggee\" string in console");
142 let found = await app.workbench.debug.waitForOutput(output => output.some(line => line.indexOf("Test output from debuggee") >= 0));
143 console.log(found);
144 assert.notStrictEqual(found, false, "\"Test output from debuggee\" string is missing in debug console");
145 console.log("Android Debug test: \"Test output from debuggee\" string is found");
146 await app.workbench.debug.stopDebugging();
147 console.log("Android Debug test: Debugging is stopped");
148 });
149
150 it("Hermes RN app Debug test", async function () {
151 this.timeout(debugAndroidTestTime);
152 prepareReactNativeProjectForHermesTesting();
153 AndroidEmulatorHelper.uninstallTestAppFromEmulator(RN_APP_PACKAGE_NAME);
154 app = await runVSCode(RNworkspacePath);
155 await app.workbench.quickopen.openFile("AppTestButton.js");
156 await app.workbench.editors.scrollTop();
157 console.log("Android Debug Hermes test: AppTestButton.js file is opened");
158 await app.workbench.debug.setBreakpointOnLine(RNHermesSetBreakpointOnLine);
159 console.log(`Android Debug Hermes test: Breakpoint is set on line ${RNHermesSetBreakpointOnLine}`);
160 console.log(`Android Debug Hermes test: Chosen debug configuration: ${RNHermesDebugConfigName}`);
161 console.log("Android Debug Hermes test: Starting debugging");
162 await app.workbench.quickopen.runDebugScenario(RNHermesDebugConfigName);
163 const opts = AppiumHelper.prepareAttachOptsForAndroidActivity(RN_APP_PACKAGE_NAME, RN_APP_ACTIVITY_NAME, AndroidEmulatorHelper.androidEmulatorName);
164 await AndroidEmulatorHelper.checkIfAppIsInstalled(RN_APP_PACKAGE_NAME, SmokeTestsConstants.androidAppBuildAndInstallTimeout);
165 let client = AppiumHelper.webdriverAttach(opts);
166 clientInited = client.init();
167 await app.workbench.debug.waitForDebuggingToStart();
168 console.log("Android Debug Hermes test: Debugging started");
169 console.log("Android Debug Hermes test: Checking for Hermes mark");
170 let isHermesWorking = await AppiumHelper.isHermesWorking(clientInited);
171 assert.equal(isHermesWorking, true);
172 console.log("Android Debug Hermes test: Reattaching to Hermes app");
173 await app.workbench.debug.stopDebugging();
174 await app.workbench.quickopen.runDebugScenario(RNHermesAttachConfigName);
175 console.log("Android Debug Hermes test: Reattached successfully");
176 await sleep(7000);
177 console.log("Android Debug Hermes test: Click Test Button");
178 await AppiumHelper.clickTestButtonHermes(clientInited);
179 await app.workbench.debug.waitForStackFrame(sf => sf.name === "AppTestButton.js" && sf.lineNumber === RNHermesSetBreakpointOnLine, `looking for AppTestButton.js and line ${RNHermesSetBreakpointOnLine}`);
180 console.log("Android Debug Hermes test: Stack frame found");
181 await app.workbench.debug.continue();
182 // await for our debug string renders in debug console
183 await sleep(SmokeTestsConstants.debugConsoleSearchTimeout);
184 if (process.env.REACT_NATIVE_TOOLS_LOGS_DIR) {
185 console.log("Android Debug Hermes test: Searching for \"Test output from Hermes debuggee\" string in output file");
186 let found = findStringInFile(path.join(process.env.REACT_NATIVE_TOOLS_LOGS_DIR, SmokeTestsConstants.ChromeDebugCoreLogFileName), "Test output from Hermes debuggee");
187 assert.notStrictEqual(found, false, "\"Test output from Hermes debuggee\" string is missing in output file");
188 console.log("Android Debug test: \"Test output from Hermes debuggee\" string is found");
189 }
190 await app.workbench.debug.disconnectFromDebugger();
191 console.log("Android Debug Hermes test: Debugging is stopped");
192 });
193
194 it("Expo app Debug test(Tunnel)", async function () {
195 if (testParameters && testParameters.RunBasicTests) {
196 this.skip();
197 }
198 this.timeout(debugExpoTestTime);
199 await expoTest("Android Expo Debug test(Tunnel)", ExpoWorkspacePath, ExpoDebugConfigName, 5);
200 });
201
202 it("Pure RN app Expo test(LAN)", async function () {
203 if (testParameters && testParameters.RunBasicTests) {
204 this.skip();
205 }
206 this.timeout(debugExpoTestTime);
207 await expoTest("Android pure RN Expo test(LAN)", pureRNWorkspacePath, ExpoLanDebugConfigName, 1);
208 });
209
210 it("Expo app Debug test(LAN)", async function () {
211 if (testParameters && testParameters.RunBasicTests) {
212 this.skip();
213 }
214 this.timeout(debugExpoTestTime);
215 await expoTest("Android Expo Debug test(LAN)", ExpoWorkspacePath, ExpoLanDebugConfigName, 1);
216 });
217
218 it("Expo app Debug test(localhost)", async function () {
219 if (testParameters && testParameters.RunBasicTests) {
220 this.skip();
221 }
222 this.timeout(debugExpoTestTime);
223 await expoTest("Android Expo Debug test(localhost)", ExpoWorkspacePath, ExpoLocalDebugConfigName, 1);
224 });
225 });
226}
227