docs(wpmc S6): implementation plan for CI + QA checklist
This commit is contained in:
@@ -0,0 +1,600 @@
|
|||||||
|
# S6 — CI workflow + Manual QA Checklist Implementation Plan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** Add Gitea Actions CI workflow that runs PHPUnit on push/PR, write a manual QA checklist covering all S2-S5 acceptance criteria from cp-cw4, and update README with testing instructions.
|
||||||
|
|
||||||
|
**Architecture:** Three documentation/config artifacts. No PHP code. No new tests. The existing 98-test Brain Monkey suite covers all functional areas at call-signature level; S6 adds infrastructure (CI) and human verification (manual checklist) to close out the testing story.
|
||||||
|
|
||||||
|
**Tech Stack:** Gitea Actions (GitHub-Actions-compatible YAML), Markdown, existing PHPUnit suite untouched.
|
||||||
|
|
||||||
|
**Spec:** `docs/superpowers/specs/2026-05-16-s6-ci-qa-checklist-design.md`
|
||||||
|
**Beads:** `cp-la7`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Working Directory
|
||||||
|
|
||||||
|
```
|
||||||
|
/Users/vladimirbryzgalov/Yandex.Disk.localized/Работа/Сайты/+Разработка сайтов+/Плагины Wordpress/wp-multi-city
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
wp-multi-city/
|
||||||
|
├── .gitea/workflows/test.yml # CREATE — Gitea Actions CI workflow
|
||||||
|
├── docs/QA-CHECKLIST.md # CREATE — 13-section manual QA checklist
|
||||||
|
└── README.md # MODIFY — Testing section + roadmap S6=done
|
||||||
|
```
|
||||||
|
|
||||||
|
No PHP changes. No phpunit changes. Existing 98 tests must remain green throughout.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 1: Gitea Actions CI workflow
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `.gitea/workflows/test.yml`
|
||||||
|
|
||||||
|
- [ ] **Step 1.1: Create the workflow file**
|
||||||
|
|
||||||
|
Create directory + file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p "/Users/vladimirbryzgalov/Yandex.Disk.localized/Работа/Сайты/+Разработка сайтов+/Плагины Wordpress/wp-multi-city/.gitea/workflows"
|
||||||
|
```
|
||||||
|
|
||||||
|
Write `.gitea/workflows/test.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
phpunit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup PHP 8.0
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: '8.0'
|
||||||
|
coverage: none
|
||||||
|
tools: composer:v2
|
||||||
|
|
||||||
|
- name: Cache Composer dependencies
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: vendor
|
||||||
|
key: ${{ runner.os }}-php8.0-${{ hashFiles('composer.json') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-php8.0-
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: composer install --no-progress --prefer-dist --no-interaction
|
||||||
|
|
||||||
|
- name: Run PHPUnit
|
||||||
|
run: vendor/bin/phpunit
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 1.2: Verify YAML syntax**
|
||||||
|
|
||||||
|
Check the file parses as valid YAML using PHP:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "/Users/vladimirbryzgalov/Yandex.Disk.localized/Работа/Сайты/+Разработка сайтов+/Плагины Wordpress/wp-multi-city"
|
||||||
|
php -r 'var_dump(yaml_parse_file(".gitea/workflows/test.yml"));' 2>&1 | head -20
|
||||||
|
```
|
||||||
|
|
||||||
|
If the `yaml` PHP extension is not installed, fall back to a Python check:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -c "import yaml; yaml.safe_load(open('.gitea/workflows/test.yml'))" && echo OK
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: parsed structure dumped or `OK` printed. If neither tool is available, eyeball-check the indentation against the source above (Gitea Actions tolerates indentation errors poorly).
|
||||||
|
|
||||||
|
- [ ] **Step 1.3: Verify existing tests still green**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "/Users/vladimirbryzgalov/Yandex.Disk.localized/Работа/Сайты/+Разработка сайтов+/Плагины Wordpress/wp-multi-city"
|
||||||
|
vendor/bin/phpunit
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: OK (98 tests, 175 assertions). The CI file shouldn't affect runtime tests — this is a sanity check that no accidental file move broke the suite.
|
||||||
|
|
||||||
|
- [ ] **Step 1.4: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "/Users/vladimirbryzgalov/Yandex.Disk.localized/Работа/Сайты/+Разработка сайтов+/Плагины Wordpress/wp-multi-city"
|
||||||
|
git add .gitea/workflows/test.yml
|
||||||
|
git commit -m "ci(wpmc S6): Gitea Actions workflow for PHPUnit on push/PR"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 2: Manual QA checklist
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `docs/QA-CHECKLIST.md`
|
||||||
|
|
||||||
|
- [ ] **Step 2.1: Write the full checklist**
|
||||||
|
|
||||||
|
Create `docs/QA-CHECKLIST.md` with this exact content:
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
# WP Multi City — Manual QA Checklist
|
||||||
|
|
||||||
|
End-to-end verification against a real WordPress installation. Run through every section before any release. Each section maps to a specific acceptance criterion from the MVP epic (`cp-cw4`).
|
||||||
|
|
||||||
|
**Test environment:**
|
||||||
|
- WordPress 6.0+ (clean install, no other plugins beyond ACF Pro)
|
||||||
|
- PHP 8.0+
|
||||||
|
- Advanced Custom Fields Pro 6.0+ activated
|
||||||
|
|
||||||
|
**Tester:** ______________ **Date:** ______________ **Plugin version:** ______________
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Plugin activation
|
||||||
|
|
||||||
|
**cp-cw4 acceptance:** "Плагин активируется на чистом WP с ACF Pro"
|
||||||
|
|
||||||
|
Preconditions: clean WP 6.0+ with activated ACF Pro.
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Copy plugin to `wp-content/plugins/wp-multi-city/`.
|
||||||
|
2. Go to admin → Plugins → activate "WP Multi City".
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- No PHP errors in `debug.log` (with `WP_DEBUG=true`).
|
||||||
|
- No admin notice about missing ACF Pro.
|
||||||
|
- Admin menu shows: "Шорткоды" (top-level), "WP Multi City" (top-level).
|
||||||
|
|
||||||
|
- [ ] Section pass
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. ACF dependency notice
|
||||||
|
|
||||||
|
Preconditions: WP with ACF Pro **deactivated**.
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Deactivate ACF Pro.
|
||||||
|
2. Refresh admin.
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- Admin notice visible: "WP Multi City: требуется активный плагин Advanced Custom Fields Pro".
|
||||||
|
- No "Шорткоды" or "WP Multi City" menu items (plugin self-disabled).
|
||||||
|
|
||||||
|
After verification, reactivate ACF Pro for the rest of the checklist.
|
||||||
|
|
||||||
|
- [ ] Section pass
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Taxonomy `town` admin UI
|
||||||
|
|
||||||
|
**cp-cw4 acceptance:** "В админке создаётся taxonomy town"
|
||||||
|
|
||||||
|
Preconditions: §1 passed.
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Open admin → Шорткоды → Города.
|
||||||
|
2. Create term with slug `spb`, name "Санкт-Петербург".
|
||||||
|
3. Create term with slug `tyumen`, name "Тюмень".
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- Both terms appear in the list.
|
||||||
|
- No "Hierarchical" parent-picker (taxonomy is flat).
|
||||||
|
- No public archive page accessible at `/town/spb/` (404 expected — taxonomy is non-public).
|
||||||
|
|
||||||
|
- [ ] Section pass
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. CPT `shortcode-town` admin UI
|
||||||
|
|
||||||
|
**cp-cw4 acceptance:** "В админке создаётся CPT shortcode-town"
|
||||||
|
|
||||||
|
Preconditions: §3 passed.
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Open admin → Шорткоды → Добавить.
|
||||||
|
2. Observe the edit screen.
|
||||||
|
3. Set title "Shortcode #1", save as Published (or Draft).
|
||||||
|
4. Note the post ID (e.g., 42) from the URL.
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- Edit screen shows: title field + ACF repeater "Подстановки по городам" (`list_shortcode`) with two sub-fields "Город" (taxonomy dropdown of town terms) + "Значение" (textarea).
|
||||||
|
- No editor / content / featured-image fields (CPT `supports=['title']` only).
|
||||||
|
- Post saves successfully.
|
||||||
|
|
||||||
|
- [ ] Section pass
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Options page UI
|
||||||
|
|
||||||
|
Preconditions: §3 passed.
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Open admin → WP Multi City.
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- ACF options page renders with 4 fields:
|
||||||
|
- `main_town_slug` — taxonomy dropdown of town terms.
|
||||||
|
- `index_town_alt` — page picker.
|
||||||
|
- `page_unic` — repeater with 3 sub-fields (page_old, page_new, town).
|
||||||
|
- `page_no_rep` — repeater with 1 sub-field (link).
|
||||||
|
- Set `main_town_slug = spb` and save.
|
||||||
|
|
||||||
|
- [ ] Section pass
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Helper functions smoke
|
||||||
|
|
||||||
|
**cp-cw4 acceptance:** "Шаблоны темы могут вызвать current_town(), _alt_get_field()"
|
||||||
|
|
||||||
|
Preconditions: §5 passed. Create page "About" via admin → Pages → Add New, slug `about`, note ID (e.g., 10).
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Add this to `wp-content/themes/<active-theme>/functions.php` (or as a mu-plugin):
|
||||||
|
```php
|
||||||
|
add_action('wp_footer', function () {
|
||||||
|
error_log('wpmc_current_town: ' . var_export(wpmc_current_town(), true));
|
||||||
|
error_log('wpmc_remove_domain_link: ' . wpmc_remove_domain_link('https://example.com/foo/'));
|
||||||
|
$term = wpmc_get_term_by_slug('tyumen');
|
||||||
|
error_log('wpmc_get_term_by_slug: ' . ($term ? $term->slug : 'null'));
|
||||||
|
});
|
||||||
|
```
|
||||||
|
2. Open `/tyumen/about/` (front-end). Check `wp-content/debug.log`.
|
||||||
|
3. Open `/` (front-end). Check log again.
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- `/tyumen/about/` log: `wpmc_current_town: 'tyumen'`, `wpmc_remove_domain_link: '/foo/'`, `wpmc_get_term_by_slug: 'tyumen'`.
|
||||||
|
- `/` log: `wpmc_current_town: 'spb'` (from main_town_slug option fallback).
|
||||||
|
|
||||||
|
Clean up: remove the debug snippet from functions.php.
|
||||||
|
|
||||||
|
- [ ] Section pass
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. `[shortcode_dmr]` resolves by current town
|
||||||
|
|
||||||
|
**cp-cw4 acceptance:** "[shortcode_dmr id=N] подменяется на значение для текущего города"
|
||||||
|
|
||||||
|
Preconditions: §6 passed. Open the shortcode-town post created in §4 (ID=42). Add two rows to `list_shortcode`:
|
||||||
|
- Row 1: Город = spb, Значение = `СПб-текст`
|
||||||
|
- Row 2: Город = tyumen, Значение = `Тюмень-текст`
|
||||||
|
|
||||||
|
Save the shortcode-town post.
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Create page "Test", slug `test`, content: `[shortcode_dmr id=42]`. Publish.
|
||||||
|
2. Open `/tyumen/test/`.
|
||||||
|
3. Open `/test/` (no city prefix).
|
||||||
|
4. Open `/nonexistent-city/test/` (no matching term).
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- `/tyumen/test/` displays `Тюмень-текст`.
|
||||||
|
- `/test/` displays `СПб-текст` (current_town falls back to main_town_slug=spb).
|
||||||
|
- `/nonexistent-city/test/` displays `СПб-текст` (first segment not a town slug → main town fallback) or empty depending on permalink resolution.
|
||||||
|
|
||||||
|
- [ ] Section pass
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. URL router patches `$wp_query`
|
||||||
|
|
||||||
|
**cp-cw4 acceptance:** "На /{city-slug}/{page-slug}/ открывается соответствующая страница"
|
||||||
|
|
||||||
|
Preconditions: §6 passed (page About ID=10 exists). §5 with main_town_slug=spb.
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Open `/tyumen/about/`.
|
||||||
|
2. View page source (or template debug output) — check `get_queried_object_id()` value.
|
||||||
|
3. Open `/spb/about/`.
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- `/tyumen/about/` loads page About (id=10) content; `get_queried_object_id()` = 10.
|
||||||
|
- In a template, `get_query_var('town')` returns `'tyumen'`.
|
||||||
|
- `/spb/about/` returns 404 OR loads About — main town routing is a no-op (Router skips), so default WP rewrite rules govern.
|
||||||
|
|
||||||
|
- [ ] Section pass
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. `/{slug}/` root with `main_page_alt`
|
||||||
|
|
||||||
|
Preconditions: §8 passed. Create page "Главная Тюмень", slug `glavnaya-tyumen`, note ID (e.g., 20). On the `tyumen` term (admin → Шорткоды → Города → tyumen → Edit), set ACF field `main_page_alt` = 20. Save term.
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Open `/tyumen/`.
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- Page Главная Тюмень (id=20) loads.
|
||||||
|
- `is_front_page()` returns true in template.
|
||||||
|
- `get_queried_object_id()` returns 20.
|
||||||
|
|
||||||
|
- [ ] Section pass
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. `page_unic` clone swap
|
||||||
|
|
||||||
|
**cp-cw4 acceptance:** "На /{city-slug}/{page-slug}/ открывается соответствующая страница" (with clone)
|
||||||
|
|
||||||
|
Preconditions: §8 passed (page About ID=10 exists). Create clone page "About-Тюмень", slug `about-tyumen`, ID=21, content "Тюменский About-content".
|
||||||
|
|
||||||
|
In admin → WP Multi City → page_unic, add one row: page_old=10 (About), page_new=21 (About-Тюмень), town=tyumen. Save options.
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Open `/tyumen/about/`.
|
||||||
|
2. Inspect page content.
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- URL bar stays `/tyumen/about/`.
|
||||||
|
- Content rendered is "Тюменский About-content" (from page 21, the clone).
|
||||||
|
- `get_queried_object_id()` returns 21 (not 10).
|
||||||
|
|
||||||
|
- [ ] Section pass
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. URL filters — town prefix injection
|
||||||
|
|
||||||
|
**cp-cw4 acceptance:** (implied) Links in templates auto-prefix with city slug.
|
||||||
|
|
||||||
|
Preconditions: §8 passed. The active theme renders a primary navigation menu. Add menu items: link to `/uslugi/` (custom link), link to page About.
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Open `/tyumen/about/`.
|
||||||
|
2. Inspect HTML of menu items (view source). Inspect any ACF link field used by the theme. Add a template snippet that outputs `home_url('/contact/')` and `home_url('/tyumen/contact/')` separately.
|
||||||
|
3. Open `/` (main town context).
|
||||||
|
|
||||||
|
Expected on `/tyumen/about/`:
|
||||||
|
- Custom menu link `/uslugi/` rendered as `https://<host>/tyumen/uslugi/` (or `/tyumen/uslugi/`).
|
||||||
|
- About menu link (originally `/about/`) rendered with `/tyumen/` prefix.
|
||||||
|
- `home_url('/contact/')` returns `https://<host>/tyumen/contact/`.
|
||||||
|
- `home_url('/tyumen/contact/')` returns `https://<host>/tyumen/contact/` (no double-prefix).
|
||||||
|
- ACF link field `/internal/` value rendered as `/tyumen/internal/`.
|
||||||
|
- mailto: and tel: links unchanged.
|
||||||
|
- External `https://other-domain.com/` links unchanged.
|
||||||
|
|
||||||
|
Expected on `/`:
|
||||||
|
- All URLs unchanged (current_town == main_town_slug → no prefix).
|
||||||
|
|
||||||
|
- [ ] Section pass
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. `page_no_rep` exclusions
|
||||||
|
|
||||||
|
Preconditions: §11 passed. In admin → WP Multi City → page_no_rep, add row: link = `/privacy/`. Save. Create page "Privacy", slug `privacy`, ID=30.
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Open `/privacy/`.
|
||||||
|
2. Open `/tyumen/privacy/`.
|
||||||
|
3. Check menu/template link to `/privacy/` from a `/tyumen/...` context.
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- `/privacy/` loads page Privacy normally, no city routing.
|
||||||
|
- `/tyumen/privacy/` — Router does not patch `$wp_query` (path excluded); WP either 404s or falls back depending on rewrite rules.
|
||||||
|
- A link to `/privacy/` rendered from `/tyumen/about/` stays `/privacy/` (NOT prefixed to `/tyumen/privacy/`).
|
||||||
|
|
||||||
|
- [ ] Section pass
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. REST API URL
|
||||||
|
|
||||||
|
**cp-cw4 acceptance:** (implied) REST API URL correct under host alias / proxy.
|
||||||
|
|
||||||
|
Preconditions: REST API enabled (default).
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. In a template, add: `<?php echo esc_html(rest_url('wp/v2/posts')); ?>`. Render any front-end page.
|
||||||
|
2. Open the printed URL in browser or via curl.
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- Rendered URL: `https://<HTTP_HOST>/wp-json/wp/v2/posts` (HTTPS forced, HTTP_HOST used).
|
||||||
|
- HTTP request returns JSON array of posts (200 OK).
|
||||||
|
- If `HTTP_HOST` differs from `site_url()`'s host, the rendered URL prefers `HTTP_HOST`.
|
||||||
|
|
||||||
|
- [ ] Section pass
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Release sign-off
|
||||||
|
|
||||||
|
- [ ] All 13 sections passed
|
||||||
|
- [ ] PHPUnit suite green (`vendor/bin/phpunit` → OK 98 tests, 175 assertions)
|
||||||
|
- [ ] PHP lint clean (`for f in includes/*.php; do php -l "$f"; done` → "No syntax errors detected" for every file)
|
||||||
|
- [ ] Tested on WP 6.0+ with PHP 8.0+
|
||||||
|
- [ ] No PHP notices/warnings in `wp-content/debug.log`
|
||||||
|
|
||||||
|
**Tester signature:** ______________ **Date:** ______________
|
||||||
|
````
|
||||||
|
|
||||||
|
- [ ] **Step 2.2: Verify Markdown renders**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "/Users/vladimirbryzgalov/Yandex.Disk.localized/Работа/Сайты/+Разработка сайтов+/Плагины Wordpress/wp-multi-city"
|
||||||
|
wc -l docs/QA-CHECKLIST.md
|
||||||
|
head -30 docs/QA-CHECKLIST.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: file >150 lines, header section renders, first checkboxes visible. Markdown syntax is conventional Github/Gitea-flavored, no validation needed beyond visual review.
|
||||||
|
|
||||||
|
- [ ] **Step 2.3: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "/Users/vladimirbryzgalov/Yandex.Disk.localized/Работа/Сайты/+Разработка сайтов+/Плагины Wordpress/wp-multi-city"
|
||||||
|
git add docs/QA-CHECKLIST.md
|
||||||
|
git commit -m "docs(wpmc S6): manual QA checklist covering 13 cp-cw4 acceptance areas"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 3: README — Testing section + roadmap status
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `README.md`
|
||||||
|
|
||||||
|
- [ ] **Step 3.1: Read current README**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "/Users/vladimirbryzgalov/Yandex.Disk.localized/Работа/Сайты/+Разработка сайтов+/Плагины Wordpress/wp-multi-city"
|
||||||
|
cat README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: see existing structure — heading, status line, требования, installation, roadmap table, "Источник" section.
|
||||||
|
|
||||||
|
- [ ] **Step 3.2: Add Testing section before the Roadmap section**
|
||||||
|
|
||||||
|
Open `README.md`. Locate the line `## Roadmap MVP` (or equivalent header). Immediately before it, insert this new section:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Automated (PHPUnit)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
composer install
|
||||||
|
vendor/bin/phpunit
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: 98 tests, 175 assertions green. Unit-level coverage via Brain Monkey + Mockery + Patchwork — no real WordPress required; the full suite runs in under one second.
|
||||||
|
|
||||||
|
### Manual QA
|
||||||
|
|
||||||
|
For end-to-end verification against a real WordPress installation, see `docs/QA-CHECKLIST.md` — 13 sections covering activation, admin UI, helpers, shortcode, router, page clones, URL filters, REST URL.
|
||||||
|
|
||||||
|
### CI
|
||||||
|
|
||||||
|
`.gitea/workflows/test.yml` runs PHPUnit on every push to `main` and every pull request. The workflow becomes active once the repo is mirrored to Gitea (S7).
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
(Note: the trailing blank line is intentional.)
|
||||||
|
|
||||||
|
- [ ] **Step 3.3: Mark S6 done in roadmap table**
|
||||||
|
|
||||||
|
In the same `README.md`, find the S6 row in the roadmap table:
|
||||||
|
|
||||||
|
```
|
||||||
|
| S6 | PHPUnit-тесты (бутстрап + integration) | cp-la7 | open |
|
||||||
|
```
|
||||||
|
|
||||||
|
Change to:
|
||||||
|
|
||||||
|
```
|
||||||
|
| S6 | PHPUnit-тесты (бутстрап + integration) | cp-la7 | done |
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 3.4: Verify suite + lint still green**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "/Users/vladimirbryzgalov/Yandex.Disk.localized/Работа/Сайты/+Разработка сайтов+/Плагины Wordpress/wp-multi-city"
|
||||||
|
vendor/bin/phpunit
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: OK (98 tests, 175 assertions). No PHP files changed in this task, so this is a no-op sanity check.
|
||||||
|
|
||||||
|
- [ ] **Step 3.5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "/Users/vladimirbryzgalov/Yandex.Disk.localized/Работа/Сайты/+Разработка сайтов+/Плагины Wordpress/wp-multi-city"
|
||||||
|
git add README.md
|
||||||
|
git commit -m "docs(wpmc S6): README Testing section + mark S6 done in roadmap"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 4: Final verification + close beads
|
||||||
|
|
||||||
|
**Files:** none
|
||||||
|
|
||||||
|
- [ ] **Step 4.1: Full PHPUnit run**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "/Users/vladimirbryzgalov/Yandex.Disk.localized/Работа/Сайты/+Разработка сайтов+/Плагины Wordpress/wp-multi-city"
|
||||||
|
vendor/bin/phpunit
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: OK (98 tests, 175 assertions), exit 0, no risky/warnings.
|
||||||
|
|
||||||
|
- [ ] **Step 4.2: Working tree clean**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "/Users/vladimirbryzgalov/Yandex.Disk.localized/Работа/Сайты/+Разработка сайтов+/Плагины Wordpress/wp-multi-city"
|
||||||
|
git status
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: `nothing to commit, working tree clean`.
|
||||||
|
|
||||||
|
- [ ] **Step 4.3: Verify artifacts exist**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "/Users/vladimirbryzgalov/Yandex.Disk.localized/Работа/Сайты/+Разработка сайтов+/Плагины Wordpress/wp-multi-city"
|
||||||
|
ls -la .gitea/workflows/test.yml docs/QA-CHECKLIST.md
|
||||||
|
grep -c "^## " docs/QA-CHECKLIST.md
|
||||||
|
grep -n "^## Testing" README.md
|
||||||
|
grep -n "cp-la7" README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
- Both files exist with non-zero size.
|
||||||
|
- `grep -c "^## "` on QA-CHECKLIST shows at least 14 (13 sections + Release sign-off).
|
||||||
|
- README shows `## Testing` heading line number.
|
||||||
|
- README S6 row contains `done`.
|
||||||
|
|
||||||
|
- [ ] **Step 4.4: Git log review**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd "/Users/vladimirbryzgalov/Yandex.Disk.localized/Работа/Сайты/+Разработка сайтов+/Плагины Wordpress/wp-multi-city"
|
||||||
|
git log --oneline | head -10
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: top of log shows the S6 commits in order:
|
||||||
|
1. `docs(wpmc S6): README Testing section + mark S6 done in roadmap`
|
||||||
|
2. `docs(wpmc S6): manual QA checklist covering 13 cp-cw4 acceptance areas`
|
||||||
|
3. `ci(wpmc S6): Gitea Actions workflow for PHPUnit on push/PR`
|
||||||
|
4. `spec(wpmc S6): CI workflow + manual QA checklist (minimal scope)`
|
||||||
|
|
||||||
|
- [ ] **Step 4.5: Close beads task**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bd close cp-la7 --reason "S6 done (minimal scope per spec): Gitea Actions CI workflow at .gitea/workflows/test.yml runs PHPUnit on push/PR. 13-section manual QA checklist at docs/QA-CHECKLIST.md covers all cp-cw4 acceptance criteria. README updated with Testing section + roadmap marked done. Existing 98-test Brain Monkey suite remains green and covers what original cp-la7 envisioned as 5 integration test files (Taxonomy, CPT, Shortcode, Router, Filters) at call-signature level."
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: cp-la7 CLOSED. `bd ready` now lists cp-7cf (S7) as the next ready front under cp-cw4.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Acceptance map (spec → tasks)
|
||||||
|
|
||||||
|
| Spec requirement | Task |
|
||||||
|
|---|---|
|
||||||
|
| `.gitea/workflows/test.yml` valid Gitea Actions YAML | 1 |
|
||||||
|
| Workflow runs phpunit on push + pull_request | 1 |
|
||||||
|
| PHP 8.0 setup + composer cache + dependency install | 1 |
|
||||||
|
| `docs/QA-CHECKLIST.md` 13 sections | 2 |
|
||||||
|
| Each section linked to cp-cw4 acceptance criterion | 2 |
|
||||||
|
| Release sign-off block at end of checklist | 2 |
|
||||||
|
| README Testing section (automated + manual + CI) | 3 |
|
||||||
|
| README roadmap S6 → done | 3 |
|
||||||
|
| PHPUnit suite remains 98/175 green | 1, 3, 4 |
|
||||||
|
| beads cp-la7 closed | 4 |
|
||||||
Reference in New Issue
Block a user