Skip to content
Merged

Release #1097

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
2 changes: 1 addition & 1 deletion .github/workflows/build-dev-artifacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
git-sha-8: ${{ steps.retrieve-git-sha-8.outputs.sha8 }}
steps:
- name: Checkout Source Files
uses: actions/checkout@v2
uses: actions/checkout@v7
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
Expand Down
52 changes: 52 additions & 0 deletions .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: "Copilot Setup Steps"

# Prepares the GitHub Copilot coding agent environment: dependencies installed,
# assets built, and a running wp-env so E2E tests can be executed right away.
on:
workflow_dispatch:
push:
paths:
- .github/workflows/copilot-setup-steps.yml
pull_request:
paths:
- .github/workflows/copilot-setup-steps.yml

jobs:
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
copilot-setup-steps:
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- uses: actions/checkout@v7

- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: "22"
cache: npm

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: "7.4"

- name: Install composer
run: composer install --prefer-dist --no-progress --quiet

- name: npm ci
run: npm ci

- name: Make build
run: |
npm run build
npm run sharing

# No --with-deps: Playwright 1.40 requests libasound2, which Ubuntu 24.04
# renamed to libasound2t64; the runner image already has the needed libs.
- name: Install Playwright browsers
run: npx playwright install chromium

- name: Setup WP Env
run: npm run wp-env start
29 changes: 15 additions & 14 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: E2E

on:
pull_request:
types: [synchronize, ready_for_review]
types: [opened, reopened, synchronize, ready_for_review]
branches-ignore:
- "update_dependencies"

Expand All @@ -13,7 +13,13 @@ jobs:

steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v4
- uses: actions/checkout@v7

- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: "22"
cache: npm

- name: Setup PHP
uses: shivammathur/setup-php@v2
Expand All @@ -24,15 +30,6 @@ jobs:
- name: Install composer
run: composer install --prefer-dist --no-progress --quiet

# setup the node cache (node_modules) with github actions cache
- name: Cache Node - npm
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-cache-

- name: npm ci
run: |
npm ci
Expand All @@ -51,14 +48,18 @@ jobs:
npm install -g playwright-cli
npx playwright install

- name: Playwright Blocks
- name: Run Playwright tests
run: |
npm run test:e2e:playwright

