import fs from "node:fs"; import path from "node:path"; import fg from "fast-glob"; import { parseTestCasesFromDoc, parseItDescriptionsFromTest } from "../../lib/parse-doc-test-cases"; import type { CheckError, SyncCheckResult } from "../../lib/sync-check/shared"; import { appTestCaseCategories } from "./categories"; function resolveStoryTestPath(docPath: string, testDir: string): string | null { const regex = /^(.+)\/docs\/business-flow\/([^/]+)\/story\/([^/]+)\.md$/; const match = regex.exec(docPath); if (!match) return null; const [, appPath, flow, name] = match; return `${appPath}/${testDir}/${flow}/${name}.test.ts`; } export async function runAppTestCaseSyncCheck( appRoot: string, cwd: string, ): Promise { const errors: CheckError[] = []; let filesChecked = 0; const config = appTestCaseCategories(appRoot); const docPaths = await fg(config.docPattern, { cwd }); for (const docPath of docPaths) { const docFullPath = path.join(cwd, docPath); const docContent = fs.readFileSync(docFullPath, "utf-8"); filesChecked += 1; const docTestCases = parseTestCasesFromDoc(docContent); if (docTestCases.length === 0) continue; const testPath = resolveStoryTestPath(docPath, config.testDir); if (!testPath) continue; const testFullPath = path.join(cwd, testPath); if (!fs.existsSync(testFullPath)) { errors.push({ type: "missing-test-file", category: config.name, docPath, sourcePath: testPath, expectedBasename: path.basename(testPath), }); continue; } filesChecked += 1; const testContent = fs.readFileSync(testFullPath, "utf-8"); const itDescriptions = parseItDescriptionsFromTest(testContent); const docSet = new Set(docTestCases); const testSet = new Set(itDescriptions); for (const docCase of docSet) { if (!testSet.has(docCase)) { errors.push({ type: "missing-test-case", category: config.name, docPath, sourcePath: testPath, expectedBasename: docCase, }); } } for (const testCase of testSet) { if (!docSet.has(testCase)) { errors.push({ type: "extra-test-case", category: config.name, docPath, sourcePath: testPath, expectedBasename: testCase, }); } } } return { errors, filesChecked }; }