diff --git a/craft/src/components/forms/ContactForm.toHtml.test.ts b/craft/src/components/forms/ContactForm.toHtml.test.ts index 210dbcb..05149ed 100644 --- a/craft/src/components/forms/ContactForm.toHtml.test.ts +++ b/craft/src/components/forms/ContactForm.toHtml.test.ts @@ -311,3 +311,27 @@ describe('ContactForm.toHtml design tokens (#44)', () => { for (const hex of ["#ef4444", "#374151", "#d1d5db", "#ffffff"]) expect(lower, `old ${hex}`).not.toContain(hex); }); }); + +describe('ContactForm.toHtml dark-aware inputs (eval 2026-11-01)', () => { + const fields = [{ type: 'text', label: 'Name', name: 'name', placeholder: 'Your name', required: true }]; + test('inputTextColor sets the typed text colour; placeholders follow it (currentColor) via a scoped rule', () => { + const { html } = toHtml({ fields, inputBg: '#1b1530', inputTextColor: '#f5f3ff' }, '', 'n1'); + expect(html).toMatch(/]*style="[^"]*color:#f5f3ff/); + expect(html).toMatch(/]*data-wsb-form/); + expect(html).toContain(''); + }); + test('without inputTextColor the old derivation stays (light stored surface -> legacy dark text)', () => { + expect(toHtml({ fields, inputBg: '#ffffff' }, '').html).toMatch(/]*color:#1f2937/); + expect(toHtml({ fields }, '').html).toMatch(/]*color:var\(--wsb-text\)/); + }); + test('an inputBorder written as a whole border ("1px solid X") is used as-is, not doubled into "1px solid 1px solid X"', () => { + const { html } = toHtml({ fields, inputBorder: '1px solid color-mix(in srgb, var(--wsb-secondary) 45%, transparent)' }, ''); + expect(html).not.toContain('1px solid 1px solid'); + expect(html).toContain('border:1px solid color-mix(in srgb, var(--wsb-secondary) 45%, transparent)'); + expect(toHtml({ fields, inputBorder: '#334155' }, '').html).toContain('border:1px solid #334155'); + }); + test('a hostile inputTextColor cannot break out of the style attribute', () => { + const { html } = toHtml({ fields, inputTextColor: 'red;}">' }, ''); + expect(html).not.toContain('