diff --git a/src/generators/ast/__tests__/generate.test.mjs b/src/generators/ast/__tests__/generate.test.mjs new file mode 100644 index 00000000..ef416567 --- /dev/null +++ b/src/generators/ast/__tests__/generate.test.mjs @@ -0,0 +1,36 @@ +import assert from 'node:assert/strict'; +import { describe, it, mock } from 'node:test'; + +// Mock dependencies +const mockReadFile = mock.fn(); +mock.module('node:fs/promises', { + namedExports: { readFile: mockReadFile }, +}); + +// Mock other internal modules as needed +// From src/generators/ast/__tests__/ to src/utils/configuration/index.mjs is ../../../utils/configuration/index.mjs +mock.module('../../../utils/configuration/index.mjs', { + defaultExport: () => ({ ast: { input: 'docs/*.md' } }), +}); + +const { processChunk } = await import('../generate.mjs'); + +describe('ast/generate.mjs error handling', () => { + it('should bubble readFile errors to the caller', async () => { + const error = new Error('FS_ERROR'); + mockReadFile.mock.mockImplementation(async () => { + throw error; + }); + + const inputSlice = ['test.md']; + const itemIndices = [0]; + + await assert.rejects( + async () => await processChunk(inputSlice, itemIndices), + err => { + assert.strictEqual(err, error); + return true; + } + ); + }); +}); diff --git a/src/generators/ast/generate.mjs b/src/generators/ast/generate.mjs index 65bcdb66..e8ccf8fa 100644 --- a/src/generators/ast/generate.mjs +++ b/src/generators/ast/generate.mjs @@ -36,7 +36,7 @@ export async function processChunk(inputSlice, itemIndices) { results.push({ tree: remarkProcessor.parse(vfile), - file: { stem: vfile.stem, basename: vfile.basename }, + file: { stem: vfile.stem, basename: vfile.basename, path }, }); } diff --git a/src/generators/metadata/__tests__/generate.test.mjs b/src/generators/metadata/__tests__/generate.test.mjs new file mode 100644 index 00000000..01511959 --- /dev/null +++ b/src/generators/metadata/__tests__/generate.test.mjs @@ -0,0 +1,53 @@ +import assert from 'node:assert/strict'; +import { describe, it, mock } from 'node:test'; + +// Mock dependencies +const mockParseApiDoc = mock.fn(); +mock.module('../utils/parse.mjs', { + namedExports: { parseApiDoc: mockParseApiDoc }, +}); + +// Mock configuration and URL utils +// From src/generators/metadata/__tests__/ to src/utils/ is ../../../utils/ +mock.module('../../../utils/configuration/index.mjs', { + defaultExport: () => ({ metadata: { typeMap: 'typeMap.json' } }), +}); +mock.module('../../../utils/url.mjs', { + namedExports: { importFromURL: async () => ({}) }, +}); + +const { processChunk } = await import('../generate.mjs'); + +describe('metadata/generate.mjs error handling', () => { + it('should bubble parsing errors to the caller', async () => { + const error = new Error('PARSE_ERROR'); + mockParseApiDoc.mock.mockImplementation(() => { + throw error; + }); + + const fullInput = [{ file: { path: 'docs/api/fs.md', basename: 'fs.md' } }]; + const itemIndices = [0]; + + await assert.rejects( + async () => await processChunk(fullInput, itemIndices, {}), + err => { + assert.strictEqual(err, error); + return true; + } + ); + }); + + it('should preserve non-Error throws from parseApiDoc', async () => { + mockParseApiDoc.mock.mockImplementation(() => { + throw 'PARSE_ERROR'; + }); + + await assert.rejects( + async () => await processChunk([{}], [0], {}), + err => { + assert.strictEqual(err, 'PARSE_ERROR'); + return true; + } + ); + }); +});