UNPKG

@moonwall/cli

Version:

Testing framework for the Moon family of projects

134 lines (133 loc) 4.06 kB
// src/internal/testIdParser.ts import { Lang, parse, findInFiles } from "@ast-grep/napi"; function extractIdFromObject(objNode) { for (const child of objNode.children()) { if (child.kind() === "pair") { const key = child.field("key"); const value = child.field("value"); if (key?.text() === "id" && value) { return value.text().replace(/^['"`]|['"`]$/g, ""); } } } return void 0; } function findIdValueNode(objNode) { for (const child of objNode.children()) { if (child.kind() === "pair") { const key = child.field("key"); const value = child.field("value"); if (key?.text() === "id" && value) { return value; } } } return void 0; } function extractTestIds(fileContent) { const ast = parse(Lang.TypeScript, fileContent); const root = ast.root(); const describeSuiteCall = root.find("describeSuite($OPTS)"); let suiteId; if (describeSuiteCall) { const optsNode = describeSuiteCall.getMatch("OPTS"); if (optsNode && optsNode.kind() === "object") { suiteId = extractIdFromObject(optsNode); } } const testIds = []; const itCalls = root.findAll("it($OPTS)"); for (const itCall of itCalls) { const optsNode = itCall.getMatch("OPTS"); if (optsNode && optsNode.kind() === "object") { const testId = extractIdFromObject(optsNode); if (testId) { testIds.push(testId); } } } return { suiteId, testIds }; } function replaceSuiteId(fileContent, newId) { const ast = parse(Lang.TypeScript, fileContent); const root = ast.root(); const describeSuiteCall = root.find("describeSuite($OPTS)"); if (!describeSuiteCall) { return void 0; } const optsNode = describeSuiteCall.getMatch("OPTS"); if (!optsNode || optsNode.kind() !== "object") { return void 0; } const idValueNode = findIdValueNode(optsNode); if (!idValueNode) { return void 0; } const originalText = idValueNode.text(); const quoteChar = originalText[0]; const edit = idValueNode.replace(`${quoteChar}${newId}${quoteChar}`); return root.commitEdits([edit]); } function hasSuiteDefinition(fileContent) { const ast = parse(Lang.TypeScript, fileContent); const root = ast.root(); return root.find("describeSuite($$$)") !== null; } async function findTestFilesMatchingPattern(testDirs, includeGlobs, idPattern) { const matches = []; let processedCount = 0; let expectedCount; await new Promise((resolve, reject) => { findInFiles( Lang.TypeScript, { paths: testDirs, matcher: { rule: { pattern: "describeSuite($OPTS)" } }, languageGlobs: includeGlobs }, (err, nodes) => { if (err) { reject(err); return; } if (nodes.length === 0) return; const node = nodes[0]; const filePath = node.getRoot().filename(); const root = node.getRoot().root(); const optsNode = node.getMatch("OPTS"); if (!optsNode || optsNode.kind() !== "object") return; const suiteId = extractIdFromObject(optsNode); if (!suiteId) return; const testIds = []; const itCalls = root.findAll("it($OPTS)"); for (const itCall of itCalls) { const itOpts = itCall.getMatch("OPTS"); if (itOpts && itOpts.kind() === "object") { const testId = extractIdFromObject(itOpts); if (testId) testIds.push(testId); } } const allIds = [suiteId, ...testIds.map((tid) => suiteId + tid)]; if (allIds.some((id) => idPattern.test(id))) { matches.push(filePath); } processedCount++; if (expectedCount !== void 0 && processedCount >= expectedCount) { resolve(); } } ).then((count) => { expectedCount = count; if (count === 0 || processedCount >= count) { resolve(); } }).catch(reject); }); return matches; } export { extractTestIds, findTestFilesMatchingPattern, hasSuiteDefinition, replaceSuiteId };