Skip to content

Commit

Permalink
Merge pull request #425 from jhedstrom/316-authentication-manager
Browse files Browse the repository at this point in the history
Create an AuthenticationManager service
  • Loading branch information
jhedstrom authored Dec 1, 2017
2 parents 2df8e22 + e36a802 commit 1dfccc2
Show file tree
Hide file tree
Showing 11 changed files with 494 additions and 143 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,23 @@
use Behat\Testwork\Hook\HookDispatcher;
use Behat\Testwork\Hook\HookRepository;

use Drupal\DrupalUserManager;
use Drupal\DrupalUserManagerInterface;
use Drupal\DrupalExtension\Manager\DrupalAuthenticationManagerInterface;
use Drupal\DrupalExtension\Manager\DrupalUserManagerInterface;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class DrupalAwareInitializerSpec extends ObjectBehavior
{
private $dispatcher;

function let(DrupalDriverManager $drupal, DrupalUserManagerInterface $userManager)
function let(DrupalDriverManager $drupal, DrupalAuthenticationManagerInterface $authenticationManager, DrupalUserManagerInterface $userManager)
{
$callCenter = new CallCenter();
$manager = new EnvironmentManager();
$repository = new HookRepository($manager);
// Cannot mock this class as it is marked as final.
$this->dispatcher = new HookDispatcher($repository, $callCenter);
$this->beConstructedWith($drupal, array(), $this->dispatcher, $userManager);
$this->beConstructedWith($drupal, array(), $this->dispatcher, $authenticationManager, $userManager);
}

function it_is_a_context_initializer()
Expand All @@ -41,11 +41,12 @@ function it_does_nothing_for_basic_contexts(Context $context)
$this->initializeContext($context);
}

function it_injects_drupal_and_parameters_and_dispatcher_and_user_manager_in_drupal_aware_Contexts(DrupalAwareInterface $context, $drupal, DrupalUserManagerInterface $userManager)
function it_injects_drupal_and_parameters_and_dispatcher_and_user_manager_in_drupal_aware_Contexts(DrupalAwareInterface $context, $drupal, DrupalAuthenticationManagerInterface $authenticationManager, DrupalUserManagerInterface $userManager)
{
$context->setDispatcher($this->dispatcher)->shouldBeCAlled();
$context->setDrupal($drupal)->shouldBeCAlled();
$context->setDrupalParameters(array())->shouldBeCAlled();
$context->setAuthenticationManager($authenticationManager)->shouldBeCalled();
$context->setUserManager($userManager)->shouldBeCalled();
$this->initializeContext($context);
}
Expand Down
22 changes: 18 additions & 4 deletions src/Drupal/DrupalExtension/Context/DrupalAwareInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
use Behat\Testwork\Hook\HookDispatcher;

use Drupal\DrupalDriverManager;
use Drupal\DrupalUserManagerInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Drupal\DrupalExtension\Manager\DrupalAuthenticationManagerInterface;
use Drupal\DrupalExtension\Manager\DrupalUserManagerInterface;

