microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
7b48f26eb8caae7ed9cc1a09249195dfed76fa76

Branches

Tags

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

Clone

HTTPS

Download ZIP

test/cdp-proxy/reactNativeCDPProxy.test.ts

242lines · 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 {
5 Connection,
6 Server,
7 WebSocketTransport,
8 IProtocolCommand,
9 IProtocolError,
10 IProtocolSuccess,
11} from "vscode-cdp-proxy";
12import { ReactNativeCDPProxy } from "./../../src/cdp-proxy/reactNativeCDPProxy";
13import { generateRandomPortNumber } from "./../../src/common/extensionHelper";
14import { RnCDPMessageHandler } from "../../src/cdp-proxy/CDPMessageHandlers/rnCDPMessageHandler";
15import { ICDPMessageHandler } from "../../src/cdp-proxy/CDPMessageHandlers/ICDPMessageHandler";
16import { HermesCDPMessageHandler } from "../../src/cdp-proxy/CDPMessageHandlers/hermesCDPMessageHandler";
17import { LogLevel } from "../../src/extension/log/LogHelper";
18import { DebuggerEndpointHelper } from "./../../src/cdp-proxy/debuggerEndpointHelper";
19import { Request } from "../../src/common/node/request";
20import assert = require("assert");
21import { CDP_API_NAMES } from "../../src/cdp-proxy/CDPMessageHandlers/CDPAPINames";
22import {
23 HERMES_NATIVE_FUNCTION_NAME,
24 HERMES_NATIVE_FUNCTION_SCRIPT_ID,
25 ARRAY_REQUEST_PHRASE_MARKER,
26 mockCallFrames,
27 mockResults,
28} from "./cdpConstants";
29import { PromiseUtil } from "../../src/common/node/promise";
30
31suite("reactNativeCDPProxy", function () {
32 const cdpProxyHostAddress = "127.0.0.1"; // localhost
33 const cdpProxyPort = generateRandomPortNumber();
34 const cdpProxyLogLevel = LogLevel.Custom;
35 const proxy = new ReactNativeCDPProxy(cdpProxyHostAddress, cdpProxyPort);
36
37 const wsTargetPort = generateRandomPortNumber();
38 let wsTargetServer: Server | null;
39
40 let targetConnection: Connection | null;
41 let debugConnection: Connection | null;
42
43 // For all hooks and tests set a time limit
44 this.timeout(5000);
45
46 async function getMessageFromTarget(message: any): Promise<any> {
47 return new Promise(resolve => {
48 targetConnection?.send(message);
49
50 debugConnection?.onCommand((evt: IProtocolCommand) => {
51 resolve(evt);
52 });
53 });
54 }
55
56 async function getMessageFromDebugger(message: any): Promise<any> {
57 return new Promise(resolve => {
58 debugConnection?.send(message);
59
60 targetConnection?.onCommand((evt: IProtocolCommand) => {
61 resolve(evt);
62 });
63 });
64 }
65
66 suiteSetup(async () => {
67 proxy.setApplicationTargetPort(wsTargetPort);
68 await proxy.initializeServer(new RnCDPMessageHandler(), cdpProxyLogLevel);
69
70 const server = await Server.create({ host: "localhost", port: wsTargetPort });
71 wsTargetServer = server;
72 server.onConnection(([connection, request]: [Connection, Request]) => {
73 targetConnection = connection;
74 });
75
76 const proxyUri = await new DebuggerEndpointHelper().getWSEndpoint(
77 `http://${cdpProxyHostAddress}:${cdpProxyPort}`,
78 );
79 debugConnection = new Connection(await WebSocketTransport.create(proxyUri));
80
81 // Due to the time limit, sooner or later this cycle will end
82 await PromiseUtil.waitUntil(() => !!targetConnection, 1000, 5000);
83 });
84
85 suiteTeardown(() => {
86 if (targetConnection) {
87 targetConnection.close();
88 targetConnection = null;
89 }
90 if (debugConnection) {
91 debugConnection.close();
92 debugConnection = null;
93 }
94 proxy.stopServer();
95 if (wsTargetServer) {
96 wsTargetServer.dispose();
97 wsTargetServer = null;
98 }
99 });
100
101 suite("MessageHandlers", () => {
102 let rnHandler = new RnCDPMessageHandler();
103 let directHandler = new HermesCDPMessageHandler();
104
105 function deliveryTest(messageHandler: ICDPMessageHandler): Mocha.Test {
106 return test(`Messages should be delivered correctly with ${messageHandler.constructor.name}`, async () => {
107 const targetMessageStart = { method: "Target.start", params: { reason: "test" } };
108 const debuggerMessageStart = {
109 method: "Debugger.start",
110 params: { reason: "test" },
111 };
112
113 const messageFromTarget = await getMessageFromTarget(targetMessageStart);
114 const messageFromDebugger = await getMessageFromDebugger(debuggerMessageStart);
115
116 assert.deepStrictEqual(messageFromTarget, targetMessageStart);
117 assert.deepStrictEqual(messageFromDebugger, debuggerMessageStart);
118 });
119 }
120
121 suite(`${rnHandler.constructor.name}`, () => {
122 suiteSetup(async () => {
123 rnHandler = new RnCDPMessageHandler();
124 Object.assign(proxy, { CDPMessageHandler: rnHandler });
125 });
126
127 deliveryTest(rnHandler);
128
129 test(`Message from target with method '${CDP_API_NAMES.DEBUGGER_PAUSED}' in first time should transorm reason to 'Break on start'`, async () => {
130 const targetMessagePaused = {
131 method: CDP_API_NAMES.DEBUGGER_PAUSED,
132 params: { reason: "other" },
133 };
134
135 const messageFromTarget = await getMessageFromTarget(targetMessagePaused);
136 targetMessagePaused.params.reason = "Break on start";
137
138 assert.deepStrictEqual(messageFromTarget, targetMessagePaused);
139 });
140 });
141
142 suite(`${directHandler.constructor.name}`, () => {
143 suiteSetup(async () => {
144 directHandler = new HermesCDPMessageHandler();
145 Object.assign(proxy, { CDPMessageHandler: directHandler });
146 });
147
148 deliveryTest(directHandler);
149
150 test(`Message from target with method '${CDP_API_NAMES.DEBUGGER_PAUSED}' should filter callFrames with Hermes Native function name and script id`, async () => {
151 const targetMessagePaused = {
152 method: CDP_API_NAMES.DEBUGGER_PAUSED,
153 params: {
154 reason: "other",
155 callFrames: mockCallFrames,
156 },
157 };
158
159 const messageFromTarget = await getMessageFromTarget(targetMessagePaused);
160 const filteredCallFrames = mockCallFrames.filter(
161 (callFrame: any) =>
162 callFrame.functionName !== HERMES_NATIVE_FUNCTION_NAME &&
163 callFrame.location.scriptId !== HERMES_NATIVE_FUNCTION_SCRIPT_ID,
164 );
165 targetMessagePaused.params.callFrames = filteredCallFrames;
166
167 assert.deepStrictEqual(messageFromTarget, targetMessagePaused);
168 });
169
170 test(`Message from target should add description for function result without description`, async () => {
171 const targetMessage = {
172 method: "Target.test",
173 params: {
174 reason: "test",
175 },
176 result: mockResults,
177 };
178
179 const messageFromTarget = await getMessageFromTarget(targetMessage);
180 targetMessage.result.result.forEach(resultObj => {
181 if (
182 resultObj.value &&
183 resultObj.value.type === "function" &&
184 !resultObj.value.description
185 ) {
186 resultObj.value.description = "function() { … }";
187 }
188 });
189
190 assert.deepStrictEqual(messageFromTarget, targetMessage);
191 });
192
193 test(`Message from debugger with method ${CDP_API_NAMES.DEBUGGER_SET_BREAKPOINT} should delete column number field from params.location`, async () => {
194 const debuggerMessage: any = {
195 method: CDP_API_NAMES.DEBUGGER_SET_BREAKPOINT,
196 params: {
197 reason: "test",
198 location: {
199 columnNumber: 15,
200 rowNumber: 100,
201 },
202 },
203 };
204
205 const messageFromDebugger = await getMessageFromDebugger(debuggerMessage);
206 delete debuggerMessage.params.location.columnNumber;
207
208 assert.deepStrictEqual(messageFromDebugger, debuggerMessage);
209 });
210
211 test(`Message from debugger with method ${CDP_API_NAMES.RUNTIME_CALL_FUNCTION_ON} with ${ARRAY_REQUEST_PHRASE_MARKER} in function declaration should return result based on message id and send back to debugger`, async () => {
212 const debuggerMessage = {
213 id: 1,
214 method: CDP_API_NAMES.RUNTIME_CALL_FUNCTION_ON,
215 params: {
216 objectId: 2,
217 reason: "test",
218 functionDeclaration: [ARRAY_REQUEST_PHRASE_MARKER, "some other"],
219 },
220 };
221 let resultMessage = {
222 result: {
223 result: {
224 objectId: debuggerMessage.params.objectId,
225 },
226 },
227 id: debuggerMessage.id,
228 };
229
230 const messageFromDebugger = await new Promise(resolve => {
231 debugConnection?.send(debuggerMessage);
232
233 debugConnection?.onReply((evt: IProtocolError | IProtocolSuccess) => {
234 resolve(evt);
235 });
236 });
237
238 assert.deepStrictEqual(messageFromDebugger, resultMessage);
239 });
240 });
241 });
242});
243