mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
235 lines
7.1 KiB
TypeScript
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>
|