import * as fse from "fs-extra"; import { expect } from "chai"; import * as pathUtil from "path"; import path from "./assert_path"; import helper from "./helper"; import * as jetpack from ".."; import { FSJetpack } from "../types"; describe("dir", () => { beforeEach(helper.setCleanTestCwd); afterEach(helper.switchBackToCorrectCwd); describe("creates directory if it doesn't exist", () => { const expectations = () => { path("x").shouldBeDirectory(); }; it("sync", () => { jetpack.dir("x"); expectations(); }); it("async", done => { jetpack.dirAsync("x").then(() => { expectations(); done(); }); }); }); describe("does nothing if directory already exists", () => { const preparations = () => { fse.mkdirsSync("x"); }; const expectations = () => { path("x").shouldBeDirectory(); }; it("sync", () => { preparations(); jetpack.dir("x"); expectations(); }); it("async", done => { preparations(); jetpack.dirAsync("x").then(() => { expectations(); done(); }); }); }); describe("creates nested directories if necessary", () => { const expectations = () => { path("a/b/c").shouldBeDirectory(); }; it("sync", () => { jetpack.dir("a/b/c"); expectations(); }); it("async", done => { jetpack.dirAsync("a/b/c").then(() => { expectations(); done(); }); }); }); describe("handles well two calls racing to create the same directory", () => { const expectations = () => { path("a/b/c").shouldBeDirectory(); }; it("async", done => { let doneCount = 0; const check = () => { doneCount += 1; if (doneCount === 2) { expectations(); done(); } }; jetpack.dirAsync("a/b/c").then(check); jetpack.dirAsync("a/b/c").then(check); }); }); describe("doesn't touch directory content by default", () => { const preparations = () => { fse.mkdirsSync("a/b"); fse.outputFileSync("a/c.txt", "abc"); }; const expectations = () => { path("a/b").shouldBeDirectory(); path("a/c.txt").shouldBeFileWithContent("abc"); }; it("sync", () => { preparations(); jetpack.dir("a"); expectations(); }); it("async", done => { preparations(); jetpack.dirAsync("a").then(() => { expectations(); done(); }); }); }); describe("makes directory empty if that option specified", () => { const preparations = () => { fse.outputFileSync("a/b/file.txt", "abc"); }; const expectations = () => { path("a/b/file.txt").shouldNotExist(); path("a").shouldBeDirectory(); }; it("sync", () => { preparations(); jetpack.dir("a", { empty: true }); expectations(); }); it("async", done => { preparations(); jetpack.dirAsync("a", { empty: true }).then(() => { expectations(); done(); }); }); }); describe("throws if given path is something other than directory", () => { const preparations = () => { fse.outputFileSync("a", "abc"); }; const expectations = (err: any) => { expect(err.message).to.have.string("exists but is not a directory"); }; it("sync", () => { preparations(); try { jetpack.dir("a"); throw new Error("Expected error to be thrown"); } catch (err) { expectations(err); } }); it("async", done => { preparations(); jetpack.dirAsync("a").catch(err => { expectations(err); done(); }); }); }); describe("respects internal CWD of jetpack instance", () => { const expectations = () => { path("a/b").shouldBeDirectory(); }; it("sync", () => { const jetContext = jetpack.cwd("a"); jetContext.dir("b"); expectations(); }); it("async", done => { const jetContext = jetpack.cwd("a"); jetContext.dirAsync("b").then(() => { expectations(); done(); }); }); }); describe("returns jetack instance pointing on this directory", () => { const expectations = (jetpackContext: FSJetpack) => { expect(jetpackContext.cwd()).to.equal(pathUtil.resolve("a")); }; it("sync", () => { expectations(jetpack.dir("a")); }); it("async", done => { jetpack.dirAsync("a").then(jetpackContext => { expectations(jetpackContext); done(); }); }); }); if (process.platform !== "win32") { describe("sets mode to newly created directory (unix only)", () => { const expectations = () => { path("a").shouldHaveMode("511"); }; it("sync, mode passed as string", () => { jetpack.dir("a", { mode: "511" }); expectations(); }); it("sync, mode passed as number", () => { jetpack.dir("a", { mode: 0o511 }); expectations(); }); it("async, mode passed as string", done => { jetpack.dirAsync("a", { mode: "511" }).then(() => { expectations(); done(); }); }); it("async, mode passed as number", done => { jetpack.dirAsync("a", { mode: 0o511 }).then(() => { expectations(); done(); }); }); }); describe("sets desired mode to every created directory (unix only)", () => { const expectations = () => { path("a").shouldHaveMode("711"); path("a/b").shouldHaveMode("711"); }; it("sync", () => { jetpack.dir("a/b", { mode: "711" }); expectations(); }); it("async", done => { jetpack.dirAsync("a/b", { mode: "711" }).then(() => { expectations(); done(); }); }); }); describe("changes mode of existing directory to desired (unix only)", () => { const preparations = () => { fse.mkdirSync("a", "777"); }; const expectations = () => { path("a").shouldHaveMode("511"); }; it("sync", () => { preparations(); jetpack.dir("a", { mode: "511" }); expectations(); }); it("async", done => { preparations(); jetpack.dirAsync("a", { mode: "511" }).then(() => { expectations(); done(); }); }); }); describe("leaves mode of directory intact by default (unix only)", () => { const preparations = () => { fse.mkdirSync("a", "700"); }; const expectations = () => { path("a").shouldHaveMode("700"); }; it("sync", () => { preparations(); jetpack.dir("a"); expectations(); }); it("async", done => { preparations(); jetpack.dirAsync("a").then(() => { expectations(); done(); }); }); }); } else { describe("specyfying mode have no effect and throws no error (windows only)", () => { const expectations = () => { path("x").shouldBeDirectory(); }; it("sync", () => { jetpack.dir("x", { mode: "511" }); expectations(); }); it("async", done => { jetpack.dirAsync("x", { mode: "511" }).then(() => { expectations(); done(); }); }); }); } describe("input validation", () => { const tests = [ { type: "sync", method: jetpack.dir as any, methodName: "dir" }, { type: "async", method: jetpack.dirAsync as any, methodName: "dirAsync" } ]; describe('"path" argument', () => { tests.forEach(test => { it(test.type, () => { expect(() => { test.method(undefined); }).to.throw( `Argument "path" passed to ${ test.methodName }(path, [criteria]) must be a string. Received undefined` ); }); }); }); describe('"criteria" object', () => { describe('"empty" argument', () => { tests.forEach(test => { it(test.type, () => { expect(() => { test.method("abc", { empty: 1 }); }).to.throw( `Argument "criteria.empty" passed to ${ test.methodName }(path, [criteria]) must be a boolean. Received number` ); }); }); }); describe('"mode" argument', () => { tests.forEach(test => { it(test.type, () => { expect(() => { test.method("abc", { mode: true }); }).to.throw( `Argument "criteria.mode" passed to ${ test.methodName }(path, [criteria]) must be a string or a number. Received boolean` ); }); }); }); }); }); });