add storybook tests for pages

This commit is contained in:
Gauthier Roebroeck 2025-06-26 16:20:17 +08:00
parent e7ba92bec7
commit bcbf6bb297
6 changed files with 184 additions and 1 deletions

View file

@ -1,3 +1,4 @@
import { announcementHandlers } 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'
@ -10,7 +11,7 @@ const doc = {
} as unknown as OpenAPIV3.Document
// manually defined handlers need to be before fromOpenApi
export const handlers = [...releasesHandlers, ...(await fromOpenApi(doc))]
export const handlers = [...announcementHandlers, ...releasesHandlers, ...(await fromOpenApi(doc))]
export const response401Unauthorized = () =>
HttpResponse.json({ error: 'Unauthorized' }, { status: 401 })

View file

@ -0,0 +1,46 @@
import { httpTyped } from '@/mocks/api/httpTyped'
export const announcementsAllRead = {
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: '<p>A longer text…</p>',
date_modified: new Date('2023-12-15T00:00:00Z'),
author: {
name: 'gotson',
url: 'https://github.com/gotson',
},
tags: ['upgrade', 'komga'],
_komga: {
read: true,
},
},
{
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: '<p>A longer text…</p>',
date_modified: new Date('2023-11-29T00:00:00Z'),
author: {
name: 'gotson',
url: 'https://github.com/gotson',
},
tags: ['upgrade', 'komga'],
_komga: {
read: true,
},
},
],
}
export const announcementHandlers = [
httpTyped.put('/api/v1/announcements', ({ response }) => response(204).empty()),
]

View file

@ -28,6 +28,14 @@ export const releasesResponseOkNotLatest = [
preRelease: false,
description: 'Truncated',
},
{
version: '1.21.2',
releaseDate: new Date('2025-03-12T04:19:30Z'),
url: 'https://github.com/gotson/komga/releases/tag/1.21.2',
latest: false,
preRelease: false,
description: 'Truncated',
},
]
export const releasesHandlers = [

View file

@ -0,0 +1,69 @@
import type { Meta, StoryObj } from '@storybook/vue3-vite'
import announcements from './announcements.vue'
import { http, delay } from 'msw'
import { response401Unauthorized } from '@/mocks/api/handlers'
import { httpTyped } from '@/mocks/api/httpTyped'
import { announcementsAllRead } from '@/mocks/api/handlers/announcements'
import { expect, waitFor } from 'storybook/test'
const meta = {
component: announcements,
render: (args: object) => ({
components: { announcements },
setup() {
return { args }
},
template: '<announcements />',
}),
parameters: {
// More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
},
args: {},
} satisfies Meta<typeof announcements>
export default meta
type Story = StoryObj<typeof meta>
export const Unread: Story = {
args: {},
play: async ({ canvas }) => {
await waitFor(() => expect(canvas.getByText('eBook drop 2')).not.toBeNull())
await expect(canvas.getByRole('button', { name: 'mark all read' })).toBeEnabled()
},
}
export const NoUnread: Story = {
parameters: {
msw: {
handlers: [
httpTyped.get('/api/v1/announcements', ({ response }) =>
response(200).json(announcementsAllRead),
),
],
},
},
play: async ({ canvas }) => {
await waitFor(() => expect(canvas.getByText('eBook drop 2')).not.toBeNull())
await expect(canvas.queryByRole('button', { name: 'mark all read' })).toBeNull()
},
}
export const Loading: Story = {
parameters: {
msw: {
handlers: [http.all('*', async () => await delay(5_000))],
},
},
}
export const Error: Story = {
parameters: {
msw: {
handlers: [http.all('*', response401Unauthorized)],
},
},
}

View file

@ -50,6 +50,7 @@
color="success"
size="x-large"
icon="i-mdi:check-all"
aria-label="mark all read"
/>
</v-fab>
</template>

View file

@ -0,0 +1,58 @@
import type { Meta, StoryObj } from '@storybook/vue3-vite'
import updates from './updates.vue'
import { http, delay } from 'msw'
import { response401Unauthorized } from '@/mocks/api/handlers'
import { httpTyped } from '@/mocks/api/httpTyped'
import { releasesResponseOkNotLatest } from '@/mocks/api/handlers/releases'
const meta = {
component: updates,
render: (args: object) => ({
components: { updates },
setup() {
return { args }
},
template: '<updates />',
}),
parameters: {
// More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
},
args: {},
} satisfies Meta<typeof updates>
export default meta
type Story = StoryObj<typeof meta>
export const Latest: Story = {
args: {},
}
export const Outdated: Story = {
parameters: {
msw: {
handlers: [
httpTyped.get('/api/v1/releases', ({ response }) =>
response(200).json(releasesResponseOkNotLatest),
),
],
},
},
}
export const Loading: Story = {
parameters: {
msw: {
handlers: [http.all('*', async () => await delay(5_000))],
},
},
}
export const Error: Story = {
parameters: {
msw: {
handlers: [http.all('*', response401Unauthorized)],
},
},
}