| name | woo-marketplace-qit |
| description | Skill for quality testing of plugins for the WooCommerce.com Marketplace. Covers all QIT (Quality Insights Toolkit) test suites (Activation, Security, PHPStan, PHP Compatibility, Malware, Woo E2E, Woo API), how to run them locally, GitHub Actions CI integration, writing custom E2E tests, and coding standards compliance via PHPCS/ESLint. Use when keywords like "QIT", "marketplace testing", "quality testing", "security scan", "PHPStan", "Woo E2E", "plugin testing", "pre-submission", "pre-submission check", "PHPCS", or "coding standards" appear. Also reference proactively when designing CI/CD pipelines or test strategies for WooCommerce plugins.
|
WooCommerce Marketplace QIT & Quality Assurance
QIT (Quality Insights Toolkit) is a testing platform developed by WooCommerce that acts as a
quality gate for both initial marketplace submissions and ongoing version updates. Since failing
any test blocks the submission from progressing, it is essential to integrate QIT from the
start of development.
QIT Test Suite Overview
Managed tests required by the marketplace:
| Test | Description | Required |
|---|
| Activation Test | Verifies the plugin activates without errors or warnings in a clean WP+WC environment | ✅ |
| Security Test | Semgrep-based security scan and coding best practices check | ✅ |
| PHPStan Test | Static analysis to detect bugs and type errors | ✅ |
| PHP Compatibility Test | Compatibility across different PHP versions (8.3–8.5) | ✅ |
| Malware Test | Detection of malicious code | ✅ |
| Woo E2E Test | Runs WooCommerce Core E2E tests (Playwright) with the extension active | ✅ |
| Woo API Test | Runs WooCommerce Core API tests with the extension active | ✅ |
| Custom E2E Test | Playwright E2E tests written by the developer | Recommended |
Failing the Activation, Security, or Malware tests also blocks version update deployments.
QIT CLI Setup
Installation
composer require --dev woocommerce/qit-cli
Authentication
Authenticate with your WooCommerce.com Partner Developer account:
./vendor/bin/qit
Once logged in with your Vendor account, you can run QIT against plugins that have been
submitted to or are listed on the marketplace.
Basic Test Execution
./vendor/bin/qit run:activation my-extension --zip=./my-extension.zip
./vendor/bin/qit run:security my-extension --zip=./my-extension.zip
./vendor/bin/qit run:phpstan my-extension --zip=./my-extension.zip
./vendor/bin/qit run:phpcompatibility my-extension --zip=./my-extension.zip
./vendor/bin/qit run:malware my-extension --zip=./my-extension.zip
./vendor/bin/qit run:e2e my-extension --zip=./my-extension.zip
./vendor/bin/qit run:api my-extension --zip=./my-extension.zip
Environment Customization
./vendor/bin/qit run:e2e my-extension \
--zip=./my-extension.zip \
--php_version=8.3 \
--wordpress_version=7.0 \
--woocommerce_version=10.9
./vendor/bin/qit run:activation my-extension \
--zip=./my-extension.zip \
--with-extension=woocommerce-subscriptions \
--with-extension=woocommerce-payments
Compatibility Testing with Extension Sets
QIT provides sets of top marketplace extensions to simplify compatibility testing:
./vendor/bin/qit run:e2e my-extension \
--zip=./my-extension.zip \
--test-package=woocommerce/checkout-tests
Use this feature to fulfill the pre-submission checklist requirement of verifying compatibility
with top marketplace extensions.
Local Test Environment (No Authentication Required)
QIT's local test environment can be used without a WooCommerce.com connection:
./vendor/bin/qit run:e2e my-extension \
--zip=./my-extension.zip \
--local
Useful for rapid feedback loops during development. Note that installing premium marketplace
plugins into the test environment does require authentication.
Custom E2E Tests (Playwright)
QIT supports Playwright-based custom tests. By following the standardized format for test
packages, you can also participate in cross-plugin compatibility testing.
Test Structure
tests/
├── e2e/
│ ├── playwright.config.ts
│ ├── example.spec.ts
│ └── utils/
│ └── helpers.ts
Basic playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: '.',
timeout: 60000,
retries: 1,
use: {
baseURL: process.env.BASE_URL || 'http://localhost:8889',
storageState: process.env.STORAGE_STATE || undefined,
},
projects: [
{
name: 'chromium',
use: { browserName: 'chromium' },
},
],
});
Example: Settings Page Test
import { test, expect } from '@playwright/test';
test.describe( 'My Extension Settings', () => {
test.beforeEach( async ( { page } ) => {
await page.goto( '/wp-login.php' );
await page.fill( '#user_login', 'admin' );
await page.fill( '#user_pass', 'password' );
await page.click( '#wp-submit' );
await page.waitForURL( '**/wp-admin/**' );
});
test( 'settings page loads without errors', async ( { page } ) => {
await page.goto( '/wp-admin/admin.php?page=wc-settings&tab=my_extension' );
await expect( page.locator( '.woocommerce' ) ).toBeVisible();
const errors: string[] = [];
page.on( 'console', msg => {
if ( msg.type() === 'error' ) errors.push( msg.text() );
});
await page.waitForTimeout( 2000 );
expect( errors ).toHaveLength( 0 );
});
test( 'can save settings', async ( { page } ) => {
await page.goto( '/wp-admin/admin.php?page=wc-settings&tab=my_extension' );
await page.fill( '#my_extension_api_key', 'test-key-123' );
await page.click( '.woocommerce-save-button' );
await expect( page.locator( '.updated' ) ).toBeVisible();
const value = await page.inputValue( '#my_extension_api_key' );
expect( value ).toBe( 'test-key-123' );
});
});
Example: Checkout Flow Test
test.describe( 'Checkout Integration', () => {
test( 'extension feature works on block checkout', async ( { page } ) => {
await page.goto( '/shop/' );
await page.click( '.add_to_cart_button' );
await page.waitForTimeout( 1000 );
await page.goto( '/checkout/' );
await expect( page.locator( '.wc-block-checkout' ) ).toBeVisible();
await expect(
page.locator( '[data-block-name="my-extension/checkout-field"]' )
).toBeVisible();
});
});
Running Custom Tests with QIT
./vendor/bin/qit run:e2e my-extension \
--zip=./my-extension.zip \
--test-package=./tests/e2e
Coding Standards Configuration
PHPCS (PHP CodeSniffer)
{
"require-dev": {
"squizlabs/php_codesniffer": "^3.13.4",
"wp-coding-standards/wpcs": "^3.3",
"phpcompatibility/phpcompatibility-wp": "^2.1",
"dealerdirect/phpcodesniffer-composer-installer": "^1.0"
},
"scripts": {
"phpcs": "phpcs",
"phpcbf": "phpcbf"
}
}
Note: Stay on PHPCS 3.13.x. PHPCS 4.0 is released but WPCS 3.3.0 still
requires squizlabs/php_codesniffer ^3.13.4 and does not support PHPCS 4.0 —
upgrading PHPCS to 4.0 will break WordPress-Coding-Standards linting.
<?xml version="1.0"?>
<ruleset name="My Extension">
<description>PHPCS ruleset for WooCommerce Marketplace extension</description>
<file>.</file>
<exclude-pattern>vendor/*</exclude-pattern>
<exclude-pattern>node_modules/*</exclude-pattern>
<exclude-pattern>build/*</exclude-pattern>
<exclude-pattern>tests/*</exclude-pattern>
<arg name="extensions" value="php"/>
<arg name="colors"/>
<arg value="sp"/>
<rule ref="WordPress-Extra">
<exclude name="WordPress.Files.FileName.InvalidClassFileName"/>
<exclude name="WordPress.Files.FileName.NotHyphenatedLowercase"/>
</rule>
<rule ref="WordPress.WP.I18n">
<properties>
<property name="text_domain" type="array">
<element value="my-extension"/>
</property>
</properties>
</rule>
<config name="testVersion" value="8.3-8.5"/>
<rule ref="PHPCompatibilityWP"/>
<config name="minimum_supported_wp_version" value="6.7"/>
</ruleset>
PHPStan
# phpstan.neon
includes:
- vendor/phpstan/phpstan/conf/bleedingEdge.neon
parameters:
level: 5
paths:
- my-extension.php
- includes/
excludePaths:
- vendor/
- node_modules/
- build/
scanDirectories:
- vendor/woocommerce/
bootstrapFiles:
- vendor/autoload.php
ignoreErrors:
# WooCommerce dynamic methods
- '#Call to an undefined method WC_Order::#'
{
"require-dev": {
"phpstan/phpstan": "^2.2",
"phpstan/extension-installer": "^1.3",
"szepeviktor/phpstan-wordpress": "^2.0"
},
"scripts": {
"phpstan": "phpstan analyse --memory-limit=512M"
}
}
ESLint (JavaScript / TypeScript)
{
"extends": [
"plugin:@woocommerce/eslint-plugin/recommended"
],
"env": {
"browser": true,
"es2021": true
},
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"settings": {
"react": {
"version": "detect"
}
}
}
{
"devDependencies": {
"@woocommerce/eslint-plugin": "^2.2.0",
"@wordpress/scripts": "^32.0.0"
},
"scripts": {
"lint:js": "wp-scripts lint-js src/",
"lint:css": "wp-scripts lint-style src/**/*.scss",
"build": "wp-scripts build",
"start": "wp-scripts start"
}
}
GitHub Actions CI Integration
Basic CI Workflow
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
phpcs:
name: PHPCS
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
tools: composer, cs2pr
- run: composer install --no-progress
- run: composer phpcs -- --report=checkstyle | cs2pr
phpstan:
name: PHPStan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
- run: composer install --no-progress
- run: composer phpstan
eslint:
name: ESLint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: '24'
cache: 'npm'
- run: npm ci
- run: npm run lint:js
php-compatibility:
name: PHP Compatibility
runs-on: ubuntu-latest
strategy:
matrix:
php: ['8.3', '8.4', '8.5']
steps:
- uses: actions/checkout@v5
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
- run: composer install --no-progress
- run: |
./vendor/bin/phpcs \
--standard=PHPCompatibilityWP \
--runtime-set testVersion ${{ matrix.php }} \
--extensions=php \
--ignore=vendor/,node_modules/,build/ \
.
activation-test:
name: Activation Test
runs-on: ubuntu-latest
strategy:
matrix:
wc: ['10.9', 'latest']
php: ['8.3', '8.4', '8.5']
steps:
- uses: actions/checkout@v5
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
- uses: actions/setup-node@v5
with:
node-version: '24'
- run: npm ci && npm run build
- name: Install wp-env
run: npm -g install @wordpress/env
- name: Configure wp-env
run: |
cat > .wp-env.override.json << 'EOF'
{
"plugins": ["."],
"env": {
"tests": {
"phpVersion": "${{ matrix.php }}"
}
}
}
EOF
- name: Start wp-env
run: wp-env start
- name: Verify activation
run: |
wp-env run tests-cli wp plugin activate ${{ github.event.repository.name }}
wp-env run tests-cli wp plugin list --status=active --format=csv | grep ${{ github.event.repository.name }}
# Verify no PHP errors
wp-env run tests-cli wp eval "error_reporting(E_ALL); do_action('admin_init');" 2>&1 | grep -v "^$" && echo "OK" || exit 1
Integrating QIT with GitHub Actions
qit-tests:
name: QIT Tests
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v5
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
- run: composer install --no-progress
- name: Build ZIP
run: |
npm ci && npm run build
mkdir -p dist
zip -r dist/my-extension.zip . \
-x ".git/*" "node_modules/*" ".github/*" "tests/*" ".wp-env*"
- name: Run QIT Activation
env:
QIT_TOKEN: ${{ secrets.QIT_TOKEN }}
run: ./vendor/bin/qit run:activation my-extension --zip=dist/my-extension.zip
- name: Run QIT Security
env:
QIT_TOKEN: ${{ secrets.QIT_TOKEN }}
run: ./vendor/bin/qit run:security my-extension --zip=dist/my-extension.zip
Pre-Submission Quality Checklist
Verify all of the following before submitting:
Automated Tests
Compatibility Tests
Code Quality
UX