deviceAuthorizationPanel.test.ts 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. import { afterEach, beforeEach, expect, it, vi } from 'vitest'
  2. import { flushPromises, mount } from '@vue/test-utils'
  3. import DeviceAuthorizationPanel from '../../src/client/components/app/DeviceAuthorizationPanel.vue'
  4. import { apiRequest } from '../../src/client/api/client'
  5. vi.mock('../../src/client/api/client', () => ({ apiRequest: vi.fn() }))
  6. const permissions = { supported: true, authorized: false, screen: false, accessibility: false, ready: false, fullAuthorized: false }
  7. let wrapper: ReturnType<typeof mount> | undefined
  8. beforeEach(() => {
  9. vi.spyOn(document, 'hidden', 'get').mockReturnValue(false)
  10. vi.mocked(apiRequest).mockResolvedValue({ hosts: [
  11. { id: 'local', name: '服务器', online: true, platform: 'darwin', local: permissions },
  12. { id: 'current', name: '我的电脑', online: true, platform: 'darwin', local: permissions },
  13. { id: 'other', name: '另一台电脑', online: true, platform: 'win32', local: { ...permissions, fullAuthorized: true } },
  14. { id: 'offline', name: '离线电脑', online: false, platform: '', local: permissions },
  15. ] })
  16. })
  17. afterEach(() => { wrapper?.unmount(); wrapper = undefined; delete window.yaoyaoDesktop; vi.restoreAllMocks(); vi.clearAllMocks() })
  18. it.each(['current', 'local'])('authorizes only the native current device %s while showing other devices read-only', async current => {
  19. const authorize = vi.fn().mockResolvedValue({ ok: true })
  20. window.yaoyaoDesktop = { deviceHost: async () => ({ deviceHost: current }), authorizeCurrentDevice: authorize } as any
  21. wrapper = mount(DeviceAuthorizationPanel)
  22. await flushPromises()
  23. const active = wrapper.get(`[data-host-id="${current}"]`)
  24. expect(active.text()).toContain('当前设备')
  25. expect(active.findAll('button')).toHaveLength(2)
  26. for (const id of ['local', 'current', 'other', 'offline'].filter(id => id !== current)) {
  27. expect(wrapper.get(`[data-host-id="${id}"]`).findAll('button')).toHaveLength(0)
  28. }
  29. expect(wrapper.get('[data-host-id="other"]').text()).toContain('已授权')
  30. expect(wrapper.get('[data-host-id="offline"]').text()).toContain('连接后更新授权状态')
  31. await active.findAll('button')[1].trigger('click'); await flushPromises()
  32. expect(authorize).toHaveBeenCalledExactlyOnceWith('full')
  33. expect(vi.mocked(apiRequest).mock.calls.every(([, options]) => !options?.method || options.method === 'GET')).toBe(true)
  34. })
  35. it.each([undefined, { deviceHost: async () => ({ deviceHost: 'current' }) }])('keeps browser and old client devices read-only', async desktop => {
  36. window.yaoyaoDesktop = desktop as any
  37. wrapper = mount(DeviceAuthorizationPanel); await flushPromises()
  38. expect(wrapper.findAll('article button')).toHaveLength(0)
  39. expect(wrapper.findAll('article')).toHaveLength(4)
  40. })
  41. it('keeps authorization failure visible for retry without claiming success', async () => {
  42. window.yaoyaoDesktop = { deviceHost: async () => ({ deviceHost: 'current' }), authorizeCurrentDevice: vi.fn().mockRejectedValue(new Error('本机控制授权已取消')) } as any
  43. wrapper = mount(DeviceAuthorizationPanel); await flushPromises()
  44. await wrapper.get('[data-host-id="current"] button').trigger('click'); await flushPromises()
  45. expect(wrapper.get('[role="alert"]').text()).toContain('已取消')
  46. expect(wrapper.find('[role="status"]').exists()).toBe(false)
  47. expect(wrapper.get('[data-host-id="current"] button').attributes('disabled')).toBeUndefined()
  48. })