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); } }); // quick-260924-i8v: Proxmox ist die erste modulgebundene Kachel; alle // uebrigen bleiben Plattform-Kacheln ohne Modulbezug. it('nur proxmox traegt einen Modulbezug, alle uebrigen Kacheln sind Plattform-Kacheln', () => { for (const type of WIDGET_TYPES.filter((t) => t !== 'proxmox')) { expect(getModuleSlugForWidgetType(type)).toBeUndefined(); } }); it("die Proxmox-Kachel gehoert zum Modul 'proxmox' (T-I8V-01)", () => { expect(getModuleSlugForWidgetType('proxmox')).toBe('proxmox'); }); 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)', () => { // quick-260923-ad9: dashboardId ist seither ein Pflichtfeld (Reiter- // Kennung) — hier fest mitgegeben, damit dieser Test weiterhin nur die // Whitelist von widgetType prueft. async function validateType(widgetType: string) { const dto = plainToInstance(CreateWidgetDto, { widgetType, dashboardId: 'dash-1' }); 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'); }); });