From 49311f8b6f313b982a1cb9770add24759357f0dc Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 8 Sep 2026 14:20:54 +0800 Subject: [PATCH 1/5] Tests: Wait for subscriber --- tests/Support/Helper/KitAPI.php | 152 +++++++++++++++++++------------- 1 file changed, 91 insertions(+), 61 deletions(-) diff --git a/tests/Support/Helper/KitAPI.php b/tests/Support/Helper/KitAPI.php index 51f00d494..0924cddb9 100644 --- a/tests/Support/Helper/KitAPI.php +++ b/tests/Support/Helper/KitAPI.php @@ -49,10 +49,7 @@ public function apiEncodeState($returnTo, $clientID) */ public function apiCheckSubscriberExists($I, $emailAddress, $firstName = false) { - // Wait for the API to update. - $I->wait(3); - - // Retry the API request as sometimes there's a lag before the subscriber is queryable via the API. + // Wait for the subscriber to be queryable, as list endpoints are eventually consistent. $results = $this->retryUntil( function () use ($emailAddress) { $results = $this->apiRequest( @@ -74,7 +71,10 @@ function () use ($emailAddress) { ); // Check at least one subscriber was returned and it matches the email address. - $I->assertNotFalse($results); + $I->assertNotFalse( + $results, + sprintf('Subscriber %s was not returned by the API in time.', $emailAddress) + ); $I->assertGreaterThan(0, $results['pagination']['total_count']); $I->assertEquals($emailAddress, $results['subscribers'][0]['email_address']); @@ -99,27 +99,35 @@ function () use ($emailAddress) { */ public function apiCheckSubscriberHasForm($I, $subscriberID, $formID, $referrer = false) { - // Run request. - $results = $this->apiRequest( - 'forms/' . $formID . '/subscribers', - 'GET', - [ - // Check all subscriber states. - 'status' => 'all', - ] - ); + // Wait for the subscriber to be assigned to the form, as list endpoints are eventually consistent. + $subscriber = $this->retryUntil( + function () use ($subscriberID, $formID) { + $results = $this->apiRequest( + 'forms/' . $formID . '/subscribers', + 'GET', + [ + // Check all subscriber states. + 'status' => 'all', + ] + ); - // Iterate through subscribers. - $subscriberHasForm = false; - foreach ($results['subscribers'] as $subscriber) { - if ($subscriber['id'] === $subscriberID) { - $subscriberHasForm = true; - break; + // Return the subscriber only if they're assigned to the form, so + // retryUntil() will keep trying otherwise. + foreach ($results['subscribers'] as $subscriber) { + if ( (int) $subscriber['id'] === (int) $subscriberID) { + return $subscriber; + } + } + + return false; } - } + ); - // Assert if the subscriber has the form. - $this->assertTrue($subscriberHasForm); + // Assert the subscriber has the form. + $I->assertNotFalse( + $subscriber, + sprintf('Subscriber %s was not assigned to Form %s in time.', $subscriberID, $formID) + ); // If a referrer is specified, assert it matches the subscriber's referrer now. if ($referrer) { @@ -138,26 +146,34 @@ public function apiCheckSubscriberHasForm($I, $subscriberID, $formID, $referrer */ public function apiCheckSubscriberHasSequence($I, $subscriberID, $sequenceID) { - // Run request. - $results = $this->apiRequest( - 'sequences/' . $sequenceID . '/subscribers', - 'GET', - [ - 'status' => 'all', - ] - ); + // Wait for the subscriber to be assigned to the sequence, as list endpoints are eventually consistent. + $subscriber = $this->retryUntil( + function () use ($subscriberID, $sequenceID) { + $results = $this->apiRequest( + 'sequences/' . $sequenceID . '/subscribers', + 'GET', + [ + 'status' => 'all', + ] + ); - // Iterate through subscribers. - $subscriberHasSequence = false; - foreach ($results['subscribers'] as $subscriber) { - if ($subscriber['id'] === $subscriberID) { - $subscriberHasSequence = true; - break; + // Return the subscriber only if they're assigned to the sequence, so + // retryUntil() will keep trying otherwise. + foreach ($results['subscribers'] as $subscriber) { + if ( (int) $subscriber['id'] === (int) $subscriberID) { + return $subscriber; + } + } + + return false; } - } + ); - // Assert if the subscriber has the sequence. - $this->assertTrue($subscriberHasSequence); + // Assert the subscriber has the sequence. + $I->assertNotFalse( + $subscriber, + sprintf('Subscriber %s was not assigned to Sequence %s in time.', $subscriberID, $sequenceID) + ); } /** @@ -169,10 +185,24 @@ public function apiCheckSubscriberHasSequence($I, $subscriberID, $sequenceID) */ public function apiCheckSubscriberHasTag($I, $subscriberID, $tagID) { - // Run request. - $results = $this->apiRequest( - 'subscribers/' . $subscriberID . '/tags', - 'GET' + // Wait for the tag to be assigned to the subscriber, as list endpoints are eventually consistent. + $results = $this->retryUntil( + function () use ($subscriberID) { + $results = $this->apiRequest( + 'subscribers/' . $subscriberID . '/tags', + 'GET' + ); + + // Return the results only if a tag is assigned, so + // retryUntil() will keep trying otherwise. + return count($results['tags']) ? $results : false; + } + ); + + // Assert the subscriber has a tag. + $I->assertNotFalse( + $results, + sprintf('Subscriber %s was not assigned Tag %s in time.', $subscriberID, $tagID) ); // Confirm the tag has been assigned to the subscriber. @@ -316,8 +346,8 @@ public function apiRequest($endpoint, $method = 'GET', $params = array()) [ 'headers' => [ 'Authorization' => 'Bearer ' . $_ENV['CONVERTKIT_OAUTH_ACCESS_TOKEN'], - 'timeout' => 5, ], + 'timeout' => 5, ] ); break; @@ -331,8 +361,8 @@ public function apiRequest($endpoint, $method = 'GET', $params = array()) 'Accept' => 'application/json', 'Content-Type' => 'application/json; charset=utf-8', 'Authorization' => 'Bearer ' . $_ENV['CONVERTKIT_OAUTH_ACCESS_TOKEN'], - 'timeout' => 5, ], + 'timeout' => 5, 'body' => (string) json_encode($params), // phpcs:ignore WordPress.WP.AlternativeFunctions ] ); @@ -344,24 +374,24 @@ public function apiRequest($endpoint, $method = 'GET', $params = array()) } /** - * Repeatedly invokes the given callback until it returns a truthy value, or - * the maximum number of attempts is reached. + * Repeatedly invokes the given callback until it returns a truthy value, or the + * maximum number of attempts is reached. + * + * Use this to wrap API checks that can be flaky due to eventual consistency at Kit's + * end. List endpoints typically reflect a write within ~30 seconds, and can take up + * to 5 minutes, so reading back immediately after a write is not reliable. * - * Use this to wrap API checks that can be flaky due to ingestion lag at - * Kit's end (e.g. a subscriber created via a form submission isn't always - * immediately queryable via the `subscribers` endpoint). + * @since 3.4.1 * - * @since 3.3.2 + * @see https://developers.kit.com/api-reference/eventual-consistency * - * @param callable $callback Callback to invoke. Should return the value - * to use, or false/null to indicate the - * check has not yet succeeded. - * @param int $attempts Maximum number of attempts. - * @param int $delay Seconds to wait between attempts. - * @return mixed The truthy value returned by $callback, or - * false if all attempts are exhausted. + * @param callable $callback Callback to invoke. Should return the value to use, or + * false / null when the check has not yet succeeded. + * @param int $attempts Maximum number of attempts. + * @param int $delay Seconds to wait between attempts. Defaults give up after ~30 seconds. + * @return mixed Value returned by the callback, or false if all attempts are exhausted. */ - private function retryUntil(callable $callback, $attempts = 4, $delay = 3) + public function retryUntil(callable $callback, $attempts = 10, $delay = 3) { for ($i = 0; $i < $attempts; $i++) { $result = $callback(); @@ -370,7 +400,7 @@ private function retryUntil(callable $callback, $attempts = 4, $delay = 3) } // Don't sleep after the final attempt. - if ($i < $attempts - 1) { + if ($i < ( $attempts - 1 )) { sleep($delay); } } From af4387af26c7bdcf669cfdf761ecbc05a55983d3 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 8 Sep 2026 14:54:30 +0800 Subject: [PATCH 2/5] Tests: Log API Requests Logs API requests to fetch the subscriber ID when creating a subscriber by email, so a lookup of the subscriber is faster --- .github/workflows/tests.yml | 21 +-- tests/Support/Helper/KitAPI.php | 164 +++++++++++++----- tests/Support/mu-plugins/kit-api-recorder.php | 53 ++++++ 3 files changed, 177 insertions(+), 61 deletions(-) create mode 100644 tests/Support/mu-plugins/kit-api-recorder.php diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index fb368ebf0..58e8ebf59 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,28 +33,9 @@ jobs: fail-fast: false matrix: wp-version: [ 'latest' ] - php-version: [ '8.2', '8.3', '8.4', '8.5' ] + php-version: [ '8.2' ] test-group: - 'EndToEnd/broadcasts/blocks-shortcodes' - - 'EndToEnd/broadcasts/import-export' - - 'EndToEnd/forms/blocks-shortcodes' - - 'EndToEnd/forms/general' - - 'EndToEnd/forms/post-types' - - 'EndToEnd/general/other' - - 'EndToEnd/general/uninstall' - - 'EndToEnd/general/plugin-screens' - - 'EndToEnd/integrations/divi-builder' - - 'EndToEnd/integrations/divi-theme' - - 'EndToEnd/integrations/elementor' - - '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' uses: ./.github/workflows/_run-tests.yml secrets: inherit diff --git a/tests/Support/Helper/KitAPI.php b/tests/Support/Helper/KitAPI.php index 0924cddb9..aa73fa3d9 100644 --- a/tests/Support/Helper/KitAPI.php +++ b/tests/Support/Helper/KitAPI.php @@ -9,6 +9,91 @@ */ class KitAPI extends \Codeception\Module { + /** + * Installs the Kit API recorder mu-plugin, and clears any previously recorded + * requests, before each test runs. + * + * @since 3.4.1 + * + * @param \Codeception\TestInterface $test Test. + */ + public function _before(\Codeception\TestInterface $test) // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore, Generic.CodeAnalysis.UnusedFunctionParameter + { + $this->getModule('lucatume\WPBrowser\Module\WPFilesystem')->haveMuPlugin( + 'kit-api-recorder.php', + (string) file_get_contents(__DIR__ . '/../mu-plugins/kit-api-recorder.php') // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents + ); + + $this->getModule('lucatume\WPBrowser\Module\WPDb')->haveOptionInDatabase('kit_api_log', []); + } + + /** + * Returns the Kit API requests the Plugin made during this test, optionally + * filtered by method, path and email address. + * + * @since 3.4.1 + * + * @param EndToEndTester $I EndToEndTester. + * @param string $method HTTP method (GET,POST,PUT,DELETE). + * @param string $path Request path, excluding the API version e.g. `subscribers`. + * @param bool|string $emailAddress Email address in the request body. + * @return array + */ + public function grabKitAPIRequests($I, $method = false, $path = false, $emailAddress = false) + { + $log = $I->grabOptionFromDatabase('kit_api_log'); + + if ( ! is_array($log)) { + return []; + } + + return array_values( + array_filter( + $log, + function ($request) use ($method, $path, $emailAddress) { + if ($method && $request['method'] !== $method) { + return false; + } + if ($path && $request['path'] !== $path) { + return false; + } + if ($emailAddress && ( ! array_key_exists('email_address', $request['body']) || $request['body']['email_address'] !== $emailAddress )) { + return false; + } + + return true; + } + ) + ); + } + + /** + * Returns the first Kit API request the Plugin made during this test that matches + * the given method, path and email address, waiting for it to be made. + * + * @since 3.4.1 + * + * @param EndToEndTester $I EndToEndTester. + * @param string $method HTTP method (GET,POST,PUT,DELETE). + * @param string $path Request path, excluding the API version e.g. `subscribers`. + * @param bool|string $emailAddress Email address in the request body. + * @return bool|array + */ + public function grabKitAPIRequest($I, $method, $path, $emailAddress = false) + { + // The request is made by WordPress when the form is submitted, which may not have + // completed when this is called e.g. when a form submits using AJAX. + return $this->retryUntil( + function () use ($I, $method, $path, $emailAddress) { + $requests = $this->grabKitAPIRequests($I, $method, $path, $emailAddress); + + return count($requests) ? $requests[0] : false; + }, + 10, + 1 + ); + } + /** * Returns an encoded `state` parameter compatible with OAuth. * @@ -42,6 +127,12 @@ public function apiEncodeState($returnTo, $clientID) /** * Check the given email address exists as a subscriber. * + * The Plugin's request to create the subscriber is used to determine the subscriber ID, + * as querying the API by email address is subject to eventual consistency. Querying by + * subscriber ID returns strongly consistent results. + * + * @see https://developers.kit.com/api-reference/eventual-consistency + * * @param EndToEndTester $I EndToEndTester. * @param string $emailAddress Email Address. * @param string $firstName First Name (false = don't check name matches). @@ -49,42 +140,33 @@ public function apiEncodeState($returnTo, $clientID) */ public function apiCheckSubscriberExists($I, $emailAddress, $firstName = false) { - // Wait for the subscriber to be queryable, as list endpoints are eventually consistent. - $results = $this->retryUntil( - function () use ($emailAddress) { - $results = $this->apiRequest( - 'subscribers', - 'GET', - [ - 'email_address' => $emailAddress, - 'include_total_count' => true, + // Get the request the Plugin made to create the subscriber. + $request = $this->grabKitAPIRequest($I, 'POST', 'subscribers', $emailAddress); - // Check all subscriber states. - 'status' => 'all', - ] - ); - - // Return the results only if a subscriber was found, so - // retryUntil() will keep trying otherwise. - return ( $results['pagination']['total_count'] > 0 ) ? $results : false; - } - ); - - // Check at least one subscriber was returned and it matches the email address. + // Check the Plugin created the subscriber. $I->assertNotFalse( - $results, - sprintf('Subscriber %s was not returned by the API in time.', $emailAddress) + $request, + sprintf('The Plugin did not send a request to create the subscriber %s.', $emailAddress) + ); + $I->assertLessThan( + 300, + $request['code'], + sprintf('The API returned a %s response when the Plugin created the subscriber %s.', $request['code'], $emailAddress) ); - $I->assertGreaterThan(0, $results['pagination']['total_count']); - $I->assertEquals($emailAddress, $results['subscribers'][0]['email_address']); + + // Fetch the subscriber by their ID, which returns strongly consistent results. + $results = $this->apiRequest('subscribers/' . $request['response']['subscriber']['id'], 'GET'); + + // Check the subscriber matches the email address. + $I->assertEquals($emailAddress, $results['subscriber']['email_address']); // If defined, check that the name matches for the subscriber. if ($firstName) { - $I->assertEquals($firstName, $results['subscribers'][0]['first_name']); + $I->assertEquals($firstName, $results['subscriber']['first_name']); } - // Return subscriber ID. - return $results['subscribers'][0]; + // Return subscriber. + return $results['subscriber']; } /** @@ -232,26 +314,26 @@ public function apiCheckSubscriberHasNoTags($I, $subscriberID) /** * Check the given email address does not exists as a subscriber. * - * @param EndToEndTester $I EndToEndTester. + * The Plugin's requests are checked, instead of querying the API by email address, + * as querying by email address is subject to eventual consistency and would therefore + * return no results for a subscriber that was created. + * + * @see https://developers.kit.com/api-reference/eventual-consistency + * + * @param EndToEndTester $I EndToEndTester. * @param string $emailAddress Email Address. */ public function apiCheckSubscriberDoesNotExist($I, $emailAddress) { - // Wait for the API to update. + // Wait for any request the Plugin might make e.g. when a form submits using AJAX. $I->wait(3); - // Run request. - $results = $this->apiRequest( - 'subscribers', - 'GET', - [ - 'email_address' => $emailAddress, - 'include_total_count' => true, - ] + // Check the Plugin did not create the subscriber. + $I->assertCount( + 0, + $this->grabKitAPIRequests($I, 'POST', 'subscribers', $emailAddress), + sprintf('The Plugin sent a request to create the subscriber %s.', $emailAddress) ); - - // Check no subscribers are returned by this request. - $I->assertEquals(0, $results['pagination']['total_count']); } /** diff --git a/tests/Support/mu-plugins/kit-api-recorder.php b/tests/Support/mu-plugins/kit-api-recorder.php new file mode 100644 index 000000000..ad06f5dd2 --- /dev/null +++ b/tests/Support/mu-plugins/kit-api-recorder.php @@ -0,0 +1,53 @@ + isset( $parsed_args['method'] ) ? $parsed_args['method'] : 'GET', + 'path' => $path, + 'query' => $query, + 'body' => is_array( $body ) ? $body : array(), + 'code' => is_wp_error( $response ) ? 0 : (int) wp_remote_retrieve_response_code( $response ), + 'error' => is_wp_error( $response ) ? $response->get_error_message() : '', + 'response' => is_wp_error( $response ) ? array() : (array) json_decode( wp_remote_retrieve_body( $response ), true ), + ); + + update_option( 'kit_api_log', $log, false ); + }, + 10, + 5 +); From 76e3c52de1058255f49a26f1aeb246dbf86a8998 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 8 Sep 2026 15:02:40 +0800 Subject: [PATCH 3/5] Run specific tests --- .github/workflows/tests.yml | 2 +- tests/Support/Helper/KitAPI.php | 36 ++++++++++++++++----------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 58e8ebf59..36e190723 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -35,7 +35,7 @@ jobs: wp-version: [ 'latest' ] php-version: [ '8.2' ] test-group: - - 'EndToEnd/broadcasts/blocks-shortcodes' + - 'EndToEnd/forms/blocks-shortcodes' uses: ./.github/workflows/_run-tests.yml secrets: inherit diff --git a/tests/Support/Helper/KitAPI.php b/tests/Support/Helper/KitAPI.php index aa73fa3d9..5adc4aad1 100644 --- a/tests/Support/Helper/KitAPI.php +++ b/tests/Support/Helper/KitAPI.php @@ -456,24 +456,24 @@ public function apiRequest($endpoint, $method = 'GET', $params = array()) } /** - * Repeatedly invokes the given callback until it returns a truthy value, or the - * maximum number of attempts is reached. - * - * Use this to wrap API checks that can be flaky due to eventual consistency at Kit's - * end. List endpoints typically reflect a write within ~30 seconds, and can take up - * to 5 minutes, so reading back immediately after a write is not reliable. - * - * @since 3.4.1 - * - * @see https://developers.kit.com/api-reference/eventual-consistency - * - * @param callable $callback Callback to invoke. Should return the value to use, or - * false / null when the check has not yet succeeded. - * @param int $attempts Maximum number of attempts. - * @param int $delay Seconds to wait between attempts. Defaults give up after ~30 seconds. - * @return mixed Value returned by the callback, or false if all attempts are exhausted. + * Repeatedly invokes the given callback until it returns a truthy value, or + * the maximum number of attempts is reached. + * + * Use this to wrap API checks that can be flaky due to ingestion lag at + * Kit's end (e.g. a subscriber created via a form submission isn't always + * immediately queryable via the `subscribers` endpoint). + * + * @since 3.3.2 + * + * @param callable $callback Callback to invoke. Should return the value + * to use, or false/null to indicate the + * check has not yet succeeded. + * @param int $attempts Maximum number of attempts. + * @param int $delay Seconds to wait between attempts. + * @return mixed The truthy value returned by $callback, or + * false if all attempts are exhausted. */ - public function retryUntil(callable $callback, $attempts = 10, $delay = 3) + public function retryUntil(callable $callback, $attempts = 4, $delay = 3) { for ($i = 0; $i < $attempts; $i++) { $result = $callback(); @@ -482,7 +482,7 @@ public function retryUntil(callable $callback, $attempts = 10, $delay = 3) } // Don't sleep after the final attempt. - if ($i < ( $attempts - 1 )) { + if ($i < $attempts - 1) { sleep($delay); } } From 71902d1764da6c6cb4b256173d724f3db2586a75 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 8 Sep 2026 15:15:32 +0800 Subject: [PATCH 4/5] Reinstate all tests --- .github/workflows/tests.yml | 21 ++++++++++++++++++++- tests/Support/Helper/KitAPI.php | 2 +- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 36e190723..fb368ebf0 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,9 +33,28 @@ jobs: fail-fast: false matrix: wp-version: [ 'latest' ] - php-version: [ '8.2' ] + php-version: [ '8.2', '8.3', '8.4', '8.5' ] test-group: + - 'EndToEnd/broadcasts/blocks-shortcodes' + - 'EndToEnd/broadcasts/import-export' - 'EndToEnd/forms/blocks-shortcodes' + - 'EndToEnd/forms/general' + - 'EndToEnd/forms/post-types' + - 'EndToEnd/general/other' + - 'EndToEnd/general/uninstall' + - 'EndToEnd/general/plugin-screens' + - 'EndToEnd/integrations/divi-builder' + - 'EndToEnd/integrations/divi-theme' + - 'EndToEnd/integrations/elementor' + - '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' uses: ./.github/workflows/_run-tests.yml secrets: inherit diff --git a/tests/Support/Helper/KitAPI.php b/tests/Support/Helper/KitAPI.php index 5adc4aad1..826fcea02 100644 --- a/tests/Support/Helper/KitAPI.php +++ b/tests/Support/Helper/KitAPI.php @@ -473,7 +473,7 @@ public function apiRequest($endpoint, $method = 'GET', $params = array()) * @return mixed The truthy value returned by $callback, or * false if all attempts are exhausted. */ - public function retryUntil(callable $callback, $attempts = 4, $delay = 3) + private function retryUntil(callable $callback, $attempts = 4, $delay = 3) { for ($i = 0; $i < $attempts; $i++) { $result = $callback(); From c29bf35591ea2128d49c3fd7bb3653272c00a213 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 8 Sep 2026 16:15:09 +0800 Subject: [PATCH 5/5] Revert apiCheckSubscriberDoesNotExist --- tests/Support/Helper/KitAPI.php | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/Support/Helper/KitAPI.php b/tests/Support/Helper/KitAPI.php index 826fcea02..acf7807fc 100644 --- a/tests/Support/Helper/KitAPI.php +++ b/tests/Support/Helper/KitAPI.php @@ -314,26 +314,26 @@ public function apiCheckSubscriberHasNoTags($I, $subscriberID) /** * Check the given email address does not exists as a subscriber. * - * The Plugin's requests are checked, instead of querying the API by email address, - * as querying by email address is subject to eventual consistency and would therefore - * return no results for a subscriber that was created. - * - * @see https://developers.kit.com/api-reference/eventual-consistency - * - * @param EndToEndTester $I EndToEndTester. + * @param EndToEndTester $I EndToEndTester. * @param string $emailAddress Email Address. */ public function apiCheckSubscriberDoesNotExist($I, $emailAddress) { - // Wait for any request the Plugin might make e.g. when a form submits using AJAX. + // Wait for the API to update. $I->wait(3); - // Check the Plugin did not create the subscriber. - $I->assertCount( - 0, - $this->grabKitAPIRequests($I, 'POST', 'subscribers', $emailAddress), - sprintf('The Plugin sent a request to create the subscriber %s.', $emailAddress) + // Run request. + $results = $this->apiRequest( + 'subscribers', + 'GET', + [ + 'email_address' => $emailAddress, + 'include_total_count' => true, + ] ); + + // Check no subscribers are returned by this request. + $I->assertEquals(0, $results['pagination']['total_count']); } /**