diff --git a/package-lock.json b/package-lock.json index b440a5b5d4..75d6f09438 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17156,6 +17156,9 @@ "license": "Apache-2.0", "dependencies": { "outmatch": "^0.7.0" + }, + "devDependencies": { + "memfs": "^3.5.1" } }, "source-code-git/host": { @@ -20334,6 +20337,7 @@ "@inlang-git/fs": { "version": "file:source-code-git/fs", "requires": { + "memfs": "^3.5.1", "outmatch": "^0.7.0" } }, diff --git a/source-code-git/fs/package.json b/source-code-git/fs/package.json index 90739a7cfd..3bfc52811c 100644 --- a/source-code-git/fs/package.json +++ b/source-code-git/fs/package.json @@ -29,5 +29,8 @@ "dependencies": { "outmatch": "^0.7.0" }, - "license": "Apache-2.0" + "license": "Apache-2.0", + "devDependencies": { + "memfs": "^3.5.1" + } } diff --git a/source-code-git/fs/src/test/filesystems.ts b/source-code-git/fs/src/test/filesystems.ts new file mode 100644 index 0000000000..03ad1eb2d8 --- /dev/null +++ b/source-code-git/fs/src/test/filesystems.ts @@ -0,0 +1,26 @@ +// eslint-disable-next-line no-restricted-imports +import * as nodefs from "node:fs/promises" +import { Volume } from "memfs" +import type { NodeishFilesystem } from "../interface.js" +import { createMemoryFs } from "../implementations/memoryFs.js" + +/** + * The filesystems to test every code on. + * + * Use this in your tests like this: + * + * @example + * for (const [name, fs] of Object.entries(filesystems)) { + * describe(name, () => { + * it("should ...", () => { + * fs.writeFile(...) + * }) + * }) + * } + */ +export const filesystems: Record = { + "node:fs/promises": nodefs, + "@inlang-git/memoryFs": createMemoryFs(), + // @ts-expect-error - memfs types are wrong + memfs: new Volume().promises, +} diff --git a/source-code-git/fs/src/utilities/fromJson.test.ts b/source-code-git/fs/src/utilities/fromJson.test.ts index 4d745a25a0..59343464d1 100644 --- a/source-code-git/fs/src/utilities/fromJson.test.ts +++ b/source-code-git/fs/src/utilities/fromJson.test.ts @@ -1,72 +1,90 @@ -import { it, expect } from "vitest" -import { createMemoryFs } from "../implementations/memoryFs.js" +import { it, expect, describe, afterAll } from "vitest" import { fromJson } from "./fromJson.js" import { toJson } from "./toJson.js" +import { filesystems } from "../test/filesystems.js" -it("should be able to import files from JSON", async () => { - const fs = createMemoryFs() - await fromJson({ - fs, - resolveFrom: "/", - json: { - "file1.txt": "Y29udGVudDE=", - "file2.js": "Y29udGVudDI=", - "node_modules/file3.js": "Y29udGVudDM=", - }, - }) - expect(await fs.readFile("/file1.txt", { encoding: "utf-8" })).toEqual("content1") - expect(await fs.readFile("/file2.js", { encoding: "utf-8" })).toEqual("content2") - expect(await fs.readFile("/node_modules/file3.js", { encoding: "utf-8" })).toEqual("content3") -}) +for (const [name, fs] of Object.entries(filesystems)) { + describe(name, async () => { + const rootTempDir = new URL("./__test_fromJson", import.meta.url).pathname -it("should be able to make a roundtrip", async () => { - const fs = createMemoryFs() - await fromJson({ - fs, - resolveFrom: "/", - json: { - "file1.txt": "Y29udGVudDE=", - "file2.js": "Y29udGVudDI=", - "node_modules/file3.js": "Y29udGVudDM=", - }, - }) - const json = await toJson({ fs, matchers: ["**/*"], resolveFrom: "/" }) - const fs2 = createMemoryFs() - await fromJson({ fs: fs2, resolveFrom: "/", json }) - expect(await fs.readFile("/file1.txt", { encoding: "utf-8" })).toEqual( - await fs2.readFile("/file1.txt", { encoding: "utf-8" }), - ) - expect(await fs.readFile("/file2.js", { encoding: "utf-8" })).toEqual( - await fs2.readFile("/file2.js", { encoding: "utf-8" }), - ) - expect(await fs.readFile("/node_modules/file3.js", { encoding: "utf-8" })).toEqual( - await fs2.readFile("/node_modules/file3.js", { encoding: "utf-8" }), - ) -}) + afterAll(async () => { + await fs.rm(rootTempDir, { recursive: true }) + }) -it("should be able to make a binary roundtrip", async () => { - const fs = createMemoryFs() - await fromJson({ - fs, - resolveFrom: "/", - json: { - "file1.txt": "Y29udGVudDE=", - "file2.gif": "R0lGODlhAQABAIAAAP///////yH5BAAAAAAALAAAAAABAAEAAAIBAAA=", - "images/file3.png": - "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAAEElEQVR4nGJgAQAAAP//AwAABgAFV7+r1AAAAABJRU5ErkJggg==", - }, - }) + it("should be able to import files from JSON", async () => { + const tempDir = rootTempDir + "/import" + await fs.mkdir(tempDir, { recursive: true }) + + await fromJson({ + fs, + resolveFrom: tempDir, + json: { + "file1.txt": "Y29udGVudDE=", + "file2.js": "Y29udGVudDI=", + "node_modules/file3.js": "Y29udGVudDM=", + }, + }) + expect(await fs.readFile(tempDir + "/file1.txt", { encoding: "utf-8" })).toEqual("content1") + expect(await fs.readFile(tempDir + "/file2.js", { encoding: "utf-8" })).toEqual("content2") + expect(await fs.readFile(tempDir + "/node_modules/file3.js", { encoding: "utf-8" })).toEqual( + "content3", + ) + }) + + it("should be able to make a roundtrip", async () => { + const tempDir = rootTempDir + "/roundtrip" + const tempDir2 = rootTempDir + "/roundtrip2" - const json = await toJson({ fs, matchers: ["**/*"], resolveFrom: "/" }) - const fs2 = createMemoryFs() - await fromJson({ fs: fs2, resolveFrom: "/", json }) - expect(await fs.readFile("/file1.txt", { encoding: "utf-8" })).toEqual( - await fs2.readFile("/file1.txt", { encoding: "utf-8" }), - ) - expect(await fs.readFile("/file2.gif", { encoding: "binary" })).toEqual( - await fs2.readFile("/file2.gif", { encoding: "binary" }), - ) - expect(await fs.readFile("images/file3.png", { encoding: "binary" })).toEqual( - await fs2.readFile("images/file3.png", { encoding: "binary" }), - ) -}) + await fs.mkdir(tempDir, { recursive: true }) + + await fromJson({ + fs, + resolveFrom: tempDir, + json: { + "file1.txt": "Y29udGVudDE=", + "file2.js": "Y29udGVudDI=", + "node_modules/file3.js": "Y29udGVudDM=", + }, + }) + const json = await toJson({ fs, matchers: ["**/*"], resolveFrom: "/" }) + await fromJson({ fs, resolveFrom: tempDir2, json }) + expect(await fs.readFile(tempDir + "/file1.txt", { encoding: "utf-8" })).toEqual( + await fs.readFile(tempDir2 + "/file1.txt", { encoding: "utf-8" }), + ) + expect(await fs.readFile(tempDir + "/file2.js", { encoding: "utf-8" })).toEqual( + await fs.readFile(tempDir2 + "/file2.js", { encoding: "utf-8" }), + ) + expect(await fs.readFile(tempDir + "/node_modules/file3.js", { encoding: "utf-8" })).toEqual( + await fs.readFile(tempDir2 + "/node_modules/file3.js", { encoding: "utf-8" }), + ) + }) + + it("should be able to make a binary roundtrip", async () => { + const tempDir = rootTempDir + "/roundtrip-binary" + const tempDir2 = rootTempDir + "/roundtrip-binary2" + + await fromJson({ + fs, + resolveFrom: "/", + json: { + "file1.txt": "Y29udGVudDE=", + "file2.gif": "R0lGODlhAQABAIAAAP///////yH5BAAAAAAALAAAAAABAAEAAAIBAAA=", + "images/file3.png": + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAAEElEQVR4nGJgAQAAAP//AwAABgAFV7+r1AAAAABJRU5ErkJggg==", + }, + }) + + const json = await toJson({ fs, matchers: ["**/*"], resolveFrom: tempDir }) + await fromJson({ fs: fs, resolveFrom: tempDir2, json }) + expect(await fs.readFile(tempDir + "/file1.txt", { encoding: "utf-8" })).toEqual( + await fs.readFile(tempDir2 + "/file1.txt", { encoding: "utf-8" }), + ) + expect(await fs.readFile(tempDir + "/file2.gif", { encoding: "binary" })).toEqual( + await fs.readFile(tempDir2 + "/file2.gif", { encoding: "binary" }), + ) + expect(await fs.readFile(tempDir + "/images/file3.png", { encoding: "binary" })).toEqual( + await fs.readFile(tempDir2 + "/images/file3.png", { encoding: "binary" }), + ) + }) + }) +}