Assessor_2.0/tests/features/db-structure-layout.test.ts

62 lines
3.5 KiB
TypeScript

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</span>');
expect(component).not.toContain('Relational schema</h2>');
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('<h3>Data flow</h3>');
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("<TriangleIcon direction={isOpen ? 'down' : 'right'} />");
});
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);
// Square tiles or the shared tile radius token; never a local radius value.
expect(styles).toMatch(/\.db-structure-card\s*\{[^}]*border:\s*var\(--border-hair\) solid var\(--tile-border\);[^}]*border-radius:\s*(?:0|var\(--tile-radius\));[^}]*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');
});
});