/ */ namespace BehatTests; use Behat\Behat\Context\Step; class ProjectContext extends AbstractContext { const ELEMENT_PROJECT_NAME = 'name'; const ELEMENT_PROJECT_MEMBERS = 'members'; const ELEMENT_ADD_PROJECT_BUTTON_CSS = '.project-add a'; const ELEMENT_SAVE_PROJECT_BUTTON = ".btn-primary[type='submit']"; const ELEMENT_DONE_CSS = '.controls .branch-button .open .close-branch-btn'; const ELEMENT_DESCRIPTION_CSS = '.project-sidebar .description .first-line'; const ELEMENT_METRIC_MEMBERS_CSS = '.project-sidebar .metrics .members .count'; const ELEMENT_METRIC_BRANCHES_CSS = '.project-sidebar .metrics .branches .count'; const ELEMENT_DROPDOWN_CSS = '.control-group-members ul.dropdown-menu'; const ELEMENT_ADD_BRANCH_CSS = '.control-group.branches a'; const ELEMENT_PROJECT_MEMBER_CSS = '.project-sidebar .members img'; const ELEMENT_PROJECT_BRANCH_CSS = '.project-sidebar .branches a'; const ELEMENT_PROJECTS_SIDEBAR_ROW_CSS = '.projects-sidebar tbody tr'; // the number of branches that have been added to the current project (this is // needed because the branch element classes are dependant on the branch number) private $branchCount = 0; /** * Call after attempting to save a project and before further interaction with the UI to * ensure that the ajax call has completed. * The function will wait until one of two conditions is met: a new page has been opened, * or the Save button has been re-enabled. * * @param $seconds int max timeout required for the assertion * * @return bool true when we are no longer at the Add Project page, or * when the Save button is enabled * @throws \Exception when neither condition is met after max seconds */ public function waitUntilSavingRequestHasReturned($seconds = 5) { $button = $this->getMinkContext()->findElementByType(self::ELEMENT_SAVE_PROJECT_BUTTON, 'css'); $projectPage = $this->configParams['base_url'] . "/projects/add/"; $start = time(); do { try { if ($this->getSession()->getCurrentUrl() !== $projectPage || $button->hasAttribute("disabled") == false) { return true; } } catch (\Exception $e) { usleep(1000); // 1 ms sleep } } while ((time() - $start) < $seconds); // max 5 seconds throw new \Exception("Failed asserting that the Save button becomes enabled."); } /** * Clicks the project save button and waits for the project page to load * * @Given /^I click the "Save" button on the "Add Project" page$/ */ public function iClickTheSaveProjectButton() { $this->getMinkContext()->findElementByType(self::ELEMENT_SAVE_PROJECT_BUTTON, 'css')->click(); $this->waitUntilSavingRequestHasReturned(); } /** * @Then /^I should be redirected to "\/projects\/(?P[^"]*)"$/ */ public function iShouldBeRedirectedToProjectPage($page) { $actual = $this->getSession()->getCurrentUrl(); $base = $this->configParams['base_url'] . "/projects/"; $expected = $base . $page; $expectedEncoded = $base . urlencode($page); // Note: it is not enough to check against the encoded only, as getCurrentUrl() returns the // encoded url for the chrome and firefox drivers and the decoded url for the safari driver assertTrue($actual === $expected || $actual === $expectedEncoded); } /** * @Then /^The "Save" button should be (enabled|disabled)$/ */ public function theSaveButtonShouldBeEnabledOrDisabled($enabled) { $button = $this->getMinkContext()->findElementByType(self::ELEMENT_SAVE_PROJECT_BUTTON, 'css'); if ($enabled === "enabled") { assertEquals(false, $button->hasAttribute("disabled")); } else { assertEquals(true, $button->hasAttribute("disabled")); } } /** * @When /^I click the "Add Project" button$/ */ public function iClickTheAddProjectButton() { $this->getMinkContext()->findElementByType(self::ELEMENT_ADD_PROJECT_BUTTON_CSS, 'css')->click(); } /** * @When /^I am on a newly opened "Add Project" page$/ */ public function iAmOnANewlyOpenedAddProjectPage() { $this->getSession()->visit($this->configParams['base_url']."/projects/add/"); } /** * @Then /^I should be redirected to the "Add Project" page$/ */ public function iShouldBeRedirectedToTheAddProjectPage() { $this->getMinkContext()->waitUntilPageUrlLoads($this->configParams['base_url'] . "/projects/add/", 5); } /** * @When /^I add the member "([^"]*)" to the project$/ */ public function iAddTheMemberToTheProject($member) { $this->iEnterInputInTheMembersField($member); $this->iClickOnUserInDropdownList($member); } /** * @When /^I click on user "([^"]*)" in the dropdown list$/ */ public function iClickOnUserInDropdownList($userName) { $elementCss = self::ELEMENT_DROPDOWN_CSS . " li[data-value^=\"$userName\"]"; $this->getMinkContext()->assertElementOnPage($elementCss); $this->getMinkContext()->findElementByType($elementCss, 'css')->click(); } /** * @Then /^I should see an error "([^"]*)"$/ */ public function iShouldSeeAnError($error) { return new Step\Then("I should see \"$error\""); } /** * @Given /^I have created a project named "(?P[^"]*)"$/ * @Given /^I have created a project named "(?P[^"]*)" with member "(?P[^"]*)"&/ */ public function iHaveCreatedAProject($projectName, $projectMember = "swarm-admin") { return array( new Step\When("I am on a newly opened \"Add Project\" page"), new Step\When("I enter \"$projectName\" in the \"Name\" field"), new Step\When("I add the member \"$projectMember\" to the project"), new Step\When("I click the \"Save\" button on the \"Add Project\" page") ); } /** * @When /^I enter a valid name and project member$/ */ public function iEnterAValidNameAndMember() { return array( new Step\When("I enter \"SampleProject\" in the \"Name\" field"), new Step\When("I add the member \"swarm-admin\" to the project") ); } /** * @When /^I click the "Add Branch" button$/ */ public function iClickTheAddBranchButton() { $this->getMinkContext()->findElementByType(self::ELEMENT_ADD_BRANCH_CSS, 'css')->click(); } /** * @When /^I add a branch with name "([^"]*)" and mapping "([^"]*)"$/ */ public function iAddABranchWithNameAndMapping($name, $mapping) { $nameId = "branch-name-" . $this->branchCount; $pathsId = "branch-paths-" . $this->branchCount; $this->branchCount++; $this->iClickTheAddBranchButton(); $this->getMinkContext()->fillField($nameId, $name); $this->getMinkContext()->fillField($pathsId, $mapping); $this->iClickDoneButton(); } /** * @Then /^I should see the project "([^"]*)" listed under "Projects"$/ */ public function iShouldSeeTheProjectListedUnder($projectName) { $this->getMinkContext()->waitUntilPageElementLoads(self::ELEMENT_PROJECTS_SIDEBAR_ROW_CSS, "css"); $pageName = urlencode(strtolower($projectName)); $projectCss = self::ELEMENT_PROJECTS_SIDEBAR_ROW_CSS . ".project a.name[href='/projects/" . $pageName . "']"; return new Step\Then("I should see an \"$projectCss\" element"); } /** * @Then /^I should see the user list "([^"]*)"$/ */ public function iShouldSeeTheUserList($usersList) { $usersArray = explode(", ", $usersList); // check that drop-down list is visible $dropdownCss = self::ELEMENT_DROPDOWN_CSS . ":not([display='none'])"; $this->getMinkContext()->assertElementOnPage($dropdownCss); // check that the drop-down contains each of the names in usersList foreach ($usersArray as $user) { $userCss = self::ELEMENT_DROPDOWN_CSS . " li[data-value^='$user']"; $this->getMinkContext()->assertElementOnPage($userCss); } } /** * @Then /^I should see "([^"]*)", "([\d]+) Members", "([\d]+) Branches" under the "About" section$/ */ public function iShouldSeeMetricsUnderTheAboutSection($description, $members, $branches) { return array( new Step\Then("I should see \"$description\" in the \"" . self::ELEMENT_DESCRIPTION_CSS . "\" element"), new Step\Then("I should see \"$members\" in the \"" . self::ELEMENT_METRIC_MEMBERS_CSS . "\" element"), new Step\Then("I should see \"$branches\" in the \"" . self::ELEMENT_METRIC_BRANCHES_CSS . "\" element") ); } /** * @Then /^I should see (users|branches) "(?P[^"]*)" under "(?P
members|branches)"$/ */ public function iShouldSeeListUnderSection($list, $section) { $entriesArray = explode(", ", $list); foreach ($entriesArray as $entry) { if ($section === "members") { $this->getMinkContext()->assertElementOnPage(self::ELEMENT_PROJECT_MEMBER_CSS . "[data-user='$entry']"); } else { $this->getMinkContext()->assertElementOnPage(self::ELEMENT_PROJECT_BRANCH_CSS . ":contains('$entry')"); } } } /** * @When /^I click on the "x" next to "([^"]*)"$/ */ public function iClickOnTheXNextToName($userName) { // Click away from the drop-down picker to ensure it is closed. This is needed // because the chrome driver can't click a button if it is obscured by something else. $this->getMinkContext()->findElementByType("i.icon-user")->click(); $removeButtonCss = ".multipicker-item[data-value^='$userName'] button.item-remove"; $this->getMinkContext()->assertElementOnPage($removeButtonCss); $this->getMinkContext()->findElementByType($removeButtonCss, 'css')->click(); } /** * @Given /^The list of users on the server includes "([^"]*)"$/ */ public function theListOfUsersOnTheServerIncludes($userList) { $usernameArray = explode(", ", $userList); foreach ($usernameArray as $username) { $this->getP4Context()->createRegularUser($username); $this->getP4Context()->instantiateWorker(); } } /** * @When /^I click "Done" on the "Add Branch" window$/ */ public function iClickDoneButton() { $this->getMinkContext()->findElementByType(self::ELEMENT_DONE_CSS, 'css')->click(); } /** * @When /^I enter "(?P[^"]*)" in the "Name" field$/ */ public function iEnterInputInTheNameField($input) { $this->getMinkContext()->fillField(self::ELEMENT_PROJECT_NAME, $input); } /** * @When /^I enter "(?P[^"]*)" in the "Members" field$/ */ public function iEnterInputInTheMembersField($input) { // wait until input is enabled $membersCss = "input#members:not([disabled])"; $this->getMinkContext()->waitUntilPageElementLoads($membersCss); $this->getMinkContext()->fillField(self::ELEMENT_PROJECT_MEMBERS, $input); } /** * @Given /^I create a project "(?P[^"]*)" with mapping "(?P[^"]*)"$/ */ public function iCreateAProjectWithMapping($projectName, $projectMapping) { $this->iAmOnANewlyOpenedAddProjectPage(); $this->iEnterInputInTheNameField($projectName); $this->iAddTheMemberToTheProject("swarm-admin"); $this->iAddABranchWithNameAndMapping("Jam", $projectMapping); $this->iClickTheSaveProjectButton(); } /** * @Then /^I should see the "(?P[^"]*)" project header$/ */ public function iShouldSeeTheProjectHeader($projectName) { $this->getMinkContext()->assertElementOnPage(".project-navbar .brand:contains('$projectName')"); } }