- Added aria-label attributes to buttons in Notifications component for better accessibility. - Updated Notifications tests to use new button interactions and ensure proper functionality. - Refactored notifications payload tests to mock API responses and validate payload transformations. - Improved error handling and feedback in notification provider tests. - Adjusted Telegram notification provider tests to streamline edit interactions.
498 lines
22 KiB
Markdown
498 lines
22 KiB
Markdown
# Telegram Notification Provider — Test Failure Remediation Plan
|
||
|
||
**Date:** 2026-03-11
|
||
**Author:** Planning Agent
|
||
**Status:** Remediation Required — All security scans pass, test failures block merge
|
||
**Previous Plan:** Archived as `docs/plans/telegram_implementation_spec.md`
|
||
|
||
---
|
||
|
||
## 1. Introduction
|
||
|
||
The Telegram notification provider feature is functionally complete with passing security scans and coverage gates. However, **56 E2E test failures** and **2 frontend unit test failures** block the PR merge. This plan identifies root causes, categorises each failure set, and provides specific remediation steps.
|
||
|
||
### Failure Summary
|
||
|
||
| Spec File | Failures | Browsers | Unique Est. | Category |
|
||
|---|---|---|---|---|
|
||
| `notifications.spec.ts` | 48 | 3 | ~16 | **Our change** |
|
||
| `notifications-payload.spec.ts` | 18 | 3 | ~6 | **Our change** |
|
||
| `telegram-notification-provider.spec.ts` | 4 | 1–3 | ~2 | **Our change** |
|
||
| `encryption-management.spec.ts` | 20 | 3 | ~7 | Pre-existing |
|
||
| `auth-middleware-cascade.spec.ts` | 18 | 3 | 6 | Pre-existing |
|
||
| `Notifications.test.tsx` (unit) | 2 | — | 2 | **Our change** |
|
||
|
||
CI retries: 2 per test (`playwright.config.js` L144). Failure counts above represent unique test failures × browser projects.
|
||
|
||
---
|
||
|
||
## 2. Root Cause Analysis
|
||
|
||
### Root Cause A: `isNew` Guard on Test Button (CRITICAL — Causes ~80% of failures)
|
||
|
||
**What changed:** The Telegram feature added a guard in `Notifications.tsx` (L117-124) that blocks the "Test" button for new (unsaved) providers:
|
||
|
||
```typescript
|
||
// Line 117-124: handleTest() early return guard
|
||
const handleTest = () => {
|
||
const formData = watch();
|
||
const currentType = normalizeProviderType(formData.type);
|
||
if (!formData.id && currentType !== 'email') {
|
||
toast.error(t('notificationProviders.saveBeforeTesting'));
|
||
return;
|
||
}
|
||
testMutation.mutate({ ...formData, type: currentType } as Partial<NotificationProvider>);
|
||
};
|
||
```
|
||
|
||
And a `disabled` attribute on the test button at `Notifications.tsx` (L382):
|
||
|
||
```typescript
|
||
// Line 382: Button disabled state
|
||
disabled={testMutation.isPending || (isNew && !isEmail)}
|
||
```
|
||
|
||
**Why it was added:** The backend `Test` handler at `notification_provider_handler.go` (L333-336) requires a saved provider ID for all non-email types. For Gotify/Telegram, the server needs the stored token. For Discord/Webhook, the server still fetches the provider from DB. Without a saved provider, the backend returns `MISSING_PROVIDER_ID`.
|
||
|
||
**Why it breaks tests:** Many existing E2E and unit tests click the test button from a **new (unsaved) provider form** using mocked endpoints. With the new guard:
|
||
1. The `<button>` is `disabled` → browser ignores clicks → mocked routes never receive requests
|
||
2. Even if not disabled, `handleTest()` returns early with a toast instead of calling `testMutation.mutate()`
|
||
3. Tests that `waitForRequest` on `/providers/test` time out (60s default)
|
||
4. Tests that assert on `capturedTestPayload` find `null`
|
||
|
||
**Is the guard correct?** Yes — it matches the backend's security-by-design constraint. The tests need to be adapted to the new behavior, not the guard removed.
|
||
|
||
### Root Cause B: Pre-existing Infrastructure Failures (encryption-management, auth-middleware-cascade)
|
||
|
||
**encryption-management.spec.ts** (17 tests, ~7 unique failures) navigates to `/security/encryption` and tests key rotation, validation, and history display. **Zero overlap** with notification provider code paths. No files modified in the Telegram PR affect encryption.
|
||
|
||
**auth-middleware-cascade.spec.ts** (6 tests, all 6 fail) uses deprecated `waitUntil: 'networkidle'`, creates proxy hosts via UI forms (`getByLabel(/domain/i)`), and tests auth flows through Caddy. **Zero overlap** with notification code. These tests have known fragility from UI element selectors and `networkidle` waits.
|
||
|
||
**Verdict:** Both are pre-existing failures. They should be tracked separately and not block the Telegram PR.
|
||
|
||
### Root Cause C: Telegram E2E Spec Issues (4 failures)
|
||
|
||
The `telegram-notification-provider.spec.ts` has 8 tests, with ~2 unique failures. Most likely candidates:
|
||
|
||
1. **"should edit telegram notification provider and preserve token"** (L159): Uses fragile keyboard navigation (focus Send Test → Tab → Enter) to reach the Edit button. If the `title` attribute on the Send Test button doesn't match the accessible name pattern `/send test/i`, or if the tab order is affected by any intermediate focusable element, the Enter press activates the wrong button or nothing at all.
|
||
|
||
2. **"should test telegram notification provider"** (L265): Clicks the row-level "Send Test" button. The locator uses `getByRole('button', { name: /send test/i })`. The button has `title={t('notificationProviders.sendTest')}` which renders as "Send Test". This should work, but the `title` attribute contributing to accessible name can be browser-dependent, particularly in WebKit.
|
||
|
||
---
|
||
|
||
## 3. Affected Tests — Complete Inventory
|
||
|
||
### 3.1 E2E Tests: `notifications.spec.ts` (Test Button on New Form)
|
||
|
||
These tests open the "Add Provider" form (no `id`), click `provider-test-btn`, and expect API interactions. The disabled button now prevents all interaction.
|
||
|
||
| # | Test Name | Line | Type Used | Failure Mode |
|
||
|---|---|---|---|---|
|
||
| 1 | should test notification provider | L1085 | discord | `waitForRequest` times out — button disabled |
|
||
| 2 | should show test success feedback | L1142 | discord | Success icon never appears — no click fires |
|
||
| 3 | should preserve Discord request payload contract for save, preview, and test | L1236 | discord | `capturedTestPayload` is null — button disabled |
|
||
| 4 | should show error when test fails | L1665 | discord | Error icon never appears — no click fires |
|
||
|
||
**Additional cascade effects:** The user reports ~16 unique failures from this file. The 4 above are directly caused by the `isNew` guard. Remaining failures may stem from cascading timeout effects, `beforeEach` state leakage after long timeouts, or other pre-existing flakiness amplified by the 60s timeout waterfall.
|
||
|
||
### 3.2 E2E Tests: `notifications-payload.spec.ts` (Test Button on New Form)
|
||
|
||
| # | Test Name | Line | Type Used | Failure Mode |
|
||
|---|---|---|---|---|
|
||
| 1 | provider-specific transformation strips gotify token from test and preview payloads | L264 | gotify | `provider-test-btn` disabled for new gotify form; `capturedTestPayload` is null |
|
||
| 2 | retry split distinguishes retryable and non-retryable failures | L410 | webhook | `provider-test-btn` disabled for new webhook form; `waitForResponse` times out |
|
||
|
||
**Tests that should still pass:**
|
||
- `valid payload flows for discord, gotify, and webhook` (L54) — uses `provider-save-btn`, not test button
|
||
- `malformed payload scenarios` (L158) — API-level tests via `page.request.post`
|
||
- `missing required fields block submit` (L192) — uses save button
|
||
- `auth/header behavior checks` (L217) — API-level tests
|
||
- `security: SSRF` (L314) — API-level tests
|
||
- `security: DNS-rebinding` (L381) — API-level tests
|
||
- `security: token does not leak` (L512) — API-level tests
|
||
|
||
### 3.3 E2E Tests: `telegram-notification-provider.spec.ts`
|
||
|
||
| # | Test Name | Line | Probable Failure Mode |
|
||
|---|---|---|---|
|
||
| 1 | should edit telegram notification provider and preserve token | L159 | Keyboard navigation (Tab from Send Test → Edit) fragility; may hit wrong element on some browsers |
|
||
| 2 | should test telegram notification provider | L265 | Row-level Send Test button; possible accessible name mismatch in WebKit with `title` attribute |
|
||
|
||
**Tests that should pass:**
|
||
- Form rendering tests (L25, L65) — UI assertions only
|
||
- Create telegram provider (L89) — mocked POST
|
||
- Delete telegram provider (L324) — mocked DELETE + confirm dialog
|
||
- Security tests (L389, L436) — mock-based assertions
|
||
|
||
### 3.4 Frontend Unit Tests: `Notifications.test.tsx`
|
||
|
||
| # | Test Name | Line | Failure Mode |
|
||
|---|---|---|---|
|
||
| 1 | submits provider test action from form using normalized discord type | L447 | `userEvent.click()` on disabled button is no-op → `testProvider` never called → `waitFor` times out |
|
||
| 2 | shows error toast when test mutation fails | L569 | Same — disabled button prevents click → `toast.error` with `saveBeforeTesting` fires instead of mutation error |
|
||
|
||
### 3.5 Pre-existing (Not Caused By Telegram PR)
|
||
|
||
| Spec | Tests | Rationale |
|
||
|---|---|---|
|
||
| `encryption-management.spec.ts` | ~7 unique | Tests encryption page at `/security/encryption`. No code overlap. |
|
||
| `auth-middleware-cascade.spec.ts` | 6 unique | Tests proxy creation + auth middleware. Uses `networkidle`. No code overlap. |
|
||
|
||
---
|
||
|
||
## 4. Remediation Plan
|
||
|
||
### Priority Order
|
||
|
||
1. **P0 — Fix unit tests** (fastest, unblocks local dev verification)
|
||
2. **P1 — Fix E2E test-button tests** (the core regression from our change)
|
||
3. **P2 — Fix telegram spec fragility** (new tests we added)
|
||
4. **P3 — Document pre-existing failures** (not our change, track separately)
|
||
|
||
---
|
||
|
||
### 4.1 P0: Frontend Unit Test Fixes
|
||
|
||
**File:** `frontend/src/pages/__tests__/Notifications.test.tsx`
|
||
|
||
#### Fix 1: "submits provider test action from form using normalized discord type" (L447)
|
||
|
||
**Problem:** Test opens "Add Provider" (new form, no `id`), clicks test button. Button is now disabled for new providers.
|
||
|
||
**Fix:** Change to test from an **existing provider's edit form** instead of a new form. This preserves the original intent (verifying the test payload uses normalized type).
|
||
|
||
```typescript
|
||
// BEFORE (L447-462):
|
||
it('submits provider test action from form using normalized discord type', async () => {
|
||
vi.mocked(notificationsApi.testProvider).mockResolvedValue()
|
||
const user = userEvent.setup()
|
||
renderWithQueryClient(<Notifications />)
|
||
|
||
await user.click(await screen.findByTestId('add-provider-btn'))
|
||
await user.type(screen.getByTestId('provider-name'), 'Preview/Test Provider')
|
||
await user.type(screen.getByTestId('provider-url'), 'https://example.com/webhook')
|
||
await user.click(screen.getByTestId('provider-test-btn'))
|
||
|
||
await waitFor(() => {
|
||
expect(notificationsApi.testProvider).toHaveBeenCalled()
|
||
})
|
||
const payload = vi.mocked(notificationsApi.testProvider).mock.calls[0][0]
|
||
expect(payload.type).toBe('discord')
|
||
})
|
||
|
||
// AFTER:
|
||
it('submits provider test action from form using normalized discord type', async () => {
|
||
vi.mocked(notificationsApi.testProvider).mockResolvedValue()
|
||
setupMocks([baseProvider]) // baseProvider has an id
|
||
const user = userEvent.setup()
|
||
renderWithQueryClient(<Notifications />)
|
||
|
||
// Open edit form for existing provider (has id → test button enabled)
|
||
const row = await screen.findByTestId(`provider-row-${baseProvider.id}`)
|
||
const buttons = within(row).getAllByRole('button')
|
||
await user.click(buttons[1]) // Edit button
|
||
|
||
await user.click(screen.getByTestId('provider-test-btn'))
|
||
|
||
await waitFor(() => {
|
||
expect(notificationsApi.testProvider).toHaveBeenCalled()
|
||
})
|
||
const payload = vi.mocked(notificationsApi.testProvider).mock.calls[0][0]
|
||
expect(payload.type).toBe('discord')
|
||
})
|
||
```
|
||
|
||
#### Fix 2: "shows error toast when test mutation fails" (L569)
|
||
|
||
**Problem:** Same — test opens new form, clicks test button, expects mutation error toast. Button is disabled.
|
||
|
||
**Fix:** Test from an existing provider's edit form.
|
||
|
||
```typescript
|
||
// BEFORE (L569-582):
|
||
it('shows error toast when test mutation fails', async () => {
|
||
vi.mocked(notificationsApi.testProvider).mockRejectedValue(new Error('Connection refused'))
|
||
const user = userEvent.setup()
|
||
renderWithQueryClient(<Notifications />)
|
||
|
||
await user.click(await screen.findByTestId('add-provider-btn'))
|
||
await user.type(screen.getByTestId('provider-name'), 'Failing Provider')
|
||
await user.type(screen.getByTestId('provider-url'), 'https://example.com/webhook')
|
||
await user.click(screen.getByTestId('provider-test-btn'))
|
||
|
||
await waitFor(() => {
|
||
expect(toast.error).toHaveBeenCalledWith('Connection refused')
|
||
})
|
||
})
|
||
|
||
// AFTER:
|
||
it('shows error toast when test mutation fails', async () => {
|
||
vi.mocked(notificationsApi.testProvider).mockRejectedValue(new Error('Connection refused'))
|
||
setupMocks([baseProvider])
|
||
const user = userEvent.setup()
|
||
renderWithQueryClient(<Notifications />)
|
||
|
||
// Open edit form for existing provider
|
||
const row = await screen.findByTestId(`provider-row-${baseProvider.id}`)
|
||
const buttons = within(row).getAllByRole('button')
|
||
await user.click(buttons[1]) // Edit button
|
||
|
||
await user.click(screen.getByTestId('provider-test-btn'))
|
||
|
||
await waitFor(() => {
|
||
expect(toast.error).toHaveBeenCalledWith('Connection refused')
|
||
})
|
||
})
|
||
```
|
||
|
||
#### Bonus: Add a NEW unit test for the `saveBeforeTesting` guard
|
||
|
||
```typescript
|
||
it('disables test button when provider is new (unsaved) and not email type', async () => {
|
||
const user = userEvent.setup()
|
||
renderWithQueryClient(<Notifications />)
|
||
|
||
await user.click(await screen.findByTestId('add-provider-btn'))
|
||
const testBtn = screen.getByTestId('provider-test-btn')
|
||
expect(testBtn).toBeDisabled()
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
### 4.2 P1: E2E Test Fixes — notifications.spec.ts
|
||
|
||
**File:** `tests/settings/notifications.spec.ts`
|
||
|
||
**Strategy:** For tests that click the test button from a new form, restructure the flow to:
|
||
1. First **save** the provider (mocked create → returns id)
|
||
2. Then **test** from the saved provider row's Send Test button (row buttons are not gated by `isNew`)
|
||
|
||
#### Fix 3: "should test notification provider" (L1085)
|
||
|
||
**Current flow:** Add form → fill → mock test endpoint → click `provider-test-btn` → verify request
|
||
**Problem:** Test button disabled for new form
|
||
**Fix:** Save first, then click test from the provider row's Send Test button.
|
||
|
||
```typescript
|
||
// In the test, after filling the form and before clicking test:
|
||
|
||
// 1. Mock the create endpoint to return a provider with an id
|
||
await page.route('**/api/v1/notifications/providers', async (route, request) => {
|
||
if (request.method() === 'POST') {
|
||
const payload = await request.postDataJSON();
|
||
await route.fulfill({
|
||
status: 201,
|
||
contentType: 'application/json',
|
||
body: JSON.stringify({ id: 'saved-test-id', ...payload }),
|
||
});
|
||
} else if (request.method() === 'GET') {
|
||
await route.fulfill({
|
||
status: 200,
|
||
contentType: 'application/json',
|
||
body: JSON.stringify([{
|
||
id: 'saved-test-id',
|
||
name: 'Test Provider',
|
||
type: 'discord',
|
||
url: 'https://discord.com/api/webhooks/test/token',
|
||
enabled: true
|
||
}]),
|
||
});
|
||
} else {
|
||
await route.continue();
|
||
}
|
||
});
|
||
|
||
// 2. Save the provider first
|
||
await page.getByTestId('provider-save-btn').click();
|
||
|
||
// 3. Wait for the provider to appear in the list
|
||
await expect(page.getByText('Test Provider')).toBeVisible({ timeout: 5000 });
|
||
|
||
// 4. Click row-level Send Test button
|
||
const providerRow = page.getByTestId('provider-row-saved-test-id');
|
||
const sendTestButton = providerRow.getByRole('button', { name: /send test/i });
|
||
await sendTestButton.click();
|
||
```
|
||
|
||
#### Fix 4: "should show test success feedback" (L1142)
|
||
|
||
Same pattern as Fix 3: save provider first, then test from row.
|
||
|
||
#### Fix 5: "should preserve Discord request payload contract for save, preview, and test" (L1236)
|
||
|
||
**Current flow:** Add form → fill → click preview → click test → save → verify all payloads
|
||
**Problem:** Test button disabled for new form
|
||
**Fix:** Reorder to: Add form → fill → click preview → **save** → **test from row** → verify payloads
|
||
|
||
The preview button is NOT disabled for new forms (only the test button is), so preview still works from the new form. The test step must happen after save.
|
||
|
||
#### Fix 6: "should show error when test fails" (L1665)
|
||
|
||
Same pattern: save first, then test from row.
|
||
|
||
---
|
||
|
||
### 4.3 P1: E2E Test Fixes — notifications-payload.spec.ts
|
||
|
||
**File:** `tests/settings/notifications-payload.spec.ts`
|
||
|
||
#### Fix 7: "provider-specific transformation strips gotify token from test and preview payloads" (L264)
|
||
|
||
**Current flow:** Add gotify form → fill with token → click preview → click test → verify token not in payloads
|
||
**Problem:** Test button disabled for new gotify form
|
||
**Fix:** Preview still works from new form. For test, save first, then test from the saved provider row.
|
||
|
||
**Note:** The row-level test call uses `{ ...provider, type: normalizeProviderType(provider.type) }` where `provider` is the list item (which never contains `token/gotify_token` per the List handler that strips tokens). So the token-stripping assertion naturally holds for row-level tests.
|
||
|
||
#### Fix 8: "retry split distinguishes retryable and non-retryable failures" (L410)
|
||
|
||
**Current flow:** Add webhook form → fill → click test → verify retry semantics
|
||
**Problem:** Test button disabled for new webhook form
|
||
**Fix:** Save first (mock create), then open edit form (which has `id`) or test from the row.
|
||
|
||
---
|
||
|
||
### 4.4 P2: Telegram E2E Spec Hardening
|
||
|
||
**File:** `tests/settings/telegram-notification-provider.spec.ts`
|
||
|
||
#### Fix 9: "should edit telegram notification provider and preserve token" (L159)
|
||
|
||
**Problem:** Uses fragile keyboard navigation to reach the Edit button:
|
||
```typescript
|
||
await sendTestButton.focus();
|
||
await page.keyboard.press('Tab');
|
||
await page.keyboard.press('Enter');
|
||
```
|
||
|
||
This assumes Tab from Send Test lands on Edit. Tab order can vary across browsers.
|
||
|
||
**Fix:** Use a direct locator for the Edit button instead of keyboard navigation:
|
||
|
||
```typescript
|
||
// BEFORE:
|
||
await sendTestButton.focus();
|
||
await page.keyboard.press('Tab');
|
||
await page.keyboard.press('Enter');
|
||
|
||
// AFTER:
|
||
const editButton = providerRow.getByRole('button').nth(1); // Send Test=0, Edit=1
|
||
await editButton.click();
|
||
```
|
||
|
||
Or use a structural locator based on the edit icon class.
|
||
|
||
#### Fix 10: "should test telegram notification provider" (L265)
|
||
|
||
**Probable issue:** The `getByRole('button', { name: /send test/i })` relies on `title` for accessible name. WebKit may not compute accessible name from `title` the same way.
|
||
|
||
**Fix (source — preferred):** Add explicit `aria-label` to the row Send Test button in `Notifications.tsx` (L703):
|
||
```tsx
|
||
<Button
|
||
variant="secondary"
|
||
size="sm"
|
||
onClick={() => testMutation.mutate({...})}
|
||
title={t('notificationProviders.sendTest')}
|
||
aria-label={t('notificationProviders.sendTest')}
|
||
>
|
||
```
|
||
|
||
**Fix (test — alternative):** Use structural locator:
|
||
```typescript
|
||
const sendTestButton = providerRow.locator('button').first();
|
||
```
|
||
|
||
---
|
||
|
||
### 4.5 P3: Document Pre-existing Failures
|
||
|
||
**Action:** File separate issues (not part of this PR) for:
|
||
|
||
1. **encryption-management.spec.ts** — ~7 unique test failures in `/security/encryption`. Likely UI rendering timing issues or flaky selectors. No code overlap with Telegram PR.
|
||
|
||
2. **auth-middleware-cascade.spec.ts** — All 6 tests fail × 3 browsers. Uses deprecated `waitUntil: 'networkidle'`, creates proxy hosts through fragile UI selectors (`getByLabel(/domain/i)`), and tests auth middleware cascade. Needs modernization pass for locators and waits.
|
||
|
||
---
|
||
|
||
## 5. Implementation Plan
|
||
|
||
### Phase 1: Unit Test Fixes (Immediate)
|
||
|
||
| Task | File | Lines | Complexity |
|
||
|---|---|---|---|
|
||
| Fix "submits provider test action" test | `Notifications.test.tsx` | L447-462 | Low |
|
||
| Fix "shows error toast" test | `Notifications.test.tsx` | L569-582 | Low |
|
||
| Add `saveBeforeTesting` guard unit test | `Notifications.test.tsx` | New | Low |
|
||
|
||
**Validation:** `cd frontend && npx vitest run src/pages/__tests__/Notifications.test.tsx`
|
||
|
||
### Phase 2: E2E Test Fixes — Core Regression
|
||
|
||
| Task | File | Lines | Complexity |
|
||
|---|---|---|---|
|
||
| Fix "should test notification provider" | `notifications.spec.ts` | L1085-1138 | Medium |
|
||
| Fix "should show test success feedback" | `notifications.spec.ts` | L1142-1178 | Medium |
|
||
| Fix "should preserve Discord payload contract" | `notifications.spec.ts` | L1236-1340 | Medium |
|
||
| Fix "should show error when test fails" | `notifications.spec.ts` | L1665-1706 | Medium |
|
||
| Fix "transformation strips gotify token" | `notifications-payload.spec.ts` | L264-312 | Medium |
|
||
| Fix "retry split retryable/non-retryable" | `notifications-payload.spec.ts` | L410-510 | High |
|
||
|
||
**Validation per test:** `npx playwright test --project=firefox <spec-file> -g "<test-name>"`
|
||
|
||
### Phase 3: Telegram Spec Hardening
|
||
|
||
| Task | File | Lines | Complexity |
|
||
|---|---|---|---|
|
||
| Replace keyboard nav with direct locator | `telegram-notification-provider.spec.ts` | L220-223 | Low |
|
||
| Add `aria-label` to row Send Test button | `Notifications.tsx` | L703-708 | Low |
|
||
| Verify all 8 telegram tests pass 3 browsers | All | — | Low |
|
||
|
||
**Validation:** `npx playwright test tests/settings/telegram-notification-provider.spec.ts`
|
||
|
||
### Phase 4: Accessibility Hardening (Optional — Low Priority)
|
||
|
||
Consider adding `aria-label` attributes to all icon-only buttons in the provider row for improved accessibility and test resilience:
|
||
|
||
| Button | Current Accessible Name Source | Recommended |
|
||
|---|---|---|
|
||
| Send Test | `title` attribute | Add `aria-label` |
|
||
| Edit | None (icon only) | Add `aria-label={t('common.edit')}` |
|
||
| Delete | None (icon only) | Add `aria-label={t('common.delete')}` |
|
||
|
||
---
|
||
|
||
## 6. Commit Slicing Strategy
|
||
|
||
**Decision:** Single PR with 2 focused commits
|
||
|
||
**Rationale:** All fixes are tightly coupled to the Telegram feature PR and represent test adaptations to a correct behavioral change. No cross-domain changes. Small total diff.
|
||
|
||
### Commit 1: "fix(test): adapt notification tests to save-before-test guard"
|
||
- **Scope:** All unit test and E2E test fixes (Phases 1-3)
|
||
- **Files:** `Notifications.test.tsx`, `notifications.spec.ts`, `notifications-payload.spec.ts`, `telegram-notification-provider.spec.ts`
|
||
- **Dependencies:** None
|
||
- **Validation Gate:** All notification-related tests pass locally on at least one browser
|
||
|
||
### Commit 2: "feat(a11y): add aria-labels to notification provider row buttons"
|
||
- **Scope:** Source code accessibility improvement (Phase 4)
|
||
- **Files:** `Notifications.tsx`
|
||
- **Dependencies:** Depends on Commit 1 (tests must pass first)
|
||
- **Validation Gate:** Telegram spec tests pass consistently on WebKit
|
||
|
||
### Rollback
|
||
- These are test-only changes (except the optional aria-label). Reverting either commit has zero production impact.
|
||
- If tests still fail after fixes, the next step is to run with `--debug` and capture trace artifacts.
|
||
|
||
---
|
||
|
||
## 7. Acceptance Criteria
|
||
|
||
- [ ] `Notifications.test.tsx` — all 2 previously failing tests pass
|
||
- [ ] `notifications.spec.ts` — all 4 isNew-guard-affected tests pass on 3 browsers
|
||
- [ ] `notifications-payload.spec.ts` — "transformation" and "retry split" tests pass on 3 browsers
|
||
- [ ] `telegram-notification-provider.spec.ts` — all 8 tests pass on 3 browsers
|
||
- [ ] No regressions in other notification tests
|
||
- [ ] New unit test validates the `saveBeforeTesting` guard / disabled button behavior
|
||
- [ ] `encryption-management.spec.ts` and `auth-middleware-cascade.spec.ts` failures documented as separate issues (not blocked by this PR)
|