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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@qavajs/playwright

v4.2.0

Published

steps to interact with playwright

Readme

@qavajs/playwright

npm license

Cucumber BDD step definitions for the Playwright test runner. Part of the qavajs framework.

Installation

npm install @qavajs/playwright

Configuration

qavajs.config.ts

import { defineConfig } from '@qavajs/playwright';
import Memory from './memory';
import App from './page_object';

export default defineConfig({
    paths: ['features/*.feature'],
    require: [
        'node_modules/@qavajs/playwright/steps.js', // built-in step definitions
        'step_definitions/*.ts'                      // custom step definitions
    ],
    memory: new Memory(),
    pageObject: new App()
});

playwright.config.ts

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

export default defineConfig({
    testMatch: 'qavajs.config.ts',
});

Page Object

Define your page object using locator helpers exported from this package:

import { locator } from '@qavajs/playwright';

class LoginPage {
    // Simple CSS/XPath/text selector
    UsernameInput = locator('#username');
    PasswordInput = locator('#password');
    SubmitButton  = locator('button[type="submit"]');

    // Template selector — argument passed via 'ElementName(arg)' syntax in steps
    RowByText = locator.template((text: string) => `tr:has-text("${text}")`);

    // Native Playwright locator — full access to page/context/parent
    ActiveTab = locator.native(({ page }) => page.locator('.tab.active'));
}

class App {
    LoginPage = locator.as(LoginPage);
}

export default App;

Reference nested elements in steps using > separator:

When I click 'LoginPage > SubmitButton'
When I click 'Table > RowByText(some text) > EditButton'

Built-in Steps

Navigation & Actions

| Step | Description | |------|-------------| | I open {value} url | Navigate to URL | | I refresh page | Reload current page | | I open new tab | Open a new blank tab | | I close current tab | Close current tab and switch to first | | I switch to {int} window | Switch to window by index (1-based) | | I switch to {value} window | Switch to window matching URL or title | | I click back button / I click forward button | Browser navigation | | I set window size {value} | Resize browser window, e.g. '1366,768' |

Interactions

| Step | Description | |------|-------------| | I click {locator} | Click element | | I force click {locator} | Click via JS (element.click()) | | I right click {locator} | Right-click element | | I double click {locator} | Double-click element | | I tap {locator} | Tap element (mobile) | | I hover over {locator} | Hover over element | | I type {value} into {locator} | Fill input (clears first) | | I type {value} chars into {locator} | Type character by character | | I clear {locator} | Clear input field | | I select {value} option from {locator} dropdown | Select option by label text | | I select {int}st/nd/rd/th option from {locator} dropdown | Select option by index | | I click {value} text in {locator} collection | Click element with text in a collection | | I click {value} coordinates in {locator} | Click at 'x, y' coordinates within element | | I drag and drop {locator} to {locator} | Drag & drop |

Scrolling

| Step | Description | |------|-------------| | I scroll by {value} | Scroll page by offset 'x, y' | | I scroll to {locator} | Scroll element into view | | I scroll by {value} in {locator} | Scroll inside a container | | I scroll until {locator} to be visible | Scroll page until element is visible | | I scroll in {locator} until {locator} to be visible | Scroll container until element is visible |

Keyboard & Mouse

| Step | Description | |------|-------------| | I press {string} key(s) | Press key(s), e.g. 'Enter', 'Control+C' | | I press {string} key(s) {int} time(s) | Press key N times | | I hold down {value} key | Hold keyboard key down | | I release {value} key | Release keyboard key | | I press {mouseButton} mouse button | Press mouse button (left, right, middle) | | I release {mouseButton} mouse button | Release mouse button | | I move mouse to {value} | Move mouse to 'x, y' coordinates | | I scroll mouse wheel by {value} | Scroll mouse wheel by 'x, y' offset |

Dialogs (Alerts)

| Step | Description | |------|-------------| | I accept alert | Accept dialog/alert | | I dismiss alert | Dismiss dialog/alert | | I type {value} to alert | Type text into a prompt dialog |

File Handling

