import { test, expect, loginUser } from '../fixtures/auth-fixtures';
import { request as playwrightRequest } from '@playwright/test';
import { waitForLoadingComplete } from '../utils/wait-helpers';

const SETTINGS_FLAGS_ENDPOINT = '/api/v1/settings';
const PROVIDERS_ENDPOINT = '/api/v1/notifications/providers';

function buildDiscordProviderPayload(name: string) {
  return {
    name,
    type: 'discord',
    url: 'https://discord.com/api/webhooks/123456789/testtoken',
    enabled: true,
    notify_proxy_hosts: true,
    notify_remote_servers: false,
    notify_domains: false,
    notify_certs: true,
    notify_uptime: false,
    notify_security_waf_blocks: false,
    notify_security_acl_denies: false,
    notify_security_rate_limit_hits: false,
  };
}

async function enableNotifyDispatchFlags(page: import('@playwright/test').Page, token: string) {
  const keys = [
    'feature.notifications.service.gotify.enabled',
    'feature.notifications.service.webhook.enabled',
  ];

  for (const key of keys) {
    const response = await page.request.post(SETTINGS_FLAGS_ENDPOINT, {
      headers: { Authorization: `Bearer ${token}` },
      data: {
        key,
        value: 'true',
        category: 'feature',
        type: 'bool',
      },
    });

    expect(response.ok()).toBeTruthy();
  }
}

