import { fileURLToPath } from 'node:url' import { afterAll, describe, expect, it } from 'vitest' import { $fetch, fetch, setup } from '@nuxt/test-utils/e2e' import { startTestPocketbase } from '../support/pocketbase' import type { Article, ArticleSummary, Category, Paginated } from '../../frontend/shared/types/blog' // setup() registers its own beforeAll/afterAll hooks, so — like startTestPocketbase() // below — it must run at module scope (top-level await), not nested inside another // hook: Vitest only picks up hooks registered during the initial collection phase. const pb = await startTestPocketbase() await setup({ rootDir: fileURLToPath(new URL('../../frontend', import.meta.url)), server: true, nuxtConfig: { runtimeConfig: { pocketbaseUrl: pb.url, public: { pocketbaseUrl: pb.url }, }, }, }) async function expectStatus(promise: Promise, statusCode: number) { const error = await promise.catch((caught) => caught) expect(error).toBeDefined() expect(error?.statusCode ?? error?.response?.status).toBe(statusCode) } afterAll(async () => { await pb.stop() }) describe('GET /content/articles', () => { it('lists only published articles, newest first', async () => { const response = await $fetch>('/content/articles') expect(response.items.map((a) => a.slug)).toEqual(['secondo-articolo', 'articolo-pubblicato']) expect(response.total).toBe(2) }) it('filters by category slug', async () => { const response = await $fetch>('/content/articles', { query: { category: 'attualita' }, }) expect(response.items.map((a) => a.slug)).toEqual(['secondo-articolo']) }) }) describe('GET /content/articles/:slug', () => { it('returns the full article with rendered html, summary and author', async () => { const article = await $fetch
('/content/articles/articolo-pubblicato') expect(article.title).toBe('Articolo pubblicato') expect(article.html).toContain('markdown') expect(article.summary.length).toBeGreaterThan(0) expect(article.author).toBe('Redazione') expect(article.category?.slug).toBe('economia') expect(article.hasTranslation).toBe(true) }) it('404s for an unknown slug', async () => { await expectStatus($fetch('/content/articles/does-not-exist'), 404) }) it('404s for a draft (unpublished) slug', async () => { await expectStatus($fetch('/content/articles/articolo-bozza'), 404) }) it('reports hasTranslation false for an article with no English content', async () => { const article = await $fetch
('/content/articles/secondo-articolo') expect(article.hasTranslation).toBe(false) }) it('returns the English fields when lang=en and a translation exists', async () => { const article = await $fetch
('/content/articles/articolo-pubblicato', { query: { lang: 'en' }, }) expect(article.title).toBe('Published article') expect(article.html).toContain('markdown') }) it('404s for lang=en when no translation exists', async () => { await expectStatus( $fetch('/content/articles/secondo-articolo', { query: { lang: 'en' } }), 404 ) }) }) describe('GET /content/articles with lang=en', () => { it('only lists articles that have an English translation', async () => { const response = await $fetch>('/content/articles', { query: { lang: 'en' }, }) expect(response.items.map((a) => a.slug)).toEqual(['articolo-pubblicato']) expect(response.items[0]?.title).toBe('Published article') }) }) describe('GET /content/categories', () => { it('lists categories sorted by name', async () => { const categories = await $fetch('/content/categories') expect(categories.map((c) => c.name)).toEqual(['Attualità', 'Economia']) }) it('only lists translated categories when lang=en', async () => { const categories = await $fetch('/content/categories', { query: { lang: 'en' } }) expect(categories.map((c) => c.name)).toEqual(['Economy']) }) }) describe('GET /content/categories/:slug', () => { it('returns one category by slug', async () => { const category = await $fetch('/content/categories/economia') expect(category.name).toBe('Economia') }) it('404s for an unknown slug', async () => { await expectStatus($fetch('/content/categories/does-not-exist'), 404) }) it('returns the English name when lang=en and a translation exists', async () => { const category = await $fetch('/content/categories/economia', { query: { lang: 'en' } }) expect(category.name).toBe('Economy') }) it('404s for lang=en when no translation exists', async () => { await expectStatus($fetch('/content/categories/attualita', { query: { lang: 'en' } }), 404) }) }) describe('GET /admin', () => { it('redirects to the PocketBase dashboard', async () => { const response = await fetch('/admin', { redirect: 'manual' }) expect(response.status).toBe(302) expect(response.headers.get('location')).toBe(`${pb.url}/_/`) }) })