import { describe, test, expect } from 'vitest'; import { ContactForm } from './ContactForm'; const toHtml = (ContactForm as any).toHtml; describe('ContactForm.toHtml relay wiring', () => { test('with recipientEmail: emits marker, placeholder action, honeypot', () => { const { html } = toHtml({ recipientEmail: 'a@b.com', thankYouUrl: '/thx', fields: [] }, ''); expect(html).toMatch(//); expect(html).toMatch(/action="__WHP_FORM_ACTION__F[0-9a-z]+__"/); expect(html).toContain('method="POST"'); expect(html).toContain('name="_gotcha"'); // marker id and action id match const mid = html.match(/id="(F[0-9a-z]+)"/)![1]; expect(html).toContain(`__WHP_FORM_ACTION__${mid}__`); }); test('without recipientEmail: no marker, falls back to formAction', () => { const { html } = toHtml({ formAction: '/legacy', fields: [] }, ''); expect(html).not.toContain('WHP-FORM'); expect(html).toContain('action="/legacy"'); expect(html).not.toContain('_gotcha'); // Backward-compat: ensure non-relay output is byte-identical (no extra blank lines from honeypot) expect(html).not.toMatch(/]*>\n\s*\n/); }); test('without recipientEmail + real fields: byte-clean legacy output (realistic case)', () => { // The empty-fields case is NOT byte-identical to the old code (the old // template emitted a stray whitespace line when fields was empty; the new // ternary drops it). Real forms always have fields, so pin THAT scenario: // no marker, no honeypot, and no whitespace-only line between
and // the first field. const fields = [{ type: 'text', label: 'Name', name: 'name', placeholder: 'Your name', required: true }]; const { html } = toHtml({ formAction: '/legacy', fields }, ''); expect(html).not.toContain('WHP-FORM'); expect(html).not.toContain('_gotcha'); expect(html).toContain('action="/legacy"'); expect(html).not.toMatch(/]*>\n\s*\n/); // First field renders directly after the form tag (no stray blank line). expect(html).toMatch(/]*>\n\s*