From 0ccda0d2de02573444b0ff4c2395d24c5acaab14 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 15 Apr 2026 10:15:02 +0200 Subject: [PATCH 01/11] Tests: improve Windows compatibility --- features/plugin-install.feature | 2 +- features/plugin-list-recently-active.feature | 8 ++++++-- features/plugin.feature | 2 +- features/theme-update.feature | 4 ++-- features/theme.feature | 10 +++++----- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/features/plugin-install.feature b/features/plugin-install.feature index 3f7a724dd..85a263c59 100644 --- a/features/plugin-install.feature +++ b/features/plugin-install.feature @@ -168,7 +168,7 @@ Feature: Install WordPress plugins Scenario: Paths aren't backslashed when destination folder already exists Given a WP install - When I run `pwd` + When I run `wp eval "echo str_replace('\\', '/', getcwd());"` Then save STDOUT as {WORKING_DIR} When I run `rm wp-content/plugins/akismet/akismet.php` diff --git a/features/plugin-list-recently-active.feature b/features/plugin-list-recently-active.feature index a3eb97f92..58f80dd46 100644 --- a/features/plugin-list-recently-active.feature +++ b/features/plugin-list-recently-active.feature @@ -63,7 +63,9 @@ Feature: List recently active WordPress plugins Success: Deactivated 2 of 2 plugins. """ - When I run `wp plugin activate $(wp plugin list --recently-active --field=name)` + When I run `wp plugin list --recently-active --field=name` + Then save STDOUT as {RECENTLY_ACTIVE_PLUGINS} + When I run `wp plugin activate {RECENTLY_ACTIVE_PLUGINS}` Then STDOUT should contain: """ Plugin 'debug-bar' activated. @@ -135,7 +137,9 @@ Feature: List recently active WordPress plugins Success: Network deactivated 2 of 2 plugins. """ - When I run `wp plugin activate $(wp plugin list --recently-active --field=name) --network` + When I run `wp plugin list --recently-active --field=name` + Then save STDOUT as {RECENTLY_ACTIVE_PLUGINS_MU} + When I run `wp plugin activate {RECENTLY_ACTIVE_PLUGINS_MU} --network` Then STDOUT should contain: """ Plugin 'site-secrets' network activated. diff --git a/features/plugin.feature b/features/plugin.feature index 558393621..4d82e9252 100644 --- a/features/plugin.feature +++ b/features/plugin.feature @@ -467,7 +467,7 @@ Feature: Manage WordPress plugins Given a WP install When I run `rm -rf wp-content/plugins` - And I run `if test -d wp-content/plugins; then echo "fail"; fi` + And I run `wp eval "if ( is_dir('wp-content/plugins') ) echo 'fail';"` Then STDOUT should be empty When I run `wp plugin install wordpress-importer --activate` diff --git a/features/theme-update.feature b/features/theme-update.feature index 09633781c..75e6ecc44 100644 --- a/features/theme-update.feature +++ b/features/theme-update.feature @@ -264,7 +264,7 @@ Feature: Update WordPress themes And I run `wp theme path twentytwelve --dir` And save STDOUT as {THEME_DIR} - When I run `mkdir {THEME_DIR}/.git` + When I run `wp eval "mkdir('{THEME_DIR}/.git', 0777, true);"` And I try `wp theme update twentytwelve` Then STDERR should contain: """ @@ -282,7 +282,7 @@ Feature: Update WordPress themes And I run `wp theme path twentytwelve --dir` And save STDOUT as {THEME_DIR} - When I run `mkdir {THEME_DIR}/.git` + When I run `wp eval "mkdir('{THEME_DIR}/.git', 0777, true);"` And I run `wp theme update twentytwelve --include-vcs` Then STDOUT should contain: """ diff --git a/features/theme.feature b/features/theme.feature index 53ea0303c..8d4caea9d 100644 --- a/features/theme.feature +++ b/features/theme.feature @@ -243,13 +243,13 @@ Feature: Manage WordPress themes When I run `wp theme list` Then STDOUT should not be empty - When I run `wp eval 'echo get_site_transient("update_themes")->last_checked;'` + When I run `wp eval "echo get_site_transient(\"update_themes\")->last_checked;"` Then save STDOUT as {LAST_UPDATED} When I run `wp theme list --skip-update-check` Then STDOUT should not be empty - When I run `wp eval 'echo get_site_transient("update_themes")->last_checked;'` + When I run `wp eval "echo get_site_transient(\"update_themes\")->last_checked;"` Then STDOUT should be: """ {LAST_UPDATED} @@ -258,7 +258,7 @@ Feature: Manage WordPress themes When I run `wp theme list` Then STDOUT should not be empty - When I run `wp eval 'echo get_site_transient("update_themes")->last_checked;'` + When I run `wp eval "echo get_site_transient(\"update_themes\")->last_checked;"` Then STDOUT should not contain: """ {LAST_UPDATED} @@ -269,7 +269,7 @@ Feature: Manage WordPress themes And I run `wp theme delete --all --force` When I run `rm -rf wp-content/themes` - And I run `if test -d wp-content/themes; then echo "fail"; fi` + And I run `wp eval "if ( is_dir('wp-content/themes') ) echo 'fail';"` Then STDOUT should be empty When I run `wp theme install twentytwelve --activate` @@ -283,7 +283,7 @@ Feature: Manage WordPress themes Scenario: Attempt to activate or fetch a broken theme Given a WP install - When I run `mkdir -pv wp-content/themes/myth` + When I run `wp eval "mkdir('wp-content/themes/myth', 0777, true);"` Then the wp-content/themes/myth directory should exist When I try `wp theme activate myth` From c27a1bf27e3d9d1be601487c360b45211aea1f14 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 15 Apr 2026 11:11:05 +0200 Subject: [PATCH 02/11] fixes --- features/plugin-install.feature | 2 +- features/plugin-list-recently-active.feature | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/features/plugin-install.feature b/features/plugin-install.feature index 85a263c59..8943e7380 100644 --- a/features/plugin-install.feature +++ b/features/plugin-install.feature @@ -168,7 +168,7 @@ Feature: Install WordPress plugins Scenario: Paths aren't backslashed when destination folder already exists Given a WP install - When I run `wp eval "echo str_replace('\\', '/', getcwd());"` + When I run `wp eval "echo str_replace(chr(92), '/', getcwd());"` Then save STDOUT as {WORKING_DIR} When I run `rm wp-content/plugins/akismet/akismet.php` diff --git a/features/plugin-list-recently-active.feature b/features/plugin-list-recently-active.feature index 58f80dd46..2fa97d012 100644 --- a/features/plugin-list-recently-active.feature +++ b/features/plugin-list-recently-active.feature @@ -42,6 +42,8 @@ Feature: List recently active WordPress plugins | debug-bar | | site-secrets | + # Skipped on Windows due to non-portable shell command substitution and newline discrepancies + @skip-windows Scenario: Use recently active plugin to activate plugins Given a WP install @@ -116,6 +118,8 @@ Feature: List recently active WordPress plugins | debug-bar | | site-secrets | + # Skipped on Windows due to non-portable shell command substitution and newline discrepancies + @skip-windows Scenario: For a MU site, use recently active plugin to activate plugins Given a WP multisite install From 0c3893989f643dfc5c5f16c8a3ac9d77c192d2ff Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 15 Apr 2026 11:32:05 +0200 Subject: [PATCH 03/11] more undo --- features/plugin-list-recently-active.feature | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/features/plugin-list-recently-active.feature b/features/plugin-list-recently-active.feature index 2fa97d012..cbd97bf51 100644 --- a/features/plugin-list-recently-active.feature +++ b/features/plugin-list-recently-active.feature @@ -65,9 +65,7 @@ Feature: List recently active WordPress plugins Success: Deactivated 2 of 2 plugins. """ - When I run `wp plugin list --recently-active --field=name` - Then save STDOUT as {RECENTLY_ACTIVE_PLUGINS} - When I run `wp plugin activate {RECENTLY_ACTIVE_PLUGINS}` + When I run `wp plugin activate $(wp plugin list --recently-active --field=name)` Then STDOUT should contain: """ Plugin 'debug-bar' activated. @@ -141,9 +139,7 @@ Feature: List recently active WordPress plugins Success: Network deactivated 2 of 2 plugins. """ - When I run `wp plugin list --recently-active --field=name` - Then save STDOUT as {RECENTLY_ACTIVE_PLUGINS_MU} - When I run `wp plugin activate {RECENTLY_ACTIVE_PLUGINS_MU} --network` + When I run `wp plugin activate $(wp plugin list --recently-active --field=name) --network` Then STDOUT should contain: """ Plugin 'site-secrets' network activated. From 6bb43a1ffa7bee540307c9a16b1078116fa3fe85 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 15 Apr 2026 14:30:58 +0200 Subject: [PATCH 04/11] Double quotes --- features/plugin.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/plugin.feature b/features/plugin.feature index 4d82e9252..a8fef52e2 100644 --- a/features/plugin.feature +++ b/features/plugin.feature @@ -356,13 +356,13 @@ Feature: Manage WordPress plugins Automattic """ - When I run `wp eval 'echo get_site_transient("update_plugins")->last_checked;'` + When I run `wp eval "echo get_site_transient('update_plugins')->last_checked;"` Then save STDOUT as {LAST_UPDATED} When I run `wp plugin list --skip-update-check` Then STDOUT should not be empty - When I run `wp eval 'echo get_site_transient("update_plugins")->last_checked;'` + When I run `wp eval "echo get_site_transient('update_plugins')->last_checked;"` Then STDOUT should be: """ {LAST_UPDATED} From f0efa341cd43de10500b41c4b32d7df9293d129a Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 15 Apr 2026 14:31:23 +0200 Subject: [PATCH 05/11] workaround with eval --- features/plugin-update.feature | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/features/plugin-update.feature b/features/plugin-update.feature index 735777486..df235a964 100644 --- a/features/plugin-update.feature +++ b/features/plugin-update.feature @@ -199,6 +199,8 @@ Feature: Update WordPress plugins # Akismet currently requires WordPress 5.8 @require-wp-5.8 + # Skipped on Windows because chmod does not reliably enforce unwritable files cross-platform + @skip-windows Scenario: Plugin updates that error should not report a success Given a WP install And I run `wp plugin install --force akismet --version=4.0` @@ -248,7 +250,9 @@ Feature: Update WordPress plugins When I run `wp plugin install wordpress-importer --version=0.5` Then STDOUT should not be empty - When I run `sed -i.bak 's/Version: .*/Version: 10000/' $(wp plugin path health-check)` + When I run `wp plugin path health-check` + Then save STDOUT as {PLUGIN_FILE} + When I run `wp eval "$f = trim('{PLUGIN_FILE}'); file_put_contents(\$f, preg_replace('/Version: .*/', 'Version: 10000', file_get_contents(\$f)));"` Then STDOUT should be empty And the return code should be 0 @@ -385,7 +389,7 @@ Feature: Update WordPress plugins And I run `wp plugin path wordpress-importer --dir` And save STDOUT as {PLUGIN_DIR} - When I run `mkdir {PLUGIN_DIR}/.git` + When I run `wp eval "mkdir(trim('{PLUGIN_DIR}') . '/.git', 0777, true);"` And I try `wp plugin update wordpress-importer` Then STDERR should contain: """ @@ -404,7 +408,7 @@ Feature: Update WordPress plugins And I run `wp plugin path wordpress-importer --dir` And save STDOUT as {PLUGIN_DIR} - When I run `mkdir {PLUGIN_DIR}/.git` + When I run `wp eval "mkdir(trim('{PLUGIN_DIR}') . '/.git', 0777, true);"` And I run `wp plugin update wordpress-importer --include-vcs` Then STDOUT should contain: """ From 48daa4c8e0bc7ee9e5eabe6b55e4e5abe71c7907 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 15 Apr 2026 16:27:16 +0200 Subject: [PATCH 06/11] more fixes --- features/plugin-update.feature | 2 +- features/plugin.feature | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/features/plugin-update.feature b/features/plugin-update.feature index df235a964..1a6144579 100644 --- a/features/plugin-update.feature +++ b/features/plugin-update.feature @@ -250,7 +250,7 @@ Feature: Update WordPress plugins When I run `wp plugin install wordpress-importer --version=0.5` Then STDOUT should not be empty - When I run `wp plugin path health-check` + When I run `wp eval "echo wp_normalize_path(WP_PLUGIN_DIR . '/health-check/health-check.php');"` Then save STDOUT as {PLUGIN_FILE} When I run `wp eval "$f = trim('{PLUGIN_FILE}'); file_put_contents(\$f, preg_replace('/Version: .*/', 'Version: 10000', file_get_contents(\$f)));"` Then STDOUT should be empty diff --git a/features/plugin.feature b/features/plugin.feature index a8fef52e2..694454915 100644 --- a/features/plugin.feature +++ b/features/plugin.feature @@ -371,7 +371,7 @@ Feature: Manage WordPress plugins When I run `wp plugin list` Then STDOUT should not be empty - When I run `wp eval 'echo get_site_transient("update_plugins")->last_checked;'` + When I run `wp eval "echo get_site_transient('update_plugins')->last_checked;"` Then STDOUT should not contain: """ {LAST_UPDATED} From 7820e160f0d607a11ccf2d4da70470e15679723e Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 15 Apr 2026 17:06:57 +0200 Subject: [PATCH 07/11] Apply some feedback from code review --- features/theme-update.feature | 2 +- features/theme.feature | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/features/theme-update.feature b/features/theme-update.feature index 75e6ecc44..124ba98d0 100644 --- a/features/theme-update.feature +++ b/features/theme-update.feature @@ -264,7 +264,7 @@ Feature: Update WordPress themes And I run `wp theme path twentytwelve --dir` And save STDOUT as {THEME_DIR} - When I run `wp eval "mkdir('{THEME_DIR}/.git', 0777, true);"` + When I run `wp eval "is_dir( '{THEME_DIR}/.git' ) || mkdir( '{THEME_DIR}/.git', 0777, true ) || exit( 1 );"` And I try `wp theme update twentytwelve` Then STDERR should contain: """ diff --git a/features/theme.feature b/features/theme.feature index 8d4caea9d..ff9c1cc16 100644 --- a/features/theme.feature +++ b/features/theme.feature @@ -243,13 +243,13 @@ Feature: Manage WordPress themes When I run `wp theme list` Then STDOUT should not be empty - When I run `wp eval "echo get_site_transient(\"update_themes\")->last_checked;"` + When I run `wp eval "echo get_site_transient( 'update_themes' )->last_checked;"` Then save STDOUT as {LAST_UPDATED} When I run `wp theme list --skip-update-check` Then STDOUT should not be empty - When I run `wp eval "echo get_site_transient(\"update_themes\")->last_checked;"` + When I run `wp eval "echo get_site_transient( 'update_themes' )->last_checked;"` Then STDOUT should be: """ {LAST_UPDATED} @@ -258,7 +258,7 @@ Feature: Manage WordPress themes When I run `wp theme list` Then STDOUT should not be empty - When I run `wp eval "echo get_site_transient(\"update_themes\")->last_checked;"` + When I run `wp eval "echo get_site_transient( 'update_themes' )->last_checked;"` Then STDOUT should not contain: """ {LAST_UPDATED} @@ -283,7 +283,7 @@ Feature: Manage WordPress themes Scenario: Attempt to activate or fetch a broken theme Given a WP install - When I run `wp eval "mkdir('wp-content/themes/myth', 0777, true);"` + When I run `wp eval "is_dir( 'wp-content/themes/myth' ) || mkdir( 'wp-content/themes/myth', 0777, true ) || exit( 1 );"` Then the wp-content/themes/myth directory should exist When I try `wp theme activate myth` From 9ad41b376d50a12144fa8ca923e3dd30fb62599b Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 15 Apr 2026 17:08:33 +0200 Subject: [PATCH 08/11] skip --- features/plugin-update.feature | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/features/plugin-update.feature b/features/plugin-update.feature index 1a6144579..2bff2b9a8 100644 --- a/features/plugin-update.feature +++ b/features/plugin-update.feature @@ -239,7 +239,8 @@ Feature: Update WordPress plugins """ And the return code should be 0 - @require-wp-5.2 + # Skipped on Windows because of sed usage that would need to be refactored for compatibility. + @require-wp-5.2 @skip-windows Scenario: Updating all plugins with some of them having an invalid version shouldn't report an error Given a WP install And I run `wp plugin delete akismet` @@ -250,9 +251,7 @@ Feature: Update WordPress plugins When I run `wp plugin install wordpress-importer --version=0.5` Then STDOUT should not be empty - When I run `wp eval "echo wp_normalize_path(WP_PLUGIN_DIR . '/health-check/health-check.php');"` - Then save STDOUT as {PLUGIN_FILE} - When I run `wp eval "$f = trim('{PLUGIN_FILE}'); file_put_contents(\$f, preg_replace('/Version: .*/', 'Version: 10000', file_get_contents(\$f)));"` + When I run `sed -i.bak 's/Version: .*/Version: 10000/' $(wp plugin path health-check)` Then STDOUT should be empty And the return code should be 0 From 82cadf1d2050a28c346cfdbdb360626822f22513 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 15 Apr 2026 18:57:42 +0200 Subject: [PATCH 09/11] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- features/theme-update.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/theme-update.feature b/features/theme-update.feature index 124ba98d0..de2eeefda 100644 --- a/features/theme-update.feature +++ b/features/theme-update.feature @@ -282,7 +282,7 @@ Feature: Update WordPress themes And I run `wp theme path twentytwelve --dir` And save STDOUT as {THEME_DIR} - When I run `wp eval "mkdir('{THEME_DIR}/.git', 0777, true);"` + When I run `wp eval "is_dir( '{THEME_DIR}/.git' ) || mkdir( '{THEME_DIR}/.git', 0777, true ) || exit( 1 );"` And I run `wp theme update twentytwelve --include-vcs` Then STDOUT should contain: """ From 75645aab7b5d5202cc05eac00432736a3120f704 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 15 Apr 2026 18:58:03 +0200 Subject: [PATCH 10/11] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- features/plugin-update.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/plugin-update.feature b/features/plugin-update.feature index 2bff2b9a8..d73331758 100644 --- a/features/plugin-update.feature +++ b/features/plugin-update.feature @@ -388,7 +388,7 @@ Feature: Update WordPress plugins And I run `wp plugin path wordpress-importer --dir` And save STDOUT as {PLUGIN_DIR} - When I run `wp eval "mkdir(trim('{PLUGIN_DIR}') . '/.git', 0777, true);"` + When I run `wp eval "$git_dir = trim('{PLUGIN_DIR}') . '/.git'; if ( ! is_dir( $git_dir ) && ! mkdir( $git_dir, 0777, true ) && ! is_dir( $git_dir ) ) { fwrite( STDERR, 'Failed to create VCS marker directory.' ); exit(1); }"` And I try `wp plugin update wordpress-importer` Then STDERR should contain: """ @@ -407,7 +407,7 @@ Feature: Update WordPress plugins And I run `wp plugin path wordpress-importer --dir` And save STDOUT as {PLUGIN_DIR} - When I run `wp eval "mkdir(trim('{PLUGIN_DIR}') . '/.git', 0777, true);"` + When I run `wp eval "$git_dir = trim('{PLUGIN_DIR}') . '/.git'; if ( ! is_dir( $git_dir ) && ! mkdir( $git_dir, 0777, true ) && ! is_dir( $git_dir ) ) { fwrite( STDERR, 'Failed to create VCS marker directory.' ); exit(1); }"` And I run `wp plugin update wordpress-importer --include-vcs` Then STDOUT should contain: """ From 09c411325986b787a5dbec447342126c7b8539b7 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Thu, 16 Apr 2026 18:18:57 +0200 Subject: [PATCH 11/11] Fix tests --- features/plugin-update.feature | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/features/plugin-update.feature b/features/plugin-update.feature index d73331758..771454d67 100644 --- a/features/plugin-update.feature +++ b/features/plugin-update.feature @@ -198,9 +198,8 @@ Feature: Update WordPress plugins """ # Akismet currently requires WordPress 5.8 - @require-wp-5.8 # Skipped on Windows because chmod does not reliably enforce unwritable files cross-platform - @skip-windows + @require-wp-5.8 @skip-windows Scenario: Plugin updates that error should not report a success Given a WP install And I run `wp plugin install --force akismet --version=4.0` @@ -381,14 +380,15 @@ Feature: Update WordPress plugins Success: Updated 2 of 2 plugins. """ - @require-wp-5.2 + # Skipped on Windows because of mkdir usage that would need to be refactored for compatibility. + @require-wp-5.2 @skip-windows Scenario: Skip plugin update when plugin directory is a VCS checkout Given a WP install And I run `wp plugin install wordpress-importer --version=0.5 --force` And I run `wp plugin path wordpress-importer --dir` And save STDOUT as {PLUGIN_DIR} - When I run `wp eval "$git_dir = trim('{PLUGIN_DIR}') . '/.git'; if ( ! is_dir( $git_dir ) && ! mkdir( $git_dir, 0777, true ) && ! is_dir( $git_dir ) ) { fwrite( STDERR, 'Failed to create VCS marker directory.' ); exit(1); }"` + When I run `mkdir {PLUGIN_DIR}/.git` And I try `wp plugin update wordpress-importer` Then STDERR should contain: """ @@ -400,14 +400,15 @@ Feature: Update WordPress plugins """ And the return code should be 1 - @require-wp-5.2 + # Skipped on Windows because of mkdir usage that would need to be refactored for compatibility. + @require-wp-5.2 @skip-windows Scenario: Update plugin in VCS checkout when --include-vcs is set Given a WP install And I run `wp plugin install wordpress-importer --version=0.5 --force` And I run `wp plugin path wordpress-importer --dir` And save STDOUT as {PLUGIN_DIR} - When I run `wp eval "$git_dir = trim('{PLUGIN_DIR}') . '/.git'; if ( ! is_dir( $git_dir ) && ! mkdir( $git_dir, 0777, true ) && ! is_dir( $git_dir ) ) { fwrite( STDERR, 'Failed to create VCS marker directory.' ); exit(1); }"` + When I run `mkdir {PLUGIN_DIR}/.git` And I run `wp plugin update wordpress-importer --include-vcs` Then STDOUT should contain: """