microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
4c3948d87069e43f5609cddf6cffa810bdfd251d

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/test/debugger/appWorker.test.ts

232lines · modeblame

3b6023b2Jimmy Thomson10 years ago1// 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 WebSocket from "ws";
6import * as path from "path";
7import * as Q from "q";
8import * as sinon from "sinon";
9
10import * as AppWorker from "../../debugger/appWorker";
11import {ScriptImporter} from "../../debugger/scriptImporter";
12
13suite("appWorker", function() {
14suite("debuggerContext", function() {
5e651f3edigeff10 years ago15const packagerPort = 8081;
3b6023b2Jimmy Thomson10 years ago16
5e651f3edigeff10 years ago17suite("SandboxedAppWorker", function() {
3b6023b2Jimmy Thomson10 years ago18const sourcesStoragePath = path.resolve(__dirname, "assets");
19const startScriptFileName = require.resolve(path.join(sourcesStoragePath, ScriptImporter.DEBUGGER_WORKER_FILE_BASENAME));
20const debugAdapterPort = 9090;
21
22let sandboxedWorker: AppWorker.SandboxedAppWorker;
23let downloadAppScriptStub = sinon.stub();
24let postReplyFunction = sinon.stub();
25let readFileStub = sinon.stub();
26
27setup(function() {
28const nodeFileSystemMock: any = {
cdf34447digeff10 years ago29readFile: readFileStub,
3b6023b2Jimmy Thomson10 years ago30};
31
32const scriptImporterMock: any = {
cdf34447digeff10 years ago33downloadAppScript: downloadAppScriptStub,
3b6023b2Jimmy Thomson10 years ago34};
35
5e651f3edigeff10 years ago36sandboxedWorker = new AppWorker.SandboxedAppWorker(packagerPort, sourcesStoragePath, debugAdapterPort, postReplyFunction, {
3b6023b2Jimmy Thomson10 years ago37nodeFileSystem: nodeFileSystemMock,
cdf34447digeff10 years ago38scriptImporter: scriptImporterMock,
3b6023b2Jimmy Thomson10 years ago39});
40});
41
42teardown(function() {
43// Reset everything
44sandboxedWorker = null;
45
46readFileStub = sinon.stub();
47downloadAppScriptStub = sinon.stub();
48postReplyFunction = sinon.stub();
49});
50
51
52test("should execute scripts correctly and be able to invoke the callback", function() {
53const expectedMessageResult = { success: true };
54const startScriptContents = `var testResponse = ${JSON.stringify(expectedMessageResult)}; postMessage(testResponse);`;
55
56readFileStub.withArgs(startScriptFileName).returns(Q.resolve(startScriptContents));
57
58return sandboxedWorker.start().then(() => {
59assert(postReplyFunction.calledWithExactly(expectedMessageResult));
60});
61});
62
63test("should be able to import scripts", function() {
64const scriptImportPath = "testScript.js";
65const startScriptContents = `importScripts("${scriptImportPath}"); postMessage("postImport");`;
66readFileStub.withArgs(startScriptFileName).returns(Q.resolve(startScriptContents));
67
68const testScriptContents = "postMessage('inImport')";
69const scriptImportDeferred = Q.defer<void>();
70downloadAppScriptStub.withArgs(scriptImportPath, debugAdapterPort).returns(scriptImportDeferred.promise.then(() => {
71return {
72contents: testScriptContents,
cdf34447digeff10 years ago73filepath: scriptImportPath,
3b6023b2Jimmy Thomson10 years ago74};
75}));
76
77return sandboxedWorker.start().then(() => {
78// We have not yet finished importing the script, we should not have posted a response yet
79assert(postReplyFunction.notCalled, "postReplyFuncton called before scripts imported");
80scriptImportDeferred.resolve(void 0);
81return Q.delay(1);
82}).then(() => {
83assert(postReplyFunction.calledWith("postImport"), "postMessage after import not handled");
84assert(postReplyFunction.calledWith("inImport"), "postMessage not registered from within import");
85});
86});
87
88test("should correctly pass postMessage to the loaded script", function() {
89const startScriptContents = `onmessage = postMessage;`;
90readFileStub.withArgs(startScriptFileName).returns(Q.resolve(startScriptContents));
91
92const testMessage = { method: "test", success: true };
93
94return sandboxedWorker.start().then(() => {
95assert(postReplyFunction.notCalled, "postRepyFunction called before message sent");
96sandboxedWorker.postMessage(testMessage);
97return Q.delay(1);
98}).then(() => {
99assert(postReplyFunction.calledWith({ data: testMessage }), "No echo back from app");
100});
101});
102});
103
104suite("MultipleLifetimesAppWorker", function() {
105const sourcesStoragePath = path.resolve(__dirname, "assets");
106const debugAdapterPort = 9090;
107
108let multipleLifetimesWorker: AppWorker.MultipleLifetimesAppWorker;
109let sandboxedAppWorkerStub: Sinon.SinonStub;
110let webSocket: Sinon.SinonStub;
111let sandboxedAppConstructor: Sinon.SinonStub;
112let webSocketConstructor: Sinon.SinonStub;
113
ac841b61Jimmy Thomson10 years ago114let sendMessage: (message: string) => void;
115
3b6023b2Jimmy Thomson10 years ago116let clock: Sinon.SinonFakeTimers;
117
118setup(function() {
119webSocket = sinon.createStubInstance(WebSocket);
120sandboxedAppWorkerStub = sinon.createStubInstance(AppWorker.SandboxedAppWorker);
121
ac841b61Jimmy Thomson10 years ago122const messageInvocation: Sinon.SinonStub = (<any>webSocket).on.withArgs("message");
123sendMessage = (message: string) => messageInvocation.callArgWith(1, message);
124
3b6023b2Jimmy Thomson10 years ago125sandboxedAppConstructor = sinon.stub();
126sandboxedAppConstructor.returns(sandboxedAppWorkerStub);
127webSocketConstructor = sinon.stub();
128webSocketConstructor.returns(webSocket);
129
5e651f3edigeff10 years ago130multipleLifetimesWorker = new AppWorker.MultipleLifetimesAppWorker(packagerPort, sourcesStoragePath, debugAdapterPort, {
3b6023b2Jimmy Thomson10 years ago131sandboxedAppConstructor: sandboxedAppConstructor,
cdf34447digeff10 years ago132webSocketConstructor: webSocketConstructor,
3b6023b2Jimmy Thomson10 years ago133});
134});
135
136teardown(function() {
137// Reset everything
138multipleLifetimesWorker = null;
139webSocket = null;
140sandboxedAppWorkerStub = null;
141sandboxedAppConstructor = null;
142webSocketConstructor = null;
ac841b61Jimmy Thomson10 years ago143sendMessage = null;
3b6023b2Jimmy Thomson10 years ago144
145if (clock) {
146clock.restore();
147clock = null;
148}
149});
150
151test("should construct a websocket connection to the correct endpoint and listen for events", function() {
152return multipleLifetimesWorker.start().then(() => {
153const websocketRegex = new RegExp("ws://[^:]*:[0-9]*/debugger-proxy\\?role=debugger");
154assert(webSocketConstructor.calledWithMatch(websocketRegex), "The web socket was not constructed to the correct url: " + webSocketConstructor.args[0][0]);
155
156const expectedListeners = ["open", "close", "message", "error"];
157expectedListeners.forEach((event) => {
158assert((<any>webSocket).on.calledWithMatch(event), `Missing listener for ${event}`);
159});
160});
161});
162
163test("should attempt to reconnect after disconnecting", function() {
164return multipleLifetimesWorker.start().then(() => {
165// Forget previous invocations
166webSocketConstructor.reset();
167
6e731058Jimmy Thomson10 years ago168clock = sinon.useFakeTimers();
169
3b6023b2Jimmy Thomson10 years ago170const closeInvocation: Sinon.SinonStub = (<any>webSocket).on.withArgs("close");
171closeInvocation.callArg(1);
172
173// Ensure that the retry is 100ms after the disconnection
174clock.tick(99);
175assert(webSocketConstructor.notCalled, "Attempted to reconnect too quickly");
176
177clock.tick(1);
178assert(webSocketConstructor.called);
179});
180});
181
182test("should respond correctly to prepareJSRuntime messages", function() {
183return multipleLifetimesWorker.start().then(() => {
184const messageId = 1;
185const testMessage = JSON.stringify({ method: "prepareJSRuntime", id: messageId });
186const expectedReply = JSON.stringify({ replyID: messageId });
187
188const appWorkerDeferred = Q.defer<void>();
189
190const appWorkerStart: Sinon.SinonStub = (<any>sandboxedAppWorkerStub).start;
191const websocketSend: Sinon.SinonStub = (<any>webSocket).send;
192
193appWorkerStart.returns(appWorkerDeferred.promise);
194
195sendMessage(testMessage);
196
197assert(appWorkerStart.called, "SandboxedAppWorker not started in respones to prepareJSRuntime");
198assert(websocketSend.notCalled, "Response sent prior to configuring sandbox worker");
199
200appWorkerDeferred.resolve(void 0);
201
202return Q.delay(1).then(() => {
203assert(websocketSend.calledWith(expectedReply), "Did not receive the expected response to prepareJSRuntime");
204});
205});
206});
ac841b61Jimmy Thomson10 years ago207
208test("should pass unknown messages to the sandboxedAppWorker", function() {
209return multipleLifetimesWorker.start().then(() => {
210// Start up an app worker
211const prepareJSMessage = JSON.stringify({ method: "prepareJSRuntime", id: 1 });
212const appWorkerStart: Sinon.SinonStub = (<any>sandboxedAppWorkerStub).start;
213appWorkerStart.returns(Q.resolve(void 0));
214
215sendMessage(prepareJSMessage);
216
217// Then attempt to message it
218
219const testMessage = { method: "unknownMethod" };
220const testMessageString = JSON.stringify(testMessage);
221
222const postMessageStub: Sinon.SinonStub = (<any>sandboxedAppWorkerStub).postMessage;
223
224assert(postMessageStub.notCalled, "sandboxedAppWorker.postMessage called prior to any message");
225sendMessage(testMessageString);
226
227assert(postMessageStub.calledWith(testMessage), "message was not passed to sandboxedAppWorker");
228});
229});
3b6023b2Jimmy Thomson10 years ago230});
231});
232});