domain-viewers.test.ts
typescript
sha256:cfefc25a166c3c3eed8ea3529aee19ea350bc05f2954d007420e924133b7d8ce
chore: pivot to nightly channel — bump version to 0.2.0.dev…
Sonnet 5
patch
13 days ago
| 1 | import { describe, it, expect } from 'vitest'; |
| 2 | import { |
| 3 | renderSymbolGraphViewer, |
| 4 | renderPianoRollViewer, |
| 5 | renderGenericViewer, |
| 6 | renderDomainViewer, |
| 7 | } from './domain-viewers'; |
| 8 | |
| 9 | // Minimal HTMLElement shim — vitest runs in node, no real DOM/SVG needed |
| 10 | // since these functions only ever set innerHTML to a plain string. |
| 11 | function makeContainer(): HTMLElement { |
| 12 | return { innerHTML: '', clientWidth: 600 } as unknown as HTMLElement; |
| 13 | } |
| 14 | |
| 15 | describe('renderSymbolGraphViewer', () => { |
| 16 | it('renders one labeled node per dimension', () => { |
| 17 | const el = makeContainer(); |
| 18 | renderSymbolGraphViewer(el, [{ name: 'file' }, { name: 'symbol' }]); |
| 19 | expect(el.innerHTML).toContain('<svg'); |
| 20 | expect(el.innerHTML).toContain('file'); |
| 21 | expect(el.innerHTML).toContain('symbol'); |
| 22 | }); |
| 23 | |
| 24 | it('renders a placeholder node when no dimensions are declared', () => { |
| 25 | const el = makeContainer(); |
| 26 | renderSymbolGraphViewer(el, []); |
| 27 | expect(el.innerHTML).toContain('state'); |
| 28 | }); |
| 29 | |
| 30 | it('escapes dimension names to prevent injection', () => { |
| 31 | const el = makeContainer(); |
| 32 | renderSymbolGraphViewer(el, [{ name: '<script>alert(1)</script>' }]); |
| 33 | expect(el.innerHTML).not.toContain('<script>'); |
| 34 | expect(el.innerHTML).toContain('<script>'); |
| 35 | }); |
| 36 | }); |
| 37 | |
| 38 | describe('renderPianoRollViewer', () => { |
| 39 | it('renders one track row per dimension', () => { |
| 40 | const el = makeContainer(); |
| 41 | renderPianoRollViewer(el, [{ name: 'drums' }, { name: 'bass' }, { name: 'lead' }]); |
| 42 | expect(el.innerHTML).toContain('<svg'); |
| 43 | expect(el.innerHTML).toContain('drums'); |
| 44 | expect(el.innerHTML).toContain('bass'); |
| 45 | expect(el.innerHTML).toContain('lead'); |
| 46 | }); |
| 47 | |
| 48 | it('is deterministic for the same dimension name', () => { |
| 49 | const a = makeContainer(); |
| 50 | const b = makeContainer(); |
| 51 | renderPianoRollViewer(a, [{ name: 'drums' }]); |
| 52 | renderPianoRollViewer(b, [{ name: 'drums' }]); |
| 53 | expect(a.innerHTML).toBe(b.innerHTML); |
| 54 | }); |
| 55 | }); |
| 56 | |
| 57 | describe('renderGenericViewer', () => { |
| 58 | it('lists declared dimensions with descriptions', () => { |
| 59 | const el = makeContainer(); |
| 60 | renderGenericViewer(el, [{ name: 'notes', description: 'Note events' }]); |
| 61 | expect(el.innerHTML).toContain('notes'); |
| 62 | expect(el.innerHTML).toContain('Note events'); |
| 63 | }); |
| 64 | |
| 65 | it('shows an informative empty state, not a blank render', () => { |
| 66 | const el = makeContainer(); |
| 67 | renderGenericViewer(el, []); |
| 68 | expect(el.innerHTML.toLowerCase()).toContain('no dimensions'); |
| 69 | }); |
| 70 | }); |
| 71 | |
| 72 | describe('renderDomainViewer dispatch', () => { |
| 73 | it('dispatches symbol_graph to the graph renderer', () => { |
| 74 | const el = makeContainer(); |
| 75 | renderDomainViewer(el, 'symbol_graph', [{ name: 'file' }]); |
| 76 | expect(el.innerHTML).toContain('Symbol graph preview'); |
| 77 | }); |
| 78 | |
| 79 | it('dispatches piano_roll to the track renderer', () => { |
| 80 | const el = makeContainer(); |
| 81 | renderDomainViewer(el, 'piano_roll', [{ name: 'drums' }]); |
| 82 | expect(el.innerHTML).toContain('Track preview'); |
| 83 | }); |
| 84 | |
| 85 | it('falls back to the generic renderer for anything else', () => { |
| 86 | const el = makeContainer(); |
| 87 | renderDomainViewer(el, 'generic', [{ name: 'x' }]); |
| 88 | expect(el.innerHTML).toContain('domain-viewer-list'); |
| 89 | }); |
| 90 | }); |
File History
1 commit
sha256:cfefc25a166c3c3eed8ea3529aee19ea350bc05f2954d007420e924133b7d8ce
chore: pivot to nightly channel — bump version to 0.2.0.dev…
Sonnet 5
patch
13 days ago