test(cli): cover upgrade selection and fallback boundaries

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
This commit is contained in:
XiaoSeS 2026-09-01 16:11:18 +08:00
parent dea1b4395c
commit 9adc49212a

View file

@ -187,6 +187,47 @@ describe('upgrade command', () => {
expect(noNamespaceMatch.stderr).toContain('not installed')
})
test('target filters select deterministically and missing matches never install', async () => {
const env = await createTempHome()
const skill = { namespace: 'global', slug: 'filtered', version: '1.0.0', fingerprint: 'fp', zipBytes: makeSkillZip('# v1') }
const registry = await startFakeRegistry({ skills: [skill] })
registries.push(registry)
const rootDir = join(env.cwd, 'skills')
await mkdir(rootDir, { recursive: true })
await runCli(['install', '@global/filtered', '--dir', rootDir, '--registry', registry.url], {
HOME: env.home,
USERPROFILE: env.home
})
for (const args of [
['--dir', rootDir],
['--agent', 'custom'],
['--namespace', 'global'],
['--registry', registry.url]
]) {
const result = await runCli(['upgrade', 'filtered', ...args, '--force', '--check'], {
HOME: env.home,
USERPROFILE: env.home
})
expect(result.exitCode).toBe(0)
}
for (const args of [
['--dir', join(env.cwd, 'missing')],
['--agent', 'codex'],
['--namespace', 'missing'],
['--registry', 'http://unmatched.invalid']
]) {
const result = await runCli(['upgrade', 'filtered', ...args, '--check'], {
HOME: env.home,
USERPROFILE: env.home
})
expect(result.exitCode).toBe(5)
expect(result.stderr).toContain('not installed')
}
expect(registry.received.downloads).toBe(1)
})
test('one resolved archive is reused for every managed target', async () => {
const env = await createTempHome()
const skill = {
@ -266,6 +307,39 @@ describe('upgrade command', () => {
expect(registry.received.downloads).toBe(1)
})
test('keeps local files when resolve is unavailable or same-version content drifts', async () => {
const env = await createTempHome()
const failures: { resolve?: 'server_error' } = {}
const skill = { namespace: 'global', slug: 'resilient', version: '1.0.0', fingerprint: 'fp-v1', zipBytes: makeSkillZip('# v1') }
const registry = await startFakeRegistry({ skills: [skill], failures })
registries.push(registry)
const rootDir = join(env.cwd, 'skills')
await mkdir(rootDir, { recursive: true })
await runCli(['install', '@global/resilient', '--dir', rootDir, '--registry', registry.url], {
HOME: env.home,
USERPROFILE: env.home
})
failures.resolve = 'server_error'
const unavailable = await runCli([
'upgrade', '@global/resilient', '--registry', registry.url, '--force', '--json'
], { HOME: env.home, USERPROFILE: env.home })
expect(unavailable.exitCode).toBe(6)
expect(JSON.parse(unavailable.stdout).items[0].action).toBe('blocked')
expect(await readFile(join(rootDir, 'resilient', 'SKILL.md'), 'utf-8')).toBe('# v1')
delete failures.resolve
skill.fingerprint = 'fp-drift'
skill.zipBytes = makeSkillZip('# changed without version bump')
const drifted = await runCli([
'upgrade', '@global/resilient', '--registry', registry.url, '--force', '--json'
], { HOME: env.home, USERPROFILE: env.home })
expect(drifted.exitCode).toBe(6)
expect(JSON.parse(drifted.stdout).items[0].reason).toContain('without a newer version')
expect(await readFile(join(rootDir, 'resilient', 'SKILL.md'), 'utf-8')).toBe('# v1')
expect(registry.received.downloads).toBe(1)
})
test('a blocked batch reports a plan and does not claim successful writes', async () => {
const env = await createTempHome()
const first = { namespace: 'global', slug: 'first', version: '1.0.0', fingerprint: 'first-v1', zipBytes: makeSkillZip('# first v1') }