Files
Charon/docs/plans/current_spec.md
GitHub Actions 6593aca0ed chore: Implement authentication fixes for TestDataManager and update user management tests
- 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.
2026-01-24 22:22:40 +00:00

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

  1. Root Cause Analysis
  2. Proposed Solution
  3. Implementation Details
  4. Tests to Re-Enable
  5. Verification Steps
  6. Dependencies & Prerequisites
  7. Risks & Mitigations
  8. 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

  1. Defensive existsSync() check: Added to implementation to verify storage state file exists before use
  2. Import verification: Clarified import strategy for playwrightRequest
  3. Dependent fixture verification: Added to checklist to verify adminUser/regularUser/guestUser fixtures

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:

  1. It posts to /api/v1/users using the unauthenticated request context
  2. The backend requires admin authentication for user creation
  3. 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

  1. Confirm auth state file exists:

    ls -la playwright/.auth/user.json
    
  2. Verify auth.setup.ts runs before tests:

    npx playwright test --project=setup --reporter=list
    

5.2 Implementation Verification

  1. Run a single testData-dependent test:

    npx playwright test tests/settings/user-management.spec.ts \
      --grep "should update permission mode" \
      --project=chromium \
      --reporter=list
    
  2. Verify API calls are authenticated by adding debug logging:

    // Temporary debug in TestDataManager.createUser()
    console.log('Creating user with context:', await this.request.storageState());
    
  3. Run all user-management tests:

    npx playwright test tests/settings/user-management.spec.ts \
      --project=chromium \
      --reporter=list
    

5.3 Post-Implementation Verification

  1. 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)
    
  2. Run full E2E suite to check for regressions:

    npx playwright test --project=chromium
    
  3. 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

  1. E2E environment running: Docker containers must be up
  2. Auth setup successful: playwright/.auth/user.json must exist and be valid
  3. 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:

  1. API Token Approach: Generate a long-lived API token during setup, pass to TestDataManager
  2. Direct Login in Fixture: Have testData fixture call login API directly before each test
  3. Shared Admin Session: Use a dedicated admin user just for TestDataManager operations

8. Implementation Checklist

Core Implementation

  • Update tests/fixtures/auth-fixtures.ts with authenticated context
  • Add existsSync defensive check for storage state file
  • Import playwrightRequest from @playwright/test (not coverage wrapper)
  • Verify STORAGE_STATE import works

Verification (Supervisor Recommendations)

  • Run single test to verify fix
  • Verify adminUser/regularUser/guestUser dependent 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.md with 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)

Root Cause: Environment configuration inconsistency prevents authenticated context from working:

  1. playwright.config.js defaults baseURL to http://localhost:8080
  2. Auth setup creates session cookies for localhost domain
  3. Tests run against Tailscale IP http://100.98.12.109:8080
  4. 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:

  1. Environment configuration fix: Align global-setup.ts and playwright.config.js default URLs to prevent cookie domain mismatch.

  2. Per-test authentication contexts: Currently all tests share the same admin session. For true isolation, each test could create its own authenticated context.

  3. Role-based TestDataManager: Allow TestDataManager to operate as different roles (admin, user, guest) to test permission boundaries.

  4. 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