Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ This repository is a PHP 8.5 package named `jooservices/wordpress-sdk`.
- Use typed query DTOs for common list/read filters where practical.
- Raw array escape hatches are allowed only as intentional, documented compatibility surfaces.
- Avoid hidden domain strings when enums or constants are clearer.
- Do not add story/product-review/article content template features to SDK core; those belong in `jooservices/wordpress-content-templates`.

## Delivery checklist

Expand All @@ -60,7 +61,7 @@ Before reporting completion:
## Integration testing standard

- Do not run SDK integration tests against live WordPress sites.
- Use only the disposable Docker/WP-CLI environment under `docker/wordpress`.
- Integration tests must require `WORDPRESS_ENV=testing`, a local WordPress URL, and the `jooservices_sdk_test_site` marker.
- The SDK public surface should be covered by unit tests, Docker integration tests, or explicit reasoned entries in the coverage-map script.
- Use only disposable local WordPress test sites. Do not add Docker/WP Composer aliases unless the complete local-only runner, setup scripts, fixtures, and safety guards are committed in the same change.
- Integration tests must require a local WordPress URL and disposable test credentials.
- The SDK public surface should be covered by unit tests, integration tests, or explicit reasoned entries in the coverage-map script.
- Integration skips must name the exact service method, route, WordPress version, and theme/plugin reason.
26 changes: 19 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,29 @@ The format follows Keep a Changelog, and this project aims to follow semantic ve

## [Unreleased]

### Added
### Removed

- Added a Docker/WP-CLI WordPress integration testing environment with disposable MariaDB and local-only WordPress services.
- Added a test-only WordPress plugin for deterministic custom endpoint CRUD coverage.
- Added localhost, `WORDPRESS_ENV=testing`, and marker-option safety guards for integration tests.
- Added service-oriented Docker integration tests and REST route contract coverage.
- Added `composer test:coverage-map` to map production public surface to unit and integration tests.
- Removed non-native content template classes, data objects, examples, and template-specific tests from SDK core.
- Removed `PostsService::createFromTemplate()` because content templates are not native WordPress REST API SDK features.

### Changed

- Updated testing docs, README development commands, and AI contributor guidance to require Docker-only WordPress integration tests.
- Kept `PostBuilder` and `ContentBuilder` as generic SDK-safe helpers for post payloads and Gutenberg-compatible block markup.
- Updated docs and testing guidance to point story, product-review, article, and custom content-template users to `jooservices/wordpress-content-templates`.

### Migration

- Install `jooservices/wordpress-content-templates` for extracted content templates:

```bash
composer require jooservices/wordpress-content-templates
```

- Generate a payload with the template package and publish it with the SDK:

```php
$post = $wordpress->posts()->create($template->toPostData());
```

## [1.1.0] - 2026-05-16

Expand Down
11 changes: 3 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,10 @@ The SDK also ships with optional developer-experience helpers under `JOOservices

- `PostBuilder` helps assemble post payloads fluently before calling `posts()->create()` or `update()`.
- `ContentBuilder` helps generate Gutenberg-compatible block markup in PHP.
- `PostTemplate`, concrete templates, and `createFromTemplate()` are template helpers built on top of normal post creation.

These helpers are not native WordPress REST API resources. They are kept as SDK extras because they reduce repetitive WordPress payload-building while staying generic to SDK users.
These helpers are not native WordPress REST API resources. They remain in the SDK because they are generic payload and Gutenberg markup helpers for normal WordPress post operations.

The Docker integration suite verifies these helpers against a real local WordPress REST API. `composer test:wordpress` starts Docker services, installs WordPress with WP-CLI, creates test auth, uploads local media fixtures, and runs the main integration tests. Optional WordPress capabilities that need extra plugins, block registration, or block-theme state live in the independent `composer test:wordpress:extended` suite. No manual WordPress setup is required; use `composer test:wordpress:reset` to wipe the disposable database and uploads volume.
Content templates for stories, product reviews, articles, and template registries now live in `jooservices/wordpress-content-templates`. That package depends on this SDK and generates SDK-compatible post/page payloads; this SDK does not depend on it.

## DTO-first querying

Expand Down Expand Up @@ -196,10 +195,6 @@ composer lint
composer lint:all
composer test
composer test:integration
composer test:wordpress
composer test:wordpress:extended
composer test:wordpress:reset
composer test:integration:docker
composer test:coverage
composer test:coverage:gate
composer test:coverage-map
Expand All @@ -208,7 +203,7 @@ composer check
composer ci
```

