clipboard.test.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import { afterEach, describe, expect, it, vi } from 'vitest'
  2. import { copyTextToClipboard } from '@/utils/clipboard'
  3. function secureContext(value: boolean) {
  4. Object.defineProperty(window, 'isSecureContext', { configurable: true, value })
  5. }
  6. function clipboard(writeText?: (text: string) => Promise<void>) {
  7. Object.defineProperty(navigator, 'clipboard', {
  8. configurable: true,
  9. value: writeText ? { writeText } : undefined,
  10. })
  11. }
  12. afterEach(() => {
  13. vi.restoreAllMocks()
  14. Reflect.deleteProperty(navigator, 'clipboard')
  15. Object.defineProperty(window, 'isSecureContext', { configurable: true, value: false })
  16. Object.defineProperty(document, 'execCommand', { configurable: true, value: undefined })
  17. })
  18. describe('copyTextToClipboard', () => {
  19. it('uses the asynchronous clipboard API in a secure context', async () => {
  20. secureContext(true)
  21. const writeText = vi.fn(async () => undefined)
  22. clipboard(writeText)
  23. await expect(copyTextToClipboard('安全复制')).resolves.toBe(true)
  24. expect(writeText).toHaveBeenCalledWith('安全复制')
  25. })
  26. it('falls back when an embedded browser rejects clipboard permission', async () => {
  27. secureContext(true)
  28. clipboard(vi.fn(async () => { throw new Error('NotAllowedError') }))
  29. const execCommand = vi.fn(() => true)
  30. Object.defineProperty(document, 'execCommand', { configurable: true, value: execCommand })
  31. await expect(copyTextToClipboard('兼容复制')).resolves.toBe(true)
  32. expect(execCommand).toHaveBeenCalledWith('copy')
  33. expect(document.querySelector('textarea')).toBeNull()
  34. })
  35. it('reports failure and cleans up when both clipboard paths are unavailable', async () => {
  36. secureContext(false)
  37. clipboard()
  38. Object.defineProperty(document, 'execCommand', {
  39. configurable: true,
  40. value: vi.fn(() => { throw new Error('copy denied') }),
  41. })
  42. await expect(copyTextToClipboard('无法复制')).resolves.toBe(false)
  43. expect(document.querySelector('textarea')).toBeNull()
  44. })
  45. })