PixelCompute Blog

What's New in Playwright v1.46, v1.47 & v1.48

Author Avatar
2025-01-01 18:30:00 UTC

Release v1.46.0

Let's explore the major changes that were made in this release.

1. Client Certificates

Playwright now allows you to specify a clientCertificate property in the use object of your project config.

Let's look at an example of setting this property globally.

import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    clientCertificates: [{
      origin: 'https://example.com',
      certPath: './cert.pem',
      keyPath: './key.pem',
      passphrase: 'password',
    }],
  },
});

Here, the first attribute, origin, specifies the domain in which the client certificate is valid. The second attribute, certPath, indicates the file path to the client certificate in PEM (Privacy Enhanced Mail) format. The third attribute, keyPath, points to the private key associated with the client certificate in PEM format. The last attribute, passphrase, is the keyword used to secure the private key.

Note: You can also specify these client certificates while creating a new browser context or a new context for making API requests.

2. Run Only Changed Tests

You might have wondered if there was a way to run only the recently changed tests in Playwright testing. While you can use --grep to run specific tests, that method can be cumbersome if there are dozens of modified tests. To address this, Playwright has introduced a new CLI option to run only the changed tests.

To run the changed tests, use the --only-changed option and the run command.

 npx playwright test --only-changed
 
 #Only run tests file changed relative to a specific commit
 npx playwright test --only-changed=fe9357c 
 
 #Only run tests file changed relative to the "main" branch
 npx playwright test --only-changed=main

Note: The --only-changed option will run only test files that have been modified since the last git commit, from a specific commit, or that have been changed on the current branch. It will also run all test files that import any modified files.

Let's explore some features that were introduced in UI mode.

1. New Annotations Tab

Playwright has added a new annotations tab next to attachments, which displays the annotations added to the tests.

2. Request Method & Status Code Displayed in the Network Tab

In the above image, we can see that under the general section, the request method GET & status code 200 of a particular request.

3. New Settings Panel

There is a new setting to show or hide routing actions (Note: All route.* actions will be hidden from v1.48 onwards). Additionally, you can enable or disable dark mode from the settings panel.

4. Base URL in the Metadata pane

We can now see the Base URL under the config section of the metadata pane.

5. Request URLs in the Actions pane

Playwright will now show the request URLs for actions initiated via APIRequestContext in the actions pane.

6. Text attachments in UI mode

We can now access the text attachments added to the tests in UI mode. The text can be specified in the body property of the options argument.

7. Links in the attachment section of the HTML reporter

Playwright now allows links in the attachment section of the HTML reporter. I.e., the links provided in the attachments will be highlighted & can be opened in a new tab.

Let's look at some minor enhancements & changes introduced in this update.

  • We can now use the maxRetries option in the apiRequestContext.fetch() method to retry a request if it encounters an ECONNRESET network error.

Here is an example:

await request.fetch('https://example.com/api/createBook', {
  method: 'post',
  data: {
    title: 'Book Title',
    author: 'John Cena',
  },
  maxRetries: 3,
});
  • We can use the box option to minimise fixture exposure in UI mode & trace viewer. This will reduce noise when using frequently used fixtures & is particularly useful for non-essential helper fixtures.

import { test as base } from '@playwright/test';

export const test = base.extend({
  helperFixture: [async ({}, use) => {
    // ...
  }, { box: true }],
});
  • We can now give fixtures a custom title that will be shown in test reports & error messages.

import { test as base } from '@playwright/test';

export const test = base.extend({
  innerFixture: [async ({}, use, testInfo) => {
    // ...
  }, { title: 'my fixture' }],
});

Performance Enhancement

  • Playwright has introduced a cache system for storing normalised texts. This will reduce the time taken by the recorder to compute selectors by 8x.

Minor Bug Fixes

  • Playwright will now throw errors for invalid dates while using the setSystemTime method in Clock APIs.

  • Playwright can now click on a link inside a disabled input label.

  • Fixed the issue where the start time for a request displayed the end time in the network tab.

  • Fixed bug in updating snapshots in UI mode with the --update-snapshots flag.

  • Fixed the issue with clicking on visible elements that aren’t interactable. Previously, if a component were not interactable, the code would reassign it to the nearest interactive parent element; otherwise, it would keep the original element. Now, the updated logic first checks if the target element is not interactable. If it’s not, it finds the nearest interactive parent, ensures this parent is visible on the screen, & then reassigns the element to this parent.

  • The setInputFiles() method will now throw an error while attempting to use directory uploads without providing the necessary directory path.

  • Playwright recorder will now support custom context menus.

  • Fixed the issue where UI mode displayed all tests instead of only the selected ones when using the --grep flag.

  • Playwright now ensures that API calls are rejected before the browser is closed or a disconnect event is fired.


