mirror of
https://github.com/iflytek/skillhub.git
synced 2026-08-28 11:25:00 +00:00
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.
151 lines
5.5 KiB
TypeScript
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')
|
|
})
|
|
})
|