claude-plugin-wordpress-manager 1.5.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/.claude-plugin/plugin.json +2 -2
  2. package/CHANGELOG.md +97 -0
  3. package/README.md +27 -13
  4. package/agents/wp-accessibility-auditor.md +206 -0
  5. package/agents/wp-content-strategist.md +18 -0
  6. package/agents/wp-deployment-engineer.md +34 -2
  7. package/agents/wp-performance-optimizer.md +12 -0
  8. package/agents/wp-security-auditor.md +20 -0
  9. package/agents/wp-security-hardener.md +266 -0
  10. package/agents/wp-site-manager.md +14 -0
  11. package/agents/wp-test-engineer.md +207 -0
  12. package/docs/guides/INDEX.md +46 -0
  13. package/docs/guides/wp-blog.md +590 -0
  14. package/docs/guides/wp-design-system.md +976 -0
  15. package/docs/guides/wp-ecommerce.md +786 -0
  16. package/docs/guides/wp-landing-page.md +762 -0
  17. package/docs/guides/wp-portfolio.md +713 -0
  18. package/docs/plans/2026-02-27-design-system-guide-design.md +30 -0
  19. package/docs/plans/2026-02-27-site-type-guides-design.md +44 -0
  20. package/package.json +2 -2
  21. package/skills/wordpress-router/references/decision-tree.md +12 -2
  22. package/skills/wp-accessibility/SKILL.md +170 -0
  23. package/skills/wp-accessibility/references/a11y-audit-tools.md +248 -0
  24. package/skills/wp-accessibility/references/a11y-testing.md +222 -0
  25. package/skills/wp-accessibility/references/block-a11y.md +247 -0
  26. package/skills/wp-accessibility/references/interactive-a11y.md +272 -0
  27. package/skills/wp-accessibility/references/media-a11y.md +254 -0
  28. package/skills/wp-accessibility/references/theme-a11y.md +309 -0
  29. package/skills/wp-audit/SKILL.md +4 -0
  30. package/skills/wp-block-development/SKILL.md +5 -0
  31. package/skills/wp-block-themes/SKILL.md +4 -0
  32. package/skills/wp-e2e-testing/SKILL.md +186 -0
  33. package/skills/wp-e2e-testing/references/ci-integration.md +174 -0
  34. package/skills/wp-e2e-testing/references/jest-wordpress.md +114 -0
  35. package/skills/wp-e2e-testing/references/phpunit-wordpress.md +141 -0
  36. package/skills/wp-e2e-testing/references/playwright-wordpress.md +108 -0
  37. package/skills/wp-e2e-testing/references/test-data-generation.md +127 -0
  38. package/skills/wp-e2e-testing/references/visual-regression.md +107 -0
  39. package/skills/wp-e2e-testing/references/wp-env-setup.md +97 -0
  40. package/skills/wp-e2e-testing/scripts/test_inspect.mjs +375 -0
  41. package/skills/wp-headless/SKILL.md +168 -0
  42. package/skills/wp-headless/references/api-layer-choice.md +160 -0
  43. package/skills/wp-headless/references/cors-config.md +245 -0
  44. package/skills/wp-headless/references/frontend-integration.md +331 -0
  45. package/skills/wp-headless/references/headless-auth.md +286 -0
  46. package/skills/wp-headless/references/webhooks.md +277 -0
  47. package/skills/wp-headless/references/wpgraphql.md +331 -0
  48. package/skills/wp-headless/scripts/headless_inspect.mjs +321 -0
  49. package/skills/wp-i18n/SKILL.md +170 -0
  50. package/skills/wp-i18n/references/js-i18n.md +201 -0
  51. package/skills/wp-i18n/references/multilingual-setup.md +219 -0
  52. package/skills/wp-i18n/references/php-i18n.md +196 -0
  53. package/skills/wp-i18n/references/rtl-support.md +206 -0
  54. package/skills/wp-i18n/references/translation-workflow.md +178 -0
  55. package/skills/wp-i18n/references/wpcli-i18n.md +177 -0
  56. package/skills/wp-i18n/scripts/i18n_inspect.mjs +330 -0
  57. package/skills/wp-interactivity-api/SKILL.md +4 -0
  58. package/skills/wp-plugin-development/SKILL.md +6 -0
  59. package/skills/wp-rest-api/SKILL.md +4 -0
  60. package/skills/wp-security/SKILL.md +179 -0
  61. package/skills/wp-security/references/api-restriction.md +147 -0
  62. package/skills/wp-security/references/authentication-hardening.md +105 -0
  63. package/skills/wp-security/references/filesystem-hardening.md +105 -0
  64. package/skills/wp-security/references/http-headers.md +105 -0
  65. package/skills/wp-security/references/incident-response.md +144 -0
  66. package/skills/wp-security/references/user-capabilities.md +115 -0
  67. package/skills/wp-security/references/wp-config-security.md +129 -0
  68. package/skills/wp-security/scripts/security_inspect.mjs +393 -0
