Skip to content

Commit b0bbf69

Browse files
Support a WRANGLER_C3_COMMAND env var to support C3 integration testing (#3461)
* [wrangler] test: ensure that mocks are cleared between tests * chore: add additional known words to spelling dictionary * [wrangler] test: mock console logs in traverse-module-graph tests This avoids unwanted excess logging output during tests. * [wrangler] test: allow the C3 command to be modified via an environment variable. `WRANGLER_C3_COMMAND` can override the command used by `wrangler init` when delegating to C3. By default this will use `create cloudflare@2`. If you want to test the integration between wrangler and C3 locally, you can do the following: ```sh # Ensure both Wrangler and C3 are built npm run build # Run the command from the Wrangler package directory cd packages/wrangler # Tell Wrangler to use the local version of create-cloudflare WRANGLER_C3_COMMAND="run create-cloudflare" npx wrangler init temp ``` This makes use of the fact we have a monorepo and npm will delegate to the local version of a package if possible. Since the way `wrangler init` is written, it will always use `npm` (or equivalent) to run C3, rather than `npx` (or equivalent). Therefore we have added a `create-cloudflare` script to the Wrangler `package.json` that will work with `npm run create-cloudflare`. But that means that you must run the `npx wrangler init` command from the `wrangler` package directory.
1 parent 03133ee commit b0bbf69

File tree

8 files changed

+124
-20
lines changed

8 files changed

+124
-20
lines changed

.vscode/settings.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@
1212
"execa",
1313
"haikunate",
1414
"haikunator",
15+
"httplogs",
1516
"iarna",
17+
"isolinear",
1618
"keyvalue",
1719
"logfwdr",
1820
"middlewares",
1921
"Miniflare",
22+
"mockpm",
2023
"mrbbot",
2124
"outdir",
2225
"outfile",
@@ -37,7 +40,8 @@
3740
"weakset",
3841
"webassemblymemory",
3942
"websockets",
40-
"xxhash"
43+
"xxhash",
44+
"zjcompt"
4145
],
4246
"cSpell.ignoreWords": [
4347
"TESTTEXTBLOBNAME",

packages/wrangler/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
"check:lint": "eslint .",
5757
"check:type": "tsc",
5858
"clean": "rimraf wrangler-dist miniflare-dist emitted-types",
59+
"create-cloudflare": "create-cloudflare",
5960
"dev": "npm run clean && concurrently -c black,blue --kill-others-on-fail false 'npm run bundle -- --watch' 'npm run check:type -- --watch --preserveWatchOutput'",
6061
"emit-types": "tsc -p tsconfig.emit.json && node -r esbuild-register scripts/emit-types.ts",
6162
"prepublishOnly": "SOURCEMAPS=false npm run build",

packages/wrangler/src/__tests__/init.test.ts

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,70 @@ describe("init", () => {
9191
{ stdio: "inherit" }
9292
);
9393
});
94+
95+
describe("with custom C3 command", () => {
96+
const ORIGINAL_ENV = process.env;
97+
98+
beforeEach(() => {
99+
process.env = {
100+
...ORIGINAL_ENV,
101+
WRANGLER_C3_COMMAND: "run create-cloudflare",
102+
};
103+
});
104+
105+
afterEach(() => {
106+
process.env = ORIGINAL_ENV;
107+
});
108+
109+
test("shows deprecation message and delegates to C3", async () => {
110+
await runWrangler("init");
111+
112+
checkFiles({
113+
items: {
114+
"./src/index.js": false,
115+
"./src/index.ts": false,
116+
"./tsconfig.json": false,
117+
"./package.json": false,
118+
"./wrangler.toml": false,
119+
},
120+
});
121+
122+
expect(std).toMatchInlineSnapshot(`
123+
Object {
124+
"debug": "",
125+
"err": "",
126+
"info": "",
127+
"out": "Running \`mockpm run create-cloudflare\`...",
128+
"warn": "▲ [WARNING] The \`init\` command is no longer supported. Please use \`mockpm run create-cloudflare\` instead.
129+
130+
The \`init\` command will be removed in a future version.
131+
132+
",
133+
}
134+
`);
135+
136+
expect(execa).toHaveBeenCalledWith(
137+
"mockpm",
138+
["run", "create-cloudflare"],
139+
{
140+
stdio: "inherit",
141+
}
142+
);
143+
});
144+
145+
it("if `-y` is used, delegate to c3 with --wrangler-defaults", async () => {
146+
await runWrangler("init -y");
147+
148+
expect(execa).toHaveBeenCalledWith(
149+
"mockpm",
150+
["run", "create-cloudflare", "--", "--wrangler-defaults"],
151+
{ stdio: "inherit" }
152+
);
153+
});
154+
});
94155
});
95156