| Step | Description | |------|-------------| | I upload {value} file to {locator} | Set file on file input directly | | I upload {value} file by clicking {locator} | Set file via file chooser dialog | | I upload files by clicking {locator}: | Set multiple files via file chooser (data table) | | I save file to {value} by clicking {locator} | Download file by clicking element | | I save {value} file content as {value} | Read file as Buffer into memory | | I save {value} text file content as {value} | Read text file (utf-8) into memory | | I expect {value} text file content {validation} {value} | Validate text file content | | I expect file matching {value} regexp exists in {value} | Assert file exists by regex in directory | | I expect {value} file exists | Assert file exists at path |

Validations

| Step | Description | |------|-------------| | I expect {locator} {state} | Validate element state (visible, present, clickable, etc.) | | I expect every element in {locator} collection {state} | Validate state of every element in collection | | I expect text of {locator} {validation} {value} | Validate element inner text | | I expect value of {locator} {validation} {value} | Validate input value | | I expect {value} property of {locator} {validation} {value} | Validate DOM property | | I expect {value} attribute of {locator} {validation} {value} | Validate HTML attribute | | I expect {value} css property of {locator} {validation} {value} | Validate computed CSS property | | I expect {value} custom property of {locator} {validation} {value} | Validate result of custom JS on element | | I expect number of elements in {locator} collection {validation} {value} | Validate collection size | | I expect text of every element in {locator} collection {validation} {value} | Validate text of all elements | | I expect {value} attribute of every element in {locator} collection {validation} {value} | Validate attribute of all elements | | I expect {value} property of every element in {locator} collection {validation} {value} | Validate property of all elements | | I expect {value} custom property of every element in {locator} collection {validation} {value} | Validate custom property of all elements | | I expect current url {validation} {value} | Validate current page URL | | I expect page title {validation} {value} | Validate page title | | I expect text of alert {validation} {value} | Validate alert message text | | I expect {value} {validation} {value} | Validate a memory value against another | | I expect every element in {value} array {validation} {value} | Validate every item in an array | | I expect at least {int} element(s) in {value} array {validation} {value} | Validate minimum number of passing items | | I expect {value} array to be sorted by {value} | Validate array is sorted by comparator function | | I expect {value} array {validation}: | Validate array members (data table) | | I expect {value} {validation} at least one of {value} | Validate value matches at least one in array | | I expect {value} {validation} at least one of: | Validate value matches at least one (data table) | | I expect {value} {validation} all of {value} | Validate value satisfies all in array | | I expect {value} {validation} all of: | Validate value satisfies all (data table) |

Memory

| Step | Description | |------|-------------| | I save text of {locator} as {value} | Save element inner text to memory | | I save value of {locator} as {value} | Save input value to memory | | I save {value} property of {locator} as {value} | Save DOM property to memory | | I save {value} attribute of {locator} as {value} | Save HTML attribute to memory | | I save {value} css property of {locator} as {value} | Save computed CSS property to memory | | I save {value} custom property of {locator} as {value} | Save custom JS result to memory | | I save number of elements in {locator} collection as {value} | Save collection size to memory | | I save text of every element of {locator} collection as {value} | Save array of texts to memory | | I save {value} attribute of every element of {locator} collection as {value} | Save array of attributes to memory | | I save {value} property of every element of {locator} collection as {value} | Save array of properties to memory | | I save {value} custom property of every element of {locator} collection as {value} | Save array of custom JS results to memory | | I save current url as {value} | Save current URL to memory | | I save page title as {value} | Save page title to memory | | I save bounding rect of {locator} as {value} | Save DOMRect to memory | | I save screenshot as {value} | Save page screenshot (Buffer) to memory | | I save full page screenshot as {value} | Save full-page screenshot (Buffer) to memory | | I save screenshot of {locator} as {value} | Save element screenshot (Buffer) to memory | | I save {value} to memory as {value} | Save any value or expression to memory | | I save multiline string to memory as {value}: | Save multiline string to memory | | I save json to memory as {value}: | Parse and save JSON string to memory | | I save key-value pairs to memory as {value}: | Save data table as object to memory | | I set {value} = {value} | Alias for saving a value to memory |

Waits

