playwright-json-runner is a package that allows you to run Playwright tests using JSON files instead of traditional .ts or .js test files. This makes it easy to define and manage automated tests in a structured and configurable way.
-
- Adding ActionTypes to the JSON
- default action-typehandlers.ts
- Adding Locator resolving strategies
- default identifier-selectors.ts
- Adding custom playwright interactions
- default rule conditions (when each apply) getter-setter-rules.ts
- default getter strategies getter-strategies.ts
- default setter strategies getter-strategies.ts
- Adding ActionTypes to the JSON
-
- Example JSON Test:
json-tests/github.playwright.json
- Example JSON Test:
Install playwright-json-runner in your Playwright project:
npm install playwright-json-runner --save-dev- Run
npm install playwright-json-runner playwright @playwright/test --save-dev - (optional) Create a config file named
playwright-json.config.tsorplaywright-json.config.js. - Place your JSON test files
json-testsdirectory example - Create
playwright.config.tswith the this test runner as a project
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: "tests", //traditional .spec.ts files live here
//this enables json test runner to be discovered by playwright
projects:[
{
name: "Json-runner",
testDir: './node_modules/playwright-json-runner/dist/',
testMatch: 'runner-playwright.js',
}
]
});Run tests using npx playwright test or npx playwright test --ui Both JSON-defined tests and traditional .spec.ts or .spec.js files will be executed.
playwright-json-runner looks for a configuration file named either playwright-json.config.ts or playwright-json.config.js.
By default:
- Configuration file:
playwright-json.config.ts - (default) JSON test directory:
json-tests - (default) JSON test file format:
*.playwright.json
This file allows you to customize how json files are handled, where they live (directory and )
import { extendConfig } from "playwright-json-runner";
const userConfig = extendConfig({
jsonTestDir: "json-tests"
});
export default userConfig;- Adding ActionTypes to the JSON
- Adding Custom Locator Resolving Strategies
- Adding Custom Playwright Interactions
Action types define the possible interactions available in JSON-based tests. These actions allow you to extend Playwright functionality to support custom behaviors.
- Allows handling new custom interactions.
- Enables clearer test definitions by making interactions explicit.
- Enhances flexibility by allowing you to define custom behaviors.
default action-typehandlers.ts
In your playwright-json.config.ts file, add a custom action type:
const userConfig = extendConfig({
actionTypeHandlers: {
"clear": async (locator) => {
setLocatorValue(locator, "");
},
"assertClear": async (locator) => {
expect(await getLocatorValue(locator)).toBe("");
}
}
});
export default userConfig{
"browser": "chromium",
"host": "https://example.com",
"scenarios": [
{
"name": "Test Custom Actions",
"steps": [
{
"description": "Clear input field",
"actions": [
{ "type": "clear", "selector": "input[id=username]" },
{ "type": "assertClear", "selector": "input[id=username]" }
]
}
]
}
]
}Locator strategies define how elements are located in the UI when an identifier is used in JSON tests.
- Provides flexible and modular ways to locate elements.
- Supports multiple locator types (e.g., selectors, roles, test IDs, text, and nested locators).
- Ensures robust and scalable test execution.
By default, several locator strategies are available, such as:
- Selector-based locators to find elements using CSS or XPath.
- Role-based locators for elements with specific ARIA roles.
- Test ID locators to find elements based on test-specific attributes.
- Text-based locators to find elements by visible text.
- Nested locators for more complex hierarchical selections.
default identifier-selectors.ts
In playwright-json.config.ts, define or extend locator strategies:
const userConfig = extendConfig({
locatorStrategies: {
textWaitForDom: async (page, strategy) => {
page.waitForLoadState("domcontentloaded");
return page.getByText(strategy.value);
}
}
});
export default userConfig{
"description": "Find text element and click",
"actions": [
{
"type": "click",
"locator": {
"type": "textWaitForDom",
"value": "Accept Terms"
}
}
]
}<label for="terms">Accept Terms</label>
<input type="checkbox" id="terms">By defining custom locator strategies, tests become more adaptive and resilient to UI changes, ensuring a more stable automation framework.
extends SetFieldValue & GetFieldValue actions and any action that uses them. Custom interactions override how element values are set or retrieved they implement how we perform actions like typing, clicking, or validating values.
- Provides better control over how Playwright interacts with UI elements.
- Allows user to implement how they handle for non-standard elements.
- Extends support as needed for any UI Component
IMPORTANT: rules order matters! notice how the new rule (often most complex) is defined on top, because whatever rule matches first, is the one that will be used
default rules and strategies already configured -getter-setter-rules.ts -getter-strategies.ts -setter-strategies.ts
xpathEval is a function that evaluates an XPath expression within a locator's context.
This allows users to dynamically resolve elements relative to the resolved locator, ensuring more flexible and adaptable test strategies.
<body>
<div id="name">
<customInputTag></customInputTag>
</div>
</body>{
"selector": "[id='name']",
"type": "setFieldValue",
"value": "first name"
}- The locator initially references the
div(id="name"). xpathEval("//customInputTag")runs inside thediv's context, returning the<customInputTag>element.- The
setFieldValueaction is executed on<customInputTag>instead of thedivitself.
const userConfig = extendConfig({
rules: {
"contentEditableDiv": ({ xpathEval }) => xpathEval("//div[@contenteditable=true]")
},
setterStrategies: {
"myCustomInput": async ({ locator, value }) => {
await locator.fill(value ?? "");
}
}
});
export default userConfig{
"description": "Set value in an editable div",
"actions": [
{
"type": "setFieldValue",
"selector": "//div[@id='editor' and contenteditable=true]",
"value": "Hello World"
}
]
}const userConfig = extendConfig({
rules: {
"contentEditableDiv": ({ xpathEval }) => xpathEval("//div[@contenteditable=true]")
},
getterStrategies: {
"contentEditableDiv": async ({ locator }) => {
return await locator.inputValue();
}
}
});
export default userConfig- Custom ActionTypes extending JSON to handle new actions.
- Custom Locator Strategies expands the way we find elements(locators) in the UI
- Custom Playwright Interactions expands how we interact with the elements (locators), good for handling special UI elements.
By configuring these aspects, you enhance test reliability and flexibility, making it easier to automate complex UI behaviors with JSON-based Playwright tests.
To define a test, create a JSON file inside json-tests/. The default file name should follow the convention *.playwright.json :
sample path:
projectName/json-tests/github.playwright.json{
"browser": "chromium",
"host": "https://github.com",
"scenarios": [
{
"name": "GitHub Login Test",
"steps": [
{
"description": "Go to GitHub",
"actions": [
{ "type": "navigate", "value": "https://github.com" }
]
},
{
"description": "Click Sign In",
"actions": [
{ "type": "click", "selector": "text=Sign in" }
]
}
]
}
]
}Once the package is installed and tests are configured, run Playwright as usual:
npx playwright testnpx playwright test --uiThis will automatically pick up JSON-based tests and execute them alongside traditional .spec.ts files.
β
Define tests in pure JSON
β
Works seamlessly with Playwright
β
Supports navigation, clicks, inputs, expects pass through
β
Configurable all actions have strategies implemented are fully configurable
β
Works alongside TypeScript/JavaScript tests
-
No tests found?
Ensure your JSON test directory (json-tests/) and test file (.playwright.json) are correctly named. -
Custom configuration?
Modifyplaywright-json.config.tsto point to the correct directory. -
Playwright not detecting tests?
Run withDEBUG=pw:apito see detailed logs.
The following example demonstrates how to extend your playwright-json.config.ts file with custom configuration options.
In your playwright-json.config.ts, you can add custom action types, selectors, and strategies as follows:
import { expect } from "@playwright/test";
import { extendConfig } from "playwright-json-runner";
import {getLocatorValue, setLocatorValue} from "playwright-json-runner"
const userConfig = extendConfig({
locatorStrategies: {
textWaitForDom: async (page, strategy) =>
{
page.waitForLoadState("domcontentloaded");
return page.getByText(strategy.value)
}
},
actionTypeHandlers:{
"clear": async (locator)=>{
setLocatorValue(locator, "")
},
"assertClear": async (locator)=>{
expect(getLocatorValue(locator)).toBe("")
}
},
//define when it applies
rules: {
"myCustomInput": ({ xpathEval }) => xpathEval("//div[@contenteditable=true")
},
//strategy for getting the value used when actionTypeHandlers call setLocatorValue
getterStrategies: {
"myCustomInput": async ({locator}) => await locator.inputValue()
},
//strategy for setting the value used when actionTypeHandlers call getLoctorvalue
setterStrategies: {
"myCustomInput": async ({locator, value}) => await locator.fill(value??"")
}
});
export default userConfig;The above configuration enables the following functionalities in any JSON test:
- Use of
identifier: checkboxLabelwithin any action (viaidentifierSelectors) - A custom
clearaction (viaactionTypeHandlers) - A custom
assertClearaction (viaactionTypeHandlers) - Ability to use
setFieldValueon an editable input using thesetterStrategiesentrymyCustomInput - Ability to use
assertFieldValueon an editable input using thegetterStrategiesentrymyCustomInput
implementations for all the baseConfig
{
"driver": "Playwright",
"browser": "chrome",
"host": "https://www.github.com/",
"scenarios": [
{
"name": "Signup Test",
"steps": [
{
"description": "Navigate to create account",
"actions": [
{
"type": "clear",
"selector": "[id=name]"
},
{
"type": "assertClear",
"selector": "[id=name]"
},
{
"type": "click",
"locator":
{
"type": "textWaitForDom",
"value": "checkbox label"
}
},
{
"type": "setFieldValue",
"selector": "//div[@id='blog-body' and contenteditable=true]",
"value": "some blog writing"
},
{
"type": "assertFieldValueEquals",
"selector": "//div[@id='blog-body' and contenteditables=true]",
"value": "some blog writing"
}
]
}
]
}
]
}This configuration and test example showcase how you can extend and customize your Playwright JSON runner setup to handle a variety of UI interactions with enhanced flexibility.
import { expect } from "@playwright/test";
import { Configuration, baseConfig } from "playwright-json-runner";
import { getLocatorValue, setLocatorValue } from "playwright-json-runner";
const userConfig: Configuration = {
//...baseConfig allows you to use default, unless overwritten
...baseConfig,
actionTypeHandlers: {
...baseConfig.actionTypeHandlers,
"clear": async (locator) => {
setLocatorValue(locator, "");
},
"assertClear": async (locator) => {
expect(await getLocatorValue(locator)).toBe("");
}
},
//the below defines setfieldvalue and getfield value functionalities
// be careful, if you use setFieldValue action in a
// Define when it applies (important: the first rule to match will be used)
rules: {
"myCustomInput": ({ xpathEval }) => xpathEval("//div[@contenteditable=true]"),
},
// Strategy for setting the value used when actionTypeHandlers call getLocatorValue
setterStrategies: {
"myCustomInput": async ({ locator, value }) => await locator.fill(value ?? "")
},
// Strategy for getting the value used when actionTypeHandlers call setLocatorValue
getterStrategies: {
"myCustomInput": async ({ locator }) => await locator.inputValue()
},
};
export default userConfig;this package is built using a Zod json schema, This schema helps you integreate with AI tools for generating a valid JSON to feed into this package
npx playwright-json-runner dump-json-schema playwright-json-runner-schema.json you may also import the Zod schema object
import { testRunSchema } from "playwright-json-runner"π Now you're ready to run Playwright tests using JSON! ππ₯