96-
describe("deprecated behaviour is retained with --no-delegate-c3", () => {
157+
describe("deprecated behavior is retained with --no-delegate-c3", () => {
97158
describe("options", () => {
98159
it("should initialize with no interactive prompts if `--yes` is used", async () => {
99160
await runWrangler("init --yes --no-delegate-c3");
@@ -2787,17 +2848,21 @@ describe("init", () => {
27872848
}
27882849
`);
27892850

2851+
expect(execa).toHaveBeenCalledTimes(1);
27902852
expect(execa).toHaveBeenCalledWith(
27912853
"mockpm",
2792-
["create", "cloudflare@2"],
2854+
[
2855+
"create",
2856+
"cloudflare@2",
2857+
"existing-memory-crystal",
2858+
"--",
2859+
"--type",
2860+
"pre-existing",
2861+
"--existing-script",
2862+
"existing-memory-crystal",
2863+
],
27932864
{ stdio: "inherit" }
27942865
);
2795-
expect(execa).toHaveBeenCalledWith("git", ["--version"]);
2796-
expect(execa).toHaveBeenCalledWith("git", [
2797-
"config",
2798-
"--get",
2799-
"init.defaultBranch",
2800-
]);
28012866
});
28022867

28032868
//TODO: Tests for a case when a worker name doesn't exist - JACOB & CASS

packages/wrangler/src/__tests__/jest.setup.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,8 @@ jest.mock("execa", () => {
213213
}),
214214
};
215215
});
216+
217+
afterEach(() => {
218+
// It is important that we clear mocks between tests to avoid leakage.
219+
jest.clearAllMocks();
220+
});

packages/wrangler/src/__tests__/traverse-module-graph.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { mkdir, writeFile } from "fs/promises";
22
import path from "path";
33
import dedent from "ts-dedent";
44
import traverseModuleGraph from "../traverse-module-graph";
5+
import { mockConsoleMethods } from "./helpers/mock-console";
56
import { runInTempDir } from "./helpers/run-in-tmp";
67
import type { ConfigModuleRuleType } from "../config";
78

@@ -14,6 +15,7 @@ import type { ConfigModuleRuleType } from "../config";
1415

1516
describe("traverse module graph", () => {
1617
runInTempDir();
18+
mockConsoleMethods();
1719

1820
it("should not detect JS without module rules", async () => {
1921
await writeFile(

packages/wrangler/src/environment-variables/factory.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,21 @@ import { logger } from "../logger";
22

33
type VariableNames =
44
| "CLOUDFLARE_ACCOUNT_ID"
5-
| "CLOUDFLARE_API_TOKEN"
5+
| "CLOUDFLARE_API_BASE_URL"
66
| "CLOUDFLARE_API_KEY"
7+
| "CLOUDFLARE_API_TOKEN"
78
| "CLOUDFLARE_EMAIL"
8-
| "WRANGLER_SEND_METRICS"
9-
| "CLOUDFLARE_API_BASE_URL"
10-
| "WRANGLER_LOG"
9+
| "NO_CONSTELLATION_WARNING"
1110
| "WRANGLER_API_ENVIRONMENT"
12-
| "WRANGLER_CLIENT_ID"
1311
| "WRANGLER_AUTH_DOMAIN"
1412
| "WRANGLER_AUTH_URL"
15-
| "WRANGLER_TOKEN_URL"
16-
| "WRANGLER_REVOKE_URL"
13+
| "WRANGLER_C3_COMMAND"
1714
| "WRANGLER_CF_AUTHORIZATION_TOKEN"
18-
| "NO_CONSTELLATION_WARNING";
15+
| "WRANGLER_CLIENT_ID"
16+
| "WRANGLER_LOG"
17+
| "WRANGLER_REVOKE_URL"
18+
| "WRANGLER_SEND_METRICS"
19+
| "WRANGLER_TOKEN_URL";
1920

2021
type DeprecatedNames =
2122
| "CF_ACCOUNT_ID"

packages/wrangler/src/environment-variables/misc-variables.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,31 @@
11
import { getEnvironmentVariableFactory } from "./factory";
22

3+
/**
4+
* `WRANGLER_C3_COMMAND` can override the command used by `wrangler init` when delegating to C3.
5+
*
6+
* By default this will use `create cloudflare@2`.
7+
* If you want to test the integration between wrangler and C3 locally, you can do the following:
8+
*
9+
* ```sh
10+
* # Ensure both Wrangler and C3 are built
11+
* npm run build
12+
* # Run the command from the Wrangler package directory
13+
* cd packages/wrangler
14+
* # Tell Wrangler to use the local version of create-cloudflare
15+
* WRANGLER_C3_COMMAND="run create-cloudflare" npx wrangler init temp
16+
* ```
17+
*
18+
* This makes use of the fact we have a monorepo and npm will delegate to the local
19+
* version of a package if possible.
20+
* Since the way `wrangler init` is written, it will always use `npm` (or equivalent) to run C3, rather than `npx` (or equivalent).
21+
* Therefore we have added a `create-cloudflare` script to the Wrangler `package.json` that will work with `npm run create-cloudflare`.
22+
* But that means that you must run the `npx wrangler init` command from the `wrangler` package directory.
23+
*/
24+
export const getC3CommandFromEnv = getEnvironmentVariableFactory({
25+
variableName: "WRANGLER_C3_COMMAND",
26+
defaultValue: () => "create cloudflare@2",
27+
});
28+
329
/**
430
* `WRANGLER_SEND_METRICS` can override whether we attempt to send metrics information to Sparrow.
531
*/

packages/wrangler/src/init.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { fetchResult } from "./cfetch";
1010
import { fetchDashboardScript } from "./cfetch/internal";
1111
import { readConfig } from "./config";
1212
import { confirm, select } from "./dialogs";
13+
import { getC3CommandFromEnv } from "./environment-variables/misc-variables";
1314
import { initializeGit, getGitVersioon, isInsideGitRepo } from "./git-client";
1415
import { logger } from "./logger";
1516
import { getPackageManager } from "./package-manager";
@@ -202,8 +203,7 @@ export async function initHandler(args: InitArgs) {
202203
}
203204

204205
const c3Arguments = [
205-
"create",
206-
"cloudflare@2",
206+
...getC3CommandFromEnv().split(" "),
207207
fromDashScriptName,
208208
"--",
209209
"--type",
@@ -252,7 +252,7 @@ export async function initHandler(args: InitArgs) {
252252
// if a wrangler.toml file does not exist (C3 expects to scaffold *new* projects)
253253
// and if --from-dash is not set (C3 will run wrangler to communicate with the API)
254254
if (!fromDashScriptName) {
255-
const c3Arguments = ["create", "cloudflare@2"];
255+
const c3Arguments = getC3CommandFromEnv().split(" ");
256256

257257
if (yesFlag) {
258258
c3Arguments.push("--", "--wrangler-defaults");

0 commit comments

Comments
 (0)