diff --git a/craft/src/components/forms/ContactForm.toHtml.test.ts b/craft/src/components/forms/ContactForm.toHtml.test.ts index d29b243..e72c4aa 100644 --- a/craft/src/components/forms/ContactForm.toHtml.test.ts +++ b/craft/src/components/forms/ContactForm.toHtml.test.ts @@ -196,3 +196,83 @@ describe('ContactForm.craft.props includes animation/visibility defaults', () => }); }); }); + +/* ---------- Webhook destination (Task 10) ---------- + This file builds props inline rather than spreading a shared object, so + `defaultProps` is introduced here for the destination cases only; every + pre-existing test above is untouched. */ +const defaultProps = { fields: [] as any[], formAction: '#' }; + +describe('ContactForm.craft.props includes the destination defaults', () => { + // The trap this pins: FormStylePanel renders each destination control behind + // `nodeProps.X !== undefined`, so a prop omitted from these defaults yields an + // invisible control and the whole feature looks like it does nothing. + test('destinationType/webhookUrl/webhookSecretId/webhookAuthMode are all present', () => { + expect(ContactForm.craft!.props).toMatchObject({ + destinationType: 'email', + webhookUrl: '', + webhookSecretId: '', + webhookAuthMode: 'signature', + }); + }); + + test('no craft prop holds a raw secret -- only an id', () => { + const keys = Object.keys(ContactForm.craft!.props as object); + expect(keys).toContain('webhookSecretId'); + expect(keys.filter((k) => /secret/i.test(k))).toEqual(['webhookSecretId']); + }); +}); + +describe('ContactForm.toHtml destination marker', () => { + test('email destination emits the legacy marker unchanged', () => { + const out = toHtml( + { ...defaultProps, destinationType: 'email', recipientEmail: 'a@example.com', thankYouUrl: '' }, ''); + expect(out.html).toContain('