Browse Source

Merge pull request #17489 from cakephp/fix-cookie-assertions

Fix cookie assertions with redirect responses
othercorey 2 years ago
parent
commit
641d38eeff

+ 1 - 1
src/TestSuite/Constraint/Response/CookieEquals.php

@@ -55,7 +55,7 @@ class CookieEquals extends ResponseBase
      */
     public function matches($other): bool
     {
-        $cookie = $this->response->getCookie($this->cookieName);
+        $cookie = $this->readCookie($this->cookieName);
 
         return $cookie !== null && $cookie['value'] === $other;
     }

+ 1 - 1
src/TestSuite/Constraint/Response/CookieSet.php

@@ -35,7 +35,7 @@ class CookieSet extends ResponseBase
      */
     public function matches($other): bool
     {
-        $cookie = $this->response->getCookie($other);
+        $cookie = $this->readCookie($other);
 
         return $cookie !== null && $cookie['value'] !== '';
     }

+ 21 - 0
src/TestSuite/Constraint/Response/ResponseBase.php

@@ -15,6 +15,7 @@ declare(strict_types=1);
  */
 namespace Cake\TestSuite\Constraint\Response;
 
+use Cake\Http\Cookie\CookieCollection;
 use PHPUnit\Framework\AssertionFailedError;
 use PHPUnit\Framework\Constraint\Constraint;
 use Psr\Http\Message\ResponseInterface;
@@ -54,4 +55,24 @@ abstract class ResponseBase extends Constraint
     {
         return (string)$this->response->getBody();
     }
+
+    /**
+     * Read a cookie from either the response cookie collection,
+     * or headers
+     *
+     * @param string $name The name of the cookie you want to read.
+     * @return array|null Null if the cookie does not exist, array with `value` as the only key.
+     */
+    protected function readCookie(string $name): ?array
+    {
+        if (method_exists($this->response, 'getCookie')) {
+            return $this->response->getCookie($name);
+        }
+        $cookies = CookieCollection::createFromHeader($this->response->getHeader('Set-Cookie'));
+        if (!$cookies->has($name)) {
+            return null;
+        }
+
+        return $cookies->get($name)->toArray();
+    }
 }

+ 7 - 1
tests/TestCase/TestSuite/IntegrationTestTraitTest.php

@@ -742,7 +742,10 @@ class IntegrationTestTraitTest extends TestCase
     public function testAssertCookieNotSet(): void
     {
         $this->cookie('test', 'value');
-        $this->get('/cookie_component_test/remove_cookie/test');
+        $this->get('/posts/index');
+        $this->assertCookieNotSet('test');
+
+        $this->get('/posts/redirectWithCookie');
         $this->assertCookieNotSet('test');
     }
 
@@ -775,6 +778,9 @@ class IntegrationTestTraitTest extends TestCase
     {
         $this->get('/posts/secretCookie');
         $this->assertCookieIsSet('secrets');
+
+        $this->get('/posts/redirectWithCookie');
+        $this->assertCookieIsSet('remember');
     }
 
     /**

+ 16 - 0
tests/test_app/TestApp/Controller/PostsController.php

@@ -18,6 +18,7 @@ namespace TestApp\Controller;
 
 use Cake\Event\EventInterface;
 use Cake\Http\Cookie\Cookie;
+use Cake\Http\Exception\RedirectException;
 use OutOfBoundsException;
 use RuntimeException;
 
@@ -189,6 +190,21 @@ class PostsController extends AppController
             ->withStringBody('ok');
     }
 
+    public function redirectWithCookie()
+    {
+        $cookies = [
+            Cookie::create('remember', '1'),
+            Cookie::create('expired', '')->withExpired(),
+        ];
+        $values = [];
+        foreach ($cookies as $cookie) {
+            $values[] = $cookie->toHeaderValue();
+        }
+        $headers = ['Set-Cookie' => $values];
+
+        throw new RedirectException('/posts', 302, $headers);
+    }
+
     /**
      * @return \Cake\Http\Response
      */