vue-lifecycle-hook.spec.ts 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import { afterEach, describe, expect, it, vi } from 'vitest'
  2. import { useViewerLifecycle } from '../packages/components/vue3/src/package/components/FileViewer/hooks/useViewerLifecycle'
  3. import type {
  4. FileViewerLifecycleContext,
  5. FileViewerLifecyclePhase,
  6. FileViewerOperationContext,
  7. FileViewerOptions
  8. } from '../packages/components/vue3/src/package/common/type'
  9. describe('Vue FileViewer lifecycle hook', () => {
  10. afterEach(() => {
  11. vi.useRealTimers()
  12. })
  13. it('keeps lifecycle timing, unload events and operation guards aligned with core contracts', async () => {
  14. vi.useFakeTimers()
  15. vi.setSystemTime(1240)
  16. const lifecycleEvents: Array<{ event: FileViewerLifecyclePhase; context: FileViewerLifecycleContext }> = []
  17. const operationEvents: Array<{ event: string; context: FileViewerOperationContext }> = []
  18. const operationErrorMessages: string[] = []
  19. const handleOperationError = vi.fn()
  20. const options: FileViewerOptions = {
  21. beforeOperation: context => {
  22. operationEvents.push({ event: `guard:${context.operation}`, context })
  23. return false
  24. }
  25. }
  26. const lifecycle = useViewerLifecycle({
  27. getOptions: () => options,
  28. getFilename: () => 'demo.pdf',
  29. getBufferSize: () => 4096,
  30. getCurrentFile: () => null,
  31. getCurrentVersion: () => 3,
  32. getFallbackFile: () => undefined,
  33. getFallbackUrl: () => '/example/demo.pdf',
  34. emitLifecycle: (event, context) => {
  35. lifecycleEvents.push({ event, context })
  36. },
  37. emitOperationBefore: context => {
  38. operationEvents.push({ event: `before:${context.operation}`, context })
  39. },
  40. emitOperationCancel: context => {
  41. operationEvents.push({ event: `cancel:${context.operation}`, context })
  42. },
  43. formatErrorMessage: (prefix, error) => `${prefix}:${error instanceof Error ? error.message : String(error)}`,
  44. handleLifecycleError: vi.fn(),
  45. handleOperationError,
  46. onOperationErrorMessage: message => {
  47. operationErrorMessages.push(message)
  48. }
  49. })
  50. lifecycle.markLoadStarted(3, 1000)
  51. const loadedContext = lifecycle.buildRenderCompleteState({
  52. version: 3,
  53. source: 'url',
  54. sourceUrl: '/example/demo.pdf'
  55. }).lifecycleContext
  56. expect(loadedContext).toMatchObject({
  57. phase: 'load-complete',
  58. filename: 'demo.pdf',
  59. source: 'url',
  60. size: 4096,
  61. duration: 240
  62. })
  63. lifecycle.setActiveDocumentContext(loadedContext)
  64. await expect(lifecycle.runBeforeOperation('download')).resolves.toBe(false)
  65. expect(operationEvents.map(item => item.event)).toEqual([
  66. 'before:download',
  67. 'guard:download',
  68. 'cancel:download'
  69. ])
  70. options.beforeOperation = () => {
  71. throw new Error('denied')
  72. }
  73. await expect(lifecycle.runBeforeOperation('print')).resolves.toBe(false)
  74. expect(handleOperationError).toHaveBeenCalledTimes(1)
  75. expect(operationErrorMessages).toEqual(['操作前置校验失败:denied'])
  76. const unloadContext = lifecycle.notifyActiveUnloadStart('replace')
  77. lifecycle.clearActiveDocumentContext()
  78. lifecycle.notifyActiveUnloadComplete(unloadContext, 'replace')
  79. expect(lifecycleEvents.map(item => item.event)).toEqual([
  80. 'unload-start',
  81. 'unload-complete'
  82. ])
  83. expect(lifecycleEvents.every(item => item.context.reason === 'replace')).toBe(true)
  84. })
  85. })