import { readFileSync } from 'node:fs'; import { describe, expect, it } from 'vitest'; import type { DbStructureTable } from '../../src/domain/db-structure'; import { summarizeDbStructure } from '../../src/features/db-structure/DbStructurePanel'; const component = readFileSync(new URL('../../src/features/db-structure/DbStructurePanel.tsx', import.meta.url), 'utf8'); const styles = readFileSync(new URL('../../src/styles/datahub.css', import.meta.url), 'utf8'); describe('DB Structure information design', () => { it('summarizes tables, columns, relationships and available row estimates', () => { const tables: DbStructureTable[] = [ { name: 'imports', layer: 'import', approximateRowCount: 12, columns: [{ name: 'id', dataType: 'uuid', nullable: false }, { name: 'source', dataType: 'text', nullable: true }], foreignKeys: [] }, { name: 'findings', layer: 'canonical', approximateRowCount: null, columns: [{ name: 'import_id', dataType: 'uuid', nullable: false }], foreignKeys: [{ column: 'import_id', referencedTable: 'imports', referencedColumn: 'id' }] } ]; expect(summarizeDbStructure(tables)).toEqual({ tables: 2, columns: 3, relationships: 1, approximateRows: 12, countedTables: 1 }); }); it('keeps schema actions and the data flow while omitting the removed introductions', () => { expect(component).not.toContain('className="db-structure-intro"'); expect(component).not.toContain('className="db-structure-intro-copy"'); expect(component).not.toContain('Database dictionary'); expect(component).not.toContain('Relational schema'); expect(component).not.toContain('Follow a scanner report or a GPO backup'); expect(component).toContain('className="db-structure-intro-actions"'); expect(component).toContain('Refresh schema'); expect(component).toContain('

Data flow

'); expect(component).toContain('className="db-structure-summary"'); expect(component).toContain('className="db-structure-toolbar"'); expect(component).toContain('className="db-structure-layer-header"'); expect(component).toContain('className="db-structure-column-head"'); expect(component).toContain('Expand all'); expect(component).toContain('Collapse all'); expect(component).toContain('aria-controls={detailsId}'); expect(component).toContain(""); }); it('uses the shared flat segment and tile grammar without legacy card decoration', () => { expect(styles).toMatch(/\.db-structure-summary\s*\{[^}]*padding:\s*var\(--segment-inset\);[^}]*background:\s*var\(--segment-surface\);[^}]*box-shadow:\s*none;/s); expect(styles).toMatch(/\.db-structure-layer\s*\{[^}]*padding:\s*var\(--segment-inset\);[^}]*border:\s*0;[^}]*background:\s*var\(--segment-surface\);[^}]*box-shadow:\s*none;/s); expect(styles).toMatch(/\.db-structure-card\s*\{[^}]*border:\s*var\(--border-hair\) solid var\(--tile-border\);[^}]*border-radius:\s*0;[^}]*background:\s*var\(--tile-surface\);[^}]*box-shadow:\s*none;/s); expect(styles).toMatch(/\.db-structure-card-header:hover\s*\{[^}]*background:\s*var\(--tile-surface-hover\);/s); expect(styles).toMatch(/\.db-structure-card-copy\s*>\s*strong\s*\{[^}]*font-size:\s*var\(--type-h4-size\);[^}]*font-weight:\s*var\(--fw-semibold\);/s); expect(styles).not.toContain('.db-structure-columns code'); }); });