Codeception: Keep a logged in state

Ms01 picture Ms01 · Dec 2, 2013 · Viewed 8.7k times · Source

I want to keep or run the login before most of my tests. But if I try to move the login code to _before it doesn't work since there is no webguy instance available to me.

What is the best way to keep the session between multiple tests? This is my code so far, would be glad to receive some help. I have googled and checked the documentation but I cannot find anything about session stuff.

<?php
use \WebGuy;

class ProductCest
{

    private $product_id = '1';

    public function _before()
    {
    }

    public function _after()
    {
    }

    // tests
    public function login(WebGuy $I) {
        $I->seeInCurrentUrl('/auth/login');
        $I->fillField("//input[@type='email']", "[email protected]");
        $I->fillField("//input[@type='password']", "1234");
        $I->click('#signIn .submit');
        $I->wait(500);

        $I->seeInCurrentUrl('/account');
    }

    /**
     * @depends login
     */
    public function chooseProduct(WebGuy $I) {
        $I->wantTo('go to products and choose one');
        $I->amOnPage('/?product=' . $this->client_id);
    }

}

Answer

Federico J. picture Federico J. · Aug 28, 2014

I think that the accepted answer is a way of accomplish it, but not the best. Doing that you'll always have to reproduce all the steps to log in into the system, when you only need to share the user session. I think that grabbing the session cookie and pass it through the required user logged tests is better. To do that, you create a login function, get the cookie, and make your tests depends on the login test first:

<?php
use \AcceptanceTester;

class testingCest
{
    private $cookie = null;

    public function _before(AcceptanceTester $I)
    {
    }

    public function _after(AcceptanceTester $I)
    {
    }


    // tests
    public function login(AcceptanceTester $I)
    {
        $I->wantTo('entrar al sistema');
        $I->amOnPage('/');
        $I->seeInCurrentUrl('/admin/login');
        $I->fillField('user','perry');
        $I->fillField('pass','pass-perry');
        $I->click('Login');
        $I->see('You\'re logged!');
        $this->cookie   = $I->grabCookie('your-session-cookie-name');
    }

    /**
     * @depends login
     */
    public function listUsers(AcceptanceTester $I)
    {
        $I->setCookie( 'your-session-cookie-name', $this->cookie );
        $I->amOnPage('/admin/users');
        $I->seeInCurrentUrl('/admin/users/1');
    }

    /**
     * @depends login
     */
    public function listRols(AcceptanceTester $I)
    {
        $I->setCookie( 'your-session-cookie-name', $this->cookie );
        $I->amOnPage('/admin/rols');
        $I->seeInCurrentUrl('/admin/rols/1');
    }
}

That way, if the login test fails, you won't get the cookie, and you won't pass the other tests.

I prefer this @depends annotation instead of the @before proposed in the other answer, because if you use @depends you'll ALWAYS execute the code in the test before, and the tests will be only executed after the login.

UPDATE

There exists another answer bellow, https://stackoverflow.com/a/41109855/1168804 that may also help you, as the framework for Codeception has evolved since the writing of this answer.