npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

playwright-request-mocker

v0.3.0

Published

Automatically generate and use network request mocks inside Playwright.

Downloads

32

Readme

playwright-request-mocker

Automatically generate and use network request mocks inside Playwright!

Features :mag_right:

Mocking your API requests takes too much precious development time, this library strives to make it effortless by:

  • Allowing you to declare just once the hook use, it finds the mock file;
  • If the mock file does not exist yet, it will open a Playwright's chromium tab, and record all your XHR requests and responses;
  • It'll automatically intercept all registered HTTP requests defined in the mock file for any future runs.

Install :construction_worker:

  1. Install the package:
  • npm install playwright-request-mocker -D
  • or yarn add playwright-request-mocker -D;
  1. Be sure to have @playwright/test also installed.

Using :electric_plug:

  1. Add to a .spec file, inside a beforeEach or test method, the hook call useNetworkRecordMocks passing the test context page, identifier of the mock (only necessary if each test scenario has a different mock), and a route to be used by the recording tab if there is no mock file yet;

    • e.g.
import { useNetworkRecordMocks } from 'playwright-request-mocker';          // if using .mjs / .ts
// const { useNetworkRecordMocks } = require('playwright-request-mocker');  //if using .js

test.describe('Your test', () => {
  // If your network requests/responses are the same for every test scenario, define it here.
  test.beforeEach(async ({ page }) => {
    await useNetworkRecordMocks(page, {
      recordRoute: `${process.env.APP_URL}/page-you-are-testing`,
    });

    await page.goto(`${process.env.APP_URL}/page-you-are-testing`);
  });

  // else use it here if each test scenario expects different results.
  test('scenario1', async ({ page }) => {
    // It'll generate a new file if it does not exist (".spec.scenario1.mocks.json")
    // then it'll read it and mock all defined network requests.
    await useNetworkRecordMocks(page, {
      identifier: 'scenario1',
      recordRoute: `${process.env.APP_URL}/page-you-are-testing`
    });

    await page.goto(`${process.env.APP_URL}/page-you-are-testing`);

    //... your steps and asserts.
  });
});
  1. Run in debug mode;
  • PWDEBUG=console forces Playwright to run headed, disables the timeouts and shows the console helper.
// Linux/macOS
PWDEBUG=console npm run playwright test

// Windows on cmd.exe
set PWDEBUG=console
npm run playwright test

// Windows on PowerShell
$env:PWDEBUG="console"
npm run playwright test
  • If the mock file does not exist yet, it'll open a new tab and will be recording all the XHR requests as you navigate. When you think you recorded everything you needed, press the resume button in the playwright/test UI.
  • After it, or if the mock file ever exists, it will use the results to run your test scenario.

How it works :question:

  • useNetworkRecordMocks checks if there is a file [invoker-file-name].mocks.json (or [invoker-file-name].[identifier].mocks.json), if it doesn't exists, it'll open a chromiun tab using chrome's recordHAR option. When the Playwright debug mode is unpaused, it'll process such file removing every request other than XHR ones;
  • useNetworkRecordMocks will parse the existing file, and mock every request declared on it.

Different use cases :footprints:

  • For a given test scenario, I need to change the mocked value: there are 3 ways to achieve this, 1 being creating a new specific mock file at each scenario (by calling useNetworkRecordMocks inside each test with a identifier), and others being overriding the route response, like the following:

Overriding approach: for when the useNetworkRecordMocks call is inside the test scenario:

  import { useNetworkRecordMocks, mockRouteResponse } from 'playwright-request-mocker';

  // [...]

  test('my different scenario', async ({
    page,
  }) => {
    const errorMessage = 'error message I expect';

    await useNetworkRecordMocks(page, {
      recordRoute: `${process.env.APP_URL}/page-you-are-testing`,
      overrideResponses: {
        "/ENDPOINT_TO_CHANGE": { errors: [{ message: errorMessage }] }
      }
    });

    await page.goto(`${process.env.APP_URL}/page-you-are-testing`);

    await Promise.all([
      page.waitForRequest('**/ENDPOINT_TO_CHANGE'),
      fillForm(page),
    ]);

    await page.waitForSelector(`text=${errorMessage}`);
    const visible = await page.isVisible(`text=${errorMessage}`);
    expect(visible).toBeTruthy();
  });

Unrouting approach: for when the useNetworkRecordMocks call is inside a beforeEach:


test.describe('Test', () => {
  test.beforeEach(async ({ page }) => {
    await useNetworkRecordMocks(page, {
      recordRoute: `${process.env.APP_URL}/page-you-are-testing`,
    });

    await page.goto(`${process.env.APP_URL}/page-you-are-testing`);
  });

  test('my different scenario', async ({
    page
  }) => {
    const errorMessage = 'error message I expect';

    page.unroute('**/ENDPOINT_TO_CHANGE');
    mockRouteResponse(
      page,
      '**/ENDPOINT_TO_CHANGE',
      { errors: [{ message: errorMessage }] },
      400,
    );

    await Promise.all([
      page.waitForRequest('**/ENDPOINT_TO_CHANGE'),
      fillForm(page),
    ]);

    await page.waitForSelector(`text=${errorMessage}`);
    const visible = await page.isVisible(`text=${errorMessage}`);
    expect(visible).toBeTruthy();
  });
}
  • I want to assert the payload sent against what was expected: useNetworkRecordMocks returns every mocked request payload, you can use it to assert the values:
  test('my different scenario', async ({
    page,
  }) => {

    const requests = await useNetworkRecordMocks(
      page,
      {
        recordRoute: `${process.env.APP_URL}/test-route`,
      }
    );

    const [req] = await Promise.all([
      page.waitForRequest('**/ENDPOINT_TO_TEST'),
      fillForm(page),
    ]);

    const expectedPayload = requests.find(r => r.url.includes('ENDPOINT_TO_TEST'))?.requestData;

    expect(expectedPayload).toStrictEqual(req.postDataJSON());

  });
  • I already have a HAR recorded file that I want to use: as long as it follows the same name structure as the file that is using it, the lib will prioritize it over recording a new one to generate the new mocks.json file:
  /tests
  |- my-test.spec.js
  |- my-test.spec.har
  |- my-test.spec.identifier.har

Feel free to contribute, report bugs, or contact me.