Issue 1:
System info

Playwright Version: [v1.35.1

Operating System: Windows 10

Browser: Chrominum

Other info:

Config file

import { defineConfig, devices } from '@playwright/test';
import GlobalConstant from './commons/GlobalConstant';

/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',
/* Run tests in files in parallel */
timeout: GlobalConstant.testTimeout * 1000,
expect: {
/**
* Maximum time expect() should wait for the condition to be met.
* For example in `await expect(locator).toHaveText();`
*/
timeout: GlobalConstant.shortTimeout * 1000,
toHaveScreenshot: {
maxDiffPixelRatio: GlobalConstant.maxPixelDiffRatio,
threshold: 0.3
}
},
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: GlobalConstant.workers,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
actionTimeout: GlobalConstant.mediumTimeout * 1000,
navigationTimeout: GlobalConstant.mediumTimeout * 1000,
/* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://127.0.0.1:3000',
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'off',
video: 'off',
screenshot: 'off',
headless: true,
userAgent: GlobalConstant.userAgent,
contextOptions: {
ignoreHTTPSErrors: true,
},
extraHTTPHeaders: {
'User-Agent': GlobalConstant.userAgent
}
},

/* Configure projects for major browsers */
projects: [
{
name: 'Desktop Edge',
snapshotPathTemplate: './screenshots/{testFilePath}/{arg}-Desktop{ext}',
use: {
...devices['Desktop Edge'],
channel: 'chrome',
browserName: 'chromium',
},
},

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

// {
// name: 'webkit',
// use: { ...devices['Desktop Safari'] },
// },

/* Test against mobile viewports. */
{
name: 'Mobile Edge',
snapshotPathTemplate: './screenshots/{testFilePath}/{arg}-Mobile{ext}',
use: {
...devices['Pixel 5'],
channel: 'chrome',
browserName: 'chromium',
},
},
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },

/* Test against tablet viewports. */
{
name: 'Tablet Edge',
snapshotPathTemplate: './screenshots/{testFilePath}/{arg}-Tablet{ext}',
use: {
...devices['Galaxy Tab S4 landscape'],
channel: 'chrome',
browserName: 'chromium'
},
},
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },

/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ..devices['Desktop Chrome'], channel: 'chrome' },
// },
],

/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://127.0.0.1:3000',
// reuseExistingServer: !process.env.CI,
// },
});

Steps

Run the test with command line for all of projects: desktop, mobile, tablet

Check result

Expected

With the first running, it should show error below:

"Error: A snapshot doesn't exist at xxxxxx" for all three projects (correct behaviour)

Actual

It only shows "Error: A snapshot doesn't exist at xxxxxx" for desktop and mobile project.

With tablet project, it do not capture screenshot for tablet and in test-results folder, it generate three files:

"xxx-actual.png
xxx-diff.png
xxx-previous.png"

I do not know where did the "xxx-previous.png" image comming from? As I run visual comparison many times, from the second running, it should generate three files instead.

"xxx-actual.png
xxx-diff.png
xxx-expected.png"

Issue 2:
System info

Playwright Version: v1.33

Operating System: Windows, Ubuntu22

Browser: All

Other info:

Source code

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

Sorry, but I deviated a bit from the issue template.

So, I am interested in page.unroute method.

I had a look at the playwright tests

playwright/tests/page/page-route.spec.ts

Line 42
in
52feff3

it('should unroute', async ({ page, server }) => {

what I see it is only tested with strings as url.

What I want to achieve is to unroute registered routes after each test.

We are using regex for that.

In our POM

we have this

registerRoutes(page: Page): Promise<void> {
return page.route(/(test\.local\/)|(domain2)/, this.testRouteHandler.bind(this));
}

async destroy(): Promise<void> {
await this.page.unroute(/(test\.local\/)|(domain2)/);
}

Looking at the implementation in pw

playwright/packages/playwright-core/src/client/page.ts

Line 460
in
52feff3

async unroute(url: URLMatch, handler?: RouteHandlerCallback): Promise<void> {

it compares urls by strict equality, and then filters out page._routes.

So I guess for pure regexes it wont work.

What I did is that I saved the url regex into an instance field, so I can pass in a reference

Like this:

readonly routeUrl = /(test\.local\/)|(domain2)/;
registerRoutes(page: Page): Promise<void> {
return page.route(this.routeUrl, this.testRouteHandler.bind(this));
}

async destroy(): Promise<void> {
await this.page.unroute(this.routeUrl);
}

After awaiting the destroy method, page object still has a length of one in _routes, and points to the registered handlers.

Our goal is to get rid for all registered routes on the page in destroy method.

How to achieve it in regex?

can unroute also return a new length or something, or a boolean that confirms that routes are indeed unregistered?

Another thing we have is that sometimes there is a request in route handler that takes some time, and eventually throws

It happens that at that time another test is running, and route handler from previous test throws in another test, and then urelated test fails.

What I thought is to collect pending promises from route handles into a local array on POM instance, since we use POM as a fixture, and after use(POMfixture) to await that all promises from that array are resolved before fixture can be teared down.

Not sure if you guys have a better advice on how to approach it?