be1e0035e0
- PATCH mit null fuer name/url/category ergibt 400 statt 500 - Modulansicht unterscheidet Ladefehler von "nicht gefunden" - Formular/Loeschdialog nennen 403 und 400 eigens - eingeklappte Seitenleiste folgt der Gruppenreihenfolge der ausgeklappten - neue Eintraege sind mit "Eigene Module" vorbelegt - Verwaltung zeigt bei Ladefehler nicht zusaetzlich "keine Eintraege" Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
76 lines
2.7 KiB
TypeScript
76 lines
2.7 KiB
TypeScript
import 'reflect-metadata';
|
|
import { plainToInstance } from 'class-transformer';
|
|
import { validate } from 'class-validator';
|
|
import { describe, expect, it } from 'vitest';
|
|
import { CreateCustomModuleDto, UpdateCustomModuleDto } from './custom-module.dto';
|
|
|
|
async function errorsFor<T extends object>(cls: new () => T, plain: Record<string, unknown>) {
|
|
const dto = plainToInstance(cls, plain);
|
|
const errors = await validate(dto as object);
|
|
return errors.map((e) => e.property);
|
|
}
|
|
|
|
const valid = { name: 'Wiki', url: 'https://example.com', category: 'infrastructure' };
|
|
|
|
describe('CreateCustomModuleDto', () => {
|
|
it('nimmt einen gueltigen Eintrag an', async () => {
|
|
expect(await errorsFor(CreateCustomModuleDto, valid)).toEqual([]);
|
|
});
|
|
|
|
it.each([
|
|
'http://example.com',
|
|
'javascript:alert(1)',
|
|
'data:text/html,x',
|
|
'ftp://x',
|
|
'kaputt',
|
|
'https://user:pw@example.com',
|
|
'https://user@example.com',
|
|
])('lehnt die Adresse %s ab', async (url) => {
|
|
expect(await errorsFor(CreateCustomModuleDto, { ...valid, url })).toContain('url');
|
|
});
|
|
|
|
it('lehnt eine unbekannte Kategorie ab', async () => {
|
|
expect(await errorsFor(CreateCustomModuleDto, { ...valid, category: 'other' })).toContain(
|
|
'category',
|
|
);
|
|
});
|
|
|
|
it.each(['', ' '])('lehnt den Namen %j ab', async (name) => {
|
|
expect(await errorsFor(CreateCustomModuleDto, { ...valid, name })).toContain('name');
|
|
});
|
|
|
|
it('trimmt den Namen', () => {
|
|
const dto = plainToInstance(CreateCustomModuleDto, { ...valid, name: ' Wiki ' });
|
|
expect(dto.name).toBe('Wiki');
|
|
});
|
|
|
|
it('lehnt zu lange Namen und Adressen ab', async () => {
|
|
expect(await errorsFor(CreateCustomModuleDto, { ...valid, name: 'a'.repeat(101) })).toContain(
|
|
'name',
|
|
);
|
|
const longUrl = `https://example.com/${'a'.repeat(2048)}`;
|
|
expect(await errorsFor(CreateCustomModuleDto, { ...valid, url: longUrl })).toContain('url');
|
|
});
|
|
});
|
|
|
|
describe('UpdateCustomModuleDto', () => {
|
|
it('akzeptiert Teilmengen', async () => {
|
|
expect(await errorsFor(UpdateCustomModuleDto, { name: 'Neu' })).toEqual([]);
|
|
expect(await errorsFor(UpdateCustomModuleDto, {})).toEqual([]);
|
|
});
|
|
|
|
it('prueft jedes gesetzte Feld gleich', async () => {
|
|
expect(await errorsFor(UpdateCustomModuleDto, { url: 'http://example.com' })).toContain('url');
|
|
expect(await errorsFor(UpdateCustomModuleDto, { category: 'other' })).toContain('category');
|
|
expect(await errorsFor(UpdateCustomModuleDto, { name: ' ' })).toContain('name');
|
|
});
|
|
|
|
it.each([
|
|
'name',
|
|
'url',
|
|
'category',
|
|
])('lehnt %s: null ab statt es durchzulassen', async (field) => {
|
|
expect(await errorsFor(UpdateCustomModuleDto, { [field]: null })).toContain(field);
|
|
});
|
|
});
|