From 621ceeb54544aa449ded84bb1540095956e4f080 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Wed, 25 Jun 2025 12:01:53 +0800 Subject: [PATCH] revamp tests --- .../src/colada/queries/actuator-info.test.ts | 44 ++++++++--------- .../src/colada/queries/announcements.test.ts | 14 +++--- .../src/colada/queries/app-releases.test.ts | 17 ++++--- next-ui/src/colada/queries/app-releases.ts | 3 +- next-ui/src/components/BuildCommit.stories.ts | 15 ++---- .../src/components/BuildVersion.stories.ts | 23 ++++----- next-ui/src/mocks/api/handlers.ts | 17 +++++-- next-ui/src/mocks/api/handlers/actuator.ts | 45 ------------------ .../src/mocks/api/handlers/announcements.ts | 47 ------------------- next-ui/src/mocks/api/handlers/base.ts | 6 --- next-ui/src/mocks/api/handlers/releases.ts | 31 ++++-------- next-ui/src/mocks/api/httpTyped.ts | 4 ++ 12 files changed, 85 insertions(+), 181 deletions(-) delete mode 100644 next-ui/src/mocks/api/handlers/actuator.ts delete mode 100644 next-ui/src/mocks/api/handlers/announcements.ts delete mode 100644 next-ui/src/mocks/api/handlers/base.ts create mode 100644 next-ui/src/mocks/api/httpTyped.ts diff --git a/next-ui/src/colada/queries/actuator-info.test.ts b/next-ui/src/colada/queries/actuator-info.test.ts index 80486d49c..3d2087357 100644 --- a/next-ui/src/colada/queries/actuator-info.test.ts +++ b/next-ui/src/colada/queries/actuator-info.test.ts @@ -1,11 +1,11 @@ -import { afterAll, afterEach, beforeAll, expect, test } from 'vitest' +import { afterAll, afterEach, beforeAll, describe, expect, test } from 'vitest' import { server } from '@/mocks/api/node' import { useActuatorInfo } from '@/colada/queries/actuator-info' import { createMockColada } from '@/mocks/pinia-colada' -import { http } from 'msw' -import { baseUrl, response401Unauthorized } from '@/mocks/api/handlers/base' import { enableAutoUnmount } from '@vue/test-utils' import type { ErrorCause } from '@/api/komga-client' +import { response401Unauthorized } from '@/mocks/api/handlers' +import { httpTyped } from '@/mocks/api/httpTyped' beforeAll(() => server.listen()) afterEach(() => server.resetHandlers()) @@ -13,23 +13,25 @@ afterAll(() => server.close()) enableAutoUnmount(afterEach) -test('when getting actuator-info then values are correct', async () => { - createMockColada(useActuatorInfo) - const { buildVersion, commitId, refresh } = useActuatorInfo() +describe('colada actuator', () => { + test('when getting actuator-info then values are correct', async () => { + createMockColada(useActuatorInfo) + const { buildVersion, commitId, refresh } = useActuatorInfo() - await refresh() - expect(buildVersion.value).toBe('9.9.9') - expect(commitId.value).toBe('ABC123') -}) - -test('when failing to get actuator-info then values are undefined', async () => { - server.use(http.get(baseUrl + 'actuator/info', response401Unauthorized)) - - createMockColada(useActuatorInfo) - const { buildVersion, commitId, refresh, error } = useActuatorInfo() - - await refresh() - expect(buildVersion.value).toBeUndefined() - expect(commitId.value).toBeUndefined() - expect((error.value?.cause as ErrorCause).status).toBe(401) + await refresh() + expect(buildVersion.value).toBe('1.21.2') + expect(commitId.value).toBe('9be980d') + }) + + test('when failing to get actuator-info then values are undefined', async () => { + server.use(httpTyped.get('/actuator/info', response401Unauthorized)) + + createMockColada(useActuatorInfo) + const { buildVersion, commitId, refresh, error } = useActuatorInfo() + + await refresh() + expect(buildVersion.value).toBeUndefined() + expect(commitId.value).toBeUndefined() + expect((error.value?.cause as ErrorCause).status).toBe(401) + }) }) diff --git a/next-ui/src/colada/queries/announcements.test.ts b/next-ui/src/colada/queries/announcements.test.ts index cf93cc09c..2afec7b68 100644 --- a/next-ui/src/colada/queries/announcements.test.ts +++ b/next-ui/src/colada/queries/announcements.test.ts @@ -1,4 +1,4 @@ -import { afterAll, afterEach, beforeAll, expect, test } from 'vitest' +import { afterAll, afterEach, beforeAll, describe, expect, test } from 'vitest' import { server } from '@/mocks/api/node' import { createMockColada } from '@/mocks/pinia-colada' import { useAnnouncements } from '@/colada/queries/announcements' @@ -10,10 +10,12 @@ afterAll(() => server.close()) enableAutoUnmount(afterEach) -test('when getting announcements then values are correct', async () => { - createMockColada(useAnnouncements) - const { unreadCount, refresh } = useAnnouncements() +describe('colada announcements', () => { + test('when getting announcements then values are correct', async () => { + createMockColada(useAnnouncements) + const { unreadCount, refresh } = useAnnouncements() - await refresh() - expect(unreadCount.value).toBe(1) + await refresh() + expect(unreadCount.value).toBe(1) + }) }) diff --git a/next-ui/src/colada/queries/app-releases.test.ts b/next-ui/src/colada/queries/app-releases.test.ts index 777695222..d85bfc095 100644 --- a/next-ui/src/colada/queries/app-releases.test.ts +++ b/next-ui/src/colada/queries/app-releases.test.ts @@ -1,4 +1,4 @@ -import { afterAll, afterEach, beforeAll, expect, test } from 'vitest' +import { afterAll, afterEach, beforeAll, describe, expect, test } from 'vitest' import { server } from '@/mocks/api/node' import { createMockColada } from '@/mocks/pinia-colada' import { useAppReleases } from '@/colada/queries/app-releases' @@ -10,11 +10,14 @@ afterAll(() => server.close()) enableAutoUnmount(afterEach) -test('when getting app releases then values are correct', async () => { - createMockColada(useAppReleases) - const { latestRelease, isLatestVersion, refresh } = useAppReleases() +describe('colada releases', () => { + test('when getting app releases then values are correct', async () => { + createMockColada(useAppReleases) + const { latestRelease, isLatestVersion, refresh, actuatorRefresh } = useAppReleases() - await refresh() - expect(latestRelease.value!.version).toBe('9.9.9') - expect(isLatestVersion.value).toBe(true) + await refresh() + await actuatorRefresh() + expect(latestRelease.value!.version).toBe('1.21.2') + expect(isLatestVersion.value).toBe(true) + }) }) diff --git a/next-ui/src/colada/queries/app-releases.ts b/next-ui/src/colada/queries/app-releases.ts index b92b15aea..e0aa9ccc4 100644 --- a/next-ui/src/colada/queries/app-releases.ts +++ b/next-ui/src/colada/queries/app-releases.ts @@ -15,7 +15,7 @@ export const useAppReleases = defineQuery(() => { gcTime: false, }) - const { buildVersion } = useActuatorInfo() + const { buildVersion, refresh: actuatorRefresh } = useActuatorInfo() const latestRelease = computed(() => data.value?.find((x) => x.latest)) const isLatestVersion = computed(() => { @@ -30,5 +30,6 @@ export const useAppReleases = defineQuery(() => { buildVersion, latestRelease, isLatestVersion, + actuatorRefresh, } }) diff --git a/next-ui/src/components/BuildCommit.stories.ts b/next-ui/src/components/BuildCommit.stories.ts index 6371c6b2f..f2509b1cf 100644 --- a/next-ui/src/components/BuildCommit.stories.ts +++ b/next-ui/src/components/BuildCommit.stories.ts @@ -1,9 +1,9 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite' import BuildCommit from './BuildCommit.vue' -import { http, HttpResponse, delay } from 'msw' -import { baseUrl, response401Unauthorized } from '@/mocks/api/handlers/base' -import { actuatorResponseOk } from '@/mocks/api/handlers/actuator' +import { http, delay } from 'msw' + +import { response401Unauthorized } from '@/mocks/api/handlers' const meta = { component: BuildCommit, @@ -30,12 +30,7 @@ export const Default: Story = { export const Loading: Story = { parameters: { msw: { - handlers: [ - http.get(baseUrl + 'actuator/info', async () => { - await delay(5_000) - return HttpResponse.json(actuatorResponseOk) - }), - ], + handlers: [http.all('*', async () => await delay(5_000))], }, }, } @@ -43,7 +38,7 @@ export const Loading: Story = { export const Error: Story = { parameters: { msw: { - handlers: [http.get(baseUrl + 'actuator/info', response401Unauthorized)], + handlers: [http.all('*', response401Unauthorized)], }, }, } diff --git a/next-ui/src/components/BuildVersion.stories.ts b/next-ui/src/components/BuildVersion.stories.ts index c3cc0531d..820f7487d 100644 --- a/next-ui/src/components/BuildVersion.stories.ts +++ b/next-ui/src/components/BuildVersion.stories.ts @@ -1,9 +1,10 @@ import type { Meta, StoryObj } from '@storybook/vue3-vite' -import { http, HttpResponse, delay } from 'msw' -import { baseUrl, response401Unauthorized } from '@/mocks/api/handlers/base' +import { http, delay } from 'msw' import BuildVersion from './BuildVersion.vue' -import { releasesResponseOk, releasesResponseOkNotLatest } from '@/mocks/api/handlers/releases' +import { releasesResponseOkNotLatest } from '@/mocks/api/handlers/releases' +import { response401Unauthorized } from '@/mocks/api/handlers' +import { httpTyped } from '@/mocks/api/httpTyped' const meta = { component: BuildVersion, @@ -31,7 +32,9 @@ export const OutdatedVersion: Story = { parameters: { msw: { handlers: [ - http.get(baseUrl + 'api/v1/releases', () => HttpResponse.json(releasesResponseOkNotLatest)), + httpTyped.get('/api/v1/releases', ({ response }) => + response(200).json(releasesResponseOkNotLatest), + ), ], }, }, @@ -40,12 +43,7 @@ export const OutdatedVersion: Story = { export const Loading: Story = { parameters: { msw: { - handlers: [ - http.get(baseUrl + 'api/v1/releases', async () => { - await delay(5_000) - return HttpResponse.json(releasesResponseOk) - }), - ], + handlers: [http.all('*', async () => await delay(5_000))], }, }, } @@ -53,10 +51,7 @@ export const Loading: Story = { export const Error: Story = { parameters: { msw: { - handlers: [ - http.get(baseUrl + 'actuator/info', response401Unauthorized), - http.get(baseUrl + 'api/v1/releases', response401Unauthorized), - ], + handlers: [http.all('*', response401Unauthorized)], }, }, } diff --git a/next-ui/src/mocks/api/handlers.ts b/next-ui/src/mocks/api/handlers.ts index 40b484757..de8a6ca17 100644 --- a/next-ui/src/mocks/api/handlers.ts +++ b/next-ui/src/mocks/api/handlers.ts @@ -1,5 +1,16 @@ -import { actuatorHandlers } from '@/mocks/api/handlers/actuator' -import { announcementsHandlers } from '@/mocks/api/handlers/announcements' import { releasesHandlers } from '@/mocks/api/handlers/releases' +import { fromOpenApi } from '@mswjs/source/open-api' +import type { OpenAPIV3 } from 'openapi-types' +import spec from '../../../../komga/docs/openapi.json' +import { HttpResponse } from 'msw' -export const handlers = [...actuatorHandlers, ...announcementsHandlers, ...releasesHandlers] +const doc = { + basePath: import.meta.env.VITE_KOMGA_API_URL, + ...spec, +} as unknown as OpenAPIV3.Document + +// manually defined handlers need to be before fromOpenApi +export const handlers = [...releasesHandlers, ...(await fromOpenApi(doc))] + +export const response401Unauthorized = () => + HttpResponse.json({ error: 'Unauthorized' }, { status: 401 }) diff --git a/next-ui/src/mocks/api/handlers/actuator.ts b/next-ui/src/mocks/api/handlers/actuator.ts deleted file mode 100644 index 877323b61..000000000 --- a/next-ui/src/mocks/api/handlers/actuator.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { http, HttpResponse } from 'msw' -import { baseUrl } from '@/mocks/api/handlers/base' - -export const actuatorResponseOk = { - git: { - branch: 'master', - commit: { - id: 'ABC123', - time: '2025-05-16T03:26:50Z', - }, - }, - build: { - artifact: 'komga', - name: 'komga', - version: '9.9.9', - group: 'komga', - }, - java: { - version: '23.0.2', - vendor: { - name: 'Eclipse Adoptium', - version: 'Temurin-23.0.2+7', - }, - runtime: { - name: 'OpenJDK Runtime Environment', - version: '23.0.2+7', - }, - jvm: { - name: 'OpenJDK 64-Bit Server VM', - vendor: 'Eclipse Adoptium', - version: '23.0.2+7', - }, - }, - os: { - name: 'Linux', - version: '6.8.0-57-generic', - arch: 'amd64', - }, -} - -export const actuatorHandlers = [ - http.get(baseUrl + 'actuator/info', () => { - return HttpResponse.json(actuatorResponseOk) - }), -] diff --git a/next-ui/src/mocks/api/handlers/announcements.ts b/next-ui/src/mocks/api/handlers/announcements.ts deleted file mode 100644 index 68330584e..000000000 --- a/next-ui/src/mocks/api/handlers/announcements.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { http, HttpResponse } from 'msw' -import { baseUrl } from '@/mocks/api/handlers/base' - -export const announcementsHandlers = [ - http.get(baseUrl + 'api/v1/announcements', () => { - return HttpResponse.json({ - version: 'https://jsonfeed.org/version/1', - title: 'Announcements', - home_page_url: 'https://komga.org/blog', - description: 'Latest Komga announcements', - items: [ - { - id: 'https://komga.org/blog/ebook-drop2', - url: 'https://komga.org/blog/ebook-drop2', - title: 'eBook drop 2', - summary: 'Version 1.9.0 contains the second feature drop for Ebooks support.', - content_html: 'Truncated', - date_modified: '2023-12-15T00:00:00Z', - author: { - name: 'gotson', - url: 'https://github.com/gotson', - }, - tags: ['upgrade', 'komga'], - _komga: { - read: false, - }, - }, - { - id: 'https://komga.org/blog/ebook-support', - url: 'https://komga.org/blog/ebook-support', - title: 'eBook support', - summary: 'Version 1.8.0 is bringing a long awaited feature: proper eBook support!', - content_html: 'Truncated', - date_modified: '2023-11-29T00:00:00Z', - author: { - name: 'gotson', - url: 'https://github.com/gotson', - }, - tags: ['upgrade', 'komga'], - _komga: { - read: true, - }, - }, - ], - }) - }), -] diff --git a/next-ui/src/mocks/api/handlers/base.ts b/next-ui/src/mocks/api/handlers/base.ts deleted file mode 100644 index c48ec99cc..000000000 --- a/next-ui/src/mocks/api/handlers/base.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { HttpResponse } from 'msw' - -export const baseUrl = import.meta.env.VITE_KOMGA_API_URL + '/' - -export const response401Unauthorized = () => - HttpResponse.json({ error: 'Unauthorized' }, { status: 401 }) diff --git a/next-ui/src/mocks/api/handlers/releases.ts b/next-ui/src/mocks/api/handlers/releases.ts index 8731b0a28..5405cf500 100644 --- a/next-ui/src/mocks/api/handlers/releases.ts +++ b/next-ui/src/mocks/api/handlers/releases.ts @@ -1,26 +1,17 @@ -import { http, HttpResponse } from 'msw' -import { baseUrl } from '@/mocks/api/handlers/base' +import { httpTyped } from '@/mocks/api/httpTyped' export const releasesResponseOk = [ { - version: '9.9.9', - releaseDate: '2025-05-16T04:31:05Z', - url: 'https://github.com/gotson/komga/releases/tag/1.21.3', + version: '1.21.2', + releaseDate: new Date('2025-03-12T04:19:30Z'), + url: 'https://github.com/gotson/komga/releases/tag/1.21.2', latest: true, preRelease: false, description: 'Truncated', }, - { - version: '1.21.2', - releaseDate: '2025-03-12T04:19:30Z', - url: 'https://github.com/gotson/komga/releases/tag/1.21.2', - latest: false, - preRelease: false, - description: 'Truncated', - }, { version: '1.21.1', - releaseDate: '2025-03-06T07:31:00Z', + releaseDate: new Date('2025-03-06T07:31:00Z'), url: 'https://github.com/gotson/komga/releases/tag/1.21.1', latest: false, preRelease: false, @@ -30,17 +21,15 @@ export const releasesResponseOk = [ export const releasesResponseOkNotLatest = [ { - version: '9.9.9', - releaseDate: '2025-05-16T04:31:05Z', - url: 'https://github.com/gotson/komga/releases/tag/1.21.3', - latest: false, + version: '1.21.3', + releaseDate: new Date('2025-03-06T07:31:00Z'), + url: 'https://github.com/gotson/komga/releases/tag/1.21.1', + latest: true, preRelease: false, description: 'Truncated', }, ] export const releasesHandlers = [ - http.get(baseUrl + 'api/v1/releases', () => { - return HttpResponse.json(releasesResponseOk) - }), + httpTyped.get('/api/v1/releases', ({ response }) => response(200).json(releasesResponseOk)), ] diff --git a/next-ui/src/mocks/api/httpTyped.ts b/next-ui/src/mocks/api/httpTyped.ts new file mode 100644 index 000000000..514399b9d --- /dev/null +++ b/next-ui/src/mocks/api/httpTyped.ts @@ -0,0 +1,4 @@ +import { createOpenApiHttp } from 'openapi-msw' +import type { paths } from '@/generated/openapi/komga' + +export const httpTyped = createOpenApiHttp({ baseUrl: import.meta.env.VITE_KOMGA_API_URL })