test(10-08): promote admin skeleton stubs to real RED tests — 8 failing tests

- AdminAuditView.skeleton.test.js: 5 real assertions (skeleton rows, cell count, no loading text, EmptyState, CTA)
- AdminUsersView.skeleton.test.js: 3 real assertions (skeleton rows, 6 cells, no loading text)
- All 8 tests fail until Task 2 updates the view components
This commit is contained in:
curo1305
2026-06-15 20:22:34 +02:00
parent a1885122a1
commit ec5fd23ec2
2 changed files with 138 additions and 10 deletions
@@ -1,12 +1,87 @@
import { describe, it } from 'vitest'
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { mount } from '@vue/test-utils'
import { setActivePinia, createPinia } from 'pinia'
vi.mock('../../../api/client.js', () => ({
adminListAuditLog: vi.fn().mockResolvedValue({ items: [], total: 0 }),
adminExportAuditLogCsv: vi.fn().mockResolvedValue({}),
adminListDailyExports: vi.fn().mockResolvedValue({ items: [] }),
adminDownloadDailyExport: vi.fn().mockResolvedValue({}),
}))
const stubs = {
BreadcrumbBar: true,
EmptyState: true,
AppIcon: true,
}
async function mountAudit(overrides = {}) {
const { default: AdminAuditView } = await import('../AdminAuditView.vue')
return mount(AdminAuditView, {
global: { stubs, plugins: [createPinia()] },
...overrides,
})
}
describe('UX-04: AdminAuditView shows skeleton table rows during loading', () => {
it.todo('renders 5+ skeleton <tr> rows when loading=true')
it.todo('skeleton rows have 5 columns matching the real table header')
it.todo('animated spinner Loading audit log… text is removed')
beforeEach(() => {
setActivePinia(createPinia())
vi.resetModules()
})
it('renders 8 skeleton <tr> rows when loading=true', async () => {
const { adminListAuditLog } = await import('../../../api/client.js')
adminListAuditLog.mockReturnValue(new Promise(() => {})) // never resolves => loading stays true
const wrapper = await mountAudit()
const tbody = wrapper.find('tbody')
expect(tbody.exists()).toBe(true)
const rows = tbody.findAll('tr')
expect(rows.length).toBeGreaterThanOrEqual(8)
})
it('skeleton rows have exactly 5 <td> cells matching column count', async () => {
const { adminListAuditLog } = await import('../../../api/client.js')
adminListAuditLog.mockReturnValue(new Promise(() => {}))
const wrapper = await mountAudit()
const rows = wrapper.find('tbody').findAll('tr')
rows.forEach(row => {
expect(row.findAll('td').length).toBe(5)
})
})
it('Loading audit log text is absent when loading=true', async () => {
const { adminListAuditLog } = await import('../../../api/client.js')
adminListAuditLog.mockReturnValue(new Promise(() => {}))
const wrapper = await mountAudit()
expect(wrapper.text()).not.toContain('Loading audit log')
})
})
describe('UX-01 (audit empty): EmptyState renders when entries is empty after load', () => {
it.todo('EmptyState icon=clipboardList headline="No entries found" appears when entries.length===0 and not loading')
it.todo('clear-filters button rendered in #cta slot')
beforeEach(() => {
setActivePinia(createPinia())
vi.resetModules()
})
it('renders <EmptyState icon="clipboardList" headline="No entries found"> when entries empty and not loading', async () => {
const { adminListAuditLog } = await import('../../../api/client.js')
adminListAuditLog.mockResolvedValue({ items: [], total: 0 })
const wrapper = await mountAudit()
await new Promise(r => setTimeout(r, 50))
await wrapper.vm.$nextTick()
const emptyState = wrapper.findComponent({ name: 'EmptyState' })
expect(emptyState.exists()).toBe(true)
expect(emptyState.attributes('icon') ?? emptyState.props('icon')).toBe('clipboardList')
const headline = emptyState.attributes('headline') ?? emptyState.props('headline')
expect(headline).toBe('No entries found')
})
it('EmptyState includes a Clear filters CTA button', async () => {
const { adminListAuditLog } = await import('../../../api/client.js')
adminListAuditLog.mockResolvedValue({ items: [], total: 0 })
const wrapper = await mountAudit()
await new Promise(r => setTimeout(r, 50))
await wrapper.vm.$nextTick()
expect(wrapper.text()).toContain('Clear filters')
})
})