/** * Fleet list Credential column. * * The state is computed by the list route so that filtering by it survives * pagination; the page must send the filter to the server rather than narrowing * the rows it already has, and must render the server's value, not derive one. */ import { describe, it, expect, vi, beforeEach } from 'vitest' import { mount, flushPromises } from '@vue/test-utils' import { ref } from 'vue' vi.mock('@/api', () => ({ endpointsApi: { list: vi.fn(), dashboardSummary: vi.fn(), dashboardStability: vi.fn(), enqueueCommand: vi.fn() }, computersApi: { types: { listAll: vi.fn(() => Promise.resolve([])) } }, locationsApi: { listAll: vi.fn(() => Promise.resolve([])) } })) vi.mock('vue-router', () => ({ useRouter: () => ({ push: vi.fn() }) })) vi.mock('@/stores/auth', () => ({ useAuthStore: () => ({ isAdmin: true, hasPermission: () => true }) })) vi.mock('@/composables/toast', () => ({ useToast: () => ({ success: vi.fn(), error: vi.fn(), info: vi.fn() }) })) vi.mock('@/composables/listQuery', () => ({ useListQuery: () => ({ page: ref(1), search: ref(''), setPage: vi.fn(), setSearch: vi.fn() }) })) vi.mock('@/components/PaginationBar.vue', () => ({ default: { name: 'PaginationBar', template: '
' } })) import { endpointsApi } from '@/api' import EndpointsList from './EndpointsList.vue' function row(assetid, hostname, credentialstate) { return { assetid, hostname, computerid: assetid, status: 'reporting', machines: [], health: null, credentialstate } } beforeEach(() => { vi.clearAllMocks() endpointsApi.dashboardSummary.mockResolvedValue({ data: { data: null } }) endpointsApi.dashboardStability.mockResolvedValue({ data: { data: [] } }) endpointsApi.list.mockResolvedValue({ data: { data: [ row(1, 'PC-ENROLLED', 'enrolled'), row(2, 'PC-PENDING', 'pending'), row(3, 'PC-BLOCKED', 'reenrollblocked'), row(4, 'PC-SHARED', 'sharedkey'), row(5, 'PC-SILENT', 'notreporting') ], meta: { pagination: { totalpages: 1 } } } }) }) describe('EndpointsList credential column', () => { it('renders a chip per server state', async () => { const wrapper = mount(EndpointsList) await flushPromises() const chips = wrapper.findAll('.credential-chip').map(chip => chip.text()) expect(chips).toEqual([ 'Enrolled', 'Pending', 'Re-enroll blocked', 'Shared key (not enrolled)', 'Not reporting' ]) expect(wrapper.find('.credential-chip.reenrollblocked').exists()).toBe(true) expect(wrapper.findAll('th').map(th => th.text())).toContain('Credential') }) it('sends the credential filter to the server', async () => { const wrapper = mount(EndpointsList) await flushPromises() const select = wrapper.findAll('select.fleet-filter') .find(element => element.text().includes('All credentials')) await select.setValue('sharedkey') await flushPromises() const params = endpointsApi.list.mock.calls.at(-1)[0] expect(params.credentialstate).toBe('sharedkey') expect(params.perpage).toBe(20) }) it('offers no credential actions on the list', async () => { const wrapper = mount(EndpointsList) await flushPromises() expect(wrapper.text()).not.toMatch(/Revoke|Allow re-enrollment/) }) })