|
| 1 | +import assert from 'node:assert/strict'; |
| 2 | +import { resolve } from 'node:path'; |
| 3 | +import { describe, it, mock } from 'node:test'; |
| 4 | + |
| 5 | +const runGenerators = mock.fn(async () => {}); |
| 6 | + |
| 7 | +mock.module('../../../src/generators.mjs', { |
| 8 | + defaultExport: () => ({ runGenerators }), |
| 9 | +}); |
| 10 | + |
| 11 | +mock.module('../../../src/parsers/markdown.mjs', { |
| 12 | + namedExports: { |
| 13 | + parseChangelog: async () => [{ version: 'v1.0.0', lts: false }], |
| 14 | + parseIndex: async () => [{ section: 'fs', api: 'fs' }], |
| 15 | + }, |
| 16 | +}); |
| 17 | + |
| 18 | +mock.module('../../../src/parsers/json.mjs', { |
| 19 | + namedExports: { |
| 20 | + parseTypeMap: async () => ({ Foo: 'foo.html' }), |
| 21 | + }, |
| 22 | +}); |
| 23 | + |
| 24 | +const logger = { |
| 25 | + debug: mock.fn(), |
| 26 | +}; |
| 27 | + |
| 28 | +mock.module('../../../src/logger/index.mjs', { |
| 29 | + defaultExport: logger, |
| 30 | +}); |
| 31 | + |
| 32 | +mock.module('semver', { |
| 33 | + namedExports: { |
| 34 | + coerce: v => ({ raw: v, major: 1, minor: 2, patch: 3 }), |
| 35 | + }, |
| 36 | +}); |
| 37 | + |
| 38 | +// Ensure the prompt option label builder (map callback) runs during module load. |
| 39 | +mock.module('../../../src/generators/index.mjs', { |
| 40 | + namedExports: { |
| 41 | + publicGenerators: { |
| 42 | + web: { name: 'web', version: '1.2.3', description: 'Web output' }, |
| 43 | + }, |
| 44 | + }, |
| 45 | +}); |
| 46 | + |
| 47 | +const cmd = (await import('../generate.mjs')).default; |
| 48 | + |
| 49 | +describe('bin/commands/generate', () => { |
| 50 | + it('calls runGenerators with normalized options', async () => { |
| 51 | + await cmd.action({ |
| 52 | + target: ['web'], |
| 53 | + input: ['doc/api/*.md'], |
| 54 | + ignore: ['**/deprecated/**'], |
| 55 | + output: 'out', |
| 56 | + version: 'v20.0.0', |
| 57 | + changelog: 'CHANGELOG.md', |
| 58 | + gitRef: 'https://example.test/ref', |
| 59 | + threads: '0', |
| 60 | + chunkSize: 'not-a-number', |
| 61 | + index: 'doc/api/index.md', |
| 62 | + typeMap: 'doc/api/type_map.json', |
| 63 | + }); |
| 64 | + |
| 65 | + assert.equal(logger.debug.mock.callCount(), 2); |
| 66 | + assert.equal(runGenerators.mock.callCount(), 1); |
| 67 | + |
| 68 | + const args = runGenerators.mock.calls[0].arguments[0]; |
| 69 | + |
| 70 | + assert.deepEqual(args.generators, ['web']); |
| 71 | + assert.deepEqual(args.input, ['doc/api/*.md']); |
| 72 | + assert.deepEqual(args.ignore, ['**/deprecated/**']); |
| 73 | + assert.equal(args.output, resolve('out')); |
| 74 | + |
| 75 | + // coerce() mocked: returns object with raw |
| 76 | + assert.equal(args.version.raw, 'v20.0.0'); |
| 77 | + |
| 78 | + // min thread/chunkSize should be 1 when parseInt fails or < 1 |
| 79 | + assert.equal(args.threads, 1); |
| 80 | + assert.equal(args.chunkSize, 1); |
| 81 | + |
| 82 | + assert.equal(args.gitRef, 'https://example.test/ref'); |
| 83 | + assert.deepEqual(args.releases, [{ version: 'v1.0.0', lts: false }]); |
| 84 | + assert.deepEqual(args.index, [{ section: 'fs', api: 'fs' }]); |
| 85 | + assert.deepEqual(args.typeMap, { Foo: 'foo.html' }); |
| 86 | + }); |
| 87 | +}); |
0 commit comments