silverstripe-behat-extension/src/SilverStripe/BehatExtension/Context/LoginContext.php
Ingo Schommer 6a7df2f702 More resistant login form detection
Had some issues with multiple login forms on the same page,
e.g. for social login, or with duplicated hidden login forms
in the header.
2014-04-07 18:08:56 +12:00

201 lines
6.5 KiB
PHP

<?php
namespace SilverStripe\BehatExtension\Context;
use Behat\Behat\Context\ClosuredContextInterface,
Behat\Behat\Context\TranslatedContextInterface,
Behat\Behat\Context\BehatContext,
Behat\Behat\Context\Step,
Behat\Behat\Exception\PendingException;
use Behat\Gherkin\Node\PyStringNode,
Behat\Gherkin\Node\TableNode;
// PHPUnit
require_once 'PHPUnit/Autoload.php';
require_once 'PHPUnit/Framework/Assert/Functions.php';
/**
* LoginContext
*
* Context used to define steps related to login and logout functionality
*/
class LoginContext extends BehatContext
{
protected $context;
/**
* Cache for logInWithPermission()
*/
protected $cache_generatedMembers = array();
/**
* Initializes context.
* Every scenario gets it's own context object.
*
* @param array $parameters context parameters (set them up through behat.yml)
*/
public function __construct(array $parameters)
{
// Initialize your context here
$this->context = $parameters;
}
/**
* Get Mink session from MinkContext
*/
public function getSession($name = null)
{
return $this->getMainContext()->getSession($name);
}
/**
* @Given /^I am logged in$/
*/
public function stepIAmLoggedIn()
{
$c = $this->getMainContext();
$adminUrl = $c->joinUrlParts($c->getBaseUrl(), $c->getAdminUrl());
$loginUrl = $c->joinUrlParts($c->getBaseUrl(), $c->getLoginUrl());
$this->getSession()->visit($adminUrl);
if (0 == strpos($this->getSession()->getCurrentUrl(), $loginUrl)) {
$this->stepILogInWith('admin', 'password');
assertStringStartsWith($adminUrl, $this->getSession()->getCurrentUrl());
}
}
/**
* Creates a member in a group with the correct permissions.
* Example: Given I am logged in with "ADMIN" permissions
*
* @Given /^I am logged in with "([^"]*)" permissions$/
*/
function iAmLoggedInWithPermissions($permCode)
{
if (!isset($this->cache_generatedMembers[$permCode])) {
$group = \Group::get()->filter('Title', "$permCode group")->first();
if (!$group) {
$group = \Injector::inst()->create('Group');
}
$group->Title = "$permCode group";
$group->write();
$permission = \Injector::inst()->create('Permission');
$permission->Code = $permCode;
$permission->write();
$group->Permissions()->add($permission);
$member = \DataObject::get_one('Member', sprintf('"Email" = \'%s\'', "$permCode@example.org"));
if (!$member) {
$member = \Injector::inst()->create('Member');
}
// make sure any validation for password is skipped, since we're not testing complexity here
$validator = \Member::password_validator();
\Member::set_password_validator(null);
$member->FirstName = $permCode;
$member->Surname = "User";
$member->Email = "$permCode@example.org";
$member->changePassword('secret');
$member->write();
$group->Members()->add($member);
\Member::set_password_validator($validator);
$this->cache_generatedMembers[$permCode] = $member;
}
return new Step\Given(sprintf('I log in with "%s" and "%s"', "$permCode@example.org", 'secret'));
}
/**
* @Given /^I am not logged in$/
*/
public function stepIAmNotLoggedIn()
{
$c = $this->getMainContext();
$this->getSession()->visit($c->joinUrlParts($c->getBaseUrl(), 'Security/logout'));
}
/**
* @When /^I log in with "(?<username>[^"]*)" and "(?<password>[^"]*)"$/
*/
public function stepILogInWith($email, $password)
{
$page = $this->getSession()->getPage();
$forms = $page->findAll('css', 'form[action="Security/LoginForm"]');
assertNotNull($forms, 'Login form not found');
// Try to find visible forms on current page
// Allow multiple login forms (e.g. social login) by filering for "Email" field
$visibleForm = null;
foreach($forms as $form) {
if($form->isVisible() && $form->find('css', '[name=Email]')) {
$visibleForm = $form;
}
}
// If no login form, go to /security/login page
if(!$visibleForm) {
$c = $this->getMainContext();
$loginUrl = $c->joinUrlParts($c->getBaseUrl(), $c->getLoginUrl());
$this->getSession()->visit($loginUrl);
$page = $this->getSession()->getPage();
$forms = $page->findAll('css', 'form[action="Security/LoginForm"]');
}
// Try to find visible forms again on login page.
$visibleForm = null;
foreach($forms as $form) {
if($form->isVisible() && $form->find('css', '[name=Email]')) {
$visibleForm = $form;
}
}
assertNotNull($visibleForm, 'Could not find login form');
$emailField = $visibleForm->find('css', '[name=Email]');
$passwordField = $visibleForm->find('css', '[name=Password]');
$submitButton = $visibleForm->find('css', '[type=submit]');
assertNotNull($emailField, 'Email field on login form not found');
assertNotNull($passwordField, 'Password field on login form not found');
assertNotNull($submitButton, 'Submit button on login form not found');
$emailField->setValue($email);
$passwordField->setValue($password);
$submitButton->press();
}
/**
* @Given /^I should see a log-in form$/
*/
public function stepIShouldSeeALogInForm()
{
$page = $this->getSession()->getPage();
$loginForm = $page->find('css', '#MemberLoginForm_LoginForm');
assertNotNull($loginForm, 'I should see a log-in form');
}
/**
* @Then /^I will see a "([^"]*)" log-in message$/
*/
public function stepIWillSeeALogInMessage($type)
{
$page = $this->getSession()->getPage();
$message = $page->find('css', sprintf('.message.%s', $type));
assertNotNull($message, sprintf('%s message not found.', $type));
}
/**
* @Then /^the password for "([^"]*)" should be "([^"]*)"$/
*/
public function stepPasswordForEmailShouldBe($id, $password)
{
$member = \Member::get()->filter('Email', $id)->First();
assertNotNull($member);
assertTrue($member->checkPassword($password)->valid());
}
}