import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { setActivePinia, createPinia } from 'pinia' import { useAdminStore } from '../src/stores/admin.js' // Covers the two helpers the admin store actions route through (DRY Finding C, // #753): _dryRunPost (URL + dry_run body, sourceId→source_id) and _guard // (lastError capture + rethrow). The store had no frontend test before. 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)), } }) } function lastCallBody(calls) { return JSON.parse(calls.at(-1).init.body) } describe('admin store', () => { beforeEach(() => setActivePinia(createPinia())) afterEach(() => vi.restoreAllMocks()) it('_dryRunPost sends the apply flag to the right endpoint', async () => { const s = useAdminStore() const calls = [] stubFetch((url, init) => { calls.push({ url, init }) return { status: 200, body: { deleted: 0 } } }) await s.pruneUnusedTags({ dryRun: false }) const c = calls.at(-1) expect(c.url).toContain('/api/admin/tags/prune-unused') expect(c.init.method).toBe('POST') expect(lastCallBody(calls)).toEqual({ dry_run: false }) }) it('_dryRunPost defaults to the safe preview', async () => { const s = useAdminStore() const calls = [] stubFetch((url, init) => { calls.push({ url, init }) return { status: 200, body: { count: 0 } } }) await s.pruneBarePosts() expect(lastCallBody(calls)).toEqual({ dry_run: true }) }) it('reconcileDuplicatePosts maps sourceId → source_id', async () => { const s = useAdminStore() const calls = [] stubFetch((url, init) => { calls.push({ url, init }) return { status: 200, body: { groups: 0 } } }) await s.reconcileDuplicatePosts({ dryRun: false, sourceId: 42 }) const c = calls.at(-1) expect(c.url).toContain('/api/admin/posts/reconcile-duplicates') expect(lastCallBody(calls)).toEqual({ dry_run: false, source_id: 42 }) }) it('_guard captures the error message on lastError and rethrows', async () => { const s = useAdminStore() stubFetch(() => ({ status: 500, body: { error: 'boom' } })) await expect(s.deleteTag(7)).rejects.toThrow('boom') expect(s.lastError).toBe('boom') }) it('_guard clears lastError on a subsequent success', async () => { const s = useAdminStore() stubFetch(() => ({ status: 500, body: { error: 'boom' } })) await expect(s.deleteTag(7)).rejects.toThrow() expect(s.lastError).toBe('boom') stubFetch(() => ({ status: 200, body: { count: 3 } })) const n = await s.tagUsageCount(7) expect(n).toBe(3) // tagUsageCount returns body.count, not the raw body expect(s.lastError).toBe(null) }) })