diff --git a/README.md b/README.md index e5fc0d1..ffb1b7c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# :sauropod: amber +# amber A library for mocking [Deno APIs](https://deno.land/api) with ease. @@ -7,7 +7,7 @@ A library for mocking [Deno APIs](https://deno.land/api) with ease. ## Features -- Compatible with [@std/testing](https://jsr.io/@std/testing) +- Built upon and compatible with [@std/testing](https://jsr.io/@std/testing) - Consistent interfaces across submodules ## Usage @@ -20,80 +20,100 @@ import * as cmd from "jsr:@chiezo/amber/cmd"; #### `mock` +Replace Deno.Command: + ```typescript -const Original = Deno.Command; +cmd.mock(); +assert(Deno.Command !== Original); +``` -it("should return a disposable", () => { - assert(Symbol.dispose in cmd.mock()); -}); +Return a disposable: -it("should replace Deno.Command", () => { - cmd.mock(); - assert(Deno.Command !== Original); -}); +```typescript +assert(Symbol.dispose in cmd.mock()); ``` #### `use` +Replace Deno.Command inside the callback: + ```typescript -it("should replace Deno.Command within the callback", () => { - using echo = cmd.spy("echo"); - cmd.use(() => { - new Deno.Command("echo"); - }); - assertSpyCalls(echo, 1); +using echo = cmd.spy("echo"); + +cmd.use(() => { + new Deno.Command("echo"); }); +assertSpyCalls(echo, 1); +``` + +#### `restore` + +Restore Deno.Command: + +```typescript +cmd.mock(); +cmd.restore(); +assert(Deno.Command === Original); ``` #### `spy` +Create a spy for a command: + ```typescript -it("should create a spy for a command", () => { - using echo = cmd.spy("echo"); - cmd.use(() => new Deno.Command("echo")); - assertSpyCalls(echo, 1); -}); +using echo = cmd.spy("echo"); + +cmd.use(() => new Deno.Command("echo")); +assertSpyCalls(echo, 1); ``` -#### `stub` +Create multiple spies for different commands separately: ```typescript -it("should create a stub for a command with a default dummy", async () => { - using echo = cmd.stub("echo"); - cmd.mock(); - await new Deno.Command("echo").output(); - assertEquals( - Deno.permissions.querySync({ name: "run", command: "echo" }).state, - "prompt", - ); - assertSpyCalls(echo, 1); -}); +using echo = cmd.spy("echo"); -it("should create a stub for a command with a given fake", () => { - cmd.stub( - "echo", - class extends Deno.Command { - constructor(command: string | URL) { - super(command); - throw new Error(); - } - }, - ); - cmd.mock(); - assertThrows(() => new Deno.Command("echo")); +using ls = cmd.spy("ls"); + +cmd.use(() => { + new Deno.Command("echo"); + assertSpyCalls(echo, 1); + assertSpyCalls(ls, 0); + new Deno.Command("ls"); + assertSpyCalls(echo, 1); + assertSpyCalls(ls, 1); }); ``` -#### `restore` +#### `stub` + +Create a stub for a command with a dummy by default: ```typescript -const Original = Deno.Command; +using echo = cmd.stub("echo"); + +cmd.mock(); +await new Deno.Command("echo").output(); +assertEquals( + Deno.permissions.querySync({ name: "run", command: "echo" }).state, + "prompt", +); +assertSpyCalls(echo, 1); +``` -it("should restore Deno.Command", () => { - cmd.mock(); - cmd.restore(); - assert(Deno.Command === Original); -}); +Create a stub for a command with a fake: + +```typescript +cmd.stub( + "echo", + class extends Deno.Command { + constructor(command: string | URL) { + super(command); + throw new Error(); + } + }, +); +cmd.mock(); +assertThrows(() => new Deno.Command("echo")); ``` ### File System @@ -104,110 +124,122 @@ import * as fs from "jsr:@chiezo/amber/fs"; #### `mock` +Return a disposable: + ```typescript -const Original = { ...Deno }; +assert(Symbol.dispose in fs.mock()); +``` -it("should return a disposable", () => { - assert(Symbol.dispose in fs.mock()); -}); +Replace file system functions as side effects: + +```typescript +fs.mock(); +assert(Deno.readTextFile !== original.readTextFile); +assert(Deno.readTextFileSync !== original.readTextFileSync); +``` + +#### `use` -it("should replace file system functions", () => { - fs.mock(); +Replace file system functions within the callback: + +```typescript +fs.use(() => { assert(Deno.readTextFile !== original.readTextFile); assert(Deno.readTextFileSync !== original.readTextFileSync); - // ...and others }); ``` -#### `use` +#### `restore` + +Restore file system functions: ```typescript -const original = { ...Deno }; - -it("should replace file system functions within the callback", () => { - fs.use(() => { - assert(Deno.readTextFile !== original.readTextFile); - assert(Deno.readTextFileSync !== original.readTextFileSync); - // ...and others - }); -}); +fs.mock(); +fs.restore(); +assert(Deno.readTextFile === original.readTextFile); +assert(Deno.readTextFileSync === original.readTextFileSync); ``` #### `spy` +Spy file system functions: + ```typescript -it("should spy file system functions", async () => { - using spy = fs.spy("../"); - await fs.use(() => Deno.readTextFile("../README.md")); - assertSpyCalls(spy.readTextFile, 1); -}); +using spy = fs.spy("../"); -it("should be able to spy multiple paths separately", async () => { - using cwd = fs.spy("."); - using root = fs.spy("../"); - await fs.use(() => Deno.readTextFile("../README.md")); - assertSpyCalls(cwd.readTextFile, 0); - assertSpyCalls(root.readTextFile, 1); -}); +await fs.use(() => Deno.readTextFile("../README.md")); +assertSpyCalls(spy.readTextFile, 1); +``` + +Spy multiple paths separately: + +```typescript +using cwd = fs.spy("."); + +using root = fs.spy("../"); + +await fs.use(() => Deno.readTextFile("../README.md")); +assertSpyCalls(cwd.readTextFile, 0); +assertSpyCalls(root.readTextFile, 1); ``` #### `stub` +Won't write to the original path: + ```typescript -it("should not write to the original path", async () => { - using stub = fs.stub("../"); - await fs.use(() => Deno.writeTextFile("../test.txt", "amber")); +using stub = fs.stub("../"); + +await fs.use(() => Deno.writeTextFile("../test.txt", "amber")); +assertEquals( + (await Deno.permissions.query({ name: "write", path: "../test.txt" })) + .state, + "prompt", +); +assertSpyCalls(stub.writeTextFile, 1); +``` + +Make the original file readable initially (readThrough): + +```typescript +using stub = fs.stub("../"); + +await fs.use(() => Deno.readTextFile("../README.md")); +assertSpyCalls(stub.readTextFile, 1); +``` + +Make the updated content readable after being written: + +```typescript +using _ = fs.stub("../"); + +await fs.use(async () => { + await Deno.writeTextFile("../README.md", "amber"); assertEquals( - (await Deno.permissions.query({ name: "write", path: "../test.txt" })) - .state, - "prompt", + await Deno.readTextFile("../README.md"), + "amber", ); - assertSpyCalls(stub.writeTextFile, 1); -}); - -it("should allow original files to be read initially (readThrough)", async () => { - using stub = fs.stub("../"); - await fs.use(() => Deno.readTextFile("../README.md")); - assertSpyCalls(stub.readTextFile, 1); }); +``` -it("should let the updated file be read after being written", async () => { - using _ = fs.stub("../"); - await fs.use(async () => { - await Deno.writeTextFile("../README.md", "amber"); - assertEquals( - await Deno.readTextFile("../README.md"), - "amber", - ); - }); -}); +Throw on a file that has not been written if readThrough is disabled: -it("should throw on a file that has not been written if readThrough is disabled", () => { - using _ = fs.stub(new URL("../", import.meta.url), { readThrough: false }); - fs.use(() => assertThrows(() => Deno.readTextFileSync("../README.md"))); -}); +```typescript +using _ = fs.stub(new URL("../", import.meta.url), { readThrough: false }); -it("should be able to stub multiple paths separately", async () => { - using cwd = fs.stub("."); - using root = fs.stub("../"); - await fs.use(() => Deno.readTextFile("../README.md")); - assertSpyCalls(cwd.readTextFile, 0); - assertSpyCalls(root.readTextFile, 1); -}); +fs.use(() => assertThrows(() => Deno.readTextFileSync("../README.md"))); ``` -#### `restore` +Stub multiple paths separately: ```typescript -const original = { ...Deno }; - -it("should restore the Deno namespace", () => { - fs.mock(); - fs.restore(); - assert(Deno.readTextFile === original.readTextFile); - assert(Deno.readTextFileSync === original.readTextFileSync); - // ...and others -}); +using cwd = fs.stub("."); + +using root = fs.stub("../"); + +await fs.use(() => Deno.readTextFile("../README.md")); +assertSpyCalls(cwd.readTextFile, 0); +assertSpyCalls(root.readTextFile, 1); ``` ### Utilities @@ -218,45 +250,47 @@ import { all } from "jsr:@chiezo/amber/util"; #### `all` +Mock multiple modules at the same time: + ```typescript -const original = { ...Deno }; +using echo = cmd.stub("echo"); -it("should mock multiple modules at the same time", async () => { - using echo = cmd.stub("echo"); - using root = fs.stub("../"); +using root = fs.stub("../"); - all(cmd, fs).mock(); +all(cmd, fs).mock(); +new Deno.Command("echo"); +assertSpyCalls(echo, 1); +await Deno.readTextFile("../README.md"); +assertSpyCalls(root.readTextFile, 1); +``` - new Deno.Command("echo"); - assertSpyCalls(echo, 1); +Use multiple modules at the same time: - await Deno.readTextFile("../README.md"); - assertSpyCalls(root.readTextFile, 1); -}); +```typescript +using echo = cmd.stub("echo"); -it("should use multiple modules at the same time", async () => { - using echo = cmd.stub("echo"); - using root = fs.stub("../"); +using root = fs.stub("../"); - await all(cmd, fs).use(async () => { - new Deno.Command("echo"); - assertSpyCalls(echo, 1); +await all(cmd, fs).use(async () => { + new Deno.Command("echo"); + assertSpyCalls(echo, 1); - await Deno.writeTextFile("../test.txt", "amber"); - assertSpyCalls(root.writeTextFile, 1); + await Deno.writeTextFile("../test.txt", "amber"); + assertSpyCalls(root.writeTextFile, 1); - assertEquals( - await Deno.readTextFile("../test.txt"), - "amber", - ); - assertSpyCalls(root.readTextFile, 1); - }); + assertEquals( + await Deno.readTextFile("../test.txt"), + "amber", + ); + assertSpyCalls(root.readTextFile, 1); }); +``` -it("should restore multiple modules at the same time", () => { - all(cmd, fs).mock(); - all(cmd, fs).restore(); - assert(Deno.Command === original.Command); - assert(Deno.readTextFile === original.readTextFile); -}); +Restore multiple modules at the same time: + +```typescript +all(cmd, fs).mock(); +all(cmd, fs).restore(); +assert(Deno.Command === original.Command); +assert(Deno.readTextFile === original.readTextFile); ``` diff --git a/deno.json b/deno.json index fa0cf7b..9c1a96a 100644 --- a/deno.json +++ b/deno.json @@ -14,6 +14,7 @@ ] }, "imports": { + "@chiezo/bddoc": "jsr:@chiezo/bddoc@^0.0.3", "@molt/lib": "jsr:@molt/lib@^0.18.0", "@std/assert": "jsr:@std/assert@^0.225.3", "@std/collections": "jsr:@std/collections@^0.224.2", @@ -23,7 +24,8 @@ }, "tasks": { "check": "deno fmt -q && deno lint -q && deno check -q src/*.ts", + "doc": "deno run --allow-env --allow-ffi --allow-read --allow-run=deno --allow-sys --allow-write=README.md docs/build.ts", "test": "deno test --allow-read --allow-write=/tmp --no-check", - "pre-commit": "deno task check && deno task test" + "pre-commit": "deno task check && deno task test && deno task doc" } } diff --git a/deno.lock b/deno.lock index 2f78a1c..e3bb510 100644 --- a/deno.lock +++ b/deno.lock @@ -2,20 +2,43 @@ "version": "3", "packages": { "specifiers": { + "jsr:@chiezo/bddoc@^0.0.3": "jsr:@chiezo/bddoc@0.0.3", + "jsr:@core/match@^0.3.1": "jsr:@core/match@0.3.1", + "jsr:@core/unknownutil@3.18.0": "jsr:@core/unknownutil@3.18.0", "jsr:@molt/lib@^0.18.0": "jsr:@molt/lib@0.18.0", "jsr:@std/assert@^0.222.1": "jsr:@std/assert@0.222.1", "jsr:@std/assert@^0.224.0": "jsr:@std/assert@0.224.0", - "jsr:@std/assert@^0.225.2": "jsr:@std/assert@0.225.3", "jsr:@std/assert@^0.225.3": "jsr:@std/assert@0.225.3", + "jsr:@std/assert@^0.226.0": "jsr:@std/assert@0.226.0", "jsr:@std/collections@^0.224.2": "jsr:@std/collections@0.224.2", "jsr:@std/fmt@^0.224.0": "jsr:@std/fmt@0.224.0", "jsr:@std/internal@^0.224.0": "jsr:@std/internal@0.224.0", "jsr:@std/internal@^1.0.0": "jsr:@std/internal@1.0.0", "jsr:@std/path@^0.222.1": "jsr:@std/path@0.222.1", - "jsr:@std/path@^0.225.1": "jsr:@std/path@0.225.1", - "jsr:@std/testing@^0.224.0": "jsr:@std/testing@0.224.0" + "jsr:@std/path@^0.225.1": "jsr:@std/path@0.225.2", + "jsr:@std/testing@^0.224.0": "jsr:@std/testing@0.224.0", + "npm:@swc/core@^1.5.24": "npm:@swc/core@1.5.24", + "npm:dedent@^1.5.3": "npm:dedent@1.5.3" }, "jsr": { + "@chiezo/bddoc@0.0.3": { + "integrity": "ff1eabd532d4480b27f9028967b53d11ff263ff225bceb4a83923252a62361de", + "dependencies": [ + "jsr:@core/match@^0.3.1", + "jsr:@std/collections@^0.224.2", + "npm:@swc/core@^1.5.24", + "npm:dedent@^1.5.3" + ] + }, + "@core/match@0.3.1": { + "integrity": "020bb0199f56877daf270a457bfeee19daa8c721819d36dc987c2a9df7cca4fd", + "dependencies": [ + "jsr:@core/unknownutil@3.18.0" + ] + }, + "@core/unknownutil@3.18.0": { + "integrity": "bff7ab4a2f554bbade301127519523b0d3baa4273ecbed51287133ac00a48738" + }, "@molt/lib@0.18.0": { "integrity": "c5b10f134f8ba68f6f6a389ad08fedca705a12d3d1d12ec2b45b06cf67b9b9e1", "dependencies": [ @@ -38,6 +61,9 @@ "jsr:@std/internal@^1.0.0" ] }, + "@std/assert@0.226.0": { + "integrity": "0dfb5f7c7723c18cec118e080fec76ce15b4c31154b15ad2bd74822603ef75b3" + }, "@std/collections@0.224.2": { "integrity": "e77819455294e92d4e7ddad1dbfd46f94174c09318e541e6621fac4a4d0ab326" }, @@ -56,10 +82,10 @@ "jsr:@std/assert@^0.222.1" ] }, - "@std/path@0.225.1": { - "integrity": "8c3220635a73730eb51fe43de9e10b79e2724a5bb8638b9355d35ae012fd9429", + "@std/path@0.225.2": { + "integrity": "0f2db41d36b50ef048dcb0399aac720a5348638dd3cb5bf80685bf2a745aa506", "dependencies": [ - "jsr:@std/assert@^0.225.2" + "jsr:@std/assert@^0.226.0" ] }, "@std/testing@0.224.0": { @@ -68,11 +94,85 @@ "jsr:@std/assert@^0.224.0" ] } + }, + "npm": { + "@swc/core-darwin-arm64@1.5.24": { + "integrity": "sha512-M7oLOcC0sw+UTyAuL/9uyB9GeO4ZpaBbH76JSH6g1m0/yg7LYJZGRmplhDmwVSDAR5Fq4Sjoi1CksmmGkgihGA==", + "dependencies": {} + }, + "@swc/core-darwin-x64@1.5.24": { + "integrity": "sha512-MfcFjGGYognpSBSos2pYUNYJSmqEhuw5ceGr6qAdME7ddbjGXliza4W6FggsM+JnWwpqa31+e7/R+GetW4WkaQ==", + "dependencies": {} + }, + "@swc/core-linux-arm-gnueabihf@1.5.24": { + "integrity": "sha512-amI2pwtcWV3E/m/nf+AQtn1LWDzKLZyjCmWd3ms7QjEueWYrY8cU1Y4Wp7wNNsxIoPOi8zek1Uj2wwFD/pttNQ==", + "dependencies": {} + }, + "@swc/core-linux-arm64-gnu@1.5.24": { + "integrity": "sha512-sTSvmqMmgT1ynH/nP75Pc51s+iT4crZagHBiDOf5cq+kudUYjda9lWMs7xkXB/TUKFHPCRK0HGunl8bkwiIbuw==", + "dependencies": {} + }, + "@swc/core-linux-arm64-musl@1.5.24": { + "integrity": "sha512-vd2/hfOBGbrX21FxsFdXCUaffjkHvlZkeE2UMRajdXifwv79jqOHIJg3jXG1F3ZrhCghCzirFts4tAZgcG8XWg==", + "dependencies": {} + }, + "@swc/core-linux-x64-gnu@1.5.24": { + "integrity": "sha512-Zrdzi7NqzQxm2BvAG5KyOSBEggQ7ayrxh599AqqevJmsUXJ8o2nMiWQOBvgCGp7ye+Biz3pvZn1EnRzAp+TpUg==", + "dependencies": {} + }, + "@swc/core-linux-x64-musl@1.5.24": { + "integrity": "sha512-1F8z9NRi52jdZQCGc5sflwYSctL6omxiVmIFVp8TC9nngjQKc00TtX/JC2Eo2HwvgupkFVl5YQJidAck9YtmJw==", + "dependencies": {} + }, + "@swc/core-win32-arm64-msvc@1.5.24": { + "integrity": "sha512-cKpP7KvS6Xr0jFSTBXY53HZX/YfomK5EMQYpCVDOvfsZeYHN20sQSKXfpVLvA/q2igVt1zzy1XJcOhpJcgiKLg==", + "dependencies": {} + }, + "@swc/core-win32-ia32-msvc@1.5.24": { + "integrity": "sha512-IoPWfi0iwqjZuf7gE223+B97/ZwkKbu7qL5KzGP7g3hJrGSKAvv7eC5Y9r2iKKtLKyv5R/T6Ho0kFR/usi7rHw==", + "dependencies": {} + }, + "@swc/core-win32-x64-msvc@1.5.24": { + "integrity": "sha512-zHgF2k1uVJL8KIW+PnVz1To4a3Cz9THbh2z2lbehaF/gKHugH4c3djBozU4das1v35KOqf5jWIEviBLql2wDLQ==", + "dependencies": {} + }, + "@swc/core@1.5.24": { + "integrity": "sha512-Eph9zvO4xvqWZGVzTdtdEJ0Vqf0VIML/o/e4Qd2RLOqtfgnlRi7avmMu5C0oqciJ0tk+hqdUKVUZ4JPoPaiGvQ==", + "dependencies": { + "@swc/core-darwin-arm64": "@swc/core-darwin-arm64@1.5.24", + "@swc/core-darwin-x64": "@swc/core-darwin-x64@1.5.24", + "@swc/core-linux-arm-gnueabihf": "@swc/core-linux-arm-gnueabihf@1.5.24", + "@swc/core-linux-arm64-gnu": "@swc/core-linux-arm64-gnu@1.5.24", + "@swc/core-linux-arm64-musl": "@swc/core-linux-arm64-musl@1.5.24", + "@swc/core-linux-x64-gnu": "@swc/core-linux-x64-gnu@1.5.24", + "@swc/core-linux-x64-musl": "@swc/core-linux-x64-musl@1.5.24", + "@swc/core-win32-arm64-msvc": "@swc/core-win32-arm64-msvc@1.5.24", + "@swc/core-win32-ia32-msvc": "@swc/core-win32-ia32-msvc@1.5.24", + "@swc/core-win32-x64-msvc": "@swc/core-win32-x64-msvc@1.5.24", + "@swc/counter": "@swc/counter@0.1.3", + "@swc/types": "@swc/types@0.1.7" + } + }, + "@swc/counter@0.1.3": { + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dependencies": {} + }, + "@swc/types@0.1.7": { + "integrity": "sha512-scHWahbHF0eyj3JsxG9CFJgFdFNaVQCNAimBlT6PzS3n/HptxqREjsm4OH6AN3lYcffZYSPxXW8ua2BEHp0lJQ==", + "dependencies": { + "@swc/counter": "@swc/counter@0.1.3" + } + }, + "dedent@1.5.3": { + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dependencies": {} + } } }, "remote": {}, "workspace": { "dependencies": [ + "jsr:@chiezo/bddoc@^0.0.3", "jsr:@molt/lib@^0.18.0", "jsr:@std/assert@^0.225.3", "jsr:@std/collections@^0.224.2", diff --git a/docs/build.ts b/docs/build.ts new file mode 100644 index 0000000..ee202d7 --- /dev/null +++ b/docs/build.ts @@ -0,0 +1,21 @@ +import { transform } from "@chiezo/bddoc"; + +Deno.chdir(new URL("../", import.meta.url)); + +let template = await Deno.readTextFile("./docs/readme.md"); + +for (const mod of ["cmd", "fs", "util"]) { + template = template.replace( + new RegExp(`\n`, "g"), + await transform( + await Deno.readTextFile(`./src/${mod}_test.ts`), + { heading: 4 }, + ), + ); +} + +await Deno.writeTextFile("README.md", template); + +await new Deno.Command("deno", { + args: ["fmt", "README.md"], +}).output(); diff --git a/docs/readme.md b/docs/readme.md new file mode 100644 index 0000000..ab4835f --- /dev/null +++ b/docs/readme.md @@ -0,0 +1,37 @@ +# amber + +A library for mocking [Deno APIs](https://deno.land/api) with ease. + +> [!WARNING]\ +> Alpha version. Not tested extensively or documented well yet. + +## Features + +- Built upon and compatible with [@std/testing](https://jsr.io/@std/testing) +- Consistent interfaces across submodules + +## Usage + +### Command + +```typescript +import * as cmd from "jsr:@chiezo/amber/cmd"; +``` + + + +### File System + +```typescript +import * as fs from "jsr:@chiezo/amber/fs"; +``` + + + +### Utilities + +```typescript +import { all } from "jsr:@chiezo/amber/util"; +``` + + diff --git a/src/cmd_test.ts b/src/cmd_test.ts index 8568d2e..afb2b3d 100644 --- a/src/cmd_test.ts +++ b/src/cmd_test.ts @@ -1,7 +1,6 @@ import { assert, assertEquals, assertThrows } from "@std/assert"; -import { afterEach, beforeEach, describe, it } from "@std/testing/bdd"; -import { assertSpyCallArg, assertSpyCalls } from "@std/testing/mock"; -import type { CommandSpy } from "./cmd.ts"; +import { afterEach, describe, it } from "@std/testing/bdd"; +import { assertSpyCalls } from "@std/testing/mock"; import * as cmd from "./cmd.ts"; describe("mock", () => { @@ -47,6 +46,19 @@ describe("spy", () => { cmd.use(() => new Deno.Command("echo")); assertSpyCalls(echo, 1); }); + + it("should create multiple spies for different commands separately", () => { + using echo = cmd.spy("echo"); + using ls = cmd.spy("ls"); + cmd.use(() => { + new Deno.Command("echo"); + assertSpyCalls(echo, 1); + assertSpyCalls(ls, 0); + new Deno.Command("ls"); + assertSpyCalls(echo, 1); + assertSpyCalls(ls, 1); + }); + }); }); describe("stub", () => { @@ -79,41 +91,3 @@ describe("stub", () => { assertThrows(() => new Deno.Command("echo")); }); }); - -describe("CommandSpy", () => { - let echo: CommandSpy<"echo">; - - beforeEach(() => { - cmd.mock(); - echo = cmd.spy("echo"); - }); - - afterEach(() => { - cmd.restore(); - }); - - it("should be tested with assertSpyCalls", () => { - assertSpyCalls(echo, 0); - new Deno.Command("echo"); - assertSpyCalls(echo, 1); - new Deno.Command("echo"); - assertSpyCalls(echo, 2); - }); - - it("should be tested with assertSpyCallArg", () => { - new Deno.Command("echo"); - assertSpyCallArg(echo, 0, 1, undefined); - new Deno.Command("echo", { cwd: "/tmp" }); - assertSpyCallArg(echo, 1, 1, { cwd: "/tmp" }); - }); - - it("should distinguish between different commands", () => { - const ls = cmd.spy("ls"); - new Deno.Command("echo"); - assertSpyCalls(echo, 1); - assertSpyCalls(ls, 0); - new Deno.Command("ls"); - assertSpyCalls(echo, 1); - assertSpyCalls(ls, 1); - }); -}); diff --git a/src/fs_test.ts b/src/fs_test.ts index d62b687..e5448bb 100644 --- a/src/fs_test.ts +++ b/src/fs_test.ts @@ -1,7 +1,6 @@ import { assert, assertEquals, assertThrows } from "@std/assert"; import { afterAll, afterEach, beforeAll, describe, it } from "@std/testing/bdd"; -import { assertSpyCall, assertSpyCalls } from "@std/testing/mock"; -import type { FileSystemSpy } from "./fs.ts"; +import { assertSpyCalls } from "@std/testing/mock"; import * as fs from "./fs.ts"; describe("mock", () => { @@ -15,7 +14,7 @@ describe("mock", () => { assert(Symbol.dispose in fs.mock()); }); - it("should replace file system functions", () => { + it("should replace file system functions as side effects", () => { fs.mock(); assert(Deno.readTextFile !== original.readTextFile); assert(Deno.readTextFileSync !== original.readTextFileSync); @@ -36,7 +35,7 @@ describe("use", () => { describe("restore", () => { const original = { ...Deno }; - it("should restore the Deno namespace", () => { + it("should restore file system functions", () => { fs.mock(); fs.restore(); assert(Deno.readTextFile === original.readTextFile); @@ -62,7 +61,7 @@ describe("spy", () => { assertSpyCalls(spy.readTextFile, 1); }); - it("should be able to spy multiple paths separately", async () => { + it("should spy multiple paths separately", async () => { using cwd = fs.spy("."); using root = fs.spy("../"); await fs.use(() => Deno.readTextFile("../README.md")); @@ -94,13 +93,13 @@ describe("stub", () => { assertSpyCalls(stub.writeTextFile, 1); }); - it("should allow original files to be read initially (readThrough)", async () => { + it("should make the original file readable initially (readThrough)", async () => { using stub = fs.stub("../"); await fs.use(() => Deno.readTextFile("../README.md")); assertSpyCalls(stub.readTextFile, 1); }); - it("should let the updated file be read after being written", async () => { + it("should make the updated content readable after being written", async () => { using _ = fs.stub("../"); await fs.use(async () => { await Deno.writeTextFile("../README.md", "amber"); @@ -116,7 +115,7 @@ describe("stub", () => { fs.use(() => assertThrows(() => Deno.readTextFileSync("../README.md"))); }); - it("should be able to stub multiple paths separately", async () => { + it("should stub multiple paths separately", async () => { using cwd = fs.stub("."); using root = fs.stub("../"); await fs.use(() => Deno.readTextFile("../README.md")); @@ -124,31 +123,3 @@ describe("stub", () => { assertSpyCalls(root.readTextFile, 1); }); }); - -describe("FileSystemSpy", () => { - let cwd: string; - let spy: FileSystemSpy; - - beforeAll(() => { - cwd = Deno.cwd(); - Deno.chdir(new URL(".", import.meta.url)); - spy = fs.spy("../"); - fs.mock(); - }); - - afterAll(() => { - spy[Symbol.dispose](); - fs.restore(); - Deno.chdir(cwd); - }); - - it("should be testable with assertSpyCalls", async () => { - await Deno.readTextFile("../README.md"); - assertSpyCalls(spy.readTextFile, 1); - }); - - it("should be testable with assertSpyCall", async () => { - await Deno.readTextFile("../README.md"); - assertSpyCall(spy.readTextFile, 0, { args: ["../README.md"] }); - }); -});