import { describe, it, expect, beforeAll, afterAll } from 'vitest' import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs' import { tmpdir } from 'node:os' import path from 'node:path' import { testConfig } from './helpers.js' import { openDatabase } from '../src/db.js' import { buildApp } from '../src/app.js' describe('static serving', () => { let dir: string beforeAll(() => { dir = mkdtempSync(path.join(tmpdir(), 'rs-static-')) mkdirSync(path.join(dir, 'web', 'dist'), { recursive: true }) mkdirSync(path.join(dir, 'artwork'), { recursive: true }) writeFileSync(path.join(dir, 'web', 'dist', 'index.html'), 'record-shop') writeFileSync(path.join(dir, 'artwork', 'abc.jpg'), 'fakejpeg') }) afterAll(() => { rmSync(dir, { recursive: true, force: true }) }) async function build() { const config = { ...testConfig(), artworkDir: path.join(dir, 'artwork') } const app = await buildApp({ db: openDatabase(':memory:'), config, webDist: path.join(dir, 'web', 'dist'), }) return app } it('serves index.html at / and SPA-falls back for client routes', async () => { const app = await build() const root = await app.inject({ method: 'GET', url: '/' }) expect(root.statusCode).toBe(200) expect(root.body).toContain('record-shop') const spa = await app.inject({ method: 'GET', url: '/library' }) expect(spa.statusCode).toBe(200) expect(spa.body).toContain('record-shop') await app.close() }) it('serves artwork files', async () => { const app = await build() const res = await app.inject({ method: 'GET', url: '/artwork/abc.jpg' }) expect(res.statusCode).toBe(200) expect(res.body).toBe('fakejpeg') await app.close() }) it('unknown api routes return json 404, not the SPA', async () => { const app = await build() const res = await app.inject({ method: 'GET', url: '/api/nope' }) expect(res.statusCode).toBe(404) expect(res.json()).toEqual({ error: 'not_found' }) await app.close() }) })