From 83a3500ccf26f5920c976fab13e0f00a3bf56ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Zeidler?= Date: Tue, 19 Mar 2024 12:20:00 +0100 Subject: [PATCH] Attributes without a group should appear first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the login theme, user profile attributes that are not assigned to an attribute group should appear before all other attributes. This aligns the login theme (registration, verify profile, etc.) with the account and admin console. Fixes #27981 Signed-off-by: René Zeidler --- .../model/AbstractUserProfileBean.java | 2 +- ...ctionUpdateProfileWithUserProfileTest.java | 18 ++++++------ .../broker/KcOidcFirstBrokerLoginTest.java | 18 ++++++------ .../forms/RegisterWithUserProfileTest.java | 28 +++++++++---------- .../testsuite/forms/VerifyProfileTest.java | 18 ++++++------ 5 files changed, 42 insertions(+), 42 deletions(-) diff --git a/services/src/main/java/org/keycloak/forms/login/freemarker/model/AbstractUserProfileBean.java b/services/src/main/java/org/keycloak/forms/login/freemarker/model/AbstractUserProfileBean.java index b055e198cd1..fdab733435d 100644 --- a/services/src/main/java/org/keycloak/forms/login/freemarker/model/AbstractUserProfileBean.java +++ b/services/src/main/java/org/keycloak/forms/login/freemarker/model/AbstractUserProfileBean.java @@ -42,7 +42,7 @@ public abstract class AbstractUserProfileBean { return a1.compareTo(a2); } - return Comparator.nullsLast(AttributeGroup::compareTo).compare(g1, g2); + return Comparator.nullsFirst(AttributeGroup::compareTo).compare(g1, g2); }; protected final MultivaluedMap formData; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileWithUserProfileTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileWithUserProfileTest.java index 2364a65dc13..7ba2f0a3494 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileWithUserProfileTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/actions/RequiredActionUpdateProfileWithUserProfileTest.java @@ -174,45 +174,45 @@ public class RequiredActionUpdateProfileWithUserProfileTest extends AbstractTest updateProfilePage.assertCurrent(); String htmlFormId="kc-update-profile-form"; - //assert fields and groups location in form, attributes without a group are the last + //assert fields and groups location in form, attributes without a group appear first Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(1) > label#header-company") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(2) > input#lastName") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(2) > label#description-company") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(2) > div:nth-child(2) > input#username") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(2) > div:nth-child(2) > input#department") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(3) > div:nth-child(2) > input#firstName") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(3) > div:nth-child(1) > label#header-contact") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(1) > label#header-company") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(2) > input#email") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(2) > label#description-company") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(5) > div:nth-child(2) > input#lastName") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(5) > div:nth-child(2) > input#department") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(6) > div:nth-child(2) > input#username") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(6) > div:nth-child(1) > label#header-contact") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(7) > div:nth-child(2) > input#firstName") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(7) > div:nth-child(2) > input#email") ).isDisplayed() ); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcFirstBrokerLoginTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcFirstBrokerLoginTest.java index b265b0b2f56..f666eee26ce 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcFirstBrokerLoginTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcFirstBrokerLoginTest.java @@ -407,45 +407,45 @@ public class KcOidcFirstBrokerLoginTest extends AbstractFirstBrokerLoginTest { //assert fields location in form String htmlFormId = "kc-idp-review-profile-form"; - //assert fields and groups location in form, attributes without a group are the last + //assert fields and groups location in form, attributes without a group appear first org.junit.Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(1) > label#header-company") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(2) > input#lastName") ).isDisplayed() ); org.junit.Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(2) > label#description-company") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(2) > div:nth-child(2) > input#username") ).isDisplayed() ); org.junit.Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(2) > div:nth-child(2) > input#department") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(3) > div:nth-child(2) > input#firstName") ).isDisplayed() ); org.junit.Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(3) > div:nth-child(1) > label#header-contact") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(1) > label#header-company") ).isDisplayed() ); org.junit.Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(2) > input#email") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(2) > label#description-company") ).isDisplayed() ); org.junit.Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(5) > div:nth-child(2) > input#lastName") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(5) > div:nth-child(2) > input#department") ).isDisplayed() ); org.junit.Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(6) > div:nth-child(2) > input#username") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(6) > div:nth-child(1) > label#header-contact") ).isDisplayed() ); org.junit.Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(7) > div:nth-child(2) > input#firstName") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(7) > div:nth-child(2) > input#email") ).isDisplayed() ); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/RegisterWithUserProfileTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/RegisterWithUserProfileTest.java index d0c4a84954e..8d8ccd88579 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/RegisterWithUserProfileTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/RegisterWithUserProfileTest.java @@ -442,46 +442,46 @@ public class RegisterWithUserProfileTest extends AbstractTestRealmKeycloakTest { registerPage.assertCurrent(); String htmlFormId="kc-register-form"; - //assert fields and groups location in form, attributes without a group are the last + //assert fields and groups location in form, attributes without a group appear first Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(1) > label#header-company") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(2) > input#lastName") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(2) > label#description-company") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(2) > div:nth-child(2) > input#username") + ).isDisplayed() + ); + // password and password confirmation fields appear after the username field, in positions 3 and 4 + Assert.assertTrue( + driver.findElement( + By.cssSelector("form#"+htmlFormId+" > div:nth-child(5) > div:nth-child(2) > input#firstName") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(2) > div:nth-child(2) > input#department") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(6) > div:nth-child(1) > label#header-company") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(3) > div:nth-child(1) > label#header-contact") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(6) > div:nth-child(2) > label#description-company") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(2) > input#email") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(7) > div:nth-child(2) > input#department") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(5) > div:nth-child(2) > input#lastName") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(8) > div:nth-child(1) > label#header-contact") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(6) > div:nth-child(2) > input#username") - ).isDisplayed() - ); - // firstname order is after username, so it will render after password and password confirmation fields - Assert.assertTrue( - driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(9) > div:nth-child(2) > input#firstName") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(9) > div:nth-child(2) > input#email") ).isDisplayed() ); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/VerifyProfileTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/VerifyProfileTest.java index e99342b9a20..5c60803e265 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/VerifyProfileTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/VerifyProfileTest.java @@ -220,45 +220,45 @@ public class VerifyProfileTest extends AbstractTestRealmKeycloakTest { verifyProfilePage.assertCurrent(); String htmlFormId="kc-update-profile-form"; - //assert fields and groups location in form, attributes without a group are the last + //assert fields and groups location in form, attributes without a group appear first Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(1) > label#header-company") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(2) > input#lastName") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(1) > div:nth-child(2) > label#description-company") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(2) > div:nth-child(2) > input#username") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(2) > div:nth-child(2) > input#department") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(3) > div:nth-child(2) > input#firstName") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(3) > div:nth-child(1) > label#header-contact") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(1) > label#header-company") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(2) > input#email") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(4) > div:nth-child(2) > label#description-company") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(5) > div:nth-child(2) > input#lastName") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(5) > div:nth-child(2) > input#department") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(6) > div:nth-child(2) > input#username") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(6) > div:nth-child(1) > label#header-contact") ).isDisplayed() ); Assert.assertTrue( driver.findElement( - By.cssSelector("form#"+htmlFormId+" > div:nth-child(7) > div:nth-child(2) > input#firstName") + By.cssSelector("form#"+htmlFormId+" > div:nth-child(7) > div:nth-child(2) > input#email") ).isDisplayed() ); }