| Step | Description | |------|-------------| | I wait {int} ms | Explicit pause in milliseconds | | I click {locator} until {locator} {state} | Click until element reaches state | | I click {locator} until text of {locator} {validation} {value} | Click until element text matches | | I click {locator} until value of {locator} {validation} {value} | Click until input value matches | | I refresh page until {locator} {state} | Refresh until element reaches state | | I refresh page until text of {locator} {validation} {value} | Refresh until element text matches | | I refresh page until value of {locator} {validation} {value} | Refresh until input value matches |

Storage (Cookies & Web Storage)

| Step | Description | |------|-------------| | I set {value} cookie as {value} | Set a cookie (value or full cookie object) | | I save value of {value} cookie as {value} | Save cookie object to memory | | I set {value} local/session storage value as {value} | Set local or session storage item | | I save value of {value} local/session storage as {value} | Save storage item to memory |

HTTP Requests

Build and send HTTP requests using Playwright's APIRequestContext:

When I create 'POST' request 'myRequest'
And I add 'https://api.example.com/users' url to '$myRequest'
And I add headers to '$myRequest':
  | Content-Type | application/json |
And I add body to '$myRequest':
  """
  { "name": "qavajs" }
  """
And I send '$myRequest' request and save response as 'myResponse'
And I parse '$myResponse' body as 'json'
Then I expect '$myResponse.payload.name' to equal 'qavajs'

| Step | Description | |------|-------------| | I create {string} request {value} | Create request with HTTP method | | I create GraphQL request {value} | Create a GraphQL request | | I add headers to {value}: | Add headers from data table | | I add {value} headers to {value} | Add headers from memory object | | I add body to {value}: | Add body from multiline string | | I add {value} body to {value} | Add body from memory value | | I add form data body to {value}: | Add multipart form data body | | I add {value} url to {value} | Set request URL | | I add {gqlRequestProperty} to GraphQL {value}: | Set query or variables on GraphQL request | | I send {value} request and save response as {value} | Send request and save response | | I parse {value} body as {bodyParsingType} | Parse response body (json, text, buffer) |

Network Mocking

When I create mock for '**/api/users' as 'usersMock'
And I set '$usersMock' mock to respond '200' with:
  """
  [{ "id": 1, "name": "mock user" }]
  """
# ... run test ...
When I restore '$usersMock' mock

| Step | Description | |------|-------------| | I create mock for {value} as {value} | Create route mock for URL pattern | | I set {value} mock to respond {value} with: | Mock response with status and body (multiline) | | I set {value} mock to respond {value} with {string} | Mock response with status and body (inline) | | I set {value} mock to abort with {value} reason | Abort request with error code | | I restore {value} mock | Remove mock for URL pattern | | I restore all mocks | Remove all active mocks |

Network Interception

When I create interception for '**/api/products' as 'productsIntercept'
And I click 'LoadButton'
And I save '$productsIntercept' response as 'productsResponse'

| Step | Description | |------|-------------| | I create interception for {value} as {value} | Start intercepting requests matching URL/predicate | | I wait for {value} response | Wait for intercepted response to complete | | I save {value} response as {value} | Save intercepted response to memory |

JavaScript Execution

| Step | Description | |------|-------------| | I execute {value} function | Execute JS expression on the page | | I execute {value} function and save result as {value} | Execute JS and save result to memory | | I execute {value} function on {locator} | Execute JS with element as argument | | I execute {value} function on {locator} and save result as {value} | Execute JS on element and save result |

Electron

Additional steps available when using QavajsPlaywrightElectronWorld:

| Step | Description | |------|-------------| | I execute {value} function/script on electron app | Execute function in Electron main process | | I execute {value} function/script on electron app and save result as {value} | Execute and save result from main process | | I click {value} electron menu | Click application menu item by path (e.g. 'File > Save') |

Memory Syntax

Values enclosed in 'single quotes' in step definitions support memory interpolation:

  • 'literal value' — plain string
  • '$variableName' — read value from memory
  • '$js(expression)' — evaluate inline JavaScript
  • '$getUser()' — call a registered memory function

Development

# Install dependencies
npm install

# Install Playwright browsers
npm run install:browsers

# Build the library
npm run build

# Run e2e tests
npm run test:e2e

# Run Electron e2e tests
npm run test:e2e:electron