Skip to content

Add E2E smoke tests#236

Merged
mrcasual merged 4 commits into
developfrom
feature/e2e-setup
Apr 2, 2026
Merged

Add E2E smoke tests#236
mrcasual merged 4 commits into
developfrom
feature/e2e-setup

Conversation

@Mwalek
Copy link
Copy Markdown
Contributor

@Mwalek Mwalek commented Apr 2, 2026

Summary

  • Adds Playwright E2E activation smoke tests using @gravitykit/e2e-bootstrap
  • Creates package.json from scratch (plugin had no npm setup)
  • Refactors CircleCI config from single build job to prepare → e2e → build pipeline
  • Adds .env.sample and E2E/environment entries to .gitignore

Why

Rolling out activation smoke tests across all GravityKit plugins to catch issues before releases — e.g. vendor namespacing bugs that crash plugins on activation.

Test plan

  • Run npm run tests:e2e:setup locally
  • Run npm run tests:e2e and verify all 3 activation tests pass
  • Confirm CI pipeline runs all three jobs in order

Summary by CodeRabbit

  • Tests
    • Added end-to-end Playwright tests with global setup/teardown and activation smoke tests to validate plugin activation and key admin pages load without fatal errors.
  • Chores
    • CI updated to a two-phase workflow that prepares a persisted test/build workspace, runs E2E tests with retries and collects artifacts, then builds the package.
    • Added test tooling manifest, sample .env for plugin/license keys, and .gitignore rules for E2E artifacts.

💾 Build file (7f30e42).

Adds Playwright E2E activation smoke tests using the shared
@gravitykit/e2e-bootstrap package. Refactors CircleCI config from a
single build job into prepare + e2e + build stages.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 2, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: de8e67cf-144c-41ad-8d77-b031dab02da9

📥 Commits

Reviewing files that changed from the base of the PR and between 7f30e42 and 4ea8358.

📒 Files selected for processing (1)
  • package.json

Walkthrough

Adds Playwright E2E test infrastructure and CI orchestration: new CircleCI two-phase jobs (prepare -> run E2e -> build), npm/Playwright configs and scripts, wp-env setup files, .env.sample and .gitignore updates, and an initial E2E test suite that verifies plugin activation and error-free admin pages. (50 words)

Changes

Cohort / File(s) Summary
CI/CD Pipeline
​.circleci/config.yml
Replaces single build_package_release job with a two-phase flow: prepare_test_and_build_environment (checkout, clone tooling, restore/save Composer & Node caches, install deps, download GF zips, generate .env, persist workspace) and run_e2e_tests (attach workspace, run npm run tests:e2e:setup with retries, run Playwright, collect artifacts/JUnit). build_package_release now attaches persisted workspace and depends on run_e2e_tests. Minor zip -d spacing fix.
Env & Ignore
.env.sample, .gitignore
Adds .env.sample with WP_ENV_PLUGINS, GRAVITY_FORMS_LICENSE_KEY, GRAVITYKIT_LICENSE_KEY and commented E2E vars. .gitignore now excludes .env, wp-env artifacts under tests/E2E/setup/ and tests/E2E/results/ / tests/E2E/report/.
JS Tooling / Scripts
package.json
Adds package manifest with scripts to generate/start/stop wp-env and run E2E setup and Playwright tests. Declares devDependencies including @gravitykit/e2e-bootstrap, @playwright/test@1.56.1, and @wordpress/env.
E2E Bootstrap & Config
tests/E2E/setup/playwright.config.js, tests/E2E/setup/playwright.global.setup.js, tests/E2E/setup/playwright.global.teardown.js, tests/E2E/setup/wp-env.config.js
Adds Playwright config and global setup/teardown wrappers using @gravitykit/e2e-bootstrap factories; adds wp-env config loader that loads .env, calls generateWpEnvConfig with pluginPath/outputDir, and exits nonzero on failure.
E2E Tests
tests/E2E/tests/activation.spec.js
Adds initial Playwright smoke tests checking plugin activation, admin dashboard load, and Gravity Forms admin page load without visible WordPress fatal/technical error messages.

Sequence Diagram(s)

