ci(test): add test:packages script and wire packages/pi-coding-agent tests into CI
The 13 test files in packages/pi-coding-agent/src/core/ were never executed in CI or by `npm test`. The test:unit glob only covers src/resources/extensions/gsd/tests/ and src/tests/, leaving lifecycle-hooks, model-registry-auth-mode, auth-storage, and 10 other suites with zero enforcement. - Add `test:packages` script that runs compiled dist tests after build - Wire into both the linux build job and windows-portability job in CI - Fix two env-isolation bugs in auth-storage.test.ts: the "returns undefined" and "falls through to fallback resolver" tests were not clearing OPENROUTER_API_KEY before calling getApiKey, causing failures when the env var is set in the caller's environment
This commit is contained in:
parent
ab5444fec8
commit
d6bd17298f
3 changed files with 34 additions and 2 deletions
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
|
|
@ -139,6 +139,9 @@ jobs:
|
|||
- name: Run unit tests
|
||||
run: npm run test:unit
|
||||
|
||||
- name: Run package tests
|
||||
run: npm run test:packages
|
||||
|
||||
- name: Run integration tests
|
||||
run: npm run test:integration
|
||||
|
||||
|
|
@ -171,3 +174,6 @@ jobs:
|
|||
|
||||
- name: Run unit tests
|
||||
run: npm run test:unit
|
||||
|
||||
- name: Run package tests
|
||||
run: npm run test:packages
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
"copy-themes": "node scripts/copy-themes.cjs",
|
||||
"copy-export-html": "node scripts/copy-export-html.cjs",
|
||||
"test:unit": "node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --experimental-test-isolation=process --test src/resources/extensions/gsd/tests/*.test.ts src/resources/extensions/gsd/tests/*.test.mjs src/tests/*.test.ts",
|
||||
"test:packages": "node --test packages/pi-coding-agent/dist/core/*.test.js",
|
||||
"test:marketplace": "GSD_TEST_CLONE_MARKETPLACES=1 node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/resources/extensions/gsd/tests/claude-import-tui.test.ts src/resources/extensions/gsd/tests/plugin-importer-live.test.ts src/tests/marketplace-discovery.test.ts",
|
||||
"test:coverage": "c8 --reporter=text --reporter=lcov --exclude='src/resources/extensions/gsd/tests/**' --exclude='src/tests/**' --exclude='scripts/**' --exclude='native/**' --exclude='node_modules/**' --check-coverage --statements=50 --lines=50 --branches=20 --functions=20 node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --experimental-test-isolation=process --test src/resources/extensions/gsd/tests/*.test.ts src/resources/extensions/gsd/tests/*.test.mjs src/tests/*.test.ts",
|
||||
"test:integration": "node --import ./src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --experimental-test-isolation=process --test src/resources/extensions/gsd/tests/*integration*.test.ts src/tests/integration/*.test.ts",
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ describe("AuthStorage — areAllCredentialsBackedOff", () => {
|
|||
// ─── mismatched oauth credential for non-OAuth provider (#2083) ───────────────
|
||||
|
||||
describe("AuthStorage — oauth credential for non-OAuth provider (#2083)", () => {
|
||||
it("returns undefined when openrouter has type:oauth (no registered OAuth provider)", async () => {
|
||||
it("returns undefined when openrouter has type:oauth (no registered OAuth provider)", async (t) => {
|
||||
// Simulates the bug: OpenRouter credential stored as type:"oauth"
|
||||
// but OpenRouter is not a registered OAuth provider.
|
||||
const storage = inMemory({
|
||||
|
|
@ -278,12 +278,25 @@ describe("AuthStorage — oauth credential for non-OAuth provider (#2083)", () =
|
|||
},
|
||||
});
|
||||
|
||||
// Isolate from any real OPENROUTER_API_KEY in the environment so the
|
||||
// fall-through to env / fallback finds nothing and returns undefined.
|
||||
const origEnv = process.env.OPENROUTER_API_KEY;
|
||||
delete process.env.OPENROUTER_API_KEY;
|
||||
t.after(() => {
|
||||
if (origEnv === undefined) {
|
||||
delete process.env.OPENROUTER_API_KEY;
|
||||
} else {
|
||||
process.env.OPENROUTER_API_KEY = origEnv;
|
||||
}
|
||||
});
|
||||
|
||||
// Before the fix, getApiKey returns undefined because
|
||||
// resolveCredentialApiKey calls getOAuthProvider("openrouter") → null → undefined.
|
||||
// The key in the oauth credential is never extracted.
|
||||
const key = await storage.getApiKey("openrouter");
|
||||
// After the fix, the oauth credential with an unrecognised provider
|
||||
// should be skipped, and getApiKey should fall through to env / fallback.
|
||||
// With no env var and no fallback resolver configured, the result is undefined.
|
||||
assert.equal(key, undefined);
|
||||
});
|
||||
|
||||
|
|
@ -312,7 +325,7 @@ describe("AuthStorage — oauth credential for non-OAuth provider (#2083)", () =
|
|||
assert.equal(key, "sk-or-v1-env-key");
|
||||
});
|
||||
|
||||
it("falls through to fallback resolver when openrouter has type:oauth credential", async () => {
|
||||
it("falls through to fallback resolver when openrouter has type:oauth credential", async (t) => {
|
||||
const storage = inMemory({
|
||||
openrouter: {
|
||||
type: "oauth",
|
||||
|
|
@ -322,6 +335,18 @@ describe("AuthStorage — oauth credential for non-OAuth provider (#2083)", () =
|
|||
},
|
||||
});
|
||||
|
||||
// Isolate from any real OPENROUTER_API_KEY so env fallback is skipped
|
||||
// and the fallback resolver is reached.
|
||||
const origEnv = process.env.OPENROUTER_API_KEY;
|
||||
delete process.env.OPENROUTER_API_KEY;
|
||||
t.after(() => {
|
||||
if (origEnv === undefined) {
|
||||
delete process.env.OPENROUTER_API_KEY;
|
||||
} else {
|
||||
process.env.OPENROUTER_API_KEY = origEnv;
|
||||
}
|
||||
});
|
||||
|
||||
storage.setFallbackResolver((provider) =>
|
||||
provider === "openrouter" ? "sk-or-v1-fallback" : undefined,
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue