├── .npmrc ├── .prettierignore ├── .github ├── funding.yml └── workflows │ └── ci.yml ├── .gitignore ├── .prettierrc.json ├── .vscode └── settings.json ├── .editorconfig ├── jsconfig.json ├── .eslintrc.json ├── license.md ├── package.json ├── readme.md ├── assertSnapshot.mjs ├── changelog.md └── test.mjs /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | package.json 2 | -------------------------------------------------------------------------------- /.github/funding.yml: -------------------------------------------------------------------------------- 1 | github: jaydenseric 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "proseWrap": "never" 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.disableAutomaticTypeAcquisition": true, 3 | "typescript.enablePromptUseWorkspaceTsdk": true, 4 | "typescript.tsdk": "node_modules/typescript/lib" 5 | } 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_style = space 7 | indent_size = 2 8 | max_line_length = 80 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "maxNodeModuleJsDepth": 10, 4 | "module": "nodenext", 5 | "noEmit": true, 6 | "strict": true 7 | }, 8 | "typeAcquisition": { 9 | "enable": false 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request] 3 | jobs: 4 | test: 5 | name: Test with Node.js v${{ matrix.node }} and ${{ matrix.os }} 6 | runs-on: ${{ matrix.os }} 7 | strategy: 8 | matrix: 9 | os: [ubuntu-latest, macos-latest] 10 | node: ["16", "18", "19"] 11 | steps: 12 | - uses: actions/checkout@v3 13 | - name: Setup Node.js v${{ matrix.node }} 14 | uses: actions/setup-node@v3 15 | with: 16 | node-version: ${{ matrix.node }} 17 | - name: npm install and test 18 | run: npm install-test 19 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["eslint:recommended"], 3 | "env": { 4 | "es2022": true, 5 | "node": true 6 | }, 7 | "parserOptions": { 8 | "ecmaVersion": "latest" 9 | }, 10 | "plugins": ["simple-import-sort"], 11 | "rules": { 12 | "simple-import-sort/imports": "error", 13 | "simple-import-sort/exports": "error" 14 | }, 15 | "overrides": [ 16 | { 17 | "files": ["*.mjs"], 18 | "parserOptions": { 19 | "sourceType": "module" 20 | }, 21 | "globals": { 22 | "__dirname": "off", 23 | "__filename": "off", 24 | "exports": "off", 25 | "module": "off", 26 | "require": "off" 27 | } 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright Jayden Seric 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "snapshot-assertion", 3 | "version": "5.0.0", 4 | "description": "Asserts a string matches a snapshot saved in a file. An environment variable can be used to save rather than assert snapshots.", 5 | "license": "MIT", 6 | "author": { 7 | "name": "Jayden Seric", 8 | "email": "me@jaydenseric.com", 9 | "url": "https://jaydenseric.com" 10 | }, 11 | "repository": "github:jaydenseric/snapshot-assertion", 12 | "homepage": "https://github.com/jaydenseric/snapshot-assertion#readme", 13 | "bugs": "https://github.com/jaydenseric/snapshot-assertion/issues", 14 | "funding": "https://github.com/sponsors/jaydenseric", 15 | "keywords": [ 16 | "snapshot", 17 | "assert", 18 | "assertion", 19 | "test", 20 | "testing", 21 | "esm", 22 | "mjs" 23 | ], 24 | "files": [ 25 | "assertSnapshot.mjs" 26 | ], 27 | "sideEffects": false, 28 | "exports": { 29 | ".": "./assertSnapshot.mjs", 30 | "./assertSnapshot.mjs": "./assertSnapshot.mjs", 31 | "./package.json": "./package.json" 32 | }, 33 | "engines": { 34 | "node": "^16.9.0 || >= 18.0.0" 35 | }, 36 | "dependencies": { 37 | "@types/node": "*" 38 | }, 39 | "devDependencies": { 40 | "coverage-node": "^8.0.0", 41 | "disposable-directory": "^6.0.0", 42 | "eslint": "^8.37.0", 43 | "eslint-plugin-simple-import-sort": "^10.0.0", 44 | "prettier": "^2.8.7", 45 | "test-director": "^11.0.0", 46 | "typescript": "^5.0.3" 47 | }, 48 | "scripts": { 49 | "eslint": "eslint .", 50 | "prettier": "prettier -c .", 51 | "types": "tsc -p jsconfig.json", 52 | "tests": "coverage-node test.mjs", 53 | "test": "npm run eslint && npm run prettier && npm run types && npm run tests", 54 | "prepublishOnly": "npm test" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # snapshot-assertion 2 | 3 | Asserts a string matches a snapshot saved in a file. An environment variable can be used to save rather than assert snapshots. 4 | 5 | ## Installation 6 | 7 | To install [`snapshot-assertion`](https://npm.im/snapshot-assertion) with [npm](https://npmjs.com/get-npm), run: 8 | 9 | ```sh 10 | npm install snapshot-assertion --save-dev 11 | ``` 12 | 13 | Then, import and use the function [`assertSnapshot`](./assertSnapshot.mjs). 14 | 15 | ## Examples 16 | 17 | A snapshot assertion in a [`test-director`](https://npm.im/test-director) test: 18 | 19 | ```js 20 | import fetch from "node-fetch"; 21 | import assertSnapshot from "snapshot-assertion"; 22 | import TestDirector from "test-director"; 23 | 24 | const tests = new TestDirector(); 25 | 26 | tests.add("Get a todo.", async () => { 27 | const response = await fetch("https://jsonplaceholder.typicode.com/todos/1"); 28 | await assertSnapshot(await response.json(), "snapshots/todo.json"); 29 | }); 30 | 31 | tests.run(); 32 | ``` 33 | 34 | Using the `SAVE_SNAPSHOTS` environment variable to save snapshots when running a package script: 35 | 36 | ```sh 37 | SAVE_SNAPSHOTS=1 npm run test 38 | ``` 39 | 40 | ## Requirements 41 | 42 | Supported runtime environments: 43 | 44 | - [Node.js](https://nodejs.org) versions `^16.9.0 || >= 18.0.0`. 45 | 46 | Projects must configure [TypeScript](https://typescriptlang.org) to use types from the ECMAScript modules that have a `// @ts-check` comment: 47 | 48 | - [`compilerOptions.allowJs`](https://typescriptlang.org/tsconfig#allowJs) should be `true`. 49 | - [`compilerOptions.maxNodeModuleJsDepth`](https://typescriptlang.org/tsconfig#maxNodeModuleJsDepth) should be reasonably large, e.g. `10`. 50 | - [`compilerOptions.module`](https://typescriptlang.org/tsconfig#module) should be `"node16"` or `"nodenext"`. 51 | 52 | ## Exports 53 | 54 | The [npm](https://npmjs.com) package [`snapshot-assertion`](https://npm.im/snapshot-assertion) features [optimal JavaScript module design](https://jaydenseric.com/blog/optimal-javascript-module-design). These ECMAScript modules are exported via the [`package.json`](./package.json) field [`exports`](https://nodejs.org/api/packages.html#exports): 55 | 56 | - [`assertSnapshot.mjs`](./assertSnapshot.mjs) 57 | -------------------------------------------------------------------------------- /assertSnapshot.mjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | import { strictEqual } from "node:assert"; 4 | import { readFile, writeFile } from "node:fs/promises"; 5 | 6 | /** 7 | * Asserts a string matches a snapshot saved in a file. A truthy 8 | * `SAVE_SNAPSHOTS` environment variable can be used to save rather than assert 9 | * snapshots. 10 | * @param {string} actualValue Actual value to assert matches the snapshot 11 | * expected value. 12 | * @param {string | URL} snapshotFile Snapshot file path or URL. Be sure any 13 | * directories in the path already exist. It’s a good idea to use a filename 14 | * extension suited to the data, e.g. `.json`, `.yml`, `.xml`, `.html`, `.md`, 15 | * or `.txt`. 16 | * @param {Function} [assertion] Assertion that receives actual and expected 17 | * values and throws an error if they don’t match. Defaults to the Node.js 18 | * [`strictEqual`](https://nodejs.org/api/assert.html#assert_assert_strictequal_actual_expected_message) 19 | * assertion. 20 | * @returns {Promise} Resolves once the snapshot has been saved or 21 | * asserted. 22 | * @example 23 | * A snapshot assertion in a [`test-director`](https://npm.im/test-director) 24 | * test: 25 | * 26 | * ```js 27 | * import fetch from "node-fetch"; 28 | * import assertSnapshot from "snapshot-assertion"; 29 | * import TestDirector from "test-director"; 30 | * 31 | * const tests = new TestDirector(); 32 | * 33 | * tests.add("Get a todo.", async () => { 34 | * const response = await fetch("https://jsonplaceholder.typicode.com/todos/1"); 35 | * await assertSnapshot(await response.json(), "snapshots/todo.json"); 36 | * }); 37 | * 38 | * tests.run(); 39 | * ``` 40 | */ 41 | export default async function assertSnapshot( 42 | actualValue, 43 | snapshotFile, 44 | assertion = strictEqual 45 | ) { 46 | if (typeof actualValue !== "string") 47 | throw new TypeError("Argument 1 `actualValue` must be a string."); 48 | 49 | if (typeof snapshotFile !== "string" && !(snapshotFile instanceof URL)) 50 | throw new TypeError( 51 | "Argument 2 `snapshotFile` must be a string or `URL` instance." 52 | ); 53 | 54 | if (typeof assertion !== "function") 55 | throw new TypeError("Argument 3 `assertion` must be a function."); 56 | 57 | if (process.env.SAVE_SNAPSHOTS) await writeFile(snapshotFile, actualValue); 58 | else { 59 | let expectedValue; 60 | 61 | try { 62 | expectedValue = await readFile(snapshotFile, "utf8"); 63 | } catch (error) { 64 | throw typeof error === "object" && 65 | // Not `null`. 66 | error && 67 | // @ts-ignore It’s ok to check this property. 68 | error.code === "ENOENT" 69 | ? new Error( 70 | `Use the environment variable \`SAVE_SNAPSHOTS=1\` to create missing snapshot \`${snapshotFile}\`.` 71 | ) 72 | : error; 73 | } 74 | 75 | assertion(actualValue, expectedValue); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # snapshot-assertion changelog 2 | 3 | ## Next 4 | 5 | ### Major 6 | 7 | - Updated Node.js support to `^14.17.0 || ^16.0.0 || >= 18.0.0`. 8 | - Updated dev dependencies, some of which require newer Node.js versions than previously supported. 9 | 10 | ### Patch 11 | 12 | - Updated GitHub Actions CI config: 13 | - Run tests with Node.js v16, v18, v19. 14 | 15 | ## 5.0.0 16 | 17 | ### Major 18 | 19 | - Updated Node.js support to `^14.17.0 || ^16.0.0 || >= 18.0.0`. 20 | - Updated dev dependencies, some of which require newer Node.js versions than previously supported. 21 | - Removed the package `main` field. 22 | - Use the `node:` URL scheme for Node.js builtin module imports. 23 | - Migrated from the Node.js builtin module `fs` to `node:fs/promises`. 24 | 25 | ### Patch 26 | 27 | - Updated `jsconfig.json`: 28 | - Set `compilerOptions.maxNodeModuleJsDepth` to `10`. 29 | - Set `compilerOptions.module` to `nodenext`. 30 | - Updated ESLint config. 31 | - Updated GitHub Actions CI config: 32 | - Run tests with Node.js v14, v16, v18. 33 | - Updated `actions/checkout` to v3. 34 | - Updated `actions/setup-node` to v3. 35 | - Tweaked formatting of a JSDoc comment. 36 | - Revamped the readme: 37 | - Removed the badges. 38 | - Added a “Requirements” section. 39 | - Added information about TypeScript config and [optimal JavaScript module design](https://jaydenseric.com/blog/optimal-javascript-module-design). 40 | 41 | ## 4.0.2 42 | 43 | ### Patch 44 | 45 | - Updated dev dependencies. 46 | - Simplified dev dependencies and config for ESLint. 47 | - Removed the [`jsdoc-md`](https://npm.im/jsdoc-md) dev dependency and the related package scripts, replacing the readme “API” section with manually written “Examples” and “Exports” sections. 48 | - Updated `jsconfig.json` to disable TypeScript automatic type acquisition for the project. 49 | - Added a `license.md` MIT License file. 50 | 51 | ## 4.0.1 52 | 53 | ### Patch 54 | 55 | - Moved [`@types/node`](https://npm.im/@types/node) from package `devDependencies` to `dependencies`, using `*` for the version. 56 | - Updated dev dependencies. 57 | 58 | ## 4.0.0 59 | 60 | ### Major 61 | 62 | - Updated Node.js support to `^12.22.0 || ^14.17.0 || >= 16.0.0`. 63 | - Updated dev dependencies, some of which require newer Node.js versions than previously supported. 64 | - Removed `./package` from the package `exports` field; the full `package.json` filename must be used in a `require` path. 65 | - Renamed `index.mjs` to `assertSnapshot.mjs` and added it to the package `exports` field. 66 | - Renamed the function `snapshot` to `assertSnapshot`. 67 | - Renamed the function `assertSnapshot` argument 2 `snapshotFilePath` to `snapshotFile`, and allow it to also be a file `URL` instance. 68 | - Added runtime argument type checks. 69 | - Implemented TypeScript types via JSDoc comments. 70 | 71 | ### Patch 72 | 73 | - Simplified package scripts. 74 | - Added a package `docs-check` script that checks the readme API docs are up to date with the source JSDoc. 75 | - Check TypeScript types via a new package `types` script. 76 | - Also run GitHub Actions CI with Node.js v17, and drop v15. 77 | - Configured Prettier option `singleQuote` to the default, `false`. 78 | - Improved tests. 79 | - Documentation tweaks. 80 | 81 | ## 3.0.0 82 | 83 | ### Major 84 | 85 | - Updated Node.js support to `^12.20 || >= 14.13`. 86 | - Updated dev dependencies, some of which require newer Node.js versions than were previously supported. 87 | - Added a package `exports` field. 88 | - The API is now ESM in `.mjs` files instead of CJS in `.js` files, [accessible via `import` but not `require`](https://nodejs.org/dist/latest/docs/api/esm.html#esm_require). 89 | 90 | ### Minor 91 | 92 | - Added package `sideEffects` field. 93 | 94 | ### Patch 95 | 96 | - Stop using [`hard-rejection`](https://npm.im/hard-rejection) to detect unhandled `Promise` rejections in tests, as Node.js v15+ does this natively. 97 | - Simplified the package scripts now that [`jsdoc-md`](https://npm.im/jsdoc-md) v10 automatically generates a Prettier formatted readme. 98 | - Updated GitHub Actions CI config: 99 | - Also run tests with Node.js v16. 100 | - Updated `actions/checkout` to v2. 101 | - Updated `actions/setup-node` to v2. 102 | - Don’t specify the `CI` environment variable as it’s set by default. 103 | - Use `Promise.all` for faster tests. 104 | - Tweak whitespace formatting. 105 | - Readme tweaks. 106 | 107 | ## 2.0.0 108 | 109 | ### Major 110 | 111 | - Updated Node.js support to `^10.17.0 || ^12.0.0 || >= 13.7.0`. 112 | - Updated dev dependencies, some of which require newer Node.js versions than previously supported. 113 | 114 | ### Patch 115 | 116 | - Ensure GitHub Actions CI runs on pull request. 117 | - Also run GitHub Actions CI with Node.js v14 and v15, and not v13. 118 | - Simplified the GitHub Actions CI config with the [`npm install-test`](https://docs.npmjs.com/cli/v7/commands/npm-install-test) command. 119 | - Improved the package `prepare:prettier` and `test:prettier` scripts. 120 | - Configured Prettier option `semi` to the default, `true`. 121 | - Removed a now redundant ESLint rule config. 122 | - Removed `npm-debug.log` from the `.gitignore` file as npm [v4.2.0](https://github.com/npm/npm/releases/tag/v4.2.0)+ doesn’t create it in the current working directory. 123 | - Use HTTPS in an `.editorconfig` comment URL. 124 | - Use HTTPS in a URL within a `snapshot` function code example. 125 | - Documented how to `import` and `require` the `snapshot` function. 126 | 127 | ## 1.0.0 128 | 129 | Initial release. 130 | -------------------------------------------------------------------------------- /test.mjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | import { doesNotReject, rejects, strictEqual } from "node:assert"; 4 | import { execFile } from "node:child_process"; 5 | import { readFile, writeFile } from "node:fs/promises"; 6 | import { join } from "node:path"; 7 | import { fileURLToPath, pathToFileURL } from "node:url"; 8 | import { promisify } from "node:util"; 9 | 10 | import disposableDirectory from "disposable-directory"; 11 | import TestDirector from "test-director"; 12 | 13 | import assertSnapshot from "./assertSnapshot.mjs"; 14 | 15 | const execFilePromise = promisify(execFile); 16 | const tests = new TestDirector(); 17 | 18 | tests.add( 19 | "`assertSnapshot` with argument 1 `actualValue` not a string.", 20 | async () => { 21 | await rejects( 22 | assertSnapshot( 23 | // @ts-ignore Testing invalid. 24 | true, 25 | "snapshot.txt" 26 | ), 27 | new TypeError("Argument 1 `actualValue` must be a string.") 28 | ); 29 | } 30 | ); 31 | 32 | tests.add( 33 | "`assertSnapshot` with argument 2 `snapshotFile` not a string or `URL` instance.", 34 | async () => { 35 | await rejects( 36 | assertSnapshot( 37 | "a", 38 | // @ts-ignore Testing invalid. 39 | true 40 | ), 41 | new TypeError( 42 | "Argument 2 `snapshotFile` must be a string or `URL` instance." 43 | ) 44 | ); 45 | } 46 | ); 47 | 48 | tests.add( 49 | "`assertSnapshot` with argument 3 `assertion` not a function.", 50 | async () => { 51 | await rejects( 52 | assertSnapshot( 53 | "a", 54 | "snapshot.txt", 55 | // @ts-ignore Testing invalid. 56 | true 57 | ), 58 | new TypeError("Argument 3 `assertion` must be a function.") 59 | ); 60 | } 61 | ); 62 | 63 | tests.add( 64 | "`assertSnapshot` with snapshot file URL, invalid scheme.", 65 | async () => { 66 | await rejects(assertSnapshot("a", new URL("http://localhost")), TypeError); 67 | } 68 | ); 69 | 70 | tests.add( 71 | "`assertSnapshot` with snapshot file URL, assertion default, snapshot present.", 72 | async () => { 73 | await disposableDirectory(async (tempDirPath) => { 74 | const snapshotFileUrl = pathToFileURL(join(tempDirPath, "snapshot.txt")); 75 | 76 | await writeFile(snapshotFileUrl, "a"); 77 | 78 | await doesNotReject(assertSnapshot("a", snapshotFileUrl)); 79 | await rejects(assertSnapshot("b", snapshotFileUrl), { 80 | code: "ERR_ASSERTION", 81 | }); 82 | }); 83 | } 84 | ); 85 | 86 | tests.add( 87 | "`assertSnapshot` with snapshot file path, assertion default, snapshot file missing, `SAVE_SNAPSHOTS` env var missing.", 88 | async () => { 89 | await disposableDirectory(async (tempDirPath) => { 90 | const snapshotFilePath = join(tempDirPath, "snapshot.txt"); 91 | 92 | await rejects( 93 | assertSnapshot("a", snapshotFilePath), 94 | new Error( 95 | `Use the environment variable \`SAVE_SNAPSHOTS=1\` to create missing snapshot \`${snapshotFilePath}\`.` 96 | ) 97 | ); 98 | }); 99 | } 100 | ); 101 | 102 | tests.add( 103 | "`assertSnapshot` with snapshot file path, assertion default, snapshot file missing, `SAVE_SNAPSHOTS` env var present.", 104 | async () => { 105 | await disposableDirectory(async (tempDirPath) => { 106 | const snapshotFilePath = join(tempDirPath, "snapshot.txt"); 107 | const testPath = join(tempDirPath, "test.mjs"); 108 | const snapshotAssertionPath = fileURLToPath( 109 | new URL("./assertSnapshot.mjs", import.meta.url) 110 | ); 111 | 112 | await Promise.all([ 113 | writeFile(snapshotFilePath, "a"), 114 | writeFile( 115 | testPath, 116 | `import assertSnapshot from "${snapshotAssertionPath}"; 117 | 118 | assertSnapshot("b", "${snapshotFilePath}"); 119 | ` 120 | ), 121 | ]); 122 | 123 | await execFilePromise("node", [testPath], { 124 | env: { 125 | ...process.env, 126 | SAVE_SNAPSHOTS: "1", 127 | }, 128 | }); 129 | 130 | strictEqual(await readFile(snapshotFilePath, "utf8"), "b"); 131 | }); 132 | } 133 | ); 134 | 135 | tests.add( 136 | "`assertSnapshot` with snapshot file path, assertion default, snapshot present.", 137 | async () => { 138 | await disposableDirectory(async (tempDirPath) => { 139 | const snapshotFilePath = join(tempDirPath, "snapshot.txt"); 140 | 141 | await writeFile(snapshotFilePath, "a"); 142 | 143 | await doesNotReject(assertSnapshot("a", snapshotFilePath)); 144 | await rejects(assertSnapshot("b", snapshotFilePath), { 145 | code: "ERR_ASSERTION", 146 | }); 147 | }); 148 | } 149 | ); 150 | 151 | tests.add( 152 | "`assertSnapshot` with snapshot file path, assertion custom, snapshot present.", 153 | async () => { 154 | await disposableDirectory(async (tempDirPath) => { 155 | const snapshotFilePath = join(tempDirPath, "snapshot.json"); 156 | 157 | await writeFile(snapshotFilePath, "a"); 158 | 159 | const errorMessage = "Different values."; 160 | 161 | /** 162 | * Asserts one value is another. 163 | * @param {unknown} actual Actual value. 164 | * @param {unknown} expected Expected value. 165 | */ 166 | function assertIs(actual, expected) { 167 | if (!Object.is(actual, expected)) throw new Error(errorMessage); 168 | } 169 | 170 | await doesNotReject(assertSnapshot("a", snapshotFilePath, assertIs)); 171 | await rejects( 172 | assertSnapshot("b", snapshotFilePath, assertIs), 173 | new Error(errorMessage) 174 | ); 175 | }); 176 | } 177 | ); 178 | 179 | tests.run(); 180 | --------------------------------------------------------------------------------