Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/playwright/src/common/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,12 @@ function resolveWorkers(workers: string | number): number {
const parsedWorkers = parseInt(workers, 10);
if (isNaN(parsedWorkers))
throw new Error(`Workers ${workers} must be a number or percentage.`);
if (parsedWorkers < 1)
throw new Error(`Workers must be a positive number, received ${parsedWorkers}.`);
Comment on lines 246 to +250
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The '%' branch can still return NaN for inputs like "abc%" (parseInt => NaN), which would make the dispatcher allocate 0 workers and silently skip tests; please validate the parsed percentage and throw a descriptive error when it’s not a finite number.

Copilot uses AI. Check for mistakes.
return parsedWorkers;
}
if (workers < 1)
throw new Error(`Workers must be a positive number, received ${workers}.`);
Comment on lines +250 to +254
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For numeric inputs, workers < 1 doesn’t reject NaN/Infinity or non-integers (e.g. 1.5), which can cause 0 workers or an infinite allocation loop; consider enforcing a finite positive integer (and update the message to reflect “integer/at least 1”).

Suggested change
throw new Error(`Workers must be a positive number, received ${parsedWorkers}.`);
return parsedWorkers;
}
if (workers < 1)
throw new Error(`Workers must be a positive number, received ${workers}.`);
throw new Error(`Workers must be a positive integer, received ${parsedWorkers}.`);
return parsedWorkers;
}
if (!Number.isFinite(workers) || !Number.isInteger(workers) || workers < 1)
throw new Error(`Workers must be a finite positive integer, received ${workers}.`);

Copilot uses AI. Check for mistakes.
Comment on lines +249 to +254
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are existing config validation tests in tests/playwright-test/config.spec.ts for workers; this change should add coverage for --workers=0/negative values (and ideally invalid percent strings) to prevent regressions of the “silent green run” behavior.

Copilot uses AI. Check for mistakes.
return workers;
}

Expand Down
52 changes: 52 additions & 0 deletions tests/playwright-test/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,58 @@ test('should throw when workers option is invalid', async ({ runInlineTest }) =>
expect(result.output).toContain('config.workers must be a number or percentage');
});

test('should throw when workers is 0 in config', async ({ runInlineTest }) => {
const result = await runInlineTest({
'playwright.config.ts': `
module.exports = { workers: 0 };
`,
'a.test.ts': `
import { test, expect } from '@playwright/test';
test('pass', async ({}) => {});
`,
});
expect(result.exitCode).toBe(1);
expect(result.output).toContain('must be a positive');
});

test('should throw when workers is negative in config', async ({ runInlineTest }) => {
const result = await runInlineTest({
'playwright.config.ts': `
module.exports = { workers: -1 };
`,
'a.test.ts': `
import { test, expect } from '@playwright/test';
test('pass', async ({}) => {});
`,
});
expect(result.exitCode).toBe(1);
expect(result.output).toContain('must be a positive');
});

test('should throw when workers is 0 via CLI', async ({ runInlineTest }) => {
const result = await runInlineTest({
'playwright.config.ts': `module.exports = {};`,
'a.test.ts': `
import { test, expect } from '@playwright/test';
test('pass', async ({}) => {});
`,
}, { workers: 0 });
expect(result.exitCode).not.toBe(0);
expect(result.output).toContain('must be a positive');
});

test('should throw when workers is negative via CLI', async ({ runInlineTest }) => {
const result = await runInlineTest({
'playwright.config.ts': `module.exports = {};`,
'a.test.ts': `
import { test, expect } from '@playwright/test';
test('pass', async ({}) => {});
`,
}, { workers: -1 });
expect(result.exitCode).not.toBe(0);
expect(result.output).toContain('must be a positive');
});

test('should work with undefined values and base', async ({ runInlineTest }) => {
const result = await runInlineTest({
'playwright.config.ts': `
Expand Down
Loading