skillhub/cli/test/integration/whoami-command.test.ts
dongmucat 9643e4157c test(cli): migrate comprehensive test suite from test/cli-integration-coverage
Migrated 39 test files covering CLI integration and unit testing:
- 6 new integration tests (auth-resolution, concurrency, cross-command, inventory-resilience, multi-registry, version-upgrade-flow)
- Enhanced 7 existing integration tests with comprehensive scenarios
- Updated 2 unit tests with correct exit code expectations

All tests use fake registry approach (no E2E/browser required) and pass lint/build/test checks.
2026-05-13 11:14:20 +08:00

151 lines
5.5 KiB
TypeScript

import { afterEach, describe, expect, test } from 'bun:test'
import { createTempHome } from '../helpers/temp-env'
import { startFakeRegistry } from '../helpers/fake-registry'
import { runCli } from '../helpers/run-cli'
let registry: { url: string; stop: () => void } | undefined
afterEach(() => {
registry?.stop()
registry = undefined
})
describe('whoami command', () => {
test('not logged in — exits with EXIT.auth and prints not logged in', async () => {
const { home } = await createTempHome()
const env = { HOME: home, USERPROFILE: home }
const result = await runCli(['whoami'], env)
expect(result.exitCode).toBe(2)
expect(result.stderr).toContain('not logged in')
})
test('happy path — human output contains handle and displayName', async () => {
registry = await startFakeRegistry({
user: { handle: 'testuser', displayName: 'Test User', email: 'test@example.com' }
})
const { home } = await createTempHome()
const env = { HOME: home, USERPROFILE: home }
// Login first to store credentials
const loginResult = await runCli(
['login', '--registry', registry.url, '--token', 'sk_ok'],
env,
)
expect(loginResult.exitCode).toBe(0)
// Now run whoami
const result = await runCli(['whoami'], env)
expect(result.exitCode).toBe(0)
expect(result.stdout).toContain('testuser')
expect(result.stdout).toContain('Test User')
})
test('--json flag — output is valid JSON with ok:true and user fields', async () => {
registry = await startFakeRegistry({
user: { handle: 'testuser', displayName: 'Test User', email: 'test@example.com' }
})
const { home } = await createTempHome()
const env = { HOME: home, USERPROFILE: home }
// Login first to store credentials
const loginResult = await runCli(
['login', '--registry', registry.url, '--token', 'sk_ok'],
env,
)
expect(loginResult.exitCode).toBe(0)
// Now run whoami --json
const result = await runCli(['whoami', '--json'], env)
expect(result.exitCode).toBe(0)
const json = JSON.parse(result.stdout)
expect(json.ok).toBe(true)
expect(json.handle).toBe('testuser')
expect(json.displayName).toBe('Test User')
})
test('--token override — works without prior login', async () => {
registry = await startFakeRegistry({
user: { handle: 'testuser', displayName: 'Test User', email: 'test@example.com' }
})
const { home } = await createTempHome()
const env = { HOME: home, USERPROFILE: home }
// No login — pass token directly
const result = await runCli(
['whoami', '--token', 'sk_ok', '--registry', registry.url],
env,
)
expect(result.exitCode).toBe(0)
expect(result.stdout).toContain('testuser')
})
test('auth failure from server — exits with EXIT.auth', async () => {
registry = await startFakeRegistry({ failures: { whoami: 'auth' } })
const { home } = await createTempHome()
const env = { HOME: home, USERPROFILE: home }
// Pass a bad token explicitly so the server returns 401
const result = await runCli(
['whoami', '--token', 'sk_bad', '--registry', registry.url],
env,
)
expect(result.exitCode).toBe(2)
expect(result.stderr.toLowerCase()).toContain('authentication failed')
})
// ---------------------------------------------------------------------------
// P1 — Stored-token revocation: token persists in credentials.json but
// server now rejects it. whoami must surface the auth failure on first
// call, not silently use a stale principal.
// ---------------------------------------------------------------------------
test('stored token that the server now rejects surfaces EXIT.auth on whoami', async () => {
// Configure a registry that requires sk_new but seed sk_old in credentials
// — simulates a token that was valid at login time but has since been
// revoked or rotated server-side.
registry = await startFakeRegistry({
token: 'sk_new',
user: { handle: 'should-not-see', displayName: 'X' }
})
const { home } = await createTempHome()
const env = { HOME: home, USERPROFILE: home }
const { mkdir, writeFile } = await import('node:fs/promises')
const { join } = await import('node:path')
await mkdir(join(home, '.skillhub'), { recursive: true })
await writeFile(
join(home, '.skillhub', 'credentials.json'),
JSON.stringify({ tokens: { [registry.url]: 'sk_old_revoked' } })
)
const result = await runCli(['whoami', '--registry', registry.url], env)
expect(result.exitCode).toBe(2)
expect(result.stderr.toLowerCase()).toMatch(/auth|401|unauthorized/)
})
// ---------------------------------------------------------------------------
// P1 — Token priority --token > SKILLHUB_TOKEN > stored, end-to-end via
// whoami. Cross-checks the auth-resolution suite by verifying the wired
// contract on this specific command.
// ---------------------------------------------------------------------------
test('--token wins over SKILLHUB_TOKEN env on whoami', async () => {
registry = await startFakeRegistry({
token: 'sk_winner',
user: { handle: 'winner', displayName: 'W' }
})
const { home } = await createTempHome()
const env = { HOME: home, USERPROFILE: home, SKILLHUB_TOKEN: 'sk_loser_env' }
const result = await runCli(
['whoami', '--token', 'sk_winner', '--registry', registry.url],
env
)
expect(result.exitCode).toBe(0)
expect(result.stdout).toContain('winner')
})
})