diff --git a/README.md b/README.md
index 324f49bd4234e..bd0475b65fe97 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# 🎠Playwright
-[](https://www.npmjs.com/package/playwright) [](https://www.chromium.org/Home) [](https://www.mozilla.org/en-US/firefox/new/) [](https://webkit.org/) [](https://aka.ms/playwright/discord)
+[](https://www.npmjs.com/package/playwright) [](https://www.chromium.org/Home) [](https://www.mozilla.org/en-US/firefox/new/) [](https://webkit.org/) [](https://aka.ms/playwright/discord)
## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright)
@@ -298,7 +298,7 @@ The [Playwright VS Code extension](https://marketplace.visualstudio.com/items?it
| :--- | :---: | :---: | :---: |
| Chromium1 151.0.7922.10 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit 26.5 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
-| Firefox 151.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
+| Firefox 152.0.4 | :white_check_mark: | :white_check_mark: | :white_check_mark: |
Headless and headed execution on all platforms. 1 Uses [Chrome for Testing](https://developer.chrome.com/blog/chrome-for-testing) by default.
diff --git a/packages/isomorphic/deviceDescriptorsSource.json b/packages/isomorphic/deviceDescriptorsSource.json
index 098f5cb0f29c0..cc021dc9b27a0 100644
--- a/packages/isomorphic/deviceDescriptorsSource.json
+++ b/packages/isomorphic/deviceDescriptorsSource.json
@@ -2662,7 +2662,7 @@
"defaultBrowserType": "chromium"
},
"Desktop Firefox HiDPI": {
- "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:151.0) Gecko/20100101 Firefox/151.0",
+ "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:152.0.4) Gecko/20100101 Firefox/152.0.4",
"screen": {
"width": 1792,
"height": 1120
@@ -2722,7 +2722,7 @@
"defaultBrowserType": "chromium"
},
"Desktop Firefox": {
- "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:151.0) Gecko/20100101 Firefox/151.0",
+ "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:152.0.4) Gecko/20100101 Firefox/152.0.4",
"screen": {
"width": 1920,
"height": 1080
diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json
index 261420d8fe256..a63a6f5baf709 100644
--- a/packages/playwright-core/browsers.json
+++ b/packages/playwright-core/browsers.json
@@ -31,9 +31,9 @@
},
{
"name": "firefox",
- "revision": "1533",
+ "revision": "1534",
"installByDefault": true,
- "browserVersion": "151.0",
+ "browserVersion": "152.0.4",
"title": "Firefox"
},
{
diff --git a/packages/playwright/src/common/config.ts b/packages/playwright/src/common/config.ts
index 4dd22b11d8e81..fc4e378625ea5 100644
--- a/packages/playwright/src/common/config.ts
+++ b/packages/playwright/src/common/config.ts
@@ -221,8 +221,13 @@ function resolveReporters(reporters: Config['reporter'], rootDir: string): Repor
function resolveWorkers(workers: string | number): number {
if (typeof workers === 'string') {
if (workers.endsWith('%')) {
+ const percent = parseInt(workers, 10);
+ if (isNaN(percent))
+ throw new Error(`Workers ${workers} must be a number or percentage.`);
+ if (percent < 1)
+ throw new Error(`Workers must be a positive number, received ${percent}.`);
const cpus = os.cpus().length;
- return Math.max(1, Math.floor(cpus * (parseInt(workers, 10) / 100)));
+ return Math.max(1, Math.floor(cpus * (percent / 100)));
}
const parsedWorkers = parseInt(workers, 10);
if (isNaN(parsedWorkers))
diff --git a/tests/playwright-test/config.spec.ts b/tests/playwright-test/config.spec.ts
index ab04bf8970c03..9c4acda6e445a 100644
--- a/tests/playwright-test/config.spec.ts
+++ b/tests/playwright-test/config.spec.ts
@@ -573,6 +573,18 @@ test('should throw when workers is negative via CLI (regression for #39938)', as
expect(result.output).toContain('Workers must be a positive number');
});
+test('should throw when workers is an invalid percentage via CLI (regression for #41679)', async ({ runInlineTest }) => {
+ const result = await runInlineTest({
+ 'playwright.config.ts': `module.exports = {};`,
+ 'a.test.ts': `
+ import { test, expect } from '@playwright/test';
+ test('fails', () => { expect(1).toBe(2); });
+ `,
+ }, { workers: 'abc%' });
+ expect(result.exitCode).toBe(1);
+ expect(result.output).toContain('Workers abc% must be a number or percentage.');
+});
+
test('should work with undefined values and base', async ({ runInlineTest }) => {
const result = await runInlineTest({
'playwright.config.ts': `