123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- import { NetworkStatus } from '@apollo/client/core'
- import { useSubscription } from '@vue/apollo-composable'
- import { createMockSubscription } from 'mock-apollo-client'
- import { effectScope } from 'vue'
- import { SampleTypedSubscriptionDocument } from '#tests/fixtures/graphqlSampleTypes.ts'
- import type {
- SampleUpdatedSubscription,
- SampleUpdatedSubscriptionVariables,
- } from '#tests/fixtures/graphqlSampleTypes.ts'
- import createMockClient from '#tests/support/mock-apollo-client.ts'
- import { useNotifications } from '#shared/components/CommonNotifications/index.ts'
- import SubscriptionHandler from '../SubscriptionHandler.ts'
- import type { IMockSubscription } from 'mock-apollo-client'
- const subscriptionFunctionCallSpy = vi.fn()
- const subscriptionSampleResult = {
- sampleUpdated: { id: 1, title: 'Test Title', text: 'Test Text' },
- }
- const subscriptionSampleResultUpdated = {
- sampleUpdated: { id: 1, title: 'Test Title2', text: 'Test Text2' },
- }
- const subscriptionSampleErrorResult = {
- networkStatus: NetworkStatus.error,
- errors: [
- {
- message: 'GraphQL Error',
- extensions: { type: 'Exceptions::UnknownError' },
- },
- ],
- }
- let mockSubscription: IMockSubscription
- const mockClient = () => {
- mockSubscription = createMockSubscription()
- createMockClient([
- {
- operationDocument: SampleTypedSubscriptionDocument,
- handler: () => mockSubscription,
- },
- ])
- subscriptionFunctionCallSpy.mockClear()
- }
- const scope = effectScope()
- describe('SubscriptionHandler', () => {
- const sampleSubscription = (
- variables: SampleUpdatedSubscriptionVariables,
- options = {},
- ) => {
- subscriptionFunctionCallSpy()
- return useSubscription<
- SampleUpdatedSubscription,
- SampleUpdatedSubscriptionVariables
- >(SampleTypedSubscriptionDocument, variables, options)
- }
- describe('constructor', () => {
- beforeEach(() => {
- mockClient()
- })
- it('instance can be created', () => {
- scope.run(() => {
- const subscriptionHandlerObject = new SubscriptionHandler(
- sampleSubscription({ id: 1 }),
- )
- expect(subscriptionHandlerObject).toBeInstanceOf(SubscriptionHandler)
- })
- })
- it('default handler options can be changed', () => {
- scope.run(() => {
- const errorNotificationMessage = 'A test message.'
- const subscriptionHandlerObject = new SubscriptionHandler(
- sampleSubscription({ id: 1 }),
- {
- errorNotificationMessage,
- },
- )
- expect(
- subscriptionHandlerObject.handlerOptions.errorNotificationMessage,
- ).toBe(errorNotificationMessage)
- })
- })
- it('given subscription function was executed', () => {
- scope.run(() => {
- const subscriptionHandlerObject = new SubscriptionHandler(
- sampleSubscription({ id: 1 }),
- )
- expect(subscriptionFunctionCallSpy).toBeCalled()
- expect(subscriptionHandlerObject.operationResult).toBeTruthy()
- })
- })
- })
- describe('loading', () => {
- beforeEach(() => {
- mockClient()
- })
- it('loading state will be updated', async () => {
- await scope.run(async () => {
- expect.assertions(2)
- const subscriptionHandlerObject = new SubscriptionHandler(
- sampleSubscription({ id: 1 }),
- )
- expect(subscriptionHandlerObject.loading().value).toBe(true)
- const subscribed = subscriptionHandlerObject.onSubscribed()
- mockSubscription.next({
- data: subscriptionSampleResult,
- })
- await subscribed
- expect(subscriptionHandlerObject.loading().value).toBe(false)
- })
- })
- })
- describe('result/subscribe', () => {
- beforeEach(() => {
- mockClient()
- })
- it('subscribed', async () => {
- await scope.run(async () => {
- expect.assertions(1)
- const subscriptionHandlerObject = new SubscriptionHandler(
- sampleSubscription({ id: 1 }),
- )
- const subscribed = subscriptionHandlerObject.onSubscribed()
- mockSubscription.next({
- data: subscriptionSampleResult,
- })
- const result = await subscribed
- expect(result).toEqual(subscriptionSampleResult)
- })
- })
- it('watch on result change', async () => {
- await scope.run(async () => {
- expect.assertions(2)
- const subscriptionHandlerObject = new SubscriptionHandler(
- sampleSubscription({ id: 1 }),
- )
- const subscribed = subscriptionHandlerObject.onSubscribed()
- mockSubscription.next({
- data: subscriptionSampleResult,
- })
- await subscribed
- let watchCount = 0
- subscriptionHandlerObject.watchOnResult((result) => {
- expect(result).toEqual(
- watchCount === 0
- ? subscriptionSampleResult
- : subscriptionSampleResultUpdated,
- )
- watchCount += 1
- })
- mockSubscription.next({
- data: subscriptionSampleResultUpdated,
- })
- })
- })
- it('register onResult callback', async () => {
- await scope.run(async () => {
- expect.assertions(1)
- const subscriptionHandlerObject = new SubscriptionHandler(
- sampleSubscription({ id: 1 }),
- )
- const resultCallbackSpy = vi.fn()
- const subscribed = subscriptionHandlerObject.onSubscribed()
- mockSubscription.next({
- data: subscriptionSampleResult,
- })
- await subscribed
- subscriptionHandlerObject.onResult((result) => {
- resultCallbackSpy(result)
- })
- mockSubscription.next({
- data: subscriptionSampleResultUpdated,
- })
- expect(resultCallbackSpy).toHaveBeenCalledWith({
- data: subscriptionSampleResultUpdated,
- })
- })
- })
- })
- describe('error handling', () => {
- describe('GraphQL errors', () => {
- beforeEach(() => {
- mockClient()
- })
- it('notification is triggerd', () => {
- scope.run(() => {
- const subscriptionHandlerObject = new SubscriptionHandler(
- sampleSubscription({ id: 1 }),
- )
- mockSubscription.next(subscriptionSampleErrorResult)
- expect(subscriptionHandlerObject.operationError().value).toBeTruthy()
- const { notifications } = useNotifications()
- expect(notifications.value.length).toBe(1)
- })
- })
- it('use error callback', () => {
- scope.run(() => {
- const errorCallbackSpy = vi.fn()
- const subscriptionHandlerObject = new SubscriptionHandler(
- sampleSubscription({ id: 1 }),
- {
- errorCallback: (error) => {
- errorCallbackSpy(error)
- },
- },
- )
- mockSubscription.next(subscriptionSampleErrorResult)
- expect(subscriptionHandlerObject.operationError().value).toBeTruthy()
- expect(errorCallbackSpy).toHaveBeenCalledWith({
- type: 'Exceptions::UnknownError',
- message: 'GraphQL Error',
- })
- })
- })
- })
- })
- describe('use operation result wrapper', () => {
- beforeEach(() => {
- mockClient()
- })
- it('use returned query options', () => {
- scope.run(() => {
- const subscriptionHandlerObject = new SubscriptionHandler(
- sampleSubscription({ id: 1 }),
- )
- expect(subscriptionHandlerObject.options()).toBeTruthy()
- })
- })
- })
- })
|