import { readFileSync } from 'node:fs'; import { describe, expect, it } from 'vitest'; const dataHub = readFileSync(new URL('../../src/features/project-import/DataHub.tsx', import.meta.url), 'utf8'); const gpoImport = readFileSync(new URL('../../src/features/project-import/GpoFolderImport.tsx', import.meta.url), 'utf8'); const styles = readFileSync(new URL('../../src/styles/datahub.css', import.meta.url), 'utf8'); describe('Mandant detail reference', () => { it('keeps entry actions on the right and separates additions from deleting the timeslot', () => { expect(styles).toMatch(/@container timeslot-sources[^}]+grid-template-columns:\s*var\(--space-5\) minmax\(0, 1fr\) calc\(var\(--space-8\) \* 2\.5\)/s); expect(styles).toMatch(/\.tenant-report-row > :last-child\s*\{[^}]*grid-column: 3;[^}]*grid-row: 1 \/ span 3;/s); const actions = dataHub.slice(dataHub.indexOf('
')); expect(actions).toContain('

Add Entry

'); expect(actions).not.toContain('Existing entries are kept.'); expect(actions).toMatch(/tenant-timeslot-delete-action[^]*?Entire timeslot<\/span>[^]*?>Delete timeslot<\/button>/); expect(actions.match(/]+\/>/)?.[0]).not.toContain('replacesScanRunId'); }); it('scrolls the complete timeslot list without an inner scrollbar per timeslot', () => { expect(styles).toMatch(/\.tenant-timeslot-list\s*\{[^}]*grid-auto-rows: max-content;/s); expect(styles).toMatch(/\.tenant-timeslot-list\s*\{[^}]*overflow-y: auto;/s); const reportListRule = styles.match(/\.tenant-report-list\s*\{([^}]*)\}/s)?.[1] ?? ''; expect(reportListRule).not.toMatch(/max-height|overflow-y|scrollbar-/); expect(dataHub).not.toContain('{selected &&
'); expect(dataHub).toContain('
'); }); it('uses the selected Work/Reports master-detail structure', () => { expect(dataHub).toContain('className="tenant-detail-layout"'); expect(dataHub).toContain('