import { describe, expect, it } from 'vitest'; import { plainToInstance } from 'class-transformer'; import { validate } from 'class-validator'; import { WIDGET_MODULE_SLUGS, WIDGET_TYPES } from '@tessera/shared'; import { CreateWidgetDto } from './dto/create-widget.dto'; import { WIDGET_MODULE_MAP, getModuleSlugForWidgetType } from './widget-module-map'; /** * quick-260922-m1h: Web und API lesen dieselbe Tabelle. Liefen sie * auseinander, wuerde der Katalog eine Kachel anbieten, die der Server * danach wieder herausfiltert (oder umgekehrt). */ describe('widget-module-map (quick-260922-m1h)', () => { it('WIDGET_MODULE_MAP ist die Tabelle aus @tessera/shared, keine zweite Kopie', () => { expect(WIDGET_MODULE_MAP).toBe(WIDGET_MODULE_SLUGS); }); it('jeder Schluessel der Tabelle ist ein bekannter Widget-Typ', () => { for (const type of Object.keys(WIDGET_MODULE_MAP)) { expect(WIDGET_TYPES).toContain(type); } }); it('die neun heutigen Kacheln sind Plattform-Kacheln ohne Modulbezug', () => { for (const type of WIDGET_TYPES) { expect(getModuleSlugForWidgetType(type)).toBeUndefined(); } }); it('ein unbekannter Typ liefert undefined statt zu werfen', () => { expect(getModuleSlugForWidgetType('gibt-es-nicht')).toBeUndefined(); }); }); /** * Der Kern des Umbaus: die `@IsIn`-Whitelist ist keine handgepflegte zweite * Liste mehr. Vergisst kuenftig jemand einen Eintrag in `packages/shared`, * schlaegt dieser Test fehl, statt die API eine gueltige Kachel mit 400 * ablehnen zu lassen. */ describe('CreateWidgetDto-Whitelist (quick-260922-m1h)', () => { async function validateType(widgetType: string) { const dto = plainToInstance(CreateWidgetDto, { widgetType }); return validate(dto); } it.each([...WIDGET_TYPES])('akzeptiert den Typ "%s"', async (widgetType) => { await expect(validateType(widgetType)).resolves.toEqual([]); }); it('lehnt einen Typ ab, der nicht in WIDGET_TYPES steht', async () => { const errors = await validateType('gibt-es-nicht'); expect(errors).toHaveLength(1); expect(errors[0].property).toBe('widgetType'); expect(errors[0].constraints).toHaveProperty('isIn'); }); });