dorfteich/apps/api/src/home/home.e2e.db.test.ts
Claude Fable 5 9c64166b10
Some checks failed
CD / Build and push images (push) Successful in 3m50s
CD / Deploy to Test (push) Successful in 10s
CI / Lint, typecheck, test (push) Successful in 4m13s
CI / Build container images (push) Has been skipped
CD / Smoke tests against Test (push) Successful in 1m14s
CD / Promote to Int (push) Successful in 11s
CI / Auth e2e pack (push) Failing after 2m44s
CI / Import/export fidelity gate (push) Has been skipped
Editable landing page for the Site Admin
The public home page (/) now renders Markdown the Site Admin stores in
the new home.content instance setting, through the same sanitizing
pipeline as the legal pages; empty falls back to the built-in welcome
text. New public GET /home/content, an Admin → Settings editor with
live preview, and an e2e test covering default/configured/escaping/
admin-only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwZ4jR4KFAPvpjWevfUGX1
2026-07-12 23:50:16 +02:00

82 lines
3.0 KiB
TypeScript

import { INestApplication } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
import request from 'supertest';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { createTestApp, sessionCookieOf } from '../testing/test-app';
import { createTestPrisma, hasTestDb, uniqueSuffix } from '../testing/test-db';
import { UsersService } from '../users/users.service';
/**
* Editable landing page end to end: the home body defaults to unconfigured,
* a Site Admin sets it through the generic settings PATCH, anonymous visitors
* read the rendered HTML, and stored Markdown can never smuggle script in.
*/
describe.skipIf(!hasTestDb)('landing page (e2e)', () => {
let app: INestApplication;
let prisma: PrismaClient;
let adminCookie: string;
const suffix = uniqueSuffix();
const password = 'ein sehr langes testpasswort';
const api = () => request(app.getHttpServer());
beforeAll(async () => {
prisma = createTestPrisma();
await prisma.rateLimit.deleteMany({});
await prisma.instanceSetting.deleteMany({ where: { key: 'home.content' } });
app = await createTestApp();
const users = app.get(UsersService);
const admin = await users.createUser({
username: `home-admin-${suffix}`,
email: `home-admin-${suffix}@example.org`,
displayName: 'Home Admin',
password,
locale: 'en',
});
await users.markEmailVerified(admin.id);
await prisma.user.update({ where: { id: admin.id }, data: { isSiteAdmin: true } });
const res = await api()
.post('/api/v1/auth/login')
.send({ usernameOrEmail: admin.username, password })
.expect(200);
adminCookie = sessionCookieOf(res);
});
afterAll(async () => {
await prisma.user.deleteMany({ where: { username: { contains: suffix } } });
await prisma.mailOutbox.deleteMany({ where: { toAddress: { contains: suffix } } });
await prisma.instanceSetting.deleteMany({ where: { key: 'home.content' } });
await prisma.$disconnect();
await app.close();
});
it('reports unconfigured content by default, without a session', async () => {
const res = await api().get('/api/v1/home/content').expect(200);
expect(res.body).toMatchObject({ configured: false, html: '' });
});
it('renders configured Markdown publicly and escapes script', async () => {
await api()
.patch('/api/v1/admin/settings')
.set('Cookie', adminCookie)
.send({ 'home.content': '# Welcome\n\nOur **wiki** <script>alert(1)</script>' })
.expect(200);
const res = await api().get('/api/v1/home/content').expect(200);
expect(res.body.configured).toBe(true);
expect(res.body.html).toContain('<h1>Welcome</h1>');
expect(res.body.html).toContain('<strong>wiki</strong>');
expect(res.body.html).not.toContain('<script>');
expect(res.body.html).toContain('&lt;script&gt;');
});
it('keeps the setting admin-only', async () => {
await api()
.patch('/api/v1/admin/settings')
.send({ 'home.content': 'anonymous edit' })
.expect(401);
});
});