From 51552dbd758fede23116a605184f6f30a15ab3eb Mon Sep 17 00:00:00 2001 From: Alex Worrad-Andrews Date: Wed, 18 Mar 2026 22:13:41 +0000 Subject: [PATCH 01/11] Add join-e2e package scaffold package.json, .wp-env.json, and playwright.config.ts for the new @ck/join-e2e package. wp-env targets WordPress 6.5 with the join-block plugin mounted; Playwright is configured for Chromium against port 8889 (wp-env tests environment). --- packages/join-e2e/.wp-env.json | 12 ++++++++++++ packages/join-e2e/package.json | 17 +++++++++++++++++ packages/join-e2e/playwright.config.ts | 20 ++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 packages/join-e2e/.wp-env.json create mode 100644 packages/join-e2e/package.json create mode 100644 packages/join-e2e/playwright.config.ts diff --git a/packages/join-e2e/.wp-env.json b/packages/join-e2e/.wp-env.json new file mode 100644 index 0000000..066771a --- /dev/null +++ b/packages/join-e2e/.wp-env.json @@ -0,0 +1,12 @@ +{ + "core": "WordPress/WordPress#6.5", + "plugins": ["../../packages/join-block"], + "mappings": { + "wp-content/e2e-scripts": "../../packages/join-e2e/scripts" + }, + "config": { + "WP_DEBUG": true, + "WP_DEBUG_LOG": true, + "SCRIPT_DEBUG": true + } +} diff --git a/packages/join-e2e/package.json b/packages/join-e2e/package.json new file mode 100644 index 0000000..7d9aec5 --- /dev/null +++ b/packages/join-e2e/package.json @@ -0,0 +1,17 @@ +{ + "name": "@ck/join-e2e", + "version": "1.0.0", + "private": true, + "scripts": { + "test": "playwright test", + "test:ui": "playwright test --ui", + "wp-env:start": "wp-env start", + "wp-env:stop": "wp-env stop", + "pretest": "bash scripts/seed.sh" + }, + "devDependencies": { + "@playwright/test": "^1.46.0", + "@wordpress/e2e-test-utils-playwright": "^0.21.0", + "@wordpress/env": "^10.0.0" + } +} diff --git a/packages/join-e2e/playwright.config.ts b/packages/join-e2e/playwright.config.ts new file mode 100644 index 0000000..7bd770e --- /dev/null +++ b/packages/join-e2e/playwright.config.ts @@ -0,0 +1,20 @@ +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + testDir: './tests', + fullyParallel: false, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: 1, + reporter: 'html', + use: { + baseURL: 'http://localhost:8889', + trace: 'on-first-retry', + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + ], +}); From 7b3b297da7897b9a90fcdf530691deff1bace246 Mon Sep 17 00:00:00 2001 From: Alex Worrad-Andrews Date: Wed, 18 Mar 2026 22:14:42 +0000 Subject: [PATCH 02/11] Add E2E seed scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit seed.sh builds join-flow with REACT_APP_USE_TEST_DATA=true (so getTestDataIfEnabled() pre-fills all fields), then calls setup.php via wp-env to create the two test pages and flush rewrite rules. setup.php creates e2e-standard-join (£5/month) and e2e-free-join (£0/month) pages using carbon-fields/ck-join-form block markup with the membership plan data embedded in the "data" block attribute, which Carbon Fields passes directly to the render callback's $fields argument. get-page-url.sh retrieves a stored page URL from the wp_options table. --- packages/join-e2e/scripts/get-page-url.sh | 13 +++ packages/join-e2e/scripts/seed.sh | 19 ++++ packages/join-e2e/scripts/setup.php | 128 ++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100755 packages/join-e2e/scripts/get-page-url.sh create mode 100755 packages/join-e2e/scripts/seed.sh create mode 100644 packages/join-e2e/scripts/setup.php diff --git a/packages/join-e2e/scripts/get-page-url.sh b/packages/join-e2e/scripts/get-page-url.sh new file mode 100755 index 0000000..0a541d8 --- /dev/null +++ b/packages/join-e2e/scripts/get-page-url.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# Prints the URL for a named E2E test page. +# Usage: ./get-page-url.sh [standard|free] +# Defaults to "standard". +set -euo pipefail + +SLUG="${1:-standard}" +OPTION_KEY="ck_e2e_${SLUG}_page_url" + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "${SCRIPT_DIR}/.." + +npx wp-env run tests-cli wp option get "${OPTION_KEY}" 2>/dev/null diff --git a/packages/join-e2e/scripts/seed.sh b/packages/join-e2e/scripts/seed.sh new file mode 100755 index 0000000..e50a6dc --- /dev/null +++ b/packages/join-e2e/scripts/seed.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +# Builds the join-flow bundle with test data enabled and seeds the wp-env +# test WordPress instance with the two E2E test pages. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PACKAGE_DIR="${SCRIPT_DIR}/.." +JOIN_FLOW_DIR="${SCRIPT_DIR}/../../join-flow" + +echo "--- Building join-flow bundle (USE_TEST_DATA=true) ---" +cd "${JOIN_FLOW_DIR}" +REACT_APP_USE_TEST_DATA=true npm run build + +echo "--- Seeding WordPress test environment ---" +cd "${PACKAGE_DIR}" +npx wp-env run tests-cli wp eval-file /var/www/html/wp-content/e2e-scripts/setup.php +npx wp-env run tests-cli wp rewrite flush --hard + +echo "--- Seed complete ---" diff --git a/packages/join-e2e/scripts/setup.php b/packages/join-e2e/scripts/setup.php new file mode 100644 index 0000000..2c43a76 --- /dev/null +++ b/packages/join-e2e/scripts/setup.php @@ -0,0 +1,128 @@ + $plans, + 'require_address' => true, + 'require_phone_number' => true, + 'ask_for_additional_donation' => false, + ]; + $attrs = wp_json_encode(['data' => $data]); + return "\n" + . '
' . "\n" + . ''; +} + +/** + * Create or update a page by post_name slug. + * Returns the page ID on success; exits with status 1 on failure. + */ +function ck_e2e_upsert_page(string $slug, string $title, string $content): int +{ + $existing = get_posts([ + 'post_type' => 'page', + 'post_status' => 'publish', + 'name' => $slug, + 'numberposts' => 1, + ]); + + if ($existing) { + $page_id = $existing[0]->ID; + wp_update_post(['ID' => $page_id, 'post_content' => $content]); + echo "Updated page '{$slug}' (ID: {$page_id}).\n"; + return $page_id; + } + + $page_id = wp_insert_post([ + 'post_name' => $slug, + 'post_title' => $title, + 'post_status' => 'publish', + 'post_type' => 'page', + 'post_content' => $content, + ], true); + + if (is_wp_error($page_id)) { + echo 'Failed to create page \'' . $slug . '\': ' . $page_id->get_error_message() . "\n"; + exit(1); + } + + echo "Created page '{$slug}' (ID: {$page_id}).\n"; + return $page_id; +} + +// Configure pretty permalinks so test URLs are predictable. +update_option('permalink_structure', '/%postname%/'); +flush_rewrite_rules(true); + +// Standard membership plan (£5/month). +$standard_plans = [ + [ + '_type' => '', + 'label' => 'Standard', + 'id' => 'standard', + 'amount' => '5', + 'allow_custom_amount' => '', + 'frequency' => 'monthly', + 'currency' => 'GBP', + 'description' => '', + 'add_tags' => '', + 'remove_tags' => '', + ], +]; + +// Free membership plan (£0/month). +$free_plans = [ + [ + '_type' => '', + 'label' => 'Free', + 'id' => 'free', + 'amount' => '0', + 'allow_custom_amount' => '', + 'frequency' => 'monthly', + 'currency' => 'GBP', + 'description' => '', + 'add_tags' => '', + 'remove_tags' => '', + ], +]; + +$standard_page_id = ck_e2e_upsert_page( + 'e2e-standard-join', + 'E2E Standard Join Test', + ck_e2e_make_block_content($standard_plans) +); + +$free_page_id = ck_e2e_upsert_page( + 'e2e-free-join', + 'E2E Free Membership Test', + ck_e2e_make_block_content($free_plans) +); + +// Persist URLs as options so get-page-url.sh can retrieve them. +update_option('ck_e2e_standard_page_url', get_permalink($standard_page_id)); +update_option('ck_e2e_free_page_url', get_permalink($free_page_id)); + +echo 'Standard page URL: ' . get_permalink($standard_page_id) . "\n"; +echo 'Free page URL: ' . get_permalink($free_page_id) . "\n"; +echo "Setup complete.\n"; From 7e6b1713aa38a1808eed18a3c79a391ae97fadac Mon Sep 17 00:00:00 2001 From: Alex Worrad-Andrews Date: Wed, 18 Mar 2026 22:15:03 +0000 Subject: [PATCH 03/11] Add Phase 1 rendering tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 01-render.spec.ts verifies: 1.1 — .ck-join-form is visible; script#env is attached and parseable JSON with WP_REST_API and at least one MEMBERSHIP_PLANS entry. 1.2 — input#firstName is visible after React mounts; no console errors. 1.3 — .progress-steps is rendered; .progress-step--current contains "Your Details" on the initial page load. --- packages/join-e2e/tests/01-render.spec.ts | 66 +++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 packages/join-e2e/tests/01-render.spec.ts diff --git a/packages/join-e2e/tests/01-render.spec.ts b/packages/join-e2e/tests/01-render.spec.ts new file mode 100644 index 0000000..f745df2 --- /dev/null +++ b/packages/join-e2e/tests/01-render.spec.ts @@ -0,0 +1,66 @@ +import { test, expect } from '@playwright/test'; + +/** + * Phase 1 — Rendering + * + * Verifies that the join form block renders correctly: the React mount point + * is present, the environment JSON is injected and parseable, the first step's + * input fields are visible, and no console errors are emitted. + */ + +const STANDARD_PAGE = '/e2e-standard-join/'; + +test.describe('1 — Rendering', () => { + test('1.1 — form container and env script are present', async ({ page }) => { + await page.goto(STANDARD_PAGE); + + // React mounts into .ck-join-form; the outer .ck-join-flow wrapper is + // emitted directly by the PHP render callback. + await expect(page.locator('.ck-join-form')).toBeVisible(); + + // The #env