|
@@ -1,22 +1,173 @@
|
|
|
import { describe, test, it, expect } from 'vitest'
|
|
import { describe, test, it, expect } from 'vitest'
|
|
|
|
|
+import SseSource from "~/services/sse/sseSource";
|
|
|
|
|
+import {EventSourcePolyfill} from "event-source-polyfill";
|
|
|
|
|
|
|
|
|
|
+class TestableSseSource extends SseSource {
|
|
|
|
|
+ public getUrl() { return this.url }
|
|
|
|
|
+ public getOnOpen() { return this.onOpen }
|
|
|
|
|
+ public getOnMessage() { return this.onMessage }
|
|
|
|
|
+ public getOnClose() { return this.onClose }
|
|
|
|
|
+ public getWithCredentials() { return this.withCredentials }
|
|
|
|
|
+
|
|
|
|
|
+ public createEventSource(url: string, withCredentials: boolean): EventSourcePolyfill {
|
|
|
|
|
+ return super.createEventSource(url, withCredentials)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public setEventSource(eventSource: EventSourcePolyfill) {
|
|
|
|
|
+ this.eventSource = eventSource
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+let mercureUrl: string
|
|
|
|
|
+let topic: string
|
|
|
|
|
+let onOpen: () => any
|
|
|
|
|
+let onMessage: (data: Array<any>) => any
|
|
|
|
|
+let onClose: () => any
|
|
|
|
|
+let sseSource: TestableSseSource
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
beforeEach(() => {
|
|
|
-
|
|
|
|
|
|
|
+ mercureUrl = 'https://my.mercure.com'
|
|
|
|
|
+ topic = 'mytopic'
|
|
|
|
|
+
|
|
|
|
|
+ onOpen = () => 'opened'
|
|
|
|
|
+ onMessage = (data: Array<any>) => 'message'
|
|
|
|
|
+ onClose = () => 'closed'
|
|
|
|
|
+
|
|
|
|
|
+ sseSource = new TestableSseSource(mercureUrl, topic, onOpen, onMessage, onClose, false)
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+afterEach(() => {
|
|
|
|
|
+ vi.restoreAllMocks()
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+describe('test constructor', () => {
|
|
|
|
|
+ test('with all params', () => {
|
|
|
|
|
+ expect(sseSource.getUrl().toString()).toEqual('https://my.mercure.com/?topic=mytopic')
|
|
|
|
|
+ expect(sseSource.getOnOpen()).toEqual(onOpen)
|
|
|
|
|
+ expect(sseSource.getOnMessage()).toEqual(onMessage)
|
|
|
|
|
+ expect(sseSource.getOnClose()).toEqual(onClose)
|
|
|
|
|
+ expect(sseSource.getWithCredentials()).toEqual(false)
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
describe('createEventSource', () => {
|
|
describe('createEventSource', () => {
|
|
|
|
|
+ test('simple call', () => {
|
|
|
|
|
+ const eventSource = sseSource.createEventSource(mercureUrl, false)
|
|
|
|
|
|
|
|
|
|
+ expect(eventSource.readyState).toEqual(0)
|
|
|
|
|
+ expect(eventSource.url).toEqual(mercureUrl)
|
|
|
|
|
+ expect(eventSource.withCredentials).toEqual(false)
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
describe('isConnected', () => {
|
|
describe('isConnected', () => {
|
|
|
-
|
|
|
|
|
|
|
+ test('no event source', () => {
|
|
|
|
|
+ expect(sseSource.isConnected()).toEqual(false)
|
|
|
|
|
+ })
|
|
|
|
|
+ test('got an event source, but it is not open', () => {
|
|
|
|
|
+ const eventSource = sseSource.createEventSource(mercureUrl, true)
|
|
|
|
|
+ sseSource.setEventSource(eventSource)
|
|
|
|
|
+ expect(sseSource.isConnected()).toEqual(false)
|
|
|
|
|
+ })
|
|
|
|
|
+ test('got an open event source', () => {
|
|
|
|
|
+ // @ts-ignore
|
|
|
|
|
+ const eventSource = vi.fn() as EventSourcePolyfill
|
|
|
|
|
+ // @ts-ignore
|
|
|
|
|
+ // noinspection JSConstantReassignment
|
|
|
|
|
+ eventSource.readyState = EventSourcePolyfill.OPEN
|
|
|
|
|
+ sseSource.setEventSource(eventSource)
|
|
|
|
|
+ expect(sseSource.isConnected()).toEqual(true)
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
describe('subscribe', () => {
|
|
describe('subscribe', () => {
|
|
|
|
|
+ test('already connected', () => {
|
|
|
|
|
+ sseSource.isConnected = vi.fn(() => true)
|
|
|
|
|
+ expect(() => sseSource.subscribe()).toThrowError("SSE - Already subscribed to this event source")
|
|
|
|
|
+ })
|
|
|
|
|
+ test('is server side', () => {
|
|
|
|
|
+ process.server = true
|
|
|
|
|
+ expect(() => sseSource.subscribe()).toThrowError("SSE - Cannot subscribe on server side")
|
|
|
|
|
+ process.server = false
|
|
|
|
|
+ })
|
|
|
|
|
+ test('successful subscription', () => {
|
|
|
|
|
+
|
|
|
|
|
+ onOpen = vi.fn(() => null)
|
|
|
|
|
+ onMessage = vi.fn((data: Array<any>) => null)
|
|
|
|
|
+
|
|
|
|
|
+ sseSource = new TestableSseSource(mercureUrl, topic, onOpen, onMessage, onClose)
|
|
|
|
|
+
|
|
|
|
|
+ const dummyEventSource = new EventSourcePolyfill('https://my.mercure.com', { withCredentials: true })
|
|
|
|
|
+
|
|
|
|
|
+ sseSource.createEventSource = vi.fn((url: string, withCredentials: boolean) => {
|
|
|
|
|
+ return dummyEventSource
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
|
|
+ console.log = vi.fn()
|
|
|
|
|
+ console.error = vi.fn()
|
|
|
|
|
+
|
|
|
|
|
+ sseSource.subscribe()
|
|
|
|
|
+ expect(sseSource.createEventSource).toHaveBeenCalled()
|
|
|
|
|
+
|
|
|
|
|
+ // @ts-ignore
|
|
|
|
|
+ dummyEventSource.onopen()
|
|
|
|
|
+ expect(onOpen).toHaveBeenCalled()
|
|
|
|
|
+ expect(console.log).toHaveBeenCalledWith('SSE - Listening for events...')
|
|
|
|
|
+
|
|
|
|
|
+ // @ts-ignore
|
|
|
|
|
+ dummyEventSource.onmessage({ data: '1' })
|
|
|
|
|
+ expect(onMessage).toHaveBeenCalledWith(1)
|
|
|
|
|
+
|
|
|
|
|
+ // @ts-ignore
|
|
|
|
|
+ dummyEventSource.onerror()
|
|
|
|
|
+ expect(console.error).toHaveBeenCalledWith('SSE - An error happened')
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
describe('unsubscribe', () => {
|
|
describe('unsubscribe', () => {
|
|
|
|
|
+ test('if no event source, does nothing', () => {
|
|
|
|
|
+ onClose = vi.fn(() => null)
|
|
|
|
|
+ sseSource = new TestableSseSource(mercureUrl, topic, onOpen, onMessage, onClose)
|
|
|
|
|
+
|
|
|
|
|
+ sseSource.unsubscribe()
|
|
|
|
|
+
|
|
|
|
|
+ expect(onClose).toHaveBeenCalledTimes(0)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ test('if event source is not opened, does nothing', () => {
|
|
|
|
|
+ onClose = vi.fn(() => null)
|
|
|
|
|
+ sseSource = new TestableSseSource(mercureUrl, topic, onOpen, onMessage, onClose)
|
|
|
|
|
+
|
|
|
|
|
+ // @ts-ignore
|
|
|
|
|
+ const eventSource = vi.fn() as EventSourcePolyfill
|
|
|
|
|
+ // @ts-ignore
|
|
|
|
|
+ // noinspection JSConstantReassignment
|
|
|
|
|
+ eventSource.readyState = EventSourcePolyfill.CLOSED
|
|
|
|
|
+ sseSource.setEventSource(eventSource)
|
|
|
|
|
+
|
|
|
|
|
+ sseSource.unsubscribe()
|
|
|
|
|
+
|
|
|
|
|
+ expect(onClose).toHaveBeenCalledTimes(0)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ test('has an open subscription', () => {
|
|
|
|
|
+ onClose = vi.fn(() => null)
|
|
|
|
|
+ sseSource = new TestableSseSource(mercureUrl, topic, onOpen, onMessage, onClose)
|
|
|
|
|
+
|
|
|
|
|
+ // @ts-ignore
|
|
|
|
|
+ const eventSource = vi.fn() as EventSourcePolyfill
|
|
|
|
|
+ // @ts-ignore
|
|
|
|
|
+ // noinspection JSConstantReassignment
|
|
|
|
|
+ eventSource.readyState = EventSourcePolyfill.OPEN
|
|
|
|
|
+ eventSource.close = vi.fn(() => null)
|
|
|
|
|
+ sseSource.setEventSource(eventSource)
|
|
|
|
|
+
|
|
|
|
|
+ console.log = vi.fn()
|
|
|
|
|
+
|
|
|
|
|
+ sseSource.unsubscribe()
|
|
|
|
|
|
|
|
|
|
+ expect(eventSource.close).toHaveBeenCalled()
|
|
|
|
|
+ expect(onClose).toHaveBeenCalled()
|
|
|
|
|
+ expect(console.log).toHaveBeenCalledWith('SSE - Subscription closed')
|
|
|
|
|
+ })
|
|
|
})
|
|
})
|