xrite-cypress-qatouch-reporter
v1.1.2
Published
Cypress plugin that auto-creates test cases, test runs, and uploads results to QA Touch — no TR codes required.
Maintainers
Readme
cypress-qatouch
A Cypress plugin 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 to QA Touch
- Uploads results (Passed / Failed / Blocked / Untested) after the run
- Run splitting — create separate QA Touch runs by browser or test-data tags
- Zero config files — everything goes in
cypress.config.ts
Installation
npm install --save-dev xrite-cypress-qatouch-reporterUsage
Register the plugin in your cypress.config.ts:
import { defineConfig } from "cypress";
import { registerQATouchPlugin } from "xrite-cypress-qatouch-reporter";
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
registerQATouchPlugin(on, {
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
});
return config;
},
},
});That's it. When you run npx cypress run, the plugin 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 | "Cypress 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 | "cypress" | Tag applied to the created test run |
| splitRunsBy | No | [] | Split QA Touch runs by 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)
import { defineConfig } from "cypress";
import { registerQATouchPlugin } from "xrite-cypress-qatouch-reporter";
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
registerQATouchPlugin(on, {
domain: process.env.QATOUCH_DOMAIN!,
apiToken: process.env.QATOUCH_API_TOKEN!,
projectKey: process.env.QATOUCH_PROJECT_KEY!,
assignTo: process.env.QATOUCH_ASSIGN_TO!,
});
return config;
},
},
});Example: Fixed module
import { defineConfig } from "cypress";
import { registerQATouchPlugin } from "xrite-cypress-qatouch-reporter";
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
registerQATouchPlugin(on, {
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,
});
return config;
},
},
});Example: Split runs by 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.
registerQATouchPlugin(on, {
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:
it("should create order @role=admin @data=us", () => {
// ...
});This keeps the QA Touch case title stable as should create order, while the reporter creates distinct QA Touch runs such as:
Cypress Run ... [browser=electron, role=admin, data=us]Cypress Run ... [browser=chrome, role=admin, data=us]
Supported splitRunsBy values:
browser— split by the browser used in the Cypress runtag:<name>— split by title metadata such as@role=adminor@data=us
Error Details & Screenshots
When a test fails, the plugin automatically captures:
- Error message — exception name, message, and the first 5 stack frames
- Screenshot — from Cypress's automatic failure screenshots
The error message and screenshot are uploaded to QA Touch as a comment on the failed test result.
CI/CD (GitHub Actions)
- name: Run Cypress tests
run: npx cypress run
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
| Cypress | QA Touch | | ------- | ------------ | | passed | Passed (1) | | failed | Failed (5) | | pending | 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- or tag-specific outcomes stay separate.
How It Works
after:run— The plugin registers a Cypressafter:runhook viaregisterQATouchPlugin(on, options)- Collect results — Iterates over all spec files and tests in the Cypress run result, extracting titles, statuses, errors, and screenshots
- Sync modules & cases — Resolves modules from
describe()block names (sync mode) or loads existing cases (fixed module), creates missing test cases - Build run groups — Groups collected results by
splitRunsBydimensions (browser, title tags) - Upload — Creates one QA Touch run per group, uploads failed tests individually with error details/screenshots, then bulk-uploads the rest
Changelog
1.1.2
- Fix:
getTestCases()pagination now uses deduplication instead ofper_page-based stop condition. The API returns variable item counts per page, which caused pagination to stop at page 1 even when more pages existed. - Fix:
moduleKeyquery parameter is silently ignored by the/getAllTestCasesAPI. Filtering by module is now done client-side usingitem.module_key.
License
ISC
