feat(frontend): tagDirectory rename and merge store actions

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-16 13:41:20 -04:00
parent 305687dc33
commit 1d1574e586
2 changed files with 109 additions and 1 deletions
+76
View File
@@ -0,0 +1,76 @@
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'
import { useTagDirectoryStore } from '../src/stores/tagDirectory.js'
function stubFetch(handler) {
globalThis.fetch = vi.fn(async (url, init) => {
const { status, body } = handler(url, init)
return {
ok: status >= 200 && status < 300,
status,
statusText: String(status),
text: async () => (body == null ? '' : JSON.stringify(body))
}
})
}
describe('tagDirectory store: rename / merge', () => {
beforeEach(() => setActivePinia(createPinia()))
afterEach(() => { vi.restoreAllMocks() })
it('rename success patches the card name in place', async () => {
const store = useTagDirectoryStore()
store.cards.push({ id: 1, name: 'old', kind: 'general' })
stubFetch(() => ({ status: 200, body: { id: 1, name: 'new', kind: 'general' } }))
const res = await store.rename(1, 'new')
expect(res.collision).toBeUndefined()
expect(store.cards[0].name).toBe('new')
})
it('rename 409 resolves a collision object (does not throw)', async () => {
const store = useTagDirectoryStore()
store.cards.push({ id: 7, name: 'dupe', kind: 'general' })
stubFetch(() => ({
status: 409,
body: {
error: 'exists',
target: { id: 2, name: 'Canon' },
source_image_count: 5,
will_alias: true
}
}))
const res = await store.rename(7, 'Canon')
expect(res.collision).toEqual({
sourceId: 7,
sourceName: 'dupe',
target: { id: 2, name: 'Canon' },
sourceImageCount: 5,
willAlias: true
})
expect(store.cards[0].name).toBe('dupe') // unchanged
})
it('merge removes the source card optimistically', async () => {
const store = useTagDirectoryStore()
store.cards.push({ id: 7, name: 'dupe' }, { id: 2, name: 'Canon' })
stubFetch(() => ({
status: 200,
body: {
target: { id: 2, name: 'Canon', kind: 'general' },
merged_count: 3,
alias_created: true,
source_deleted: true
}
}))
const res = await store.merge(7, 2)
expect(store.cards.map(c => c.id)).toEqual([2])
expect(res.merged_count).toBe(3)
})
it('rename non-409 error rethrows', async () => {
const store = useTagDirectoryStore()
store.cards.push({ id: 1, name: 'x' })
stubFetch(() => ({ status: 400, body: { error: 'bad' } }))
await expect(store.rename(1, '')).rejects.toThrow()
})
})