/** * Endpoints (shared key) settings page. * * The shared key only matters to PCs that have not enrolled, so the page must * say how far enrollment has got, and the regenerate and revoke confirms must * name how many PCs the change actually reaches. */ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' import { mount, flushPromises, RouterLinkStub } from '@vue/test-utils' vi.mock('@/api', () => ({ default: { get: vi.fn(), post: vi.fn(), put: vi.fn(), delete: vi.fn() } })) vi.mock('vue-router', () => ({ useRouter: () => ({ push: vi.fn() }) })) import api from '@/api' import AgentKeySettings from './AgentKeySettings.vue' const KEY = { tokenprefix: 'abcd', createddate: null, lastusedat: null } function enrollmentPayload(settings = { sharedkeyallowed: true, autoenroll: true }) { return { data: { data: { settings, counts: { enrolled: 30, notenrolled: 8, pending: 2 }, computers: [], requests: [ { requestid: 1, status: 'pending', reason: 'serial mismatch' }, { requestid: 2, status: 'pending', reason: 'awaiting approval' }, { requestid: 3, status: 'pending', reason: 'reenroll blocked' }, { requestid: 4, status: 'issued', reason: null } ] } } } } async function render(payload = enrollmentPayload()) { api.get.mockImplementation((path) => { if (path === '/endpoints/agentkey') { return Promise.resolve({ data: { data: { key: KEY, envkeyfallback: false } } }) } if (path === '/endpoints/enrollment') return Promise.resolve(payload) return Promise.resolve({ data: { data: {} } }) }) api.post.mockResolvedValue({ data: { data: { key: KEY } } }) api.delete.mockResolvedValue({ data: { data: { key: null } } }) const wrapper = mount(AgentKeySettings, { global: { stubs: { RouterLink: RouterLinkStub } } }) await flushPromises() return wrapper } describe('AgentKeySettings shared key section', () => { beforeEach(() => { api.get.mockReset() api.post.mockReset() api.delete.mockReset() }) afterEach(() => { vi.unstubAllGlobals() }) it('titles the section for the per-PC model', async () => { const wrapper = await render() expect(wrapper.text()).toContain('Shared key (used until PCs enroll)') expect(wrapper.text()).not.toContain('Key management') expect(wrapper.text()).toMatch(/Enrolled PCs ignore it/) expect(wrapper.text()).toMatch(/At cutover/) }) it('shows enrollment progress from one small enrollment read', async () => { const wrapper = await render() expect(api.get).toHaveBeenCalledWith('/endpoints/enrollment', { params: { perpage: 1 } }) const summary = wrapper.find('.enrollment-summary').text() expect(summary).toContain('30 of 40 PCs enrolled') expect(summary).toContain('10 still on the shared key') // A blocked PC asking again is not a request anyone has to decide. expect(summary).toContain('2 pending enrollment requests') const link = wrapper.findComponent(RouterLinkStub) expect(link.props('to')).toEqual({ name: 'endpoints-enrollment-settings' }) }) it('regenerate confirm names the PCs that need the new key', async () => { const confirmSpy = vi.fn(() => true) vi.stubGlobal('confirm', confirmSpy) const wrapper = await render() const button = wrapper.findAll('button').find(b => b.text() === 'Regenerate key') await button.trigger('click') await flushPromises() expect(confirmSpy.mock.calls[0][0]).toMatch(/10 PCs not enrolled will need the new key/) expect(confirmSpy.mock.calls[0][0]).toMatch(/Enrolled PCs are not affected/) expect(api.post).toHaveBeenCalledWith('/endpoints/agentkey/regenerate') }) it('revoke confirm names the PCs that lose access', async () => { const confirmSpy = vi.fn(() => true) vi.stubGlobal('confirm', confirmSpy) const wrapper = await render() const button = wrapper.findAll('button').find(b => b.text() === 'Revoke key') await button.trigger('click') await flushPromises() expect(confirmSpy.mock.calls[0][0]).toMatch(/10 PCs not enrolled will lose access/) expect(api.delete).toHaveBeenCalledWith('/endpoints/agentkey') }) it('sends nothing when revoke is declined', async () => { vi.stubGlobal('confirm', vi.fn(() => false)) const wrapper = await render() const button = wrapper.findAll('button').find(b => b.text() === 'Revoke key') await button.trigger('click') await flushPromises() expect(api.delete).not.toHaveBeenCalled() }) it('still manages the key when the enrollment read fails', async () => { api.get.mockImplementation((path) => { if (path === '/endpoints/enrollment') return Promise.reject(new Error('403')) if (path === '/endpoints/agentkey') { return Promise.resolve({ data: { data: { key: KEY, envkeyfallback: false } } }) } return Promise.resolve({ data: { data: {} } }) }) vi.stubGlobal('confirm', vi.fn(() => true)) vi.spyOn(console, 'error').mockImplementation(() => {}) const wrapper = mount(AgentKeySettings, { global: { stubs: { RouterLink: RouterLinkStub } } }) await flushPromises() expect(wrapper.find('.enrollment-summary').exists()).toBe(false) const button = wrapper.findAll('button').find(b => b.text() === 'Revoke key') expect(button.exists()).toBe(true) }) })