diff --git a/package-lock.json b/package-lock.json index 99a692b..fef8af2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "glob": "^10.3.4", "husky": "^8.0.3", "jest": "^29.6.4", + "jest-file-snapshot": "^0.7.0", "lint-staged": "^13.1.0", "npm-run-all": "^4.1.5", "prettier": "3.0.3", @@ -4205,6 +4206,34 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -6003,6 +6032,95 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-file-snapshot": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/jest-file-snapshot/-/jest-file-snapshot-0.7.0.tgz", + "integrity": "sha512-HkuzLleG2bEVz5nu7ey3SkiBeBvTz8IhY0mJ9W+9BO4xiIi3nVUfB81jFLWS7PMPpeBVgkpW0G1YyrYKi3Hcxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "filenamify": "^4.3.0", + "jest-diff": "^29.7.0", + "mkdirp": "^3.0.1" + } + }, + "node_modules/jest-file-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-file-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-file-snapshot/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-file-snapshot/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-file-snapshot/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-file-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jest-get-type": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", @@ -7620,6 +7738,22 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -9669,6 +9803,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -9770,6 +9917,19 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/trough": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", diff --git a/package.json b/package.json index c2a86ac..8a246c5 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "glob": "^10.3.4", "husky": "^8.0.3", "jest": "^29.6.4", + "jest-file-snapshot": "^0.7.0", "lint-staged": "^13.1.0", "npm-run-all": "^4.1.5", "prettier": "3.0.3", diff --git a/test.ts b/test.ts index 405353b..5d910d5 100644 --- a/test.ts +++ b/test.ts @@ -1,5 +1,6 @@ -import { readFile, writeFile } from 'fs/promises' +import { readFile } from 'fs/promises' import { globSync } from 'glob' +import { toMatchFile } from 'jest-file-snapshot' import type { Nodes } from 'mdast' import rehypeStringify from 'rehype-stringify' import remarkParse from 'remark-parse' @@ -9,10 +10,6 @@ import { removePosition } from 'unist-util-remove-position' import { rehypeAstro, remarkAstro } from './src' -async function read(filename: string) { - return await readFile(filename, { encoding: 'utf-8' }) -} - function remarkRemovePosition() { return (tree: Nodes) => { removePosition(tree) @@ -24,51 +21,28 @@ function remarkJson(this: Processor) { this.Compiler = (root) => JSON.stringify(root, undefined, 2) } -function splitLines(s: string) { - return s.split(/\r?\n/) -} - -function remarkProcessor() { - return unified() +const processors = { + json: unified() .use(remarkParse) .use(remarkRemovePosition) .use(remarkAstro) - .use(remarkJson) -} - -function rehypeProcessor() { - return unified() + .use(remarkJson), + html: unified() .use(remarkParse) .use(remarkRehype) .use(rehypeAstro) - .use(rehypeStringify) + .use(rehypeStringify), } -describe.each([ - ['remarkAstro', 'json', remarkProcessor], - ['rehypeAstro', 'html', rehypeProcessor], -])('%s', (_, ext, processor) => { - test.each(globSync('src/replacements/*/test.md'))( - '%s', - async (inputFilename) => { - const result = ( - await processor().process(await readFile(inputFilename)) - ).value.toString() +expect.extend({ toMatchFile }) + +describe.each(globSync('src/replacements/*/test.md'))('convert %s', (path) => { + const stem = path.replace(/\.md$/, '') + let input: Buffer - const expectedFilename = inputFilename.replace(/\.md$/, `.${ext}`) - let expected - try { - expected = await read(expectedFilename) - } catch { - const draftFilename = inputFilename.replace(/\.md$/, `.draft.${ext}`) - await writeFile(draftFilename, result) - throw new Error( - `Could not read the expected results file, '${expectedFilename}'. Please review the draft results file at '${draftFilename}'. If the results are correct, then rename it to '${expectedFilename}' and add it to version control.` - ) - } + beforeAll(async () => (input = await readFile(path))) - // Compare lines, not the strings themselves, due to newlines on Windows - expect(splitLines(result)).toStrictEqual(splitLines(expected)) - } + test.each(Object.entries(processors))(`to ${stem}.%s`, (ext, proc) => + expect(proc.processSync(input).value).toMatchFile(`${stem}.${ext}`) ) })