Skip to content

Commit 5cec974

Browse files
committed
test: fix unit tests
1 parent f2d1655 commit 5cec974

File tree

5 files changed

+317
-26
lines changed

5 files changed

+317
-26
lines changed

test/controllers/debug-controller.ts

+296
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
import { Yok } from "../../lib/common/yok";
2+
import * as stubs from "../stubs";
3+
import { assert } from "chai";
4+
import { EventEmitter } from "events";
5+
import * as constants from "../../lib/common/constants";
6+
import { CONNECTION_ERROR_EVENT_NAME, DebugCommandErrors, TrackActionNames, DebugTools } from "../../lib/constants";
7+
import { DebugController } from "../../lib/controllers/debug-controller";
8+
import { BuildDataService } from "../../lib/services/build-data-service";
9+
import { DebugDataService } from "../../lib/services/debug-data-service";
10+
import { LiveSyncServiceResolver } from "../../lib/resolvers/livesync-service-resolver";
11+
import { PrepareDataService } from "../../lib/services/prepare-data-service";
12+
import { ProjectDataService } from "../../lib/services/project-data-service";
13+
import { StaticConfig } from "../../lib/config";
14+
import { DevicePlatformsConstants } from "../../lib/common/mobile/device-platforms-constants";
15+
import { LiveSyncProcessDataService } from "../../lib/services/livesync-process-data-service";
16+
17+
const fakeChromeDebugPort = 123;
18+
const fakeChromeDebugUrl = `fakeChromeDebugUrl?experiments=true&ws=localhost:${fakeChromeDebugPort}`;
19+
const defaultDeviceIdentifier = "Nexus5";
20+
21+
class PlatformDebugService extends EventEmitter /* implements IPlatformDebugService */ {
22+
public async debug(debugData: IDebugData, debugOptions: IDebugOptions): Promise<IDebugResultInfo> {
23+
return { debugUrl: fakeChromeDebugUrl };
24+
}
25+
}
26+
27+
interface IDebugTestDeviceInfo {
28+
deviceInfo: {
29+
status: string;
30+
platform: string;
31+
identifier: string;
32+
};
33+
34+
isEmulator: boolean;
35+
}
36+
37+
interface IDebugTestData {
38+
isDeviceFound: boolean;
39+
deviceInformation: IDebugTestDeviceInfo;
40+
isApplicationInstalledOnDevice: boolean;
41+
hostInfo: {
42+
isWindows: boolean;
43+
isDarwin: boolean;
44+
};
45+
}
46+
47+
const getDefaultDeviceInformation = (platform?: string): IDebugTestDeviceInfo => ({
48+
deviceInfo: {
49+
status: constants.CONNECTED_STATUS,
50+
platform: platform || "Android",
51+
identifier: defaultDeviceIdentifier
52+
},
53+
54+
isEmulator: false
55+
});
56+
57+
const getDefaultTestData = (platform?: string): IDebugTestData => ({
58+
isDeviceFound: true,
59+
deviceInformation: getDefaultDeviceInformation(platform),
60+
isApplicationInstalledOnDevice: true,
61+
hostInfo: {
62+
isWindows: false,
63+
isDarwin: true
64+
}
65+
});
66+
67+
describe("debugController", () => {
68+
const getTestInjectorForTestConfiguration = (testData: IDebugTestData): IInjector => {
69+
const testInjector = new Yok();
70+
testInjector.register("devicesService", {
71+
getDeviceByIdentifier: (identifier: string): Mobile.IDevice => {
72+
return testData.isDeviceFound ?
73+
<Mobile.IDevice>{
74+
deviceInfo: testData.deviceInformation.deviceInfo,
75+
76+
applicationManager: {
77+
isApplicationInstalled: async (appIdentifier: string): Promise<boolean> => testData.isApplicationInstalledOnDevice
78+
},
79+
80+
isEmulator: testData.deviceInformation.isEmulator
81+
} : null;
82+
}
83+
});
84+
85+
testInjector.register("androidDeviceDebugService", PlatformDebugService);
86+
87+
testInjector.register("iOSDeviceDebugService", PlatformDebugService);
88+
89+
testInjector.register("mobileHelper", {
90+
isAndroidPlatform: (platform: string) => {
91+
return platform.toLowerCase() === "android";
92+
},
93+
isiOSPlatform: (platform: string) => {
94+
return platform.toLowerCase() === "ios";
95+
}
96+
});
97+
98+
testInjector.register("errors", stubs.ErrorsStub);
99+
100+
testInjector.register("hostInfo", testData.hostInfo);
101+
102+
testInjector.register("logger", stubs.LoggerStub);
103+
104+
testInjector.register("analyticsService", {
105+
trackEventActionInGoogleAnalytics: (data: IEventActionData) => Promise.resolve()
106+
});
107+
108+
testInjector.register("buildDataService", BuildDataService);
109+
testInjector.register("buildController", {});
110+
111+
testInjector.register("debugDataService", DebugDataService);
112+
testInjector.register("deviceInstallAppService", {});
113+
testInjector.register("hmrStatusService", {});
114+
testInjector.register("hooksService", {});
115+
testInjector.register("liveSyncServiceResolver", LiveSyncServiceResolver);
116+
testInjector.register("platformsDataService", {});
117+
testInjector.register("pluginsService", {});
118+
testInjector.register("prepareController", {});
119+
testInjector.register("prepareDataService", PrepareDataService);
120+
testInjector.register("prepareNativePlatformService", {});
121+
testInjector.register("projectDataService", ProjectDataService);
122+
testInjector.register("fs", {});
123+
testInjector.register("staticConfig", StaticConfig);
124+
testInjector.register("devicePlatformsConstants", DevicePlatformsConstants);
125+
testInjector.register("androidResourcesMigrationService", {});
126+
testInjector.register("liveSyncProcessDataService", LiveSyncProcessDataService);
127+
128+
return testInjector;
129+
};
130+
131+
describe("debug", () => {
132+
const getDebugData = (debugOptions?: IDebugOptions): IDebugData => ({
133+
deviceIdentifier: defaultDeviceIdentifier,
134+
applicationIdentifier: "org.nativescript.app1",
135+
projectDir: "/Users/user/app1",
136+
projectName: "app1",
137+
debugOptions: debugOptions || {}
138+
});
139+
140+
describe("rejects the result promise when", () => {
141+
const assertIsRejected = async (testData: IDebugTestData, expectedError: string, userSpecifiedOptions?: IDebugOptions): Promise<void> => {
142+
const testInjector = getTestInjectorForTestConfiguration(testData);
143+
const debugController = testInjector.resolve(DebugController);
144+
145+
const debugData = getDebugData();
146+
await assert.isRejected(debugController.startDebug(debugData, userSpecifiedOptions), expectedError);
147+
};
148+
149+
it("there's no attached device as the specified identifier", async () => {
150+
const testData = getDefaultTestData();
151+
testData.isDeviceFound = false;
152+
153+
await assertIsRejected(testData, "Cannot find device with identifier");
154+
});
155+
156+
it("the device is not trusted", async () => {
157+
const testData = getDefaultTestData();
158+
testData.deviceInformation.deviceInfo.status = constants.UNREACHABLE_STATUS;
159+
160+
await assertIsRejected(testData, "is unreachable. Make sure it is Trusted ");
161+
});
162+
163+
it("the application is not installed on device", async () => {
164+
const testData = getDefaultTestData();
165+
testData.isApplicationInstalledOnDevice = false;
166+
167+
await assertIsRejected(testData, "is not installed on device with identifier");
168+
});
169+
170+
it("device is neither iOS or Android", async () => {
171+
const testData = getDefaultTestData();
172+
testData.deviceInformation.deviceInfo.platform = "WP8";
173+
174+
await assertIsRejected(testData, DebugCommandErrors.UNSUPPORTED_DEVICE_OS_FOR_DEBUGGING);
175+
});
176+
177+
const assertIsRejectedWhenPlatformDebugServiceFails = async (platform: string): Promise<void> => {
178+
const testData = getDefaultTestData();
179+
testData.deviceInformation.deviceInfo.platform = platform;
180+
181+
const testInjector = getTestInjectorForTestConfiguration(testData);
182+
const expectedErrorMessage = "Platform specific error";
183+
const platformDebugService = testInjector.resolve<IDeviceDebugService>(`${platform}DeviceDebugService`);
184+
platformDebugService.debug = async (data: IDebugData, debugOptions: IDebugOptions): Promise<any> => {
185+
throw new Error(expectedErrorMessage);
186+
};
187+
188+
const debugController = testInjector.resolve(DebugController);
189+
190+
const debugData = getDebugData();
191+
await assert.isRejected(debugController.startDebug(debugData, null), expectedErrorMessage);
192+
};
193+
194+
it("androidDeviceDebugService's debug method fails", async () => {
195+
await assertIsRejectedWhenPlatformDebugServiceFails("android");
196+
});
197+
198+
it("iOSDeviceDebugService's debug method fails", async () => {
199+
await assertIsRejectedWhenPlatformDebugServiceFails("iOS");
200+
});
201+
});
202+
203+
describe(`raises ${CONNECTION_ERROR_EVENT_NAME} event`, () => {
204+
_.each(["android", "iOS"], platform => {
205+
it(`when ${platform}DebugService raises ${CONNECTION_ERROR_EVENT_NAME} event`, async () => {
206+
const testData = getDefaultTestData();
207+
testData.deviceInformation.deviceInfo.platform = platform;
208+
209+
const testInjector = getTestInjectorForTestConfiguration(testData);
210+
const debugController = testInjector.resolve(DebugController);
211+
let dataRaisedForConnectionError: any = null;
212+
debugController.on(CONNECTION_ERROR_EVENT_NAME, (data: any) => {
213+
dataRaisedForConnectionError = data;
214+
});
215+
216+
const debugData = getDebugData();
217+
await assert.isFulfilled(debugController.startDebug(debugData, null));
218+
219+
const expectedErrorData = { deviceIdentifier: "deviceId", message: "my message", code: 2048 };
220+
const platformDebugService = testInjector.resolve<IDeviceDebugService>(`${platform}DeviceDebugService`);
221+
platformDebugService.emit(CONNECTION_ERROR_EVENT_NAME, expectedErrorData);
222+
assert.deepEqual(dataRaisedForConnectionError, expectedErrorData);
223+
});
224+
});
225+
});
226+
227+
describe("returns chrome url along with port returned by platform specific debug service", () => {
228+
_.each(["android", "iOS"], platform => {
229+
it(`for ${platform} device`, async () => {
230+
const testData = getDefaultTestData();
231+
testData.deviceInformation.deviceInfo.platform = platform;
232+
233+
const testInjector = getTestInjectorForTestConfiguration(testData);
234+
const debugController = testInjector.resolve(DebugController);
235+
236+
const debugData = getDebugData();
237+
const debugInfo = await debugController.startDebug(debugData, null);
238+
239+
assert.deepEqual(debugInfo, {
240+
url: fakeChromeDebugUrl,
241+
port: fakeChromeDebugPort,
242+
deviceIdentifier: debugData.deviceIdentifier
243+
});
244+
});
245+
});
246+
});
247+
248+
describe("tracks to google analytics", () => {
249+
_.each([
250+
{
251+
testName: "Inspector when --inspector is passed",
252+
debugOptions: { inspector: true },
253+
additionalData: DebugTools.Inspector
254+
},
255+
{
256+
testName: "Chrome when no options are passed",
257+
debugOptions: null,
258+
additionalData: DebugTools.Chrome
259+
},
260+
{
261+
testName: "Chrome when --chrome is passed",
262+
debugOptions: { chrome: true },
263+
additionalData: DebugTools.Chrome
264+
}], testCase => {
265+
266+
it(testCase.testName, async () => {
267+
const testData = getDefaultTestData();
268+
testData.deviceInformation.deviceInfo.platform = "iOS";
269+
270+
const testInjector = getTestInjectorForTestConfiguration(testData);
271+
const analyticsService = testInjector.resolve<IAnalyticsService>("analyticsService");
272+
let dataTrackedToGA: IEventActionData = null;
273+
analyticsService.trackEventActionInGoogleAnalytics = async (data: IEventActionData): Promise<void> => {
274+
dataTrackedToGA = data;
275+
};
276+
277+
const debugController = testInjector.resolve(DebugController);
278+
const debugData = getDebugData(testCase.debugOptions);
279+
await debugController.startDebug(debugData);
280+
const devicesService = testInjector.resolve<Mobile.IDevicesService>("devicesService");
281+
const device = devicesService.getDeviceByIdentifier(testData.deviceInformation.deviceInfo.identifier);
282+
283+
const expectedData = JSON.stringify({
284+
action: TrackActionNames.Debug,
285+
device,
286+
additionalData: testCase.additionalData,
287+
projectDir: debugData.projectDir
288+
}, null, 2);
289+
290+
// Use JSON.stringify as the compared objects link to new instances of different classes.
291+
assert.deepEqual(JSON.stringify(dataTrackedToGA, null, 2), expectedData);
292+
});
293+
});
294+
});
295+
});
296+
});

0 commit comments

Comments
 (0)