Release v1.47.0

Let's explore the features that were introduced in this release.

1. Network Tab Improvements

  • Filtering by Asset Type & URL - This feature allows users to filter network requests based on specific asset types (like images, scripts, or stylesheets) & URLs.

  • Preview of Font Assets - This feature allows users to see a visual representation of the fonts being loaded in the application.

2. New CLI Option

We can now specify a single tsconfig file in the command line, & Playwright will use it not only for the test files but for all imported files.

To pass a specific tsconfig, use the --tsconfig option along with the file name.

npx playwright test --tsconfig tsconfig.test.json

3. New Query Params for APIRequestContext

We can now pass URLSearchParams or a string as query parameters to APIRequestContext.

Here is an example that implements this:

test('query params', async ({ request }) => {
  const searchParams = new URLSearchParams();
  searchParams.set('userId', 3);
  const response = await request.get(
      'https://jsonplaceholder.typicode.com/posts',
      {
        params: searchParams // or as a string: 'userId=5'
      }
  );
});

Next, Let's explore some other improvements made in UI mode.

1. Query String Parameters.

We can now see the list of query parameters in the request tab under the query string parameters section.

2. Open text/html Attachments in a New Tab.

We can now open the attachments with a text/html content type in a new tab in the HTML report. This is useful for including third-party reports or other HTML content in the Playwright test report.

Let's look at some minor enhancements & changes introduced in this update.

  • We can now remove all event listeners (or all the listeners of a given type if the type is specified) using the removeAllListeners() method. The arguments given to this method are type, which is the listener type & behavior, an option to determine how to handle already running listeners & errors thrown by them.

Here is an example:

await browser.removeAllListeners("event", { 
   behavior: "wait" //or "ignoreErrors", "default"
}); 
  • We can now pass the key & cert attribute of the clientCertificates option as buffers instead of file paths while creating a new browser context.

await page
   .getByTestId("data-testId")
   .selectOption("value", { 
      noWaitAfter: boolean //deprecated
   });
  • Playwright will now record the trace even if the test-scoped fixture times out.

Performance Enhancements

  • Improved react code in UI mode, trace viewer & HTML reporter.

Minor Bug Fixes

  • Fixed the issue where watch mode in UI mode did not run newly added tests in the same file.

  • Fixed issues with downloading attachments in UI mode.

  • Now, the snapshots will render special characters correctly due to UTF-8 encoding.

  • From this update onwards, timeout in afterEach hook will not prevent fixture teardowns with custom timeout.

  • Now, we can list out the only changed tests with the combination of list & only changed flag Here is an example:

npx playwright test --list --only-changed
  • Playwright will throw errors for a duplicate test name.

  • Fixed issues where expect.poll error reporting not handling non-expect errors.

  • Fixed a bug in the Network tab where the request body was not correctly formatted when the Content-Type header was lowercase (content-type), even though the value was application/json.

  • We can now use custom matchers on expect.poll.


Release v1.48.0

Let's explore the major changes that were made in this release.

routeWebSocket

We can use this method to modify Websocket connections that are made by any page in the browser context. Using this method, we can mock or intercept a Websocket.

Let's look at a mocked Websocket.

await page.routeWebSocket('/echo.websocket.org/', ws => {
  ws.send("Welcome!");
  
  ws.onMessage('Welcome' => {
    if (message === 'Hello chatbot')
      ws.send('Hello friend');
      ws.send('How can I help you today?');
  });
});

In this example, we are not calling the server; Instead, we are mocking the entire communication over the WebSocket.

Let's look at an intercepted Websocket.

await page.routeWebSocket('/echo.websocket.org/', ws => {
  const server = ws.connectToServer();
  
  ws.onMessage('Welcome' => {
    if (message === "Hello chatbot")
      server.send('Hello friend');
    else
      server.send(message);
  });
});

In this case, we are connecting with the server, allowing us to intercept messages in between & modify or block them.