sequenceDiagram
    participant CircleCI as CircleCI Workflow
    participant Prep as prepare_test_and_build_environment
    participant Workspace as Persisted Workspace (/home/circleci)
    participant E2E as run_e2e_tests (xlarge)
    participant WPEnv as wp-env setup (npm/@gravitykit/e2e-bootstrap)
    participant Playwright as Playwright Test Runner
    participant Artifacts as Artifacts & JUnit Store
    participant Build as build_package_release

    CircleCI ->> Prep: start prepare_test_and_build_environment
    Prep ->> Prep: checkout, clone tooling, restore/save caches\ninstall deps, download GF zips, generate `.env`
    Prep ->> Workspace: persist workspace to /home/circleci
    CircleCI ->> E2E: trigger run_e2e_tests (attach workspace)
    E2E ->> Workspace: attach persisted workspace
    E2E ->> WPEnv: run `npm run tests:e2e:setup` (retry up to 3, clear .wp-env between attempts)
    WPEnv -->> E2E: wp-env started
    E2E ->> Playwright: discover specs and execute tests
    Playwright -->> Artifacts: upload traces/screenshots and JUnit results
    CircleCI ->> Build: run build_package_release (depends on run_e2e_tests)
    Build ->> Workspace: attach persisted workspace and continue packaging
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Add E2E smoke tests #236: Adds the same E2E test suite and supporting files and introduces the prepare → run_e2e_tests → build CircleCI flow (strong overlap with these changes).
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title 'Add E2E smoke tests' directly and accurately summarizes the main change: introducing end-to-end smoke tests for plugin activation validation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/e2e-setup

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
.circleci/config.yml (2)

71-75: Retrying setup should also tear down wp-env state.

Deleting /home/circleci/.wp-env only clears the local metadata directory. If npm run tests:e2e:setup already started Docker containers or volumes, the next iteration is still reusing stale state, so the retry loop may not actually recover the failure.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.circleci/config.yml around lines 71 - 75, The retry loop that runs npm run
tests:e2e:setup should also perform a full wp-env teardown before deleting
/home/circleci/.wp-env so stale containers/volumes aren’t reused; update the
while loop (the block around npm run tests:e2e:setup) to run the project’s
teardown routine (for example invoking the wp-env stop/destroy or npm run
tests:e2e:teardown task) on failure, then remove the metadata dir and
sleep/retry, ensuring each attempt starts from a clean wp-env state.

53-56: Scope the workspace to only what downstream jobs actually need.

Persisting /home/circleci/. carries hidden home-directory files, temp downloads, and the .npmrc / .env created earlier into every downstream job. That makes workspace transfers heavier and keeps token/license material on disk longer than necessary.

💡 Keep the workspace narrow
       - persist_to_workspace:
           root: /home/circleci
           paths:
-            - .
+            - plugin
+            - tooling

Then recreate .npmrc and .env in the job that consumes them so they do not get propagated into build_package_release.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.circleci/config.yml around lines 53 - 56, The workspace persistence
currently uses "root: /home/circleci" with "paths: - .", which captures the
entire home including hidden files; change the persist_to_workspace stanza to
only persist the specific repo/build artifact directory(ies) needed by
downstream jobs instead of the home root, and remove persisting of dotfiles like
".npmrc" and ".env"; instead, recreate those files in the job that consumes them
(do not persist them into build_package_release). Update the "root" and "paths"
entries to target the specific project output folder(s) and/or artifact files
referenced by downstream jobs rather than the blanket ".".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.circleci/config.yml:
- Around line 40-41: The unzip step can fail if the glob matches multiple
archives; change the pipeline so the download command and unzip use a single
explicit filename variable instead of relying on an unquoted glob: capture the
downloaded archive name (e.g., from the output of
"/home/circleci/tooling/build-tools/build_tools.sh gh -o 'release download -R
gravityforms/gravityforms --clobber --pattern \"*.zip\" --dir .tmp'"), assert
that exactly one file matches in .tmp (fail the job if more/none), assign that
single path to a variable (e.g., GF_ZIP) and then call "unzip $GF_ZIP -d .tmp"
so shell glob expansion cannot pass multiple args to unzip.

---

