From: Grégoire Aubert Date: Mon, 20 Nov 2017 11:36:09 +0000 (+0100) Subject: Update users permission IT's X-Git-Tag: 7.0-RC1~280 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ad4567f4361fa1843cd57dc614e0ed0c653c86d2;p=sonarqube.git Update users permission IT's --- diff --git a/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/Navigation.java b/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/Navigation.java index 25fc6937c8e..996f46d3557 100644 --- a/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/Navigation.java +++ b/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/Navigation.java @@ -178,6 +178,10 @@ public class Navigation { return open("/account/notifications", NotificationsPage.class); } + public UsersManagementPage openUsersManagement() { + return open("/admin/users", UsersManagementPage.class); + } + public ProjectPermissionsPage openProjectPermissions(String projectKey) { String url = "/project_roles?id=" + escape(projectKey); return open(url, ProjectPermissionsPage.class); diff --git a/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/UsersManagementItem.java b/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/UsersManagementItem.java new file mode 100644 index 00000000000..0cd63650f10 --- /dev/null +++ b/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/UsersManagementItem.java @@ -0,0 +1,98 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonarqube.qa.util.pageobjects; + +import com.codeborne.selenide.Condition; +import com.codeborne.selenide.SelenideElement; + +import static com.codeborne.selenide.Selenide.$; +import static com.codeborne.selenide.Selenide.$$; + +public class UsersManagementItem { + private final SelenideElement elt; + + public UsersManagementItem(SelenideElement elt) { + this.elt = elt; + } + + public UsersManagementItem hasTokensCount(Integer count) { + this.elt.$(".js-user-tokens").should(Condition.exist).parent().shouldHave(Condition.text(count.toString())); + return this; + } + + public UsersManagementItem generateToken(String name) { + this.openTokenModal(); + $(".modal #generate-token-form input").should(Condition.exist).sendKeys(name); + $(".modal #generate-token-form .js-generate-token").should(Condition.exist).click(); + $(".modal code").should(Condition.exist); + getTokenRow(name).should(Condition.exist); + closeModal(); + return this; + } + + public UsersManagementItem revokeToken(String name) { + this.openTokenModal(); + SelenideElement tokenRow = getTokenRow(name).should(Condition.exist); + tokenRow.$("button").should(Condition.exist).shouldHave(Condition.text("Revoke")).click(); + tokenRow.$("button").shouldHave(Condition.text("Sure?")).click(); + getTokenRow(name).shouldNot(Condition.exist); + closeModal(); + return this; + } + + public UsersManagementItem changePassword(String oldPwd, String newPwd) { + this.elt.$("button.dropdown-toggle").should(Condition.exist).click(); + this.elt.$(".js-user-change-password").shouldBe(Condition.visible).click(); + isModalOpen("Change password"); + $(".modal #old-user-password").should(Condition.exist).sendKeys(oldPwd); + $(".modal #user-password").should(Condition.exist).sendKeys(newPwd); + $(".modal #confirm-user-password").should(Condition.exist).sendKeys(newPwd); + $(".modal .js-confirm").click(); + $(".modal").shouldNot(Condition.exist); + return this; + } + + public UsersManagementItem deactivateUser() { + this.elt.$("button.dropdown-toggle").should(Condition.exist).click(); + this.elt.$(".js-user-deactivate").should(Condition.exist).click(); + isModalOpen("Deactivate User"); + $(".modal .js-confirm").should(Condition.exist).click(); + return this; + } + + private void openTokenModal() { + if (!$(".modal").exists()) { + this.elt.$(".js-user-tokens").should(Condition.exist).click(); + } + isModalOpen("Tokens"); + } + + private static void closeModal() { + $(".modal .js-modal-close").should(Condition.exist).click(); + } + + private static void isModalOpen(String title) { + $(".modal .modal-head").should(Condition.exist).shouldHave(Condition.text(title)); + } + + private static SelenideElement getTokenRow(String name) { + return $$(".modal tr").findBy(Condition.text(name)); + } +} diff --git a/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/UsersManagementPage.java b/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/UsersManagementPage.java new file mode 100644 index 00000000000..efc2edf913d --- /dev/null +++ b/server/sonar-qa-util/src/main/java/org/sonarqube/qa/util/pageobjects/UsersManagementPage.java @@ -0,0 +1,52 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonarqube.qa.util.pageobjects; + +import com.codeborne.selenide.Condition; +import com.codeborne.selenide.SelenideElement; + +import static com.codeborne.selenide.Selenide.$; +import static com.codeborne.selenide.Selenide.$$; + +public class UsersManagementPage { + public UsersManagementPage() { + $("#users-page").shouldBe(Condition.visible); + } + + public UsersManagementPage hasUsersCount(Integer count) { + $$(".js-user-login").shouldHaveSize(count); + return this; + } + + public UsersManagementItem getUser(String login) { + SelenideElement elt = $$(".js-user-login").findBy(Condition.text(login)).should(Condition.exist); + return new UsersManagementItem(elt.parent().parent().parent()); + } + + public UsersManagementPage createUser(String login) { + $("#users-create").should(Condition.exist).click(); + $(".modal .modal-head").should(Condition.exist).shouldHave(Condition.text("Create User")); + $(".modal #create-user-login").should(Condition.exist).sendKeys(login); + $(".modal #create-user-name").should(Condition.exist).sendKeys("Name of " + login); + $(".modal #create-user-password").should(Condition.exist).sendKeys(login); + $(".modal .js-confirm").should(Condition.exist).click(); + return this; + } +} diff --git a/tests/src/test/java/org/sonarqube/tests/user/RealmAuthenticationTest.java b/tests/src/test/java/org/sonarqube/tests/user/RealmAuthenticationTest.java index 686732cb340..a99d247263c 100644 --- a/tests/src/test/java/org/sonarqube/tests/user/RealmAuthenticationTest.java +++ b/tests/src/test/java/org/sonarqube/tests/user/RealmAuthenticationTest.java @@ -19,6 +19,7 @@ */ package org.sonarqube.tests.user; +import com.codeborne.selenide.Condition; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.sonar.orchestrator.Orchestrator; @@ -37,7 +38,9 @@ import org.sonar.wsclient.connectors.HttpClient4Connector; import org.sonar.wsclient.services.AuthenticationQuery; import org.sonar.wsclient.user.UserParameters; import org.sonarqube.qa.util.Tester; +import org.sonarqube.qa.util.pageobjects.Navigation; import org.sonarqube.qa.util.pageobjects.SystemInfoPage; +import org.sonarqube.qa.util.pageobjects.UsersManagementPage; import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.WsResponse; import org.sonarqube.ws.client.user.CreateRequest; @@ -233,7 +236,17 @@ public class RealmAuthenticationTest { // Given clean Sonar installation and no users in external system // Let's create and delete the user "tester" in Sonar DB - runSelenese(orchestrator, "/user/ExternalAuthenticationTest/create-and-delete-user.html"); + Navigation nav = tester.openBrowser(); + UsersManagementPage page = nav.logIn().submitCredentials(ADMIN_USER_LOGIN).openUsersManagement(); + page + .createUser(USER_LOGIN) + .hasUsersCount(3) + .getUser(USER_LOGIN) + .deactivateUser(); + page.hasUsersCount(2); + nav.logOut() + .logIn().submitWrongCredentials(USER_LOGIN, USER_LOGIN) + .getErrorMessage().shouldHave(Condition.text("Authentication failed")); // And now update the security with the user that was deleted String login = USER_LOGIN; diff --git a/tests/src/test/java/org/sonarqube/tests/user/UsersPageTest.java b/tests/src/test/java/org/sonarqube/tests/user/UsersPageTest.java index 38b62681a9c..2aa83ffae74 100644 --- a/tests/src/test/java/org/sonarqube/tests/user/UsersPageTest.java +++ b/tests/src/test/java/org/sonarqube/tests/user/UsersPageTest.java @@ -20,26 +20,27 @@ package org.sonarqube.tests.user; import com.sonar.orchestrator.Orchestrator; +import org.junit.After; +import org.sonarqube.ws.Users.CreateWsResponse.User; +import org.sonarqube.qa.util.Tester; +import org.sonarqube.qa.util.pageobjects.UsersManagementPage; import org.sonarqube.tests.Category1Suite; import java.util.List; -import org.junit.After; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.sonarqube.ws.Users; -import org.sonarqube.ws.client.WsClient; import org.sonarqube.ws.client.user.GroupsRequest; -import util.selenium.Selenese; import util.user.UserRule; + import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.assertj.core.api.Assertions.assertThat; -import static util.ItUtils.newAdminWsClient; public class UsersPageTest { - private static final String ADMIN_USER_LOGIN = "admin-user"; + private User adminUser; @ClassRule public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; @@ -47,38 +48,54 @@ public class UsersPageTest { @Rule public UserRule userRule = UserRule.from(orchestrator); - private WsClient adminClient = newAdminWsClient(orchestrator); + @Rule + public Tester tester = new Tester(orchestrator).disableOrganizations(); @Before - public void initAdminUser() throws Exception { - userRule.createAdminUser(ADMIN_USER_LOGIN, ADMIN_USER_LOGIN); + public void initUsers() throws Exception { + adminUser = tester.users().generateAdministrator(u -> u.setLogin("admin-user").setPassword("admin-user")); + tester.users().generate(u -> u.setLogin("random-user").setPassword("random-user")); } @After - public void deleteAdminUser() { + public void resetUsers() { userRule.resetUsers(); } @Test public void generate_and_revoke_user_token() { - Selenese.runSelenese(orchestrator, "/user/UsersPageTest/generate_and_revoke_user_token.html"); + UsersManagementPage page = tester.openBrowser().logIn().submitCredentials(adminUser.getLogin()).openUsersManagement(); + tester.wsClient().users().skipOnboardingTutorial(); + + page + .hasUsersCount(3) + .getUser(adminUser.getLogin()) + .hasTokensCount(0) + .generateToken("token-test") + .hasTokensCount(1) + .revokeToken("token-test") + .hasTokensCount(0); } @Test public void admin_should_change_his_own_password() { - Selenese.runSelenese(orchestrator, "/user/UsersPageTest/admin_should_change_its_own_password.html"); + UsersManagementPage page = tester.openBrowser().logIn().submitCredentials(adminUser.getLogin()).openUsersManagement(); + tester.wsClient().users().skipOnboardingTutorial(); + page + .hasUsersCount(3) + .getUser(adminUser.getLogin()) + .changePassword(adminUser.getLogin(), "newpassword"); } @Test public void return_groups_belonging_to_a_user() { String login = randomAlphabetic(10); String group = randomAlphabetic(10); - userRule.createUser(login, login); - userRule.createGroup(group); - userRule.associateGroupsToUser(login, group); - - List result = adminClient.users().groups(GroupsRequest.builder().setLogin(login).build()).getGroupsList(); + tester.users().generate(u -> u.setLogin(login).setPassword(login)); + tester.groups().generate(null, g -> g.setName(group)); + tester.groups().addMemberToGroups(tester.organizations().getDefaultOrganization(), login, group); + List result = tester.as(adminUser.getLogin()).wsClient().users().groups(GroupsRequest.builder().setLogin(login).build()).getGroupsList(); assertThat(result).extracting(Users.GroupsWsResponse.Group::getName).contains(group); } } diff --git a/tests/src/test/resources/user/ExternalAuthenticationTest/create-and-delete-user.html b/tests/src/test/resources/user/ExternalAuthenticationTest/create-and-delete-user.html deleted file mode 100644 index 9be06a9320a..00000000000 --- a/tests/src/test/resources/user/ExternalAuthenticationTest/create-and-delete-user.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - create-and-delete-users - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
create-and-delete-users
open/sessions/new
typeloginadmin-user
typepasswordadmin-user
clickAndWaitcommit
waitForElementPresentcss=.js-user-authenticated
open/users
storejavascript{new Date().getTime()}userId
waitForTextcontent*Create User*
clickid=users-create
waitForTextid=create-user-form*Create User*
typeid=create-user-login${userId}
typeid=create-user-nameName of ${userId}
typeid=create-user-passwordpassword
clickid=create-user-submit
waitForTextid=users-list*${userId}*
clickcss=[data-login="${userId}"] .dropdown-toggle
clickcss=[data-login="${userId}"] .js-user-deactivate
waitForTextid=deactivate-user-form*${userId}*
clickid=deactivate-user-submit
waitForNotTextid=users-list*${userId}*
open/sessions/logout
open/sessions/new
typelogintester
typepasswordpassword
clickAndWaitcommitdeactivate-user-form
waitForTextlogin_form*Authentication failed*
- - diff --git a/tests/src/test/resources/user/UsersPageTest/admin_should_change_its_own_password.html b/tests/src/test/resources/user/UsersPageTest/admin_should_change_its_own_password.html deleted file mode 100644 index 228686fcd62..00000000000 --- a/tests/src/test/resources/user/UsersPageTest/admin_should_change_its_own_password.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - admin_should_change_its_own_password - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
admin_should_change_its_own_password
open/sessions/login
typeloginadmin-user
typepasswordadmin-user
clickAndWaitcommit
waitForElementPresentcss=.js-user-authenticated
open/users
waitForElementPresentcss=[data-login=admin-user]
clickcss=[data-login=admin-user] .dropdown-toggle
clickcss=[data-login=admin-user] .js-user-change-password
waitForElementPresentcss=.modal
typeid=change-user-password-old-passwordadmin-user
typeid=change-user-password-passwordnew-admin-user
typeid=change-user-password-password-confirmationnew-admin-user
clickid=change-user-password-submit
assertElementNotPresentcss=.modal
- - diff --git a/tests/src/test/resources/user/UsersPageTest/generate_and_revoke_user_token.html b/tests/src/test/resources/user/UsersPageTest/generate_and_revoke_user_token.html deleted file mode 100644 index 1c816cbd3d7..00000000000 --- a/tests/src/test/resources/user/UsersPageTest/generate_and_revoke_user_token.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - generate_and_revoke_user_token - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
generate_and_revoke_user_token
open/sessions/new
typeloginadmin-user
typepasswordadmin-user
clickAndWaitcommit
waitForElementPresentcss=.js-user-authenticated
open/users
waitForElementPresentcss=.js-user-tokens
clickcss=.js-user-tokens
waitForTextcss=.modal*No tokens*
waitForElementPresentcss=.js-generate-token-form input
typecss=.js-generate-token-form inputtest-token
clickcss=.js-generate-token-form button
waitForElementPresentcss=.modal code
waitForTextcss=.modal*test-token*
waitForElementPresentcss=.js-revoke-token-form
clickcss=.js-revoke-token-form button
clickcss=.js-revoke-token-form button
assertElementNotPresentcss=.js-revoke-token-form
- -