Now, Let's look at some methods we can call on a WebSocket.

  1. close - Closes one side of the WebSocket connection.

await ws.close();
await ws.close({code: 1000, reason});

Here, we can pass the code & reason as options. Code represents the close code indicating a reason for closure & the reason will be the reason for closing the connection.

  1. connectToServer - Connects to the actual WebSocket server, & returns the server-side WebSocketRoute instance.

ws.connectToServer();
  1. onClose - We can use this method to disable the default closure (Ie. closing one side of the connection will close the other side). And we can pass a handler as an argument that will handle the closure.

ws.onClose(handler);
  1. onMessage - We can use this method to handle messages that are sent by the WebSocket, either from the page or from the server.

ws.onMessage(handler);
  1. send - We can use this method to send a message to the WebSocket. It will send a message to the page when this method is called on the original WebSocket. We can also use this method to send a message to the server if we call this method on the result of webSocketRoute.connectToServer().

ws.send(message);
  1. url - This can be used to access the URL of the WebSocket created on the page.

ws.url();

Next, Let's explore some other improvements made in UI mode.

1. Copy Requests as cURL or Fetch in the Network Tab

You can now copy requests from the Network tab in the Trace Viewer, with the option to choose either cURL or Fetch format.

2. Trace Viewer: Output Toggle Button Highlighted for Terminal Errors

The Trace Viewer will now highlight the output toggle button if the terminal contains an error.

Let's look at some minor enhancements & changes introduced in this update.

  • form option in apiRequestContext.fetch() now accepts FormData.

Here is an example:

const formData = new FormData();
form.set('firstName', 'John');
form.append('lastName', 'Cena');

await request.fetch('https://example.com/api/uploadForm', {
  method: 'post',
  form: formData
});
  • Memory leaks can be detected through the requestGC() method. Let's understand this through an example:

await page.evaluate(() => 
globalThis.suspectWeakRef = new WeakRef(suspect));

await page.requestGC();

expect(await page.evaluate(() =>           !globalThis.suspectWeakRef.deref())).toBe(true);

In the first line, we save a weak reference to an object (referred to as suspect) to a global variable called suspectWeakRef. The second line calls the page.requestGC() method to clean up unused objects. In the last line, we check if the object was deleted, & if it was not deleted, it could signify that there is a memory leak.

  • The test.step allows you to pass a custom location as an option, which will be displayed in the trace viewer & reporter. By default, the location of test.step() is shown.

Here is an example:

test("Test 1", async ({ page }) => {
  await test.step("login",async () => {
      await expect(
        page.getByRole("heading", { name: "Login" })
      ).toBeVisible();
  },
  { 
   location: { 
     line: 2, 
     file: "e2e/example.spec.ts", 
     column: 10 
    } 
  }); 
});
  • The requests made by APIRequestContext record the detailed timing & security information in the HAR (HTTP Archive) format.

  • Playwright has updated the expect.extend behaviour so that it no longer mutates the global expect instance. Here is an example:

const expectOne = expect.extend({
  toCustomMatcher() {
    console.log("Hello");

    return {
      pass: true,
      message: () => 'Random message',
    };
  },
});
      
const expectTwo = expect.extend({
  toCustomMatcher() {
    console.log("Hi");

    return {
      pass: true,
      message: () => 'Random message',
    };
  },
});

Here, both expectOne & expectTwo are distinct instances, unlike in previous versions, where they would have been the same.

  • We can now copy the text in annotations & filename in HTML reporter.

  • Playwright now supports TLS client certificates with proxy servers.

  • Playwright will not execute an upfront test run on watch mode.

  • We can now use the buffer mode to run the changed tests in watch mode.

Watch mode can be activated by executing the following command:

PWTEST_WATCH=1 npx playwright test

After turning on watch mode, we can activate Buffer mode by pressing b. The changed tests will be shown on the terminal & we can run the tests by pressing Enter.

Minor Bug Fixes

  • Playwright will no longer consider the --retries for the --maxFailures flag.

  • Fixed the issue with the expect.poll did not display the custom error message when provided.

  • Playwright has disabled the ThirdPartyStoragePartitioning for Chromium.

  • Fixed the issue where UI mode did not recognise the --tsconfig flag specified via the CLI.

If you liked this blog, check out our complete archive of blogs on various topics.

Stay up to date with our blogs.

Subscribe to receive email notifications for new posts.

NeetoPublish Made with NeetoPublish