sseSource.test.ts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import { describe, test, it, expect, beforeEach, afterEach, vi } from 'vitest'
  2. import SseSource from "~/services/sse/sseSource";
  3. import {EventSourcePolyfill} from "event-source-polyfill";
  4. class TestableSseSource extends SseSource {
  5. public getUrl() { return this.url }
  6. public getOnOpen() { return this.onOpen }
  7. public getOnMessage() { return this.onMessage }
  8. public getOnClose() { return this.onClose }
  9. public getWithCredentials() { return this.withCredentials }
  10. public createEventSource(url: string, withCredentials: boolean): EventSourcePolyfill {
  11. return super.createEventSource(url, withCredentials)
  12. }
  13. public setEventSource(eventSource: EventSourcePolyfill) {
  14. this.eventSource = eventSource
  15. }
  16. }
  17. let mercureUrl: string
  18. let topic: string
  19. let onOpen: () => any
  20. let onMessage: (data: Array<any>) => any
  21. let onClose: () => any
  22. let sseSource: TestableSseSource
  23. const init_console_log = console.log
  24. beforeEach(() => {
  25. mercureUrl = 'https://my.mercure.com'
  26. topic = 'mytopic'
  27. onOpen = () => 'opened'
  28. onMessage = (data: Array<any>) => 'message'
  29. onClose = () => 'closed'
  30. sseSource = new TestableSseSource(mercureUrl, topic, onOpen, onMessage, onClose, false)
  31. })
  32. afterEach(() => {
  33. console.log = init_console_log
  34. vi.restoreAllMocks()
  35. })
  36. describe('test constructor', () => {
  37. test('with all params', () => {
  38. expect(sseSource.getUrl().toString()).toEqual('https://my.mercure.com/?topic=mytopic')
  39. expect(sseSource.getOnOpen()).toEqual(onOpen)
  40. expect(sseSource.getOnMessage()).toEqual(onMessage)
  41. expect(sseSource.getOnClose()).toEqual(onClose)
  42. expect(sseSource.getWithCredentials()).toEqual(false)
  43. })
  44. })
  45. describe('createEventSource', () => {
  46. test('simple call', () => {
  47. const eventSource = sseSource.createEventSource(mercureUrl, false)
  48. expect(eventSource.readyState).toEqual(0)
  49. expect(eventSource.url).toEqual(mercureUrl)
  50. expect(eventSource.withCredentials).toEqual(false)
  51. })
  52. })
  53. describe('isConnected', () => {
  54. test('no event source', () => {
  55. expect(sseSource.isConnected()).toEqual(false)
  56. })
  57. test('got an event source, but it is not open', () => {
  58. const eventSource = sseSource.createEventSource(mercureUrl, true)
  59. sseSource.setEventSource(eventSource)
  60. expect(sseSource.isConnected()).toEqual(false)
  61. })
  62. test('got an open event source', () => {
  63. // @ts-ignore
  64. const eventSource = vi.fn() as EventSourcePolyfill
  65. // @ts-ignore
  66. // noinspection JSConstantReassignment
  67. eventSource.readyState = EventSourcePolyfill.OPEN
  68. sseSource.setEventSource(eventSource)
  69. expect(sseSource.isConnected()).toEqual(true)
  70. })
  71. })
  72. describe('subscribe', () => {
  73. test('already connected', () => {
  74. sseSource.isConnected = vi.fn(() => true)
  75. expect(() => sseSource.subscribe()).toThrowError("SSE - Already subscribed to this event source")
  76. })
  77. test('is server side', () => {
  78. process.server = true
  79. expect(() => sseSource.subscribe()).toThrowError("SSE - Cannot subscribe on server side")
  80. process.server = false
  81. })
  82. test('successful subscription', () => {
  83. onOpen = vi.fn(() => null)
  84. onMessage = vi.fn((data: Array<any>) => null)
  85. sseSource = new TestableSseSource(mercureUrl, topic, onOpen, onMessage, onClose)
  86. const dummyEventSource = new EventSourcePolyfill('https://my.mercure.com', { withCredentials: true })
  87. sseSource.createEventSource = vi.fn((url: string, withCredentials: boolean) => {
  88. return dummyEventSource
  89. })
  90. console.log = vi.fn()
  91. console.error = vi.fn()
  92. sseSource.subscribe()
  93. expect(sseSource.createEventSource).toHaveBeenCalled()
  94. // @ts-ignore
  95. dummyEventSource.onopen()
  96. expect(onOpen).toHaveBeenCalled()
  97. expect(console.log).toHaveBeenCalledWith('SSE - Listening for events...')
  98. // @ts-ignore
  99. dummyEventSource.onmessage({ data: '1' })
  100. expect(onMessage).toHaveBeenCalledWith(1)
  101. // @ts-ignore
  102. const event = { target: { readyState: EventSourcePolyfill.CLOSED } }
  103. dummyEventSource.close = vi.fn()
  104. // @ts-ignore
  105. dummyEventSource.onerror(event)
  106. expect(console.log).toHaveBeenCalledWith('SSE closed')
  107. expect(dummyEventSource.close).toHaveBeenCalled()
  108. })
  109. })
  110. describe('unsubscribe', () => {
  111. test('if no event source, does nothing', () => {
  112. onClose = vi.fn(() => null)
  113. sseSource = new TestableSseSource(mercureUrl, topic, onOpen, onMessage, onClose)
  114. sseSource.unsubscribe()
  115. expect(onClose).toHaveBeenCalledTimes(0)
  116. })
  117. test('if event source is not opened, does nothing', () => {
  118. onClose = vi.fn(() => null)
  119. sseSource = new TestableSseSource(mercureUrl, topic, onOpen, onMessage, onClose)
  120. // @ts-ignore
  121. const eventSource = vi.fn() as EventSourcePolyfill
  122. // @ts-ignore
  123. // noinspection JSConstantReassignment
  124. eventSource.readyState = EventSourcePolyfill.CLOSED
  125. sseSource.setEventSource(eventSource)
  126. sseSource.unsubscribe()
  127. expect(onClose).toHaveBeenCalledTimes(0)
  128. })
  129. test('has an open subscription', () => {
  130. onClose = vi.fn(() => null)
  131. sseSource = new TestableSseSource(mercureUrl, topic, onOpen, onMessage, onClose)
  132. // @ts-ignore
  133. const eventSource = vi.fn() as EventSourcePolyfill
  134. // @ts-ignore
  135. // noinspection JSConstantReassignment
  136. eventSource.readyState = EventSourcePolyfill.OPEN
  137. eventSource.close = vi.fn(() => null)
  138. sseSource.setEventSource(eventSource)
  139. console.log = vi.fn()
  140. sseSource.unsubscribe()
  141. expect(eventSource.close).toHaveBeenCalled()
  142. expect(onClose).toHaveBeenCalled()
  143. expect(console.log).toHaveBeenCalledWith('SSE - Subscription closed')
  144. })
  145. })