mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge remote-tracking branch 'origin/3.0' into 3.1
Conflicts: tests/behat/features/bootstrap/SilverStripe/Framework/Test/Behaviour/CmsUiContext.php
This commit is contained in:
commit
7791f20f49
23
dev/BehatFixtureFactory.php
Normal file
23
dev/BehatFixtureFactory.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package framework
|
||||||
|
* @subpackage testing
|
||||||
|
*/
|
||||||
|
class BehatFixtureFactory extends \FixtureFactory {
|
||||||
|
public function createObject($name, $identifier, $data = null) {
|
||||||
|
if(!$data) $data = array();
|
||||||
|
|
||||||
|
// Copy identifier to some visible property unless its already defined.
|
||||||
|
// Exclude files, since they generate their own named based on the file path.
|
||||||
|
if(!is_a($name, 'File', true)) {
|
||||||
|
foreach(array('Name', 'Title') as $fieldName) {
|
||||||
|
if(singleton($name)->hasField($fieldName) && !isset($data[$fieldName])) {
|
||||||
|
$data[$fieldName] = $identifier;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::createObject($name, $identifier, $data);
|
||||||
|
}
|
||||||
|
}
|
@ -116,6 +116,7 @@ class FixtureBlueprint {
|
|||||||
|
|
||||||
$this->setValue($obj, $fieldName, $fieldVal, $fixtures);
|
$this->setValue($obj, $fieldName, $fieldVal, $fixtures);
|
||||||
}
|
}
|
||||||
|
|
||||||
$obj->write();
|
$obj->write();
|
||||||
|
|
||||||
// Save to fixture before relationship processing in case of reflexive relationships
|
// Save to fixture before relationship processing in case of reflexive relationships
|
||||||
|
@ -5,6 +5,7 @@ namespace SilverStripe\Framework\Test\Behaviour;
|
|||||||
use SilverStripe\BehatExtension\Context\SilverStripeContext,
|
use SilverStripe\BehatExtension\Context\SilverStripeContext,
|
||||||
SilverStripe\BehatExtension\Context\BasicContext,
|
SilverStripe\BehatExtension\Context\BasicContext,
|
||||||
SilverStripe\BehatExtension\Context\LoginContext,
|
SilverStripe\BehatExtension\Context\LoginContext,
|
||||||
|
SilverStripe\BehatExtension\Context\FixtureContext,
|
||||||
SilverStripe\Framework\Test\Behaviour\CmsFormsContext,
|
SilverStripe\Framework\Test\Behaviour\CmsFormsContext,
|
||||||
SilverStripe\Framework\Test\Behaviour\CmsUiContext;
|
SilverStripe\Framework\Test\Behaviour\CmsUiContext;
|
||||||
|
|
||||||
@ -20,6 +21,12 @@ require_once 'PHPUnit/Framework/Assert/Functions.php';
|
|||||||
*/
|
*/
|
||||||
class FeatureContext extends SilverStripeContext
|
class FeatureContext extends SilverStripeContext
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var FixtureFactory
|
||||||
|
*/
|
||||||
|
protected $fixtureFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes context.
|
* Initializes context.
|
||||||
* Every scenario gets it's own context object.
|
* Every scenario gets it's own context object.
|
||||||
@ -28,11 +35,46 @@ class FeatureContext extends SilverStripeContext
|
|||||||
*/
|
*/
|
||||||
public function __construct(array $parameters)
|
public function __construct(array $parameters)
|
||||||
{
|
{
|
||||||
|
parent::__construct($parameters);
|
||||||
|
|
||||||
$this->useContext('BasicContext', new BasicContext($parameters));
|
$this->useContext('BasicContext', new BasicContext($parameters));
|
||||||
$this->useContext('LoginContext', new LoginContext($parameters));
|
$this->useContext('LoginContext', new LoginContext($parameters));
|
||||||
$this->useContext('CmsFormsContext', new CmsFormsContext($parameters));
|
$this->useContext('CmsFormsContext', new CmsFormsContext($parameters));
|
||||||
$this->useContext('CmsUiContext', new CmsUiContext($parameters));
|
$this->useContext('CmsUiContext', new CmsUiContext($parameters));
|
||||||
|
|
||||||
parent::__construct($parameters);
|
$fixtureContext = new FixtureContext($parameters);
|
||||||
|
$fixtureContext->setFixtureFactory($this->getFixtureFactory());
|
||||||
|
$this->useContext('FixtureContext', $fixtureContext);
|
||||||
|
|
||||||
|
// Use blueprints to set user name from identifier
|
||||||
|
$factory = $fixtureContext->getFixtureFactory();
|
||||||
|
$blueprint = \Injector::inst()->create('FixtureBlueprint', 'Member');
|
||||||
|
$blueprint->addCallback('beforeCreate', function($identifier, &$data, &$fixtures) {
|
||||||
|
if(!isset($data['FirstName'])) $data['FirstName'] = $identifier;
|
||||||
|
});
|
||||||
|
$factory->define('Member', $blueprint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMinkParameters(array $parameters)
|
||||||
|
{
|
||||||
|
parent::setMinkParameters($parameters);
|
||||||
|
|
||||||
|
if(isset($parameters['files_path'])) {
|
||||||
|
$this->getSubcontext('FixtureContext')->setFilesPath($parameters['files_path']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return FixtureFactory
|
||||||
|
*/
|
||||||
|
public function getFixtureFactory() {
|
||||||
|
if(!$this->fixtureFactory) {
|
||||||
|
$this->fixtureFactory = \Injector::inst()->create('BehatFixtureFactory');
|
||||||
|
}
|
||||||
|
return $this->fixtureFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setFixtureFactory(FixtureFactory $factory) {
|
||||||
|
$this->fixtureFactory = $factory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ use Behat\Behat\Context\ClosuredContextInterface,
|
|||||||
Behat\Behat\Context\BehatContext,
|
Behat\Behat\Context\BehatContext,
|
||||||
Behat\Behat\Context\Step,
|
Behat\Behat\Context\Step,
|
||||||
Behat\Behat\Exception\PendingException,
|
Behat\Behat\Exception\PendingException,
|
||||||
Behat\Mink\Exception\ElementNotFoundException;
|
Behat\Mink\Exception\ElementNotFoundException,
|
||||||
use Behat\Gherkin\Node\PyStringNode,
|
Behat\Gherkin\Node\PyStringNode,
|
||||||
Behat\Gherkin\Node\TableNode;
|
Behat\Gherkin\Node\TableNode;
|
||||||
|
|
||||||
|
|
||||||
@ -310,7 +310,7 @@ class CmsUiContext extends BehatContext
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Workaround for chosen.js dropdowns which hide the original dropdown field.
|
* Workaround for chosen.js dropdowns or tree dropdowns which hide the original dropdown field.
|
||||||
*
|
*
|
||||||
* @When /^(?:|I )fill in the "(?P<field>(?:[^"]|\\")*)" dropdown with "(?P<value>(?:[^"]|\\")*)"$/
|
* @When /^(?:|I )fill in the "(?P<field>(?:[^"]|\\")*)" dropdown with "(?P<value>(?:[^"]|\\")*)"$/
|
||||||
* @When /^(?:|I )fill in "(?P<value>(?:[^"]|\\")*)" for the "(?P<field>(?:[^"]|\\")*)" dropdown$/
|
* @When /^(?:|I )fill in "(?P<value>(?:[^"]|\\")*)" for the "(?P<field>(?:[^"]|\\")*)" dropdown$/
|
||||||
@ -320,6 +320,12 @@ class CmsUiContext extends BehatContext
|
|||||||
$field = $this->fixStepArgument($field);
|
$field = $this->fixStepArgument($field);
|
||||||
$value = $this->fixStepArgument($value);
|
$value = $this->fixStepArgument($value);
|
||||||
|
|
||||||
|
$nativeField = $this->getSession()->getPage()->findField($field);
|
||||||
|
if($nativeField) {
|
||||||
|
$nativeField->selectOption($value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Given the fuzzy matching, we might get more than one matching field.
|
// Given the fuzzy matching, we might get more than one matching field.
|
||||||
$formFields = array();
|
$formFields = array();
|
||||||
|
|
||||||
@ -338,26 +344,28 @@ class CmsUiContext extends BehatContext
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertGreaterThan(0, count($formFields), sprintf(
|
// Find by name (incl. hidden fields)
|
||||||
'Chosen.js dropdown named "%s" not found',
|
if(!$formFields) {
|
||||||
$field
|
$formFields = $this->getSession()->getPage()->findAll('xpath', "//*[@name='$field']");
|
||||||
));
|
}
|
||||||
|
|
||||||
|
assertGreaterThan(0, count($formFields), sprintf(
|
||||||
|
'Chosen.js dropdown named "%s" not found',
|
||||||
|
$field
|
||||||
|
));
|
||||||
|
|
||||||
|
// Traverse up to field holder
|
||||||
$containers = array();
|
$containers = array();
|
||||||
foreach($formFields as $formField) {
|
foreach($formFields as $formField) {
|
||||||
// Traverse up to field holder
|
|
||||||
$containerCandidate = $formField;
|
|
||||||
do {
|
do {
|
||||||
$containerCandidate = $containerCandidate->getParent();
|
$container = $formField->getParent();
|
||||||
} while($containerCandidate && !preg_match('/field/', $containerCandidate->getAttribute('class')));
|
$containerClasses = explode(' ', $container->getAttribute('class'));
|
||||||
|
$containers[] = $container;
|
||||||
if(
|
} while(
|
||||||
$containerCandidate
|
$container
|
||||||
&& $containerCandidate->isVisible()
|
&& in_array('field', $containerClasses)
|
||||||
&& preg_match('/field/', $containerCandidate->getAttribute('class'))
|
&& $container->getTagName() != 'form'
|
||||||
) {
|
);
|
||||||
$containers[] = $containerCandidate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assertGreaterThan(0, count($containers), 'Chosen.js field container not found');
|
assertGreaterThan(0, count($containers), 'Chosen.js field container not found');
|
||||||
@ -371,17 +379,27 @@ class CmsUiContext extends BehatContext
|
|||||||
$this->getSession()->wait(100); // wait for dropdown overlay to appear
|
$this->getSession()->wait(100); // wait for dropdown overlay to appear
|
||||||
$linkEl->click();
|
$linkEl->click();
|
||||||
|
|
||||||
|
if(in_array('treedropdown', $containerClasses)) {
|
||||||
|
// wait for ajax dropdown to load
|
||||||
|
$this->getSession()->wait(
|
||||||
|
5000,
|
||||||
|
"jQuery('#" . $container->getAttribute('id') . " .treedropdownfield-panel li').length > 0"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// wait for dropdown overlay to appear (might be animated)
|
||||||
|
$this->getSession()->wait(300);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$listEl = $container->find('xpath', sprintf('.//li[contains(normalize-space(string(.)), \'%s\')]', $value));
|
$listEl = $container->find('xpath', sprintf('.//li[contains(normalize-space(string(.)), \'%s\')]', $value));
|
||||||
assertNotNull($listEl, sprintf(
|
if(null === $listEl) {
|
||||||
|
throw new \InvalidArgumentException(sprintf(
|
||||||
'Chosen.js list element with title "%s" not found',
|
'Chosen.js list element with title "%s" not found',
|
||||||
$value
|
$value
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// Dropdown flyout might be animated
|
$listEl->find('xpath', './/a')->click();
|
||||||
// $this->getSession()->wait(1000, 'jQuery(":animated").length == 0');
|
|
||||||
$this->getSession()->wait(300);
|
|
||||||
|
|
||||||
$listEl->click();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,37 +5,10 @@ Feature: Manage files
|
|||||||
So that I can insert them into my content efficiently
|
So that I can insert them into my content efficiently
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
# Idea: We could weave the database reset into this through
|
Given a "file" "assets/folder1/file1.jpg"
|
||||||
# saying 'Given there are ONLY the following...'.
|
And a "file" "assets/folder1/folder1.1/file2.jpg"
|
||||||
Given there are the following Folder records
|
And a "folder" "assets/folder2"
|
||||||
"""
|
|
||||||
folder1:
|
|
||||||
Filename: assets/folder1
|
|
||||||
folder1.1:
|
|
||||||
Filename: assets/folder1/folder1.1
|
|
||||||
Parent: =>Folder.folder1
|
|
||||||
folder2:
|
|
||||||
Filename: assets/folder2
|
|
||||||
Name: folder2
|
|
||||||
"""
|
|
||||||
And there are the following File records
|
|
||||||
"""
|
|
||||||
file1:
|
|
||||||
Filename: assets/folder1/file1.jpg
|
|
||||||
Name: file1.jpg
|
|
||||||
Parent: =>Folder.folder1
|
|
||||||
file2:
|
|
||||||
Filename: assets/folder1/folder1.1/file2.jpg
|
|
||||||
Name: file2.jpg
|
|
||||||
Parent: =>Folder.folder1.1
|
|
||||||
"""
|
|
||||||
And I am logged in with "ADMIN" permissions
|
And I am logged in with "ADMIN" permissions
|
||||||
# Alternative fixture shortcuts, with their titles
|
|
||||||
# as shown in admin/security rather than technical permission codes.
|
|
||||||
# Just an idea for now, could be handled by YAML fixtures as well
|
|
||||||
# And I am logged in with the following permissions
|
|
||||||
# - Access to 'Pages' section
|
|
||||||
# - Access to 'Files' section
|
|
||||||
And I go to "/admin/assets"
|
And I go to "/admin/assets"
|
||||||
|
|
||||||
@modal
|
@modal
|
||||||
@ -76,7 +49,7 @@ Feature: Manage files
|
|||||||
Scenario: I can change the folder of a file
|
Scenario: I can change the folder of a file
|
||||||
Given I click on "folder1" in the "Files" table
|
Given I click on "folder1" in the "Files" table
|
||||||
And I click on "file1" in the "folder1" table
|
And I click on "file1" in the "folder1" table
|
||||||
And I fill in =>Folder.folder2 for "ParentID"
|
And I fill in "folder2" for "ParentID" dropdown
|
||||||
And I press the "Save" button
|
And I press the "Save" button
|
||||||
# /show/0 is to ensure that we are on top level folder
|
# /show/0 is to ensure that we are on top level folder
|
||||||
And I go to "/admin/assets/show/0"
|
And I go to "/admin/assets/show/0"
|
||||||
|
@ -1,48 +1,21 @@
|
|||||||
@database-defaults
|
@javascript
|
||||||
Feature: Manage users
|
Feature: Manage users
|
||||||
As a site administrator
|
As a site administrator
|
||||||
I want to create and manage user accounts on my site
|
I want to create and manage user accounts on my site
|
||||||
So that I can control access to the CMS
|
So that I can control access to the CMS
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given there are the following Permission records
|
Given a "member" "Admin" belonging to "Admin Group" with "Email"="admin@test.com"
|
||||||
"""
|
And a "member" "Staff" belonging to "Staff Group" with "Email"="staffmember@test.com"
|
||||||
admin:
|
And the "group" "Admin Group" has permissions "Full administrative rights"
|
||||||
Code: ADMIN
|
|
||||||
security-admin:
|
|
||||||
Code: CMS_ACCESS_SecurityAdmin
|
|
||||||
"""
|
|
||||||
And there are the following Group records
|
|
||||||
"""
|
|
||||||
admingroup:
|
|
||||||
Title: Admin Group
|
|
||||||
Code: admin
|
|
||||||
Permissions: =>Permission.admin
|
|
||||||
staffgroup:
|
|
||||||
Title: Staff Group
|
|
||||||
Code: staffgroup
|
|
||||||
"""
|
|
||||||
And there are the following Member records
|
|
||||||
"""
|
|
||||||
admin:
|
|
||||||
FirstName: Admin
|
|
||||||
Email: admin@test.com
|
|
||||||
Groups: =>Group.admingroup
|
|
||||||
staffmember:
|
|
||||||
FirstName: Staff
|
|
||||||
Email: staffmember@test.com
|
|
||||||
Groups: =>Group.staffgroup
|
|
||||||
"""
|
|
||||||
And I am logged in with "ADMIN" permissions
|
And I am logged in with "ADMIN" permissions
|
||||||
And I go to "/admin/security"
|
And I go to "/admin/security"
|
||||||
|
|
||||||
@javascript
|
|
||||||
Scenario: I can list all users regardless of group
|
Scenario: I can list all users regardless of group
|
||||||
When I click the "Users" CMS tab
|
When I click the "Users" CMS tab
|
||||||
Then I should see "admin@test.com" in the "#Root_Users" element
|
Then I should see "admin@test.com" in the "#Root_Users" element
|
||||||
And I should see "staffmember@test.com" in the "#Root_Users" element
|
And I should see "staffmember@test.com" in the "#Root_Users" element
|
||||||
|
|
||||||
@javascript
|
|
||||||
Scenario: I can list all users in a specific group
|
Scenario: I can list all users in a specific group
|
||||||
When I click the "Groups" CMS tab
|
When I click the "Groups" CMS tab
|
||||||
# TODO Please check how performant this is
|
# TODO Please check how performant this is
|
||||||
@ -50,7 +23,6 @@ Feature: Manage users
|
|||||||
Then I should see "admin@test.com" in the "#Root_Members" element
|
Then I should see "admin@test.com" in the "#Root_Members" element
|
||||||
And I should not see "staffmember@test.com" in the "#Root_Members" element
|
And I should not see "staffmember@test.com" in the "#Root_Members" element
|
||||||
|
|
||||||
@javascript
|
|
||||||
Scenario: I can add a user to the system
|
Scenario: I can add a user to the system
|
||||||
When I click the "Users" CMS tab
|
When I click the "Users" CMS tab
|
||||||
And I press the "Add Member" button
|
And I press the "Add Member" button
|
||||||
@ -64,12 +36,10 @@ Feature: Manage users
|
|||||||
When I go to "admin/security/"
|
When I go to "admin/security/"
|
||||||
Then I should see "john.doe@test.com" in the "#Root_Users" element
|
Then I should see "john.doe@test.com" in the "#Root_Users" element
|
||||||
|
|
||||||
@javascript
|
|
||||||
Scenario: I can edit an existing user and add him to an existing group
|
Scenario: I can edit an existing user and add him to an existing group
|
||||||
When I click the "Users" CMS tab
|
When I click the "Users" CMS tab
|
||||||
And I click "staffmember@test.com" in the "#Root_Users" element
|
And I click "staffmember@test.com" in the "#Root_Users" element
|
||||||
And I select "Admin Group" from "Groups"
|
And I select "Admin Group" from "Groups"
|
||||||
And I additionally select "Administrators" from "Groups"
|
|
||||||
And I press the "Save" button
|
And I press the "Save" button
|
||||||
Then I should see a "Saved Member" message
|
Then I should see a "Saved Member" message
|
||||||
|
|
||||||
@ -78,7 +48,6 @@ Feature: Manage users
|
|||||||
And I click "Admin Group" in the "#Root_Groups" element
|
And I click "Admin Group" in the "#Root_Groups" element
|
||||||
Then I should see "staffmember@test.com"
|
Then I should see "staffmember@test.com"
|
||||||
|
|
||||||
@javascript
|
|
||||||
Scenario: I can delete an existing user
|
Scenario: I can delete an existing user
|
||||||
When I click the "Users" CMS tab
|
When I click the "Users" CMS tab
|
||||||
And I click "staffmember@test.com" in the "#Root_Users" element
|
And I click "staffmember@test.com" in the "#Root_Users" element
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
@database-defaults
|
|
||||||
Feature: My Profile
|
Feature: My Profile
|
||||||
As a CMS user
|
As a CMS user
|
||||||
I want to be able to change personal settings
|
I want to be able to change personal settings
|
||||||
|
Loading…
Reference in New Issue
Block a user