microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
5759f79cea6d220d75c4589a028aec52100953d6

Branches

Tags

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

Clone

HTTPS

Download ZIP

test/resources/reactNative022.ts

178lines · 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 path from "path";
5import * as assert from "assert";
6import {PromiseUtil} from "../../src/common/node/promise";
7import {IAndroidRunOptions} from "../../src/extension/launchArgs";
8import {ISpawnResult} from "../../src/common/node/childProcess";
9import {FileSystem} from "../../src/common/node/fileSystem";
10import {Package} from "../../src/common/node/package";
11import {Recording, Simulator} from "./processExecution/simulator";
12import {AdbHelper} from "../../src/extension/android/adb";
13import {APKSerializer} from "./simulators/apkSerializer";
14
15const sampleRNProjectPath = path.join(__dirname, "sampleReactNative022Project");
16const processExecutionsRecordingsPath = path.join(__dirname, "processExecutionsRecordings");
17
18/* This class simulates calling the React-Native CLI v0.22. It currently supports react-native init
19 and react-native run-android. */
20export class ReactNative022 {
21
22 public static DEFAULT_PROJECT_FILE = path.join(sampleRNProjectPath, "package.json");
23
24 private static ANDROID_APK_RELATIVE_PATH = "android/app/build/outputs/apk/app-debug.apk";
25
26 private projectFileContent: string;
27
28 private simulator: Simulator = new Simulator({
29 beforeStart: () => this.readAndroidPackageName(), // 1. We read the package.json to verify this is a RN project
30 outputBased: [
31 {
32 eventPattern: /:app:assembleDebug/,
33 action: () => this.createAPK(), // 2. We compile the application.
34 },
35 {
36 eventPattern: /Installed on [0-9]+ devices*\./,
37 action: () => this.installAppInAllDevices(), // 3. We install it on all available devices.
38 },
39 ],
40 beforeSuccess: (stdout: string, stderr: string) => // 4. If we didn't had any errors after starting to launch the app,
41 this.launchApp(stdout, stderr), // it means we were succesful
42 });
43
44 private recording: Recording;
45
46 private androidPackageName: string;
47 private projectRoot: string;
48 private androidAPKPath: string;
49
50 constructor(private fileSystem: FileSystem, private adbHelper: AdbHelper) {
51 assert(this.fileSystem, "fileSystem shouldn't be null");
52 }
53
54 public fromProjectFileContent(content: string): this {
55 this.projectFileContent = content;
56 return this;
57 }
58
59 public loadRecordingFromName(recordingName: string): Promise<void> {
60 return this.loadRecordingFromFile(path.join(processExecutionsRecordingsPath, `${recordingName}.json`));
61 }
62
63 public loadRecordingFromString(recordingContent: string): Promise<void> {
64 return Promise.resolve(this.loadRecording(JSON.parse(recordingContent)));
65 }
66
67 public loadRecordingFromFile(recordingPath: string): Promise<void> {
68 return new FileSystem().readFile(recordingPath)
69 .then(fileContents => {
70 this.loadRecording(JSON.parse(fileContents.toString()));
71 });
72 }
73
74 public loadRecording(recording: Recording): void {
75 assert(recording, "recording shouldn't be null");
76 this.recording = recording;
77 }
78
79 public createProject(projectRoot: string, projectName: string): Promise<void> {
80 return Promise.resolve()
81 .then(() => {
82 this.fileSystem.makeDirectoryRecursiveSync(projectRoot);
83 return this.projectFileContent !== undefined ?
84 this.projectFileContent :
85 this.readDefaultProjectFile();
86 }).then(defaultContents => {
87 const reactNativeConfiguration = JSON.parse(defaultContents.toString());
88 reactNativeConfiguration.name = projectName;
89 const reactNativeConfigurationFormatted = JSON.stringify(reactNativeConfiguration);
90 return this.fileSystem.writeFile(this.getPackageJsonPath(projectRoot), reactNativeConfigurationFormatted);
91 }).then(() => {
92 return this.fileSystem.mkDir(this.getAndroidProjectPath(projectRoot));
93 });
94 }
95
96 public runAndroid(runOptions: IAndroidRunOptions): ISpawnResult {
97 this.projectRoot = runOptions.projectRoot;
98 this.simulator.simulate(this.recording).then(() => {});
99 return this.simulator.spawn();
100 }
101
102 private getAndroidProjectPath(projectRoot = this.projectRoot): string {
103 return path.join(projectRoot, "android");
104 }
105
106 private getPackageJsonPath(projectRoot: string): string {
107 return new Package(projectRoot, { fileSystem: this.fileSystem }).informationJsonFilePath();
108 }
109
110 private readAndroidPackageName(): Promise<void> {
111 return new Package(this.projectRoot, { fileSystem: this.fileSystem }).name().then(name => {
112 this.androidPackageName = `com.${name.toLowerCase()}`;
113 });
114 }
115
116 private createAPK(): Promise<void> {
117 return this.isAndroidProjectPresent().then(isPresent => {
118 return isPresent ? void 0 : Promise.reject<void>(new Error("The recording expects the Android project to be present, but it's not"));
119 }).then(() => {
120 this.androidAPKPath = path.join(this.projectRoot, ReactNative022.ANDROID_APK_RELATIVE_PATH);
121 return new APKSerializer(this.fileSystem).writeApk(this.androidAPKPath, { packageName: this.androidPackageName });
122 });
123 }
124
125 private isAndroidProjectPresent(): Promise<boolean> {
126 // TODO: Make more checks as neccesary for the tests
127 return this.fileSystem.directoryExists(this.getAndroidProjectPath());
128 }
129
130 private installAppInAllDevices(): Promise<void> {
131 let devices = this.adbHelper.getConnectedDevices();
132 return new PromiseUtil().reduce(devices, device => this.installAppInDevice(device.id));
133 }
134
135 private installAppInDevice(deviceId: string): Promise<void> {
136 throw Error("Mock not implemented");
137 }
138
139 private launchApp(stdout: string, stderr: string): Promise<void> {
140 /*
141 Sample output we want to accept:
142 BUILD SUCCESSFUL
143
144 Total time: 9.052 secs
145 Starting the app (C:\Program Files (x86)\Android\android-sdk/platform-tools/adb shell am start -n com.sampleapplication/.MainActivity)...
146 Starting: Intent { cmp=com.sampleapplication/.MainActivity }
147
148
149 Sample output we don't to accept:
150 BUILD SUCCESSFUL
151
152 Total time: 9.052 secs
153 Starting the app (C:\Program Files (x86)\Android\android-sdk/platform-tools/adb shell am start -n com.sampleapplication/.MainActivity)...
154 Starting: Intent { cmp=com.sampleapplication/.MainActivity }
155 Error: some error happened
156 **/
157 const succesfulOutputEnd = `Starting the app \\(.*adb shell am start -n ([^ /]+)\/\\.MainActivity\\)\\.\\.\\.\\s+`
158 + `Starting: Intent { cmp=([^ /]+)\/\\.MainActivity }\\s+$`;
159 const matches = stdout.match(new RegExp(succesfulOutputEnd));
160 if (matches) {
161 if (matches.length === 3 && matches[1] === this.androidPackageName && matches[2] === this.androidPackageName) {
162 return this.adbHelper.launchApp(this.projectRoot, this.androidPackageName);
163 } else {
164 return Promise.reject<void>(new Error("There was an error while trying to match the Starting the app messages."
165 + "Expected to match the pattern and recognize the expected android package name, but it failed."
166 + `Expected android package name: ${this.androidPackageName}. Actual matches: ${JSON.stringify(matches)}`));
167 }
168 } else {
169 // The record doesn't indicate that the app was launched, so we don't do anything
170 return Promise.resolve();
171 }
172 }
173
174 private readDefaultProjectFile(): Promise<string | Buffer> {
175 const realFileSystem = new FileSystem(); // We always use the real file system (not the mock one) to read the sample project
176 return realFileSystem.readFile(ReactNative022.DEFAULT_PROJECT_FILE);
177 }
178}
179