@@ -491,6 +491,32 @@ public function testRefreshTokenWithInvalidToken()
491491 $ this ->assertEquals ($ result ->get_error_code (), 'convertkit_api_error ' );
492492 }
493493
494+ /**
495+ * Test that making a call with an expired access token results in refresh_token()
496+ * not being automatically called, when the WordPress site isn't a production site.
497+ *
498+ * @since 2.0.2
499+ *
500+ * @return void
501+ */
502+ public function testRefreshTokenWhenAccessTokenExpiredErrorOnNonProductionSite ()
503+ {
504+ // If the refresh token action in the libraries is triggered when calling get_account(), the test failed.
505+ add_action (
506+ 'convertkit_api_refresh_token ' ,
507+ function () {
508+ $ this ->fail ('`convertkit_api_refresh_token` was triggered when calling `get_account` with an expired access token on a non-production site. ' );
509+ }
510+ );
511+
512+ // Filter requests to mock the token expiry and refreshing the token.
513+ add_filter ( 'pre_http_request ' , array ( $ this , 'mockAccessTokenExpiredResponse ' ), 10 , 3 );
514+ add_filter ( 'pre_http_request ' , array ( $ this , 'mockRefreshTokenResponse ' ), 10 , 3 );
515+
516+ // Run request, which will trigger the above filters as if the token expired and refreshes automatically.
517+ $ result = $ this ->api ->get_account ();
518+ }
519+
494520 /**
495521 * Test that supplying no API credentials to the API class returns a WP_Error.
496522 *
@@ -6239,6 +6265,90 @@ function( $response ) use ( $httpCode, $httpMessage, $body ) { // phpcs:ignore G
62396265 );
62406266 }
62416267
6268+ /**
6269+ * Mocks an API response as if the Access Token expired.
6270+ *
6271+ * @since 2.0.2
6272+ *
6273+ * @param mixed $response HTTP Response.
6274+ * @param array $parsed_args Request arguments.
6275+ * @param string $url Request URL.
6276+ * @return mixed
6277+ */
6278+ public function mockAccessTokenExpiredResponse ( $ response , $ parsed_args , $ url )
6279+ {
6280+ // Only mock requests made to the /account endpoint.
6281+ if ( strpos ( $ url , 'https://api.convertkit.com/v4/account ' ) === false ) {
6282+ return $ response ;
6283+ }
6284+
6285+ // Remove this filter, so we don't end up in a loop when retrying the request.
6286+ remove_filter ( 'pre_http_request ' , array ( $ this , 'mockAccessTokenExpiredResponse ' ) );
6287+
6288+ // Return a 401 unauthorized response with the errors body as if the API
6289+ // returned "The access token expired".
6290+ return array (
6291+ 'headers ' => array (),
6292+ 'body ' => wp_json_encode (
6293+ array (
6294+ 'errors ' => array (
6295+ 'The access token expired ' ,
6296+ ),
6297+ )
6298+ ),
6299+ 'response ' => array (
6300+ 'code ' => 401 ,
6301+ 'message ' => 'The access token expired ' ,
6302+ ),
6303+ 'cookies ' => array (),
6304+ 'http_response ' => null ,
6305+ );
6306+ }
6307+
6308+ /**
6309+ * Mocks an API response as if a refresh token was used to fetch new tokens.
6310+ *
6311+ * @since 2.0.2
6312+ *
6313+ * @param mixed $response HTTP Response.
6314+ * @param array $parsed_args Request arguments.
6315+ * @param string $url Request URL.
6316+ * @return mixed
6317+ */
6318+ public function mockRefreshTokenResponse ( $ response , $ parsed_args , $ url )
6319+ {
6320+ // Only mock requests made to the /token endpoint.
6321+ if ( strpos ( $ url , 'https://api.convertkit.com/oauth/token ' ) === false ) {
6322+ return $ response ;
6323+ }
6324+
6325+ // Remove this filter, so we don't end up in a loop when retrying the request.
6326+ remove_filter ( 'pre_http_request ' , array ( $ this , 'mockRefreshTokenResponse ' ) );
6327+
6328+ // Return a mock access and refresh token for this API request, as calling
6329+ // refresh_token results in a new access and refresh token being provided,
6330+ // which would result in other tests breaking due to changed tokens.
6331+ return array (
6332+ 'headers ' => array (),
6333+ 'body ' => wp_json_encode (
6334+ array (
6335+ 'access_token ' => 'new- ' . $ _ENV ['CONVERTKIT_OAUTH_ACCESS_TOKEN ' ],
6336+ 'refresh_token ' => 'new- ' . $ _ENV ['CONVERTKIT_OAUTH_REFRESH_TOKEN ' ],
6337+ 'token_type ' => 'bearer ' ,
6338+ 'created_at ' => strtotime ( 'now ' ),
6339+ 'expires_in ' => 10000 ,
6340+ 'scope ' => 'public ' ,
6341+ )
6342+ ),
6343+ 'response ' => array (
6344+ 'code ' => 200 ,
6345+ 'message ' => 'OK ' ,
6346+ ),
6347+ 'cookies ' => array (),
6348+ 'http_response ' => null ,
6349+ );
6350+ }
6351+
62426352 /**
62436353 * Helper method to assert the given key exists as an array
62446354 * in the API response.
0 commit comments