diff --git a/clis/linux-do/topic-content.test.js b/clis/linux-do/topic-content.test.js index d0dcd800e..3e4aa4dd9 100644 --- a/clis/linux-do/topic-content.test.js +++ b/clis/linux-do/topic-content.test.js @@ -51,9 +51,9 @@ describe('linux-do topic-content', () => { expect(command?.columns).toEqual(['content']); }); it('keeps topic adapter as a summarized first-page reader after the split', () => { - const topicTs = fs.readFileSync(new URL('./topic.ts', import.meta.url), 'utf8'); - expect(topicTs).not.toContain('main_only'); - expect(topicTs).toContain('slice(0, 200)'); - expect(topicTs).toContain('帖子首页摘要和回复'); + const topicSource = fs.readFileSync(new URL('./topic.js', import.meta.url), 'utf8'); + expect(topicSource).not.toContain('main_only'); + expect(topicSource).toContain('slice(0, 200)'); + expect(topicSource).toContain('帖子首页摘要和回复'); }); }); diff --git a/scripts/check-doc-coverage.sh b/scripts/check-doc-coverage.sh index 9174721f3..aea12bdbc 100755 --- a/scripts/check-doc-coverage.sh +++ b/scripts/check-doc-coverage.sh @@ -30,6 +30,11 @@ for adapter_dir in "$SRC_DIR"/*/; do adapter_name="$(basename "$adapter_dir")" # Skip internal directories (e.g., _shared) [[ "$adapter_name" == _* ]] && continue + # Skip helper-only directories that do not expose any top-level adapter commands. + top_level_files="$(find "$adapter_dir" -maxdepth 1 -type f | awk -F/ '{print $NF}')" + if [[ -n "$top_level_files" ]] && ! printf '%s\n' "$top_level_files" | grep -qv '^_'; then + continue + fi total=$((total + 1)) # Check if doc exists in browser/ or desktop/ subdirectories diff --git a/src/ci-regressions.test.ts b/src/ci-regressions.test.ts new file mode 100644 index 000000000..ebf6dc160 --- /dev/null +++ b/src/ci-regressions.test.ts @@ -0,0 +1,51 @@ +import { execFileSync } from 'node:child_process'; +import * as fs from 'node:fs'; +import * as os from 'node:os'; +import * as path from 'node:path'; +import { afterEach, describe, expect, it } from 'vitest'; + +const tempDirs: string[] = []; + +afterEach(() => { + for (const dir of tempDirs.splice(0)) { + fs.rmSync(dir, { recursive: true, force: true }); + } +}); + +describe('CI regression coverage', () => { + it('ignores helper-only adapter directories when checking docs coverage', () => { + const fixtureRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'opencli-doc-coverage-')); + tempDirs.push(fixtureRoot); + + const scriptsDir = path.join(fixtureRoot, 'scripts'); + const clisDir = path.join(fixtureRoot, 'clis', 'slock'); + const docsBrowserDir = path.join(fixtureRoot, 'docs', 'adapters', 'browser'); + const docsDesktopDir = path.join(fixtureRoot, 'docs', 'adapters', 'desktop'); + + fs.mkdirSync(scriptsDir, { recursive: true }); + fs.mkdirSync(clisDir, { recursive: true }); + fs.mkdirSync(docsBrowserDir, { recursive: true }); + fs.mkdirSync(docsDesktopDir, { recursive: true }); + + fs.copyFileSync( + path.join(process.cwd(), 'scripts', 'check-doc-coverage.sh'), + path.join(scriptsDir, 'check-doc-coverage.sh'), + ); + fs.writeFileSync( + path.join(clisDir, '_utils.js'), + 'export const helper = () => "noop";\n', + ); + + const output = execFileSync( + 'bash', + [path.join(scriptsDir, 'check-doc-coverage.sh'), '--strict'], + { + cwd: fixtureRoot, + encoding: 'utf8', + }, + ); + + expect(output).toContain('Doc Coverage: 0/0 adapters documented'); + expect(output).toContain('All adapters have documentation'); + }); +}); diff --git a/vitest.config.ts b/vitest.config.ts index 08834de62..e05db4a7a 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -9,7 +9,7 @@ export default defineConfig({ test: { name: 'unit', include: ['src/**/*.test.ts'], - exclude: ['clis/**/*.test.ts'], + exclude: ['src/clis/**/*.test.ts'], sequence: { groupOrder: 0 }, }, }, @@ -23,7 +23,7 @@ export default defineConfig({ { test: { name: 'adapter', - include: ['clis/**/*.test.ts'], + include: ['clis/**/*.test.js', 'src/clis/**/*.test.ts'], sequence: { groupOrder: 1 }, }, },