diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index de73ee8ad..bc99aa5c6 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -57,14 +57,8 @@ jobs: shell: bash run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns - - name: Run tests (node20) - if: ${{ matrix.node == '20' }} - shell: bash - run: npm run test:node20 - - name: Run tests shell: bash - if: ${{ matrix.node != '20' }} run: npm run test:no-build # Gating job for branch protection. diff --git a/GEMINI.md b/GEMINI.md index d0eac03eb..fad71d480 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -1,5 +1,6 @@ # Instructions -- use `npm run build` to run tsc and test build. -- use `npm run test` to run tests, run all tests to verify correctness. -- use only scripts from `package.json` to run commands. +- Use only scripts from `package.json` to run commands. +- Use `npm run build` to run tsc and test build. +- Use `npm run test` to build and run tests, run all tests to verify correctness. +- use `npm run test path-to-test.ts` to build and run a single test file, for example, `npm run test tests/McpContext.test.ts`. diff --git a/package.json b/package.json index 562c5961e..630fb103c 100644 --- a/package.json +++ b/package.json @@ -16,12 +16,10 @@ "docs:generate": "node --experimental-strip-types scripts/generate-docs.ts", "start": "npm run build && node build/src/index.js", "start-debug": "DEBUG=mcp:* DEBUG_COLORS=false npm run build && node build/src/index.js", - "test:node20": "node --import ./build/tests/setup.js --test-reporter spec --test-force-exit --test build/tests", - "test:no-build": "node --import ./build/tests/setup.js --no-warnings=ExperimentalWarning --experimental-print-required-tla --test-reporter spec --test-force-exit --test \"build/tests/**/*.test.js\"", "test": "npm run build && npm run test:no-build", - "test:only": "npm run build && npm run test:only:no-build", - "test:only:no-build": "node --import ./build/tests/setup.js --no-warnings=ExperimentalWarning --test-reporter spec --test-force-exit --test --test-only \"build/tests/**/*.test.js\"", - "test:update-snapshots": "npm run build && node --import ./build/tests/setup.js --no-warnings=ExperimentalWarning --test-force-exit --test --test-update-snapshots \"build/tests/**/*.test.js\"", + "test:no-build": "node scripts/test.mjs", + "test:only": "npm run build && node scripts/test.mjs --test-only", + "test:update-snapshots": "npm run build && node scripts/test.mjs --test-update-snapshots", "prepare": "node --experimental-strip-types scripts/prepare.ts", "verify-server-json-version": "node --experimental-strip-types scripts/verify-server-json-version.ts" }, diff --git a/scripts/test.mjs b/scripts/test.mjs new file mode 100644 index 000000000..5e061537b --- /dev/null +++ b/scripts/test.mjs @@ -0,0 +1,59 @@ +/** + * @license + * Copyright 2026 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +// Note: can be converted to ts file once node 20 support is dropped. +// Node 20 does not support --experimental-strip-types flag. + +import {spawn} from 'node:child_process'; +import path from 'node:path'; +import process from 'node:process'; + +const args = process.argv.slice(2); +const userArgs = args.filter(arg => !arg.startsWith('-')); +const flags = args.filter(arg => arg.startsWith('-')); + +const files = []; + +if (userArgs.length > 0) { + for (const arg of userArgs) { + // Map .ts files to build/ .js files + let testPath = arg; + if (testPath.endsWith('.ts')) { + testPath = testPath.replace(/\.ts$/, '.js'); + if (!testPath.startsWith('build/')) { + testPath = path.join('build', testPath); + } + } + files.push(testPath); + } +} else { + const isNode20 = process.version.startsWith('v20.'); + if (isNode20) { + files.push('build/tests'); + } else { + files.push('build/tests/**/*.test.js'); + } +} + +const nodeArgs = [ + '--import', + './build/tests/setup.js', + '--no-warnings=ExperimentalWarning', + '--test-reporter', + 'spec', + '--test-force-exit', + '--test', + ...flags, + ...files, +]; + +const child = spawn('node', nodeArgs, { + stdio: 'inherit', +}); + +child.on('close', code => { + process.exit(code ?? 1); +}); diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json index c6c5981bf..1a65b2e08 100644 --- a/scripts/tsconfig.json +++ b/scripts/tsconfig.json @@ -19,5 +19,5 @@ "noEmit": true, "useUnknownInCatchVariables": false }, - "include": ["./**/*.ts", "./**/*.js"] + "include": ["./**/*.ts", "./**/*.js", "./**/*.mjs"] }