import { describe, it, expect, vi, beforeEach } from 'vitest' import { mount } from '@vue/test-utils' import { setActivePinia, createPinia } from 'pinia' vi.mock('../../../api/client.js', () => ({ adminListUsers: vi.fn().mockResolvedValue({ items: [] }), adminCreateUser: vi.fn().mockResolvedValue({}), adminDeactivateUser: vi.fn().mockResolvedValue({}), adminReactivateUser: vi.fn().mockResolvedValue({}), adminDeleteUser: vi.fn().mockResolvedValue({}), adminResetUserPassword: vi.fn().mockResolvedValue({}), })) const stubs = { BreadcrumbBar: true, EmptyState: true, AppIcon: true, } async function mountUsers(overrides = {}) { const { default: AdminUsersView } = await import('../AdminUsersView.vue') return mount(AdminUsersView, { global: { stubs, plugins: [createPinia()] }, ...overrides, }) } describe('UX-04: AdminUsersView shows skeleton table rows during loading', () => { beforeEach(() => { setActivePinia(createPinia()) vi.resetModules() }) it('renders 5 skeleton rows when loading=true', async () => { const { adminListUsers } = await import('../../../api/client.js') adminListUsers.mockReturnValue(new Promise(() => {})) // never resolves => loading stays true const wrapper = await mountUsers() const tbody = wrapper.find('tbody') expect(tbody.exists()).toBe(true) const rows = tbody.findAll('tr') expect(rows.length).toBeGreaterThanOrEqual(5) }) it('skeleton rows have exactly 6 cells', async () => { const { adminListUsers } = await import('../../../api/client.js') adminListUsers.mockReturnValue(new Promise(() => {})) const wrapper = await mountUsers() const rows = wrapper.find('tbody').findAll('tr') rows.forEach(row => { expect(row.findAll('td').length).toBe(6) }) }) it('Loading users text is absent when loading=true', async () => { const { adminListUsers } = await import('../../../api/client.js') adminListUsers.mockReturnValue(new Promise(() => {})) const wrapper = await mountUsers() expect(wrapper.text()).not.toContain('Loading users') }) })