test.describe('Notifications Payload Matrix', () => {
  test.beforeEach(async ({ page, adminUser }) => {
    await loginUser(page, adminUser);
    await waitForLoadingComplete(page);
    await page.goto('/settings/notifications');
    await waitForLoadingComplete(page);
  });

  test('valid payload flows for discord, gotify, and webhook', async ({ page }) => {
    const createdProviders: Array<Record<string, unknown>> = [];
    const capturedCreatePayloads: Array<Record<string, unknown>> = [];

    await test.step('Mock providers create/list endpoints', async () => {
      await page.route('**/api/v1/notifications/providers', async (route, request) => {
        if (request.method() === 'GET') {
          await route.fulfill({
            status: 200,
            contentType: 'application/json',
            body: JSON.stringify(createdProviders),
          });
          return;
        }

        if (request.method() === 'POST') {
          const payload = (await request.postDataJSON()) as Record<string, unknown>;
          capturedCreatePayloads.push(payload);
          const created = {
            id: `provider-${capturedCreatePayloads.length}`,
            ...payload,
          };
          createdProviders.push(created);
          await route.fulfill({
            status: 201,
            contentType: 'application/json',
            body: JSON.stringify(created),
          });
          return;
        }

        await route.continue();
      });
    });

    const scenarios = [
      {
        type: 'discord',
        name: `discord-matrix-${Date.now()}`,
        url: 'https://discord.com/api/webhooks/123/discordtoken',
      },
      {
        type: 'gotify',
        name: `gotify-matrix-${Date.now()}`,
        url: 'https://gotify.example.com/message',
      },
      {
        type: 'webhook',
        name: `webhook-matrix-${Date.now()}`,
        url: 'https://example.com/notify',
      },
      {
        type: 'telegram',
        name: `telegram-matrix-${Date.now()}`,
        url: '987654321',
      },
      {
        type: 'slack',
        name: `slack-matrix-${Date.now()}`,
        url: '#slack-alerts',
      },
      {
        type: 'ntfy',
        name: `ntfy-matrix-${Date.now()}`,
        url: 'https://ntfy.sh/my-topic',
      },
    ] as const;

    for (const scenario of scenarios) {
      await test.step(`Create ${scenario.type} provider and capture outgoing payload`, async () => {
        await page.getByRole('button', { name: /add.*provider/i }).click();

        await page.getByTestId('provider-name').fill(scenario.name);
        await page.getByTestId('provider-type').selectOption(scenario.type);
        await page.getByTestId('provider-url').fill(scenario.url);

        if (scenario.type === 'gotify') {
          await page.getByTestId('provider-gotify-token').fill('  gotify-secret-token  ');
        }

        if (scenario.type === 'telegram') {
          await page.getByTestId('provider-gotify-token').fill('bot123456789:ABCdefGHI');
        }

        if (scenario.type === 'slack') {
          await page.getByTestId('provider-gotify-token').fill('https://hooks.slack.com/services/T00000000/B00000000/xxxxxxxxxxxxxxxxxxxx');
        }

        if (scenario.type === 'ntfy') {
          await page.getByTestId('provider-gotify-token').fill('tk_ntfy_matrix_token');
        }

        await page.getByTestId('provider-save-btn').click();
      });
    }

    await test.step('Verify payload contract per provider type', async () => {
      expect(capturedCreatePayloads).toHaveLength(6);

      const discordPayload = capturedCreatePayloads.find((payload) => payload.type === 'discord');
      expect(discordPayload).toBeTruthy();
      expect(discordPayload?.token).toBeUndefined();
      expect(discordPayload?.gotify_token).toBeUndefined();

      const gotifyPayload = capturedCreatePayloads.find((payload) => payload.type === 'gotify');
      expect(gotifyPayload).toBeTruthy();
      expect(gotifyPayload?.token).toBe('gotify-secret-token');
      expect(gotifyPayload?.gotify_token).toBeUndefined();

      const webhookPayload = capturedCreatePayloads.find((payload) => payload.type === 'webhook');
      expect(webhookPayload).toBeTruthy();
      expect(webhookPayload?.token).toBeUndefined();
      expect(typeof webhookPayload?.config).toBe('string');

      const telegramPayload = capturedCreatePayloads.find((payload) => payload.type === 'telegram');
      expect(telegramPayload).toBeTruthy();
      expect(telegramPayload?.token).toBe('bot123456789:ABCdefGHI');
      expect(telegramPayload?.gotify_token).toBeUndefined();
      expect(telegramPayload?.url).toBe('987654321');

      const slackPayload = capturedCreatePayloads.find((payload) => payload.type === 'slack');
      expect(slackPayload).toBeTruthy();
      expect(slackPayload?.token).toBe('https://hooks.slack.com/services/T00000000/B00000000/xxxxxxxxxxxxxxxxxxxx');
      expect(slackPayload?.gotify_token).toBeUndefined();
      expect(slackPayload?.url).toBe('#slack-alerts');

      const ntfyPayload = capturedCreatePayloads.find((payload) => payload.type === 'ntfy');
      expect(ntfyPayload).toBeTruthy();
      expect(ntfyPayload?.token).toBe('tk_ntfy_matrix_token');
      expect(ntfyPayload?.gotify_token).toBeUndefined();
      expect(ntfyPayload?.url).toBe('https://ntfy.sh/my-topic');
    });
  });

  test('malformed payload scenarios return sanitized validation errors', async ({ page, adminUser }) => {
    await test.step('Malformed JSON to preview endpoint returns INVALID_REQUEST', async () => {
      const response = await page.request.post('/api/v1/notifications/providers/preview', {
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${adminUser.token}`,
        },
        data: '{"type":',
      });

      expect(response.status()).toBe(400);
      const body = (await response.json()) as Record<string, unknown>;
      expect(body.code).toBe('INVALID_REQUEST');
      expect(body.category).toBe('validation');
    });

    await test.step('Malformed template content returns TEMPLATE_PREVIEW_FAILED', async () => {
      const response = await page.request.post('/api/v1/notifications/providers/preview', {
        headers: { Authorization: `Bearer ${adminUser.token}` },
        data: {
          type: 'webhook',
          url: 'https://example.com/notify',
          template: 'custom',
          config: '{"message": {{.Message}',
        },
      });

      expect(response.status()).toBe(400);
      const body = (await response.json()) as Record<string, unknown>;
      expect(body.code).toBe('TEMPLATE_PREVIEW_FAILED');
      expect(body.category).toBe('validation');
    });
  });

  test('missing required fields block submit and show validation', async ({ page }) => {
    let createCalled = false;

    await test.step('Prevent create call from being silently sent', async () => {
      await page.route('**/api/v1/notifications/providers', async (route, request) => {
        if (request.method() === 'POST') {
          createCalled = true;
        }

        await route.continue();
      });
    });

    await test.step('Submit empty provider form', async () => {
      await page.getByRole('button', { name: /add.*provider/i }).click();
      await page.getByTestId('provider-save-btn').click();
    });

    await test.step('Validate required field errors and no outbound create', async () => {
      await expect(page.getByTestId('provider-url-error')).toBeVisible();
      await expect(page.getByTestId('provider-name')).toHaveAttribute('aria-invalid', 'true');
      expect(createCalled).toBeFalsy();
    });
  });

  test('auth/header behavior checks for protected settings endpoint', async ({ page, adminUser }) => {
    const providerName = `auth-check-${Date.now()}`;
    let providerID = '';

    await test.step('Protected settings write rejects invalid bearer token', async () => {
      const unauthenticatedRequest = await playwrightRequest.newContext({
        baseURL: process.env.PLAYWRIGHT_BASE_URL || 'http://127.0.0.1:8080',
      });

      try {
        const noAuthResponse = await unauthenticatedRequest.post(SETTINGS_FLAGS_ENDPOINT, {
          headers: { Authorization: 'Bearer invalid-token' },
          data: {
            key: 'feature.notifications.service.webhook.enabled',
            value: 'true',
            category: 'feature',
            type: 'bool',
          },
        });

        expect([401, 403]).toContain(noAuthResponse.status());
      } finally {
        await unauthenticatedRequest.dispose();
      }
    });

    await test.step('Create provider with bearer token succeeds', async () => {
      const authResponse = await page.request.post(PROVIDERS_ENDPOINT, {
        headers: { Authorization: `Bearer ${adminUser.token}` },
        data: buildDiscordProviderPayload(providerName),
      });

      expect(authResponse.status()).toBe(201);
      const created = (await authResponse.json()) as Record<string, unknown>;
      providerID = String(created.id ?? '');
      expect(providerID.length).toBeGreaterThan(0);
    });

    await test.step('Cleanup created provider', async () => {
      const deleteResponse = await page.request.delete(`${PROVIDERS_ENDPOINT}/${providerID}`, {
        headers: { Authorization: `Bearer ${adminUser.token}` },
      });

      expect(deleteResponse.ok()).toBeTruthy();
    });
  });

  test('provider-specific transformation strips gotify token from test and preview payloads', async ({ page }) => {
    let capturedPreviewPayload: Record<string, unknown> | null = null;
    let capturedTestPayload: Record<string, unknown> | null = null;
    const providers: Array<Record<string, unknown>> = [];
    const gotifyName = `gotify-transform-${Date.now()}`;

    await test.step('Mock create, list, preview, and test endpoints', async () => {
      await page.route('**/api/v1/notifications/providers', async (route, request) => {
        if (request.method() === 'POST') {
          const payload = (await request.postDataJSON()) as Record<string, unknown>;
          // Simulate backend: strip token from stored/listed provider (json:"-")
          const created = {
            id: 'gotify-transform-id',
            name: payload.name,
            type: payload.type,
            url: payload.url,
            enabled: true,
            has_token: true,
          };
          providers.splice(0, providers.length, created);
          await route.fulfill({
            status: 201,
            contentType: 'application/json',
            body: JSON.stringify(created),
          });
          return;
        }
        if (request.method() === 'GET') {
          await route.fulfill({
            status: 200,
            contentType: 'application/json',
            body: JSON.stringify(providers),
          });
          return;
        }
        await route.continue();
      });

      await page.route('**/api/v1/notifications/providers/preview', async (route, request) => {
        capturedPreviewPayload = (await request.postDataJSON()) as Record<string, unknown>;
        await route.fulfill({
          status: 200,
          contentType: 'application/json',
          body: JSON.stringify({ rendered: '{"ok":true}', parsed: { ok: true } }),
        });
      });

      await page.route('**/api/v1/notifications/providers/test', async (route, request) => {
        capturedTestPayload = (await request.postDataJSON()) as Record<string, unknown>;
        await route.fulfill({
          status: 200,
          contentType: 'application/json',
          body: JSON.stringify({ message: 'Test notification sent' }),
        });
      });
    });

    await test.step('Fill gotify form with write-only token and trigger preview', async () => {
      await page.getByRole('button', { name: /add.*provider/i }).click();
      await page.getByTestId('provider-type').selectOption('gotify');
      await page.getByTestId('provider-name').fill(gotifyName);
      await page.getByTestId('provider-url').fill('https://gotify.example.com/message');
      await page.getByTestId('provider-gotify-token').fill('super-secret-token');

      const previewResponsePromise = page.waitForResponse(
        (response) =>
          /\/api\/v1\/notifications\/providers\/preview$/.test(response.url())
          && response.request().method() === 'POST'
      );
      await page.getByTestId('provider-preview-btn').click();
      const previewResponse = await previewResponsePromise;
      capturedPreviewPayload = (await previewResponse.request().postDataJSON()) as Record<string, unknown>;
    });

    await test.step('Save provider', async () => {
      await page.getByTestId('provider-save-btn').click();
    });

    await test.step('Send test from saved provider row', async () => {
      const providerRow = page.getByTestId('provider-row-gotify-transform-id');
      await expect(providerRow).toBeVisible({ timeout: 5000 });

      const testResponsePromise = page.waitForResponse(
        (response) =>
          /\/api\/v1\/notifications\/providers\/test$/.test(response.url())
          && response.request().method() === 'POST'
      );
      const sendTestButton = providerRow.getByRole('button', { name: /send test/i });
      await sendTestButton.click();
      const testResponse = await testResponsePromise;
      capturedTestPayload = (await testResponse.request().postDataJSON()) as Record<string, unknown>;
    });

    await test.step('Assert token is not sent on preview/test payloads', async () => {
      expect(capturedPreviewPayload).toBeTruthy();
      expect(capturedPreviewPayload?.type).toBe('gotify');
      expect(capturedPreviewPayload?.token).toBeUndefined();
      expect(capturedPreviewPayload?.gotify_token).toBeUndefined();

      expect(capturedTestPayload).toBeTruthy();
      expect(capturedTestPayload?.type).toBe('gotify');
      expect(capturedTestPayload?.token).toBeUndefined();
      expect(capturedTestPayload?.gotify_token).toBeUndefined();
    });
  });

  test('security: SSRF redirect/internal target, query-token, and oversized payload are blocked', async ({ page, adminUser }) => {
    await test.step('Enable gotify and webhook dispatch feature flags', async () => {
      await enableNotifyDispatchFlags(page, adminUser.token);
    });

    await test.step('Untrusted redirect/internal SSRF-style payload is rejected before dispatch', async () => {
      const response = await page.request.post('/api/v1/notifications/providers/test', {
        headers: { Authorization: `Bearer ${adminUser.token}` },
        data: {
          type: 'webhook',
          name: 'ssrf-test',
          url: 'https://127.0.0.1/internal',
          template: 'custom',
          config: '{"message":"{{.Message}}"}',
        },
      });

      expect(response.status()).toBe(400);
      const body = (await response.json()) as Record<string, unknown>;
      expect(body.code).toBe('MISSING_PROVIDER_ID');
      expect(body.category).toBe('validation');
      expect(String(body.error ?? '')).not.toContain('127.0.0.1');
    });

    await test.step('Gotify query-token URL is rejected with sanitized error', async () => {
      const queryToken = 's3cr3t-query-token';
      const response = await page.request.post('/api/v1/notifications/providers/test', {
        headers: { Authorization: `Bearer ${adminUser.token}` },
        data: {
          type: 'gotify',
          name: 'query-token-test',
          url: `https://gotify.example.com/message?token=${queryToken}`,
          template: 'custom',
          config: '{"message":"{{.Message}}"}',
        },
      });

      expect(response.status()).toBe(400);
      const body = (await response.json()) as Record<string, unknown>;
  expect(body.code).toBe('MISSING_PROVIDER_ID');
  expect(body.category).toBe('validation');

      const responseText = JSON.stringify(body);
      expect(responseText).not.toContain(queryToken);
      expect(responseText.toLowerCase()).not.toContain('token=');
    });

    await test.step('Oversized payload/template is rejected', async () => {
      const oversizedTemplate = `{"message":"${'x'.repeat(12_500)}"}`;
      const response = await page.request.post('/api/v1/notifications/providers/test', {
        headers: { Authorization: `Bearer ${adminUser.token}` },
        data: {
          type: 'webhook',
          name: 'oversized-template-test',
          url: 'https://example.com/webhook',
          template: 'custom',
          config: oversizedTemplate,
        },
      });

      expect(response.status()).toBe(400);
      const body = (await response.json()) as Record<string, unknown>;
      expect(body.code).toBe('MISSING_PROVIDER_ID');
      expect(body.category).toBe('validation');
    });
  });

  test('security: DNS-rebinding-observable hostname path is blocked with sanitized response', async ({ page, adminUser }) => {
    await test.step('Enable gotify and webhook dispatch feature flags', async () => {
      await enableNotifyDispatchFlags(page, adminUser.token);
    });

    await test.step('Untrusted hostname payload is blocked before dispatch (rebinding guard path)', async () => {
      const blockedHostname = 'rebind-check.127.0.0.1.nip.io';
      const response = await page.request.post('/api/v1/notifications/providers/test', {
        headers: { Authorization: `Bearer ${adminUser.token}` },
        data: {
          type: 'webhook',
          name: 'dns-rebinding-observable',
          url: `https://${blockedHostname}/notify`,
          template: 'custom',
          config: '{"message":"{{.Message}}"}',
        },
      });

      expect(response.status()).toBe(400);
      const body = (await response.json()) as Record<string, unknown>;
  expect(body.code).toBe('MISSING_PROVIDER_ID');
  expect(body.category).toBe('validation');

      const responseText = JSON.stringify(body);
      expect(responseText).not.toContain(blockedHostname);
      expect(responseText).not.toContain('127.0.0.1');
    });
  });

  test('security: retry split distinguishes retryable and non-retryable failures with deterministic response semantics', async ({ page }) => {
    const capturedTestPayloads: Array<Record<string, unknown>> = [];
    let nonRetryableBody: Record<string, unknown> | null = null;
    let retryableBody: Record<string, unknown> | null = null;
    const providers: Array<Record<string, unknown>> = [];
    let providerCounter = 0;

    await test.step('Stub provider create, list, and test endpoints', async () => {
      await page.route('**/api/v1/notifications/providers', async (route, request) => {
        if (request.method() === 'POST') {
          const payload = (await request.postDataJSON()) as Record<string, unknown>;
          providerCounter++;
          const created = { id: `retry-provider-${providerCounter}`, ...payload, enabled: true };
          providers.push(created);
          await route.fulfill({
            status: 201,
            contentType: 'application/json',
            body: JSON.stringify(created),
          });
          return;
        }
        if (request.method() === 'GET') {
          await route.fulfill({
            status: 200,
            contentType: 'application/json',
            body: JSON.stringify(providers),
          });
          return;
        }
        await route.continue();
      });

      await page.route('**/api/v1/notifications/providers/test', async (route, request) => {
        const payload = (await request.postDataJSON()) as Record<string, unknown>;
        capturedTestPayloads.push(payload);

        const scenarioName = String(payload.name ?? '');
        const isRetryable = scenarioName.includes('retryable') && !scenarioName.includes('non-retryable');
        const requestID = isRetryable ? 'stub-request-retryable' : 'stub-request-non-retryable';

        await route.fulfill({
          status: 400,
          contentType: 'application/json',
          body: JSON.stringify({
            code: 'PROVIDER_TEST_FAILED',
            category: 'dispatch',
            error: 'Provider test failed',
            request_id: requestID,
            retryable: isRetryable,
          }),
        });
      });
    });

    await test.step('Create and save non-retryable provider', async () => {
      await page.getByRole('button', { name: /add.*provider/i }).click();
      await page.getByTestId('provider-type').selectOption('webhook');
      await page.getByTestId('provider-name').fill('retry-split-non-retryable');
      await page.getByTestId('provider-url').fill('https://non-retryable.example.invalid/notify');
      await page.getByTestId('provider-save-btn').click();
    });

    await test.step('Execute deterministic non-retryable test call from saved row', async () => {
      const providerRow = page.getByTestId('provider-row-retry-provider-1');
      await expect(providerRow).toBeVisible({ timeout: 5000 });

      const nonRetryableResponsePromise = page.waitForResponse(
        (response) =>
          /\/api\/v1\/notifications\/providers\/test$/.test(response.url())
          && response.request().method() === 'POST'
          && (response.request().postData() ?? '').includes('retry-split-non-retryable')
      );

      const sendTestButton = providerRow.getByRole('button', { name: /send test/i });
      await sendTestButton.click();
      const nonRetryableResponse = await nonRetryableResponsePromise;
      nonRetryableBody = (await nonRetryableResponse.json()) as Record<string, unknown>;

      expect(nonRetryableResponse.status()).toBe(400);
      expect(nonRetryableBody.code).toBe('PROVIDER_TEST_FAILED');
      expect(nonRetryableBody.category).toBe('dispatch');
      expect(nonRetryableBody.error).toBe('Provider test failed');
      expect(nonRetryableBody.retryable).toBe(false);
      expect(nonRetryableBody.request_id).toBe('stub-request-non-retryable');
    });

    await test.step('Create and save retryable provider', async () => {
      await page.getByRole('button', { name: /add.*provider/i }).click();
      await page.getByTestId('provider-type').selectOption('webhook');
      await page.getByTestId('provider-name').fill('retry-split-retryable');
      await page.getByTestId('provider-url').fill('https://retryable.example.invalid/notify');
      await page.getByTestId('provider-save-btn').click();
    });

    await test.step('Execute deterministic retryable test call from saved row', async () => {
      const providerRow = page.getByTestId('provider-row-retry-provider-2');
      await expect(providerRow).toBeVisible({ timeout: 5000 });

      const retryableResponsePromise = page.waitForResponse(
        (response) =>
          /\/api\/v1\/notifications\/providers\/test$/.test(response.url())
          && response.request().method() === 'POST'
          && (response.request().postData() ?? '').includes('retry-split-retryable')
      );

      const sendTestButton = providerRow.getByRole('button', { name: /send test/i });
      await sendTestButton.click();
      const retryableResponse = await retryableResponsePromise;
      retryableBody = (await retryableResponse.json()) as Record<string, unknown>;

      expect(retryableResponse.status()).toBe(400);
      expect(retryableBody.code).toBe('PROVIDER_TEST_FAILED');
      expect(retryableBody.category).toBe('dispatch');
      expect(retryableBody.error).toBe('Provider test failed');
      expect(retryableBody.retryable).toBe(true);
      expect(retryableBody.request_id).toBe('stub-request-retryable');
    });

    await test.step('Assert stable split distinction and sanitized API contract shape', async () => {
      expect(capturedTestPayloads).toHaveLength(2);

      expect(capturedTestPayloads[0]?.name).toBe('retry-split-non-retryable');
      expect(capturedTestPayloads[1]?.name).toBe('retry-split-retryable');

      expect(nonRetryableBody).toMatchObject({
        code: 'PROVIDER_TEST_FAILED',
        category: 'dispatch',
        error: 'Provider test failed',
        retryable: false,
      });
      expect(retryableBody).toMatchObject({
        code: 'PROVIDER_TEST_FAILED',
        category: 'dispatch',
        error: 'Provider test failed',
        retryable: true,
      });

      test.info().annotations.push({
        type: 'retry-split-semantics',
        description: 'non-retryable and retryable contracts are validated via deterministic route-stubbed /providers/test responses',
      });
    });
  });

  test('security: token does not leak in list and visible edit surfaces', async ({ page, adminUser }) => {
    const name = `gotify-redaction-${Date.now()}`;
    let providerID = '';

    await test.step('Create gotify provider with token on write path', async () => {
      const createResponse = await page.request.post(PROVIDERS_ENDPOINT, {
        headers: { Authorization: `Bearer ${adminUser.token}` },
        data: {
          ...buildDiscordProviderPayload(name),
          type: 'gotify',
          url: 'https://gotify.example.com/message',
          token: 'write-only-secret-token',
          config: '{"message":"{{.Message}}"}',
        },
      });

      expect(createResponse.status()).toBe(201);
      const created = (await createResponse.json()) as Record<string, unknown>;
      providerID = String(created.id ?? '');
      expect(providerID.length).toBeGreaterThan(0);
    });

    await test.step('List providers does not expose token fields', async () => {
      const listResponse = await page.request.get(PROVIDERS_ENDPOINT, {
        headers: { Authorization: `Bearer ${adminUser.token}` },
      });
      expect(listResponse.ok()).toBeTruthy();

      const providers = (await listResponse.json()) as Array<Record<string, unknown>>;
      const gotify = providers.find((provider) => provider.id === providerID);
      expect(gotify).toBeTruthy();
      expect(gotify?.token).toBeUndefined();
      expect(gotify?.gotify_token).toBeUndefined();
    });

    await test.step('Edit form does not pre-fill token in visible surface', async () => {
      await page.reload();
      await waitForLoadingComplete(page);

      const row = page.getByTestId(`provider-row-${providerID}`);
      await expect(row).toBeVisible({ timeout: 10000 });

      const testButton = row.getByRole('button', { name: /send test notification/i });
      await expect(testButton).toBeVisible();
      await testButton.focus();
      await page.keyboard.press('Tab');
      await page.keyboard.press('Enter');

      const tokenInput = page.getByTestId('provider-gotify-token');
      await expect(tokenInput).toBeVisible();
      await expect(tokenInput).toHaveValue('');

      const pageText = await page.locator('main').innerText();
      expect(pageText).not.toContain('write-only-secret-token');
    });

    await test.step('Cleanup created provider', async () => {
      const deleteResponse = await page.request.delete(`${PROVIDERS_ENDPOINT}/${providerID}`, {
        headers: { Authorization: `Bearer ${adminUser.token}` },
      });

      expect(deleteResponse.ok()).toBeTruthy();
    });
  });
});
