fix(tests): Enhance CrowdSecConfig with new input fields and improve accessibility
- Added IDs to input fields in CrowdSecConfig for better accessibility. - Updated labels to use <label> elements for checkboxes and inputs. - Improved error handling and user feedback in the CrowdSecConfig tests. - Enhanced test coverage for console enrollment and banned IP functionalities. fix: Update SecurityHeaders to include aria-label for delete button - Added aria-label to the delete button for better screen reader support. test: Add comprehensive tests for proxyHostsHelpers and validation utilities - Implemented tests for formatting and help text functions in proxyHostsHelpers. - Added validation tests for email and IP address formats. chore: Update vitest configuration for dynamic coverage thresholds - Adjusted coverage thresholds to be dynamic based on environment variables. - Included additional coverage reporters. chore: Update frontend-test-coverage script to reflect new coverage threshold - Increased minimum coverage requirement from 85% to 87.5%. fix: Ensure tests pass with consistent data in passwd file - Updated tests/etc/passwd to ensure consistent content.
This commit is contained in:
@@ -1,55 +1,152 @@
|
||||
# Frontend Coverage Boost Plan (>=85%)
|
||||
# Frontend Test Coverage Improvement Plan
|
||||
|
||||
Current (QA): statements 84.54%, branches 75.85%, functions 78.97%.
|
||||
Goal: reach >=85% with the smallest number of high-yield tests.
|
||||
## Objective
|
||||
Increase frontend test coverage to **88%** locally while maintaining stable CI builds. Current overall line coverage is **84.73%**.
|
||||
|
||||
## Targeted Tests (minimal set with maximum lift)
|
||||
## Strategy
|
||||
|
||||
- **API units (fast, high gap)**
|
||||
- [src/api/notifications.ts](frontend/src/api/notifications.ts): cover payload branches in `previewProvider` (with/without `data`) and `previewExternalTemplate` (id vs inline template vs both), plus happy-path CRUD wrappers to verify endpoint URLs.
|
||||
- [src/api/logs.ts](frontend/src/api/logs.ts): assert `getLogContent` query param building (search/host/status/level/sort), `downloadLog` sets `window.location.href`, and `connectLiveLogs` callbacks for `onOpen`, `onMessage` (valid JSON), parse error branch, `onError`, and `onClose` (closing when readyState OPEN/CONNECTING).
|
||||
- [src/api/users.ts](frontend/src/api/users.ts): cover invite, permissions update, validate/accept invite paths; assert returned shapes and URL composition (e.g., `/users/${id}/permissions`).
|
||||
1. **Target Low Coverage / High Value Areas**: Focus on components with complex logic or API interactions that are currently under-tested.
|
||||
2. **Environment-Specific Thresholds**: Implement dynamic coverage thresholds to enforce high standards locally without causing CI fragility.
|
||||
|
||||
- **Component tests (few, branch-heavy)**
|
||||
- [src/pages/SMTPSettings.tsx](frontend/src/pages/SMTPSettings.tsx): component test with React Testing Library (RTL).
|
||||
- Ensure initial render waits for query then hydrates host/port/encryption (flaky area); verify loading spinner disappears.
|
||||
- Save success vs error toast branches; `Test Connection` success/error; `Send Test Email` success clears input and error path shows toast.
|
||||
- Button disables: test connection disabled when `host` or `fromAddress` empty; send test disabled when `testEmail` empty.
|
||||
- [src/components/LiveLogViewer.tsx](frontend/src/components/LiveLogViewer.tsx): component test with mocked `WebSocket` and `connectLiveLogs`.
|
||||
- Verify pause/resume toggles, log trimming to `maxLogs`, filter by text/level, parse-error branch (bad JSON), and disconnect cleanup invokes returned close fn.
|
||||
- [src/pages/UsersPage.tsx](frontend/src/pages/UsersPage.tsx): component test.
|
||||
- Invite modal success when `email_sent` false shows manual link copy branch; toggle permission mode text for allow_all vs deny_all; checkbox host toggle logic.
|
||||
- Permissions modal seeds state from selected user and saves via `updateUserPermissions` mutation.
|
||||
- Delete confirm branch (stub `confirm`), enabled Switch disabled for admins, enabled toggles for non-admin users.
|
||||
## Targeted Files
|
||||
|
||||
- **Security & CrowdSec flows**
|
||||
- [src/pages/CrowdSecConfig.tsx](frontend/src/pages/CrowdSecConfig.tsx): component test (can mock queries/mutations).
|
||||
- Cover hub unavailable (503) -> `preset-hub-unavailable`, cached preview fallback via `getCrowdsecPresetCache`, validation error (400) -> `preset-validation-error`, and apply fallback when backend returns 501 to hit local apply path and `preset-apply-info` rendering.
|
||||
- Import flow with file set + disabled state; mode toggle (`crowdsec-mode-toggle`) updates via `updateSetting`; ensure decisions table renders "No banned IPs" vs list.
|
||||
- [src/pages/Security.tsx](frontend/src/pages/Security.tsx): component test.
|
||||
- Banner when `cerberus.enabled` is false; toggles `toggle-crowdsec`/`toggle-acl`/`toggle-waf`/`toggle-rate-limit` call mutations and optimistic cache rollback on error.
|
||||
- LiveLogViewer renders only when Cerberus enabled; whitelist input saves via `useUpdateSecurityConfig` and break-glass button triggers mutation.
|
||||
### 1. `src/api/plugins.ts` (Current: 0%)
|
||||
**Complexity**: LOW
|
||||
**Value**: MEDIUM (Core API interactions)
|
||||
**Test Cases**:
|
||||
- `getPlugins`: Mocks client.get, returns data.
|
||||
- `getPlugin`: Mocks client.get with ID.
|
||||
- `enablePlugin`: Mocks client.post with ID.
|
||||
- `disablePlugin`: Mocks client.post with ID.
|
||||
- `reloadPlugins`: Mocks client.post, verifies return count.
|
||||
|
||||
- **Shell/UI overview**
|
||||
- [src/pages/Dashboard.tsx](frontend/src/pages/Dashboard.tsx): component test to cover health states (ok, error, undefined) and counts computed from hooks.
|
||||
- [src/components/Layout.tsx](frontend/src/components/Layout.tsx): component test.
|
||||
- Feature-flag filtering (hide Uptime/Cerberus when flags false), sidebar collapse persistence (localStorage), mobile toggle (`data-testid="mobile-menu-toggle"`), nested menu expand/collapse, logout button click, and version/git commit rendering.
|
||||
### 2. `src/components/PermissionsPolicyBuilder.tsx` (Current: ~32%)
|
||||
**Complexity**: MEDIUM
|
||||
**Value**: HIGH (Complex string manipulation logic)
|
||||
**Test Cases**:
|
||||
- Renders correctly with empty value.
|
||||
- Parses existing JSON value into state.
|
||||
- Adds a new feature with `self` allowing.
|
||||
- Adds a new feature with custom origin.
|
||||
- Updates existing feature when added again.
|
||||
- Removes a feature.
|
||||
- "Quick Add" buttons populate multiple features.
|
||||
- Generates correct Permissions-Policy header string preview.
|
||||
- Handles invalid JSON gracefully.
|
||||
|
||||
- **Missing/low names from QA list**
|
||||
- `Summary.tsx`, `FeatureFlagProvider.tsx`, `useFeatureFlags.ts`, `LiveLogViewerRow.tsx`: confirm current paths (may have been renamed). Add light RTL/unit tests mirroring above patterns if still present (e.g., summary widget rendering counts, provider supplying default flags).
|
||||
### 3. `src/components/DNSProviderForm.tsx` (Current: ~55%)
|
||||
**Complexity**: HIGH
|
||||
**Value**: HIGH (Critical configuration form)
|
||||
**Test Cases**:
|
||||
- Renders default state correctly.
|
||||
- Pre-fills form when editing an existing provider.
|
||||
- Changes inputs based on selected `Provider Type` (e.g., Cloudflare vs Route53).
|
||||
- Validates required fields.
|
||||
- Handles `Test Connection` success/failure states.
|
||||
- Submits create payload correctly.
|
||||
- Submits update payload correctly.
|
||||
- Toggles "Advanced Settings".
|
||||
- Handles Multi-Credential mode toggles.
|
||||
|
||||
## SMTPSettings Deflake Strategy
|
||||
### 4. `src/utils/validation.ts` (Current: ~0%)
|
||||
**Complexity**: LOW
|
||||
**Value**: HIGH (Security and data validation logic)
|
||||
**Test Cases**:
|
||||
- `isValidEmail`: valid emails, invalid emails, empty strings.
|
||||
- `isIPv4`: valid IPs, invalid IPs, out of range numbers.
|
||||
- `isPrivateOrDockerIP`:
|
||||
- 10.x.x.x (Private)
|
||||
- 172.16-31.x.x (Private/Docker)
|
||||
- 192.168.x.x (Private)
|
||||
- Public IPs (e.g. 8.8.8.8)
|
||||
- `isLikelyDockerContainerIP`:
|
||||
- 172.17-31.x.x (Docker range)
|
||||
- Non-docker IPs.
|
||||
|
||||
- Wait for data: use `await screen.findByText('Email (SMTP) Settings')` and `await waitFor(() => expect(hostInput).toHaveValue('...'))` after mocking `getSMTPConfig` to resolve once.
|
||||
- Avoid racing mutations: wrap `vi.useFakeTimers()` only if timers are used; otherwise keep real timers and `await act(async () => ...)` on mutations.
|
||||
- Reset query cache per test (`queryClient.clear()` or `QueryClientProvider` fresh instance) and isolate toast spies.
|
||||
- Prefer role/label queries (`getByLabelText('SMTP Host')`) over brittle text selectors; ensure `toast` mocks are flushed before assertions.
|
||||
### 5. `src/utils/proxyHostsHelpers.ts` (Current: ~0%)
|
||||
**Complexity**: MEDIUM
|
||||
**Value**: MEDIUM (UI Helper logic)
|
||||
**Test Cases**:
|
||||
- `formatSettingLabel`: Verify correct labels for keys.
|
||||
- `settingHelpText`: Verify help text mapping.
|
||||
- `settingKeyToField`: Verify identity mapping.
|
||||
- `applyBulkSettingsToHosts`:
|
||||
- Applies settings to multiple hosts.
|
||||
- Handles missing hosts gracefully.
|
||||
- Reports progress callback.
|
||||
- Updates error count on failure.
|
||||
|
||||
## Ordered Phases (minimal steps to >=85%)
|
||||
### 6. `src/components/ProxyHostForm.tsx` (Current: ~78% lines, ~61% func)
|
||||
**Complexity**: VERY HIGH (1378 lines)
|
||||
**Value**: MAXIMUM (Core Component)
|
||||
**Test Cases**:
|
||||
- **Missing Paths Analysis**: Focus on the ~40% of functions not called (likely validation, secondary tabs, dynamic rows).
|
||||
- **Secondary Tabs**: "Custom Locations", "Advanced" (HSTS, HTTP/2).
|
||||
- **SSL Flows**: Let's Encrypt vs Custom certificates generation flows.
|
||||
- **Dynamic Rows**: Adding/removing upstream servers, rewrites interactions.
|
||||
- **Error Simulation**: API failures during connection testing.
|
||||
|
||||
- Phase 1 (API unit bursts) — expected +0.30 to statements: notifications.ts, logs.ts, users.ts.
|
||||
- Phase 2 (UI quick wins) — expected +0.50: SMTPSettings, LiveLogViewer, UsersPage.
|
||||
- Phase 3 (Security shell) — expected +0.40: CrowdSecConfig, Security page.
|
||||
- Phase 4 (Shell polish) — expected +0.20: Dashboard, Layout, any remaining Summary/feature-flag provider files if present.
|
||||
### 7. `src/components/CredentialManager.tsx` (Current: ~50.7%)
|
||||
**Complexity**: MEDIUM (132 lines)
|
||||
**Value**: HIGH (Security sensitive)
|
||||
**Missing Lines**: ~65 lines
|
||||
**Strategy**:
|
||||
- Test CRUD operations for different credential types.
|
||||
- Verify error handling during creation and deletion.
|
||||
- Test empty states and loading states.
|
||||
|
||||
Total projected lift: ~+1.4% (buffered) with 8–10 focused tests. Stop after Phase 3 if coverage already surpasses 85%; Phase 4 only if buffer needed.
|
||||
### 8. `src/pages/CrowdSecConfig.tsx` (Current: ~82.5%)
|
||||
**Complexity**: HIGH (332 lines)
|
||||
**Value**: MEDIUM (Configuration page)
|
||||
**Missing Lines**: ~58 lines
|
||||
**Strategy**:
|
||||
- Focus on form interactions for all configuration sections.
|
||||
- Test "Enable/Disable" toggle flows.
|
||||
- Verify API error handling when saving configuration.
|
||||
|
||||
## Configuration Changes
|
||||
|
||||
### Dynamic Thresholds
|
||||
Modify `frontend/vitest.config.ts` to set coverage thresholds based on the environment.
|
||||
|
||||
```typescript
|
||||
const isCI = process.env.CI === 'true';
|
||||
|
||||
export default defineConfig({
|
||||
// ...
|
||||
test: {
|
||||
coverage: {
|
||||
// ...
|
||||
thresholds: {
|
||||
lines: isCI ? 83 : 88,
|
||||
functions: isCI ? 78 : 88,
|
||||
branches: isCI ? 77 : 85,
|
||||
statements: isCI ? 83 : 88,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Execution Plan
|
||||
|
||||
1. **Implement Tests (Phase 1)**:
|
||||
- Create `src/api/__tests__/plugins.test.ts`
|
||||
- Create `src/components/__tests__/PermissionsPolicyBuilder.test.tsx`
|
||||
- Create `src/components/__tests__/DNSProviderForm.test.tsx` (or expand existing)
|
||||
2. **Implement Tests (Phase 2)**:
|
||||
- Create `src/utils/__tests__/validation.test.ts`
|
||||
- Create `src/utils/__tests__/proxyHostsHelpers.test.ts`
|
||||
3. **Implement Tests (Phase 3 - The Heavy Lifter)**:
|
||||
- **Target**: `src/components/ProxyHostForm.tsx`
|
||||
- **Goal**: >90% coverage for this 1.4k line file.
|
||||
- **Strategy**: Expand `src/components/__tests__/ProxyHostForm.test.tsx` to cover edge cases, secondary tabs, and validation logic.
|
||||
4. **Implement Tests (Phase 4 - The Final Push)**:
|
||||
- **Target**: `src/components/CredentialManager.tsx` and `src/pages/CrowdSecConfig.tsx`
|
||||
- **Goal**: Reduce missing lines by >100 (combined).
|
||||
- **Strategy**: Create dedicated test files focusing on the unreached branches identified in coverage reports.
|
||||
5. **Update Configuration**:
|
||||
- Update `frontend/vitest.config.ts`
|
||||
6. **Verify**:
|
||||
- Run `npm run test:coverage` locally to confirm >88%.
|
||||
- Verify CI build simulation.
|
||||
|
||||
Reference in New Issue
Block a user