Files
jsc-anima/hooks/persist.test.ts
T
2026-10-15 09:06:15 +00:00

77 lines
3.2 KiB
TypeScript

import { expect, mock, test } from 'claude-code/testing'
import { CHARACTERS } from './characters'
const setup = (on: any, active?: string) => {
mock.store(on, active ? { active } : undefined)
on('command.register', () => ({ value: { name: 'x' } }) as never)
on('session.start', () => ({ cwd: '/tmp' }) as never)
on('command.run', () => ({ text: '' }))
on('prompt.compose', () => ({ sections: [] }))
}
const compose = ($: any) => $.prompt.compose({ model: 'm', promptModel: 'm', surfaces: [], tools: [], outputStyle: null, traits: [] } as never)
const persona = async ($: any): Promise<string | undefined> => (await compose($)).sections.find((s: any) => s.id === 'jsc-anima:persona')?.text
const start = ($: any) => $.session.start({ source: 'startup', cwd: '/tmp' } as never)
test('啟動狀態跨 session 保留:下次開啟自動恢復', async ($, on) => {
setup(on, 'sao-suguha')
await start($)
expect(await persona($)).toContain('直葉')
})
test('啟動角色後寫入儲存,新 session 恢復;離開後不再恢復', async ($, on) => {
setup(on)
await start($)
await $.command.run({ command: 'sao-asuna', args: '' } as never)
await $.command.run({ command: 'anima-off', args: '' } as never)
await $.command.run({ command: 'sao-suguha', args: '' } as never)
await start($)
expect(await persona($)).toContain('直葉')
await $.command.run({ command: 'anima-off', args: '' } as never)
await start($)
expect(await persona($)).toBeUndefined()
})
test('在 /config 關閉 persist 後不恢復', { options: { persist: false } }, async ($, on) => {
setup(on, 'sao-asuna')
await start($)
expect(await persona($)).toBeUndefined()
})
test('儲存的角色不存在時不恢復', async ($, on) => {
setup(on, 'no-such-character')
await start($)
expect(await persona($)).toBeUndefined()
})
test('微調數值軸:反映在 persona,其餘維持角色包預設,且不改動角色包', { options: { axisGentle: 2, axisHumor: 9 } }, async ($, on) => {
setup(on, 'sao-asuna')
const before = { ...CHARACTERS.find(c => c.slug === 'sao-asuna')!.axes }
await start($)
const text = (await persona($))!
expect(text).toContain('溫柔 2')
expect(text).toContain('幽默 9')
expect(text).toContain(`傲嬌 ${before.tsundere}`)
expect(CHARACTERS.find(c => c.slug === 'sao-asuna')!.axes).toEqual(before)
})
test('未微調(-1)沿用角色包預設', { options: { axisGentle: -1 } }, async ($, on) => {
setup(on, 'sao-asuna')
await start($)
expect(await persona($)).toContain(`溫柔 ${CHARACTERS.find(c => c.slug === 'sao-asuna')!.axes.gentle}`)
})
test('8 個數值軸都可微調', {
options: { axisGentle: 1, axisTsundere: 2, axisLively: 3, axisFormal: 4, axisTalkative: 5, axisHumor: 6, axisProactive: 7, axisExpressive: 8 },
}, async ($, on) => {
setup(on, 'sao-asuna')
await start($)
expect(await persona($)).toContain('溫柔 1、傲嬌 2、活潑 3、正式 4、話量 5、幽默 6、主動 7、情緒外顯 8')
})
test('超出 0-10 的覆蓋值被忽略', { options: { axisGentle: 11 } }, async ($, on) => {
setup(on, 'sao-asuna')
await start($)
expect(await persona($)).toContain(`溫柔 ${CHARACTERS.find(c => c.slug === 'sao-asuna')!.axes.gentle}`)
})