- name: Upload tests artifacts
if: failure()
uses: actions/upload-artifact@v4
with:
name: artifact
path: ./artifacts
name: playwright-artifacts
if-no-files-found: ignore
path: |
playwright-report/
test-results/
flaky-tests/
retention-days: 1
2 changes: 1 addition & 1 deletion .github/workflows/test-js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
with:
persist-credentials: false
- name: Build files using ${{ matrix.node-version }}
uses: actions/setup-node@v1
uses: actions/setup-node@v7
with:
node-version: ${{ matrix.node-version }}
- name: Lint js files
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test-php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v4
uses: actions/checkout@v7
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
Expand All @@ -41,7 +41,7 @@ jobs:
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- name: Checkout source code
uses: actions/checkout@v4
uses: actions/checkout@v7
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
Expand All @@ -64,7 +64,7 @@ jobs:
php-version: "7.4"
extensions: simplexml
- name: Checkout source code
uses: actions/checkout@v4
uses: actions/checkout@v7
- name: Install composer
run: |
composer install --prefer-dist --no-progress
Expand Down
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,9 @@ assets/.DS_Store
.DS_Store
temp-images
.vscode
.wp-env.override.json
assets/js/build
assets/js/react
assets/js/react
test-results
playwright-report
flaky-tests
9 changes: 9 additions & 0 deletions .wp-env.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
{
"core": null,
"plugins": [ "." ],
"config": {
"WP_DEBUG": true,
"WP_DEBUG_LOG": true,
"WP_DEBUG_DISPLAY": false,
"DISABLE_WP_CRON": true
},
"mappings": {
"wp-content/mu-plugins": "./tests/e2e/mu-plugins"
},
"env": {
"tests": {
"config": {
Expand Down
40 changes: 40 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ composer run phpstan # Static analysis (level 6)
npm run wp-env start # Start WordPress environment
npm run test:e2e:playwright # Run Playwright E2E tests
npm run test:e2e:playwright:ui # E2E with Playwright UI mode
# If the bundled Chromium crashes on launch (SIGTRAP on newer macOS), use system Chrome:
PLAYWRIGHT_CHANNEL=chrome npm run test:e2e:playwright

# If wp-env start fails with "port is already allocated", pin free ports in the
# gitignored `.wp-env.override.json` (same pattern as Otter), then restart:
# { "port": 8892, "testsPort": 8900 }
# Playwright reads testsPort from that file automatically; override with WP_BASE_URL if needed.

# Distribution
npm run dist # Create distribution ZIP archive
Expand Down Expand Up @@ -103,4 +110,37 @@ PHPUnit test suites are defined in `phpunit.xml` with individual files in `tests

E2E tests use Playwright with `@wordpress/e2e-test-utils-playwright`. Specs live in `tests/e2e/specs/`. Config at `tests/e2e/playwright.config.js`.

### wp-env ports (multi-checkout)

wp-env namespaces containers per checkout, but host ports are shared. If `8888`/`8889` are taken by another instance, create a gitignored `.wp-env.override.json` (see [Otter](https://github.com/Codeinwp/otter-blocks/blob/master/AGENTS.md#wp-env-instance-ports--multi-checkout)) with free ports, then `npm run wp-env start`:

```json
{ "port": 8892, "testsPort": 8900 }
```

Port precedence for Playwright: `WP_BASE_URL` > `WP_ENV_PORT` > `.wp-env.override.json` (`testsPort`, then `port`) > `8889`. E2E targets the tests instance (`testsPort`).

E2E runs never hit real social APIs. `tests/e2e/mu-plugins/rop-e2e-bootstrap.php` (mapped into wp-env as an mu-plugin via `.wp-env.json`) intercepts `ROP_POST_ON_X_API`/`ROP_POST_LOGS_API` requests through `pre_http_request`, records their payloads, and exposes REST endpoints under `rop-e2e/v1` (`/reset`, `/account`, `/publish-now`, `/requests`). Specs consume these through the `ropUtils` fixture from `tests/e2e/fixtures` — use it for setup (`reset()` + `seedAccount()` in `beforeEach`) and for asserting on captured request payloads (`getRequests()`) instead of driving account setup through the UI. wp-env runs with `DISABLE_WP_CRON` so shares only happen via the explicit `runPublishNow(postId)` trigger.

PHPUnit bootstrap (`tests/bootstrap.php`) requires WordPress test suite via `WP_TESTS_DIR` env var.

## Test-Writing Practices (TDD)

Work in the red → green loop: write one failing test first, then only enough code to make it pass. One seam, one test, one minimal implementation per cycle — don't write a batch of tests up front for imagined behavior, and don't add speculative features to satisfy tests that don't exist yet. Refactoring is a separate review step, not part of the loop.

**Test at public seams, never against internals.** A seam is a boundary where behavior is observable without reaching inside. In this plugin the established seams are:

- The wp-admin UI driven through Playwright (what a user sees and clicks)
- HTTP payloads sent to external APIs, captured at `pre_http_request` by the E2E mu-plugin (`ropUtils.getRequests()`)
- The plugin's REST API (`tweet-old-post/v8/...`)
- Public PHP classes/methods covered by PHPUnit in `tests/`

Adding a test at a new seam is a design decision — agree on it first rather than testing whatever is reachable.

**Anti-patterns to avoid:**

- **Implementation-coupled tests** — asserting on private methods, internal option/DB structure, or CSS class names that a refactor would rename. The tell: the test breaks when code is refactored but behavior hasn't changed. (Reading state through the `rop-e2e/v1` endpoints is fine — they exist to expose the seam.)
- **Tautological tests** — computing the expected value the same way the code does, so the assertion can never disagree with the code. Expected values must be independent literals: a known handle (`@testaccount`), a known token (`rop-e2e-token`), a worked example.
- **Horizontal slicing** — writing all tests first, then all implementation. Each new test should respond to what the previous cycle taught you.

A good test reads like a specification: `shares a published post through the mocked X process` says exactly what capability exists.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
},
"require-dev": {
"wp-coding-standards/wpcs": "^2.3",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.2",
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
"phpunit/phpunit": "9.*",
"yoast/phpunit-polyfills": "^2.0",
"codeinwp/phpcs-ruleset": "dev-main",
Expand Down
Loading
Loading