@@ -0,0 +1,309 @@
1
+ # Theme Accessibility
2
+
3
+ Use this file when building accessible WordPress themes and achieving `accessibility-ready` tag compliance.
4
+
5
+ ## accessibility-ready tag requirements
6
+
7
+ WordPress.org requires these for the `accessibility-ready` tag:
8
+
9
+ 1. **Skip links** — must be the first focusable element
10
+ 2. **Keyboard navigation** — all interactive elements reachable and operable
11
+ 3. **Contrast ratios** — text meets WCAG 2.1 AA (4.5:1 normal, 3:1 large)
12
+ 4. **Resize text** — content usable at 200% zoom
13
+ 5. **Form labels** — all inputs have associated labels
14
+ 6. **Image alt text** — all images have alt attributes (decorative = `alt=""`)
15
+ 7. **Visible focus** — focus indicators on all interactive elements
16
+ 8. **Landmarks** — proper use of HTML5 landmark elements
17
+ 9. **No autoplay** — media must not autoplay with sound
18
+
19
+ ## Landmarks and page structure
20
+
21
+ ```html
22
+ <body <?php body_class(); ?>>
23
+ <?php wp_body_open(); ?>
24
+
25
+ <a class="skip-link screen-reader-text" href="#primary">
26
+ <?php esc_html_e('Skip to content', 'my-theme'); ?>
27
+ </a>
28
+
29
+ <header id="masthead" role="banner">
30
+ <nav id="site-navigation" role="navigation"
31
+ aria-label="<?php esc_attr_e('Primary Menu', 'my-theme'); ?>">
32
+ <?php wp_nav_menu(['theme_location' => 'primary']); ?>
33
+ </nav>
34
+ </header>
35
+
36
+ <main id="primary" role="main">
37
+ <!-- page content -->
38
+ </main>
39
+
40
+ <aside id="sidebar" role="complementary"
41
+ aria-label="<?php esc_attr_e('Sidebar', 'my-theme'); ?>">
42
+ <?php dynamic_sidebar('sidebar-1'); ?>
43
+ </aside>
44
+
45
+ <footer id="colophon" role="contentinfo">
46
+ <!-- footer content -->
47
+ </footer>
48
+ </body>
49
+ ```
50
+
51
+ ## Skip link CSS
52
+
53
+ ```css
54
+ .skip-link {
55
+ position: absolute;
56
+ top: -100%;
57
+ left: 0;
58
+ z-index: 999999;
59
+ padding: 0.5rem 1rem;
60
+ background: #000;
61
+ color: #fff;
62
+ text-decoration: none;
63
+ font-size: 1rem;
64
+ }
65
+
66
+ .skip-link:focus {
67
+ top: 0;
68
+ clip: auto;
69
+ clip-path: none;
70
+ width: auto;
71
+ height: auto;
72
+ }
73
+ ```
74
+
75
+ ## Focus indicators
76
+
77
+ ```css
78
+ /* Visible focus for all interactive elements */
79
+ a:focus,
80
+ button:focus,
81
+ input:focus,
82
+ select:focus,
83
+ textarea:focus,
84
+ [tabindex]:focus {
85
+ outline: 2px solid var(--wp--preset--color--primary, #0073aa);
86
+ outline-offset: 2px;
87
+ }
88
+
89
+ /* Remove default only if replacing with custom indicator */
90
+ a:focus-visible {
91
+ outline: 3px solid #0073aa;
92
+ outline-offset: 2px;
93
+ border-radius: 2px;
94
+ }
95
+ ```
96
+
97
+ Never use `outline: none` without providing an alternative visible focus indicator.
98
+
99
+ ## Navigation menus
100
+
101
+ ### Menu walker with ARIA
102
+
103
+ ```php
104
+ // In header.php or navigation template
105
+ wp_nav_menu([
106
+ 'theme_location' => 'primary',
107
+ 'container' => 'nav',
108
+ 'container_class' => 'main-navigation',
109
+ 'container_id' => 'primary-menu',
110
+ 'items_wrap' => '<ul id="%1$s" class="%2$s" role="menubar">%3$s</ul>',
111
+ ]);
112
+ ```
113
+
114
+ ### Dropdown submenus
115
+
116
+ ```js
117
+ // Accessible submenu toggle
118
+ document.querySelectorAll('.menu-item-has-children > a').forEach((link) => {
119
+ const submenu = link.nextElementSibling;
120
+ const toggle = document.createElement('button');
121
+ toggle.className = 'submenu-toggle';
122
+ toggle.setAttribute('aria-expanded', 'false');
123
+ toggle.setAttribute('aria-label',
124
+ link.textContent.trim() + ' submenu');
125
+ toggle.innerHTML = '<span class="screen-reader-text">Toggle submenu</span>';
126
+
127
+ toggle.addEventListener('click', () => {
128
+ const expanded = toggle.getAttribute('aria-expanded') === 'true';
129
+ toggle.setAttribute('aria-expanded', String(!expanded));
130
+ submenu.hidden = expanded;
131
+ });
132
+
133
+ link.after(toggle);
134
+ });
135
+ ```
136
+
137
+ ## Forms
138
+
139
+ ```html
140
+ <!-- Every input needs a label -->
141
+ <label for="search-input">
142
+ <?php esc_html_e('Search', 'my-theme'); ?>
143
+ </label>
144
+ <input type="search" id="search-input" name="s"
145
+ placeholder="<?php esc_attr_e('Search...', 'my-theme'); ?>">
146
+
147
+ <!-- Group related fields -->
148
+ <fieldset>
149
+ <legend><?php esc_html_e('Contact Information', 'my-theme'); ?></legend>
150
+ <label for="name"><?php esc_html_e('Name', 'my-theme'); ?></label>
151
+ <input type="text" id="name" name="name" required
152
+ aria-required="true">
153
+ <label for="email"><?php esc_html_e('Email', 'my-theme'); ?></label>
154
+ <input type="email" id="email" name="email" required
155
+ aria-required="true">
156
+ </fieldset>
157
+
158
+ <!-- Error messages -->
159
+ <input type="email" id="email" name="email"
160
+ aria-describedby="email-error" aria-invalid="true">
161
+ <p id="email-error" class="form-error" role="alert">
162
+ <?php esc_html_e('Please enter a valid email address.', 'my-theme'); ?>
163
+ </p>
164
+ ```
165
+
166
+ ## Images in themes
167
+
168
+ ```php
169
+ <!-- Content images: meaningful alt -->
170
+ <img src="<?php echo esc_url($image_url); ?>"
171
+ alt="<?php echo esc_attr($image_alt); ?>">
172
+
173
+ <!-- Decorative images: empty alt -->
174
+ <img src="decorative-border.png" alt="" role="presentation">
175
+
176
+ <!-- Background images with text: ensure contrast or provide alt -->
177
+ <div class="hero" style="background-image: url(hero.jpg);"
178
+ role="img" aria-label="<?php esc_attr_e('Mountain landscape', 'my-theme'); ?>">
179
+ <h1><?php esc_html_e('Welcome', 'my-theme'); ?></h1>
180
+ </div>
181
+ ```
182
+
183
+ ### Post thumbnails
184
+
185
+ ```php
186
+ // Theme support with alt text
187
+ if (has_post_thumbnail()) {
188
+ the_post_thumbnail('large', [
189
+ 'alt' => get_the_title(), // fallback if no alt set
190
+ ]);
191
+ }
192
+ ```
193
+
194
+ ## Color and typography
195
+
196
+ ```css
197
+ /* Ensure readable text sizes */
198
+ body {
199
+ font-size: 1rem; /* At least 16px */
200
+ line-height: 1.5; /* WCAG recommends 1.5 for body text */
201
+ }
202
+
203
+ /* Respect user preferences */
204
+ @media (prefers-reduced-motion: reduce) {
205
+ *,
206
+ *::before,
207
+ *::after {
208
+ animation-duration: 0.01ms !important;
209
+ transition-duration: 0.01ms !important;
210
+ scroll-behavior: auto !important;
211
+ }
212
+ }
213
+
214
+ @media (prefers-contrast: more) {
215
+ :root {
216
+ --text-color: #000;
217
+ --bg-color: #fff;
218
+ --link-color: #00008b;
219
+ }
220
+ }
221
+ ```
222
+
223
+ ## Screen reader utilities
224
+
225
+ ```css
226
+ /* WordPress core screen-reader-text class */
227
+ .screen-reader-text {
228
+ border: 0;
229
+ clip: rect(1px, 1px, 1px, 1px);
230
+ clip-path: inset(50%);
231
+ height: 1px;
232
+ margin: -1px;
233
+ overflow: hidden;
234
+ padding: 0;
235
+ position: absolute !important;
236
+ width: 1px;
237
+ word-wrap: normal !important;
238
+ }
239
+
240
+ .screen-reader-text:focus {
241
+ background-color: #f1f1f1;
242
+ clip: auto !important;
243
+ clip-path: none;
244
+ display: block;
245
+ font-size: 0.875rem;
246
+ height: auto;
247
+ left: 5px;
248
+ line-height: normal;
249
+ padding: 15px 23px 14px;
250
+ text-decoration: none;
251
+ top: 5px;
252
+ width: auto;
253
+ z-index: 100000;
254
+ }
255
+ ```
256
+
257
+ ## theme.json accessibility settings
258
+
259
+ ```json
260
+ {
261
+ "settings": {
262
+ "color": {
263
+ "palette": [
264
+ {
265
+ "slug": "primary",
266
+ "color": "#0073aa",
267
+ "name": "Primary"
268
+ },
269
+ {
270
+ "slug": "foreground",
271
+ "color": "#1e1e1e",
272
+ "name": "Foreground"
273
+ },
274
+ {
275
+ "slug": "background",
276
+ "color": "#ffffff",
277
+ "name": "Background"
278
+ }
279
+ ]
280
+ },
281
+ "typography": {
282
+ "fluid": true,
283
+ "fontSizes": [
284
+ { "slug": "small", "size": "0.875rem", "name": "Small" },
285
+ { "slug": "medium", "size": "1rem", "name": "Medium" },
286
+ { "slug": "large", "size": "1.25rem", "name": "Large" }
287
+ ]
288
+ }
289
+ }
290
+ }
291
+ ```
292
+
293
+ Ensure all palette color combinations meet WCAG AA contrast ratios.
294
+
295
+ ## Verification
296
+
297
+ ```bash
298
+ # Test theme accessibility-ready requirements
299
+ npx @axe-core/cli https://localhost:8888/ --tags wcag2a,wcag2aa
300
+
301
+ # Check for missing alt attributes
302
+ curl -s https://site.com/ | grep -oP '<img[^>]*>' | grep -v 'alt='
303
+
304
+ # Check for skip link
305
+ curl -s https://site.com/ | grep -i "skip"
306
+
307
+ # Validate landmarks
308
+ curl -s https://site.com/ | grep -cE "<(main|nav|header|footer|aside|section)"
309
+ ```
@@ -112,3 +112,7 @@ Combine findings into a unified report with:
112
112
  - **`references/security-checklist.md`** - WordPress security audit checklist
