Problem/Motivation
I tried looking for an existing issue but couldn't quite locate one. I recently ran into an issue when testing custom code around cookies and logging in/out with functional tests, outlined here:
https://drupal.stackexchange.com/questions/317324/drupal-unable-to-login...
It came down to the Mink driver not properly clearing cookies / session related data when logging out a user until I used $this->getSession()->reset();
drupalLogout does not seem to account for this:
protected function drupalLogout() {
// Make a request to the logout page, and redirect to the user page, the
// idea being if you were properly logged out you should be seeing a login
// screen.
$assert_session = $this->assertSession();
$destination = Url::fromRoute('user.page')->toString();
$this->drupalGet(Url::fromRoute('user.logout', [], ['query' => ['destination' => $destination]]));
$assert_session->fieldExists('name');
$assert_session->fieldExists('pass');
// @see BrowserTestBase::drupalUserIsLoggedIn()
unset($this->loggedInUser->sessionId);
$this->loggedInUser = FALSE;
\Drupal::currentUser()->setAccount(new AnonymousUserSession());
}
Steps to reproduce
With code that sets cookies, trying to log in a user that gets those cookies, logging them out and then using drupalLogin will produce the following error:
User <em class="placeholder">NAME</em> successfully logged in.
Failed asserting that false is true.In my case I am doing a redirect because of the logic required and so the assert in drupalLogin fails, whereas the drupalGet/submitForm method works. This should work either way, as the code (in this example) does work in a real browser / real human testing it.
Proposed resolution
Ensure the session is reset/cleared cleanly when using drupalLogout for functional tests or provide a note in the docs on this behavior to know to call $this->getSession()->reset() in certain scenarios.
Comments
Comment #2
kevinquillen commentedComment #3
pbonnefoi commentedI have a similar problem trying to fix a unit test on a contrib module, but adding $this->getSession()->reset(); did not work. Do you add it right after drupalLogout() ?
An improvement on the error message would be very nice as well because it does not make much sense.
The unit test causing problem is from the redirect_after_login contrib module.
Comment #4
kevinquillen commentedCalling drupalLogout() in this scenario is the problem because assert() fails (its in one of the test traits) - it thinks the session is still authenticated. This does not happen outside of a test.
I believe if the test method was updated to this, it would resolve the issue:
Multiple login/logouts in a single test method that alters or adds to user session data or cookie data is otherwise problematic to test.
Comment #5
pbonnefoi commentedOk good to know, thank you very much for the insights !
Comment #7
fenstratJust noting here that I saw these same odd failures, especially when running multiple drupalLogin() calls:
And that calling
$this->getSession()->reset()didn't solve it.Instead it was related to dumping the container, and the container differing while under test. In my case this was using Drupal Test Traits, see
#3436284: DTT can use different cached container than running site causing issues with testing.