interface DrupalAwareInterface extends Context {

Expand Down Expand Up @@ -36,14 +36,28 @@ public function setDrupalParameters(array $parameters);
/**
* Sets the Drupal user manager instance.
*
* @param \Drupal\DrupalUserManagerInterface $userManager
* @param \Drupal\DrupalExtension\Manager\DrupalUserManagerInterface $userManager
*/
public function setUserManager(DrupalUserManagerInterface $userManager);

/**
* Gets the Drupal user manager instance.
*
* @return \Drupal\DrupalUserManagerInterface
* @return \Drupal\DrupalExtension\Manager\DrupalUserManagerInterface
*/
public function getUserManager();

/**
* Sets the Drupal authentication manager instance.
*
* @param \Drupal\DrupalExtension\Manager\DrupalAuthenticationManagerInterface $authenticationManager
*/
public function setAuthenticationManager(DrupalAuthenticationManagerInterface $authenticationManager);

/**
* Gets the Drupal authentication manager instance.
*
* @return \Drupal\DrupalExtension\Manager\DrupalAuthenticationManagerInterface
*/
public function getAuthenticationManager();
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@
use Behat\Testwork\Hook\HookDispatcher;

use Drupal\DrupalDriverManager;
use Drupal\DrupalExtension\Context\DrupalContext;
use Drupal\DrupalExtension\Context\DrupalAwareInterface;
use Drupal\DrupalUserManagerInterface;
use Drupal\DrupalExtension\Manager\DrupalAuthenticationManagerInterface;
use Drupal\DrupalExtension\Manager\DrupalUserManagerInterface;

class DrupalAwareInitializer implements ContextInitializer {
private $drupal, $parameters, $dispatcher, $userManager;
private $drupal, $parameters, $dispatcher, $authenticationManager, $userManager;

public function __construct(DrupalDriverManager $drupal, array $parameters, HookDispatcher $dispatcher, DrupalUserManagerInterface $userManager) {
public function __construct(DrupalDriverManager $drupal, array $parameters, HookDispatcher $dispatcher, DrupalAuthenticationManagerInterface $authenticationManager, DrupalUserManagerInterface $userManager) {
$this->drupal = $drupal;
$this->parameters = $parameters;
$this->dispatcher = $dispatcher;
$this->authenticationManager = $authenticationManager;
$this->userManager = $userManager;
}

Expand All @@ -40,6 +41,9 @@ public function initializeContext(Context $context) {
// Add all parameters to the context.
$context->setDrupalParameters($this->parameters);

// Set the Drupal authentication manager.
$context->setAuthenticationManager($this->authenticationManager);

// Set the Drupal user manager.
$context->setUserManager($this->userManager);
}
Expand Down
156 changes: 29 additions & 127 deletions src/Drupal/DrupalExtension/Context/RawDrupalContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
use Behat\Testwork\Hook\HookDispatcher;

use Drupal\DrupalDriverManager;
use Drupal\DrupalUserManagerInterface;
use Drupal\DrupalExtension\DrupalParametersTrait;
use Drupal\DrupalExtension\Manager\DrupalAuthenticationManagerInterface;
use Drupal\DrupalExtension\Manager\DrupalUserManagerInterface;

use Drupal\DrupalExtension\Hook\Scope\AfterLanguageEnableScope;
use Drupal\DrupalExtension\Hook\Scope\AfterNodeCreateScope;
Expand All @@ -25,6 +27,8 @@
*/
class RawDrupalContext extends RawMinkContext implements DrupalAwareInterface {

use DrupalParametersTrait;

/**
* Drupal driver manager.
*
Expand All @@ -33,23 +37,23 @@ class RawDrupalContext extends RawMinkContext implements DrupalAwareInterface {
private $drupal;

/**
* Test parameters.
* Event dispatcher object.
*
* @var array
* @var \Behat\Testwork\Hook\HookDispatcher
*/
private $drupalParameters;
protected $dispatcher;

/**
* Event dispatcher object.
* Drupal authentication manager.
*
* @var \Behat\Testwork\Hook\HookDispatcher
* @var \Drupal\DrupalExtension\Manager\DrupalAuthenticationManagerInterface
*/
protected $dispatcher;
protected $authenticationManager;

/**
* Drupal user manager.
*
* @var \Drupal\DrupalUserManagerInterface
* @var \Drupal\DrupalExtension\Manager\DrupalUserManagerInterface
*/
protected $userManager;

Expand Down Expand Up @@ -109,6 +113,20 @@ public function getUserManager() {
return $this->userManager;
}

/**
* {@inheritdoc}
*/
public function setAuthenticationManager(DrupalAuthenticationManagerInterface $authenticationManager) {
$this->authenticationManager = $authenticationManager;
}

/**
* {@inheritdoc}
*/
public function getAuthenticationManager() {
return $this->authenticationManager;
}

/**
* Magic setter.
*/
Expand Down Expand Up @@ -163,56 +181,6 @@ public function setDispatcher(HookDispatcher $dispatcher) {
$this->dispatcher = $dispatcher;
}

/**
* Set parameters provided for Drupal.
*/
public function setDrupalParameters(array $parameters) {
$this->drupalParameters = $parameters;
}

/**
* Returns a specific Drupal parameter.
*
* @param string $name
* Parameter name.
*
* @return mixed
*/
public function getDrupalParameter($name) {
return isset($this->drupalParameters[$name]) ? $this->drupalParameters[$name] : NULL;
}

/**
* Returns a specific Drupal text value.
*
* @param string $name
* Text value name, such as 'log_out', which corresponds to the default 'Log
* out' link text.
* @throws \Exception
* @return
*/
public function getDrupalText($name) {
$text = $this->getDrupalParameter('text');
if (!isset($text[$name])) {
throw new \Exception(sprintf('No such Drupal string: %s', $name));
}
return $text[$name];
}

/**
* Returns a specific css selector.
*
* @param $name
* string CSS selector name
*/
public function getDrupalSelector($name) {
$text = $this->getDrupalParameter('selectors');
if (!isset($text[$name])) {
throw new \Exception(sprintf('No such selector configured: %s', $name));
}
return $text[$name];
}

/**
* Get active Drupal Driver.
*
Expand Down Expand Up @@ -538,43 +506,14 @@ public function languageCreate(\stdClass $language) {
* The user to log in.
*/
public function login(\stdClass $user) {
$manager = $this->getUserManager();

// Check if logged in.
if ($this->loggedIn()) {
$this->logout();
}

$this->getSession()->visit($this->locatePath('/user'));
$element = $this->getSession()->getPage();
$element->fillField($this->getDrupalText('username_field'), $user->name);
$element->fillField($this->getDrupalText('password_field'), $user->pass);
$submit = $element->findButton($this->getDrupalText('log_in'));
if (empty($submit)) {
throw new \Exception(sprintf("No submit button at %s", $this->getSession()->getCurrentUrl()));
}

// Log in.
$submit->click();

if (!$this->loggedIn()) {
if (isset($user->role)) {
throw new \Exception(sprintf("Unable to determine if logged in because 'log_out' link cannot be found for user '%s' with role '%s'", $user->name, $user->role));
}
else {
throw new \Exception(sprintf("Unable to determine if logged in because 'log_out' link cannot be found for user '%s'", $user->name));
}
}

$manager->setCurrentUser($user);
$this->getAuthenticationManager()->logIn($user);
}

/**
* Logs the current user out.
*/
public function logout() {
$this->getSession()->visit($this->locatePath('/user/logout'));
$this->getUserManager()->setCurrentUser(FALSE);
$this->getAuthenticationManager()->logOut();
}

/**
Expand All @@ -584,44 +523,7 @@ public function logout() {
* Returns TRUE if a user is logged in for this session.
*/
public function loggedIn() {
$session = $this->getSession();

// If the session has not been started yet, or no page has yet been loaded,
// then this is a brand new test session and the user is not logged in.
if (!$session->isStarted() || !$page = $session->getPage()) {
return FALSE;
}

// Look for a css selector to determine if a user is logged in.
// Default is the logged-in class on the body tag.
// Which should work with almost any theme.
try {
if ($page->has('css', $this->getDrupalSelector('logged_in_selector'))) {
return TRUE;
}
} catch (DriverException $e) {
// This test may fail if the driver did not load any site yet.
}

// Some themes do not add that class to the body, so lets check if the
// login form is displayed on /user/login.
$session->visit($this->locatePath('/user/login'));
if (!$page->has('css', $this->getDrupalSelector('login_form_selector'))) {
return TRUE;
}

$session->visit($this->locatePath('/'));

// As a last resort, if a logout link is found, we are logged in. While not
// perfect, this is how Drupal SimpleTests currently work as well.
if ($page->findLink($this->getDrupalText('log_out'))) {
return TRUE;
}

// The user appears to be anonymous. Clear the current user from the user
// manager so this reflects the actual situation.
$this->getUserManager()->setCurrentUser(FALSE);
return FALSE;
return $this->getAuthenticationManager()->loggedIn();
}

/**
Expand Down
Loading

0 comments on commit 1dfccc2

Please sign in to comment.