Files
Charon/docs/plans/archive/ci_test_cleanup_spec.md
akanealw eec8c28fb3
Some checks are pending
Go Benchmark / Performance Regression Check (push) Waiting to run
Cerberus Integration / Cerberus Security Stack Integration (push) Waiting to run
Upload Coverage to Codecov / Backend Codecov Upload (push) Waiting to run
Upload Coverage to Codecov / Frontend Codecov Upload (push) Waiting to run
CodeQL - Analyze / CodeQL analysis (go) (push) Waiting to run
CodeQL - Analyze / CodeQL analysis (javascript-typescript) (push) Waiting to run
CrowdSec Integration / CrowdSec Bouncer Integration (push) Waiting to run
Docker Build, Publish & Test / build-and-push (push) Waiting to run
Docker Build, Publish & Test / Security Scan PR Image (push) Blocked by required conditions
Quality Checks / Auth Route Protection Contract (push) Waiting to run
Quality Checks / Codecov Trigger/Comment Parity Guard (push) Waiting to run
Quality Checks / Backend (Go) (push) Waiting to run
Quality Checks / Frontend (React) (push) Waiting to run
Rate Limit integration / Rate Limiting Integration (push) Waiting to run
Security Scan (PR) / Trivy Binary Scan (push) Waiting to run
Supply Chain Verification (PR) / Verify Supply Chain (push) Waiting to run
WAF integration / Coraza WAF Integration (push) Waiting to run
changed perms
2026-04-22 18:19:14 +00:00

92 lines
4.0 KiB
Markdown
Executable File

# CI/CD Test Remix & Stabilization Plan
**Status**: Draft
**Owner**: DevOps / QA
**Context**: Fixing flaky E2E tests in `proxy-hosts.spec.ts` identified in CI Remediation Report.
## 1. Problem Analysis
### Symptoms
1. **"Add Proxy Host" Modal Failure**: Test clicks "Add Proxy Host" but dialog doesn't appear.
2. **Empty State Detection Failure**: Test asserts "Empty State OR Table" visible, but fails (neither visible).
3. **Spinner Timeouts**: Loading state tests are flaky.
### Root Cause
**Mismatched Loading Indicators**:
- The test helper `waitForLoadingComplete` waits for `.animate-spin` (loading spinner).
- The `ProxyHosts` page uses `SkeletonTable` (pulse animation) for its initial loading state.
- **Result**: `waitForLoadingComplete` returns immediately because no spinner is found. The test proceeds while the Skeleton is still visible.
- **Impact**:
- **Empty State Test**: Fails because checking for EmptyState/Table happens while Skeleton is still rendered.
- **Add Host Test**: The click might verify, but the page is currently rendering/hydrating/transitioning, causing flaky behavior or race conditions.
## 2. Remediation Specification
### Objective
Make `proxy-hosts.spec.ts` robust by accurately detecting the page's "ready" state and using precise selectors.
### Tasks
#### Phase 1: Selector Hardening
- **Target specific "Add" button**: Use `data-testid` or precise hierarchy to distinguish the Header button from the Empty State button (though logic allows either, precision helps debugging).
- **Consolidate Button Interaction**: Ensure we are waiting for the button to be interactive.
#### Phase 2: Loading State Logic Update
- **Detect Skeleton**: Add logic to wait for `SkeletonTable` (or `.animate-pulse`, `.skeleton`) to disappear.
- **Update Test Flow**:
- `beforeEach`: Wait for Table OR Empty State to be visible (implies Skeleton is gone).
- `should show loading skeleton`: Update to assert presence of `role="status"` or `.animate-pulse` selector instead of `.animate-spin`.
#### Phase 3: Empty State Verification
- **Explicit Assertion**: Instead of `catch(() => false)`, use `expect(locator).toBeVisible()` inside a `test.step` that handles the conditional logic gracefully (e.g., using `Promise.race` or checking count before assertion).
- **Wait for transition**: Ensure test waits for the transition from `loading=true` to `loading=false`.
## 3. Implementation Steps
### Step 1: Update `tests/utils/wait-helpers.ts` (Optional)
*Consider adding `waitForSkeletonComplete` if this pattern is common.*
*For now, local handling in `proxy-hosts.spec.ts` is sufficient.*
### Step 2: Rewrite `tests/core/proxy-hosts.spec.ts`
Modify `beforeEach` and specific tests:
```typescript
// Proposed Change for beforeEach
test.beforeEach(async ({ page, adminUser }) => {
await loginUser(page, adminUser);
await page.goto('/proxy-hosts');
// Wait for REAL content availability, bypassing Skeleton
const table = page.getByRole('table');
const emptyState = page.getByRole('heading', { name: 'No proxy hosts' });
const addHostBtn = page.getByRole('button', { name: 'Add Proxy Host' }).first();
// Wait for either table OR empty state to be visible
await expect(async () => {
const tableVisible = await table.isVisible();
const emptyVisible = await emptyState.isVisible();
expect(tableVisible || emptyVisible).toBeTruthy();
}).toPass({ timeout: 10000 });
await expect(addHostBtn).toBeVisible();
});
```
### Step 3: Fix "Loading Skeleton" Test
Target the actual Skeleton element:
```typescript
test('should show loading skeleton while fetching data', async ({ page }) => {
await page.reload();
// Verify Skeleton exists
const skeleton = page.locator('.animate-pulse'); // or specific skeleton selector
await expect(skeleton.first()).toBeVisible();
// Then verify it disappears
await expect(skeleton.first()).not.toBeVisible();
});
```
## 4. Verification
1. Run `npx playwright test tests/core/proxy-hosts.spec.ts --project=chromium`
2. Ensure 0% flake rate.