diff --git a/Features/Context/ContentActions.php b/Features/Context/ContentActions.php index 584b7827f..eced2e2e3 100644 --- a/Features/Context/ContentActions.php +++ b/Features/Context/ContentActions.php @@ -9,8 +9,29 @@ */ namespace EzSystems\PlatformUIBundle\Features\Context; +use PHPUnit_Framework_Assert as Assertion; + class ContentActions extends PlatformUI { + /** + * @var EzSystems\PlatformUIBundle\Features\Context\SubContext\ContentEditContext + */ + protected $contentEditContext; + + /** + * @var EzSystems\PlatformUIBundle\Features\Context\SubContext\DashboardContext + */ + protected $dashboardContext; + + /** + */ + private function iSeeNotification($message) + { + $this->sleep(); + $result = $this->getElementByText($message, '.ez-notification-text'); + Assertion::AssertNotNull($result); + } + /** * @Then I am notified that :name has been copied under :destiny */ @@ -25,10 +46,11 @@ public function iSeeCopiedNotification($name, $destiny) */ public function moveInto($name, $destiny) { - $this->onFullView($name); - $this->clickActionBar('Move'); - $this->selectFromUniversalDiscovery("eZ Platform/$destiny"); - $this->confirmSelection(); + $this->contentEditContext->onFullView($name); + $this->waitWhileLoading(); + $this->dashboardContext->clickActionBar('Move'); + $this->dashboardContext->selectFromUniversalDiscovery("eZ Platform/$destiny"); + $this->dashboardContext->confirmSelection(); $destinyName = explode('/', $destiny); $destinyName = end($destinyName); $this->iSeeMovedNotification($name, $destinyName); @@ -58,9 +80,9 @@ public function iSeeMovedNotification($name, $destiny) */ public function removeContent($name) { - $this->onFullView($name); + $this->contentEditContext->onFullView($name); $this->waitWhileLoading(); - $this->clickActionBar('Send to Trash'); + $this->dashboardContext->clickActionBar('Send to Trash'); } /** diff --git a/Features/Context/Fields.php b/Features/Context/Fields.php index 6a00caf20..7ce13da9a 100644 --- a/Features/Context/Fields.php +++ b/Features/Context/Fields.php @@ -9,14 +9,24 @@ */ namespace EzSystems\PlatformUIBundle\Features\Context; -use EzSystems\BehatBundle\ObjectManager\FieldType; use Behat\Mink\WebAssert; +use eZ\Bundle\EzPublishCoreBundle\Features\Context\FieldTypeContext as FieldType; class Fields extends PlatformUI { const NOTIFICATION_CONTENT_PUBLISHED = 'Content has been published'; const NOTIFICATION_PUBLISH_ERROR = 'An error occured while publishing the draft'; + /** + * @var eZ\Bundle\EzPublishCoreBundle\Features\Context\FieldTypeContext + */ + protected $fieldtypeContext; + + /** + * @var EzSystems\PlatformUIBundle\Features\Context\SubContext\DashboardContext + */ + protected $dashboardContext; + protected function getFieldIdentCss($identifier, $contentId = '') { return "ez-field-$contentId-$identifier"; @@ -49,12 +59,11 @@ protected function getEditLabelCss($type, $fieldIdentifier = '', $contentId = '' protected function getThisFieldIdent() { - $fieldManager = $this->getFieldTypeManager(); - $identifier = $fieldManager->getThisFieldTypeIdentifier(); + $identifier = $this->fieldtypeContext->getThisFieldTypeIdentifier(); // check if we are editing a field for draft or published content - if ($fieldManager->getFieldContentState() == FieldType::CONTENT_PUBLISHED) { - $contentId = $fieldManager->getThisContentId(); + if ($this->fieldtypeContext->getFieldContentState() == FieldType::CONTENT_PUBLISHED) { + $contentId = $this->fieldtypeContext->getThisContentId(); } else { $contentId = ''; } @@ -67,14 +76,13 @@ protected function getThisFieldIdent() */ public function createAContentOfThisType() { - $fieldManager = $this->getFieldTypeManager(); - $fieldManager->setFieldContentState(FieldType::CONTENT_TYPE_PUBLISHED); - $name = $fieldManager->getThisContentTypeName(); + $this->fieldtypeContext->setFieldContentState(FieldType::CONTENT_TYPE_PUBLISHED); + $name = $this->fieldtypeContext->getThisContentTypeName(); - $this->clickNavigationZone('Content'); - $this->clickNavigationItem('Content structure'); - $this->clickActionBar('Create'); - $this->clickContentType($name); + $this->dashboardContext->clickNavigationZone('Content'); + $this->dashboardContext->clickNavigationItem('Content structure'); + $this->dashboardContext->clickActionBar('Create'); + $this->dashboardContext->clickContentType($name); $this->platformStatus = self::WAITING_FOR_PUBLISHING; } @@ -83,14 +91,13 @@ public function createAContentOfThisType() */ public function editThisContent() { - $fieldManager = $this->getFieldTypeManager(); - $fieldManager->setFieldContentState(FieldType::CONTENT_PUBLISHED); - $name = $fieldManager->getThisContentName(); + $this->fieldtypeContext->setFieldContentState(FieldType::CONTENT_PUBLISHED); + $name = $this->fieldtypeContext->getThisContentName(); - $this->clickNavigationZone('Content'); - $this->clickNavigationItem('Content structure'); - $this->clickOnTreePath($name); - $this->clickActionBar('Edit'); + $this->dashboardContext->clickNavigationZone('Content'); + $this->dashboardContext->clickNavigationItem('Content structure'); + $this->dashboardContext->clickOnTreePath($name); + $this->dashboardContext->clickActionBar('Edit'); $this->platformStatus = self::WAITING_FOR_PUBLISHING; // assert $this->iSeeContentEditView(); @@ -147,7 +154,7 @@ public function uncheckFieldValue() public function publishContent() { if ($this->platformStatus == self::WAITING_FOR_PUBLISHING) { - $this->clickEditActionBar('Publish'); + $this->dashboardContext->clickEditActionBar('Publish'); } else { throw new \Exception('Cannot publish content, application in wrong state'); } @@ -161,9 +168,8 @@ public function publishContent() public function seeRequiredFieldtOfType($label) { if ($this->platformStatus == self::WAITING_FOR_PUBLISHING) { - $fieldManager = $this->getFieldTypeManager(); // $type = ... - //$name = $fieldManager->getThisFieldTypeName(); + //$name = $fieldtypeContext->getThisFieldTypeName(); $verification = new WebAssert($this->getSession()); //$verification->elementTextContains('css', $this->getEditLabelCss($type, $name), $label . '*');. @@ -186,7 +192,7 @@ public function iSeeContentEditView() */ public function contentIsPublished() { - $this->iSeeNotification(self::NOTIFICATION_CONTENT_PUBLISHED); + $this->dashboardContext->iSeeNotification(self::NOTIFICATION_CONTENT_PUBLISHED); } /** @@ -205,11 +211,11 @@ public function failsWithMessage($message) public function seeFieldtOfType($type, $label = null) { if ($this->platformStatus == self::WAITING_FOR_PUBLISHING) { - $this->clickEditActionBar('Publish'); + $this->dashboardContext->clickEditActionBar('Publish'); } $verification = new WebAssert($this->getSession()); // for view we need the internal field identifier... - $internalName = $this->getFieldTypeManager()->getFieldTypeInternalIdentifier($type); + $internalName = $this->fieldtypeContext->getFieldTypeInternalIdentifier($type); $verification->elementExists('css', ".ez-fieldview-$internalName .ez-fieldview-value-content"); if ($label != null) { @@ -222,13 +228,12 @@ public function seeFieldtOfType($type, $label = null) */ public function viewThisContent() { - $fieldManager = $this->getFieldTypeManager(); - $fieldManager->setFieldContentState(FieldType::CONTENT_PUBLISHED); - $name = $fieldManager->getThisContentName(); + $this->fieldtypeContext->setFieldContentState(FieldType::CONTENT_PUBLISHED); + $name = $this->fieldtypeContext->getThisContentName(); - $this->clickNavigationZone('Content'); - $this->clickNavigationItem('Content structure'); - $this->clickOnTreePath($name); + $this->dashboardContext->clickNavigationZone('Content'); + $this->dashboardContext->clickNavigationItem('Content structure'); + $this->dashboardContext->clickOnTreePath($name); } /** diff --git a/Features/Context/PlatformUI.php b/Features/Context/PlatformUI.php index 91c68d106..12769dae0 100644 --- a/Features/Context/PlatformUI.php +++ b/Features/Context/PlatformUI.php @@ -9,9 +9,11 @@ */ namespace EzSystems\PlatformUIBundle\Features\Context; -use EzSystems\BehatBundle\Context\Browser\Context; +use ReflectionClass; +use Behat\Behat\Hook\Scope\BeforeScenarioScope; +use Behat\MinkExtension\Context\RawMinkContext; -class PlatformUI extends Context +class PlatformUI extends RawMinkContext { /** * Default Platform URI. @@ -44,9 +46,6 @@ class PlatformUI extends Context const NOT_WAITING = 0; const WAITING_FOR_PUBLISHING = 1; - use SubContext\Authentication; - use SubContext\CommonActions; - /** * PlatformUI relative URL path. * @@ -79,11 +78,6 @@ class PlatformUI extends Context */ protected $platformStatus = self::NOT_WAITING; - /** - * Mapping of the new paths of contents after being moved. - */ - protected $newPathsMap = array(); - /** * Initialize class. * @@ -91,9 +85,6 @@ class PlatformUI extends Context */ public function __construct($uri = self::PLATFORM_URI, $user = null, $password = null) { - parent::__construct(); - $this->pageIdentifierMap['roles'] = '/ez#/admin/pjax%2Frole'; - $this->pageIdentifierMap['users'] = '/ez#/view/%2Fapi%2Fezp%2Fv2%2Fcontent%2Flocations%2F1%2F5/eng-GB'; $this->platformUiUri = $uri; if ($user != null) { $this->user = $user; @@ -103,6 +94,30 @@ public function __construct($uri = self::PLATFORM_URI, $user = null, $password = } } + /** + * @BeforeScenario + * + * Default gather contexts method. + * Uses doc comment type hint to get the contexts and set them + */ + public function gatherContexts(BeforeScenarioScope $scope) + { + $refClass = new ReflectionClass($this); + $refProperties = $refClass->getProperties(); + foreach ($refProperties as $refProperty) { + $propertyName = $refProperty->getName(); + // get property type hint from doc comment + preg_match_all('#@var\s(.*?)\n#s', $refProperty->getDocComment(), $matches); + foreach ($matches[1] as $typeHint) { + // checks if the type hint implements Behat Context + $implements = @class_implements($typeHint); + if (!empty($implements) && in_array('Behat\Behat\Context\Context', $implements)) { + $this->$propertyName = $scope->getEnvironment()->getContext($typeHint); + } + } + } + } + /** * @BeforeScenario */ @@ -118,7 +133,6 @@ public function afterScenario() { $this->closeConfirmBox(); $this->closeEditView(); - $this->iLogout(); } /** @@ -130,11 +144,41 @@ public function beforeStep() $this->waitWhileLoading(); } - /** - * @AfterStep - */ - public function afterStep() + public function fillFieldWithValue($field, $value = '') { + $fieldNode = $this->spin( + function () use ($field) { + $fieldNode = $this->getSession()->getPage()->findField($field); + if ($fieldNode == null) { + throw new \Exception('Field not found'); + } + + return $fieldNode; + } + ); + + $this->spin( + function () use ($fieldNode, $field, $value) { + // make sure any autofocus elements don't mis-behave when setting value + $fieldNode->blur(); + usleep(10 * 1000); + $fieldNode->focus(); + usleep(10 * 1000); + + // setting value on pre-filled inputs can cause issues, clearing before + $fieldNode->setValue(''); + $fieldNode->setValue($value); + + // verication that the field was really filled in correctly + $this->sleep(); + $check = $this->getSession()->getPage()->findField($field)->getValue(); + if ($check != $value) { + throw new \Exception('Failed to set the field value: ' . $check); + } + + return true; + } + ); } /** @@ -284,7 +328,7 @@ function () use ($selector, $baseElement, $checkVisibility) { * @param string $selector CSS selector of the element * @param string $textSelector Extra CSS selector for text of the element * @param string $baseElement Element in which the search is based - * @param int $iteration Iteration number, used to control number of executions + * * @return array */ protected function getElementByText($text, $selector, $textSelector = null, $baseElement = null) @@ -408,33 +452,4 @@ protected function closeEditView() } catch (\Exception $e) { } } - /** - * Attaches a file to a input field on the HTML. - * - * @param string $file file name relative to mink definitions - * @param string $selector CSS file upload element selector - */ - protected function attachFile($fileName, $selector) - { - if ($this->getMinkParameter('files_path')) { - $fullPath = rtrim( - realpath( - $this->getMinkParameter('files_path') - ), - DIRECTORY_SEPARATOR - ) . DIRECTORY_SEPARATOR . $fileName; - - if (is_file($fullPath)) { - $fileInput = 'input[type="file"]' . $selector; - $field = $this->getSession()->getPage()->find('css', $fileInput); - - if (null === $field) { - throw new Exception("File input $selector is not found"); - } - $field->attachFile($fullPath); - } - } else { - throw new Exception("File $fileName is not found at the given location: $fullPath"); - } - } } diff --git a/Features/Context/Role.php b/Features/Context/Role.php index be9126de8..a81357aa6 100644 --- a/Features/Context/Role.php +++ b/Features/Context/Role.php @@ -14,12 +14,34 @@ class Role extends PlatformUI { /** - * @Given I am on the RolesUI + * @var EzSystems\PlatformUIBundle\Features\Context\SubContext\DashboardContext + */ + protected $dashboardContext; + + /** + * @var EzSystems\PlatformUIBundle\Features\Context\SubContext\BrowserContext + */ + protected $browserContext; + + /** + * @Given I am on the Roles page */ public function onRolesPage() { - $this->clickNavigationZone('Admin Panel'); - $this->clickNavigationItem('Roles'); + $this->getSession()->visit( + $this->locatePath( + self::PLATFORM_URI . '#/admin/pjax%2Frole' + ) + ); + } + + /** + * @Given I am on the RolesUI + */ + public function onRolesUI() + { + $this->dashboardContext->clickNavigationZone('Admin Panel'); + $this->dashboardContext->clickNavigationItem('Roles'); } /** @@ -70,7 +92,7 @@ public function iEditRole($name) */ public function roleDetailsView($role) { - $this->onRolesPage(); + $this->onRolesUI(); $this->clickElementByText($role, '.ez-role-name a'); } @@ -79,7 +101,7 @@ public function roleDetailsView($role) */ public function iSeeRolePage() { - $this->iSeeTitle('Roles'); + $this->browserContext->iSeeTitle('Roles'); } /** @@ -112,7 +134,7 @@ public function noAssigmentsForThisRole() */ public function roleWasPublished() { - $this->iSeeNotification('The role was published.'); + $this->dashboardContext->iSeeNotification('The role was published.'); } /** @@ -132,9 +154,9 @@ public function roleWasNotPublished($name) */ public function nameAlreadyExists($name) { - $this->iSeeNotification('Form did not validate. Please review errors below.'); + $this->dashboardContext->iSeeNotification('Form did not validate. Please review errors below.'); $element = $this->getElementByText( - 'Identifier "' . $name . '" already exists. Role identifier must be unique.', + 'Identifier "' . $name . '" already exists. Role identifier must be unique.', 'li' ); if (!$element) { @@ -147,7 +169,7 @@ public function nameAlreadyExists($name) */ public function roleAssigmentLabel() { - $this->iSeeTitle('Invalid argument: The role name must be unique.'); + $this->browserContext->iSeeTitle('Invalid argument: The role name must be unique.'); } /** diff --git a/Features/Context/SubContext/Authentication.php b/Features/Context/SubContext/Authentication.php index bbe5e7e95..588493ca7 100644 --- a/Features/Context/SubContext/Authentication.php +++ b/Features/Context/SubContext/Authentication.php @@ -9,8 +9,19 @@ */ namespace EzSystems\PlatformUIBundle\Features\Context\SubContext; -trait Authentication +use EzSystems\PlatformUIBundle\Features\Context\PlatformUI; +use EzSystems\PlatformBehatBundle\Context\RepositoryContext; +use eZ\Publish\API\Repository\Repository; +use eZ\Publish\API\Repository\UserService; +use eZ\Publish\API\Repository\RoleService; + +class Authentication extends PlatformUI { + use RepositoryContext; + + const DEFAULT_LANGUAGE = 'eng-GB'; + const USERGROUP_ROOT_CONTENT_ID = 4; + /** * Control variable to check if logged in. * @@ -18,12 +29,85 @@ trait Authentication */ protected $shouldBeLoggedIn; + /** + * @var \eZ\Publish\API\Repository\UserService + */ + protected $userService; + + /** + * @var \eZ\Publish\API\Repository\RoleService + */ + protected $roleService; + + /** + * @injectService $repository @ezpublish.api.repository + * @injectService $userService @ezpublish.api.service.user + * @injectService $roleService @ezpublish.api.service.role + */ + public function __construct(Repository $repository, UserService $userService, RoleService $roleService) + { + $this->setRepository($repository); + $this->userService = $userService; + $this->roleService = $roleService; + } + + /** + * Get credentials for a specific role. + * + * @uses \EzSystems\BehatBundle\Context\Object\User + * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException + * + * @param string $role Role intended for testing + * + * @return array Associative with 'login' and 'password' + */ + protected function getCredentialsFor($roleIdentifier) + { + $role = $this->roleService->loadRoleByIdentifier($roleIdentifier); + + // create a new user, uses 'User' trait + $username = 'User' . uniqid(); + $password = $username; + $email = "${username}@ez.no"; + $userCreateStruct = $this->userService->newUserCreateStruct( + $username, + $email, + $password, + self::DEFAULT_LANGUAGE + ); + $userCreateStruct->setField('first_name', $username); + $userCreateStruct->setField('last_name', $username); + + $parentGroup = $this->userService->loadUserGroup(self::USERGROUP_ROOT_CONTENT_ID); + $user = $this->userService->createUser($userCreateStruct, array($parentGroup)); + + // Assign role to created user (without limitation) + $this->roleService->assignRoleToUser($role, $user); + + return array( + 'login' => $username, + 'password' => $password, + ); + } + + /** + * @AfterScenario + */ + public function afterScenarioLogout() + { + $this->iLogout(); + } + /** * @Given I go to homepage */ public function goToPlatformUi($url = '') { - $this->visit($this->platformUiUri . $url); + $this->getSession()->visit( + $this->locatePath( + self::PLATFORM_URI . $url + ) + ); } /** @@ -35,7 +119,7 @@ public function goToPlatformUiAndLogIn($username, $password) $this->waitWhileLoading(); $this->fillFieldWithValue('username', $username); $this->fillFieldWithValue('password', $password); - $this->iClickAtButton('Login'); + $this->clickElementByText('Login', 'button'); $this->iShouldBeLoggedIn(); } @@ -68,7 +152,7 @@ public function iLogout() $this->waitWhileLoading(); $el->click(); $this->waitWhileLoading(); - $this->iClickAtLink('Logout'); + $this->clickElementByText('Logout', 'a'); } /** diff --git a/Features/Context/SubContext/BrowserContext.php b/Features/Context/SubContext/BrowserContext.php new file mode 100644 index 000000000..17d027067 --- /dev/null +++ b/Features/Context/SubContext/BrowserContext.php @@ -0,0 +1,134 @@ +clickElementByText($link, 'a'); + } + + /** + * @Given I clicked on/at (the) :button button + * @When I click on/at (the) :button button + * + * Clicks the button identified by ':button' + */ + public function iClickAtButton($button) + { + $this->clickElementByText($button, 'button'); + } + + /** + * @When I fill in :field with :value + * @When I set :field as empty + * + * Spin function make it possible to retry in case of failure + */ + public function fillFieldWithValue($field, $value = '') + { + $fieldNode = $this->spin( + function () use ($field) { + $fieldNode = $this->getSession()->getPage()->findField($field); + if ($fieldNode == null) { + throw new \Exception('Field not found'); + } + + return $fieldNode; + } + ); + + $this->spin( + function () use ($fieldNode, $field, $value) { + // make sure any autofocus elements don't mis-behave when setting value + $fieldNode->blur(); + usleep(10 * 1000); + $fieldNode->focus(); + usleep(10 * 1000); + + // setting value on pre-filled inputs can cause issues, clearing before + $fieldNode->setValue(''); + $fieldNode->setValue($value); + + // verication that the field was really filled in correctly + $this->sleep(); + $check = $this->getSession()->getPage()->findField($field)->getValue(); + if ($check != $value) { + throw new \Exception('Failed to set the field value: ' . $check); + } + + return true; + } + ); + } + + /** + * @Then I (should) see :title title/topic + */ + public function iSeeTitle($title) + { + $page = $this->getSession()->getPage(); + $this->spin( + function () use ($title, $page) { + $titleElements = $page->findAll('css', 'h1, h2, h3'); + foreach ($titleElements as $titleElement) { + $elementText = $titleElement->getText(); + if ($elementText == $title) { + return $titleElement; + } + } + throw new \Exception("Title '$title' not found"); + } + ); + } + + /** + * @Then I should see a :label input field + */ + public function seeInputField($label) + { + $field = $this->getSession()->getPage()->findField($label); + if (!$field) { + throw new \Exception("Field '$label' not found"); + } + } + + /** + * @Given I checked :label checkbox + * @When I check :label checkbox + * + * Toggles the value for the checkbox with name ':label' + */ + public function checkOption($option) + { + $session = $this->getSession(); + $selectorsHandler = $session->getSelectorsHandler(); + $literal = $selectorsHandler->xpathLiteral($option); + + // To be able to work on mink 1.6 (ezplatform) & mink 1.5 (5.4+ezpublish-community) w/o deprecation exceptions + $selector = $selectorsHandler->isSelectorRegistered('named_partial') ? + $selectorsHandler->getSelector('named_partial') : + $selectorsHandler->getSelector('named'); + $xpath = $selector->translateToXPath(array('field', $literal)); + + $fieldElement = $session->getPage()->find('xpath', $xpath); + $fieldElement->check(); + } +} diff --git a/Features/Context/SubContext/CommonActions.php b/Features/Context/SubContext/CommonActions.php deleted file mode 100644 index 0bd5ddd71..000000000 --- a/Features/Context/SubContext/CommonActions.php +++ /dev/null @@ -1,431 +0,0 @@ -clickElementByText($link, 'a'); - } - - /** - * @Given I clicked on/at (the) :button button - * @When I click on/at (the) :button button - * - * Clicks the button identified by ':button' - */ - public function iClickAtButton($button) - { - $this->clickElementByText($button, 'button'); - } - - /** - * @When I fill in :field with :value - * @When I set :field as empty - * - * Spin function make it possible to retry in case of failure - */ - public function fillFieldWithValue($field, $value = '') - { - $fieldNode = $this->spin( - function () use ($field) { - $fieldNode = $this->getSession()->getPage()->findField($field); - if ($fieldNode == null) { - throw new \Exception('Field not found'); - } - - return $fieldNode; - } - ); - - $this->spin( - function () use ($fieldNode, $field, $value) { - // make sure any autofocus elements don't mis-behave when setting value - $fieldNode->blur(); - usleep(10 * 1000); - $fieldNode->focus(); - usleep(10 * 1000); - - // setting value on pre-filled inputs can cause issues, clearing before - $fieldNode->setValue(''); - $fieldNode->setValue($value); - - // verication that the field was really filled in correctly - $this->sleep(); - $check = $this->getSession()->getPage()->findField($field)->getValue(); - if ($check != $value) { - throw new \Exception('Failed to set the field value: ' . $check); - } - - return true; - } - ); - } - - /** - * @Then I (should) see :title title/topic - */ - public function iSeeTitle($title) - { - $page = $this->getSession()->getPage(); - $this->spin( - function () use ($title, $page) { - $titleElements = $page->findAll('css', 'h1, h2, h3'); - foreach ($titleElements as $titleElement) { - $elementText = $titleElement->getText(); - if ($elementText == $title) { - return $titleElement; - } - } - throw new \Exception("Title '$title' not found"); - } - ); - } - - /** - * @Then I should see a :label input field - */ - public function seeInputField($label) - { - $field = $this->getSession()->getPage()->findField($label); - if (!$field) { - throw new \Exception("Field '$label' not found"); - } - } - - /** - * @Given I checked :label checkbox - * @When I check :label checkbox - * - * Toggles the value for the checkbox with name ':label' - */ - public function checkOption($option) - { - $fieldElements = $this->getXpath()->findFields($option); - EzAssertion::assertElementFound($option, $fieldElements, null, 'checkbox'); - - // this is needed for the cases where are checkboxes and radio's - // side by side, for main option the radio and the extra being the - // checkboxes values - if (strtolower($fieldElements[0]->getAttribute('type')) !== 'checkbox') { - $value = $fieldElements[0]->getAttribute('value'); - $fieldElements = $this->getXpath()->findXpath("//input[@type='checkbox' and @value='$value']"); - EzAssertion::assertElementFound($value, $fieldElements, null, 'checkbox'); - } - - $fieldElements[0]->check(); - } - - /** - * @Given I click (on) the logo - * Clicks on the PlatformUI logo - */ - public function clickLogo() - { - $page = $this->getSession()->getPage(); - $selector = '.ez-logo a'; - $page->find('css', $selector)->click(); - } - - /** - * @Given I click (on) the tab :tab - * Clicks on a PlatformUI tab - * - * @param string $tab Text of the element to click - */ - public function clickTab($tab) - { - $this->clickElementByText($tab, '.ez-tabs-label a[href]'); - } - - /** - * @Given I click (on) the navigation zone :zone - * Click on a PlatformUI menu zone - * - * @param string $zone Text of the element to click - */ - public function clickNavigationZone($zone) - { - $this->clickElementByText($zone, '.ez-zone-name'); - $this->waitWhileLoading(); - // Clicking navigation zone triggers load of first item, - // we must wait before interacting with the page (see EZP-25128) - // this method sleeps for a default amount (see EzSystems\PlatformUIBundle\Features\Context\PlaformUI) - $this->sleep(); - } - - /** - * @Given I click on the :button button number :index - * Click on a PlatformUI button - * - * @param string $button Text of the element to click - * @param string $index WHAT IS THIS?! - */ - public function clickButtonWithIndex($button, $index) - { - $this->clickElementByText($button, 'button', $index); - } - - /** - * @Given I click (on) the navigation item :item - * Click on a PlatformUI sub-menu option - * - * @param string $item Text of the element to click - */ - public function clickNavigationItem($item) - { - $this->clickElementByText($item, '.ez-navigation-item'); - $this->waitWhileLoading(); - } - - /** - * @Given I click (on) the discovery bar button :button - * Click on a PlatformUI discovery bar - * - * @param string $button Text of the element to click - */ - public function clickDiscoveryBar($button) - { - $this->clickElementByText($button, '.ez-view-discoverybarview .ez-action', '.action-label'); - $this->waitWhileLoading(); - } - - /** - * @Given I click (on) the action bar button :button - * Click on a PlatformUI action bar - * - * @param string $button Text of the element to click - */ - public function clickActionBar($button) - { - $this->clickElementByText($button, '.ez-actionbar-container .ez-action', '.action-label'); - $this->waitWhileLoading(); - } - - /** - * @Given I click (on) the edit action bar button :button - * Click on a PlatformUI edit action bar - * - * @param string $button Text of the element to click - */ - public function clickEditActionBar($button) - { - $this->clickElementByText($button, '.ez-editactionbar-container .ez-action', '.action-label'); - $this->waitWhileLoading(); - } - - /** - * @Given I click (on) the content tree with path :path - * @Then I see :path in the content tree - * Explores the content tree, expanding it and click on the desired element - * - * @param string $path The content tree path such as 'Content1/Content2/ContentIWantToClick' - */ - public function clickOnTreePath($path) - { - $node = $this->findWithWait('.ez-view-discoverybarview'); - $this->clickDiscoveryBar('Content tree'); - $this->openTreePath($path, $node); - } - - /** - * @Given I click (on) the content type :contentType - * Click on a PlatformUI side menu content type - * - * @param string $contentType Text of the element to click - */ - public function clickContentType($contentType) - { - $this->clickElementByText($contentType, '.ez-contenttypeselector-types .ez-selection-filter-item '); - $this->waitWhileLoading(); - } - - /** - * @Given I create a content of content type :type with: - */ - public function iCreateContentType($type, TableNode $fields) - { - $this->clickNavigationZone('Platform'); - $this->iClickAtLink('Content structure'); - $this->clickActionBar('Create a content'); - $this->clickContentType($type); - foreach ($fields as $fieldArray) { - $keys = array_keys($fieldArray); - for ($i = 0; $i < count($keys); ++$i) { - $this->fillFieldWithValue($keys[$i], $fieldArray[$keys[$i]]); - } - } - } - - /** - * @When I select the :path folder in the Universal Discovery Widget - */ - public function selectFromUniversalDiscovery($path) - { - // wait wihile UDW is hidden... - $this->waitWhileLoading('.is-universaldiscovery-hidden'); - $node = $this->findWithWait('.ez-view-universaldiscoveryview'); - $node = $this->findWithWait('.ez-view-universaldiscoverybrowseview .ez-ud-browse-tree', $node); - $this->openTreePath($path, $node); - } - - /** - * @When I confirm the selection - * Confirm selection in Universal descovery. - */ - public function confirmSelection() - { - $this->clickElementByText('Confirm selection', '.ez-universaldiscovery-confirm'); - } - - /** - * @Given I am on :name full view - */ - public function onFullView($name) - { - $path = $this->getBasicContentManager()->getContentPath($name); - $this->goToContentWithPath($path); - } - - /** - * Opens a content in PlatformUi. - */ - private function goToContentWithPath($path) - { - $this->clickNavigationZone('Content'); - $this->clickNavigationItem('Content structure'); - $this->clickOnTreePath($path); - } - - /** - * @Then I am on the :name location view - */ - public function onLocationView($name) - { - // little info about content in platformUI, - // for now only verifies if the title matches - $this->waitWhileLoading(); - $this->iSeeTitle($name); - } - - /** - * @Then I don't see :path in the content tree - * @Then I do not see :path in the content tree - * Explores the content tree, expanding it and click on the desired element. - * - * @param string $path The content tree path such as 'Content1/Content2/ContentIWantToClick' - */ - public function dontSeeTreePath($path) - { - $found = true; - try { - $this->clickOnTreePath($path); - } catch (\Exception $e) { - $found = false; - } - - if ($found) { - throw new \Exception("Tree path '$path' was found"); - } - - return true; - } - - /** - * @Then I see Content :contentName of type :contentType - */ - public function contentExists($contentName, $contentType) - { - $contentId = $this->getLocationId(); - $content = $this->getContentManager()->loadContentWithLocationId($contentId); - $contentInfo = $content->contentInfo; - $contentTypeName = $this->getContentManager()->getContentType($content); - Assertion::assertEquals($contentName, $contentInfo->name, 'Content has wrong name'); - Assertion::assertEquals($contentType, $contentTypeName, 'Content has wrong type'); - } - - /** - * @Then I am notified that :message - */ - public function iSeeNotification($message) - { - $this->sleep(); - $result = $this->getElementByText($message, '.ez-notification-text'); - if (!$result) { - throw new \Exception("The notification with message '$message' was not shown"); - } - } - - /** - * @Then I am not notified that :message - */ - public function iDoNotSeeNotification($message) - { - try { - $this->iSeeNotification($message); - } catch (\Exception $e) { - return; - } - throw new \Exception("Unexpected notification shown with message '$message'"); - } - - /** - * @Then I should see elements with the following names: - */ - public function iSeeElements(TableNode $elements) - { - foreach ($elements as $element) { - $found = false; - $name = array_values($element)[0]; - $found = $this->getElementByText($name, '.ez-selection-filter-item'); - Assertion::assertNotNull($found, "Element: $name not found"); - } - } - - /** - * @Then I should see (an) element :element with (an) file :file - */ - public function iSeeElementFile($element, $file) - { - $url = $this->getFileUrl($element, '.ez-fieldview-label'); - $fileContentActual = file_get_contents($url); - $file = rtrim( - realpath($this->getMinkParameter('files_path')), - DIRECTORY_SEPARATOR - ) . DIRECTORY_SEPARATOR . $file; - $fileContentExpected = file_get_contents($file); - Assertion::assertEquals($fileContentActual, $fileContentExpected); - } - - /** - * @Then /^I should be on the dashboard$/ - */ - public function iShouldBeOnTheDashboard() - { - $this->assertSession()->elementExists('css', '.ez-view-dashboardview'); - } - - /** - * @Given /^I am redirected to a location view$/ - */ - public function iHaveBeenRedirectedToALocationView() - { - $this->assertSession()->elementExists('css', '.ez-mainviews .ez-view-locationviewview'); - } -} diff --git a/Features/Context/SubContext/ContentEditContext.php b/Features/Context/SubContext/ContentEditContext.php new file mode 100644 index 000000000..b4fffa5a2 --- /dev/null +++ b/Features/Context/SubContext/ContentEditContext.php @@ -0,0 +1,105 @@ +dashboardContext->clickNavigationZone('Platform'); + $this->dashboardContext->clickLink('Content structure'); + $this->dashboardContext->clickActionBar('Create a content'); + $this->dashboardContext->clickContentType($type); + foreach ($fields as $fieldArray) { + $keys = array_keys($fieldArray); + for ($i = 0; $i < count($keys); ++$i) { + $this->browserContext->fillFieldWithValue($keys[$i], $fieldArray[$keys[$i]]); + } + } + } + + /** + * @Given I am on :name full view + */ + public function onFullView($name) + { + $path = $this->basicContentContext->getContentPath($name); + $this->goToContentWithPath($path); + } + + /** + * Opens a content in PlatformUi. + */ + private function goToContentWithPath($path) + { + $this->dashboardContext->clickNavigationZone('Content'); + $this->dashboardContext->clickNavigationItem('Content structure'); + $this->waitWhileLoading(); + $this->dashboardContext->clickOnTreePath($path); + } + + /** + * @Then I am on the :name location view + */ + public function onLocationView($name) + { + // little info about content in platformUI, + // for now only verifies if the title matches + $this->waitWhileLoading(); + $this->browserContext->iSeeTitle($name); + } + + /** + * @Then I see Content :contentName of type :contentType + */ + public function contentExists($contentName, $contentType) + { + $contentId = $this->getLocationId(); + $content = $this->getContentManager()->loadContentWithLocationId($contentId); + $contentInfo = $content->contentInfo; + $contentTypeName = $this->getContentManager()->getContentType($content); + Assertion::assertEquals($contentName, $contentInfo->name, 'Content has wrong name'); + Assertion::assertEquals($contentType, $contentTypeName, 'Content has wrong type'); + } + + /** + * @Then I should see elements with the following names: + */ + public function iSeeElements(TableNode $elements) + { + foreach ($elements as $element) { + $found = false; + $name = array_values($element)[0]; + $found = $this->getElementByText($name, '.ez-selection-filter-item'); + Assertion::assertNotNull($found, "Element: $name not found"); + } + } +} diff --git a/Features/Context/SubContext/DashboardContext.php b/Features/Context/SubContext/DashboardContext.php new file mode 100644 index 000000000..a91650b93 --- /dev/null +++ b/Features/Context/SubContext/DashboardContext.php @@ -0,0 +1,201 @@ +getSession()->getPage(); + $selector = '.ez-logo a'; + $page->find('css', $selector)->click(); + } + + /** + * @Given I click (on) the navigation zone :zone + * Click on a PlatformUI menu zone. + * + * @param string $zone Text of the element to click + */ + public function clickNavigationZone($zone) + { + $this->clickElementByText($zone, '.ez-zone-name'); + $this->waitWhileLoading(); + // Clicking navigation zone triggers load of first item, + // we must wait before interacting with the page (see EZP-25128) + // this method sleeps for a default amount (see EzSystems\PlatformUIBundle\Features\Context\PlaformUI) + $this->sleep(); + } + + /** + * @Given I click (on) the navigation item :item + * Click on a PlatformUI sub-menu option. + * + * @param string $item Text of the element to click + */ + public function clickNavigationItem($item) + { + $this->clickElementByText($item, '.ez-navigation-item'); + $this->waitWhileLoading(); + } + + /** + * @Given I click (on) the discovery bar button :button + * Click on a PlatformUI discovery bar. + * + * @param string $button Text of the element to click + */ + public function clickDiscoveryBar($button) + { + $this->clickElementByText($button, '.ez-view-discoverybarview .ez-action', '.action-label'); + $this->waitWhileLoading(); + } + + /** + * @Given I click (on) the action bar button :button + * Click on a PlatformUI action bar. + * + * @param string $button Text of the element to click + */ + public function clickActionBar($button) + { + $this->clickElementByText($button, '.ez-actionbar-container .ez-action', '.action-label'); + $this->waitWhileLoading(); + } + + /** + * @Given I click (on) the edit action bar button :button + * Click on a PlatformUI edit action bar. + * + * @param string $button Text of the element to click + */ + public function clickEditActionBar($button) + { + $this->clickElementByText($button, '.ez-editactionbar-container .ez-action', '.action-label'); + $this->waitWhileLoading(); + } + + /** + * @Given I click (on) the content tree with path :path + * @Then I see :path in the content tree + * Explores the content tree, expanding it and click on the desired element. + * + * @param string $path The content tree path such as 'Content1/Content2/ContentIWantToClick' + */ + public function clickOnTreePath($path) + { + $node = $this->findWithWait('.ez-view-discoverybarview'); + $this->clickDiscoveryBar('Content tree'); + $this->openTreePath($path, $node); + } + + /** + * @Given I click (on) the content type :contentType + * Click on a PlatformUI side menu content type. + * + * @param string $contentType Text of the element to click + */ + public function clickContentType($contentType) + { + $this->clickElementByText($contentType, '.ez-contenttypeselector-types .ez-selection-filter-item '); + $this->waitWhileLoading(); + } + + /** + * @Then I don't see :path in the content tree + * @Then I do not see :path in the content tree + * Explores the content tree, expanding it and click on the desired element. + * + * @param string $path The content tree path such as 'Content1/Content2/ContentIWantToClick' + */ + public function dontSeeTreePath($path) + { + $found = true; + try { + $this->clickOnTreePath($path); + } catch (\Exception $e) { + $found = false; + } + + if ($found) { + throw new \Exception("Tree path '$path' was found"); + } + + return true; + } + + /** + * @When I select the :path folder in the Universal Discovery Widget + */ + public function selectFromUniversalDiscovery($path) + { + // wait wihile UDW is hidden... + $this->waitWhileLoading('.is-universaldiscovery-hidden'); + $node = $this->findWithWait('.ez-view-universaldiscoveryview'); + $node = $this->findWithWait('.ez-view-universaldiscoverybrowseview .ez-ud-browse-tree', $node); + $this->openTreePath($path, $node); + } + + /** + * @When I confirm the selection + * Confirm selection in Universal descovery. + */ + public function confirmSelection() + { + $this->clickElementByText('Confirm selection', '.ez-universaldiscovery-confirm'); + } + + /** + * @Then I am notified that :message + */ + public function iSeeNotification($message) + { + $this->sleep(); + $result = $this->getElementByText($message, '.ez-notification-text'); + if (!$result) { + throw new \Exception("The notification with message '$message' was not shown"); + } + } + + /** + * @Then I am not notified that :message + */ + public function iDoNotSeeNotification($message) + { + try { + $this->iSeeNotification($message); + } catch (\Exception $e) { + return; + } + throw new \Exception("Unexpected notification shown with message '$message'"); + } + + /** + * @Then I should be on the dashboard + */ + public function iShouldBeOnTheDashboard() + { + $this->assertSession()->elementExists('css', '.ez-view-dashboardview'); + } + + /** + * @Given I am redirected to a location view + */ + public function iHaveBeenRedirectedToALocationView() + { + $this->assertSession()->elementExists('css', '.ez-mainviews .ez-view-locationviewview'); + } +} diff --git a/Features/Context/Users.php b/Features/Context/Users.php index e82b0d420..7518f8103 100644 --- a/Features/Context/Users.php +++ b/Features/Context/Users.php @@ -13,24 +13,46 @@ class Users extends PlatformUI { + /** + * @var EzSystems\PlatformUIBundle\Features\Context\SubContext\DashboardContext + */ + protected $dashboardContext; + + /** + * @var EzSystems\PlatformUIBundle\Features\Context\SubContext\BrowserContext + */ + protected $browserContext; + + /** + * @Given I am on the Users page + */ + public function onUsersPage() + { + $this->getSession()->visit( + $this->locatePath( + self::PLATFORM_URI . '#/view/%2Fapi%2Fezp%2Fv2%2Fcontent%2Flocations%2F1%2F5/eng-GB' + ) + ); + } + /** * @When I create a new User * @When I fill a new User fields with: */ public function iCreateUser(TableNode $users = null) { - $this->clickActionBar('Create'); + $this->dashboardContext->clickActionBar('Create'); $this->waitWhileLoading('.ez-contenttypes-loading'); - $this->checkOption('Users'); - $this->clickContentType('User'); + $this->browserContext->checkOption('Users'); + $this->dashboardContext->clickContentType('User'); if ($users) { foreach ($users as $user) { - $this->fillFieldWithValue('First name', $user['First name']); - $this->fillFieldWithValue('Last name', $user['Last name']); - $this->fillFieldWithValue('Login', $user['Login']); - $this->fillFieldWithValue('Email', $user['Email']); - $this->fillFieldWithValue('Password', $user['Password']); - $this->fillFieldWithValue('Confirm password', $user['Password']); + $this->browserContext->fillFieldWithValue('First name', $user['First name']); + $this->browserContext->fillFieldWithValue('Last name', $user['Last name']); + $this->browserContext->fillFieldWithValue('Login', $user['Login']); + $this->browserContext->fillFieldWithValue('Email', $user['Email']); + $this->browserContext->fillFieldWithValue('Password', $user['Password']); + $this->browserContext->fillFieldWithValue('Confirm password', $user['Password']); } } } @@ -40,10 +62,10 @@ public function iCreateUser(TableNode $users = null) */ public function editUserUser($username) { - $this->clickOnTreePath("$username $username"); + $this->dashboardContext->clickOnTreePath("$username $username"); $this->sleep(); //safegaurd for application delays $this->waitWhileLoading(); - $this->clickActionBar('Edit'); + $this->dashboardContext->clickActionBar('Edit'); } /** @@ -52,7 +74,7 @@ public function editUserUser($username) public function iSeeUsersPage() { $this->sleep(); // safegaurd for application delays - $this->iSeeTitle('Users'); + $this->browserContext->iSeeTitle('Users'); } /** diff --git a/behat_suites.yml b/behat_suites.yml index 7107ff056..82ad1e6f1 100644 --- a/behat_suites.yml +++ b/behat_suites.yml @@ -3,20 +3,44 @@ platformui: # basic platform suite: login, logout, etc standard: paths: [ vendor/ezsystems/platform-ui-bundle/Features/Standard ] - contexts: [ EzSystems\PlatformUIBundle\Features\Context\PlatformUI ] + contexts: + - EzSystems\PlatformUIBundle\Features\Context\SubContext\BrowserContext + - EzSystems\PlatformUIBundle\Features\Context\SubContext\Authentication + - EzSystems\PlatformUIBundle\Features\Context\SubContext\DashboardContext # content operations: CRUD, navigation, moving contentactions: paths: [ vendor/ezsystems/platform-ui-bundle/Features/ContentActions ] - contexts: [ EzSystems\PlatformUIBundle\Features\Context\ContentActions ] + contexts: + - eZ\Bundle\EzPublishCoreBundle\Features\Context\BasicContentContext + - EzSystems\PlatformUIBundle\Features\Context\SubContext\BrowserContext + - EzSystems\PlatformUIBundle\Features\Context\SubContext\Authentication + - EzSystems\PlatformUIBundle\Features\Context\SubContext\DashboardContext + - EzSystems\PlatformUIBundle\Features\Context\SubContext\ContentEditContext + - EzSystems\PlatformUIBundle\Features\Context\ContentActions # role features role: paths: [ vendor/ezsystems/platform-ui-bundle/Features/RoleUI ] - contexts: [ EzSystems\PlatformUIBundle\Features\Context\Role ] + contexts: + - eZ\Bundle\EzPublishCoreBundle\Features\Context\RoleContext + - EzSystems\PlatformUIBundle\Features\Context\SubContext\BrowserContext + - EzSystems\PlatformUIBundle\Features\Context\SubContext\Authentication + - EzSystems\PlatformUIBundle\Features\Context\SubContext\DashboardContext + - EzSystems\PlatformUIBundle\Features\Context\Role # fieldtype specific tests - definition, validation, publishing, etc fieldtype_integer: paths: [ vendor/ezsystems/platform-ui-bundle/Features/Stories/FieldTypes/IntegerFieldType.feature ] - contexts: [ EzSystems\PlatformUIBundle\Features\Context\Fields ] + contexts: + - eZ\Bundle\EzPublishCoreBundle\Features\Context\FieldTypeContext + - EzSystems\PlatformUIBundle\Features\Context\SubContext\BrowserContext + - EzSystems\PlatformUIBundle\Features\Context\SubContext\Authentication + - EzSystems\PlatformUIBundle\Features\Context\SubContext\DashboardContext + - EzSystems\PlatformUIBundle\Features\Context\Fields # user features user: paths: [ vendor/ezsystems/platform-ui-bundle/Features/Users/users.feature ] - contexts: [ EzSystems\PlatformUIBundle\Features\Context\Users ] + contexts: + - eZ\Bundle\EzPublishCoreBundle\Features\Context\UserContext + - EzSystems\PlatformUIBundle\Features\Context\SubContext\BrowserContext + - EzSystems\PlatformUIBundle\Features\Context\SubContext\Authentication + - EzSystems\PlatformUIBundle\Features\Context\SubContext\DashboardContext + - EzSystems\PlatformUIBundle\Features\Context\Users