import { test, expect } from '@playwright/test'; import { FRONTEND_URL, createTestAddress, deleteAddress } from '../../fixtures/test-helpers'; import { request as apiRequest } from '@playwright/test'; test.describe('Webhook Presets', () => { test('selecting each preset fills valid settings', async ({ page, context }) => { test.setTimeout(60_000); const api = await apiRequest.newContext(); let jwt: string | undefined; // Block popups (presets open doc URLs in new tabs) context.on('page', (p) => p.close()); try { const created = await createTestAddress(api, 'webhook-preset'); jwt = created.jwt; // Login via JWT await page.goto(`${FRONTEND_URL}/en/?jwt=${jwt}`); // Click "Webhook Settings" in the sidebar menu const webhookMenu = page.getByText('Webhook Settings'); await expect(webhookMenu).toBeVisible({ timeout: 10_000 }); await webhookMenu.click(); // Verify presets button is visible const presetsBtn = page.getByRole('button', { name: 'Presets' }); await expect(presetsBtn).toBeVisible({ timeout: 5000 }); // Helper to get form field value by label text const getFieldValue = async (label: string): Promise => { // Find the label, then get the sibling textbox in the same form row const row = page.locator('div', { hasText: new RegExp(`^${label}$`) }).locator('..'); const textbox = row.getByRole('textbox'); return textbox.inputValue(); }; // Define expected presets and their key fields const expectedPresets = [ { name: 'Message Pusher', urlPattern: 'msgpusher.com', bodyKeys: ['token', 'title', 'description', 'content'], }, { name: 'Bark', urlPattern: 'api.day.app', bodyKeys: ['title', 'body', 'group'], }, { name: 'ntfy', urlPattern: 'ntfy.sh', bodyKeys: ['topic', 'title', 'message', 'tags'], }, ]; for (const preset of expectedPresets) { // Open dropdown and select preset await presetsBtn.click(); const option = page.locator('.n-dropdown-option', { hasText: preset.name }); await expect(option).toBeVisible({ timeout: 5_000 }); await option.click(); // Wait for dropdown to close, then for URL field to contain preset pattern await expect(option).toBeHidden({ timeout: 5_000 }); await page.waitForTimeout(500); const allTextboxes = page.getByRole('textbox'); const count = await allTextboxes.count(); // Find URL, HEADERS, BODY values by reading all textboxes let urlValue = ''; let headersValue = ''; let bodyValue = ''; for (let i = 0; i < count; i++) { const val = await allTextboxes.nth(i).inputValue(); if (val.includes(preset.urlPattern)) { urlValue = val; } else if (val.includes('Content-Type')) { headersValue = val; } else if (val.includes('${subject}')) { bodyValue = val; } } // Verify URL expect(urlValue, `${preset.name}: URL should contain ${preset.urlPattern}`).toContain(preset.urlPattern); // Verify HEADERS is valid JSON with Content-Type expect(headersValue, `${preset.name}: HEADERS should not be empty`).toBeTruthy(); const headers = JSON.parse(headersValue); expect(headers, `${preset.name}: headers should have Content-Type`).toHaveProperty('Content-Type', 'application/json'); // Verify BODY is valid JSON with expected keys expect(bodyValue, `${preset.name}: BODY should not be empty`).toBeTruthy(); const body = JSON.parse(bodyValue); for (const key of preset.bodyKeys) { expect(body, `${preset.name}: body should have key "${key}"`).toHaveProperty(key); } } } finally { try { if (jwt) await deleteAddress(api, jwt); } finally { await api.dispose(); } } }); });