Issue 1:
System info

Playwright Version: v1.33.0

Operating System: macOS 13.2,

Browser: All

Other info:

An issue with custom Errors that have a getter for the message property.

For some reason, Playwright is trying to set the message property of the error object, which is not allowed in some Error classes.

So, this causes a TypeError to be thrown

Source code

I provided the exact source code that allows reproducing the issue locally.

import { test } from "@playwright/test";
import { z } from "zod";

class MyError extends Error {
#issues: string[] = [];
constructor(message: string) {
super();
this.name = "MyError";
this.#issues.push(message);
}

get message() {
return this.#issues.join("\n");
}
}

test("Error", async () => {
// Error: Error message
throw new Error("Error message");

// TypeError: Cannot set property message of Error which has only a getter
throw new MyError("Error message");

z.object({
name: z.string(),
})
// TypeError: Cannot set property message of [object Object] which has only a getter
.parse({
// throws ZodError with only message getter
name: undefined,
});
});

Link to the GitHub repository with the repro

repo with an example

Config file

// playwright.config.ts
export default defineConfig({
testDir: "./tests",
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: "html",
use: {
trace: "on-first-retry",
},
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},

{
name: "firefox",
use: { ...devices["Desktop Firefox"] },
},

{
name: "webkit",
use: { ...devices["Desktop Safari"] },
},
],
});

Steps

[Run the test]

[Get an error]

Expected

The playwright should not modify the original error message as some custom Errors do not provide a setter

Actual

TypeError: Cannot set property message of [object Object] which has only a getter

TypeError: Cannot set property message of Error which has only a getter

Issue 2:
System info

Playwright Version: [v1.28.1]

Operating System: [Android]

Browser: [Chromium]

Other info: Using realMobile on BrowserStack

Source code

I provided exact source code that allows reproducing the issue locally.

Config file

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export type BrowserStackTestOptions = {
os: string;
browser: string;
browserName: string;
browserVersion: string;
osVersion: string;
realMobile: boolean;
deviceName: string;
};

export default defineConfig<BrowserStackTestOptions>({
projects: [
{
name: 'browserstack.android-chrome-latest',
use: {
osVersion: '12.0',
deviceName: 'Samsung Galaxy S22 Ultra',
realMobile: true,
browserName: 'chromium',
},
},
});

Test file (self-contained)

const patchedCaps = { /* construct browserstack capabilites from BrowserStackTestOptions in the config.project */ };

it('should verify navigation url', async ({ }) => {
const browser = await _android.connect(
`wss://cdp.browserstack.com/playwright?caps=${encodeURIComponent(JSON.stringify(patchedCaps))}`
);
const context = await browser.launchBrowser();
const page = await context.newPage();
await page.route('https://x-cancel.examplethatdoesntexisthere.com/', async route => {
route
.fulfill({
status: 200,
body: '<html></html>',
})
.catch(() => {});
});

await page.goto('https://testurl.com/with-link');
await page.getByRole('button', { name: 'navigate to x-cancel url' }).click();
await page.waitForURL('https://x-cancel.examplethatdoesntexisthere.com');
expect(await page.url()).toBe('https://x-cancel.examplethatdoesntexisthere.com');
});

Steps

[Run the test]

[Test will fail]

Expected

Should pass on Android Chrome the same way it does as on the desktop browsers.

Actual

Test will fail with the following error:

page.route: Unknown scheme for Params: Page.setNetworkInterceptionPatterns

I'm guessing it would fail on local Android device as well, but I don't have device setup locally to test. I also was unable to test with the latest version of Playwright, because Browserstack currently only has version up to 1.28.1 on Android.