wrangler 2.0.16 → 2.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/wrangler.js +42 -8
- package/miniflare-dist/index.mjs +1 -0
- package/package.json +65 -63
- package/src/__tests__/configuration.test.ts +11 -7
- package/src/__tests__/helpers/run-in-tmp.ts +22 -23
- package/src/__tests__/https-options.test.ts +51 -18
- package/src/__tests__/index.test.ts +13 -13
- package/src/__tests__/jest.setup.ts +13 -0
- package/src/__tests__/kv.test.ts +33 -2
- package/src/__tests__/metrics.test.ts +415 -0
- package/src/__tests__/pages.test.ts +15 -8
- package/src/__tests__/publish.test.ts +49 -23
- package/src/__tests__/secret.test.ts +84 -78
- package/src/__tests__/tail.test.ts +8 -0
- package/src/__tests__/test-old-node-version.js +31 -0
- package/src/__tests__/user.test.ts +7 -7
- package/src/__tests__/whoami.test.tsx +11 -1
- package/src/api/dev.ts +4 -1
- package/src/cli.ts +1 -1
- package/src/config/config.ts +8 -0
- package/src/config/validation.ts +9 -0
- package/src/config-cache.ts +2 -1
- package/src/dev/local.tsx +31 -25
- package/src/dev/remote.tsx +2 -2
- package/src/dev.tsx +6 -0
- package/src/entry.ts +1 -1
- package/src/{__tests__/helpers/faye-websocket.d.ts → faye-websocket.d.ts} +0 -0
- package/src/global-wrangler-config-path.ts +26 -0
- package/src/https-options.ts +8 -4
- package/src/index.tsx +120 -22
- package/src/kv.ts +23 -1
- package/src/metrics/index.ts +4 -0
- package/src/metrics/metrics-config.ts +222 -0
- package/src/metrics/metrics-dispatcher.ts +93 -0
- package/src/metrics/send-event.ts +80 -0
- package/src/miniflare-cli/index.ts +1 -0
- package/src/package-manager.ts +45 -0
- package/src/pages/build.tsx +2 -0
- package/src/pages/deployments.tsx +2 -0
- package/src/pages/dev.tsx +4 -0
- package/src/pages/projects.tsx +3 -0
- package/src/pages/publish.tsx +3 -0
- package/src/pages/upload.tsx +26 -14
- package/src/publish.ts +28 -15
- package/src/pubsub/pubsub-commands.tsx +43 -0
- package/src/user/user.tsx +29 -20
- package/src/worker-namespace.ts +16 -0
- package/templates/static-asset-facade.js +11 -5
- package/templates/tsconfig.json +2 -2
- package/wrangler-dist/cli.d.ts +298 -0
- package/wrangler-dist/cli.js +2589 -1659
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { mkdirSync } from "node:fs";
|
|
2
|
+
import fetchMock from "jest-fetch-mock";
|
|
3
|
+
import { version as wranglerVersion } from "../../package.json";
|
|
4
|
+
import { purgeConfigCaches, saveToConfigCache } from "../config-cache";
|
|
5
|
+
import { logger } from "../logger";
|
|
6
|
+
import { getMetricsDispatcher, getMetricsConfig } from "../metrics";
|
|
7
|
+
import {
|
|
8
|
+
CURRENT_METRICS_DATE,
|
|
9
|
+
readMetricsConfig,
|
|
10
|
+
USER_ID_CACHE_PATH,
|
|
11
|
+
writeMetricsConfig,
|
|
12
|
+
} from "../metrics/metrics-config";
|
|
13
|
+
import { writeAuthConfigFile } from "../user";
|
|
14
|
+
import { setMockResponse, unsetAllMocks } from "./helpers/mock-cfetch";
|
|
15
|
+
import { mockConsoleMethods } from "./helpers/mock-console";
|
|
16
|
+
import { mockConfirm } from "./helpers/mock-dialogs";
|
|
17
|
+
import { useMockIsTTY } from "./helpers/mock-istty";
|
|
18
|
+
import { runInTempDir } from "./helpers/run-in-tmp";
|
|
19
|
+
|
|
20
|
+
declare const global: { SPARROW_SOURCE_KEY: string | undefined };
|
|
21
|
+
|
|
22
|
+
describe("metrics", () => {
|
|
23
|
+
const ORIGINAL_SPARROW_SOURCE_KEY = global.SPARROW_SOURCE_KEY;
|
|
24
|
+
const std = mockConsoleMethods();
|
|
25
|
+
runInTempDir();
|
|
26
|
+
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
global.SPARROW_SOURCE_KEY = "MOCK_KEY";
|
|
29
|
+
logger.loggerLevel = "debug";
|
|
30
|
+
// Create a node_modules directory to store config-cache files
|
|
31
|
+
mkdirSync("node_modules");
|
|
32
|
+
});
|
|
33
|
+
afterEach(() => {
|
|
34
|
+
global.SPARROW_SOURCE_KEY = ORIGINAL_SPARROW_SOURCE_KEY;
|
|
35
|
+
fetchMock.resetMocks();
|
|
36
|
+
unsetAllMocks();
|
|
37
|
+
purgeConfigCaches();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe("getMetricsDispatcher()", () => {
|
|
41
|
+
const MOCK_DISPATCHER_OPTIONS = {
|
|
42
|
+
// By setting this to true we avoid the `getMetricsConfig()` logic in these tests.
|
|
43
|
+
sendMetrics: true,
|
|
44
|
+
offline: false,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// These tests should never hit the `/user` API endpoint.
|
|
48
|
+
const userRequests = mockUserRequest();
|
|
49
|
+
afterEach(() => {
|
|
50
|
+
expect(userRequests.count).toBe(0);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe("identify()", () => {
|
|
54
|
+
it("should send a request to the default URL", async () => {
|
|
55
|
+
const dispatcher = await getMetricsDispatcher(MOCK_DISPATCHER_OPTIONS);
|
|
56
|
+
fetchMock.mockResponse("");
|
|
57
|
+
await dispatcher.identify({ a: 1, b: 2 });
|
|
58
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
59
|
+
const [url, { body, headers }] = fetchMock.mock.calls[0];
|
|
60
|
+
expect(url).toEqual("https://sparrow.cloudflare.com/api/v1/identify");
|
|
61
|
+
expect(JSON.parse(body)).toEqual(
|
|
62
|
+
expect.objectContaining({
|
|
63
|
+
event: "identify",
|
|
64
|
+
properties: {
|
|
65
|
+
category: "Workers",
|
|
66
|
+
wranglerVersion,
|
|
67
|
+
a: 1,
|
|
68
|
+
b: 2,
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
);
|
|
72
|
+
expect(headers).toEqual(
|
|
73
|
+
expect.objectContaining({
|
|
74
|
+
"Sparrow-Source-Key": "MOCK_KEY",
|
|
75
|
+
})
|
|
76
|
+
);
|
|
77
|
+
expect(std.debug).toMatchInlineSnapshot(
|
|
78
|
+
`"Metrics dispatcher: Posting data {\\"type\\":\\"identify\\",\\"name\\":\\"identify\\",\\"properties\\":{\\"a\\":1,\\"b\\":2}}"`
|
|
79
|
+
);
|
|
80
|
+
expect(std.out).toMatchInlineSnapshot(`""`);
|
|
81
|
+
expect(std.warn).toMatchInlineSnapshot(`""`);
|
|
82
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("should write a debug log if the dispatcher is disabled", async () => {
|
|
86
|
+
const dispatcher = await getMetricsDispatcher({
|
|
87
|
+
...MOCK_DISPATCHER_OPTIONS,
|
|
88
|
+
sendMetrics: false,
|
|
89
|
+
});
|
|
90
|
+
await dispatcher.identify({ a: 1, b: 2 });
|
|
91
|
+
expect(fetchMock).toHaveBeenCalledTimes(0);
|
|
92
|
+
expect(std.debug).toMatchInlineSnapshot(
|
|
93
|
+
`"Metrics dispatcher: Dispatching disabled - would have sent {\\"type\\":\\"identify\\",\\"name\\":\\"identify\\",\\"properties\\":{\\"a\\":1,\\"b\\":2}}."`
|
|
94
|
+
);
|
|
95
|
+
expect(std.out).toMatchInlineSnapshot(`""`);
|
|
96
|
+
expect(std.warn).toMatchInlineSnapshot(`""`);
|
|
97
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("should write a debug log if the request fails", async () => {
|
|
101
|
+
const dispatcher = await getMetricsDispatcher(MOCK_DISPATCHER_OPTIONS);
|
|
102
|
+
fetchMock.mockReject(new Error("BAD REQUEST"));
|
|
103
|
+
await dispatcher.identify({ a: 1, b: 2 });
|
|
104
|
+
expect(std.debug).toMatchInlineSnapshot(`
|
|
105
|
+
"Metrics dispatcher: Posting data {\\"type\\":\\"identify\\",\\"name\\":\\"identify\\",\\"properties\\":{\\"a\\":1,\\"b\\":2}}
|
|
106
|
+
Metrics dispatcher: Failed to send request: BAD REQUEST"
|
|
107
|
+
`);
|
|
108
|
+
expect(std.out).toMatchInlineSnapshot(`""`);
|
|
109
|
+
expect(std.warn).toMatchInlineSnapshot(`""`);
|
|
110
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should write a warning log if no source key has been provided", async () => {
|
|
114
|
+
global.SPARROW_SOURCE_KEY = undefined;
|
|
115
|
+
const dispatcher = await getMetricsDispatcher(MOCK_DISPATCHER_OPTIONS);
|
|
116
|
+
await dispatcher.identify({ a: 1, b: 2 });
|
|
117
|
+
expect(fetchMock).toHaveBeenCalledTimes(0);
|
|
118
|
+
expect(std.debug).toMatchInlineSnapshot(
|
|
119
|
+
`"Metrics dispatcher: Source Key not provided. Be sure to initialize before sending events. { type: 'identify', name: 'identify', properties: { a: 1, b: 2 } }"`
|
|
120
|
+
);
|
|
121
|
+
expect(std.out).toMatchInlineSnapshot(`""`);
|
|
122
|
+
expect(std.warn).toMatchInlineSnapshot(`""`);
|
|
123
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe("sendEvent()", () => {
|
|
128
|
+
it("should send a request to the default URL", async () => {
|
|
129
|
+
const dispatcher = await getMetricsDispatcher(MOCK_DISPATCHER_OPTIONS);
|
|
130
|
+
fetchMock.mockResponse("");
|
|
131
|
+
await dispatcher.sendEvent("some-event", { a: 1, b: 2 });
|
|
132
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
133
|
+
const [url, { body, headers }] = fetchMock.mock.calls[0];
|
|
134
|
+
expect(url).toEqual("https://sparrow.cloudflare.com/api/v1/event");
|
|
135
|
+
expect(JSON.parse(body)).toEqual(
|
|
136
|
+
expect.objectContaining({
|
|
137
|
+
event: "some-event",
|
|
138
|
+
properties: {
|
|
139
|
+
category: "Workers",
|
|
140
|
+
wranglerVersion,
|
|
141
|
+
a: 1,
|
|
142
|
+
b: 2,
|
|
143
|
+
},
|
|
144
|
+
})
|
|
145
|
+
);
|
|
146
|
+
expect(headers).toEqual(
|
|
147
|
+
expect.objectContaining({
|
|
148
|
+
"Sparrow-Source-Key": "MOCK_KEY",
|
|
149
|
+
})
|
|
150
|
+
);
|
|
151
|
+
expect(std.debug).toMatchInlineSnapshot(
|
|
152
|
+
`"Metrics dispatcher: Posting data {\\"type\\":\\"event\\",\\"name\\":\\"some-event\\",\\"properties\\":{\\"a\\":1,\\"b\\":2}}"`
|
|
153
|
+
);
|
|
154
|
+
expect(std.out).toMatchInlineSnapshot(`""`);
|
|
155
|
+
expect(std.warn).toMatchInlineSnapshot(`""`);
|
|
156
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it("should write a debug log if the dispatcher is disabled", async () => {
|
|
160
|
+
const dispatcher = await getMetricsDispatcher({
|
|
161
|
+
...MOCK_DISPATCHER_OPTIONS,
|
|
162
|
+
sendMetrics: false,
|
|
163
|
+
});
|
|
164
|
+
await dispatcher.sendEvent("some-event", { a: 1, b: 2 });
|
|
165
|
+
expect(fetchMock).toHaveBeenCalledTimes(0);
|
|
166
|
+
expect(std.debug).toMatchInlineSnapshot(
|
|
167
|
+
`"Metrics dispatcher: Dispatching disabled - would have sent {\\"type\\":\\"event\\",\\"name\\":\\"some-event\\",\\"properties\\":{\\"a\\":1,\\"b\\":2}}."`
|
|
168
|
+
);
|
|
169
|
+
expect(std.out).toMatchInlineSnapshot(`""`);
|
|
170
|
+
expect(std.warn).toMatchInlineSnapshot(`""`);
|
|
171
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it("should write a debug log if the request fails", async () => {
|
|
175
|
+
const dispatcher = await getMetricsDispatcher(MOCK_DISPATCHER_OPTIONS);
|
|
176
|
+
fetchMock.mockReject(new Error("BAD REQUEST"));
|
|
177
|
+
await dispatcher.sendEvent("some-event", { a: 1, b: 2 });
|
|
178
|
+
expect(std.debug).toMatchInlineSnapshot(`
|
|
179
|
+
"Metrics dispatcher: Posting data {\\"type\\":\\"event\\",\\"name\\":\\"some-event\\",\\"properties\\":{\\"a\\":1,\\"b\\":2}}
|
|
180
|
+
Metrics dispatcher: Failed to send request: BAD REQUEST"
|
|
181
|
+
`);
|
|
182
|
+
expect(std.out).toMatchInlineSnapshot(`""`);
|
|
183
|
+
expect(std.warn).toMatchInlineSnapshot(`""`);
|
|
184
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("should write a warning log if no source key has been provided", async () => {
|
|
188
|
+
global.SPARROW_SOURCE_KEY = undefined;
|
|
189
|
+
const dispatcher = await getMetricsDispatcher(MOCK_DISPATCHER_OPTIONS);
|
|
190
|
+
await dispatcher.sendEvent("some-event", { a: 1, b: 2 });
|
|
191
|
+
expect(fetchMock).toHaveBeenCalledTimes(0);
|
|
192
|
+
expect(std.debug).toMatchInlineSnapshot(
|
|
193
|
+
`"Metrics dispatcher: Source Key not provided. Be sure to initialize before sending events. { type: 'event', name: 'some-event', properties: { a: 1, b: 2 } }"`
|
|
194
|
+
);
|
|
195
|
+
expect(std.out).toMatchInlineSnapshot(`""`);
|
|
196
|
+
expect(std.warn).toMatchInlineSnapshot(`""`);
|
|
197
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
describe("getMetricsConfig()", () => {
|
|
203
|
+
const { setIsTTY } = useMockIsTTY();
|
|
204
|
+
beforeEach(() => {
|
|
205
|
+
// Default the mock TTY to interactive for all these tests.
|
|
206
|
+
setIsTTY(true);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
describe("enabled", () => {
|
|
210
|
+
it("should return the sendMetrics argument for enabled if it is defined", async () => {
|
|
211
|
+
expect(
|
|
212
|
+
await getMetricsConfig({ sendMetrics: false, offline: false })
|
|
213
|
+
).toMatchObject({
|
|
214
|
+
enabled: false,
|
|
215
|
+
});
|
|
216
|
+
expect(
|
|
217
|
+
await getMetricsConfig({ sendMetrics: true, offline: false })
|
|
218
|
+
).toMatchObject({
|
|
219
|
+
enabled: true,
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("should return enabled false if the process is not interactive", async () => {
|
|
224
|
+
setIsTTY(false);
|
|
225
|
+
expect(
|
|
226
|
+
await getMetricsConfig({
|
|
227
|
+
sendMetrics: undefined,
|
|
228
|
+
offline: false,
|
|
229
|
+
})
|
|
230
|
+
).toMatchObject({
|
|
231
|
+
enabled: false,
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it("should return enabled true if the user on this device previously agreed to send metrics", async () => {
|
|
236
|
+
await writeMetricsConfig({
|
|
237
|
+
permission: {
|
|
238
|
+
enabled: true,
|
|
239
|
+
date: new Date(2022, 6, 4),
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
expect(
|
|
243
|
+
await getMetricsConfig({
|
|
244
|
+
sendMetrics: undefined,
|
|
245
|
+
offline: false,
|
|
246
|
+
})
|
|
247
|
+
).toMatchObject({
|
|
248
|
+
enabled: true,
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it("should return enabled false if the user on this device previously refused to send metrics", async () => {
|
|
253
|
+
await writeMetricsConfig({
|
|
254
|
+
permission: {
|
|
255
|
+
enabled: false,
|
|
256
|
+
date: new Date(2022, 6, 4),
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
expect(
|
|
260
|
+
await getMetricsConfig({
|
|
261
|
+
sendMetrics: undefined,
|
|
262
|
+
offline: false,
|
|
263
|
+
})
|
|
264
|
+
).toMatchObject({
|
|
265
|
+
enabled: false,
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it("should accept and store permission granting to send metrics if the user agrees", async () => {
|
|
270
|
+
const checkConfirmations = mockConfirm({
|
|
271
|
+
text: "Would you like to help improve Wrangler by sending usage metrics to Cloudflare?",
|
|
272
|
+
result: true,
|
|
273
|
+
});
|
|
274
|
+
expect(
|
|
275
|
+
await getMetricsConfig({
|
|
276
|
+
sendMetrics: undefined,
|
|
277
|
+
offline: false,
|
|
278
|
+
})
|
|
279
|
+
).toMatchObject({
|
|
280
|
+
enabled: true,
|
|
281
|
+
});
|
|
282
|
+
checkConfirmations();
|
|
283
|
+
expect((await readMetricsConfig()).permission).toMatchObject({
|
|
284
|
+
enabled: true,
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it("should accept and store permission declining to send metrics if the user declines", async () => {
|
|
289
|
+
const checkConfirmations = mockConfirm({
|
|
290
|
+
text: "Would you like to help improve Wrangler by sending usage metrics to Cloudflare?",
|
|
291
|
+
result: false,
|
|
292
|
+
});
|
|
293
|
+
expect(
|
|
294
|
+
await getMetricsConfig({
|
|
295
|
+
sendMetrics: undefined,
|
|
296
|
+
offline: false,
|
|
297
|
+
})
|
|
298
|
+
).toMatchObject({
|
|
299
|
+
enabled: false,
|
|
300
|
+
});
|
|
301
|
+
checkConfirmations();
|
|
302
|
+
expect((await readMetricsConfig()).permission).toMatchObject({
|
|
303
|
+
enabled: false,
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it("should ignore the config if the permission date is older than the current metrics date", async () => {
|
|
308
|
+
const checkConfirmations = mockConfirm({
|
|
309
|
+
text: "Would you like to help improve Wrangler by sending usage metrics to Cloudflare?",
|
|
310
|
+
result: false,
|
|
311
|
+
});
|
|
312
|
+
const OLD_DATE = new Date(2000);
|
|
313
|
+
await writeMetricsConfig({
|
|
314
|
+
permission: { enabled: true, date: OLD_DATE },
|
|
315
|
+
});
|
|
316
|
+
expect(
|
|
317
|
+
await getMetricsConfig({
|
|
318
|
+
sendMetrics: undefined,
|
|
319
|
+
offline: false,
|
|
320
|
+
})
|
|
321
|
+
).toMatchObject({
|
|
322
|
+
enabled: false,
|
|
323
|
+
});
|
|
324
|
+
checkConfirmations();
|
|
325
|
+
const { permission } = await readMetricsConfig();
|
|
326
|
+
expect(permission?.enabled).toBe(false);
|
|
327
|
+
// The date should be updated to today's date
|
|
328
|
+
expect(permission?.date).toEqual(CURRENT_METRICS_DATE);
|
|
329
|
+
|
|
330
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
331
|
+
"Usage metrics tracking has changed since you last granted permission.
|
|
332
|
+
Your choice has been saved in the following file: home/.wrangler/config/metrics.json.
|
|
333
|
+
|
|
334
|
+
You can override the user level setting for a project in \`wrangler.toml\`:
|
|
335
|
+
|
|
336
|
+
- to disable sending metrics for a project: \`send_metrics = false\`
|
|
337
|
+
- to enable sending metrics for a project: \`send_metrics = true\`"
|
|
338
|
+
`);
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
describe("deviceId", () => {
|
|
343
|
+
it("should return a deviceId found in the config file", async () => {
|
|
344
|
+
await writeMetricsConfig({ deviceId: "XXXX-YYYY-ZZZZ" });
|
|
345
|
+
const { deviceId } = await getMetricsConfig({
|
|
346
|
+
sendMetrics: true,
|
|
347
|
+
offline: false,
|
|
348
|
+
});
|
|
349
|
+
expect(deviceId).toEqual("XXXX-YYYY-ZZZZ");
|
|
350
|
+
expect((await readMetricsConfig()).deviceId).toEqual(deviceId);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
it("should create and store a new deviceId if none is found in the config file", async () => {
|
|
354
|
+
await writeMetricsConfig({});
|
|
355
|
+
const { deviceId } = await getMetricsConfig({
|
|
356
|
+
sendMetrics: true,
|
|
357
|
+
offline: false,
|
|
358
|
+
});
|
|
359
|
+
expect(deviceId).toMatch(
|
|
360
|
+
/[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}/
|
|
361
|
+
);
|
|
362
|
+
expect((await readMetricsConfig()).deviceId).toEqual(deviceId);
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
describe("userId", () => {
|
|
367
|
+
const userRequests = mockUserRequest();
|
|
368
|
+
it("should return a userId found in a cache file", async () => {
|
|
369
|
+
await saveToConfigCache(USER_ID_CACHE_PATH, {
|
|
370
|
+
userId: "CACHED_USER_ID",
|
|
371
|
+
});
|
|
372
|
+
const { userId } = await getMetricsConfig({
|
|
373
|
+
sendMetrics: true,
|
|
374
|
+
offline: false,
|
|
375
|
+
});
|
|
376
|
+
expect(userId).toEqual("CACHED_USER_ID");
|
|
377
|
+
expect(userRequests.count).toBe(0);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
it("should fetch the userId from Cloudflare and store it in a cache file", async () => {
|
|
381
|
+
writeAuthConfigFile({ oauth_token: "DUMMY_TOKEN" });
|
|
382
|
+
const { userId } = await getMetricsConfig({
|
|
383
|
+
sendMetrics: true,
|
|
384
|
+
offline: false,
|
|
385
|
+
});
|
|
386
|
+
expect(userId).toEqual("MOCK_USER_ID");
|
|
387
|
+
expect(userRequests.count).toBe(1);
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it("should not fetch the userId from Cloudflare if running in `offline` mode", async () => {
|
|
391
|
+
writeAuthConfigFile({ oauth_token: "DUMMY_TOKEN" });
|
|
392
|
+
const { userId } = await getMetricsConfig({
|
|
393
|
+
sendMetrics: true,
|
|
394
|
+
offline: true,
|
|
395
|
+
});
|
|
396
|
+
expect(userId).toBe(undefined);
|
|
397
|
+
expect(userRequests.count).toBe(0);
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
function mockUserRequest() {
|
|
404
|
+
const requests = { count: 0 };
|
|
405
|
+
beforeEach(() => {
|
|
406
|
+
setMockResponse("/user", () => {
|
|
407
|
+
requests.count++;
|
|
408
|
+
return { id: "MOCK_USER_ID" };
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
afterEach(() => {
|
|
412
|
+
requests.count = 0;
|
|
413
|
+
});
|
|
414
|
+
return requests;
|
|
415
|
+
}
|
|
@@ -45,6 +45,13 @@ describe("pages", () => {
|
|
|
45
45
|
outOfBandTests.forEach((fn) => fn());
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
+
beforeEach(() => {
|
|
49
|
+
// @ts-expect-error we're using a very simple setTimeout mock here
|
|
50
|
+
jest.spyOn(global, "setTimeout").mockImplementation((fn, _period) => {
|
|
51
|
+
setImmediate(fn);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
48
55
|
it("should should display a list of available subcommands, for pages with no subcommand", async () => {
|
|
49
56
|
await runWrangler("pages");
|
|
50
57
|
await endEventLoop();
|
|
@@ -645,8 +652,8 @@ describe("pages", () => {
|
|
|
645
652
|
});
|
|
646
653
|
bodies.push(JSON.parse(init.body as string) as UploadPayloadFile[]);
|
|
647
654
|
}
|
|
648
|
-
//
|
|
649
|
-
expect(bodies.map((b) => b.length)).toEqual([
|
|
655
|
+
// One bucket should end up with 2 files
|
|
656
|
+
expect(bodies.map((b) => b.length).sort()).toEqual([1, 1, 2]);
|
|
650
657
|
// But we don't know the order, so flatten and test without ordering
|
|
651
658
|
expect(bodies.flatMap((b) => b)).toEqual(
|
|
652
659
|
expect.arrayContaining([
|
|
@@ -759,8 +766,8 @@ describe("pages", () => {
|
|
|
759
766
|
});
|
|
760
767
|
bodies.push(JSON.parse(init.body as string) as UploadPayloadFile[]);
|
|
761
768
|
}
|
|
762
|
-
//
|
|
763
|
-
expect(bodies.map((b) => b.length)).toEqual([
|
|
769
|
+
// One bucket should end up with 2 files
|
|
770
|
+
expect(bodies.map((b) => b.length).sort()).toEqual([1, 1, 2]);
|
|
764
771
|
// But we don't know the order, so flatten and test without ordering
|
|
765
772
|
expect(bodies.flatMap((b) => b)).toEqual(
|
|
766
773
|
expect.arrayContaining([
|
|
@@ -874,8 +881,8 @@ describe("pages", () => {
|
|
|
874
881
|
});
|
|
875
882
|
bodies.push(JSON.parse(init.body as string) as UploadPayloadFile[]);
|
|
876
883
|
}
|
|
877
|
-
//
|
|
878
|
-
expect(bodies.map((b) => b.length)).toEqual([
|
|
884
|
+
// One bucket should end up with 2 files
|
|
885
|
+
expect(bodies.map((b) => b.length).sort()).toEqual([1, 1, 2]);
|
|
879
886
|
// But we don't know the order, so flatten and test without ordering
|
|
880
887
|
expect(bodies.flatMap((b) => b)).toEqual(
|
|
881
888
|
expect.arrayContaining([
|
|
@@ -1163,8 +1170,8 @@ describe("pages", () => {
|
|
|
1163
1170
|
});
|
|
1164
1171
|
bodies.push(JSON.parse(init.body as string) as UploadPayloadFile[]);
|
|
1165
1172
|
}
|
|
1166
|
-
//
|
|
1167
|
-
expect(bodies.map((b) => b.length)).toEqual([
|
|
1173
|
+
// One bucket should end up with 2 files
|
|
1174
|
+
expect(bodies.map((b) => b.length).sort()).toEqual([1, 1, 2]);
|
|
1168
1175
|
// But we don't know the order, so flatten and test without ordering
|
|
1169
1176
|
expect(bodies.flatMap((b) => b)).toEqual(
|
|
1170
1177
|
expect.arrayContaining([
|
|
@@ -29,7 +29,7 @@ import type { FormData, File } from "undici";
|
|
|
29
29
|
describe("publish", () => {
|
|
30
30
|
mockAccountId();
|
|
31
31
|
mockApiToken();
|
|
32
|
-
runInTempDir(
|
|
32
|
+
runInTempDir();
|
|
33
33
|
const { setIsTTY } = useMockIsTTY();
|
|
34
34
|
const std = mockConsoleMethods();
|
|
35
35
|
const {
|
|
@@ -51,6 +51,31 @@ describe("publish", () => {
|
|
|
51
51
|
unsetMockFetchKVGetValues();
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
+
describe("output additional script information", () => {
|
|
55
|
+
mockApiToken();
|
|
56
|
+
|
|
57
|
+
it("should print worker information at log level", async () => {
|
|
58
|
+
setIsTTY(false);
|
|
59
|
+
writeWranglerToml();
|
|
60
|
+
writeWorkerSource();
|
|
61
|
+
mockSubDomainRequest();
|
|
62
|
+
mockUploadWorkerRequest({ expectedType: "esm", sendScriptIds: true });
|
|
63
|
+
mockOAuthServerCallback();
|
|
64
|
+
|
|
65
|
+
await runWrangler("publish ./index");
|
|
66
|
+
|
|
67
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
68
|
+
"Total Upload: 0xx KiB / gzip: 0xx KiB
|
|
69
|
+
Worker ID: abc12345
|
|
70
|
+
Worker ETag: etag98765
|
|
71
|
+
Worker PipelineHash: hash9999
|
|
72
|
+
Uploaded test-name (TIMINGS)
|
|
73
|
+
Published test-name (TIMINGS)
|
|
74
|
+
test-name.test-sub-domain.workers.dev"
|
|
75
|
+
`);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
54
79
|
describe("authentication", () => {
|
|
55
80
|
mockApiToken({ apiToken: null });
|
|
56
81
|
beforeEach(() => {
|
|
@@ -97,33 +122,23 @@ describe("publish", () => {
|
|
|
97
122
|
api_token: "some-api-token",
|
|
98
123
|
});
|
|
99
124
|
|
|
100
|
-
const accessTokenRequest = mockGrantAccessToken({ respondWith: "ok" });
|
|
101
|
-
mockGrantAuthorization({ respondWith: "success" });
|
|
102
|
-
|
|
103
125
|
await expect(runWrangler("publish index.js")).resolves.toBeUndefined();
|
|
104
126
|
|
|
105
|
-
expect(accessTokenRequest.actual.url).toEqual(
|
|
106
|
-
accessTokenRequest.expected.url
|
|
107
|
-
);
|
|
108
|
-
|
|
109
127
|
expect(std.out).toMatchInlineSnapshot(`
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
Published test-name (TIMINGS)
|
|
116
|
-
test-name.test-sub-domain.workers.dev"
|
|
117
|
-
`);
|
|
128
|
+
"Total Upload: 0xx KiB / gzip: 0xx KiB
|
|
129
|
+
Uploaded test-name (TIMINGS)
|
|
130
|
+
Published test-name (TIMINGS)
|
|
131
|
+
test-name.test-sub-domain.workers.dev"
|
|
132
|
+
`);
|
|
118
133
|
expect(std.warn).toMatchInlineSnapshot(`
|
|
119
|
-
|
|
134
|
+
"[33m▲ [43;33m[[43;30mWARNING[43;33m][0m [1mIt looks like you have used Wrangler 1's \`config\` command to login with an API token.[0m
|
|
120
135
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
136
|
+
This is no longer supported in the current version of Wrangler.
|
|
137
|
+
If you wish to authenticate via an API token then please set the \`CLOUDFLARE_API_TOKEN\`
|
|
138
|
+
environment variable.
|
|
124
139
|
|
|
125
|
-
|
|
126
|
-
|
|
140
|
+
"
|
|
141
|
+
`);
|
|
127
142
|
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
128
143
|
});
|
|
129
144
|
|
|
@@ -6123,6 +6138,7 @@ function mockUploadWorkerRequest(
|
|
|
6123
6138
|
expectedMigrations?: CfWorkerInit["migrations"];
|
|
6124
6139
|
env?: string;
|
|
6125
6140
|
legacyEnv?: boolean;
|
|
6141
|
+
sendScriptIds?: boolean;
|
|
6126
6142
|
} = {}
|
|
6127
6143
|
) {
|
|
6128
6144
|
const {
|
|
@@ -6137,6 +6153,7 @@ function mockUploadWorkerRequest(
|
|
|
6137
6153
|
env = undefined,
|
|
6138
6154
|
legacyEnv = false,
|
|
6139
6155
|
expectedMigrations,
|
|
6156
|
+
sendScriptIds,
|
|
6140
6157
|
} = options;
|
|
6141
6158
|
setMockResponse(
|
|
6142
6159
|
env && !legacyEnv
|
|
@@ -6185,7 +6202,16 @@ function mockUploadWorkerRequest(
|
|
|
6185
6202
|
expect(await (formBody.get(name) as File).text()).toEqual(content);
|
|
6186
6203
|
}
|
|
6187
6204
|
|
|
6188
|
-
return {
|
|
6205
|
+
return {
|
|
6206
|
+
available_on_subdomain,
|
|
6207
|
+
...(sendScriptIds
|
|
6208
|
+
? {
|
|
6209
|
+
id: "abc12345",
|
|
6210
|
+
etag: "etag98765",
|
|
6211
|
+
pipeline_hash: "hash9999",
|
|
6212
|
+
}
|
|
6213
|
+
: {}),
|
|
6214
|
+
};
|
|
6189
6215
|
}
|
|
6190
6216
|
);
|
|
6191
6217
|
}
|