Run `composer test:wordpress` for the one-command Docker/WP-CLI WordPress integration flow. Run `composer test:wordpress:extended` after it, or by itself, for optional capabilities such as deterministic plugin reads, dynamic block rendering, global styles, navigation/template routes, site health reads, and the chaptered story template workflow with uploaded media. See [Testing](./docs/04-development/testing.md) for details, safety guards, reset commands, and route skip policy.
Run `composer test:integration` only against a disposable local WordPress test site created for SDK testing. The stale Docker/WP Composer aliases from pre-release documentation are not shipped in 1.2.0 because their runner files are not present in this repository.

`composer test:coverage` now includes a Clover XML audit gate. Aggregate statement coverage must stay at or above 90%, and no coverable production file, class, or method in `src/` may remain at 0% coverage unless it has a documented exclusion reason in `tools/test-coverage-gate.php`.

Expand Down
17 changes: 0 additions & 17 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,23 +76,6 @@
],
"test:coverage:gate": "php tools/test-coverage-gate.php",
"test:coverage-map": "php tools/test-coverage-map.php",
"integration:up": "docker compose -f docker/wordpress/docker-compose.integration.yml up -d db wordpress",
"integration:setup": "docker/wordpress/scripts/setup.sh && docker/wordpress/scripts/seed.sh",
"integration:seed": "docker/wordpress/scripts/seed.sh",
"integration:down": "docker/wordpress/scripts/teardown.sh",
"test:wordpress": [
"Composer\\Config::disableProcessTimeout",
"docker/wordpress/scripts/run-integration-tests.sh"
],
"test:wordpress:extended": [
"Composer\\Config::disableProcessTimeout",
"docker/wordpress/scripts/run-extended-integration-tests.sh"
],
"test:wordpress:reset": "docker/wordpress/scripts/run-integration-tests.sh reset",
"test:integration:docker": [
"Composer\\Config::disableProcessTimeout",
"docker/wordpress/scripts/run-integration-tests.sh"
],
"security": "composer audit",
"quality": [
"@lint",
Expand Down
3 changes: 2 additions & 1 deletion docs/02-user-guide/01-services-and-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ Examples:

- `PostBuilder` for fluent post payload construction
- `ContentBuilder` for Gutenberg block content generation
- template helpers such as `PostTemplate` and `posts()->createFromTemplate()`

Story, product-review, article, and custom content templates are provided by `jooservices/wordpress-content-templates`, which depends on this SDK and passes generated payloads to `posts()->create()`.

These helpers are documented as SDK convenience layers on top of the normal REST services.

Expand Down
2 changes: 1 addition & 1 deletion docs/02-user-guide/posts.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ $created = $wp->posts()->create(['title' => 'Draft', 'status' => 'draft']);

Use `cursor()` or `each()` for large sites. Use `all()` only when loading all matching posts into memory is acceptable.

Optional template helpers such as `posts()->createFromTemplate()` are SDK extras layered on top of normal post creation rather than separate WordPress REST endpoints.
Content template helpers are not part of SDK core. Use `jooservices/wordpress-content-templates` when you want story, product review, article, or custom content templates that generate payloads for `posts()->create()`.
3 changes: 1 addition & 2 deletions docs/03-examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,4 @@ This section collects complete workflows built from the public SDK services.

Repository PHP examples:

- [Template usage example](../../examples/template-usage.php)
- [Custom template example](../../examples/custom-template.php)
- Content template examples live in `jooservices/wordpress-content-templates`.
2 changes: 1 addition & 1 deletion docs/04-development/ai-contributor-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Do not use phase, planning, temporary, or vague bucket names in code, tests, hel

If requirements are unclear, conflicting, missing, or cannot be verified from repository truth, stop and ask.

Integration tests must never target a live WordPress site. Use only the Docker/WP-CLI environment in `docker/wordpress`, require `WORDPRESS_ENV=testing`, require a local WordPress URL, and require the `jooservices_sdk_test_site` marker. Public SDK classes and concrete service methods should be mapped by unit tests, Docker integration tests, or an explicit reason in `tools/test-coverage-map.php`.
Integration tests must never target a live WordPress site. Use only disposable local WordPress test sites, and do not restore Docker/WP Composer aliases without committing the complete local-only runner, setup scripts, fixtures, and safety guards in the same change. Public SDK classes and concrete service methods should be mapped by unit tests, integration tests, or an explicit reason in `tools/test-coverage-map.php`.

Aggregate coverage alone is insufficient. Contributors must run `composer test:coverage`, which now audits `coverage.xml` and fails when overall statement coverage drops below 90% or any coverable production file, class, or method in `src/` is still at 0% coverage. Exclusions in `tools/test-coverage-gate.php` need a concrete reason.

Expand Down
78 changes: 10 additions & 68 deletions docs/04-development/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,91 +10,37 @@ Shared helpers should use purpose-based names. Do not use phase, planning, tempo
composer test
composer test:unit
composer test:integration
composer test:wordpress
composer test:wordpress:extended
composer test:wordpress:reset
composer test:integration:docker
composer test:all
composer test:coverage
composer test:coverage:gate
composer test:coverage-map
```

`composer test` and `composer test:coverage` run the unit suite so normal validation does not depend on WordPress. `composer test:wordpress` runs the main Docker integration suite. `composer test:wordpress:extended` runs optional WordPress capabilities independently after, or instead of, the main integration command.
`composer test` and `composer test:coverage` run the unit suite so normal validation does not depend on WordPress. `composer test:integration` runs the integration suite and must only be used with a disposable local WordPress test site.

`composer test:coverage` now runs a Clover XML coverage gate after PHPUnit writes `coverage.xml`. Aggregate statement coverage must stay at or above 90%. The gate also fails when any coverable production file, class, or method under `src/` is left at 0% coverage. Do not rely on the aggregate percentage alone.

## Unit Tests

Unit tests cover DTO hydration and serialization, query DTO output, endpoint path builders, auth middleware, response decoding, exception redaction, pagination helpers, service request construction, and content/template support. They must use fake clients or deterministic local values and must not make network calls.
Unit tests cover DTO hydration and serialization, query DTO output, endpoint path builders, auth middleware, response decoding, exception redaction, pagination helpers, service request construction, and generic builder support. They must use fake clients or deterministic local values and must not make network calls.

## Docker Integration Tests
## Integration Tests

Integration tests must run only against the disposable Docker WordPress environment in `docker/wordpress`.
Integration tests must run only against a disposable local WordPress environment created for SDK testing.

```bash
composer test:wordpress
```

The Docker runner starts MariaDB, WordPress, and WP-CLI, waits for HTTP readiness, installs WordPress with WP-CLI, activates the test endpoint plugin, creates local test users, generates a WordPress Application Password, seeds deterministic `sdk_test_` data, writes `.env.integration`, runs `composer test:integration`, and removes containers and volumes with `docker compose down -v`.

`composer test:integration:docker` is kept as an equivalent compatibility alias.

Template integration tests are part of this command. They create real draft posts through `posts()->createFromTemplate()`, upload local media fixtures through `media()->upload()`, verify fetched WordPress content, and clean up posts/media/terms after each test. Coverage includes the chaptered `StoryTemplate` story `The Lanterns of Grey Harbor`, a product review template, and a registered custom template.

## Extended Docker Integration Tests

Optional WordPress capabilities are covered by a separate one-command suite:

```bash
composer test:wordpress:extended
```

The extended runner starts the same disposable MariaDB, WordPress, and WP-CLI services, installs WordPress if needed, seeds the normal test marker and content, activates a local fixture plugin from `tests/Fixtures/wordpress-plugins/sdk-test-plugin`, activates a bundled block theme when available, flushes rewrite rules, writes extended test environment flags, prints route diagnostics, runs only the `ExtendedIntegration` PHPUnit suite, and then removes containers and volumes unless `WORDPRESS_TEST_KEEP_CONTAINERS=1` is set.

The fixture plugin is deterministic and local. It has a valid plugin header and registers `jooservices/test-dynamic-block`, whose render callback returns HTML containing `sdk-test-dynamic-block` and the requested message. It has no external API key, network dependency, or production side effect.

The extended suite covers:

- plugin endpoint reads against `sdk-test-plugin/sdk-test-plugin`
- block renderer requests for `jooservices/test-dynamic-block`
- global styles, navigation, templates, template parts, site health, themes, block types, widget types, and sidebars as independently checked raw routes
- a chaptered `StoryTemplate` draft post for `The Lanterns of Grey Harbor` with categories, tags, uploaded cover media, featured media, chapter headings, body paragraphs, and quote assertions

Global styles and other optional routes may still be absent in a specific WordPress/theme combination. Each optional route test checks only its own route and skips with the WordPress version, active theme, and active plugin list; one missing route does not skip unrelated extended tests.

Use the lifecycle commands when debugging:

```bash
composer integration:up
composer integration:setup
composer integration:seed
composer test:integration
composer integration:down
```

The runner also supports direct maintenance commands:
The 1.2.0 release does not ship Docker/WP Composer aliases because the Docker runner files are not present in this repository. Do not add `composer test:wordpress`, `composer test:wordpress:extended`, or Docker aliases back without committing the complete local-only runner, setup scripts, fixtures, and safety guards in the same change.

```bash
docker/wordpress/scripts/run-integration-tests.sh reset
docker/wordpress/scripts/run-integration-tests.sh stop
docker/wordpress/scripts/run-extended-integration-tests.sh reset
docker/wordpress/scripts/run-extended-integration-tests.sh stop
WORDPRESS_TEST_KEEP_CONTAINERS=1 composer test:wordpress
WORDPRESS_TEST_KEEP_CONTAINERS=1 composer test:wordpress:extended
```
Template-specific integration tests live in `jooservices/wordpress-content-templates`. SDK integration tests stay focused on native WordPress REST API endpoints, generic post payload creation, media uploads, and Gutenberg content builder behavior.

The local test site uses disposable credentials only. Do not commit real WordPress credentials.

## Safety Guard

Integration tests refuse to run unless all of these are true:

- `WORDPRESS_ENV=testing`
- `WORDPRESS_URL` points to `localhost`, `127.0.0.1`, or the Docker service host `wordpress`
- the authenticated test plugin marker route confirms the WordPress option `jooservices_sdk_test_site = 1`

This prevents destructive SDK tests from running against production, staging, or personal WordPress sites.
Do not run SDK integration tests against production, staging, or personal WordPress sites. Until a complete Docker/WP runner is restored, contributors should treat the integration suite as manually provisioned and keep normal release validation on unit tests, coverage, coverage-map, static analysis, and security audit.

## Coverage Map

Expand Down Expand Up @@ -124,10 +70,6 @@ Acceptable reasons include:

## Troubleshooting

- Port `8088` already in use: stop the conflicting process or override the compose file locally before running tests.
- Docker not running: start Docker Desktop or the Docker daemon, then rerun `composer test:wordpress`.
- DB not ready: rerun the command; the compose healthcheck waits for MariaDB initialization.
- WordPress install failed: run `docker/wordpress/scripts/run-integration-tests.sh reset` and rerun.
- Extended provisioning failed: run `composer test:wordpress:reset`, then rerun `composer test:wordpress:extended`.
- WP-CLI failed: inspect the printed failing `wp` step; no global host WP-CLI is required.
- Permissions: ensure Docker can mount the repository and the scripts are executable.
- Missing WordPress environment values: set `WORDPRESS_URL`, `WORDPRESS_USER`, and `WORDPRESS_APP_PASSWORD` for a disposable local test site only.
- WordPress server is unreachable: start the local test site and verify `/wp-json/` is reachable.
- Integration failures after resource creation: clean up the disposable local test site before rerunning.
3 changes: 1 addition & 2 deletions docs/guides/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,4 @@ The following table outlines the current capabilities of the SDK services.
The SDK includes powerful tools for generating content:

- **ContentBuilder**: Fluent API for creating Gutenberg-compatible block content programmatically.
- **Templates**: Type-safe Post Templates (Stories, Product Reviews) for standardized content creation.

- **Content templates**: Available in `jooservices/wordpress-content-templates`, outside SDK core.
Loading
Loading