Files
convert/test/staticServing.test.js
T

96 lines
3.5 KiB
JavaScript

import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import request from 'supertest';
import fs from 'node:fs/promises';
import path from 'node:path';
import os from 'node:os';
import { createApp } from '../src/app.js';
import { getPrismaClient, closePrismaClient } from '../src/db.js';
import { loadConfig } from '../src/config.js';
import { ensureStorageDirs } from '../src/storage.js';
let app;
let prisma;
let config;
let frontendDist;
beforeAll(async () => {
frontendDist = await fs.mkdtemp(path.join(os.tmpdir(), 'converter-dist-'));
await fs.mkdir(path.join(frontendDist, 'fr'), { recursive: true });
await fs.mkdir(path.join(frontendDist, 'assets'), { recursive: true });
await fs.mkdir(path.join(frontendDist, '404'), { recursive: true });
await fs.writeFile(path.join(frontendDist, '404', 'index.html'), '<html><body>not found</body></html>');
await fs.writeFile(
path.join(frontendDist, 'fr', 'index.html'),
`<html><body>fr home ${'x'.repeat(2000)}</body></html>`
);
await fs.writeFile(path.join(frontendDist, 'assets', 'app.abc123.js'), 'console.log(1)');
config = {
...loadConfig(),
storageDir: await fs.mkdtemp(path.join(os.tmpdir(), 'converter-api-')),
frontendDist,
};
await ensureStorageDirs(config);
prisma = getPrismaClient(config);
app = createApp(config, prisma);
});
afterAll(async () => {
await closePrismaClient();
await fs.rm(config.storageDir, { recursive: true, force: true });
await fs.rm(frontendDist, { recursive: true, force: true });
});
describe('root redirect', () => {
it('redirects to /en/ when Accept-Language prefers English', async () => {
const response = await request(app).get('/').set('Accept-Language', 'en-US,en;q=0.9');
expect(response.status).toBe(301);
expect(response.headers.location).toBe('/en/');
});
it('redirects to /fr/ when Accept-Language prefers French', async () => {
const response = await request(app).get('/').set('Accept-Language', 'fr-FR,fr;q=0.9,en;q=0.5');
expect(response.status).toBe(301);
expect(response.headers.location).toBe('/fr/');
});
it('defaults to /fr/ when Accept-Language is absent', async () => {
const response = await request(app).get('/');
expect(response.status).toBe(301);
expect(response.headers.location).toBe('/fr/');
});
});
describe('static asset serving', () => {
it('sends HTML pages with Cache-Control: no-cache', async () => {
const response = await request(app).get('/fr/');
expect(response.status).toBe(200);
expect(response.headers['cache-control']).toBe('no-cache');
});
it('sends hashed assets with a long immutable Cache-Control', async () => {
const response = await request(app).get('/assets/app.abc123.js');
expect(response.status).toBe(200);
expect(response.headers['cache-control']).toBe('public, max-age=31536000, immutable');
});
it('compresses responses when the client accepts it', async () => {
const response = await request(app).get('/fr/').set('Accept-Encoding', 'gzip');
expect(response.headers['content-encoding']).toBe('gzip');
});
});
describe('404 handling', () => {
it('returns a real 404 status for an unknown path', async () => {
const response = await request(app).get('/this-page-does-not-exist/');
expect(response.status).toBe(404);
expect(response.text).toContain('not found');
});
it('still serves a known route with 200', async () => {
const response = await request(app).get('/fr/');
expect(response.status).toBe(200);
expect(response.text).toContain('fr home');
});
});