# E2E Test Fix - Remediation Plan v2 **Date:** 2026-02-01 **Status:** Ready for Implementation **Test File:** `tests/dns-provider-types.spec.ts` **Component:** `frontend/src/components/DNSProviderForm.tsx` **Priority:** High **Revised:** 2026-02-01 (Per Supervisor feedback - Option 2 is primary approach) --- ## Executive Summary The E2E test for webhook provider type selection is failing due to a **React render timing race condition**, not a missing fallback schema. The test clicks the webhook option in the dropdown and immediately waits for the credentials section to appear, but React needs time to: 1. Update `providerType` state (async `setProviderType`) 2. Re-render the component 3. Recompute `selectedProviderInfo` from the updated state 4. Conditionally render the credentials section based on the new value When the test waits for `[data-testid="credentials-section"]` too quickly, React hasn't completed this cycle yet, causing a timeout. --- ## Root Cause Analysis ### Investigation Results #### ✅ Verified: Webhook HAS Fallback Schema **File:** `frontend/src/data/dnsProviderSchemas.ts` (Lines 245-301) ```typescript webhook: { type: 'webhook', name: 'Webhook', fields: [ { name: 'create_url', label: 'Create Record URL', type: 'text', required: true, ... }, { name: 'delete_url', label: 'Delete Record URL', type: 'text', required: false, ... }, { name: 'auth_type', label: 'Authentication Type', type: 'select', required: false, ... }, { name: 'auth_value', label: 'Auth Value', type: 'password', required: false, ... }, { name: 'insecure_skip_verify', label: 'Skip TLS Verification', type: 'select', ... }, ], documentation_url: '', } ``` **Conclusion:** Option A (missing fallback) is **ruled out**. Webhook provider **does** have a complete fallback definition. --- #### ❌ Root Cause: React Re-Render Timing **File:** `frontend/src/components/DNSProviderForm.tsx` **Line 87-92:** `getSelectedProviderInfo()` function ```tsx const getSelectedProviderInfo = (): DNSProviderTypeInfo | undefined => { if (!providerType) return undefined return ( providerTypes?.find((pt) => pt.type === providerType) || (defaultProviderSchemas[providerType as keyof typeof defaultProviderSchemas] as DNSProviderTypeInfo) ); } ``` - **Fallback logic is correct**: If `providerTypes` (React Query) hasn't loaded, it uses `defaultProviderSchemas` - **But the function depends on `providerType` state**, which is updated asynchronously **Line 152:** Computed value assignment ```tsx const selectedProviderInfo = getSelectedProviderInfo() ``` - This is recomputed **every render** - Depends on current `providerType` state value **Line 205-209:** Conditional rendering of credentials section ```tsx {selectedProviderInfo && ( <>
``` - The **entire credentials section** is inside the conditional - The `data-testid="credentials-section"` label only exists when `selectedProviderInfo` is truthy - If React hasn't re-rendered after state update, this section doesn't exist in the DOM --- #### ⏱️ Timing Chain Breakdown **Test Sequence:** ```typescript // 1. Select webhook from dropdown await page.getByRole('option', { name: /webhook/i }).click(); // 2. Immediately wait for credentials section await page.locator('[data-testid="credentials-section"]').waitFor({ state: 'visible', timeout: 10000 }); ``` **React State/Render Cycle:** 1. **T=0ms**: User clicks webhook option 2. **T=1ms**: `