@@ -81,7 +81,7 @@ public function test_caches_get_requests(): void
8181 $ this ->assertEquals ('HIT ' , $ response2 ->getHeaderLine ('X-Cache-Status ' ));
8282 }
8383
84- public function test_cache_miss_adds_x_cache_status_header (): void
84+ public function test_cache_miss_returns_successful_response (): void
8585 {
8686 $ responses = [
8787 new GuzzleResponse (200 , ['Content-Type ' => 'application/json ' ], '{"data":"test"} ' ),
@@ -93,8 +93,9 @@ public function test_cache_miss_adds_x_cache_status_header(): void
9393
9494 $ response = $ handler ->get ('/users ' );
9595
96- // After request is cached, the response won't have the header until fetched from cache
96+ // First request is a cache miss, response should be successful
9797 $ this ->assertEquals (200 , $ response ->getStatusCode ());
98+ $ this ->assertEquals ('{"data":"test"} ' , $ response ->body ());
9899 }
99100
100101 public function test_does_not_cache_post_requests_by_default (): void
@@ -286,7 +287,7 @@ public function test_cache_respects_max_age_from_response(): void
286287 $ this ->assertEquals ('{"data":"cached"} ' , $ response ->body ());
287288 }
288289
289- public function test_cache_disabled_when_respect_headers_false_and_no_store (): void
290+ public function test_cache_respects_no_store_when_respect_headers_enabled (): void
290291 {
291292 $ responses = [
292293 new GuzzleResponse (200 , [
@@ -298,7 +299,7 @@ public function test_cache_disabled_when_respect_headers_false_and_no_store(): v
298299
299300 $ handler = $ this ->create_handler_with_mock_responses ($ responses );
300301 $ handler ->baseUri ('https://api.example.com ' );
301- // Even with respect_cache_headers=false , no-store should be respected
302+ // With respect_cache_headers=true (default) , no-store should be respected
302303 $ handler ->withCache (null , ['respect_cache_headers ' => true ]);
303304
304305 $ response1 = $ handler ->get ('/users ' );
@@ -308,4 +309,33 @@ public function test_cache_disabled_when_respect_headers_false_and_no_store(): v
308309 $ response2 = $ handler ->get ('/users ' );
309310 $ this ->assertEquals ('{"data":"second"} ' , $ response2 ->body ());
310311 }
312+
313+ public function test_cache_requires_revalidation_with_no_cache_directive (): void
314+ {
315+ // no-cache means the response may be cached but must be revalidated before use
316+ // This is different from no-store which forbids caching entirely
317+ $ responses = [
318+ new GuzzleResponse (200 , [
319+ 'Content-Type ' => 'application/json ' ,
320+ 'Cache-Control ' => 'no-cache ' ,
321+ 'ETag ' => '"abc123" ' ,
322+ ], '{"data":"first"} ' ),
323+ // Second request should include conditional headers and may get 304
324+ new GuzzleResponse (304 , [], '' ),
325+ ];
326+
327+ $ handler = $ this ->create_handler_with_mock_responses ($ responses );
328+ $ handler ->baseUri ('https://api.example.com ' );
329+ $ handler ->withCache (null , ['respect_cache_headers ' => true ]);
330+
331+ // First request - gets response with no-cache
332+ $ response1 = $ handler ->get ('/users ' );
333+ $ this ->assertEquals ('{"data":"first"} ' , $ response1 ->body ());
334+ $ this ->assertEquals (200 , $ response1 ->getStatusCode ());
335+
336+ // Second request - should revalidate and use cached response if 304
337+ $ response2 = $ handler ->get ('/users ' );
338+ // Response should still be the cached one after revalidation
339+ $ this ->assertEquals (200 , $ response2 ->getStatusCode ());
340+ }
311341}
0 commit comments