Files
opencode-kimi-full/test/constants.test.ts
T
lemon07r 64550fb057 Release v1.0.2: broaden offline test coverage
Adds one test file per source file plus a shared fetch mock helper:

- test/constants.test.ts: OAuth scope/client_id/PROVIDER_ID/MODEL_ID pins,
  rules 1, 6, 8.
- test/headers.test.ts: seven fingerprint header keys, UA/X-Msh-Version
  track KIMI_CLI_VERSION, ASCII-only values, device-id format and
  stability across calls (rules 1, 2).
- test/oauth.test.ts: form-encoded bodies for device-start/refresh,
  authorization_pending/expired_token/unknown-error branches, non-OK and
  non-JSON error shapes.
- test/plugin.test.ts: chat.params provider+model gating, full effort
  matrix (rule 4), prompt_cache_key gating (rule 5), camelCase effort
  input, loader Authorization ownership (rule 3), refresh-on-expiry with
  persistAuth, 401 single-retry no-loop, device-flow authorize wiring.
- test/_util/fetchMock.ts: zero-dep global-fetch swap returning canned
  Responses with call capture.

Notes:

- Tests use the real ~/.kimi/device_id; getDeviceId is idempotent and the
  file is shared with kimi-cli by design (AGENTS.md rule 2), so no HOME
  redirect is needed. Attempted monkey-patching os.homedir instead is
  fragile under Bun's eager import-binding resolution.
- pollDeviceToken tests use interval=1 because `device.interval || 5`
  treats 0 as the default 5s and would push each iteration past the
  default bun-test timeout.

Total: 35 tests, ~5s to run.
2026-04-17 03:18:23 -04:00

43 lines
1.8 KiB
TypeScript

import { test, expect } from "bun:test"
import * as C from "../src/constants.ts"
// These values form the "identity" of the plugin on the wire. Typos silently
// downgrade K2.6 → K2.5 (scope/client_id) or collide with models.dev
// (PROVIDER_ID). See AGENTS.md "Contracts to keep intact".
test("KIMI_CLI_VERSION is a non-empty semver", () => {
expect(C.KIMI_CLI_VERSION).toMatch(/^\d+\.\d+\.\d+$/)
})
test("USER_AGENT embeds KIMI_CLI_VERSION", () => {
expect(C.USER_AGENT).toBe(`KimiCodeCLI/${C.KIMI_CLI_VERSION}`)
})
test("OAuth constants match upstream kimi-cli exactly", () => {
// Pinned values from research/kimi-cli/src/kimi_cli/auth/oauth.py. If these
// drift from upstream, tokens are issued against the wrong scope/client and
// the backend routes to K2.5.
expect(C.OAUTH_HOST).toBe("https://auth.kimi.com")
expect(C.OAUTH_DEVICE_AUTH_URL).toBe("https://auth.kimi.com/api/oauth/device_authorization")
expect(C.OAUTH_TOKEN_URL).toBe("https://auth.kimi.com/api/oauth/token")
expect(C.OAUTH_CLIENT_ID).toBe("17e5f671-d194-4dfb-9706-5516cb48c098")
expect(C.OAUTH_SCOPE).toBe("kimi-code")
expect(C.OAUTH_DEVICE_GRANT).toBe("urn:ietf:params:oauth:grant-type:device_code")
expect(C.OAUTH_REFRESH_GRANT).toBe("refresh_token")
})
test("PROVIDER_ID does not collide with models.dev (AGENTS.md rule 8)", () => {
expect(C.PROVIDER_ID).toBe("kimi-for-coding-oauth")
expect(C.PROVIDER_ID).not.toBe("kimi-for-coding")
})
test("MODEL_ID goes over the wire verbatim (AGENTS.md rule 6)", () => {
expect(C.MODEL_ID).toBe("kimi-for-coding")
})
test("REFRESH_SAFETY_WINDOW_MS is positive and well below token TTL", () => {
// Token TTLs are ~15 min; anything bigger would mean we refresh on every call.
expect(C.REFRESH_SAFETY_WINDOW_MS).toBeGreaterThan(0)
expect(C.REFRESH_SAFETY_WINDOW_MS).toBeLessThan(5 * 60_000)
})