Files
wp-multi-city/docs/superpowers/specs/2026-05-16-s6-ci-qa-checklist-design.md

240 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# S6 — CI workflow + Manual QA Checklist
- Beads: `cp-la7` (parent epic `cp-cw4`)
- Depends on: `cp-i17` (S5 — URL filters, закрыт)
- Blocks: `cp-7cf` (S7 — README + Gitea release + PUC)
- Дата: 2026-05-16
## Цель
Завершить тестовый этап MVP. Текущий 98-тестовый Brain Monkey suite уже покрывает 5 функциональных областей из изначального cp-la7 (Taxonomy, CPT, Shortcode, Router, Filters) на уровне call-signature через мок-фреймворк. Реальные WP integration tests с DB и WP-core checkout overkill для MVP и существенно overlap с unit-тестами.
S6 добавляет два artifact'а, которые закроют epic acceptance:
- **Gitea Actions workflow** — автоматический прогон phpunit на push/PR, готов к активации при mirror'е в Gitea (S7).
- **Manual QA checklist** — пошаговая ручная проверка против реального WP с ACF Pro, привязанная к acceptance criteria из cp-cw4.
И обновление README с инструкциями по тестированию.
Никаких новых PHP-классов, никаких новых phpunit-тестов. S6 — infrastructure-only.
## Артефакты
```
wp-multi-city/
├── .gitea/workflows/test.yml # CREATE — CI workflow
├── docs/QA-CHECKLIST.md # CREATE — manual smoke checklist
└── README.md # MODIFY — Testing section + roadmap status
```
## CI workflow — `.gitea/workflows/test.yml`
Gitea Actions syntax — subset of GitHub Actions, поддерживается с Gitea 1.19. Workflow срабатывает на push и pull_request:
```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
```
Файл лежит готовым; станет активным когда Gitea remote добавится в S7. До этого момента — placeholder без active CI.
PHP matrix (8.0/8.1/8.2/8.3), coverage report, lint job — отложено до S7+.
## Manual QA checklist — `docs/QA-CHECKLIST.md`
Структура: 13 секций, каждая с шагами и expected outcome. Каждый чекпойнт — `- [ ]` для отметки. Привязка к acceptance criteria из cp-cw4 явная.
### Шаблон секций
```markdown
## N. <Имя секции>
**Cp-cw4 acceptance: <привязка>**
Preconditions: <состояние сайта>
Steps:
1. <шаг>
2. <шаг>
Expected:
- <критерий>
- <критерий>
- [ ] Section pass
```
### Полные 13 секций
**1. Plugin activation**
- Preconditions: чистый WP 6.0+ с активированным ACF Pro.
- Steps: загрузить плагин в `wp-content/plugins/wp-multi-city/`; активировать через admin → Plugins.
- Expected: нет PHP-ошибок; нет admin notice "WP Multi City requires ACF Pro"; в admin menu появляются «Шорткоды», «WP Multi City».
**2. ACF dependency notice**
- Preconditions: WP с деактивированным ACF Pro.
- Steps: активировать плагин.
- Expected: admin notice "WP Multi City: требуется активный плагин Advanced Custom Fields Pro" виден; плагин не вешает хуки.
**3. Admin UI — taxonomy town**
- Preconditions: плагин активен, ACF Pro установлен.
- Steps: открыть admin → Шорткоды → Города.
- Expected: пустой список term'ов; кнопка «Добавить» работает; создать term `tyumen` и `spb`.
**4. Admin UI — CPT shortcode-town**
- Preconditions: §3 завершён.
- Steps: открыть admin → Шорткоды → Добавить.
- Expected: edit-screen показывает поле title + ACF repeater «Подстановки по городам» (`list_shortcode`) с двумя sub-fields «Город» и «Значение»; town sub-field — dropdown с термами spb/tyumen.
**5. Admin UI — Options page**
- Preconditions: §3 завершён.
- Steps: открыть admin → WP Multi City.
- Expected: ACF options page «WPMultiCity / Routing» с 4 полями: main_town_slug (dropdown town), index_town_alt (page picker), page_unic (repeater 3 sub-fields), page_no_rep (repeater 1 sub-field link).
**6. Helper functions smoke**
- Preconditions: §3 завершён, создана страница «About» (ID=10).
- Steps: в functions.php темы (или mu-plugin) вставить:
```php
add_action('wp_footer', function() {
error_log('current_town: ' . var_export(wpmc_current_town(), true));
error_log('get_term: ' . var_export(wpmc_get_term_by_slug('tyumen'), true));
error_log('remove_domain_link: ' . wpmc_remove_domain_link('https://example.com/foo/'));
});
```
Открыть `/tyumen/about/` (или с любым term-slug в URL).
- Expected: error log показывает `current_town: 'tyumen'`, `get_term: WP_Term { term_id: ..., slug: 'tyumen' }`, `remove_domain_link: '/foo/'`. Открытие `/`: `current_town` = `null` (без main_town_slug в options).
**7. [shortcode_dmr] resolves by town**
- Preconditions: §3-4 завершено. Создан shortcode-town пост ID=42 с одной row: town=tyumen, text=«Тюмень-текст».
- Steps: создать страницу с content `[shortcode_dmr id=42]`. Открыть на `/tyumen/<page-slug>/`. Открыть на `/<page-slug>/`.
- Expected: на /tyumen/ — «Тюмень-текст»; на / — пусто (без main_town_slug).
**8. Router patches $wp_query**
- Preconditions: §3, §5 завершено. В Options Page выставлен main_town_slug=spb. Создана page «About» ID=10.
- Steps: открыть `/tyumen/about/`.
- Expected: контентом загружается страница About (через `$wp_query->page_id=10`); `get_query_var('town')` в шаблоне = `'tyumen'`. Открыть `/spb/about/` — стандартный WP fallback (main town не патчится).
**9. /{slug}/ root with main_page_alt**
- Preconditions: §8 завершено. Создана страница «Главная Тюмень» ID=20. На term'е tyumen выставлен ACF field `main_page_alt` = 20.
- Steps: открыть `/tyumen/`.
- Expected: загружается page 20; `is_front_page()` = true; `get_queried_object()->ID` = 20.
**10. page_unic clone swap**
- Preconditions: §8 завершено. Создана клон-страница «About-Tyumen» ID=21. В Options Page → page_unic добавлена row: page_old=10, page_new=21, town=tyumen.
- Steps: открыть `/tyumen/about/`.
- Expected: контентом загружается page 21 (клон), не 10 (оригинал); URL остаётся `/tyumen/about/`.
**11. URL filters — town prefix injection**
- Preconditions: §8 завершено. Тема выводит menu (nav-menu) со ссылкой на `/uslugi/`.
- Steps: открыть `/tyumen/about/`; inspect menu link; inspect ACF link field value (если есть).
- Expected: menu link href = `/tyumen/uslugi/` или `https://host/tyumen/uslugi/`; ссылка на main town (`/spb/uslugi/`) не префиксится; внешние ссылки (`https://other.com/`) не префиксятся; mailto:/tel: не меняются; ссылки уже с городским префиксом (`/tyumen/contact/`) не получают double-prefix.
**12. page_no_rep exclusions**
- Preconditions: §8 завершено. В Options Page → page_no_rep добавлен `/privacy/`. Создана страница Privacy ID=30.
- Steps: открыть `/privacy/`.
- Expected: стандартный WP load page Privacy; `$wp_query` не патчится; ссылки на этой странице (по template) не префиксятся (`is_routable_path` возвращает false).
**13. rest_url + REST API**
- Preconditions: WP REST API доступен.
- Steps: в шаблоне `echo rest_url('wp/v2/posts')`; обратиться к этому URL через curl или браузер.
- Expected: URL возвращает `https://{HTTP_HOST}/wp-json/wp/v2/posts` (не site_url); ответ — JSON список постов.
### Финал чеклиста
В конце документа — раздел "Release sign-off":
```markdown
## Release sign-off
- [ ] All 13 sections passed
- [ ] PHPUnit suite green (`vendor/bin/phpunit` → OK 98 tests, 175 assertions)
- [ ] PHP lint clean (`composer test-lint` или `find includes -name '*.php' -exec php -l {} \;`)
- [ ] Tested on WP 6.0+ with PHP 8.0+
- [ ] No PHP notices/warnings in error_log
Tester: ______________ Date: ______________ Plugin version: ______________
```
## README — обновление
Добавить новую секцию «Testing» после раздела «Установка»:
```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 WP required; runs in <1s).
### Manual QA
For end-to-end verification against a real WordPress installation, see `docs/QA-CHECKLIST.md`. Run through the checklist before any release.
### CI
`.gitea/workflows/test.yml` runs PHPUnit on every push and pull request. Active once the repo is mirrored to Gitea (S7).
```
Обновить roadmap-таблицу: пометить S6 как `done`:
```
| S6 | PHPUnit-тесты (бутстрап + integration) | cp-la7 | done |
```
## Acceptance verification
После всех 3 артефактов:
1. `.gitea/workflows/test.yml` — YAML валидный, проходит через `yamllint` (опционально).
2. `docs/QA-CHECKLIST.md` существует, 13 секций + sign-off, плюс прохождение хотя бы 1 секции в реальной среде для smoke (опционально).
3. README обновлён, roadmap-таблица показывает S6=done.
4. `vendor/bin/phpunit` всё ещё зелёный (98/175) — ни один из 3 артефактов не ломает существующий suite.
## Что НЕ входит в S6
- Реальные WP integration tests с DB и WP-core checkout (overlap с unit-тестами, overkill для MVP).
- Docker/wp-env runtime для тестов.
- PHP matrix в CI (8.0/8.1/8.2/8.3) — отложено до S7+.
- Code coverage reports (phpunit coverage) — отложено.
- `bin/smoke.php` wp-cli helper — отложено; manual checklist покрывает MVP.
- Lint job в CI (phpcs/phpstan) — отложено.
## Open questions
Нет. Все решения зафиксированы.