Nitpick comments:
In @.circleci/config.yml:
- Around line 71-75: The retry loop that runs npm run tests:e2e:setup should
also perform a full wp-env teardown before deleting /home/circleci/.wp-env so
stale containers/volumes aren’t reused; update the while loop (the block around
npm run tests:e2e:setup) to run the project’s teardown routine (for example
invoking the wp-env stop/destroy or npm run tests:e2e:teardown task) on failure,
then remove the metadata dir and sleep/retry, ensuring each attempt starts from
a clean wp-env state.
- Around line 53-56: The workspace persistence currently uses "root:
/home/circleci" with "paths: - .", which captures the entire home including
hidden files; change the persist_to_workspace stanza to only persist the
specific repo/build artifact directory(ies) needed by downstream jobs instead of
the home root, and remove persisting of dotfiles like ".npmrc" and ".env";
instead, recreate those files in the job that consumes them (do not persist them
into build_package_release). Update the "root" and "paths" entries to target the
specific project output folder(s) and/or artifact files referenced by downstream
jobs rather than the blanket ".".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 79bb1a45-1502-4339-b169-335e9b5acffd

📥 Commits

Reviewing files that changed from the base of the PR and between 0d351a0 and ed89cc1.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • .circleci/config.yml
  • .env.sample
  • .gitignore
  • package.json
  • tests/E2E/setup/playwright.config.js
  • tests/E2E/setup/playwright.global.setup.js
  • tests/E2E/setup/playwright.global.teardown.js
  • tests/E2E/setup/wp-env.config.js
  • tests/E2E/tests/activation.spec.js

Comment thread .circleci/config.yml
Comment on lines +40 to +41
/home/circleci/tooling/build-tools/build_tools.sh gh -o 'release download -R gravityforms/gravityforms --clobber --pattern "*.zip" --dir .tmp'
unzip .tmp/gravityforms*.zip -d .tmp
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's find and examine the CircleCI config file
find . -name "config.yml" -path "*/.circleci/*" | head -5

Repository: GravityKit/GravityExport-Lite

Length of output: 95


🏁 Script executed:

# Read the relevant section of the CircleCI config around lines 40-41
if [ -f ".circleci/config.yml" ]; then
  sed -n '35,50p' .circleci/config.yml | cat -n
fi

Repository: GravityKit/GravityExport-Lite

Length of output: 1089


🌐 Web query:

GitHub CLI (gh) release download --pattern behavior and how it filters zip files

💡 Result:

The GitHub CLI gh release download command uses the --pattern (or -p) flag to filter release assets based on glob patterns. It downloads only assets whose filenames match any of the provided patterns. Key behavior: - Uses Go's filepath.Match function for matching, which supports standard shell glob patterns: * (any characters), ? (single character), [abc] (character class), [a-z] (range). - Multiple patterns can be specified (e.g., -p '.deb' -p '.rpm'); an asset matches if it fits any pattern. - Patterns are case-sensitive on case-sensitive filesystems (Linux/macOS), case-insensitive on Windows. - Examples from docs: --pattern '.deb' downloads Debian packages; --pattern 'amd64.deb' for specific binaries. - For zip files: --pattern '.zip' matches any zip archive asset (e.g., gh release download --pattern '.zip'). - If no assets match, it errors with "no assets match the file pattern". - Without a tag, targets latest release and requires --pattern or --archive. - Note: Default source code zip/tar.gz (not uploaded assets) are handled separately via --archive=zip, not --pattern. Shell quoting matters (e.g., Windows CMD may need adjustments, works better in PowerShell/Git Bash). Complex regex-like patterns (e.g., alternations with |) do not work; use simple globs.

Citations:


🌐 Web query:

unzip command glob pattern behavior with multiple matching files

💡 Result:

The unzip command supports glob patterns (wildcards like , ?, []) both for specifying multiple ZIP archive files and for selecting multiple files within a single archive to extract. When specifying the ZIP file(s) with a glob pattern (e.g., unzip '.zip'), quote the pattern to prevent shell expansion. Without quotes, the shell expands .zip to individual filenames, causing unzip to treat the first as the archive and the rest as internal files, resulting in "filename not matched" errors for the others. With quotes (e.g., unzip '.zip'), unzip receives the literal pattern, expands it internally, and processes each matching archive in OS-determined order. For extracting specific files from an archive using a glob (e.g., unzip archive.zip '.txt'), quote the pattern so unzip—not the shell—performs the matching against archive members. Unzip's wildcards match sequences of characters (), single characters (?), or bracketed sets/ranges ([abc], [a-z]). By default, wildcards match '/' directory separators, so patterns can span subdirectories unless modified by options like -W. Multiple matching files are all extracted. Examples from man pages: - unzip source.zip "*.[fch]" Makefile -d /tmp (extracts all *.f, *.c, *.h, and Makefile) - unzip foo *.[ch] -x / (extracts C source files from main directory only) Sources confirm this behavior consistently across Unix-like systems (Ubuntu, Oracle Solaris, Linux man pages).

Citations:


Select exactly one Gravity Forms archive before extraction.

Line 40 downloads all .zip files from the gravityforms release, but line 41 uses an unquoted glob pattern gravityforms*.zip. If the shell expands this to multiple files, unzip receives them as separate arguments—treating the first as the archive and interpreting the rest as file patterns to extract from it, causing extraction to fail or produce unexpected results.

Narrow the download pattern to gravityforms*.zip, assert a single match, and use an explicit variable to avoid shell glob expansion:

Suggested fix
-            /home/circleci/tooling/build-tools/build_tools.sh gh -o 'release download -R gravityforms/gravityforms --clobber --pattern "*.zip" --dir .tmp'
-            unzip .tmp/gravityforms*.zip -d .tmp
+            /home/circleci/tooling/build-tools/build_tools.sh gh -o 'release download -R gravityforms/gravityforms --clobber --pattern "gravityforms*.zip" --dir .tmp'
+            zip_count=$(find .tmp -maxdepth 1 -type f -name 'gravityforms*.zip' | wc -l)
+            [ "$zip_count" -eq 1 ] || { echo "Expected exactly one Gravity Forms zip, found $zip_count"; exit 1; }
+            zip_file=$(find .tmp -maxdepth 1 -type f -name 'gravityforms*.zip')
+            unzip "$zip_file" -d .tmp
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/home/circleci/tooling/build-tools/build_tools.sh gh -o 'release download -R gravityforms/gravityforms --clobber --pattern "*.zip" --dir .tmp'
unzip .tmp/gravityforms*.zip -d .tmp
/home/circleci/tooling/build-tools/build_tools.sh gh -o 'release download -R gravityforms/gravityforms --clobber --pattern "gravityforms*.zip" --dir .tmp'
zip_count=$(find .tmp -maxdepth 1 -type f -name 'gravityforms*.zip' | wc -l)
[ "$zip_count" -eq 1 ] || { echo "Expected exactly one Gravity Forms zip, found $zip_count"; exit 1; }
zip_file=$(find .tmp -maxdepth 1 -type f -name 'gravityforms*.zip')
unzip "$zip_file" -d .tmp
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.circleci/config.yml around lines 40 - 41, The unzip step can fail if the
glob matches multiple archives; change the pipeline so the download command and
unzip use a single explicit filename variable instead of relying on an unquoted
glob: capture the downloaded archive name (e.g., from the output of
"/home/circleci/tooling/build-tools/build_tools.sh gh -o 'release download -R
gravityforms/gravityforms --clobber --pattern \"*.zip\" --dir .tmp'"), assert
that exactly one file matches in .tmp (fail the job if more/none), assign that
single path to a variable (e.g., GF_ZIP) and then call "unzip $GF_ZIP -d .tmp"
so shell glob expansion cannot pass multiple args to unzip.

…ict mode violation

WordPress adds a second <tr data-plugin="..."> for the update notification row.
The broad [data-plugin*="gfexcel.php"] selector matched both rows, causing a
Playwright strict mode violation. Targeting .deactivate a within the plugin row
resolves to a single element regardless of pending updates.
@Mwalek Mwalek requested a review from mrcasual April 2, 2026 11:43
@mrcasual mrcasual merged commit 0529ae6 into develop Apr 2, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants