diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/InternationalizationTest.java b/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/InternationalizationTest.java index f12cca1a97..7090367735 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/InternationalizationTest.java +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/InternationalizationTest.java @@ -19,12 +19,12 @@ package org.keycloak.testsuite.ui.account2; import org.jboss.arquillian.graphene.page.Page; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.keycloak.models.UserModel; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.testsuite.ui.account2.page.PersonalInfoPage; import org.keycloak.testsuite.ui.account2.page.WelcomeScreen; +import org.keycloak.testsuite.util.WaitUtils; import java.util.List; import java.util.Map; @@ -36,7 +36,6 @@ import static org.junit.Assert.assertEquals; /** * @author Vaclav Muzikar */ -@Ignore // TODO remove this once KEYCLOAK-12936 is resolved public class InternationalizationTest extends AbstractAccountTest { @Page private WelcomeScreen welcomeScreen; @@ -53,20 +52,6 @@ public class InternationalizationTest extends AbstractAccountTest { @Before public void beforeI18nTest() { assertTestUserLocale(null); - assertEquals(DEFAULT_LOCALE_NAME, welcomeScreen.header().getCurrentLocaleName()); - } - - @Test - public void welcomeScreenTest() { - welcomeScreen.header().selectLocale(CUSTOM_LOCALE); - assertCustomLocaleWelcomeScreen(); - - // check if selected locale is preserved - welcomeScreen.clickPersonalInfoLink(); - assertCustomLocaleLoginPage(); - loginToAccount(); - assertTestUserLocale(CUSTOM_LOCALE); - assertCustomLocalePersonalInfo(); } @Test @@ -74,8 +59,10 @@ public class InternationalizationTest extends AbstractAccountTest { personalInfoPage.navigateTo(); loginToAccount(); assertTestUserLocale(null); - assertEquals(DEFAULT_LOCALE_NAME, personalInfoPage.header().getCurrentLocaleName()); - personalInfoPage.header().selectLocale(CUSTOM_LOCALE); + personalInfoPage.selectLocale(CUSTOM_LOCALE); + personalInfoPage.clickSave(false); + WaitUtils.waitForPageToLoad(); + assertTestUserLocale(CUSTOM_LOCALE); assertCustomLocalePersonalInfo(); @@ -95,13 +82,11 @@ public class InternationalizationTest extends AbstractAccountTest { } @Test - @SuppressWarnings("unchecked") public void userAttributeTest() { testUser.setAttributes(singletonMap(UserModel.LOCALE, singletonList(CUSTOM_LOCALE))); testUserResource().update(testUser); welcomeScreen.navigateTo(); - assertEquals(DEFAULT_LOCALE_NAME, welcomeScreen.header().getCurrentLocaleName()); welcomeScreen.clickPersonalInfoLink(); assertEquals(DEFAULT_LOCALE_NAME, loginPage.localeDropdown().getSelected()); loginToAccount(); @@ -109,14 +94,10 @@ public class InternationalizationTest extends AbstractAccountTest { } private void assertCustomLocaleWelcomeScreen() { - welcomeScreen.header().assertLocaleVisible(true); - assertEquals(CUSTOM_LOCALE_NAME, welcomeScreen.header().getCurrentLocaleName()); assertEquals("Vítejte v Keycloaku", welcomeScreen.getWelcomeMessage()); } private void assertCustomLocalePersonalInfo() { - personalInfoPage.header().assertLocaleVisible(true); - assertEquals(CUSTOM_LOCALE_NAME, personalInfoPage.header().getCurrentLocaleName()); assertEquals("Osobní údaje", personalInfoPage.getPageTitle()); } @@ -126,7 +107,7 @@ public class InternationalizationTest extends AbstractAccountTest { private void assertTestUserLocale(String expectedLocale) { String actualLocale = null; - List userLocales = null; + List userLocales; Map> userAttributes = testUserResource().toRepresentation().getAttributes(); if (userAttributes != null) { diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/ReferrerTest.java b/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/ReferrerTest.java index c62558162d..403168f230 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/ReferrerTest.java +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/ReferrerTest.java @@ -18,7 +18,6 @@ package org.keycloak.testsuite.ui.account2; import org.jboss.arquillian.graphene.page.Page; -import org.junit.Ignore; import org.junit.Test; import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.RealmRepresentation; @@ -123,31 +122,6 @@ public class ReferrerTest extends AbstractAccountTest { testReferrer(personalInfoPage.header(), false); } - /** - * Test that i18n and referrer work well together - */ - @Test - @Ignore // TODO remove this once KEYCLOAK-12936 is resolved - public void i18nTest() { - RealmRepresentation realm = testRealmResource().toRepresentation(); - configureInternationalizationForRealm(realm); - testRealmResource().update(realm); - testContext.setTestRealmReps(Collections.emptyList()); // a small hack; we want realm re-import after this test - - welcomeScreen.navigateTo(FAKE_CLIENT_ID, getFakeClientUrl()); - welcomeScreen.header().assertReferrerLinkVisible(true); - welcomeScreen.header().selectLocale(CUSTOM_LOCALE); - welcomeScreen.header().assertReferrerLinkVisible(true); - - welcomeScreen.clickPersonalInfoLink(); - assertEquals(CUSTOM_LOCALE_NAME, loginPage.localeDropdown().getSelected()); - loginToAccount(); - personalInfoPage.header().assertReferrerLinkVisible(true); - personalInfoPage.header().selectLocale(DEFAULT_LOCALE); - assertEquals(DEFAULT_LOCALE_NAME, personalInfoPage.header().getCurrentLocaleName()); - testReferrer(personalInfoPage.header(), true); - } - private void testReferrer(AbstractHeader header, boolean expectReferrerVisible) { if (expectReferrerVisible) { assertEquals(REFERRER_LINK_TEXT, header.getReferrerLinkText()); diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/WelcomeScreenTest.java b/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/WelcomeScreenTest.java index e9f1c1f05f..8d7f4d8065 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/WelcomeScreenTest.java +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/WelcomeScreenTest.java @@ -43,7 +43,6 @@ public class WelcomeScreenTest extends AbstractAccountTest { public void loginLogoutTest() { accountWelcomeScreen.assertCurrent(); accountWelcomeScreen.header().assertLogoutBtnVisible(false); - accountWelcomeScreen.header().assertLocaleVisible(false); // login accountWelcomeScreen.header().clickLoginBtn(); diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/PersonalInfoPage.java b/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/PersonalInfoPage.java index 954fb1cd6a..456f6810a7 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/PersonalInfoPage.java +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/PersonalInfoPage.java @@ -20,6 +20,7 @@ package org.keycloak.testsuite.ui.account2.page; import org.keycloak.representations.idm.UserRepresentation; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; +import org.openqa.selenium.support.ui.Select; import static org.keycloak.testsuite.util.UIAssert.assertElementDisabled; import static org.keycloak.testsuite.util.UIAssert.assertInputElementValid; @@ -38,6 +39,8 @@ public class PersonalInfoPage extends AbstractLoggedInPage { private WebElement firstName; @FindBy(id = "last-name") private WebElement lastName; + @FindBy(id = "locale-select") + private Select localeSelector; @FindBy(id = "save-btn") private WebElement saveBtn; @FindBy(id = "cancel-btn") @@ -105,8 +108,14 @@ public class PersonalInfoPage extends AbstractLoggedInPage { } public void clickSave() { + clickSave(true); + } + + public void clickSave(boolean assertAlert) { saveBtn.click(); - alert().assertIsDisplayed(); + if (assertAlert) { + alert().assertIsDisplayed(); + } } public void clickCancel() { @@ -126,4 +135,8 @@ public class PersonalInfoPage extends AbstractLoggedInPage { && user.getFirstName().equals(getFirstName()) && user.getLastName().equals(getLastName()); } + + public void selectLocale(String customLocale) { + localeSelector.selectByValue(customLocale); + } } diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/fragment/AbstractHeader.java b/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/fragment/AbstractHeader.java index c6c6cd893e..a93bdace31 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/fragment/AbstractHeader.java +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/fragment/AbstractHeader.java @@ -60,36 +60,8 @@ public abstract class AbstractHeader extends AbstractFragmentWithMobileLayout { return getToolsBtnText(getReferrerLink()); } - public void selectLocale(String locale) { - if (isMobileLayout()) { - clickMobileKebab(); - } - getLocaleBtn().click(); - clickLink(getLocaleDropdown().findElement(By.id(getLocaleElementIdPrefix() + locale))); - } - - public String getCurrentLocaleName() { - if (!isMobileLayout()) { - return getTextFromElement(getLocaleBtn()); - } - else { - clickMobileKebab(); - String ret = getTextFromElement(getLocaleBtn()); - clickMobileKebab(); // hide the dropdown again - return ret; - } - } - - public void assertLocaleVisible(boolean expected) { - assertToolsBtnVisible(expected, getLocaleBtn()); - } - public abstract void clickMobileKebab(); - protected abstract WebElement getLocaleBtn(); - - protected abstract WebElement getLocaleDropdown(); - protected abstract WebElement getLogoutBtn (); protected abstract WebElement getReferrerLink(); diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/fragment/LoggedInPageHeader.java b/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/fragment/LoggedInPageHeader.java index 8de0a25157..8c62eba65d 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/fragment/LoggedInPageHeader.java +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/fragment/LoggedInPageHeader.java @@ -54,16 +54,6 @@ public class LoggedInPageHeader extends AbstractHeader { clickLink(mobileKebab); } - @Override - protected WebElement getLocaleBtn() { - return isMobileLayout() ? localeBtnMobile : localeBtn; - } - - @Override - protected WebElement getLocaleDropdown() { - return isMobileLayout() ? localeDropdownMobile : localeDropdown; - } - @Override protected WebElement getLogoutBtn() { return isMobileLayout() ? logoutBtnMobile : logoutBtn; diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/fragment/WelcomeScreenHeader.java b/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/fragment/WelcomeScreenHeader.java index c24ac77693..8426f7aa15 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/fragment/WelcomeScreenHeader.java +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/test/java/org/keycloak/testsuite/ui/account2/page/fragment/WelcomeScreenHeader.java @@ -41,11 +41,6 @@ public class WelcomeScreenHeader extends AbstractHeader { @FindBy(id = "landing-mobile-local-toggle") private WebElement localeBtnMobile; - @FindBy(id = "landing-locale-dropdown-list") - private WebElement localeDropdown; - @FindBy(id = "landingMobileDropdown") // the mobile locale menu is integrated with the generic mobile menu - private WebElement localeDropdownMobile; - @FindBy(id = "landingReferrerLink") private WebElement referrerLink; @FindBy(id = "landingMobileReferrerLink") @@ -67,16 +62,6 @@ public class WelcomeScreenHeader extends AbstractHeader { assertToolsBtnVisible(expected, isMobileLayout() ? loginBtnMobile : loginBtn); } - @Override - protected WebElement getLocaleBtn() { - return isMobileLayout() ? localeBtnMobile : localeBtn; - } - - @Override - protected WebElement getLocaleDropdown() { - return isMobileLayout() ? localeDropdownMobile : localeDropdown; - } - @Override protected WebElement getLogoutBtn() { return isMobileLayout() ? logoutBtnMobile : logoutBtn; diff --git a/themes/pom.xml b/themes/pom.xml index b696600733..908c3291f5 100755 --- a/themes/pom.xml +++ b/themes/pom.xml @@ -216,6 +216,10 @@ **/node_modules/@patternfly/react-core/dist/umd/components/Form/FormHelperText.js **/node_modules/@patternfly/react-core/dist/umd/components/Form/Form.js **/node_modules/@patternfly/react-core/dist/umd/components/Form/index.js + **/node_modules/@patternfly/react-core/dist/umd/components/FormSelect/index.js + **/node_modules/@patternfly/react-core/dist/umd/components/FormSelect/FormSelect.js + **/node_modules/@patternfly/react-core/dist/umd/components/FormSelect/FormSelectOption.js + **/node_modules/@patternfly/react-core/dist/umd/components/FormSelect/FormSelectOptionGroup.js **/node_modules/@patternfly/react-core/dist/umd/components/Modal/ModalBoxBody.js **/node_modules/@patternfly/react-core/dist/umd/components/Modal/ModalBoxCloseButton.js **/node_modules/@patternfly/react-core/dist/umd/components/Modal/ModalBoxFooter.js diff --git a/themes/src/main/resources/theme/keycloak-preview/account/index.ftl b/themes/src/main/resources/theme/keycloak-preview/account/index.ftl index 4521b3a1e6..db33a6672d 100644 --- a/themes/src/main/resources/theme/keycloak-preview/account/index.ftl +++ b/themes/src/main/resources/theme/keycloak-preview/account/index.ftl @@ -29,7 +29,7 @@ var features = { isRegistrationEmailAsUsername : ${realm.registrationEmailAsUsername?c}, isEditUserNameAllowed : ${realm.editUsernameAllowed?c}, - isInternationalizationEnabled : false, + isInternationalizationEnabled : ${realm.isInternationalizationEnabled()?c}, isLinkedAccountsEnabled : ${realm.identityFederationEnabled?c}, isEventsEnabled : ${isEventsEnabled?c}, isMyResourcesEnabled : ${(realm.userManagedAccessAllowed && isAuthorizationEnabled)?c}, diff --git a/themes/src/main/resources/theme/keycloak-preview/account/messages/messages_en.properties b/themes/src/main/resources/theme/keycloak-preview/account/messages/messages_en.properties index 9e8936c1d0..e3a92c9daf 100644 --- a/themes/src/main/resources/theme/keycloak-preview/account/messages/messages_en.properties +++ b/themes/src/main/resources/theme/keycloak-preview/account/messages/messages_en.properties @@ -11,6 +11,7 @@ remove=Remove update=Update loadingMessage=Account Console loading ... +selectLocale=Select a locale # Device Activity Page signedInDevices=Signed In Devices signedInDevicesExplanation=Sign out any device that is unfamiliar. diff --git a/themes/src/main/resources/theme/keycloak-preview/account/resources/WelcomePageScripts.js b/themes/src/main/resources/theme/keycloak-preview/account/resources/WelcomePageScripts.js index b8284c95cf..d5078ebf90 100644 --- a/themes/src/main/resources/theme/keycloak-preview/account/resources/WelcomePageScripts.js +++ b/themes/src/main/resources/theme/keycloak-preview/account/resources/WelcomePageScripts.js @@ -53,60 +53,6 @@ var loadPatternFly = function () { patternFlyHasLoaded = true; } -var toggleLocaleDropdown = function () { - var localeDropdownList = document.getElementById("landing-locale-dropdown-list"); - if (localeDropdownList.hasAttribute("hidden")) { - localeDropdownList.removeAttribute("hidden"); - document.getElementById("landing-locale-dropdown-button").setAttribute("aria-expanded", true); - } else { - localeDropdownList.setAttribute("hidden", true); - document.getElementById("landing-locale-dropdown-button").setAttribute("aria-expanded", false); - } -}; - -var toggleMobileDropdown = function () { - var mobileDropdown = document.getElementById("landingMobileDropdown"); - var mobileKebab = document.getElementById("landingMobileKebab"); - var mobileKebabButton = document.getElementById("landingMobileKebabButton"); - if (mobileDropdown.style.display === 'none') { - mobileDropdown.style.display = 'block'; - mobileKebab.classList.add("pf-m-expanded"); - mobileKebabButton.setAttribute("aria-expanded", "true"); - } else { - mobileDropdown.style.display = 'none'; - mobileKebab.classList.remove("pf-m-expanded"); - mobileKebabButton.setAttribute("aria-expanded", "false"); - } -}; - -var toggleMobileChooseLocale = function() { - var mobileLocaleSelectedIcon = document.getElementById("landingMobileLocaleSelectedIcon"); - var isDropdownClosed = mobileLocaleSelectedIcon.classList.contains("fa-angle-right"); - var mobileLocaleSeparator = document.getElementById("landingMobileLocaleSeparator"); - - if (isDropdownClosed) { - mobileLocaleSelectedIcon.classList.remove("fa-angle-right"); - mobileLocaleSelectedIcon.classList.add("fa-angle-down"); - mobileLocaleSeparator.style.display = 'block'; - } else { - mobileLocaleSelectedIcon.classList.add("fa-angle-right"); - mobileLocaleSelectedIcon.classList.remove("fa-angle-down"); - mobileLocaleSeparator.style.display = 'none'; - } - - for (var i=0; i < availableLocales.length; i++) { - if (locale === availableLocales[i].locale) continue; // don't unhide current locale - var mobileLocaleSelection = document.getElementById("landing-mobile-locale-" + availableLocales[i].locale); - if (isDropdownClosed) { - mobileLocaleSelection.style.display= 'inline'; - } else { - mobileLocaleSelection.style.display= 'none'; - } - } - - toggleMobileDropdown(); -} - var loadjs = function (url, loadListener) { const script = document.createElement("script"); script.src = resourceUrl + url; diff --git a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/PageToolbar.tsx b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/PageToolbar.tsx index 7f47628bc8..5e9abaddb3 100644 --- a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/PageToolbar.tsx +++ b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/PageToolbar.tsx @@ -21,7 +21,6 @@ import {Dropdown, KebabToggle, Toolbar, ToolbarGroup, ToolbarItem} from '@patter import {ReferrerDropdownItem} from './widgets/ReferrerDropdownItem'; import {ReferrerLink} from './widgets/ReferrerLink'; import {Features} from './widgets/features'; -import {LocaleNav,LocaleDropdown} from './widgets/LocaleSelectors'; import {LogoutButton,LogoutDropdownItem} from './widgets/Logout'; declare const referrerName: string; @@ -54,10 +53,6 @@ export class PageToolbar extends React.Component); - } - kebabDropdownItems.push(); return ( @@ -71,12 +66,6 @@ export class PageToolbar extends React.Component - {features.isInternationalizationEnabled && - - - - } - diff --git a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/account-page/AccountPage.tsx b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/account-page/AccountPage.tsx index b54f57ea43..dd8a261411 100644 --- a/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/account-page/AccountPage.tsx +++ b/themes/src/main/resources/theme/keycloak-preview/account/resources/app/content/account-page/AccountPage.tsx @@ -23,8 +23,10 @@ import { Features } from '../../widgets/features'; import { Msg } from '../../widgets/Msg'; import { ContentPage } from '../ContentPage'; import { ContentAlert } from '../ContentAlert'; +import { LocaleSelector } from '../../widgets/LocaleSelectors'; declare const features: Features; +declare const locale: string; interface AccountPageProps { } @@ -34,6 +36,7 @@ interface FormFields { readonly firstName?: string; readonly lastName?: string; readonly email?: string; + attributes?: { locale?: [string] }; } interface AccountPageState { @@ -58,7 +61,8 @@ export class AccountPage extends React.Component) => { this.setState(this.DEFAULT_STATE); - this.setState({...{ formFields: response.data }}); + const formFields = response.data; + if (!formFields.attributes || !formFields.attributes.locale) { + formFields.attributes = { locale: [locale] }; + } + + this.setState({...{ formFields: formFields }}); }); } @@ -100,6 +109,9 @@ export class AccountPage extends React.Component { // to use response, say ((response: AxiosResponse) => { ContentAlert.success('accountUpdatedMessage'); + if (locale !== this.state.formFields.attributes!.locale![0]) { + window.location.reload(); + } }); } else { const formData = new FormData(form); @@ -187,6 +199,19 @@ export class AccountPage extends React.Component + {features.isInternationalizationEnabled && + this.setState({ + errors: this.state.errors, + formFields: { ...this.state.formFields, attributes: { ...this.state.formFields.attributes, locale: [value] }} + })} + /> + }