-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserverUtil.ts
More file actions
236 lines (197 loc) · 7.58 KB
/
serverUtil.ts
File metadata and controls
236 lines (197 loc) · 7.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
import assert from "node:assert";
import type { Server } from "node:http";
import express, { type Request } from "express";
import type { IPlatform } from "./platform";
export type AppMessagePayload = {
message: string;
args?: unknown[];
};
export let server: Server | undefined;
export let updateResponse: CheckForUpdateResponseMock | undefined;
export let testMessageResponse: string | undefined;
export let testMessageCallback: ((requestBody: AppMessagePayload) => void) | undefined;
export let updateCheckCallback: ((request: Request) => void) | undefined;
export let updatePackagePath: string;
export function setupServer(targetPlatform: IPlatform): void {
console.log(`Setting up server at ${targetPlatform.getServerUrl()}`);
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use((_, response, next) => {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Allow-Headers", "origin, content-type, accept, X-CodePush-SDK-Version");
next();
});
app.get("/v0.1/public/codepush/update_check", (request, response) => {
updateCheckCallback?.(request);
response.send(updateResponse);
console.log("Update check called from the app.");
console.log(`Request: ${JSON.stringify(request.query)}`);
console.log(`Response: ${JSON.stringify(updateResponse)}`);
});
app.get("/v0.1/public/codepush/report_status/download", (_, response) => {
console.log("Application downloading the package.");
response.download(updatePackagePath);
});
app.post("/reportTestMessage", (request, response) => {
console.log("Application reported a test message.");
console.log(`Body: ${JSON.stringify(request.body)}`);
if (!testMessageResponse) {
console.log("Sending OK");
response.sendStatus(200);
} else {
console.log(`Sending body: ${testMessageResponse}`);
response.status(200).send(testMessageResponse);
}
testMessageCallback?.(request.body as AppMessagePayload);
});
const serverPortMatch = /:([0-9]+)/.exec(targetPlatform.getServerUrl());
if (!serverPortMatch?.[1]) {
throw new Error(`Unable to determine a server port from URL: ${targetPlatform.getServerUrl()}`);
}
server = app.listen(Number(serverPortMatch[1]));
}
export function cleanupServer(): void {
server?.close();
server = undefined;
}
export function resetServerState(): void {
updateResponse = undefined;
testMessageResponse = undefined;
testMessageCallback = undefined;
updateCheckCallback = undefined;
}
export class CheckForUpdateResponseMock {
public download_url = "";
public is_available = false;
public should_run_binary_version = false;
public package_size = 0;
public update_app_version = false;
public target_binary_range = "";
public is_disabled = false;
public description = "";
public label = "";
public package_hash = "";
public is_mandatory = false;
}
export class UpdateCheckRequestMock {
public deploymentKey = "";
public appVersion = "";
public packageHash = "";
public isCompanion = false;
}
export function createDefaultResponse(): CheckForUpdateResponseMock {
return new CheckForUpdateResponseMock();
}
export function createUpdateResponse(
mandatory = false,
targetPlatform?: IPlatform,
randomHash = true,
): CheckForUpdateResponseMock {
const response = new CheckForUpdateResponseMock();
response.is_available = true;
response.target_binary_range = "1.0.0";
response.download_url = "mock.url/v0.1/public/codepush/report_status/download";
response.is_mandatory = mandatory;
response.label = "mock-update";
response.package_hash = "12345-67890";
response.package_size = 12345;
if (targetPlatform) {
response.download_url = `${targetPlatform.getServerUrl()}/v0.1/public/codepush/report_status/download`;
}
if (randomHash) {
response.package_hash = `randomHash-${Math.floor(Math.random() * 10_000)}`;
}
return response;
}
export function expectTestMessages(expectedMessages: Array<string | AppMessage>): Promise<void> {
return new Promise<void>((resolve, reject) => {
let messageIndex = 0;
let lastRequestBody: AppMessagePayload | null = null;
testMessageCallback = (requestBody) => {
try {
console.log(`Message index: ${messageIndex}`);
if (lastRequestBody !== null && areEqual(requestBody, lastRequestBody)) {
return;
}
const expectedMessage = expectedMessages[messageIndex];
if (typeof expectedMessage === "string") {
assert.equal(requestBody.message, expectedMessage);
} else {
assert(areEqual(requestBody, expectedMessage));
}
lastRequestBody = requestBody;
messageIndex += 1;
if (messageIndex === expectedMessages.length) {
resolve();
}
} catch (error) {
reject(error);
}
};
});
}
export class TestMessage {
public static readonly CHECK_UP_TO_DATE = "CHECK_UP_TO_DATE";
public static readonly CHECK_UPDATE_AVAILABLE = "CHECK_UPDATE_AVAILABLE";
public static readonly CHECK_ERROR = "CHECK_ERROR";
public static readonly DOWNLOAD_SUCCEEDED = "DOWNLOAD_SUCCEEDED";
public static readonly DOWNLOAD_ERROR = "DOWNLOAD_ERROR";
public static readonly UPDATE_INSTALLED = "UPDATE_INSTALLED";
public static readonly INSTALL_ERROR = "INSTALL_ERROR";
public static readonly DEVICE_READY_AFTER_UPDATE = "DEVICE_READY_AFTER_UPDATE";
public static readonly UPDATE_FAILED_PREVIOUSLY = "UPDATE_FAILED_PREVIOUSLY";
public static readonly NOTIFY_APP_READY_SUCCESS = "NOTIFY_APP_READY_SUCCESS";
public static readonly NOTIFY_APP_READY_FAILURE = "NOTIFY_APP_READY_FAILURE";
public static readonly SKIPPED_NOTIFY_APPLICATION_READY = "SKIPPED_NOTIFY_APPLICATION_READY";
public static readonly SYNC_STATUS = "SYNC_STATUS";
public static readonly RESTART_SUCCEEDED = "RESTART_SUCCEEDED";
public static readonly RESTART_FAILED = "RESTART_FAILED";
public static readonly PENDING_PACKAGE = "PENDING_PACKAGE";
public static readonly CURRENT_PACKAGE = "CURRENT_PACKAGE";
public static readonly SYNC_UP_TO_DATE = 0;
public static readonly SYNC_UPDATE_INSTALLED = 1;
public static readonly SYNC_UPDATE_IGNORED = 2;
public static readonly SYNC_ERROR = 3;
public static readonly SYNC_IN_PROGRESS = 4;
public static readonly SYNC_CHECKING_FOR_UPDATE = 5;
public static readonly SYNC_AWAITING_USER_ACTION = 6;
public static readonly SYNC_DOWNLOADING_PACKAGE = 7;
public static readonly SYNC_INSTALLING_UPDATE = 8;
}
export class TestMessageResponse {
public static readonly SKIP_NOTIFY_APPLICATION_READY = "SKIP_NOTIFY_APPLICATION_READY";
}
export class AppMessage {
public constructor(
public readonly message: string,
public readonly args?: unknown[],
) {}
public static fromString(message: string): AppMessage {
return new AppMessage(message);
}
}
export function areEqual(
firstMessage: AppMessagePayload | AppMessage | null | undefined,
secondMessage: AppMessagePayload | AppMessage | null | undefined,
): boolean {
if (firstMessage === secondMessage) {
return true;
}
if (!firstMessage || !secondMessage || firstMessage.message !== secondMessage.message) {
return false;
}
if (firstMessage.args === secondMessage.args) {
return true;
}
if (!firstMessage.args || !secondMessage.args || firstMessage.args.length !== secondMessage.args.length) {
return false;
}
for (let index = 0; index < firstMessage.args.length; index += 1) {
if (firstMessage.args[index] !== secondMessage.args[index]) {
return false;
}
}
return true;
}