## [E2E-5] Config edit saves and persists after page reload **Where found:** The `/config` page allows editing jail settings, filter definitions, and server-level options. It is covered by unit tests (`frontend/src/pages/__tests__/ConfigPage.test.tsx`, `backend/tests/test_routers/test_config.py`) but no E2E test verifies that a change made in the UI actually persists through the backend, survives a page reload, and reflects the new value. **Why this is needed:** The config page uses an auto-save mechanism (`useAutoSave`) that debounces writes. A regression in the debounce logic, the PATCH endpoint, or the GET-on-mount rehydration would silently discard user edits. Only a full round-trip test can catch this. **Goal:** Change a config field value via the UI, wait for the auto-save indicator to confirm the save, reload the page, and assert the new value is still present. **What to do:** 1. Create `e2e/tests/04_config_edit.robot`. 2. Suite Setup: `Login As Admin`. 3. Choose a safe, low-risk config field to edit — e.g., the `[DEFAULT]` `bantime` value, or a per-jail `maxretry` setting. 4. Record the original value before editing so it can be restored in teardown. 5. Test case: ```robot *** Settings *** Library Browser Resource ../resources/auth.resource Test Teardown Restore Original Config Value *** Test Cases *** Config Field Edit Persists After Reload Login As Admin Go To ${FRONTEND_URL}/config Wait For Elements State css=[role="tablist"] visible timeout=15s # Read current value for teardown ${original}= Get Text css=[data-field="bantime"] Set Suite Variable ${ORIGINAL_BANTIME} ${original} # Edit the field Fill Text css=[data-field="bantime"] 7200 # Wait for auto-save indicator to show "Saved" Wait For Elements State css=[data-autosave="saved"] visible timeout=15s # Reload and verify persistence Reload Wait For Elements State css=[data-field="bantime"] visible timeout=15s Get Text css=[data-field="bantime"] == 7200 *** Keywords *** Restore Original Config Value Go To ${FRONTEND_URL}/config Fill Text css=[data-field="bantime"] ${ORIGINAL_BANTIME} Wait For Elements State css=[data-autosave="saved"] visible timeout=15s ``` 6. Also verify via the API that the value was actually written: ```robot ${resp}= GET ${BACKEND_URL}/api/config expected_status=200 Should Contain ${resp.text} 7200 ``` **Possible traps and issues:** - The config page auto-save uses a debounce delay. The test must wait for the "Saved" indicator rather than a fixed `Sleep`, otherwise the reload may happen before the PATCH request fires. - The selectors `[data-field="bantime"]` and `[data-autosave="saved"]` do not exist in the current frontend components (no `data-*` attributes on production elements). These must be added to the components before the test can work. See [E2E-6] for the prerequisite task. - Config fields are rendered inside a tab panel. The correct tab must be activated before the target field is interactable. The test must click the right tab first. - If the backend validates the new value and rejects it (e.g., bantime must be a positive integer), the test will fail at the API assertion. Use a value that is guaranteed to be valid. - Editing config files on disk via the API may restart the fail2ban service inside the container, causing a brief health-check failure and destabilising subsequent tests in the suite. Run config edit tests last or use a test-only jail that is isolated from the main config. - Teardown must restore the original value even if the test fails mid-way. Ensure `Test Teardown` is set, not just a final keyword call. **Docs changes needed:** - Document the auto-save debounce behaviour and the "Saved" indicator semantics in [Web-Development.md](Web-Development.md) so E2E test authors know what to wait for. - Note in [Testing-Requirements.md](Testing-Requirements.md) that config edit tests must restore state in teardown. **Doc references:** - [Web-Development.md](Web-Development.md) - [CONFIGURATION.md](CONFIGURATION.md) - [Testing-Requirements.md](Testing-Requirements.md) - `frontend/src/components/config/__tests__/AutoSaveIndicator.test.tsx` - `frontend/src/hooks/__tests__/useAutoSave.test.ts` - `backend/tests/test_routers/test_config.py` --- ## [E2E-6] Add `data-testid` / `data-*` attributes to production frontend components **Where found:** Inspecting the frontend source, `data-testid` attributes appear only in test mock files (e.g., `MapPage.test.tsx` line 57: `
`). The production components in `frontend/src/components/` and `frontend/src/pages/` have no `data-testid` or `data-*` attributes. E2E tests [E2E-2], [E2E-4], and [E2E-5] all require stable selectors that survive CSS and class-name refactors. **Why this is needed:** CSS class selectors and `aria-label` text are brittle — they break when styles change or text is translated. `data-testid` attributes are the idiomatic, refactor-safe way to locate elements in E2E tests. Without them, every UI change risks breaking the E2E suite for reasons unrelated to correctness. **Goal:** Key interactive and landmark elements across all pages and the config form have `data-testid` (or semantic `data-*`) attributes that the Robot Framework E2E suite can rely on. **What to do:** 1. Identify the minimum set of elements needed by the four E2E suites: - `data-testid="page-error-boundary"` on the `PageErrorBoundary` fallback render. - `data-testid="dashboard"`, `data-testid="map-page"`, `data-testid="jails-page"`, `data-testid="history-page"`, `data-testid="blocklists-page"`, `data-testid="config-page"` on each page's root element. - `data-testid="history-table"` on the History page table body. - `data-testid="blocklist-import-button"` on the manual import trigger. - `data-testid="autosave-status"` on the auto-save indicator, with `data-status="saved" | "saving" | "error"`. - `data-field=""` on config input fields that E2E tests will edit. 2. Add the attributes directly to the JSX — no wrappers, no extra elements. 3. Do not add `data-testid` to elements that already have stable semantic roles (e.g., `