playwright-qatouch
v1.1.1
Published
Playwright reporter that auto-creates test cases, test runs, and uploads results to QA Touch — no TR codes required.
Maintainers
Readme
playwright-qatouch
A Playwright reporter that automatically syncs test cases, creates test runs, and uploads results to QA Touch — no TR codes required.
Features
- Full sync mode — auto-creates QA Touch modules from your
describe()blocks, creates missing test cases, and builds test runs - Title-based matching — no need to put
TR0123codes in your test names - Auto-creates test runs with milestone and assignment
- Error details & screenshots — failed tests upload the error message and screenshot attachments to QA Touch
- Uploads results (Passed / Failed / Blocked / Untested) after the run
- Generalized run grouping — create separate QA Touch runs by browser, Playwright project, role, or test-data tags
- Zero config files — everything goes in
playwright.config.ts
Installation
npm install --save-dev playwright-qatouchUsage
Add the reporter to your playwright.config.ts:
import { defineConfig } from "@playwright/test";
export default defineConfig({
reporter: [
["html"],
[
"playwright-qatouch",
{
domain: process.env.QATOUCH_DOMAIN,
apiToken: process.env.QATOUCH_API_TOKEN,
projectKey: process.env.QATOUCH_PROJECT_KEY,
assignTo: process.env.QATOUCH_ASSIGN_TO,
// sync defaults to true — modules are created from describe() blocks
},
],
],
});That's it. When you run npx playwright test, the reporter will:
- Resolve modules from your
describe()blocks (or use a fixedtestsuiteId) - Fetch existing test cases, create any missing ones
- Create a new test run under the specified milestone
- Collect all test results (including error messages and screenshots for failures)
- Upload failed tests individually with details, then bulk-upload the rest
Configuration Options
| Option | Required | Default | Description |
| --------------- | ------------------------- | ------------------------- | -------------------------------------------------- |
| domain | Yes | — | Your QA Touch domain (subdomain) |
| apiToken | Yes | — | QA Touch API token |
| projectKey | Yes | — | QA Touch project key |
| testsuiteId | Yes (unless sync: true) | — | Module/testsuite key to push results into |
| assignTo | Yes | — | User key to assign the test run to |
| sync | No | true | Full sync: auto-create modules & cases from suites |
| milestoneName | No | "Playwright Automation" | Release/milestone name (reuses or creates) |
| milestoneKey | No | — | Existing milestone key (skips name lookup) |
| createCases | No | true | Auto-create missing test cases |
| createTestRun | No | true | Auto-create a test run |
| tag | No | "playwright" | Tag applied to the created test run |
| splitRunsBy | No | [] | Split QA Touch runs by project, browser, or tag:<name> |
Sync mode vs. fixed module
| Mode | Config | Behaviour |
| ------------------ | -------------------------------- | --------------------------------------------------------------------------------------------------------- |
| Sync (default) | sync: true, no testsuiteId | Reads describe() block names, matches or creates QA Touch modules, creates missing cases in each module |
| Fixed module | sync: false, set testsuiteId | All tests are pushed into the single specified module — no modules are created |
Example: Full sync (recommended)
// playwright.config.ts
export default defineConfig({
reporter: [
[
"playwright-qatouch",
{
domain: process.env.QATOUCH_DOMAIN,
apiToken: process.env.QATOUCH_API_TOKEN,
projectKey: process.env.QATOUCH_PROJECT_KEY,
assignTo: process.env.QATOUCH_ASSIGN_TO,
// sync defaults to true — modules are created from describe() names
},
],
],
});Example: Fixed module
// playwright.config.ts
export default defineConfig({
reporter: [
[
"playwright-qatouch",
{
domain: process.env.QATOUCH_DOMAIN,
apiToken: process.env.QATOUCH_API_TOKEN,
projectKey: process.env.QATOUCH_PROJECT_KEY,
testsuiteId: process.env.QATOUCH_TESTSUITE_ID,
assignTo: process.env.QATOUCH_ASSIGN_TO,
sync: false,
},
],
],
});Example: Generalized execution context
Use splitRunsBy when the same logical test case runs under multiple execution contexts and you want separate QA Touch runs instead of one merged result.
export default defineConfig({
reporter: [
[
"playwright-qatouch",
{
domain: process.env.QATOUCH_DOMAIN,
apiToken: process.env.QATOUCH_API_TOKEN,
projectKey: process.env.QATOUCH_PROJECT_KEY,
assignTo: process.env.QATOUCH_ASSIGN_TO,
splitRunsBy: ["browser", "tag:role", "tag:data"],
},
],
],
});Then add execution metadata to the test title:
test("should create order @role=admin @data=us", async ({ page }) => {
// ...
});This keeps the QA Touch case title stable as should create order, while the reporter creates distinct QA Touch runs such as:
Playwright Run ... [browser=chromium, role=admin, data=us]Playwright Run ... [browser=firefox, role=admin, data=us]
Supported splitRunsBy values:
project— split by Playwright project namebrowser— split by inferred browser name from the Playwright projecttag:<name>— split by title metadata such as@role=adminor@data=us
Error Details & Screenshots
When a test fails, the reporter automatically captures:
- Error message — exception name, message, and the first 5 stack frames
- Screenshot — from Playwright's built-in screenshot attachments
To get screenshots on failure, enable them in your Playwright config:
export default defineConfig({
use: {
screenshot: "only-on-failure",
},
});The error message and screenshot are uploaded to QA Touch as a comment on the failed test result.
CI/CD (GitHub Actions)
- name: Run Playwright tests
run: npx playwright test
env:
QATOUCH_DOMAIN: ${{ secrets.QATOUCH_DOMAIN }}
QATOUCH_API_TOKEN: ${{ secrets.QATOUCH_API_TOKEN }}
QATOUCH_PROJECT_KEY: ${{ secrets.QATOUCH_PROJECT_KEY }}
QATOUCH_ASSIGN_TO: ${{ secrets.QATOUCH_ASSIGN_TO }}Set sync: false and add testsuiteId in your config if you want to target a fixed module instead of auto-creating from describe() names.
Status Mapping
| Playwright | QA Touch | | ----------- | ------------ | | passed | Passed (1) | | failed | Failed (5) | | timedOut | Failed (5) | | interrupted | Blocked (3) | | skipped | Untested (2) |
When splitRunsBy is empty, repeated executions of the same test title are merged and the worst status wins (failed > blocked > passed > untested).
When splitRunsBy is set, each group gets its own QA Touch test run, so browser-, role-, or data-specific outcomes stay separate.
How It Works
onBegin— Resolves modules (sync mode) or loads existing cases (fixed module), creates missing test cases, creates a test runonTestEnd— Collects each test result and assigns it to a run group based onsplitRunsBy(failures also capture error message and screenshot path)onEnd— Creates one QA Touch run per group, uploads failed tests individually with error details/screenshots, then bulk-uploads the rest
License
ISC
