From f6e55350bd07c4ba409e1cd19ac527da200682e0 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Thu, 13 Nov 2025 22:22:48 +0800 Subject: [PATCH 01/18] Member Content: Courses: Improve SQL query for 6.9 compat. --- includes/class-convertkit-output-restrict-content.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/class-convertkit-output-restrict-content.php b/includes/class-convertkit-output-restrict-content.php index c66817893..43a122c68 100644 --- a/includes/class-convertkit-output-restrict-content.php +++ b/includes/class-convertkit-output-restrict-content.php @@ -512,7 +512,7 @@ public function maybe_change_previous_post_where_clause( $where, $in_same_term, $new_where = 'p.post_parent = ' . $post->post_parent . ' AND p.menu_order < ' . $post->menu_order; // Replace existing where statement with new statement. - $where = 'WHERE ' . $new_where . ' ' . substr( $where, strpos( $where, 'AND' ) ); + $where = 'WHERE ' . $new_where . ' ' . substr( $where, strpos( $where, 'AND p.post_type = \'' . $post->post_type . '\' ' ) ); // Return. return $where; @@ -551,7 +551,7 @@ public function maybe_change_next_post_where_clause( $where, $in_same_term, $exc $new_where = 'p.post_parent = ' . $post->post_parent . ' AND p.menu_order > ' . $post->menu_order; // Replace existing where statement with new statement. - $where = 'WHERE ' . $new_where . ' ' . substr( $where, strpos( $where, 'AND' ) ); + $where = 'WHERE ' . $new_where . ' ' . substr( $where, strpos( $where, 'AND p.post_type = \'' . $post->post_type . '\' ' ) ); // Return. return $where; From 7c82265cc6adeaed191f8004dd9426f09d17a984 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Mon, 17 Nov 2025 21:16:38 +0800 Subject: [PATCH 02/18] Tests: Improve Reliability --- tests/Support/Helper/WPBulkEdit.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/Support/Helper/WPBulkEdit.php b/tests/Support/Helper/WPBulkEdit.php index 8f72affd7..3a7d4584a 100644 --- a/tests/Support/Helper/WPBulkEdit.php +++ b/tests/Support/Helper/WPBulkEdit.php @@ -43,9 +43,12 @@ public function bulkEdit($I, $postType, $postIDs, $configuration) } } - // Scroll so that the Update button is in the viewport. - $I->scrollTo('#bulk-edit .inline-edit-wrapper:last-child'); + // Wait, because WooCommerce will scroll back to the top of the page. + $I->wait(2); + // Scroll so that the Update button is in the viewport. + $I->scrollTo('#woocommerce-fields-bulk'); + // Click Update. $I->click('#bulk_edit'); From 58ae5eb604ba68d12498ef6c1db3a740095029a0 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Mon, 17 Nov 2025 21:28:32 +0800 Subject: [PATCH 03/18] Improve bulk edit --- tests/Support/Helper/WPBulkEdit.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/Support/Helper/WPBulkEdit.php b/tests/Support/Helper/WPBulkEdit.php index 3a7d4584a..5100eed84 100644 --- a/tests/Support/Helper/WPBulkEdit.php +++ b/tests/Support/Helper/WPBulkEdit.php @@ -43,12 +43,15 @@ public function bulkEdit($I, $postType, $postIDs, $configuration) } } - // Wait, because WooCommerce will scroll back to the top of the page. + // Wait, because some bulk edit screens (WooCommerce) hijack the UI and scroll back to the top of the page. $I->wait(2); // Scroll so that the Update button is in the viewport. - $I->scrollTo('#woocommerce-fields-bulk'); - + $I->scrollTo('#bulk-edit .inline-edit-wrapper:last-child'); + + // Scroll so that the Update button is in the viewport. + // $I->scrollTo('#woocommerce-fields-bulk'); + // Click Update. $I->click('#bulk_edit'); From 65af43b70269b2d18211c65a5182d9cd51205272 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Mon, 17 Nov 2025 21:28:45 +0800 Subject: [PATCH 04/18] Wait for Plugins page to load after Plugin activation --- tests/Support/Helper/ThirdPartyPlugin.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/Support/Helper/ThirdPartyPlugin.php b/tests/Support/Helper/ThirdPartyPlugin.php index 12c5e0872..9be58b86e 100644 --- a/tests/Support/Helper/ThirdPartyPlugin.php +++ b/tests/Support/Helper/ThirdPartyPlugin.php @@ -68,7 +68,10 @@ public function activateThirdPartyPlugin($I, $name, $wizardExpectsToDisplay = tr break; } - // Wait for the Plugins page to load with the Plugin activated, to confirm it activated. + // Wait for the Plugins page to load. + $I->waitForElementVisible('body.plugins-php'); + + // Confirm the Plugin is activated. $I->waitForElementVisible('table.plugins tr[data-slug=' . $name . '].active'); // Some Plugins throw warnings / errors on activation, so we can't reliably check for errors. From a146847c7e23927adb4f3bea51899ae2235ef1e1 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Mon, 17 Nov 2025 21:42:55 +0800 Subject: [PATCH 05/18] Plugin activation: reload page to avoid stale reference --- tests/Support/Helper/ThirdPartyPlugin.php | 9 ++------- tests/Support/Helper/WPBulkEdit.php | 3 --- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/tests/Support/Helper/ThirdPartyPlugin.php b/tests/Support/Helper/ThirdPartyPlugin.php index 9be58b86e..9092c1f68 100644 --- a/tests/Support/Helper/ThirdPartyPlugin.php +++ b/tests/Support/Helper/ThirdPartyPlugin.php @@ -56,20 +56,15 @@ public function activateThirdPartyPlugin($I, $name, $wizardExpectsToDisplay = tr if ( $wizardExpectsToDisplay ) { $I->waitForElementVisible('body.convertkit'); } - - // Go to the Plugins screen again. - $I->amOnPluginsPage(); break; case 'uncode-wpbakery-page-builder': - // Go to the Plugins screen again. $I->waitForElementVisible('body.toplevel_page_vc-general'); - $I->amOnPluginsPage(); break; } - // Wait for the Plugins page to load. - $I->waitForElementVisible('body.plugins-php'); + // Go to the Plugins screen again. + $I->amOnPluginsPage(); // Confirm the Plugin is activated. $I->waitForElementVisible('table.plugins tr[data-slug=' . $name . '].active'); diff --git a/tests/Support/Helper/WPBulkEdit.php b/tests/Support/Helper/WPBulkEdit.php index 5100eed84..4c1ba5614 100644 --- a/tests/Support/Helper/WPBulkEdit.php +++ b/tests/Support/Helper/WPBulkEdit.php @@ -49,9 +49,6 @@ public function bulkEdit($I, $postType, $postIDs, $configuration) // Scroll so that the Update button is in the viewport. $I->scrollTo('#bulk-edit .inline-edit-wrapper:last-child'); - // Scroll so that the Update button is in the viewport. - // $I->scrollTo('#woocommerce-fields-bulk'); - // Click Update. $I->click('#bulk_edit'); From 6b96a0c2f3eb1bc56aad67b109a6552f030b3185 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Mon, 17 Nov 2025 21:57:19 +0800 Subject: [PATCH 06/18] Login: Improve login reliability --- tests/Support/Helper/ThirdPartyPlugin.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/Support/Helper/ThirdPartyPlugin.php b/tests/Support/Helper/ThirdPartyPlugin.php index 9092c1f68..cc02c4886 100644 --- a/tests/Support/Helper/ThirdPartyPlugin.php +++ b/tests/Support/Helper/ThirdPartyPlugin.php @@ -154,12 +154,15 @@ public function doLoginAsAdmin($I) $I->waitForElementVisible('#user_login'); $I->waitForElementVisible('#user_pass'); $I->waitForElementVisible('#wp-submit'); + $I->waitForElementVisible('#backtoblog'); // Fill in the login form. $I->click('#user_login'); $I->fillField('#user_login', $_ENV['WORDPRESS_ADMIN_USER']); + $I->seeInField('#user_login', $_ENV['WORDPRESS_ADMIN_USER']); $I->click('#user_pass'); $I->fillField('#user_pass', $_ENV['WORDPRESS_ADMIN_PASSWORD']); + $I->seeInField('#user_pass', $_ENV['WORDPRESS_ADMIN_PASSWORD']); // Submit. $I->click('#wp-submit'); From d9d5ba22dc09a09cd4e0ab4663819f29ce8c656d Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Mon, 17 Nov 2025 21:57:35 +0800 Subject: [PATCH 07/18] API: Use microtime() on emails to avoid race condition where two tests have the same email address --- tests/Support/Helper/Email.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Support/Helper/Email.php b/tests/Support/Helper/Email.php index 002ec8b49..79ec94958 100644 --- a/tests/Support/Helper/Email.php +++ b/tests/Support/Helper/Email.php @@ -22,6 +22,6 @@ class Email extends \Codeception\Module */ public function generateEmailAddress($domain = 'kit.com') { - return 'wordpress-' . date( 'Y-m-d-H-i-s' ) . '-php-' . PHP_VERSION_ID . '@' . $domain; + return 'wordpress-' . microtime() . '-php-' . PHP_VERSION_ID . '@' . $domain; } } From f1ce730fd4e02694e93bf5b0defe693ad61f7300 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Mon, 17 Nov 2025 21:59:07 +0800 Subject: [PATCH 08/18] Category Forms: Improve detection of success notice --- .../forms/general/CategoryFormCest.php | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/tests/EndToEnd/forms/general/CategoryFormCest.php b/tests/EndToEnd/forms/general/CategoryFormCest.php index fbb9fdce4..70369b251 100644 --- a/tests/EndToEnd/forms/general/CategoryFormCest.php +++ b/tests/EndToEnd/forms/general/CategoryFormCest.php @@ -212,11 +212,8 @@ public function testEditCategoryWithValidFormSetting(EndToEndTester $I) // Click Update. $I->click('Update'); - // Wait for the page to load. - $I->waitForElementVisible('#wpfooter'); - // Check that the update succeeded. - $I->seeElementInDOM('div.notice-success'); + $I->waitForElementVisible('.notice-success'); // Check that no PHP warnings or notices were output. $I->checkNoWarningsAndNoticesOnScreen($I); @@ -287,11 +284,8 @@ public function testEditCategoryWithNoneFormSetting(EndToEndTester $I) // Click Update. $I->click('Update'); - // Wait for the page to load. - $I->waitForElementVisible('#wpfooter'); - // Check that the update succeeded. - $I->seeElementInDOM('div.notice-success'); + $I->waitForElementVisible('.notice-success'); // Check that no PHP warnings or notices were output. $I->checkNoWarningsAndNoticesOnScreen($I); @@ -487,11 +481,8 @@ public function testEditCategoryWithFormPositionBefore(EndToEndTester $I) // Click Update. $I->click('Update'); - // Wait for the page to load. - $I->waitForElementVisible('#wpfooter'); - // Check that the update succeeded. - $I->seeElementInDOM('div.notice-success'); + $I->waitForElementVisible('.notice-success'); // Check that no PHP warnings or notices were output. $I->checkNoWarningsAndNoticesOnScreen($I); @@ -572,11 +563,8 @@ public function testEditCategoryWithFormPositionAfter(EndToEndTester $I) // Click Update. $I->click('Update'); - // Wait for the page to load. - $I->waitForElementVisible('#wpfooter'); - // Check that the update succeeded. - $I->seeElementInDOM('div.notice-success'); + $I->waitForElementVisible('.notice-success'); // Check that no PHP warnings or notices were output. $I->checkNoWarningsAndNoticesOnScreen($I); From 068d37768a65b3ac0f258bb47ed666dd6aa36b35 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Mon, 17 Nov 2025 21:59:23 +0800 Subject: [PATCH 09/18] Review Request: Improve detection of links --- tests/EndToEnd/general/other/ReviewRequestCest.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/EndToEnd/general/other/ReviewRequestCest.php b/tests/EndToEnd/general/other/ReviewRequestCest.php index 96e20cf1b..d1ba91e5f 100644 --- a/tests/EndToEnd/general/other/ReviewRequestCest.php +++ b/tests/EndToEnd/general/other/ReviewRequestCest.php @@ -195,11 +195,17 @@ public function testReviewRequestNotificationDisplayed(EndToEndTester $I) $I->amOnAdminPage('index.php'); // Confirm the review displays. - $I->seeElementInDOM('div.review-convertkit'); + $I->waitForElementVisible('div.review-convertkit'); // Confirm links are correct. - $I->seeInSource(''); - $I->seeInSource(''); + $I->assertEquals( + $I->grabAttributeFrom('div.review-convertkit a.button-primary', 'href'), + 'https://wordpress.org/support/plugin/convertkit/reviews/?filter=5#new-post' + ); + $I->assertEquals( + $I->grabAttributeFrom('div.review-convertkit a.button:not(.button-primary)', 'href'), + 'https://kit.com/support' + ); } /** From ffa218dae15b34be3c9629a7cd035c91fa79341b Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Mon, 17 Nov 2025 22:15:15 +0800 Subject: [PATCH 10/18] Emails: Use better method for microtime generation --- tests/Support/Helper/Email.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Support/Helper/Email.php b/tests/Support/Helper/Email.php index 79ec94958..a96f761c9 100644 --- a/tests/Support/Helper/Email.php +++ b/tests/Support/Helper/Email.php @@ -22,6 +22,7 @@ class Email extends \Codeception\Module */ public function generateEmailAddress($domain = 'kit.com') { - return 'wordpress-' . microtime() . '-php-' . PHP_VERSION_ID . '@' . $domain; + $date = \DateTime::createFromFormat('U.u', number_format(microtime(true), 6, '.', '')); + return 'wordpress-' . $date->format('Y-m-d-H-i-s-u') . '-php-' . PHP_VERSION_ID . '@' . $domain; } } From 54c53e590649bb8e2f27ede2f3634afb1e91809e Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Mon, 17 Nov 2025 22:44:42 +0800 Subject: [PATCH 11/18] Tests: Member Content Filters: Check filter option selected after submission --- .../general/RestrictContentFilterPageCest.php | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/tests/EndToEnd/restrict-content/general/RestrictContentFilterPageCest.php b/tests/EndToEnd/restrict-content/general/RestrictContentFilterPageCest.php index 4f090c67e..cb36debe0 100644 --- a/tests/EndToEnd/restrict-content/general/RestrictContentFilterPageCest.php +++ b/tests/EndToEnd/restrict-content/general/RestrictContentFilterPageCest.php @@ -104,12 +104,12 @@ public function testFilterByProduct(EndToEndTester $I) $I->selectOption('#wp-convertkit-restrict-content-filter', $_ENV['CONVERTKIT_API_PRODUCT_NAME']); $I->click('Filter'); - // Wait for the WP_List_Table of Pages to load. - $I->waitForElementVisible('tbody#the-list'); - // Check that no PHP warnings or notices were output. $I->checkNoWarningsAndNoticesOnScreen($I); + // Check the filter dropdown is set to the selected value. + $I->seeOptionIsSelected('#wp-convertkit-restrict-content-filter', $_ENV['CONVERTKIT_API_PRODUCT_NAME']); + // Confirm that the Page is still listed, and has the 'Kit Member Content' label. $I->see('Kit: Page: Restricted Content: Product: Filter Test'); $I->see('Kit Member Content'); @@ -153,12 +153,12 @@ public function testFilterByTag(EndToEndTester $I) $I->selectOption('#wp-convertkit-restrict-content-filter', $_ENV['CONVERTKIT_API_TAG_NAME']); $I->click('Filter'); - // Wait for the WP_List_Table of Pages to load. - $I->waitForElementVisible('tbody#the-list'); - // Check that no PHP warnings or notices were output. $I->checkNoWarningsAndNoticesOnScreen($I); + // Check the filter dropdown is set to the selected value. + $I->seeOptionIsSelected('#wp-convertkit-restrict-content-filter', $_ENV['CONVERTKIT_API_TAG_NAME']); + // Confirm that the Page is still listed, and has the 'Kit Member Content' label. $I->see('Kit: Page: Restricted Content: Tag: Filter Test'); $I->see('Kit Member Content'); @@ -203,12 +203,12 @@ public function testFilterByForm(EndToEndTester $I) $I->selectOption('#wp-convertkit-restrict-content-filter', $_ENV['CONVERTKIT_API_FORM_NAME']); $I->click('Filter'); - // Wait for the WP_List_Table of Pages to load. - $I->waitForElementVisible('tbody#the-list'); - // Check that no PHP warnings or notices were output. $I->checkNoWarningsAndNoticesOnScreen($I); + // Check the filter dropdown is set to the selected value. + $I->seeOptionIsSelected('#wp-convertkit-restrict-content-filter', $_ENV['CONVERTKIT_API_FORM_NAME']); + // Confirm that the Page is still listed, and has the 'Kit Member Content' label. $I->see('Kit: Page: Restricted Content: Form: Filter Test'); $I->see('Kit Member Content'); @@ -285,12 +285,12 @@ public function testFilterByAllMemberOnlyContent(EndToEndTester $I) $I->selectOption('#wp-convertkit-restrict-content-filter', 'All member-only content'); $I->click('Filter'); - // Wait for the WP_List_Table of Pages to load. - $I->waitForElementVisible('tbody#the-list'); - // Check that no PHP warnings or notices were output. $I->checkNoWarningsAndNoticesOnScreen($I); + // Check the filter dropdown is set to the selected value. + $I->seeOptionIsSelected('#wp-convertkit-restrict-content-filter', 'All member-only content'); + // Confirm that the Restrict Content Pages are listed. $I->see('Kit: Page: Restricted Content: Form: Filter Test'); $I->see('Kit: Page: Restricted Content: Tag: Filter Test'); @@ -371,9 +371,6 @@ public function testNoFilteringWhenAllContentSelected(EndToEndTester $I) // Click the Filter button with no changes made. $I->click('Filter'); - // Wait for the WP_List_Table of Pages to load. - $I->waitForElementVisible('tbody#the-list'); - // Check that no PHP warnings or notices were output. $I->checkNoWarningsAndNoticesOnScreen($I); From c51a0fe34642471f2622d618776dd63921635814 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 18 Nov 2025 10:45:55 +0800 Subject: [PATCH 12/18] Configure chromedriver to be less flaky --- tests/EndToEnd.suite.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/EndToEnd.suite.yml b/tests/EndToEnd.suite.yml index c6edbd6e3..9bc855a5a 100644 --- a/tests/EndToEnd.suite.yml +++ b/tests/EndToEnd.suite.yml @@ -55,8 +55,10 @@ modules: capabilities: "goog:chromeOptions": args: + - "--headless" - "--disable-gpu" - "--disable-dev-shm-usage" + - "--disable-software-rasterizer" - "--proxy-server='direct://'" - "--proxy-bypass-list=*" - "--no-sandbox" From 03a8228f20c373343f015be5d8ae06e99c4aed05 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 18 Nov 2025 10:46:01 +0800 Subject: [PATCH 13/18] Improve Uncode tests --- ...roductThirdPartyThemeOrPageBuilderCest.php | 38 ++++++++----------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/tests/EndToEnd/restrict-content/post-types/RestrictContentProductThirdPartyThemeOrPageBuilderCest.php b/tests/EndToEnd/restrict-content/post-types/RestrictContentProductThirdPartyThemeOrPageBuilderCest.php index 82970aaa1..d99ac8e32 100644 --- a/tests/EndToEnd/restrict-content/post-types/RestrictContentProductThirdPartyThemeOrPageBuilderCest.php +++ b/tests/EndToEnd/restrict-content/post-types/RestrictContentProductThirdPartyThemeOrPageBuilderCest.php @@ -22,8 +22,14 @@ class RestrictContentProductThirdPartyThemeOrPageBuilderCest */ public function _before(EndToEndTester $I) { - // Activate Kit plugin. + // Activate Kit Plugin and third party Plugins. $I->activateKitPlugin($I); + $I->activateThirdPartyPlugin($I, 'disable-_load_textdomain_just_in_time-doing_it_wrong-notice'); + $I->useTheme('uncode'); + $I->activateThirdPartyPlugin($I, 'uncode-core'); + + // Setup Kit Plugin, disabling JS. + $I->setupKitPluginDisableJS($I); } /** @@ -37,13 +43,7 @@ public function _before(EndToEndTester $I) */ public function testRestrictContentByProductWithUncodeThemeAndVisualComposer(EndToEndTester $I) { - // Setup Kit Plugin, disabling JS. - $I->setupKitPluginDisableJS($I); - - // Activate Uncode theme and Plugins. - $I->activateThirdPartyPlugin($I, 'disable-_load_textdomain_just_in_time-doing_it_wrong-notice'); - $I->useTheme('uncode'); - $I->activateThirdPartyPlugin($I, 'uncode-core'); + // Activate Visual Composer Page Builder. $I->activateThirdPartyPlugin($I, 'uncode-wpbakery-page-builder'); // Programmatically create a Page using the Visual Composer Page Builder. @@ -78,11 +78,8 @@ public function testRestrictContentByProductWithUncodeThemeAndVisualComposer(End ] ); - // Deactivate Uncode theme and Plugins. + // Deactivate Visual Composer Page Builder. $I->deactivateThirdPartyPlugin($I, 'uncode-wpbakery-page-builder'); - $I->deactivateThirdPartyPlugin($I, 'uncode-core'); - $I->useTheme('twentytwentyfive'); - $I->deactivateThirdPartyPlugin($I, 'disable-_load_textdomain_just_in_time-doing_it_wrong-notice'); } /** @@ -96,13 +93,6 @@ public function testRestrictContentByProductWithUncodeThemeAndVisualComposer(End */ public function testRestrictContentByProductWithUncodeTheme(EndToEndTester $I) { - // Setup Kit Plugin, disabling JS. - $I->setupKitPluginDisableJS($I); - - // Activate Uncode theme and Plugins. - $I->useTheme('uncode'); - $I->activateThirdPartyPlugin($I, 'uncode-core'); - // Programmatically create a Page using the Visual Composer Page Builder. $pageID = $I->havePostInDatabase( [ @@ -133,10 +123,6 @@ public function testRestrictContentByProductWithUncodeTheme(EndToEndTester $I) 'member_content' => 'Member-only content.', ] ); - - // Deactivate Uncode theme and Plugins. - $I->deactivateThirdPartyPlugin($I, 'uncode-core'); - $I->useTheme('twentytwentyfive'); } /** @@ -150,6 +136,12 @@ public function testRestrictContentByProductWithUncodeTheme(EndToEndTester $I) */ public function _passed(EndToEndTester $I) { + // Deactivate Plugins and revert to default theme. + $I->deactivateThirdPartyPlugin($I, 'uncode-core'); + $I->useTheme('twentytwentyfive'); + $I->deactivateThirdPartyPlugin($I, 'disable-_load_textdomain_just_in_time-doing_it_wrong-notice'); + + // Deactivate and reset Kit Plugin. $I->clearRestrictContentCookie($I); $I->deactivateKitPlugin($I); $I->resetKitPlugin($I); From 831b68d6b4272f5f6da11ef94723f1cf353afb01 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 18 Nov 2025 11:38:56 +0800 Subject: [PATCH 14/18] Form Builder Tests: Improve reliability --- .../PageBlockFormBuilderCest.php | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/tests/EndToEnd/forms/blocks-shortcodes/PageBlockFormBuilderCest.php b/tests/EndToEnd/forms/blocks-shortcodes/PageBlockFormBuilderCest.php index 994f6045d..1319b02a4 100644 --- a/tests/EndToEnd/forms/blocks-shortcodes/PageBlockFormBuilderCest.php +++ b/tests/EndToEnd/forms/blocks-shortcodes/PageBlockFormBuilderCest.php @@ -149,7 +149,7 @@ public function testFormBuilderBlockWithDefaultConfiguration(EndToEndTester $I) $I->click('div.wp-block-convertkit-form-builder button[type="submit"]'); // Confirm that the message and form is displayed. - $I->waitForElementVisible('body.page'); + $I->waitForElementVisible('.convertkit-form-builder-subscribed-message'); $I->see('Thanks for subscribing!'); $I->seeElementInDOM('input[name="convertkit[first_name]"]'); $I->seeElementInDOM('input[name="convertkit[email]"]'); @@ -265,12 +265,11 @@ public function testFormBuilderBlockWithTextCustomization(EndToEndTester $I) $I->fillField('input[name="convertkit[first_name]"]', 'First'); $I->fillField('input[name="convertkit[email]"]', $emailAddress); $I->click('div.wp-block-convertkit-form-builder button[type="submit"]'); - $I->waitForElementVisible('body.page'); // Check that the form no longer displays and the message displays. $I->dontSeeElementInDOM('input[name="convertkit[first_name]"]'); $I->dontSeeElementInDOM('input[name="convertkit[email]"]'); - $I->see('Welcome to the newsletter!'); + $I->waitForText('Welcome to the newsletter!', 10, '.convertkit-form-builder.wp-block-convertkit-form-builder'); // Confirm that the email address was added to Kit. $I->apiCheckSubscriberExists( @@ -367,10 +366,9 @@ public function testFormBuilderBlockWithFormEnabled(EndToEndTester $I) $I->fillField('input[name="convertkit[first_name]"]', 'First'); $I->fillField('input[name="convertkit[email]"]', $emailAddress); $I->click('div.wp-block-convertkit-form-builder button[type="submit"]'); - $I->waitForElementVisible('body.page'); // Confirm that the email address was added to Kit. - $I->waitForElementVisible('body.page'); + $I->waitForElementVisible('.convertkit-form-builder-subscribed-message'); $I->wait(3); $subscriber = $I->apiCheckSubscriberExists( $I, @@ -474,10 +472,9 @@ public function testFormBuilderBlockWithTaggingEnabled(EndToEndTester $I) $I->fillField('input[name="convertkit[first_name]"]', 'First'); $I->fillField('input[name="convertkit[email]"]', $emailAddress); $I->click('div.wp-block-convertkit-form-builder button[type="submit"]'); - $I->waitForElementVisible('body.page'); // Confirm that the email address was added to Kit. - $I->waitForElementVisible('body.page'); + $I->waitForElementVisible('.convertkit-form-builder-subscribed-message'); $I->wait(3); $subscriber = $I->apiCheckSubscriberExists( $I, @@ -580,10 +577,9 @@ public function testFormBuilderBlockWithSequenceEnabled(EndToEndTester $I) $I->fillField('input[name="convertkit[first_name]"]', 'First'); $I->fillField('input[name="convertkit[email]"]', $emailAddress); $I->click('div.wp-block-convertkit-form-builder button[type="submit"]'); - $I->waitForElementVisible('body.page'); // Confirm that the email address was added to Kit. - $I->waitForElementVisible('body.page'); + $I->waitForElementVisible('.convertkit-form-builder-subscribed-message'); $I->wait(3); $subscriber = $I->apiCheckSubscriberExists( $I, @@ -718,7 +714,7 @@ public function testFormBuilderBlockWithCustomField(EndToEndTester $I) $I->click('div.wp-block-convertkit-form-builder button[type="submit"]'); // Confirm that the email address was added to Kit. - $I->waitForElementVisible('body.page'); + $I->waitForElementVisible('.convertkit-form-builder-subscribed-message'); $I->wait(3); $subscriber = $I->apiCheckSubscriberExists( $I, @@ -1051,7 +1047,7 @@ public function testFormBuilderWithRecaptchaEnabled(EndToEndTester $I) $I->click('div.wp-block-convertkit-form-builder button[type="submit"]'); // Confirm that the email address was added to Kit. - $I->waitForElementVisible('body.page'); + $I->waitForElementVisible('.convertkit-form-builder-subscribed-message'); $I->wait(3); $I->apiCheckSubscriberExists( $I, @@ -1118,7 +1114,6 @@ public function testFormBuilderWithRecaptchaEnabledAndHighMinimumScore(EndToEndT $I->click('div.wp-block-convertkit-form-builder button[type="submit"]'); // Confirm that the email address was not added to Kit, as reCAPTCHA score failed. - $I->waitForElementVisible('body.page'); $I->wait(3); $I->apiCheckSubscriberDoesNotExist($I, $emailAddress); } @@ -1192,7 +1187,7 @@ public function testFormBuilderWithStoreEntriesEnabled(EndToEndTester $I) $I->click('div.wp-block-convertkit-form-builder button[type="submit"]'); // Confirm that the email address was added to Kit. - $I->waitForElementVisible('body.page'); + $I->waitForElementVisible('.convertkit-form-builder-subscribed-message'); $I->wait(3); $subscriber = $I->apiCheckSubscriberExists( $I, From 100c86889fbfec6315a0e3737c2fe2697e648b26 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 18 Nov 2025 11:55:56 +0800 Subject: [PATCH 15/18] GitHub Actions: Run integration tests in own matrix --- .github/workflows/tests.yml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4e71c3fa8..e4c920b87 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -72,7 +72,8 @@ jobs: 'EndToEnd/products', 'EndToEnd/restrict-content/general', 'EndToEnd/restrict-content/post-types', - 'EndToEnd/tags' + 'EndToEnd/tags', + 'Integration' ] # Steps to install, configure and run tests @@ -313,14 +314,7 @@ jobs: working-directory: ${{ env.PLUGIN_DIR }} run: php vendor/bin/codecept build - # Run Codeception Integration Tests on the PHP 8.3 instance before the EndToEnd/tags End to End tests. - # We run these once to avoid hitting API rate limits. - - name: Run tests/wpunit - if: ${{ matrix.php-versions == '8.3' && matrix.test-groups == 'EndToEnd/tags' }} - working-directory: ${{ env.PLUGIN_DIR }} - run: php vendor/bin/codecept run tests/Integration --fail-fast - - # Run Codeception End to End Tests + # Run Codeception Tests. - name: Run tests/${{ matrix.test-groups }} working-directory: ${{ env.PLUGIN_DIR }} run: php vendor/bin/codecept run tests/${{ matrix.test-groups }} --fail-fast From 5f931811a367f0cb47a4c2906a9c9a5ead0dab50 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 18 Nov 2025 12:45:13 +0800 Subject: [PATCH 16/18] Isolate review request test --- .github/workflows/tests.yml | 19 +------------------ .../other/ActivateDeactivatePluginCest.php | 2 +- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e4c920b87..9dbd541f0 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -56,24 +56,7 @@ jobs: # Folder names within the 'tests' folder to run tests in parallel. test-groups: [ - 'EndToEnd/broadcasts/blocks-shortcodes', - 'EndToEnd/broadcasts/import-export', - 'EndToEnd/forms/blocks-shortcodes', - 'EndToEnd/forms/general', - 'EndToEnd/forms/post-types', - 'EndToEnd/general/other', - 'EndToEnd/general/plugin-screens', - 'EndToEnd/integrations/divi-builder', - 'EndToEnd/integrations/divi-theme', - 'EndToEnd/integrations/other', - 'EndToEnd/integrations/wlm', - 'EndToEnd/integrations/woocommerce', - 'EndToEnd/landing-pages', - 'EndToEnd/products', - 'EndToEnd/restrict-content/general', - 'EndToEnd/restrict-content/post-types', - 'EndToEnd/tags', - 'Integration' + 'EndToEnd/general/other' ] # Steps to install, configure and run tests diff --git a/tests/EndToEnd/general/other/ActivateDeactivatePluginCest.php b/tests/EndToEnd/general/other/ActivateDeactivatePluginCest.php index 99c8122f6..88dfd4e37 100644 --- a/tests/EndToEnd/general/other/ActivateDeactivatePluginCest.php +++ b/tests/EndToEnd/general/other/ActivateDeactivatePluginCest.php @@ -57,7 +57,7 @@ public function testPluginActivationAndDeactivationWithOtherPlugins(EndToEndTest $I->checkNoWarningsAndNoticesOnScreen($I); // Deactivate Plugins. - $I->deactivateKitPlugin($I); $I->deactivateThirdPartyPlugin($I, 'convertkit-for-woocommerce'); + $I->deactivateKitPlugin($I); } } From 3660cfa4aedacfc6deac167286174790f63ea222 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 18 Nov 2025 12:54:29 +0800 Subject: [PATCH 17/18] Reinstate all tests --- .github/workflows/tests.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9dbd541f0..e4c920b87 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -56,7 +56,24 @@ jobs: # Folder names within the 'tests' folder to run tests in parallel. test-groups: [ - 'EndToEnd/general/other' + 'EndToEnd/broadcasts/blocks-shortcodes', + 'EndToEnd/broadcasts/import-export', + 'EndToEnd/forms/blocks-shortcodes', + 'EndToEnd/forms/general', + 'EndToEnd/forms/post-types', + 'EndToEnd/general/other', + 'EndToEnd/general/plugin-screens', + 'EndToEnd/integrations/divi-builder', + 'EndToEnd/integrations/divi-theme', + 'EndToEnd/integrations/other', + 'EndToEnd/integrations/wlm', + 'EndToEnd/integrations/woocommerce', + 'EndToEnd/landing-pages', + 'EndToEnd/products', + 'EndToEnd/restrict-content/general', + 'EndToEnd/restrict-content/post-types', + 'EndToEnd/tags', + 'Integration' ] # Steps to install, configure and run tests From 5c6c288fce3334e7bed0a10f70670a8ebb71dcc1 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 18 Nov 2025 14:06:21 +0800 Subject: [PATCH 18/18] Switch back to main frame after viewing an iframe --- .../EndToEnd/integrations/other/ContactForm7FormCest.php | 3 +++ tests/EndToEnd/integrations/other/ForminatorCest.php | 3 +++ tests/EndToEnd/products/PageBlockProductCest.php | 9 +++++++++ tests/EndToEnd/products/PageShortcodeProductCest.php | 9 +++++++++ 4 files changed, 24 insertions(+) diff --git a/tests/EndToEnd/integrations/other/ContactForm7FormCest.php b/tests/EndToEnd/integrations/other/ContactForm7FormCest.php index dea304b75..e9a1cc2b4 100644 --- a/tests/EndToEnd/integrations/other/ContactForm7FormCest.php +++ b/tests/EndToEnd/integrations/other/ContactForm7FormCest.php @@ -359,6 +359,9 @@ function($I) { $I->waitForElementVisible('.formkit-modal'); $I->switchToIFrame('.formkit-modal iframe'); $I->waitForElementVisible('main[data-component="Page"]'); + + // Switch back to main window. + $I->switchToIFrame(); } /** diff --git a/tests/EndToEnd/integrations/other/ForminatorCest.php b/tests/EndToEnd/integrations/other/ForminatorCest.php index d2313cbe1..a37fdb5d1 100644 --- a/tests/EndToEnd/integrations/other/ForminatorCest.php +++ b/tests/EndToEnd/integrations/other/ForminatorCest.php @@ -524,6 +524,9 @@ function($I) { $I->waitForElementVisible('.formkit-modal'); $I->switchToIFrame('.formkit-modal iframe'); $I->waitForElementVisible('main[data-component="Page"]'); + + // Switch back to main window. + $I->switchToIFrame(); } /** diff --git a/tests/EndToEnd/products/PageBlockProductCest.php b/tests/EndToEnd/products/PageBlockProductCest.php index a326c7964..a3b901a85 100644 --- a/tests/EndToEnd/products/PageBlockProductCest.php +++ b/tests/EndToEnd/products/PageBlockProductCest.php @@ -256,6 +256,9 @@ public function testProductBlockWithValidDiscountCodeParameter(EndToEndTester $I $I->switchToIFrame('iframe[data-active]'); $I->waitForElementVisible('.formkit-main'); $I->see('$0.00'); + + // Switch back to main window. + $I->switchToIFrame(); } /** @@ -312,6 +315,9 @@ public function testProductBlockWithInvalidDiscountCodeParameter(EndToEndTester $I->switchToIFrame('iframe[data-active]'); $I->waitForElementVisible('.formkit-main'); $I->see('The coupon is not valid.'); + + // Switch back to main window. + $I->switchToIFrame(); } /** @@ -369,6 +375,9 @@ public function testProductBlockWithCheckoutParameterEnabled(EndToEndTester $I) $I->switchToIFrame('iframe[data-active]'); $I->waitForElementVisible('.formkit-main'); $I->see('Order Summary'); + + // Switch back to main window. + $I->switchToIFrame(); } /** diff --git a/tests/EndToEnd/products/PageShortcodeProductCest.php b/tests/EndToEnd/products/PageShortcodeProductCest.php index 56b42ce4e..b710c7b7f 100644 --- a/tests/EndToEnd/products/PageShortcodeProductCest.php +++ b/tests/EndToEnd/products/PageShortcodeProductCest.php @@ -262,6 +262,9 @@ public function testProductShortcodeInVisualEditorWithValidDiscountCodeParameter $I->switchToIFrame('iframe[data-active]'); $I->waitForElementVisible('.formkit-main'); $I->see('$0.00'); + + // Switch back to main window. + $I->switchToIFrame(); } /** @@ -308,6 +311,9 @@ public function testProductShortcodeInVisualEditorWithInvalidDiscountCodeParamet $I->switchToIFrame('iframe[data-active]'); $I->waitForElementVisible('.formkit-main'); $I->see('The coupon is not valid.'); + + // Switch back to main window. + $I->switchToIFrame(); } /** @@ -355,6 +361,9 @@ public function testProductShortcodeWithCheckoutParameterEnabled(EndToEndTester $I->switchToIFrame('iframe[data-active]'); $I->waitForElementVisible('.formkit-main'); $I->see('Order Summary'); + + // Switch back to main window. + $I->switchToIFrame(); } /**