Skip to content

Commit 24cc41a

Browse files
committed
Merge branch 'fix/issue-wootax-298' of https://github.com/Automattic/woocommerce-services into fix/issue-wootax-298
2 parents cc5dbfa + a1dd09d commit 24cc41a

2 files changed

Lines changed: 80 additions & 10 deletions

File tree

tests/php/test-woocommerce-connect-client.php

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -286,12 +286,21 @@ public function test_extend_store_api_skips_registration_when_store_api_unavaila
286286
}
287287

288288
/**
289-
* is_store_api_available() reflects whether the StoreApi class the plugin
290-
* depends on actually exists, so the guard tracks the real class.
289+
* is_store_api_available() returns true when the StoreApi class the plugin
290+
* depends on is present. The PHPUnit harness loads WooCommerce, so the class
291+
* exists here - pinning to true means a typo or rename in the guarded class
292+
* string would fail this test rather than silently tracking the change.
291293
*
292294
* @covers WC_Connect_Loader::is_store_api_available
293295
*/
294-
public function test_is_store_api_available_tracks_store_api_class() {
296+
public function test_is_store_api_available_returns_true_when_store_api_class_present() {
297+
// Precondition: the harness must actually load the StoreApi class for the
298+
// assertion below to be meaningful.
299+
$this->assertTrue(
300+
class_exists( '\Automattic\WooCommerce\StoreApi\StoreApi' ),
301+
'Test precondition: the StoreApi class must be loaded in the test harness.'
302+
);
303+
295304
$sut = $this->getMockBuilder( 'WC_Connect_Loader' )
296305
->disableOriginalConstructor()
297306
->setMethods( null )
@@ -300,11 +309,52 @@ public function test_is_store_api_available_tracks_store_api_class() {
300309
$method = new ReflectionMethod( 'WC_Connect_Loader', 'is_store_api_available' );
301310
$method->setAccessible( true );
302311

303-
$this->assertSame(
304-
class_exists( '\Automattic\WooCommerce\StoreApi\StoreApi' ),
312+
$this->assertTrue(
305313
$method->invoke( $sut ),
306-
'is_store_api_available() should mirror the existence of the StoreApi class.'
314+
'is_store_api_available() should return true when the StoreApi class is present.'
307315
);
308316
}
309317

318+
/**
319+
* On the unavailable path, extend_store_api() logs a notice - but at most
320+
* once per day, because it runs on `woocommerce_blocks_loaded` (nearly every
321+
* request). The throttle transient must suppress the second same-day call.
322+
*
323+
* @covers WC_Connect_Loader::extend_store_api
324+
* @covers WC_Connect_Loader::log_store_api_unavailable
325+
*/
326+
public function test_extend_store_api_logs_unavailable_notice_once_per_day() {
327+
delete_transient( 'wcservices_store_api_unavailable_logged' );
328+
329+
// Spy logger injected via the woocommerce_logging_class filter. Returning
330+
// an object bypasses wc_get_logger()'s static cache.
331+
$logger = $this->getMockBuilder( 'WC_Logger_Interface' )->getMock();
332+
$logger->expects( $this->once() )
333+
->method( 'notice' )
334+
->with(
335+
'StoreApi class not found. Store API extensions will not be registered.',
336+
array( 'source' => 'woocommerce-services' )
337+
);
338+
339+
$inject_logger = function () use ( $logger ) {
340+
return $logger;
341+
};
342+
add_filter( 'woocommerce_logging_class', $inject_logger );
343+
344+
$sut = $this->getMockBuilder( 'WC_Connect_Loader' )
345+
->disableOriginalConstructor()
346+
->setMethods( array( 'is_store_api_available', 'register_store_api_extensions' ) )
347+
->getMock();
348+
349+
$sut->method( 'is_store_api_available' )->willReturn( false );
350+
$sut->expects( $this->never() )->method( 'register_store_api_extensions' );
351+
352+
// First skip logs the notice; the second same-day skip is throttled.
353+
$sut->extend_store_api();
354+
$sut->extend_store_api();
355+
356+
remove_filter( 'woocommerce_logging_class', $inject_logger );
357+
delete_transient( 'wcservices_store_api_unavailable_logged' );
358+
}
359+
310360
}

woocommerce-services.php

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -990,10 +990,7 @@ public function init_store_notices() {
990990
*/
991991
public function extend_store_api() {
992992
if ( ! $this->is_store_api_available() ) {
993-
wc_get_logger()->notice(
994-
'StoreApi class not found. Store API extensions will not be registered.',
995-
array( 'source' => 'woocommerce-services' )
996-
);
993+
$this->log_store_api_unavailable();
997994
return;
998995
}
999996

@@ -1009,6 +1006,29 @@ protected function is_store_api_available() {
10091006
return class_exists( '\Automattic\WooCommerce\StoreApi\StoreApi' );
10101007
}
10111008

1009+
/**
1010+
* Log, at most once per day, that the Store API is unavailable.
1011+
*
1012+
* `extend_store_api()` runs on `woocommerce_blocks_loaded`, which fires on
1013+
* nearly every request. On installs missing the StoreApi class the notice
1014+
* would otherwise be written on every page load, so it is throttled to once
1015+
* per day via a transient.
1016+
*/
1017+
protected function log_store_api_unavailable() {
1018+
$transient_key = 'wcservices_store_api_unavailable_logged';
1019+
1020+
if ( get_transient( $transient_key ) ) {
1021+
return;
1022+
}
1023+
1024+
wc_get_logger()->notice(
1025+
'StoreApi class not found. Store API extensions will not be registered.',
1026+
array( 'source' => 'woocommerce-services' )
1027+
);
1028+
1029+
set_transient( $transient_key, 1, DAY_IN_SECONDS );
1030+
}
1031+
10121032
/**
10131033
* Register the plugin's Store API extensions.
10141034
*/

0 commit comments

Comments
 (0)