@@ -46,7 +46,10 @@ public function test_returns_cached_addons_when_available(): void {
4646 public function test_force_bypasses_cache_and_persists_formatted_result (): void {
4747 $ cache = $ this ->createMock ( CacheInterface::class );
4848 $ cache ->method ( 'is_throttled ' )->willReturn ( false );
49- $ cache ->expects ( $ this ->never () )->method ( 'get ' );
49+ // `get` is consulted even on a forced refresh so the cached
50+ // catalog can serve as a fallback when the API call fails or
51+ // the throttle kicks in. Returning `false` mimics "no cache".
52+ $ cache ->method ( 'get ' )->willReturn ( false );
5053 $ cache ->expects ( $ this ->once () )
5154 ->method ( 'set ' )
5255 ->with (
@@ -84,7 +87,7 @@ static function ( array $value ): bool {
8487 $ this ->assertTrue ( $ result [0 ]['is_premium ' ] );
8588 }
8689
87- public function test_returns_empty_array_on_api_error (): void {
90+ public function test_returns_empty_when_api_errors_and_no_cache (): void {
8891 $ cache = $ this ->createMock ( CacheInterface::class );
8992 $ cache ->method ( 'get ' )->willReturn ( false );
9093 $ cache ->method ( 'is_throttled ' )->willReturn ( false );
@@ -98,7 +101,32 @@ public function test_returns_empty_array_on_api_error(): void {
98101 $ this ->assertSame ( array (), ( new Addon ( $ this ->plugin (), $ cache , $ factory ) )->get_addons () );
99102 }
100103
101- public function test_throttled_request_returns_empty_array_and_does_not_call_api (): void {
104+ public function test_force_falls_back_to_cache_when_api_errors (): void {
105+ $ cached = array (
106+ array (
107+ 'id ' => 42 ,
108+ 'title ' => 'Cached ' ,
109+ ),
110+ );
111+
112+ $ cache = $ this ->createMock ( CacheInterface::class );
113+ $ cache ->method ( 'get ' )->willReturn ( $ cached );
114+ $ cache ->method ( 'is_throttled ' )->willReturn ( false );
115+ // API failed → catalog must not be overwritten.
116+ $ cache ->expects ( $ this ->never () )->method ( 'set ' );
117+
118+ $ api = $ this ->createMock ( ApiClientInterface::class );
119+ $ api ->method ( 'get ' )->willReturn ( new WP_Error ( 'fail ' , 'no ' ) );
120+
121+ $ factory = $ this ->createMock ( ApiFactory::class );
122+ $ factory ->method ( 'make_for_plugin ' )->willReturn ( $ api );
123+
124+ $ result = ( new Addon ( $ this ->plugin (), $ cache , $ factory ) )->get_addons ( true );
125+
126+ $ this ->assertSame ( $ cached , $ result );
127+ }
128+
129+ public function test_throttled_request_returns_empty_when_no_cache (): void {
102130 $ cache = $ this ->createMock ( CacheInterface::class );
103131 $ cache ->method ( 'get ' )->willReturn ( false );
104132 $ cache ->method ( 'is_throttled ' )->with ( 'addons_check ' )->willReturn ( true );
@@ -112,6 +140,31 @@ public function test_throttled_request_returns_empty_array_and_does_not_call_api
112140 $ this ->assertSame ( array (), ( new Addon ( $ this ->plugin (), $ cache , $ factory ) )->get_addons () );
113141 }
114142
143+ public function test_force_falls_back_to_cache_when_throttled (): void {
144+ $ cached = array (
145+ array (
146+ 'id ' => 9 ,
147+ 'title ' => 'Stale but fine ' ,
148+ ),
149+ );
150+
151+ $ cache = $ this ->createMock ( CacheInterface::class );
152+ $ cache ->method ( 'get ' )->willReturn ( $ cached );
153+ $ cache ->method ( 'is_throttled ' )->with ( 'addons_check ' )->willReturn ( true );
154+ // Throttle blocked the API call → catalog stays as it is.
155+ $ cache ->expects ( $ this ->never () )->method ( 'set ' );
156+
157+ $ api = $ this ->createMock ( ApiClientInterface::class );
158+ $ api ->expects ( $ this ->never () )->method ( 'get ' );
159+
160+ $ factory = $ this ->createMock ( ApiFactory::class );
161+ $ factory ->method ( 'make_for_plugin ' )->willReturn ( $ api );
162+
163+ $ result = ( new Addon ( $ this ->plugin (), $ cache , $ factory ) )->get_addons ( true );
164+
165+ $ this ->assertSame ( $ cached , $ result );
166+ }
167+
115168 public function test_mark_requested_called_after_request (): void {
116169 $ cache = $ this ->createMock ( CacheInterface::class );
117170 $ cache ->method ( 'get ' )->willReturn ( false );
0 commit comments