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

12 KiB
Raw Permalink Blame History

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:

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 явная.

Шаблон секций

## 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) вставить:
    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":

## 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» после раздела «Установка»:

## 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

Нет. Все решения зафиксированы.