mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 10:58:56 +00:00
350 lines
10 KiB
TypeScript
350 lines
10 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
|
|
import { tmpdirSync } from "harness";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
let dirc = 0;
|
|
function nextdir() {
|
|
return `test${++dirc}`;
|
|
}
|
|
|
|
// Helper function to create a temporary directory for testing
|
|
function getTmpDir() {
|
|
const tempDir = path.join(
|
|
tmpdirSync("mkdir-test"),
|
|
`bun-fs-mkdir-test-${Date.now()}-${Math.random().toString(16).slice(2)}`,
|
|
);
|
|
|
|
// Create the temp dir if it doesn't exist
|
|
if (!fs.existsSync(tempDir)) {
|
|
fs.mkdirSync(tempDir, { recursive: true });
|
|
}
|
|
|
|
return tempDir;
|
|
}
|
|
|
|
describe("fs.mkdir", () => {
|
|
let tmpdir: string;
|
|
|
|
// Setup a fresh tmpdir before tests
|
|
beforeEach(() => {
|
|
tmpdir = getTmpDir();
|
|
});
|
|
|
|
// Clean up after tests
|
|
afterEach(() => {
|
|
try {
|
|
fs.rmSync(tmpdir, { recursive: true, force: true });
|
|
} catch (err) {
|
|
// Ignore cleanup errors
|
|
}
|
|
});
|
|
|
|
it("creates directory using assigned path", async () => {
|
|
const pathname = path.join(tmpdir, nextdir());
|
|
|
|
await new Promise<void>((resolve, reject) =>
|
|
fs.mkdir(pathname, err => {
|
|
if (err) return reject(err);
|
|
resolve();
|
|
}),
|
|
);
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
});
|
|
|
|
it("creates directory with assigned mode value", async () => {
|
|
const pathname = path.join(tmpdir, nextdir());
|
|
|
|
await new Promise<void>((resolve, reject) =>
|
|
fs.mkdir(pathname, 0o777, err => {
|
|
if (err) return reject(err);
|
|
resolve();
|
|
}),
|
|
);
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
});
|
|
|
|
it("creates directory with mode passed as an options object", async () => {
|
|
const pathname = path.join(tmpdir, nextdir());
|
|
|
|
await new Promise<void>((resolve, reject) =>
|
|
fs.mkdir(pathname, { mode: 0o777 }, err => {
|
|
if (err) return reject(err);
|
|
resolve();
|
|
}),
|
|
);
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
});
|
|
|
|
it("throws for invalid path types", () => {
|
|
[false, 1, {}, [], null, undefined].forEach((invalidPath: any) => {
|
|
expect(() => fs.mkdir(invalidPath, () => {})).toThrow(TypeError);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("fs.mkdirSync", () => {
|
|
let tmpdir: string;
|
|
|
|
beforeEach(() => {
|
|
tmpdir = getTmpDir();
|
|
});
|
|
|
|
afterEach(() => {
|
|
try {
|
|
fs.rmSync(tmpdir, { recursive: true, force: true });
|
|
} catch (err) {
|
|
// Ignore cleanup errors
|
|
}
|
|
});
|
|
|
|
it("creates directory with assigned path", () => {
|
|
const pathname = path.join(tmpdir, nextdir());
|
|
|
|
fs.mkdirSync(pathname);
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
});
|
|
|
|
it("creates directory with mode passed as an options object", () => {
|
|
const pathname = path.join(tmpdir, nextdir());
|
|
|
|
fs.mkdirSync(pathname, { mode: 0o777 });
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
});
|
|
|
|
it("throws for invalid path types", () => {
|
|
[false, 1, {}, [], null, undefined].forEach((invalidPath: any) => {
|
|
expect(() => fs.mkdirSync(invalidPath)).toThrow(TypeError);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("fs.mkdir - recursive", () => {
|
|
let tmpdir: string;
|
|
|
|
beforeEach(() => {
|
|
tmpdir = getTmpDir();
|
|
});
|
|
|
|
afterEach(() => {
|
|
try {
|
|
fs.rmSync(tmpdir, { recursive: true, force: true });
|
|
} catch (err) {
|
|
// Ignore cleanup errors
|
|
}
|
|
});
|
|
|
|
it("creates nested directories when both top-level and sub-folders don't exist", () => {
|
|
const dir1 = nextdir();
|
|
const dir2 = nextdir();
|
|
const pathname = path.join(tmpdir, dir1, dir2);
|
|
|
|
fs.mkdirSync(pathname, { recursive: true });
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
expect(fs.statSync(pathname).isDirectory()).toBe(true);
|
|
});
|
|
|
|
it("doesn't throw when directory already exists with recursive flag", () => {
|
|
const dir1 = nextdir();
|
|
const dir2 = nextdir();
|
|
const pathname = path.join(tmpdir, dir1, dir2);
|
|
|
|
fs.mkdirSync(pathname, { recursive: true });
|
|
expect(() => fs.mkdirSync(pathname, { recursive: true })).not.toThrow();
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
expect(fs.statSync(pathname).isDirectory()).toBe(true);
|
|
});
|
|
|
|
it("throws when path is a file with recursive flag", () => {
|
|
const dir1 = nextdir();
|
|
const dir2 = nextdir();
|
|
const pathname = path.join(tmpdir, dir1, dir2);
|
|
|
|
// Create the parent directory
|
|
fs.mkdirSync(path.dirname(pathname));
|
|
|
|
// Create a file with the same name as the desired directory
|
|
fs.writeFileSync(pathname, "", "utf8");
|
|
|
|
expect(() => fs.mkdirSync(pathname, { recursive: true })).toThrow(Error);
|
|
});
|
|
|
|
it("throws when part of the path is a file with recursive flag", () => {
|
|
const dir1 = nextdir();
|
|
const dir2 = nextdir();
|
|
const filename = path.join(tmpdir, dir1);
|
|
const pathname = path.join(filename, dir2, nextdir());
|
|
|
|
// Need to check if tmpdir exists to avoid EEXIST error
|
|
if (!fs.existsSync(tmpdir)) {
|
|
fs.mkdirSync(tmpdir, { recursive: true });
|
|
}
|
|
|
|
// Create a file with the same name as a directory in the path
|
|
fs.writeFileSync(filename, "", "utf8");
|
|
|
|
expect(() => fs.mkdirSync(pathname, { recursive: true })).toThrow(Error);
|
|
});
|
|
|
|
it("throws for invalid recursive option types", () => {
|
|
const pathname = path.join(tmpdir, nextdir());
|
|
|
|
["", 1, {}, [], null, Symbol("test"), () => {}].forEach((recursive: any) => {
|
|
expect(() => fs.mkdirSync(pathname, { recursive })).toThrow(TypeError);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("fs.mkdir - return values", () => {
|
|
let tmpdir: string;
|
|
|
|
beforeEach(() => {
|
|
tmpdir = getTmpDir();
|
|
});
|
|
|
|
afterEach(() => {
|
|
try {
|
|
fs.rmSync(tmpdir, { recursive: true, force: true });
|
|
} catch (err) {
|
|
// Ignore cleanup errors
|
|
}
|
|
});
|
|
|
|
it("returns first folder created with recursive when all folders are new", async () => {
|
|
const dir1 = nextdir();
|
|
const dir2 = nextdir();
|
|
const firstPathCreated = path.join(tmpdir, dir1);
|
|
const pathname = path.join(tmpdir, dir1, dir2);
|
|
|
|
const result = await new Promise<string | undefined>((resolve, reject) =>
|
|
fs.mkdir(pathname, { recursive: true }, (err, result) => {
|
|
if (err) return reject(err);
|
|
resolve(result);
|
|
}),
|
|
);
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
expect(fs.statSync(pathname).isDirectory()).toBe(true);
|
|
expect(result).toBe(path.toNamespacedPath(firstPathCreated));
|
|
});
|
|
|
|
it("returns last folder created with recursive when only last folder is new", async () => {
|
|
const dir1 = nextdir();
|
|
const dir2 = nextdir();
|
|
const pathname = path.join(tmpdir, dir1, dir2);
|
|
|
|
// Create the parent directory
|
|
fs.mkdirSync(path.join(tmpdir, dir1));
|
|
|
|
const result = await new Promise<string | undefined>((resolve, reject) =>
|
|
fs.mkdir(pathname, { recursive: true }, (err, result) => {
|
|
if (err) return reject(err);
|
|
resolve(result);
|
|
}),
|
|
);
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
expect(fs.statSync(pathname).isDirectory()).toBe(true);
|
|
expect(result).toBe(path.toNamespacedPath(pathname));
|
|
});
|
|
|
|
it("returns undefined with recursive when no new folders are created", async () => {
|
|
const dir1 = nextdir();
|
|
const dir2 = nextdir();
|
|
const pathname = path.join(tmpdir, dir1, dir2);
|
|
|
|
// Create the directories first
|
|
fs.mkdirSync(pathname, { recursive: true });
|
|
|
|
const result = await new Promise<string | undefined>((resolve, reject) =>
|
|
fs.mkdir(pathname, { recursive: true }, (err, result) => {
|
|
if (err) return reject(err);
|
|
resolve(result);
|
|
}),
|
|
);
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
expect(fs.statSync(pathname).isDirectory()).toBe(true);
|
|
expect(result).toBeUndefined();
|
|
});
|
|
|
|
it("mkdirSync returns first folder created with recursive when all folders are new", () => {
|
|
const dir1 = nextdir();
|
|
const dir2 = nextdir();
|
|
const firstPathCreated = path.join(tmpdir, dir1);
|
|
const pathname = path.join(tmpdir, dir1, dir2);
|
|
|
|
const result = fs.mkdirSync(pathname, { recursive: true });
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
expect(fs.statSync(pathname).isDirectory()).toBe(true);
|
|
expect(result).toBe(path.toNamespacedPath(firstPathCreated));
|
|
});
|
|
|
|
it("mkdirSync returns undefined with recursive when no new folders are created", () => {
|
|
const dir1 = nextdir();
|
|
const dir2 = nextdir();
|
|
const pathname = path.join(tmpdir, dir1, dir2);
|
|
|
|
// Create the directories first
|
|
fs.mkdirSync(pathname, { recursive: true });
|
|
|
|
const result = fs.mkdirSync(pathname, { recursive: true });
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
expect(fs.statSync(pathname).isDirectory()).toBe(true);
|
|
expect(result).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe("fs.promises.mkdir", () => {
|
|
let tmpdir: string;
|
|
|
|
beforeEach(() => {
|
|
tmpdir = getTmpDir();
|
|
});
|
|
|
|
afterEach(() => {
|
|
try {
|
|
fs.rmSync(tmpdir, { recursive: true, force: true });
|
|
} catch (err) {
|
|
// Ignore cleanup errors
|
|
}
|
|
});
|
|
|
|
it("returns first folder created with recursive when all folders are new", async () => {
|
|
const dir1 = nextdir();
|
|
const dir2 = nextdir();
|
|
const firstPathCreated = path.join(tmpdir, dir1);
|
|
const pathname = path.join(tmpdir, dir1, dir2);
|
|
|
|
const result = await fs.promises.mkdir(pathname, { recursive: true });
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
expect(fs.statSync(pathname).isDirectory()).toBe(true);
|
|
expect(result).toBe(path.toNamespacedPath(firstPathCreated));
|
|
});
|
|
|
|
it("returns last folder created with recursive when only last folder is new", async () => {
|
|
const dir1 = nextdir();
|
|
const dir2 = nextdir();
|
|
const pathname = path.join(tmpdir, dir1, dir2);
|
|
|
|
// Create the parent directory
|
|
fs.mkdirSync(path.join(tmpdir, dir1));
|
|
|
|
const result = await fs.promises.mkdir(pathname, { recursive: true });
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
expect(fs.statSync(pathname).isDirectory()).toBe(true);
|
|
expect(result).toBe(path.toNamespacedPath(pathname));
|
|
});
|
|
|
|
it("returns undefined with recursive when no new folders are created", async () => {
|
|
const dir1 = nextdir();
|
|
const dir2 = nextdir();
|
|
const pathname = path.join(tmpdir, dir1, dir2);
|
|
|
|
// Create the directories first
|
|
fs.mkdirSync(pathname, { recursive: true });
|
|
|
|
const result = await fs.promises.mkdir(pathname, { recursive: true });
|
|
expect(fs.existsSync(pathname)).toBe(true);
|
|
expect(fs.statSync(pathname).isDirectory()).toBe(true);
|
|
expect(result).toBeUndefined();
|
|
});
|
|
});
|