Skip to content

[Bug]: UI Mode buffers all test steps when root-level testDir conflicts with project-specific testDirs #38367

@AlonMiz

Description

@AlonMiz

Version

1.47.2 (also happens on latest)

Steps to reproduce

  1. Create a playwright.config.ts with BOTH a root-level testDir AND project-specific testDir:
import {defineConfig, devices} from '@playwright/test';

export default defineConfig({
  testDir: './integration',  // ❌ Root-level testDir pointing to non-existent directory
  
  projects: [
    {
      name: 'chromium',
      use: {...devices['Desktop Chrome']},
      testDir: './tests/e2e'  // ✅ Project-specific testDir (actual location)
    }
  ]
});
  1. Create a simple test in ./tests/e2e/example.spec.ts:
import {test, expect} from '@playwright/test';

test('example test', async ({page}) => {
  await page.goto('https://playwright.dev');
  await page.locator('h1').waitFor();
  await expect(page).toHaveTitle(/Playwright/);
});
  1. Run Playwright UI Mode:
npx playwright test --ui --project=chromium
  1. Observe the behavior in the UI Mode sidebar

Expected behavior

Test steps should appear in real-time in the UI Mode sidebar as they execute:

  • "page.goto" appears immediately when navigation starts
  • "locator.waitFor" appears when waiting begins
  • "expect" appears when assertion runs
  • Timeline shows progress in real-time

Actual behavior

All test steps are buffered and appear only after the test completes or fails:

  • UI Mode sidebar shows "Running" with a loading indicator
  • Timeline stays at 0s
  • No steps appear in the sidebar during test execution
  • After ~30 seconds (or when test completes), ALL steps dump at once
  • Timeline jumps from 0s to final duration instantly

Screenshot of buffering behavior:

  • Sidebar shows "Running" with blank steps list
  • Timeline at 0s despite test executing
  • All actions appear simultaneously after completion

Additional context

Root Cause Analysis

The issue occurs because:

  1. Playwright's test discovery mechanism tries to scan BOTH:

    • Root-level testDir: './integration' (which doesn't exist)
    • Project-level testDir: './tests/e2e' (which exists)
  2. This creates a race condition in the test discovery process

  3. The UI Mode reporter waits for the root-level discovery to complete before streaming steps

  4. Since ./integration doesn't exist, the discovery times out (~30 seconds)

  5. During this timeout, all test steps are buffered instead of streamed to the UI

Workaround

Remove or comment out the root-level testDir:

export default defineConfig({
  // testDir: './integration',  // ❌ Remove this line
  
  projects: [
    {
      name: 'chromium',
      use: {...devices['Desktop Chrome']},
      testDir: './tests/e2e'  // ✅ Only use project-specific testDir
    }
  ]
});

Suggested Fix

Playwright should either:

  1. Validate configuration: Warn when both root-level and project-specific testDir are set
  2. Handle gracefully: Prioritize project-specific testDir and ignore root-level when projects are defined
  3. Document clearly: Add a warning in the documentation about this limitation
  4. Fail fast: If root-level testDir doesn't exist, fail immediately instead of timing out

Impact

This issue affects:

  • Developer experience in UI Mode (appears broken/frozen)
  • Debugging efficiency (can't see steps in real-time)
  • Large monorepos with multiple projects (common pattern)

Environment

System:
  OS: macOS Sequoia
  CPU: (10) arm64 Apple M1 Pro
Binaries:
  Node: 20.19.0 - ~/.nvm/versions/node/v20.19.0/bin/node
  npm: 10.8.2 - ~/.nvm/versions/node/v20.19.0/bin/npm
npmPackages:
  @playwright/test: 1.47.2 => 1.47.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions