wrangler 0.0.0-e64812e → 0.0.0-e8e684c7

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.
Files changed (214) hide show
  1. package/README.md +27 -3
  2. package/bin/wrangler.js +150 -62
  3. package/kv-asset-handler.js +1 -0
  4. package/miniflare-dist/index.mjs +663 -7
  5. package/package.json +173 -152
  6. package/src/__tests__/config-cache-without-cache-dir.test.ts +38 -0
  7. package/src/__tests__/config-cache.test.ts +30 -24
  8. package/src/__tests__/configuration.test.ts +4015 -3363
  9. package/src/__tests__/dev.test.tsx +1290 -952
  10. package/src/__tests__/generate.test.ts +91 -0
  11. package/src/__tests__/guess-worker-format.test.ts +68 -68
  12. package/src/__tests__/helpers/cmd-shim.d.ts +6 -6
  13. package/src/__tests__/helpers/mock-account-id.ts +24 -24
  14. package/src/__tests__/helpers/mock-bin.ts +20 -20
  15. package/src/__tests__/helpers/mock-cfetch.ts +179 -94
  16. package/src/__tests__/helpers/mock-console.ts +49 -39
  17. package/src/__tests__/helpers/mock-dialogs.ts +94 -71
  18. package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -0
  19. package/src/__tests__/helpers/mock-http-server.ts +30 -30
  20. package/src/__tests__/helpers/mock-istty.ts +65 -18
  21. package/src/__tests__/helpers/mock-known-routes.ts +7 -0
  22. package/src/__tests__/helpers/mock-kv.ts +26 -26
  23. package/src/__tests__/helpers/mock-oauth-flow.ts +223 -228
  24. package/src/__tests__/helpers/mock-process.ts +39 -0
  25. package/src/__tests__/helpers/mock-stdin.ts +82 -77
  26. package/src/__tests__/helpers/mock-web-socket.ts +21 -21
  27. package/src/__tests__/helpers/run-in-tmp.ts +27 -28
  28. package/src/__tests__/helpers/run-wrangler.ts +8 -8
  29. package/src/__tests__/helpers/write-worker-source.ts +16 -16
  30. package/src/__tests__/helpers/write-wrangler-toml.ts +9 -9
  31. package/src/__tests__/https-options.test.ts +142 -109
  32. package/src/__tests__/index.test.ts +222 -233
  33. package/src/__tests__/init.test.ts +2139 -1603
  34. package/src/__tests__/jest.setup.ts +114 -34
  35. package/src/__tests__/kv.test.ts +1222 -1032
  36. package/src/__tests__/logger.test.ts +100 -74
  37. package/src/__tests__/metrics.test.ts +450 -0
  38. package/src/__tests__/package-manager.test.ts +303 -303
  39. package/src/__tests__/pages.test.ts +1173 -652
  40. package/src/__tests__/parse.test.ts +252 -252
  41. package/src/__tests__/publish.test.ts +6788 -5301
  42. package/src/__tests__/pubsub.test.ts +367 -0
  43. package/src/__tests__/r2.test.ts +328 -225
  44. package/src/__tests__/route.test.ts +18 -18
  45. package/src/__tests__/secret.test.ts +470 -459
  46. package/src/__tests__/tail.test.ts +676 -564
  47. package/src/__tests__/test-old-node-version.js +31 -0
  48. package/src/__tests__/user.test.ts +136 -112
  49. package/src/__tests__/validate-dev-props.test.ts +56 -0
  50. package/src/__tests__/version.test.ts +35 -0
  51. package/src/__tests__/whoami.test.tsx +267 -83
  52. package/src/__tests__/worker-namespace.test.ts +329 -0
  53. package/src/abort.d.ts +1 -1
  54. package/src/api/dev.ts +93 -0
  55. package/src/api/index.ts +1 -0
  56. package/src/bundle-reporter.tsx +29 -0
  57. package/src/bundle.ts +430 -157
  58. package/src/cfetch/index.ts +80 -80
  59. package/src/cfetch/internal.ts +244 -91
  60. package/src/cli.ts +21 -7
  61. package/src/config/config.ts +224 -195
  62. package/src/config/diagnostics.ts +61 -61
  63. package/src/config/environment.ts +422 -357
  64. package/src/config/index.ts +219 -193
  65. package/src/config/validation-helpers.ts +379 -357
  66. package/src/config/validation.ts +1690 -1367
  67. package/src/config-cache.ts +81 -41
  68. package/src/create-worker-preview.ts +208 -136
  69. package/src/create-worker-upload-form.ts +275 -238
  70. package/src/dev/dev-vars.ts +13 -13
  71. package/src/dev/dev.tsx +477 -351
  72. package/src/dev/local.tsx +426 -295
  73. package/src/dev/remote.tsx +406 -211
  74. package/src/dev/use-esbuild.ts +154 -94
  75. package/src/dev/validate-dev-props.ts +31 -0
  76. package/src/dev-registry.tsx +160 -0
  77. package/src/dev.tsx +696 -0
  78. package/src/dialogs.tsx +97 -97
  79. package/src/dispatch-namespace.ts +206 -0
  80. package/src/durable.ts +87 -87
  81. package/src/entry.ts +234 -228
  82. package/src/environment-variables.ts +23 -23
  83. package/src/errors.ts +6 -6
  84. package/src/faye-websocket.d.ts +6 -0
  85. package/src/generate.ts +131 -0
  86. package/src/git-client.ts +42 -0
  87. package/src/global-wrangler-config-path.ts +26 -0
  88. package/src/https-options.ts +84 -80
  89. package/src/index.tsx +2164 -2768
  90. package/src/init.ts +622 -0
  91. package/src/inspect.ts +678 -593
  92. package/src/intl-polyfill.d.ts +123 -123
  93. package/src/is-ci.ts +14 -0
  94. package/src/is-interactive.ts +12 -0
  95. package/src/kv.ts +299 -277
  96. package/src/logger.ts +46 -39
  97. package/src/metrics/index.ts +5 -0
  98. package/src/metrics/metrics-config.ts +239 -0
  99. package/src/metrics/metrics-dispatcher.ts +96 -0
  100. package/src/metrics/metrics-usage-headers.ts +24 -0
  101. package/src/metrics/send-event.ts +92 -0
  102. package/src/miniflare-cli/assets.ts +554 -0
  103. package/src/miniflare-cli/enum-keys.ts +8 -8
  104. package/src/miniflare-cli/index.ts +198 -32
  105. package/src/miniflare-cli/request-context.ts +18 -18
  106. package/src/module-collection.ts +212 -212
  107. package/src/open-in-browser.ts +4 -6
  108. package/src/package-manager.ts +173 -128
  109. package/src/pages/build.tsx +238 -0
  110. package/src/pages/constants.ts +12 -0
  111. package/src/pages/deployments.tsx +106 -0
  112. package/src/pages/dev.tsx +528 -0
  113. package/src/pages/errors.ts +22 -0
  114. package/src/pages/functions/buildPlugin.ts +109 -0
  115. package/src/pages/functions/buildWorker.ts +155 -0
  116. package/{pages → src/pages}/functions/filepath-routing.test.ts +113 -113
  117. package/src/pages/functions/filepath-routing.ts +189 -0
  118. package/src/pages/functions/identifiers.ts +78 -0
  119. package/src/pages/functions/routes-consolidation.test.ts +250 -0
  120. package/src/pages/functions/routes-consolidation.ts +73 -0
  121. package/src/pages/functions/routes-transformation.test.ts +271 -0
  122. package/src/pages/functions/routes-transformation.ts +122 -0
  123. package/src/pages/functions/routes.ts +151 -0
  124. package/src/pages/functions.tsx +96 -0
  125. package/src/pages/index.tsx +94 -0
  126. package/src/pages/projects.tsx +169 -0
  127. package/src/pages/publish.tsx +391 -0
  128. package/src/pages/types.ts +49 -0
  129. package/src/pages/upload.tsx +413 -0
  130. package/src/pages/utils.ts +12 -0
  131. package/src/parse.ts +209 -125
  132. package/src/paths.ts +6 -6
  133. package/src/preview.ts +31 -0
  134. package/src/proxy.ts +410 -389
  135. package/src/publish.ts +773 -534
  136. package/src/pubsub/index.ts +286 -0
  137. package/src/pubsub/pubsub-commands.tsx +623 -0
  138. package/src/r2.ts +100 -19
  139. package/src/selfsigned.d.ts +23 -23
  140. package/src/sites.tsx +278 -201
  141. package/src/tail/filters.ts +111 -109
  142. package/src/tail/index.ts +230 -217
  143. package/src/tail/printing.ts +86 -46
  144. package/src/update-check.ts +11 -11
  145. package/src/user/choose-account.tsx +69 -0
  146. package/src/user/env-vars.ts +46 -0
  147. package/src/user/generate-auth-url.ts +33 -0
  148. package/src/user/generate-random-state.ts +16 -0
  149. package/src/user/index.ts +3 -0
  150. package/src/user/user.tsx +1191 -0
  151. package/src/whoami.tsx +141 -42
  152. package/src/worker.ts +123 -99
  153. package/src/zones.ts +167 -0
  154. package/templates/checked-fetch.js +17 -0
  155. package/templates/first-party-worker-module-facade.ts +18 -0
  156. package/templates/format-dev-errors.ts +32 -0
  157. package/templates/new-worker-scheduled.js +3 -3
  158. package/templates/new-worker-scheduled.ts +15 -15
  159. package/templates/new-worker.js +3 -3
  160. package/templates/new-worker.ts +15 -15
  161. package/templates/no-op-worker.js +10 -0
  162. package/templates/pages-shim.ts +9 -0
  163. package/templates/pages-template-plugin.ts +167 -0
  164. package/templates/pages-template-worker.ts +172 -0
  165. package/templates/serve-static-assets.ts +63 -0
  166. package/templates/service-bindings-module-facade.js +54 -0
  167. package/templates/service-bindings-sw-facade.js +42 -0
  168. package/templates/tsconfig.json +95 -95
  169. package/wrangler-dist/cli.d.ts +338 -0
  170. package/wrangler-dist/cli.js +95449 -67524
  171. package/pages/functions/buildPlugin.ts +0 -105
  172. package/pages/functions/buildWorker.ts +0 -151
  173. package/pages/functions/filepath-routing.ts +0 -189
  174. package/pages/functions/identifiers.ts +0 -78
  175. package/pages/functions/routes.ts +0 -156
  176. package/pages/functions/template-plugin.ts +0 -147
  177. package/pages/functions/template-worker.ts +0 -143
  178. package/src/__tests__/helpers/faye-websocket.d.ts +0 -6
  179. package/src/pages.tsx +0 -2038
  180. package/src/user.tsx +0 -1203
  181. package/templates/static-asset-facade.js +0 -47
  182. package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
  183. package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
  184. package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
  185. package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
  186. package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
  187. package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
  188. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
  189. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
  190. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
  191. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
  192. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
  193. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
  194. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
  195. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
  196. package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
  197. package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
  198. package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
  199. package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
  200. package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
  201. package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
  202. package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
  203. package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
  204. package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
  205. package/vendor/wrangler-mime/CHANGELOG.md +0 -289
  206. package/vendor/wrangler-mime/LICENSE +0 -21
  207. package/vendor/wrangler-mime/Mime.js +0 -97
  208. package/vendor/wrangler-mime/README.md +0 -187
  209. package/vendor/wrangler-mime/cli.js +0 -46
  210. package/vendor/wrangler-mime/index.js +0 -4
  211. package/vendor/wrangler-mime/lite.js +0 -4
  212. package/vendor/wrangler-mime/package.json +0 -52
  213. package/vendor/wrangler-mime/types/other.js +0 -1
  214. package/vendor/wrangler-mime/types/standard.js +0 -1
