Skip to content

Commit 0945a18

Browse files
committed
feat(test-utils): typed json and test name
1 parent e0a001c commit 0945a18

3 files changed

Lines changed: 49 additions & 30 deletions

File tree

.changeset/funny-steaks-bathe.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@bomb.sh/tools": patch
3+
---
4+
5+
Allows strongly typed `.json` files in fixtures

.changeset/pink-hands-admire.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@bomb.sh/tools": patch
3+
---
4+
5+
Use current test name as a prefix for tmpdir in fixture

src/test-utils.ts

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,51 @@ import { mkdtemp, mkdir, writeFile, rm, readFile as fsReadFile } from "node:fs/p
33
import { tmpdir } from "node:os";
44
import { sep } from "node:path";
55
import { fileURLToPath, pathToFileURL } from "node:url";
6-
import { onTestFinished } from "vitest";
6+
import { expect, onTestFinished } from "vitest";
77

88
export interface Fixture {
9-
root: URL;
10-
resolve: (...segments: string[]) => URL;
11-
readFile: (file: PathLike) => Promise<string>;
12-
cleanup: () => Promise<void>;
9+
root: URL;
10+
resolve: (...segments: string[]) => URL;
11+
readFile: (file: PathLike) => Promise<string>;
12+
cleanup: () => Promise<void>;
1313
}
1414

15-
export async function createFixture(files: Record<string, string>): Promise<Fixture> {
16-
const root = new URL(`bsh-`, `file://${tmpdir()}/`);
17-
const path = await mkdtemp(fileURLToPath(root));
18-
const base = pathToFileURL(path + sep);
15+
type FileContent = string | Record<string, unknown> | unknown[];
1916

20-
for (const [name, content] of Object.entries(files)) {
21-
const url = new URL(name, base);
22-
const dir = new URL("./", url);
23-
await mkdir(dir, { recursive: true });
24-
if (name.endsWith(".json") && typeof content !== "string") {
25-
await writeFile(url, JSON.stringify(content, null, 2), "utf8");
26-
} else {
27-
await writeFile(url, content, "utf8");
28-
}
29-
}
17+
export async function createFixture<const T extends Record<string, FileContent>>(files: {
18+
[K in keyof T]: K extends `${string}.json` ? FileContent : string;
19+
}): Promise<Fixture> {
20+
const raw = expect.getState().currentTestName ?? "bsh";
21+
const prefix = raw
22+
.toLowerCase()
23+
.replace(/[^a-z0-9]+/g, "-")
24+
.replace(/^-|-$/g, "");
25+
const root = new URL(`${prefix}-`, `file://${tmpdir()}/`);
26+
const path = await mkdtemp(fileURLToPath(root));
27+
const base = pathToFileURL(path + sep);
3028

31-
const cleanup = () => rm(path, { recursive: true, force: true });
32-
onTestFinished(cleanup);
29+
for (const [name, content] of Object.entries(files as Record<string, FileContent>)) {
30+
const url = new URL(name, base);
31+
const dir = new URL("./", url);
32+
await mkdir(dir, { recursive: true });
33+
if (name.endsWith(".json") && typeof content !== "string") {
34+
await writeFile(url, JSON.stringify(content, null, 2), "utf8");
35+
} else {
36+
await writeFile(url, content as string, "utf8");
37+
}
38+
}
3339

34-
const resolve = (...segments: string[]) => new URL(`./${segments.join("/")}`, base);
35-
const readFile = (file: PathLike) =>
36-
fsReadFile(new URL(`./${file}`, base), { encoding: "utf-8" });
40+
const cleanup = () => rm(path, { recursive: true, force: true });
41+
onTestFinished(cleanup);
3742

38-
return {
39-
root: pathToFileURL(path),
40-
resolve,
41-
readFile,
42-
cleanup,
43-
};
43+
const resolve = (...segments: string[]) => new URL(`./${segments.join("/")}`, base);
44+
const readFile = (file: PathLike) =>
45+
fsReadFile(new URL(`./${file}`, base), { encoding: "utf-8" });
46+
47+
return {
48+
root: pathToFileURL(path),
49+
resolve,
50+
readFile,
51+
cleanup,
52+
};
4453
}

0 commit comments

Comments
 (0)