mardi 5 juillet 2016

Testing Cookies

I'm working on a ecommerce website using Laravel 5.2 and I've run into a problem when testing the part of the app that uses cookies.

The idea is that a Cart is created for every user that visits the website. Here is my Cart model:

class Cart extends Model
{
    protected $fillable = [
        'cookie_token',
    ];

    /**
     * Returns the Cart for the current user.
     *
     * @return Cart
     */
    public static function current()
    {
        $cookie_token = Cookie::get('cookie_token') ?: self::generateCookieToken();
        return self::getCartByCookieToken($cookie_token);
    }

    /**
     * Returns the Cart for the given cookie_token or creates a new one.
     * 
     * @param $cookie_token
     * @return Cart
     */
    protected static function getCartByCookieToken($cookie_token)
    {
        $cart = Cart::where('cookie_token', $cookie_token)
            ->first();

        if (empty($cart)) {
            $cart = Cart::create(['cookie_token' => $cookie_token]);
            Cookie::queue('cookie_token', $cookie_token, 525600);
        }

        return $cart;
    }
}

So when I call Cart::current() I get the row from the database with cookie_token retrieved from the cookie or a new row is generated and the cookie is saved.

It works well in the browser but not in the tests. Here's the simplest test I have:

class CartTest extends TestCase
{
    use DatabaseTransactions;

    /** @test */
    public function an_item_can_be_added_to_the_cart()
    {
        $product = factory(App\Product::class)->create();

        Cart::current()->addItem($product);

        $this->assertEquals(1, Cart::current()->count());
        $this->assertEquals($product->id, Cart::current()->items()->first()->product_id);
    }

The tests fail and if I disable the DatabaseTransactions trait, I can see in the database that 3 rows are created with 3 different values of the field cookie_token.

It seems that cookies are not saved during testing, so when I call Cart::current(), a new row is created each time, rather than fetching the one created with the same call a line before.

I'm not an expert on tests, so I'm probably missing something. I guess I should maybe mock it somehow? How can I test code that uses cookies?

Aucun commentaire:

Enregistrer un commentaire