diff --git a/packages/cli/test/functional/testUtil/compare.ts b/packages/cli/test/functional/testUtil/compare.ts index c631b14f7b..91e7dafa89 100644 --- a/packages/cli/test/functional/testUtil/compare.ts +++ b/packages/cli/test/functional/testUtil/compare.ts @@ -27,12 +27,12 @@ function _readFileSync(...paths: string[]) { } /** - * Filters out .page-vue-render.js files from the list of file paths. + * Filters out .page-vue-render.js and .DS_Store files from the list of file paths. * @param {string[]} filePaths - List of file paths - * @returns {string[]} Filtered list without *.page-vue-render.js files + * @returns {string[]} Filtered list without generated render files and macOS metadata */ -function filterPageVueRenderFiles(filePaths: string[]) { - return filePaths.filter(p => !p.endsWith('.page-vue-render.js')); +function filterIgnoredFiles(filePaths: string[]) { + return filePaths.filter(p => !p.endsWith('.page-vue-render.js') && !p.endsWith('.DS_Store')); } /** @@ -87,8 +87,8 @@ function compare(root: string, expectedSiteRelativePath = 'expected', siteRelati // Vue render JS files (*.page-vue-render.js) are not committed to version control, // so we exclude them from the comparison to avoid false positive diffs. // Note: Every non-includes .html file has a corresponding js render binary file - actualPaths = filterPageVueRenderFiles(actualPaths); - expectedPaths = filterPageVueRenderFiles(expectedPaths); + actualPaths = filterIgnoredFiles(actualPaths); + expectedPaths = filterIgnoredFiles(expectedPaths); // Check for file existence of ignoredPaths and that they are present in actualPaths if (ignoredPaths.length !== 0 && !_.isEqual(_.intersection(ignoredPaths, actualPaths), ignoredPaths)) { @@ -100,9 +100,12 @@ function compare(root: string, expectedSiteRelativePath = 'expected', siteRelati expectedPaths = expectedPaths.filter(p => !ignoredPaths.includes(p)); let error = false; - if (expectedPaths.length !== actualPaths.length) { - throw new Error('Unequal number of files! ' - + `Expected: ${expectedPaths.length}, Actual: ${actualPaths.length}`); + const missingPaths = _.difference(expectedPaths, actualPaths); + const unexpectedPaths = _.difference(actualPaths, expectedPaths); + if (missingPaths.length || unexpectedPaths.length) { + throw new Error('Different files built!' + + `\nMissing files: ${JSON.stringify(missingPaths)}` + + `\nUnexpected files: ${JSON.stringify(unexpectedPaths)}`); } /* eslint-disable no-continue */ @@ -110,10 +113,6 @@ function compare(root: string, expectedSiteRelativePath = 'expected', siteRelati const expectedFilePath = expectedPaths[i]; const actualFilePath = actualPaths[i]; - if (expectedFilePath !== actualFilePath) { - throw new Error(`Different files built! Expected: ${expectedFilePath}, Actual: ${actualFilePath}`); - } - if (isBinary(expectedFilePath) || TEST_BLACKLIST.ignores(expectedFilePath)) { continue; } diff --git a/packages/cli/test/unit/compare.test.ts b/packages/cli/test/unit/compare.test.ts new file mode 100644 index 0000000000..e21240ce7d --- /dev/null +++ b/packages/cli/test/unit/compare.test.ts @@ -0,0 +1,24 @@ +import fs from 'fs'; +import os from 'os'; +import path from 'path'; +import { compare } from '../functional/testUtil/compare.js'; + +test('compare ignores nested .DS_Store files and reports path differences', () => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'markbind-compare-')); + const expectedDirectory = path.join(root, 'expected'); + const actualDirectory = path.join(root, '_site'); + try { + fs.mkdirSync(expectedDirectory); + fs.mkdirSync(path.join(actualDirectory, 'nested'), { recursive: true }); + fs.writeFileSync(path.join(expectedDirectory, 'index.html'), 'same'); + fs.writeFileSync(path.join(actualDirectory, 'index.html'), 'same'); + fs.writeFileSync(path.join(actualDirectory, 'nested', '.DS_Store'), 'metadata'); + expect(() => compare(root)).not.toThrow(); + fs.writeFileSync(path.join(expectedDirectory, 'missing.html'), ''); + fs.writeFileSync(path.join(actualDirectory, 'unexpected.html'), ''); + expect(() => compare(root)) + .toThrow('Missing files: ["missing.html"]\nUnexpected files: ["unexpected.html"]'); + } finally { + fs.rmSync(root, { recursive: true, force: true }); + } +});