Test Package Manifest Reference
The qit-test.json file defines a test package's behavior, requirements, and integration points.
IDE Validation: To enable IDE validation and autocompletion, use
qit package:scaffoldwith the--with-schemaoption, or manually add"$schema": "https://raw.githubusercontent.com/woocommerce/qit-cli/trunk/src/src/PreCommand/Schemas/test-package-manifest-schema.json"to your manifest.
Minimal Example
{
"package": "your-extension-slug/checkout-tests",
"package_type": "test",
"test": {
"phases": {
"run": ["npm test"]
},
"results": {
"ctrf-json": "./results/ctrf.json",
"blob-dir": "./results/artifacts"
}
}
}
Complete Structure
{
"package": "namespace/name",
"package_type": "test or utility",
"description": "string",
"tags": ["array"],
"test_dir": "string",
"requires": {
"secrets": ["array"],
"php": "string",
"wordpress": "string",
"plugins": ["array of slugs"],
"themes": ["array of slugs"],
"external_services": ["array"],
"network": false,
"tunnel": false
},
"test": {
"phases": {
"globalSetup": ["array or objects"],
"setup": ["array or objects"],
"run": ["array or objects"],
"teardown": ["array or objects"],
"globalTeardown": ["array or objects"]
},
"results": {
"ctrf-json": "string",
"blob-dir": "string",
"json": "string",
"allure-dir": "string"
}
},
"actions": {
"capabilityName": "./path/to/implementation.ts"
},
"mu_plugins": ["array"],
"envs": {"key": "value"}
}
Required Fields
These fields are always required:
package
Required | string
Full package identifier in format namespace/name. Both namespace and name must match pattern ^[a-zA-Z0-9_.-]+$.
"package": "your-extension-slug/payment-tests"
package_type
Required | string
Type of package: "test" or "utility".
"test"- Traditional test packages that execute tests and produce results. Must have arunphase andresultsconfiguration."utility"- Configuration and setup packages without test execution. Must NOT have arunphase orresultsconfiguration.
"package_type": "test"
Best Practice: Always explicitly set this field even though QIT can auto-detect package type. Explicit declaration makes your intent clear and prevents accidental misconfiguration.
test
Required | object
Contains phases and results configuration. Must have at least a phases object.
Optional Top-Level Fields
description
Optional | string
Human-readable description (max 500 characters).
"description": "Payment gateway integration tests"
test_type
Optional | string
Type of test. Currently only "e2e" is supported. Defaults to "e2e" if not specified.
"test_type": "e2e"
tags
Optional | string[]
Tags for categorizing and searching test packages. Each tag must match pattern ^[a-zA-Z0-9_.-]+$.
"tags": ["payment", "stripe", "integration"]
test_dir
Optional | string
Directory containing test files. Defaults to "./". Must start with ./.
"test_dir": "./tests"
mu_plugins
Optional | string[]
Must-use plugins to install. Paths to mu-plugin files.
"mu_plugins": ["./mu-plugins/test-helper.php"]
envs
Optional | object
Environment variables to set during test execution. Values can be string, boolean, or number.
"envs": {
"TEST_MODE": "integration",
"DEBUG": true,
"MAX_RETRIES": 3
}
actions
Optional | object
Named actions this package registers for other packages to discover at runtime via qit.actions(). Maps action names to relative file paths. Each file must have an export default (that's the action implementation).
Like WordPress do_action(), multiple packages can register the same action name, and consumers iterate over all of them.
"actions": {
"makePurchase": "./flows/pay.ts",
"refundOrder": "./flows/refund.ts"
}
Action names must be camelCase identifiers (^[a-zA-Z][a-zA-Z0-9_]*$). Paths must start with ./. See Actions for the full guide.
requires
Optional requirements and constraints.
requires.secrets
Optional | string[]
Environment variables that must be present.
"requires": {
"secrets": ["STRIPE_KEY", "STRIPE_SECRET", "WEBHOOK_SIGNING_SECRET"]
}
These will be:
- Validated before execution
- Passed to all commands
- Redacted from output
requires.php
Optional | string
PHP version constraint.
"requires": {
"php": ">=8.0"
}
requires.wordpress
Optional | string
WordPress version constraint.
"requires": {
"wordpress": ">=6.4"
}
requires.plugins
Optional | string[]
Required plugins (will be installed and activated). Array of plugin slugs.
"requires": {
"plugins": ["woocommerce", "woocommerce-subscriptions"]
}
requires.themes
Optional | string[]
Required themes (will be installed). Array of theme slugs.
"requires": {
"themes": ["storefront"]
}
requires.network
Optional | boolean
Whether this package requires external network access. Default: false (tests run offline).
"requires": {
"network": true
}
requires.tunnel
Optional | boolean
Whether this package requires a tunnel for external access (e.g., payment gateway webhooks). Default: false.
"requires": {
"tunnel": true
}
requires.external_services
Optional | string[]
External services needed (for documentation purposes).
"requires": {
"external_services": ["stripe-api", "webhook-endpoint"]
}
test.phases
Commands to execute at different lifecycle points.
globalSetup
Optional | string[]
Runs once before ALL packages.
"globalSetup": [
"wp plugin install woocommerce --activate",
"wp option set woocommerce_onboarding_complete yes",
"wp user create customer customer@test.com --role=customer"
]
setup
Optional | string[]
Runs before THIS package's tests.
"setup": [
"npm ci",
"npx playwright install chromium",
"mkdir -p results"
]
run
Required for test packages | string[]
Executes the tests.
"run": [
"npx playwright test --reporter=ctrf-json"
]
teardown
Optional | string[]
Cleanup after THIS package.
"teardown": [
"rm -rf temp",
"wp option delete test_setting"
]
globalTeardown
Optional | string[]
Runs once after ALL packages.
"globalTeardown": [
"wp user delete customer --yes",
"wp post delete $(wp post list --post_type=product --format=ids) --force"
]
test.results
Where to find test output. Required for test packages, forbidden for utility packages.
ctrf-json
Required for test packages | string
Path to CTRF JSON file.
"ctrf-json": "./test-results/report.json"
blob-dir
Required for test packages | string
Directory containing artifacts.
"blob-dir": "./test-results/artifacts"
Structure:
artifacts/
├── screenshots/
│ └── failed-test.png
├── videos/
│ └── test-run.webm
└── logs/
└── console.log
json
Optional | string
Path to original JSON test results (before CTRF conversion).
"json": "./test-results/raw.json"
allure-dir
Optional | string
Allure results directory for advanced reporting.
"allure-dir": "./allure-results"
Validation Rules
Test Package Rules
If a package has a run phase:
- It MUST have
test.results - It MUST have
ctrf-jsonandblob-dir - It MAY have
allure-dir
Utility Package Rules
If a package has NO run phase:
- It MUST NOT have
test.results - It MAY have any other phases
Command Execution
Command Format
Commands can be either strings or objects with additional configuration:
String Format (Simple)
"setup": [
"echo 'Starting setup'",
"npm install",
"echo 'Setup complete'"
]
Object Format (Advanced)
"setup": [
{
"command": "npm install",
"runs_on": "host",
"timeout": 300,
"continue_on_error": false
}
]
Object properties:
command(required): The command to executeruns_on:"host"or"docker"(default: auto-detection; npm/npx run on host, everything else runs in Docker)timeout: Command timeout in seconds (1-3600)continue_on_error: Continue even if command fails (default:false)
Environment Variables
Commands have access to:
- System environment variables
- Declared secrets
- QIT variables like
$QIT_SITE_URL
"run": [
"BASE_URL=$QIT_SITE_URL npm test"
]
Working Directory
Commands execute in the package directory.
Exit Codes
Any non-zero exit code fails the phase.
Examples
Complete Test Package
{
"package": "your-extension-slug/checkout-tests",
"package_type": "test",
"description": "WooCommerce checkout flow tests",
"requires": {
"secrets": ["STRIPE_TEST_KEY", "STRIPE_TEST_SECRET"],
"php": ">=8.0",
"wordpress": ">=6.4"
},
"test": {
"phases": {
"globalSetup": [
"wp plugin install woocommerce-gateway-stripe --activate",
"wp option set woocommerce_stripe_settings '{\"enabled\":\"yes\",\"testmode\":\"yes\"}' --format=json"
],
"setup": [
"npm ci",
"npx playwright install"
],
"run": [
"npx playwright test checkout.spec.js --reporter=ctrf-json"
],
"teardown": [
"rm -rf test-results/temp"
],
"globalTeardown": [
"wp option delete woocommerce_stripe_settings"
]
},
"results": {
"ctrf-json": "./test-results/ctrf.json",
"blob-dir": "./test-results/artifacts",
"allure-dir": "./test-results/allure"
}
}
}
Complete Utility Package
{
"package": "woocommerce/test-environment",
"package_type": "utility",
"description": "Test environment configuration",
"test": {
"phases": {
"globalSetup": [
"wp core update-db",
"wp plugin install wordpress-importer --activate",
"wp import ./data/sample-content.xml --authors=create",
"wp wc tool run install_pages --user=1",
"wp wc payment_gateway update cod --enabled=true --user=1",
"wp option set woocommerce_task_list_hidden yes",
"wp option set woocommerce_onboarding_profile_completed yes"
],
"globalTeardown": [
"wp site empty --yes",
"wp plugin deactivate wordpress-importer"
]
}
}
}
Minimal Test Package
{
"package": "your-extension-slug/smoke-tests",
"package_type": "test",
"test": {
"phases": {
"run": ["npm test"]
},
"results": {
"ctrf-json": "./ctrf.json",
"blob-dir": "./artifacts"
}
}
}
Minimal Utility Package
{
"package": "woocommerce/disable-onboarding",
"package_type": "utility",
"test": {
"phases": {
"globalSetup": [
"wp option set woocommerce_task_list_hidden yes"
]
}
}
}