Files
bun.sh/test/js/node/fs/glob.test.ts

235 lines
7.1 KiB
TypeScript

/**
* @note `fs.glob` et. al. are powered by {@link Bun.Glob}, which is extensively
* tested elsewhere. These tests check API compatibility with Node.js.
*/
import { afterAll, beforeAll, describe, expect, it } from "bun:test";
import { isWindows, tempDirWithFiles } from "harness";
import fs from "node:fs";
let tmp: string;
beforeAll(() => {
tmp = tempDirWithFiles("fs-glob", {
"foo.txt": "foo",
a: {
"bar.txt": "bar",
"baz.js": "baz",
},
"folder.test": {
"file.txt": "content",
"another-folder": {
"some-file.txt": "content",
},
},
});
});
afterAll(() => {
return fs.promises.rmdir(tmp, { recursive: true });
});
describe("fs.glob", () => {
it("has a length of 3", () => {
expect(fs).toHaveProperty("glob");
expect(typeof fs.glob).toEqual("function");
expect(fs.glob).toHaveLength(3);
});
it("is named 'glob'", () => {
expect(fs.glob.name).toEqual("glob");
});
it("when successful, passes paths to the callback", done => {
fs.glob("*.txt", { cwd: tmp }, (err, paths) => {
expect(err).toBeNull();
expect(paths.sort()).toStrictEqual(["foo.txt"]);
done();
});
});
it("can filter out files", done => {
const exclude = (path: string) => path.endsWith(".js");
fs.glob("a/*", { cwd: tmp, exclude }, (err, paths) => {
if (err) done(err);
if (isWindows) {
expect(paths).toStrictEqual(["a\\bar.txt"]);
} else {
expect(paths).toStrictEqual(["a/bar.txt"]);
}
done();
});
});
it("can filter out files (2)", done => {
const exclude = ["**/*.js"];
fs.glob("a/*", { cwd: tmp, exclude }, (err, paths) => {
if (err) done(err);
if (isWindows) {
expect(paths).toStrictEqual(["a\\bar.txt"]);
} else {
expect(paths).toStrictEqual(["a/bar.txt"]);
}
done();
});
});
describe("invalid arguments", () => {
it("throws if no callback is provided", () => {
expect(() => fs.glob("*.txt")).toThrow(TypeError);
expect(() => fs.glob("*.txt", undefined)).toThrow(TypeError);
expect(() => fs.glob("*.txt", { cwd: tmp })).toThrow(TypeError);
expect(() => fs.glob("*.txt", { cwd: tmp }, undefined)).toThrow(TypeError);
});
});
it("matches directories", () => {
const paths = fs.globSync("*.test", { cwd: tmp });
expect(paths).toContain("folder.test");
});
it("supports arrays of patterns", () => {
const expected = isWindows ? ["a\\bar.txt", "a\\baz.js"] : ["a/bar.txt", "a/baz.js"];
expect(fs.globSync(["a/bar.txt", "a/baz.js"], { cwd: tmp })).toStrictEqual(expected);
});
}); // </fs.glob>
describe("fs.globSync", () => {
it("has a length of 2", () => {
expect(fs).toHaveProperty("globSync");
expect(typeof fs.globSync).toBe("function");
expect(fs.globSync).toHaveLength(2);
});
it("is named 'globSync'", () => {
expect(fs.globSync.name).toEqual("globSync");
});
it.each([
["*.txt", ["foo.txt"]],
["a/**", isWindows ? ["a\\bar.txt", "a\\baz.js"] : ["a/bar.txt", "a/baz.js"]],
])("fs.glob(%p, { cwd: /tmp/fs-glob }) === %p", (pattern, expected) => {
expect(fs.globSync(pattern, { cwd: tmp }).sort()).toStrictEqual(expected);
});
describe("when process.cwd() is set", () => {
let oldProcessCwd: () => string;
beforeAll(() => {
oldProcessCwd = process.cwd;
process.cwd = () => tmp;
});
afterAll(() => {
process.cwd = oldProcessCwd;
});
it("respects the new cwd", () => {
expect(fs.globSync("*.txt")).toStrictEqual(["foo.txt"]);
});
});
it("can filter out files", () => {
const exclude = (path: string) => path.endsWith(".js");
const expected = isWindows ? ["a\\bar.txt"] : ["a/bar.txt"];
expect(fs.globSync("a/*", { cwd: tmp, exclude })).toStrictEqual(expected);
});
it("can filter out files (2)", () => {
const exclude = ["**/*.js"];
const expected = isWindows ? ["a\\bar.txt"] : ["a/bar.txt"];
expect(fs.globSync("a/*", { cwd: tmp, exclude })).toStrictEqual(expected);
});
it("works without providing options", () => {
const oldProcessCwd = process.cwd;
try {
process.cwd = () => tmp;
const paths = fs.globSync("*.txt");
expect(paths).toContain("foo.txt");
} finally {
process.cwd = oldProcessCwd;
}
});
it("matches directories", () => {
const paths = fs.globSync("*.test", { cwd: tmp });
expect(paths).toContain("folder.test");
});
it("supports arrays of patterns", () => {
const expected = isWindows ? ["a\\bar.txt", "a\\baz.js"] : ["a/bar.txt", "a/baz.js"];
expect(fs.globSync(["a/bar.txt", "a/baz.js"], { cwd: tmp })).toStrictEqual(expected);
});
}); // </fs.globSync>
describe("fs.promises.glob", () => {
it("has a length of 2", () => {
expect(fs.promises).toHaveProperty("glob");
expect(typeof fs.promises.glob).toBe("function");
expect(fs.promises.glob).toHaveLength(2);
});
it("is named 'glob'", () => {
expect(fs.promises.glob.name).toEqual("glob");
});
it("returns an AsyncIterable over matched paths", async () => {
const iter = fs.promises.glob("*.txt", { cwd: tmp });
// FIXME: .toHaveProperty does not support symbol keys
expect(iter[Symbol.asyncIterator]).toBeDefined();
for await (const path of iter) {
expect(path).toMatch(/\.txt$/);
}
});
it("works without providing options", async () => {
const oldProcessCwd = process.cwd;
try {
process.cwd = () => tmp;
const iter = fs.promises.glob("*.txt");
expect(iter[Symbol.asyncIterator]).toBeDefined();
const paths = [];
for await (const path of iter) {
paths.push(path);
}
expect(paths).toContain("foo.txt");
} finally {
process.cwd = oldProcessCwd;
}
});
it("matches directories", async () => {
const iter = fs.promises.glob("*.test", { cwd: tmp });
expect(iter[Symbol.asyncIterator]).toBeDefined();
let count = 0;
for await (const path of iter) {
expect(path).toBe("folder.test");
count++;
}
expect(count).toBe(1);
});
it("can filter out files", async () => {
const exclude = (path: string) => path.endsWith(".js");
const expected = isWindows ? ["a\\bar.txt"] : ["a/bar.txt"];
expect(Array.fromAsync(fs.promises.glob("a/*", { cwd: tmp, exclude }))).resolves.toStrictEqual(expected);
});
it("can filter out files (2)", async () => {
const exclude = ["**/*.js"];
const expected = isWindows ? ["a\\bar.txt"] : ["a/bar.txt"];
expect(Array.fromAsync(fs.promises.glob("a/*", { cwd: tmp, exclude }))).resolves.toStrictEqual(expected);
const exclude2 = ["folder.test/another-folder"];
const expected2 = isWindows ? ["folder.test\\file.txt"] : ["folder.test/file.txt"];
expect(
Array.fromAsync(fs.promises.glob("folder.test/**/*", { cwd: tmp, exclude: exclude2 })),
).resolves.toStrictEqual(expected2);
});
it("supports arrays of patterns", async () => {
const expected = isWindows ? ["a\\bar.txt", "a\\baz.js"] : ["a/bar.txt", "a/baz.js"];
expect(Array.fromAsync(fs.promises.glob(["a/bar.txt", "a/baz.js"], { cwd: tmp }))).resolves.toStrictEqual(expected);
});
}); // </fs.promises.glob>