Skip to content

Commit 26a8c52

Browse files
committed
chore(compas): add cli test setup
- Handles persisted directories in between test runs. Should improve debuggability icm with the `--debug` flag - Supports sending inputs - Collects the resulting stdout to match on. - Feels somewhat overkill to snapshot output + directory state for now. May do that at some point.
1 parent 99ba21e commit 26a8c52

File tree

7 files changed

+658
-10
lines changed

7 files changed

+658
-10
lines changed

packages/compas/src/main/development/state.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,10 @@ export class State {
110110
new ActionsIntegration(this),
111111
new PackageManagerIntegration(this),
112112

113-
// Should be the last integration
113+
// Should be the last integration, since it will
114114
new FileWatcherIntegration(this),
115115
];
116116

117-
// TODO: Package install command
118-
119-
// TODO: package install
120-
121117
// Init and add to state
122118
for (const integration of integrations) {
123119
await integration.init();

packages/compas/src/main/init/compas.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { existsSync } from "node:fs";
22
import { readFile } from "node:fs/promises";
3-
import { exec, spawn } from "@compas/stdlib";
3+
import { environment, exec, spawn } from "@compas/stdlib";
44
import { writeFileChecked } from "../../shared/fs.js";
55
import { logger } from "../../shared/output.js";
66
import { packageManagerDetermine } from "../../shared/package-manager.js";
@@ -84,7 +84,6 @@ async function initCompasInNewProject(env) {
8484
version: "0.0.1",
8585
type: "module",
8686
scripts: {},
87-
keywords: [],
8887
dependencies: {
8988
compas: compasVersion,
9089
},
@@ -136,7 +135,17 @@ coverage
136135
await exec("git init");
137136
await exec("git checkout -b main");
138137
await exec("git add -A");
139-
await exec(`git commit -m "Initialized project with ${env.compasVersion}"`);
138+
139+
if (environment._COMPAS_SKIP_COMMIT_SIGN === "true") {
140+
// Test purposes
141+
await exec(
142+
`git commit -c commit.gpgsign=false -m "Initialized project with ${env.compasVersion}"`,
143+
);
144+
} else {
145+
await exec(
146+
`git commit -m "Initialized project with ${env.compasVersion}"`,
147+
);
148+
}
140149
}
141150

142151
logger.info(`

packages/compas/src/shared/package-manager.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { existsSync } from "node:fs";
2-
import { pathJoin } from "@compas/stdlib";
2+
import { environment, pathJoin } from "@compas/stdlib";
33

44
export const PACKAGE_MANAGER_LOCK_FILES = [
55
"bun.lockb",
@@ -21,7 +21,14 @@ export const PACKAGE_MANAGER_LOCK_FILES = [
2121
* }}
2222
*/
2323
export function packageManagerDetermine(rootDirectory = "") {
24-
if (existsSync(pathJoin(rootDirectory, "bun.lockb"))) {
24+
if (environment._COMPAS_SKIP_PACKAGE_MANAGER === "true") {
25+
return {
26+
name: "_compas_skip_package_manager",
27+
installCommand: "echo '_compas_skip_package_manager_install'",
28+
nodeModulesBinCommand: "echo '_compas_skip_package_manager_bin'",
29+
packageJsonScriptCommand: "echo '_compas_skip_package_manager_script'",
30+
};
31+
} else if (existsSync(pathJoin(rootDirectory, "bun.lockb"))) {
2532
return {
2633
name: "bun",
2734
installCommand: "bun install",

packages/compas/test/cli.test.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { existsSync } from "node:fs";
2+
import { readdir } from "node:fs/promises";
3+
import { mainTestFn, test } from "@compas/cli";
4+
import { pathJoin } from "@compas/stdlib";
5+
import { testCompasCli, testDirectory } from "./utils.js";
6+
7+
mainTestFn(import.meta);
8+
9+
test("compas/cli", (t) => {
10+
t.jobs = 4;
11+
12+
const workingDirectory = testDirectory(t.name);
13+
14+
t.test("does not create a debug file without --debug", async (t) => {
15+
const cwd = workingDirectory("no-debug");
16+
17+
await testCompasCli({
18+
args: ["foo"],
19+
inputs: [],
20+
waitForExit: true,
21+
cwd,
22+
});
23+
24+
t.equal(existsSync(pathJoin(cwd, ".cache/compas")), false);
25+
});
26+
27+
t.test("creates a debug file with --debug", async (t) => {
28+
const cwd = workingDirectory("with-debug");
29+
30+
await testCompasCli({
31+
args: ["foo", "--debug"],
32+
inputs: [],
33+
waitForExit: true,
34+
cwd,
35+
});
36+
37+
t.equal(existsSync(pathJoin(cwd, ".cache/compas")), true);
38+
t.equal(
39+
(await readdir(pathJoin(cwd, ".cache/compas"), {})).some(
40+
(it) => it.startsWith("debug-") && it.endsWith(".txt"),
41+
),
42+
true,
43+
);
44+
});
45+
46+
t.test("package.json is not available", async (t) => {
47+
const cwd = workingDirectory("no-package-json");
48+
49+
const { stdout } = await testCompasCli({
50+
args: [],
51+
inputs: [],
52+
waitForExit: true,
53+
cwd,
54+
});
55+
56+
t.ok(
57+
stdout.includes("Please run 'npx compas@latest init' to install Compas."),
58+
);
59+
});
60+
61+
t.test("unsupported command", async (t) => {
62+
const cwd = workingDirectory("unknown-command");
63+
64+
const { stdout } = await testCompasCli({
65+
args: ["foo"],
66+
inputs: [],
67+
waitForExit: true,
68+
cwd,
69+
});
70+
71+
t.ok(stdout.includes(`Unsupported command. Available commands:`));
72+
});
73+
});
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
import { existsSync } from "node:fs";
2+
import { mkdir, readdir, readFile } from "node:fs/promises";
3+
import { mainTestFn, test } from "@compas/cli";
4+
import { dirnameForModule, pathJoin } from "@compas/stdlib";
5+
import { writeFileChecked } from "../../src/shared/fs.js";
6+
import { testCompasCli, testDirectory } from "../utils.js";
7+
8+
mainTestFn(import.meta);
9+
10+
test("compas/commands/init", (t) => {
11+
t.jobs = 4;
12+
13+
const workingDirectory = testDirectory(t.name);
14+
15+
t.test("exits in CI mode", async (t) => {
16+
const cwd = workingDirectory("no-ci");
17+
18+
const { stdout } = await testCompasCli({
19+
args: ["init"],
20+
inputs: [],
21+
waitForExit: true,
22+
cwd,
23+
env: {
24+
...process.env,
25+
CI: "true",
26+
},
27+
});
28+
29+
t.ok(stdout.includes("'compas init' is not supported in CI."));
30+
});
31+
32+
t.test("new project", async (t) => {
33+
const cwd = workingDirectory("new-project");
34+
35+
const { stdout } = await testCompasCli({
36+
args: ["init"],
37+
inputs: [],
38+
waitForExit: true,
39+
cwd,
40+
});
41+
42+
// Package.json
43+
t.ok(
44+
existsSync(pathJoin(cwd, "package.json")),
45+
"Should create a package.json",
46+
);
47+
t.deepEqual(
48+
JSON.parse(await readFile(pathJoin(cwd, "package.json"), "utf-8")),
49+
{
50+
name: "new-project",
51+
private: true,
52+
version: "0.0.1",
53+
type: "module",
54+
scripts: {},
55+
dependencies: {
56+
compas: JSON.parse(
57+
await readFile(
58+
pathJoin(dirnameForModule(import.meta), "../../package.json"),
59+
"utf-8",
60+
),
61+
).version,
62+
},
63+
},
64+
);
65+
66+
// Package manager
67+
t.ok(stdout.includes("_compas_skip_package_manager_install"));
68+
69+
// Git
70+
t.ok(
71+
existsSync(pathJoin(cwd, ".gitignore")),
72+
".gitignore should've been created",
73+
);
74+
t.ok(existsSync(pathJoin(cwd, ".git")), "Git repo should've been created");
75+
76+
// Output
77+
t.ok(stdout.includes("'npx compas'"));
78+
});
79+
80+
t.test("new project - already .git", async (t) => {
81+
const cwd = workingDirectory("new-project-already-git");
82+
83+
await mkdir(pathJoin(cwd, ".git"));
84+
85+
const { stdout } = await testCompasCli({
86+
args: ["init"],
87+
inputs: [],
88+
waitForExit: true,
89+
cwd,
90+
});
91+
92+
// Package.json
93+
t.ok(
94+
existsSync(pathJoin(cwd, "package.json")),
95+
"Should create a package.json",
96+
);
97+
98+
// Package manager
99+
t.ok(stdout.includes("_compas_skip_package_manager_install"));
100+
101+
// Git
102+
t.ok(
103+
existsSync(pathJoin(cwd, ".gitignore")),
104+
".gitignore should've been created",
105+
);
106+
t.equal(
107+
(await readdir(pathJoin(cwd, ".git"))).length,
108+
0,
109+
".git directory should be empty",
110+
);
111+
112+
// Output
113+
t.ok(stdout.includes("'npx compas'"));
114+
});
115+
116+
t.test("exiting project - no dependencies", async (t) => {
117+
const cwd = workingDirectory("existing-project-no-deps");
118+
119+
await writeFileChecked(pathJoin(cwd, "package.json"), "{}");
120+
121+
const { stdout } = await testCompasCli({
122+
args: ["init"],
123+
inputs: [],
124+
waitForExit: true,
125+
cwd,
126+
});
127+
128+
// Package.json
129+
130+
t.deepEqual(
131+
JSON.parse(await readFile(pathJoin(cwd, "package.json"), "utf-8")),
132+
{
133+
dependencies: {
134+
compas: JSON.parse(
135+
await readFile(
136+
pathJoin(dirnameForModule(import.meta), "../../package.json"),
137+
"utf-8",
138+
),
139+
).version,
140+
},
141+
},
142+
);
143+
144+
// Package manager
145+
t.ok(stdout.includes("Patching package.json"));
146+
t.ok(stdout.includes("_compas_skip_package_manager_install"));
147+
148+
// Output
149+
t.ok(stdout.includes("Ready to roll!"));
150+
});
151+
152+
t.test("exiting project - no update", async (t) => {
153+
const cwd = workingDirectory("existing-project-no-update");
154+
155+
await writeFileChecked(
156+
pathJoin(cwd, "package.json"),
157+
JSON.stringify({
158+
dependencies: {
159+
compas: JSON.parse(
160+
await readFile(
161+
pathJoin(dirnameForModule(import.meta), "../../package.json"),
162+
"utf-8",
163+
),
164+
).version,
165+
},
166+
}),
167+
);
168+
169+
const { stdout } = await testCompasCli({
170+
args: ["init"],
171+
inputs: [],
172+
waitForExit: true,
173+
cwd,
174+
});
175+
176+
// Package.json
177+
t.deepEqual(
178+
JSON.parse(await readFile(pathJoin(cwd, "package.json"), "utf-8")),
179+
{
180+
dependencies: {
181+
compas: JSON.parse(
182+
await readFile(
183+
pathJoin(dirnameForModule(import.meta), "../../package.json"),
184+
"utf-8",
185+
),
186+
).version,
187+
},
188+
},
189+
);
190+
191+
// Package manager
192+
t.ok(
193+
!stdout.includes("_compas_skip_package_manager_install"),
194+
"Package manager did run, but didn't need to",
195+
);
196+
197+
// Output
198+
t.ok(stdout.includes("Already up-to-date!"));
199+
});
200+
201+
t.test("exiting project - update", async (t) => {
202+
const cwd = workingDirectory("existing-project-update");
203+
204+
await writeFileChecked(
205+
pathJoin(cwd, "package.json"),
206+
JSON.stringify({
207+
dependencies: {
208+
compas: "*",
209+
},
210+
}),
211+
);
212+
213+
const { stdout } = await testCompasCli({
214+
args: ["init"],
215+
inputs: [],
216+
waitForExit: true,
217+
cwd,
218+
});
219+
220+
// Package.json
221+
t.deepEqual(
222+
JSON.parse(await readFile(pathJoin(cwd, "package.json"), "utf-8")),
223+
{
224+
dependencies: {
225+
compas: JSON.parse(
226+
await readFile(
227+
pathJoin(dirnameForModule(import.meta), "../../package.json"),
228+
"utf-8",
229+
),
230+
).version,
231+
},
232+
},
233+
);
234+
235+
// Package manager
236+
t.ok(stdout.includes("Patching package.json"));
237+
t.ok(stdout.includes("_compas_skip_package_manager_install"));
238+
239+
// Output
240+
t.ok(stdout.includes("Ready to roll!"));
241+
});
242+
});

0 commit comments

Comments
 (0)