- Refactored TestDataManager to use authenticated context with Playwright's newContext method. - Updated auth-fixtures to ensure proper authentication state is inherited for API requests. - Created constants.ts to avoid circular imports and manage shared constants. - Fixed critical bug in auth setup that caused E2E tests to fail due to improper imports. - Re-enabled user management tests with updated selectors and added comments regarding current issues. - Documented environment configuration issues causing cookie domain mismatches in skipped tests. - Generated QA report detailing test results and recommendations for further action.
16 KiB
Phase 2: TestDataManager Authentication Fix Implementation Plan
Goal: Fix TestDataManager to use authenticated API context, enabling 8 skipped tests in user management.
Target: Enable all user management E2E tests that are currently skipped due to TestDataManager using unauthenticated API calls.
Estimated Effort: 2-3 hours
Executive Summary
The testData fixture in Playwright tests creates a TestDataManager instance using an unauthenticated API context. This causes all API calls made by TestDataManager (like createUser(), deleteUser()) to fail with "Admin access required" errors. This plan details how to fix the fixture to use authenticated API requests by leveraging the stored authentication state from playwright/.auth/user.json.
Table of Contents
- Root Cause Analysis
- Proposed Solution
- Implementation Details
- Tests to Re-Enable
- Verification Steps
- Dependencies & Prerequisites
- Risks & Mitigations
- Implementation Checklist
Supervisor Review: APPROVED ✅
Reviewed by: Supervisor Agent (Senior Advisor) Date: 2026-01-22 Verdict: Plan is ready for implementation
Review Summary
| Criterion | Status | Notes |
|---|---|---|
| Completeness | ✅ Pass | All changes documented |
| Technical Accuracy | ✅ Pass | Correct Playwright pattern |
| Risk Assessment | ✅ Pass | Adequate with fallbacks |
| Dependencies | ✅ Pass | All verified |
| Verification | ✅ Pass | Comprehensive |
| Edge Cases | 🔸 Minor | Added defensive file existence check |
Incorporated Recommendations
- Defensive
existsSync()check: Added to implementation to verify storage state file exists before use - Import verification: Clarified import strategy for
playwrightRequest - Dependent fixture verification: Added to checklist to verify
adminUser/regularUser/guestUserfixtures
1. Root Cause Analysis
Current Problem
The testData fixture in auth-fixtures.ts creates a TestDataManager instance using the Playwright request fixture:
// tests/fixtures/auth-fixtures.ts (lines 69-75)
testData: async ({ request }, use, testInfo) => {
const manager = new TestDataManager(request, testInfo.title);
await use(manager);
await manager.cleanup();
},
The issue: Playwright's request fixture creates an unauthenticated API context. It does NOT use the storageState from playwright.config.js that the browser context uses.
When TestDataManager.createUser() is called:
- It posts to
/api/v1/usersusing the unauthenticatedrequestcontext - The backend requires admin authentication for user creation
- The request fails with 401/403 "Admin access required"
Evidence
From user-management.spec.ts:
// SKIP: testData.createUser() uses unauthenticated API calls
// The TestDataManager's request context doesn't inherit auth from the browser session
// This causes user creation and cleanup to fail with "Admin access required"
// TODO: Fix by making TestDataManager use authenticated API requests
2. Proposed Solution
Approach: Create Authenticated APIRequestContext from Storage State
Modify the testData fixture to create an authenticated APIRequestContext using the stored authentication state from playwright/.auth/user.json.
Key Changes
| File | Change Type | Description |
|---|---|---|
| tests/fixtures/auth-fixtures.ts | Modify | Update testData fixture to use authenticated API context |
| tests/auth.setup.ts | Reference only | Storage state path already exported |
3. Implementation Details
3.1 File: tests/fixtures/auth-fixtures.ts
Current Implementation (Lines 69-75)
/**
* TestDataManager fixture with automatic cleanup
* Creates a unique namespace per test and cleans up all resources after
*/
testData: async ({ request }, use, testInfo) => {
const manager = new TestDataManager(request, testInfo.title);
await use(manager);
await manager.cleanup();
},
Proposed Implementation
// Import playwrightRequest directly from @playwright/test (not from coverage wrapper)
// @bgotink/playwright-coverage doesn't re-export request.newContext()
import { request as playwrightRequest } from '@playwright/test';
import { existsSync } from 'fs';
import { STORAGE_STATE } from '../auth.setup';
// ... existing code ...
/**
* TestDataManager fixture with automatic cleanup
*
* FIXED: Now creates an authenticated API context using stored auth state.
* This ensures API calls (like createUser, deleteUser) inherit the admin
* session established by auth.setup.ts.
*
* Previous Issue: The base `request` fixture was unauthenticated, causing
* "Admin access required" errors on protected endpoints.
*/
testData: async ({ baseURL }, use, testInfo) => {
// Defensive check: Verify auth state file exists (created by auth.setup.ts)
if (!existsSync(STORAGE_STATE)) {
throw new Error(
`Auth state file not found at ${STORAGE_STATE}. ` +
'Ensure auth.setup has run first. Check that dependencies: ["setup"] is configured.'
);
}
// Create an authenticated API request context using stored auth state
// This inherits the admin session from auth.setup.ts
const authenticatedContext = await playwrightRequest.newContext({
baseURL,
storageState: STORAGE_STATE,
extraHTTPHeaders: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
});
const manager = new TestDataManager(authenticatedContext, testInfo.title);
try {
await use(manager);
} finally {
// Ensure cleanup runs even if test fails
await manager.cleanup();
// Dispose the API context to release resources
await authenticatedContext.dispose();
}
},
3.2 Full Updated Import Section
Add these imports at the top of auth-fixtures.ts:
import { test as base, expect } from '@bgotink/playwright-coverage';
import { request as playwrightRequest } from '@playwright/test';
import { existsSync } from 'fs';
import { TestDataManager } from '../utils/TestDataManager';
import { STORAGE_STATE } from '../auth.setup';
Note: playwrightRequest is imported from @playwright/test directly because @bgotink/playwright-coverage does not re-export the request module needed for request.newContext().
3.3 Verify STORAGE_STATE Export in auth.setup.ts
The current auth.setup.ts already exports STORAGE_STATE:
// tests/auth.setup.ts (lines 20-22)
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
export const STORAGE_STATE = join(__dirname, '../playwright/.auth/user.json');
No changes needed to this file.
4. Tests to Re-Enable
After implementing this fix, the following 8 tests in tests/settings/user-management.spec.ts should be re-enabled by removing test.skip():
| # | Test Name | File:Line | Current Skip Reason |
|---|---|---|---|
| 1 | should open permissions modal | user-management.spec.ts:496 | Permissions button + testData auth |
| 2 | should update permission mode | user-management.spec.ts:534 | testData.createUser() uses unauthenticated API calls |
| 3 | should add permitted hosts | user-management.spec.ts:609 | Depends on settings button + testData auth |
| 4 | should remove permitted hosts | user-management.spec.ts:665 | Same as above |
| 5 | should save permission changes | user-management.spec.ts:722 | Same as above |
| 6 | should enable/disable user | user-management.spec.ts:773 | TestDataManager auth + test data pollution |
| 7 | should delete user with confirmation | user-management.spec.ts:839 | Delete button + testData auth |
| 8 | should change user role | user-management.spec.ts:899 | Role badge selector + testData auth |
Note on Mixed Skip Reasons
Some tests have dual skip reasons (e.g., "UI not implemented" + "testData auth issue"). After the auth fix, these tests should be evaluated:
- If UI is now implemented: Remove skip entirely
- If UI is still missing: Keep skip with updated reason (remove auth-related reason)
5. Verification Steps
5.1 Pre-Implementation Verification
-
Confirm auth state file exists:
ls -la playwright/.auth/user.json -
Verify auth.setup.ts runs before tests:
npx playwright test --project=setup --reporter=list
5.2 Implementation Verification
-
Run a single testData-dependent test:
npx playwright test tests/settings/user-management.spec.ts \ --grep "should update permission mode" \ --project=chromium \ --reporter=list -
Verify API calls are authenticated by adding debug logging:
// Temporary debug in TestDataManager.createUser() console.log('Creating user with context:', await this.request.storageState()); -
Run all user-management tests:
npx playwright test tests/settings/user-management.spec.ts \ --project=chromium \ --reporter=list
5.3 Post-Implementation Verification
-
Verify skip count reduction:
grep -c "test.skip" tests/settings/user-management.spec.ts # Before: ~22 skips # After: ~14 skips (8 removed for auth fix) -
Run full E2E suite to check for regressions:
npx playwright test --project=chromium -
Verify cleanup works (no orphaned test users):
- Check users list in UI after running tests
- All
test-*prefixed users should be cleaned up
6. Dependencies & Prerequisites
Dependencies
| Dependency | Status | Notes |
|---|---|---|
auth.setup.ts runs first |
✅ Configured | Via dependencies: ['setup'] in playwright.config.js |
STORAGE_STATE exported |
✅ Already exported | From auth.setup.ts |
| Storage state file created | ✅ Auto-created | By auth.setup.ts on first run |
Prerequisites
- E2E environment running: Docker containers must be up
- Auth setup successful:
playwright/.auth/user.jsonmust exist and be valid - Admin user exists: The setup user must have admin role
7. Risks & Mitigations
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Storage state file missing/stale | Low | Test failures | Defensive existsSync() check added; re-run setup if needed |
| Auth cookie expired mid-test | Low | API 401 errors | Tests are short; setup runs before each run |
| Circular dependency with auth fixtures | Low | Import errors | testData only imports STORAGE_STATE, not auth fixtures |
| Context disposal race condition | Low | Resource leak | Use try/finally pattern (already in proposal) |
| Parallel test isolation | Medium | Test pollution | All tests share admin session; document that testData is not parallelism-safe if multiple workers create conflicting resources |
Fallback Plan
If the storage state approach doesn't work, alternative options:
- API Token Approach: Generate a long-lived API token during setup, pass to TestDataManager
- Direct Login in Fixture: Have testData fixture call login API directly before each test
- Shared Admin Session: Use a dedicated admin user just for TestDataManager operations
8. Implementation Checklist
Core Implementation
- Update
tests/fixtures/auth-fixtures.tswith authenticated context - Add
existsSyncdefensive check for storage state file - Import
playwrightRequestfrom@playwright/test(not coverage wrapper) - Verify
STORAGE_STATEimport works
Verification (Supervisor Recommendations)
- Run single test to verify fix
- Verify
adminUser/regularUser/guestUserdependent fixtures still work - Confirm API requests include authentication cookies
Test Re-enablement
- Remove
test.skip()from 8 identified tests - Update skip comments in tests that remain skipped (remove auth-related reasons)
Regression & Documentation
- Run full user-management test suite
- Verify no regressions in other test files
- Update
docs/plans/skipped-tests-remediation.mdwith Phase 2 completion status - Document any remaining issues
9. Phase 2 Completion Status
Implementation Completed ✅
| Item | Status | Notes |
|---|---|---|
Update auth-fixtures.ts |
✅ Complete | Authenticated context implemented |
Add existsSync check |
✅ Complete | Defensive file check added |
| Import verification | ✅ Complete | playwrightRequest from @playwright/test |
| Test re-enablement | 🔸 Partial | 2 tests re-enabled then re-skipped (see blocker) |
Blocker Discovered: Cookie Domain Mismatch
Root Cause: Environment configuration inconsistency prevents authenticated context from working:
playwright.config.jsdefaultsbaseURLtohttp://localhost:8080- Auth setup creates session cookies for
localhostdomain - Tests run against Tailscale IP
http://100.98.12.109:8080 - Cookies aren't sent cross-domain → API calls remain unauthenticated
Evidence:
- Tests pass when run against
localhost:8080 - Tests fail when run against Tailscale IP due to missing auth cookies
Fix Required (separate task):
# Option 1: Set environment variable consistently
export PLAYWRIGHT_BASE_URL="http://localhost:8080"
# Option 2: Update global-setup.ts default to match playwright.config.js
# tests/global-setup.ts line 8:
-const baseUrl = process.env.PLAYWRIGHT_BASE_URL || 'http://100.98.12.109:8080';
+const baseUrl = process.env.PLAYWRIGHT_BASE_URL || 'http://localhost:8080';
Tests Re-Skipped with Updated Comments
The 2 tests were re-skipped with environment documentation:
tests/settings/user-management.spec.ts- "should update permission mode"tests/settings/user-management.spec.ts- "should enable/disable user"
10. Future Improvements
After Phase 2 completion, consider:
-
Environment configuration fix: Align
global-setup.tsandplaywright.config.jsdefault URLs to prevent cookie domain mismatch. -
Per-test authentication contexts: Currently all tests share the same admin session. For true isolation, each test could create its own authenticated context.
-
Role-based TestDataManager: Allow TestDataManager to operate as different roles (admin, user, guest) to test permission boundaries.
-
Parallel-safe user creation: The current fix uses a single shared auth session. For highly parallel execution, consider per-worker authentication.
Change Log
| Date | Author | Change |
|---|---|---|
| 2026-01-22 | Planning Agent | Initial Phase 2 implementation plan |
| 2026-01-22 | Supervisor Agent | Approved with recommendations: defensive checks, import verification, fixture testing |
| 2026-01-22 | Frontend_Dev | Implemented authenticated context in auth-fixtures.ts |
| 2026-01-22 | QA_Security | Discovered cookie domain mismatch blocker |
| 2026-01-22 | Management | Re-skipped tests, documented blocker for future resolution |