@@ -2,64 +2,189 @@ import { render } from "ink-testing-library";
2
2
  import React from "react";
3
3
  import { writeAuthConfigFile } from "../user";
4
4
  import { getUserInfo, WhoAmI } from "../whoami";
5
- import { setMockResponse } from "./helpers/mock-cfetch";
5
+ import {
6
+ createFetchResult,
7
+ setMockRawResponse,
8
+ setMockResponse,
9
+ unsetAllMocks,
10
+ } from "./helpers/mock-cfetch";
6
11
  import { mockConsoleMethods } from "./helpers/mock-console";
7
12
  import { useMockIsTTY } from "./helpers/mock-istty";
8
13
  import { runInTempDir } from "./helpers/run-in-tmp";
9
14
  import type { UserInfo } from "../whoami";
10
15
 
11
16
  describe("getUserInfo()", () => {
12
- runInTempDir({ homedir: "./home" });
13
- const std = mockConsoleMethods();
14
- const { setIsTTY } = useMockIsTTY();
15
-
16
- beforeEach(() => {
17
- setIsTTY(true);
18
- });
19
-
20
- it("should return undefined if there is no config file", async () => {
21
- const userInfo = await getUserInfo();
22
- expect(userInfo).toBeUndefined();
23
- });
24
-
25
- it("should return undefined if there is an empty config file", async () => {
26
- writeAuthConfigFile({});
27
- const userInfo = await getUserInfo();
28
- expect(userInfo).toBeUndefined();
29
- });
30
-
31
- it("should return the user's email and accounts if authenticated via config token", async () => {
32
- writeAuthConfigFile({ oauth_token: "some-oauth-token" });
33
-
34
- setMockResponse("/user", () => {
35
- return { email: "user@example.com" };
36
- });
37
- setMockResponse("/accounts", () => {
38
- return [
39
- { name: "Account One", id: "account-1" },
40
- { name: "Account Two", id: "account-2" },
41
- { name: "Account Three", id: "account-3" },
42
- ];
43
- });
44
-
45
- const userInfo = await getUserInfo();
46
-
47
- expect(userInfo).toEqual({
48
- authType: "OAuth",
49
- apiToken: "some-oauth-token",
50
- email: "user@example.com",
51
- accounts: [
52
- { name: "Account One", id: "account-1" },
53
- { name: "Account Two", id: "account-2" },
54
- { name: "Account Three", id: "account-3" },
55
- ],
56
- });
57
- });
58
-
59
- it("should display a warning message if the config file contains a legacy api_token field", async () => {
60
- writeAuthConfigFile({ api_token: "API_TOKEN" });
61
- await getUserInfo();
62
- expect(std.warn).toMatchInlineSnapshot(`
17
+ const ENV_COPY = process.env;
18
+
19
+ runInTempDir();
20
+ const std = mockConsoleMethods();
21
+ const { setIsTTY } = useMockIsTTY();
22
+
23
+ beforeEach(() => {
24
+ setIsTTY(true);
25
+ });
26
+
27
+ afterEach(() => {
28
+ process.env = ENV_COPY;
29
+ unsetAllMocks();
30
+ });
31
+
32
+ it("should return undefined if there is no config file", async () => {
33
+ const userInfo = await getUserInfo();
34
+ expect(userInfo).toBeUndefined();
35
+ });
36
+
37
+ it("should return undefined if there is an empty config file", async () => {
38
+ writeAuthConfigFile({});
39
+ const userInfo = await getUserInfo();
40
+ expect(userInfo).toBeUndefined();
41
+ });
42
+
43
+ it("should return undefined for email if the user settings API request fails with 9109", async () => {
44
+ process.env = {
45
+ CLOUDFLARE_API_TOKEN: "123456789",
46
+ };
47
+ setMockRawResponse("/user", () =>
48
+ createFetchResult(undefined, false, [
49
+ { code: 9109, message: "Uauthorized to access requested resource" },
50
+ ])
51
+ );
52
+ setMockResponse("/accounts", () => []);
53
+ const userInfo = await getUserInfo();
54
+ expect(userInfo?.email).toBeUndefined();
55
+ });
56
+
57
+ it("should say it's using an API token when one is set", async () => {
58
+ process.env = {
59
+ CLOUDFLARE_API_TOKEN: "123456789",
60
+ };
61
+ setMockResponse("/user", () => {
62
+ return { email: "user@example.com" };
63
+ });
64
+ setMockResponse("/accounts", () => {
65
+ return [
66
+ { name: "Account One", id: "account-1" },
67
+ { name: "Account Two", id: "account-2" },
68
+ { name: "Account Three", id: "account-3" },
69
+ ];
70
+ });
71
+
72
+ const userInfo = await getUserInfo();
73
+ expect(userInfo).toEqual({
74
+ authType: "API Token",
75
+ apiToken: "123456789",
76
+ email: "user@example.com",
77
+ accounts: [
78
+ { name: "Account One", id: "account-1" },
79
+ { name: "Account Two", id: "account-2" },
80
+ { name: "Account Three", id: "account-3" },
81
+ ],
82
+ });
83
+ });
84
+
85
+ it("should say it's using a Global API Key when one is set", async () => {
86
+ process.env = {
87
+ CLOUDFLARE_API_KEY: "123456789",
88
+ CLOUDFLARE_EMAIL: "user@example.com",
89
+ };
90
+ setMockResponse("/accounts", () => {
91
+ return [
92
+ { name: "Account One", id: "account-1" },
93
+ { name: "Account Two", id: "account-2" },
94
+ { name: "Account Three", id: "account-3" },
95
+ ];
96
+ });
97
+
98
+ const userInfo = await getUserInfo();
99
+ expect(userInfo).toEqual({
100
+ authType: "Global API Key",
101
+ apiToken: "123456789",
102
+ email: "user@example.com",
103
+ accounts: [
104
+ { name: "Account One", id: "account-1" },
105
+ { name: "Account Two", id: "account-2" },
106
+ { name: "Account Three", id: "account-3" },
107
+ ],
108
+ });
109
+ });
110
+
111
+ it("should use a Global API Key in preference to an API token", async () => {
112
+ process.env = {
113
+ CLOUDFLARE_API_KEY: "123456789",
114
+ CLOUDFLARE_EMAIL: "user@example.com",
115
+ CLOUDFLARE_API_TOKEN: "123456789",
116
+ };
117
+ setMockResponse("/accounts", () => {
118
+ return [
119
+ { name: "Account One", id: "account-1" },
120
+ { name: "Account Two", id: "account-2" },
121
+ { name: "Account Three", id: "account-3" },
122
+ ];
123
+ });
124
+
125
+ const userInfo = await getUserInfo();
126
+ expect(userInfo).toEqual({
127
+ authType: "Global API Key",
128
+ apiToken: "123456789",
129
+ email: "user@example.com",
130
+ accounts: [
131
+ { name: "Account One", id: "account-1" },
132
+ { name: "Account Two", id: "account-2" },
133
+ { name: "Account Three", id: "account-3" },
134
+ ],
135
+ });
136
+ });
137
+
138
+ it("should return undefined only a Global API Key, but not Email, is set", async () => {
139
+ process.env = {
140
+ CLOUDFLARE_API_KEY: "123456789",
141
+ };
142
+ const userInfo = await getUserInfo();
143
+ expect(userInfo).toEqual(undefined);
144
+ });
145
+
146
+ it("should return the user's email and accounts if authenticated via config token", async () => {
147
+ writeAuthConfigFile({ oauth_token: "some-oauth-token" });
148
+
149
+ setMockResponse("/user", () => {
150
+ return { email: "user@example.com" };
151
+ });
152
+ setMockResponse("/accounts", () => {
153
+ return [
154
+ { name: "Account One", id: "account-1" },
155
+ { name: "Account Two", id: "account-2" },
156
+ { name: "Account Three", id: "account-3" },
157
+ ];
158
+ });
159
+
160
+ const userInfo = await getUserInfo();
161
+
162
+ expect(userInfo).toEqual({
163
+ authType: "OAuth Token",
164
+ apiToken: "some-oauth-token",
165
+ email: "user@example.com",
166
+ accounts: [
167
+ { name: "Account One", id: "account-1" },
168
+ { name: "Account Two", id: "account-2" },
169
+ { name: "Account Three", id: "account-3" },
170
+ ],
171
+ });
172
+ });
173
+
174
+ it("should display a warning message if the config file contains a legacy api_token field", async () => {
175
+ writeAuthConfigFile({ api_token: "API_TOKEN" });
176
+ setMockResponse("/user", () => {
177
+ return { email: "user@example.com" };
178
+ });
179
+ setMockResponse("/accounts", () => {
180
+ return [
181
+ { name: "Account One", id: "account-1" },
182
+ { name: "Account Two", id: "account-2" },
183
+ { name: "Account Three", id: "account-3" },
184
+ ];
185
+ });
186
+ await getUserInfo();
187
+ expect(std.warn).toMatchInlineSnapshot(`
63
188
  "â–² [WARNING] It looks like you have used Wrangler 1's \`config\` command to login with an API token.
64
189
 
65
190
  This is no longer supported in the current version of Wrangler.
@@ -68,38 +193,97 @@ describe("getUserInfo()", () => {
68
193
 
69
194
  "
70
195
  `);
71
- });
196
+ });
72
197
  });
73
198
 
74
199
  describe("WhoAmI component", () => {
75
- it("should return undefined if there is no user", async () => {
76
- const { lastFrame } = render(<WhoAmI user={undefined}></WhoAmI>);
77
-
78
- expect(lastFrame()).toMatchInlineSnapshot(
79
- `"You are not authenticated. Please run \`wrangler login\`."`
80
- );
81
- });
82
-
83
- it("should display the user's email and accounts", async () => {
84
- const user: UserInfo = {
85
- authType: "OAuth",
86
- apiToken: "some-oauth-token",
87
- email: "user@example.com",
88
- accounts: [
89
- { name: "Account One", id: "account-1" },
90
- { name: "Account Two", id: "account-2" },
91
- { name: "Account Three", id: "account-3" },
92
- ],
93
- };
94
-
95
- const { lastFrame } = render(<WhoAmI user={user}></WhoAmI>);
96
-
97
- expect(lastFrame()).toContain(
98
- "You are logged in with an OAuth Token, associated with the email 'user@example.com'!"
99
- );
100
- expect(lastFrame()).toMatch(/Account Name .+ Account ID/);
101
- expect(lastFrame()).toMatch(/Account One .+ account-1/);
102
- expect(lastFrame()).toMatch(/Account Two .+ account-2/);
103
- expect(lastFrame()).toMatch(/Account Three .+ account-3/);
104
- });
200
+ it("should return undefined if there is no user", async () => {
201
+ const { lastFrame } = render(<WhoAmI user={undefined}></WhoAmI>);
202
+
203
+ expect(lastFrame()).toMatchInlineSnapshot(
204
+ `"You are not authenticated. Please run \`wrangler login\`."`
205
+ );
206
+ });
207
+
208
+ it("should display the user's email, accounts and OAuth scopes", async () => {
209
+ const user: UserInfo = {
210
+ authType: "OAuth Token",
211
+ apiToken: "some-oauth-token",
212
+ email: "user@example.com",
213
+ tokenPermissions: ["scope1:read", "scope2:write", "scope3"],
214
+ accounts: [
215
+ { name: "Account One", id: "account-1" },
216
+ { name: "Account Two", id: "account-2" },
217
+ { name: "Account Three", id: "account-3" },
218
+ ],
219
+ };
220
+
221
+ const { lastFrame } = render(<WhoAmI user={user}></WhoAmI>);
222
+
223
+ expect(lastFrame()).toContain(
224
+ "You are logged in with an OAuth Token, associated with the email 'user@example.com'!"
225
+ );
226
+ expect(lastFrame()).toMatch(/Account Name .+ Account ID/);
227
+ expect(lastFrame()).toMatch(/Account One .+ account-1/);
228
+ expect(lastFrame()).toMatch(/Account Two .+ account-2/);
229
+ expect(lastFrame()).toMatch(/Account Three .+ account-3/);
230
+ expect(lastFrame()).toContain(
231
+ "Token Permissions: If scopes are missing, you may need to logout and re-login."
232
+ );
233
+ expect(lastFrame()).toContain("- scope1 (read)");
234
+ expect(lastFrame()).toContain("- scope2 (write)");
235
+ expect(lastFrame()).toContain("- scope3");
236
+ });
237
+
238
+ // For the case where the cache hasn't updated to include the scopes array
239
+ it("should display the user's email and accounts, but no OAuth scopes if none provided", async () => {
240
+ const user: UserInfo = {
241
+ authType: "OAuth Token",
242
+ apiToken: "some-oauth-token",
243
+ email: "user@example.com",
244
+ tokenPermissions: undefined,
245
+ accounts: [
246
+ { name: "Account One", id: "account-1" },
247
+ { name: "Account Two", id: "account-2" },
248
+ { name: "Account Three", id: "account-3" },
249
+ ],
250
+ };
251
+
252
+ const { lastFrame } = render(<WhoAmI user={user}></WhoAmI>);
253
+
254
+ expect(lastFrame()).toContain(
255
+ "You are logged in with an OAuth Token, associated with the email 'user@example.com'!"
256
+ );
257
+ expect(lastFrame()).toMatch(/Account Name .+ Account ID/);
258
+ expect(lastFrame()).toMatch(/Account One .+ account-1/);
259
+ expect(lastFrame()).toMatch(/Account Two .+ account-2/);
260
+ expect(lastFrame()).toMatch(/Account Three .+ account-3/);
261
+ });
262
+
263
+ it("should display the user's email, accounts and link to view token permissions for non-OAuth tokens", async () => {
264
+ const user: UserInfo = {
265
+ authType: "API Token",
266
+ apiToken: "some-api-token",
267
+ email: "user@example.com",
268
+ tokenPermissions: undefined,
269
+ accounts: [
270
+ { name: "Account One", id: "account-1" },
271
+ { name: "Account Two", id: "account-2" },
272
+ { name: "Account Three", id: "account-3" },
273
+ ],
274
+ };
275
+
276
+ const { lastFrame } = render(<WhoAmI user={user}></WhoAmI>);
277
+
278
+ expect(lastFrame()).toContain(
279
+ "You are logged in with an API Token, associated with the email 'user@example.com'!"
280
+ );
281
+ expect(lastFrame()).toMatch(/Account Name .+ Account ID/);
282
+ expect(lastFrame()).toMatch(/Account One .+ account-1/);
283
+ expect(lastFrame()).toMatch(/Account Two .+ account-2/);
284
+ expect(lastFrame()).toMatch(/Account Three .+ account-3/);
285
+ expect(lastFrame()).toContain(
286
+ "To see token permissions visit https://dash.cloudflare.com/profile/api-tokens"
287
+ );
288
+ });
105
289
  });