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

133 lines
3.8 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 fs from "node:fs";
import { describe, beforeAll, afterAll, it, expect } from "bun:test";
import { isWindows, tempDirWithFiles } from "harness";
let tmp: string;
beforeAll(() => {
tmp = tempDirWithFiles("fs-glob", {
"foo.txt": "foo",
a: {
"bar.txt": "bar",
"baz.js": "baz",
},
});
});
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();
});
});
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);
});
});
}); // </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);
});
describe("invalid arguments", () => {
// TODO: GlobSet
it("does not support arrays of patterns yet", () => {
expect(() => fs.globSync(["*.txt"])).toThrow(TypeError);
});
});
}); // </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$/);
}
});
}); // </fs.promises.glob>