import { describe, it } from 'node:test'; import { strict as assert } from 'node:assert'; import { readFileSync } from 'node:fs'; import { resolve } from 'node:path'; const componentPath = resolve('src/components/Callout.astro'); function readComponent() { return readFileSync(componentPath, 'utf-8'); } describe('Callout component', () => { it('should exist at src/components/Callout.astro', () => { // Will throw if file doesn't exist const content = readComponent(); assert.ok(content.length > 0, 'Component file should not be empty'); }); describe('Props interface', () => { it('should define type prop with 5 allowed values', () => { const content = readComponent(); assert.match(content, /type\?/, 'type should be an optional prop'); assert.match(content, /note/, 'should include note type'); assert.match(content, /pattern/, 'should include pattern type'); assert.match(content, /antipattern/, 'should include antipattern type'); assert.match(content, /warning/, 'should include warning type'); assert.match(content, /tip/, 'should include tip type'); }); it('should default type to note', () => { const content = readComponent(); assert.match(content, /=\s*['"]note['"]/, 'type should default to note'); }); }); describe('Config record mapping', () => { it('should map note to border-default, text-secondary, Note', () => { const content = readComponent(); assert.match(content, /border-default/, 'note should use border-default'); assert.match(content, /text-secondary/, 'note should use text-secondary'); }); it('should map pattern to accent-primary, accent-primary, Pattern', () => { const content = readComponent(); assert.match(content, /accent-primary/, 'pattern should use accent-primary'); }); it('should map antipattern to error-border, error-text, Anti-pattern', () => { const content = readComponent(); assert.match(content, /error-border/, 'antipattern should use error-border'); assert.match(content, /error-text/, 'antipattern should use error-text'); assert.match(content, /Anti-pattern/, 'antipattern should have Anti-pattern label'); }); it('should map warning to warning-border, warning-text, Warning', () => { const content = readComponent(); assert.match(content, /warning-border/, 'warning should use warning-border'); assert.match(content, /warning-text/, 'warning should use warning-text'); }); it('should map tip to accent-secondary, accent-secondary, Tip', () => { const content = readComponent(); assert.match(content, /accent-secondary/, 'tip should use accent-secondary'); }); }); describe('Semantic HTML', () => { it('should use aside element with role=note', () => { const content = readComponent(); assert.match(content, /