diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index e78f3df..d918be4 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [18.x] + node-version: [20.x] fail-fast: false steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 diff --git a/src/utils/getTestFrameworkName.ts b/src/utils/getTestFrameworkName.ts index bbd1d66..e11fe2e 100644 --- a/src/utils/getTestFrameworkName.ts +++ b/src/utils/getTestFrameworkName.ts @@ -2,12 +2,12 @@ import type { PackageJSON } from "@nodesecure/npm-types"; // CONSTANTS -const kNodeTestRunnerRegex = /(?:node\s+--test|tsx)/; +const kNodeTestRunnerRegex = /[node|tsx]\s+.*--test/; export function getTestFrameworkName(packageJson: PackageJSON): string { const { devDependencies: deps = {}, scripts = {} } = packageJson; - if (kNodeTestRunnerRegex.test(scripts.test)) { + if (kNodeTestRunnerRegex.test(scripts.test) || isUsingNodeTestRunner(scripts, "test")) { return "node:test"; } if ("ava" in deps) { @@ -16,7 +16,7 @@ export function getTestFrameworkName(packageJson: PackageJSON): string { if ("jest" in deps) { return "jest"; } - if ("japa" in deps) { + if ("@japa/runner" in deps) { return "japa"; } if ("tape" in deps) { @@ -28,3 +28,38 @@ export function getTestFrameworkName(packageJson: PackageJSON): string { return "N/A"; } + +function isUsingNodeTestRunner(scripts: Record, scriptName: string, visited = new Set()): boolean { + if (visited.has(scriptName)) { + return false; + } + + const scriptCommand = scripts[scriptName]; + if (scriptCommand && kNodeTestRunnerRegex.test(scriptCommand)) { + return true; + } + + const calledScripts = extractCalledScripts(scriptCommand); + + for (const calledScript of calledScripts) { + if (isUsingNodeTestRunner(scripts, calledScript, visited)) { + return true; + } + } + + return false; +} + +function extractCalledScripts(scriptCommand: string): string[] { + const npmRunRegex = /npm run (\S+)/g; + + const calledScripts: string[] = []; + + let match: RegExpExecArray | null; + + while ((match = npmRunRegex.exec(scriptCommand)) !== null) { + calledScripts.push(match[1]); + } + + return calledScripts; +} diff --git a/test/getTestFrameworkName.spec.ts b/test/getTestFrameworkName.spec.ts index 229aef5..a39a71e 100644 --- a/test/getTestFrameworkName.spec.ts +++ b/test/getTestFrameworkName.spec.ts @@ -7,11 +7,13 @@ import { getTestFrameworkName } from "../src/utils"; describe("getTestFrameworkName()", () => { it("Should return N/A", () => { - assert.equal(getTestFrameworkName({ test: "2.0.0", test2: "3.0.0" }), "N/A"); + assert.equal(getTestFrameworkName({ name: "test", version: "1.0.0", test: "2.0.0", test2: "3.0.0" }), "N/A"); }); it("Should return ava", () => { const packageJson = { + name: "test", + version: "1.0.0", devDependencies: { ava: "^2.0.0" } @@ -21,6 +23,8 @@ describe("getTestFrameworkName()", () => { it("Should return jest", () => { const packageJson = { + name: "test", + version: "1.0.0", devDependencies: { jest: "^2.0.0" } @@ -30,8 +34,10 @@ describe("getTestFrameworkName()", () => { it("Should return japa", () => { const packageJson = { + name: "test", + version: "1.0.0", devDependencies: { - japa: "^2.0.0" + "@japa/runner": "^2.0.0" } }; assert.equal(getTestFrameworkName(packageJson), "japa"); @@ -39,6 +45,8 @@ describe("getTestFrameworkName()", () => { it("Should return tape", () => { const packageJson = { + name: "test", + version: "1.0.0", devDependencies: { tape: "^2.0.0" } @@ -48,6 +56,8 @@ describe("getTestFrameworkName()", () => { it("Should return mocha", () => { const packageJson = { + name: "test", + version: "1.0.0", devDependencies: { mocha: "^2.0.0" } @@ -56,12 +66,39 @@ describe("getTestFrameworkName()", () => { assert.equal(getTestFrameworkName(packageJson), "mocha"); }); - it("Should return node:test", () => { - const packageJson = { - scripts: { - test: "node --test" - } - }; - assert.equal(getTestFrameworkName(packageJson), "node:test"); + describe("node:test", () => { + it("Should return node:test for test script", () => { + const packageJson = { + name: "test", + version: "1.0.0", + scripts: { + test: "node --test" + } + }; + assert.equal(getTestFrameworkName(packageJson), "node:test"); + }); + + it("Should return node:test when a nested script uses node --test", () => { + const packageJson = { + name: "test", + version: "1.0.0", + scripts: { + test: "c8 --all --src ./src -r html npm run test-only", + "test-only": "glob -c \"node --loader=esmock --no-warnings --test-concurrency 1 --test\" \"test/**/*.test.js\"" + } + }; + assert.equal(getTestFrameworkName(packageJson), "node:test"); + }); + + it("Should return node:test for test script when using tsx", () => { + const packageJson = { + name: "test", + version: "1.0.0", + scripts: { + test: "tsx --test" + } + }; + assert.equal(getTestFrameworkName(packageJson), "node:test"); + }); }); });