113
113
  - **`references/performance-checklist.md`** - Performance analysis checklist
114
114
  - **`references/seo-checklist.md`** - SEO audit checklist
115
+
116
+ ## Related skills
117
+
118
+ - `wp-security` — Deep security hardening, filesystem permissions, HTTP headers, incident response procedures
@@ -174,3 +174,8 @@ If you’re uncertain about upstream behavior/version support, consult canonical
174
174
 
175
175
  - WordPress Developer Resources (Block Editor Handbook, Theme Handbook, Plugin Handbook)
176
176
  - Gutenberg repo docs for bleeding-edge behaviors
177
+
178
+ ## Related skills
179
+
180
+ - `wp-e2e-testing` — Playwright E2E tests, Jest unit tests for block JavaScript, wp-env test environments
181
+ - `wp-accessibility` — Block ARIA patterns, keyboard navigation, color contrast checks
@@ -116,3 +116,7 @@ Common issues:
116
116
  If upstream behavior is unclear, consult canonical docs:
117
117
 
118
118
  - Theme Handbook and Block Editor Handbook for `theme.json`, templates, patterns, and style variations.
119
+
120
+ ## Related skills
121
+
122
+ - `wp-accessibility` — Theme accessibility-ready requirements, skip links, focus indicators, WCAG compliance
@@ -0,0 +1,186 @@
1
+ ---
2
+ name: wp-e2e-testing
3
+ description: "Use when setting up, writing, or debugging WordPress tests: E2E with Playwright, unit tests with PHPUnit, JavaScript tests with Jest, visual regression, test data generation, wp-env test environment, and CI pipeline integration."
4
+ compatibility: "Targets WordPress 6.9+ (PHP 7.2.24+). Filesystem-based agent with bash + node. Some workflows require WP-CLI and Docker."
5
+ version: 1.0.0
6
+ source: "vinmor/wordpress-manager"
7
+ ---
8
+
9
+ # WP E2E Testing
10
+
11
+ ## When to use
12
+
13
+ Use this skill when the task involves WordPress testing workflows:
14
+
15
+ - Setting up a test suite from scratch for a WordPress plugin, theme, or block
16
+ - Writing E2E tests with Playwright against a running WordPress instance
17
+ - Adding PHPUnit tests for PHP code (hooks, filters, REST endpoints, custom post types)
18
+ - Writing Jest unit tests for JavaScript/React block code
19
+ - Debugging test failures in CI or locally
20
+ - Setting up a CI pipeline (GitHub Actions) for WordPress test automation
21
+ - Adding visual regression testing to catch unintended UI changes
22
+ - Generating test data and fixtures for reproducible test runs
23
+ - Configuring wp-env as a Docker-based test environment
24
+
25
+ ## Inputs required
26
+
27
+ - **Repo root**: current working directory or `--cwd` path
28
+ - **Project kind**: plugin, theme, or block (auto-detected via `detect_wp_project.mjs`)
29
+ - **Existing test setup**: which frameworks are already configured (auto-detected via `test_inspect.mjs`)
30
+ - **CI platform**: GitHub Actions is the primary target; adaptable to others
31
+
32
+ ## Procedure
33
+
34
+ ### 0) Detect existing test setup
35
+
36
+ Run the detection scripts to understand what is already in place:
37
+
38
+ ```bash
39
+ node skills/wp-e2e-testing/scripts/test_inspect.mjs
40
+ node skills/wp-project-triage/scripts/detect_wp_project.mjs
41
+ ```
42
+
43
+ The `test_inspect.mjs` script outputs JSON with:
44
+ - `frameworks` — which test frameworks are configured (Playwright, Jest, PHPUnit, visual regression)
45
+ - `testEnvironment` — whether wp-env and Docker are available
46
+ - `ci` — whether CI workflows exist and which platform
47
+ - `summary` — boolean flags for quick decision-making
48
+
49
+ Use this output to skip steps that are already complete and focus on gaps.
50
+
51
+ ### 1) Choose testing strategy by project kind
52
+
53
+ Different WordPress project types need different testing approaches:
54
+
55
+ | Project kind | E2E (Playwright) | Unit JS (Jest) | Unit PHP (PHPUnit) | Visual regression |
56
+ |-------------|:-:|:-:|:-:|:-:|
57
+ | Plugin (classic) | Optional | If has JS | Recommended | Optional |
58
+ | Plugin (block) | Recommended | Recommended | Recommended | Recommended |
59
+ | Theme (classic) | Optional | Rare | Optional | Recommended |
60
+ | Theme (block/FSE) | Recommended | If has JS | Optional | Recommended |
61
+ | Gutenberg contrib | Required | Required | Required | Required |
62
+
63
+ **General rule**: if the project has a user-facing UI, add E2E tests. If it has PHP logic (hooks, filters, REST), add PHPUnit. If it has JS/React, add Jest. If appearance matters, add visual regression.
64
+
65
+ ### 2) Set up test environment (wp-env)
66
+
67
+ wp-env provides a Docker-based WordPress instance purpose-built for testing. It spins up two environments: development (port 8888) and tests (port 8889).
68
+
69
+ Key steps:
70
+ 1. Ensure Docker is running (`docker info`)
71
+ 2. Create or verify `.wp-env.json` in the project root
72
+ 3. Start the environment with `npx wp-env start`
73
+ 4. Verify with `npx wp-env run tests-cli wp option get siteurl`
74
+
75
+ The tests environment is isolated and can be reset without affecting development data. PHPUnit runs inside the tests container. Playwright connects to the development or tests URL.
76
+
77
+ Read: `references/wp-env-setup.md`
78
+
79
+ ### 3) E2E tests with Playwright
80
+
81
+ WordPress provides `@wordpress/e2e-test-utils-playwright` which wraps Playwright with WordPress-specific utilities: authenticated admin sessions, block editor helpers, REST API seeding.
82
+
83
+ Key steps:
84
+ 1. Install Playwright and WP utilities
85
+ 2. Configure `playwright.config.ts` with WordPress base URL
86
+ 3. Write tests using `admin`, `editor`, and `requestUtils` fixtures
87
+ 4. Run with `npx wp-scripts test-playwright` or `npx playwright test`
88
+
89
+ Read: `references/playwright-wordpress.md`
90
+
91
+ ### 4) JavaScript unit tests with Jest
92
+
93
+ `@wordpress/scripts` bundles a preconfigured Jest setup. It handles JSX/TSX transforms, WordPress global mocks, and module resolution.
94
+
95
+ Key steps:
96
+ 1. Ensure `@wordpress/scripts` is a devDependency
97
+ 2. Add a `test-unit-js` script to package.json (or use the default)
98
+ 3. Create test files alongside source (`*.test.js`) or in `__tests__/`
99
+ 4. Mock WordPress globals (`wp`, `jQuery`) as needed
100
+ 5. Run with `npx wp-scripts test-unit-js`
101
+
102
+ Read: `references/jest-wordpress.md`
103
+
104
+ ### 5) PHP unit tests with PHPUnit
105
+
106
+ WordPress ships a PHPUnit test bootstrapper. The `wp scaffold plugin-tests` WP-CLI command generates the full scaffolding.
107
+
108
+ Key steps:
109
+ 1. Scaffold test files with `wp scaffold plugin-tests my-plugin`
110
+ 2. Extend `WP_UnitTestCase` for WordPress-aware tests
111
+ 3. Use `set_up()` and `tear_down()` for test lifecycle
112
+ 4. Test hooks, filters, REST endpoints, and custom post types
113
+ 5. Run with `npx wp-env run tests-cli --env-cwd=wp-content/plugins/my-plugin phpunit`
114
+
115
+ Read: `references/phpunit-wordpress.md`
116
+
117
+ ### 6) Visual regression testing
118
+
119
+ Screenshot comparison catches unintended UI changes. Playwright's built-in `toHaveScreenshot()` matcher is the simplest approach for WordPress projects already using Playwright.
120
+
121
+ Key steps:
122
+ 1. Add screenshot assertions to existing Playwright tests
123
+ 2. Generate baseline screenshots on the main branch
124
+ 3. Configure threshold tolerance for acceptable pixel differences
125
+ 4. Store baselines in the repository or as CI artifacts
126
+ 5. Review diffs on failure before updating baselines
127
+
128
+ Read: `references/visual-regression.md`
129
+
130
+ ### 7) Test data and fixtures
131
+
132
+ Reproducible tests need predictable data. WordPress provides factory methods for PHP tests and REST API utilities for E2E tests.
133
+
134
+ Key steps:
135
+ 1. Use `self::factory()->post->create()` in PHPUnit tests
136
+ 2. Use `requestUtils.createPost()` in Playwright E2E tests
137
+ 3. Seed bulk data via WP-CLI (`wp post generate`)
138
+ 4. Clean up after each test to prevent state leakage
139
+
140
+ Read: `references/test-data-generation.md`
141
+
142
+ ### 8) CI pipeline integration
143
+
144
+ GitHub Actions is the standard CI platform for WordPress projects. A typical pipeline runs PHPUnit across a PHP version matrix, Jest for JS tests, and Playwright for E2E.
145
+
146
+ Key steps:
147
+ 1. Create `.github/workflows/tests.yml`
148
+ 2. Add MySQL service container for PHPUnit
149
+ 3. Define a test matrix for PHP and WP version combinations
150
+ 4. Cache node_modules and Composer vendor
151
+ 5. Upload Playwright traces and screenshots as artifacts on failure
152
+
153
+ Read: `references/ci-integration.md`
154
+
155
+ ## Verification
156
+
157
+ After completing the setup, verify:
158
+
159
+ - `npx wp-scripts test-unit-js` passes (if Jest tests exist)
160
+ - `npx wp-env run tests-cli --env-cwd=wp-content/plugins/<plugin> phpunit` passes (if PHPUnit tests exist)
161
+ - `npx wp-scripts test-playwright` passes (if E2E tests exist)
162
+ - Visual regression baselines are generated and stored
163
+ - CI workflow runs green on push and pull request events
164
+ - Test coverage meets project threshold (aim for 80%+ on critical paths)
165
+
166
+ ## Failure modes / debugging
167
+
168
+ - **wp-env fails to start**: check Docker is running (`docker info`), check port conflicts (`lsof -i :8888`), try `npx wp-env destroy` then `npx wp-env start`
169
+ - **Playwright tests timeout**: increase `timeout` in `playwright.config.ts`, ensure wp-env is fully started before tests run, check `baseURL` matches the running instance
170
+ - **PHPUnit "No tests executed"**: verify `phpunit.xml` points to the correct test directory, ensure test class extends `WP_UnitTestCase`, ensure method names start with `test_`
171
+ - **Jest "Cannot find module"**: check `moduleNameMapper` in jest config, ensure `@wordpress/scripts` is installed, run `npm install` to refresh dependencies
172
+ - **Visual regression false positives**: increase pixel threshold, mask dynamic elements (timestamps, ads), use consistent viewport sizes, disable animations in test config
173
+ - **CI MySQL connection refused**: ensure the `mysql` service container is healthy before running PHPUnit, add a wait step or health check
174
+ - **"Class WP_UnitTestCase not found"**: the test bootstrap is missing or the WordPress test library is not installed; re-run `bin/install-wp-tests.sh` or use wp-env which handles this automatically
175
+
176
+ ## Escalation
177
+
178
+ - For Gutenberg-specific testing: https://developer.wordpress.org/block-editor/contributors/code/testing-overview/
179
+ - For @wordpress/scripts: https://developer.wordpress.org/block-editor/reference-guides/packages/packages-scripts/
180
+ - For wp-env: https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/
181
+ - For Playwright WP utilities: https://developer.wordpress.org/block-editor/reference-guides/packages/packages-e2e-test-utils-playwright/
182
+ - For PHPUnit with WordPress: https://make.wordpress.org/core/handbook/testing/automated-testing/phpunit/
183
+
184
+ ## Recommended Agent
185
+
186
+ For hands-on test execution, debugging, and CI setup, use the **`wp-test-engineer`** agent.
@@ -0,0 +1,174 @@
1
+ # CI Pipeline Integration for WordPress Tests
2
+
3
+ Use this file when setting up GitHub Actions (or similar CI) for WordPress test automation.
4
+
5
+ ## GitHub Actions workflow
6
+
7
+ ```yaml
8
+ # .github/workflows/tests.yml
9
+ name: Tests
10
+
11
+ on:
12
+ push:
13
+ branches: [main]
14
+ pull_request:
15
+ branches: [main]
16
+
17
+ jobs:
18
+ php-tests:
19
+ runs-on: ubuntu-latest
20
+ strategy:
21
+ matrix:
22
+ php: ['8.1', '8.2', '8.3']
23
+ wp: ['6.8', '6.9']
24
+ services:
25
+ mysql:
26
+ image: mysql:8.0
27
+ env:
28
+ MYSQL_ROOT_PASSWORD: root
29
+ MYSQL_DATABASE: wordpress_test
30
+ ports: ['3306:3306']
31
+ options: >-
32
+ --health-cmd="mysqladmin ping"
33
+ --health-interval=10s
34
+ --health-timeout=5s
35
+ --health-retries=5
36
+
37
+ steps:
38
+ - uses: actions/checkout@v4
39
+
40
+ - name: Setup PHP
41
+ uses: shivammathur/setup-php@v2
42
+ with:
43
+ php-version: ${{ matrix.php }}
44
+ extensions: mysqli
45
+ coverage: xdebug
46
+
47
+ - name: Cache Composer
48
+ uses: actions/cache@v4
49
+ with:
50
+ path: vendor
51
+ key: composer-${{ hashFiles('composer.lock') }}
52
+
53
+ - name: Install dependencies
54
+ run: composer install --no-interaction
55
+
56
+ - name: Install WP test suite
57
+ run: bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1 ${{ matrix.wp }}
58
+
59
+ - name: Run PHPUnit
60
+ run: vendor/bin/phpunit
61
+
62
+ js-tests:
63
+ runs-on: ubuntu-latest
64
+ steps:
65
+ - uses: actions/checkout@v4
66
+
67
+ - name: Setup Node.js
68
+ uses: actions/setup-node@v4
69
+ with:
70
+ node-version: 20
71
+ cache: npm
72
+
73
+ - name: Install dependencies
74
+ run: npm ci
75
+
76
+ - name: Run Jest
77
+ run: npx wp-scripts test-unit-js --ci --coverage
78
+
79
+ e2e-tests:
80
+ runs-on: ubuntu-latest
81
+ steps:
82
+ - uses: actions/checkout@v4
83
+
84
+ - name: Setup Node.js
85
+ uses: actions/setup-node@v4
86
+ with:
87
+ node-version: 20
88
+ cache: npm
89
+
90
+ - name: Install dependencies
91
+ run: npm ci
92
+
93
+ - name: Install Playwright browsers
94
+ run: npx playwright install chromium --with-deps
95
+
96
+ - name: Start wp-env
97
+ run: npx wp-env start
98
+
99
+ - name: Run Playwright tests
100
+ run: npx wp-scripts test-playwright
101
+
102
+ - name: Upload artifacts on failure
103
+ uses: actions/upload-artifact@v4
104
+ if: failure()
105
+ with:
106
+ name: playwright-artifacts
107
+ path: artifacts/
108
+ retention-days: 7
109
+ ```
110
+
111
+ ## Caching strategies
112
+
113
+ ```yaml
114
+ # Node modules
115
+ - uses: actions/cache@v4
116
+ with:
117
+ path: ~/.npm
118
+ key: npm-${{ hashFiles('package-lock.json') }}
119
+
120
+ # Playwright browsers
121
+ - uses: actions/cache@v4
122
+ with:
123
+ path: ~/.cache/ms-playwright
124
+ key: playwright-${{ hashFiles('package-lock.json') }}
125
+
126
+ # Docker images for wp-env
127
+ - uses: ScribeMD/docker-cache@0.5.0
128
+ with:
129
+ key: docker-${{ hashFiles('.wp-env.json') }}
130
+ ```
131
+
132
+ ## Parallel test execution
133
+
134
+ Split Playwright tests across multiple workers:
135
+
136
+ ```yaml
137
+ e2e-tests:
138
+ strategy:
139
+ matrix:
140
+ shard: [1, 2, 3]
141
+ steps:
142
+ # ...
143
+ - run: npx playwright test --shard=${{ matrix.shard }}/3
144
+ ```
145
+
146
+ ## PHPUnit without wp-env (standalone)
147
+
148
+ For projects that don't use wp-env, the `install-wp-tests.sh` script sets up the WP test suite:
149
+
150
+ ```bash
151
+ bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1 latest true
152
+ ```
153
+
154
+ Arguments: `db_name db_user db_pass db_host wp_version skip_db_create`
155
+
156
+ ## Conditional jobs
157
+
158
+ Run expensive E2E tests only when relevant files change:
159
+
160
+ ```yaml
161
+ e2e-tests:
162
+ if: |
163
+ contains(github.event.pull_request.labels.*.name, 'e2e') ||
164
+ github.ref == 'refs/heads/main'
165
+ ```
166
+
167
+ ## Best practices
168
+
169
+ - Run PHPUnit with matrix strategy for PHP/WP version coverage
170
+ - Cache aggressively (npm, Composer, Playwright browsers, Docker)
171
+ - Upload test artifacts (traces, screenshots) on failure for debugging
172
+ - Use `--ci` flag for Jest to disable interactive mode
173
+ - Set reasonable timeouts to catch hanging tests early
174
+ - Run lint/format checks as a separate job (fast fail)