Realm settings(login tab): fix switches (#1183)

* fix login tab

update cypress test

cypress test

rebase

test updates

cypress test fix

get correct ids

fix get call

fix tests

try refetching realm

add useEffect to fix server GET call

uncomment test

revert to original useFetch

prettier

create new function

set timeout to 10 ms

set to 100 ms

* add comment to useEffect per Jon feedback
This commit is contained in:
Jenny 2021-09-27 13:15:36 -04:00 committed by GitHub
parent bd5b0da694
commit 02ce5c4e6e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 185 additions and 76 deletions

View file

@ -126,6 +126,15 @@ describe("Realm settings tests", () => {
realmSettingsPage.toggleSwitch(realmSettingsPage.rememberMeSwitch); realmSettingsPage.toggleSwitch(realmSettingsPage.rememberMeSwitch);
}); });
it("Check login tab values", () => {
sidebarPage.goToRealmSettings();
cy.findByTestId("rs-login-tab").click();
cy.get("#kc-user-reg-switch-off").should("be.visible");
cy.get("#kc-forgot-pw-switch-off").should("be.visible");
cy.get("#kc-remember-me-switch-off").should("not.be.visible");
});
it("Go to email tab", () => { it("Go to email tab", () => {
sidebarPage.goToRealmSettings(); sidebarPage.goToRealmSettings();
cy.findByTestId("rs-email-tab").click(); cy.findByTestId("rs-email-tab").click();

View file

@ -5,18 +5,33 @@ import { FormAccess } from "../components/form-access/FormAccess";
import { HelpItem } from "../components/help-enabler/HelpItem"; import { HelpItem } from "../components/help-enabler/HelpItem";
import { FormPanel } from "../components/scroll-form/FormPanel"; import { FormPanel } from "../components/scroll-form/FormPanel";
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation"; import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
import { Controller, useForm } from "react-hook-form";
type RealmSettingsLoginTabProps = { type RealmSettingsLoginTabProps = {
save: (realm: RealmRepresentation) => void; save: (realm: RealmRepresentation) => void;
realm: RealmRepresentation; realm: RealmRepresentation;
refresh: () => void;
}; };
export const RealmSettingsLoginTab = ({ export const RealmSettingsLoginTab = ({
save, save,
realm, realm,
refresh,
}: RealmSettingsLoginTabProps) => { }: RealmSettingsLoginTabProps) => {
const { t } = useTranslation("realm-settings"); const { t } = useTranslation("realm-settings");
const form = useForm<RealmRepresentation>({ mode: "onChange" });
const updateSwitchValue = (
onChange: (newValue: boolean) => void,
value: boolean,
name: string
) => {
save({ ...realm, [name as keyof typeof realm]: value });
onChange(value);
refresh();
};
return ( return (
<PageSection variant="light"> <PageSection variant="light">
<FormPanel className="kc-login-screen" title="Login screen customization"> <FormPanel className="kc-login-screen" title="Login screen customization">
@ -35,17 +50,24 @@ export const RealmSettingsLoginTab = ({
} }
hasNoPaddingTop hasNoPaddingTop
> >
<Controller
name="registrationAllowed"
defaultValue={realm.registrationAllowed}
control={form.control}
render={({ onChange, value }) => (
<Switch <Switch
id="kc-user-reg-switch" id="kc-user-reg-switch"
data-testid="user-reg-switch" data-testid="user-reg-switch"
name="registrationAllowed" name="registrationAllowed"
label={t("common:on")} label={t("common:on")}
labelOff={t("common:off")} labelOff={t("common:off")}
isChecked={realm?.registrationAllowed} isChecked={value}
onChange={(value) => { onChange={(value) => {
save({ ...realm, registrationAllowed: value }); updateSwitchValue(onChange, value, "registrationAllowed");
}} }}
/> />
)}
/>
</FormGroup> </FormGroup>
<FormGroup <FormGroup
label={t("forgotPassword")} label={t("forgotPassword")}
@ -59,17 +81,24 @@ export const RealmSettingsLoginTab = ({
} }
hasNoPaddingTop hasNoPaddingTop
> >
<Controller
name="resetPasswordAllowed"
defaultValue={realm.resetPasswordAllowed}
control={form.control}
render={({ onChange, value }) => (
<Switch <Switch
id="kc-forgot-pw-switch" id="kc-forgot-pw-switch"
data-testid="forgot-pw-switch" data-testid="forgot-pw-switch"
name="resetPasswordAllowed" name="resetPasswordAllowed"
label={t("common:on")} label={t("common:on")}
labelOff={t("common:off")} labelOff={t("common:off")}
isChecked={realm?.resetPasswordAllowed} isChecked={value}
onChange={(value) => { onChange={(value) => {
save({ ...realm, resetPasswordAllowed: value }); updateSwitchValue(onChange, value, "resetPasswordAllowed");
}} }}
/> />
)}
/>
</FormGroup> </FormGroup>
<FormGroup <FormGroup
label={t("rememberMe")} label={t("rememberMe")}
@ -83,17 +112,24 @@ export const RealmSettingsLoginTab = ({
} }
hasNoPaddingTop hasNoPaddingTop
> >
<Controller
name="rememberMe"
defaultValue={realm.rememberMe}
control={form.control}
render={({ onChange, value }) => (
<Switch <Switch
id="kc-remember-me-switch" id="kc-remember-me-switch"
data-testid="remember-me-switch" data-testid="remember-me-switch"
name="rememberMe" name="rememberMe"
label={t("common:on")} label={t("common:on")}
labelOff={t("common:off")} labelOff={t("common:off")}
isChecked={realm?.rememberMe} isChecked={value}
onChange={(value) => { onChange={(value) => {
save({ ...realm, rememberMe: value }); updateSwitchValue(onChange, value, "rememberMe");
}} }}
/> />
)}
/>
</FormGroup> </FormGroup>
</FormAccess> </FormAccess>
</FormPanel> </FormPanel>
@ -111,17 +147,28 @@ export const RealmSettingsLoginTab = ({
} }
hasNoPaddingTop hasNoPaddingTop
> >
<Controller
name="registrationEmailAsUsername"
defaultValue={realm.registrationEmailAsUsername}
control={form.control}
render={({ onChange, value }) => (
<Switch <Switch
id="kc-email-as-username-switch" id="kc-email-as-username-switch"
data-testid="email-as-username-switch" data-testid="email-as-username-switch"
name="registrationEmailAsUsername" name="registrationEmailAsUsername"
label={t("common:on")} label={t("common:on")}
labelOff={t("common:off")} labelOff={t("common:off")}
isChecked={realm?.registrationEmailAsUsername} isChecked={value}
onChange={(value) => { onChange={(value) => {
save({ ...realm, registrationEmailAsUsername: value }); updateSwitchValue(
onChange,
value,
"registrationEmailAsUsername"
);
}} }}
/> />
)}
/>
</FormGroup> </FormGroup>
<FormGroup <FormGroup
label={t("loginWithEmail")} label={t("loginWithEmail")}
@ -135,17 +182,24 @@ export const RealmSettingsLoginTab = ({
} }
hasNoPaddingTop hasNoPaddingTop
> >
<Controller
name="loginWithEmailAllowed"
defaultValue={realm.loginWithEmailAllowed}
control={form.control}
render={({ onChange, value }) => (
<Switch <Switch
id="kc-login-with-email-switch" id="kc-login-with-email-switch"
data-testid="login-with-email-switch" data-testid="login-with-email-switch"
name="loginWithEmailAllowed" name="loginWithEmailAllowed"
label={t("common:on")} label={t("common:on")}
labelOff={t("common:off")} labelOff={t("common:off")}
isChecked={realm?.loginWithEmailAllowed} isChecked={value}
onChange={(value) => { onChange={(value) => {
save({ ...realm, loginWithEmailAllowed: value }); updateSwitchValue(onChange, value, "loginWithEmailAllowed");
}} }}
/> />
)}
/>
</FormGroup> </FormGroup>
<FormGroup <FormGroup
label={t("duplicateEmails")} label={t("duplicateEmails")}
@ -159,6 +213,11 @@ export const RealmSettingsLoginTab = ({
} }
hasNoPaddingTop hasNoPaddingTop
> >
<Controller
name="duplicateEmailsAllowed"
defaultValue={realm.duplicateEmailsAllowed}
control={form.control}
render={({ onChange }) => (
<Switch <Switch
id="kc-duplicate-emails-switch" id="kc-duplicate-emails-switch"
data-testid="duplicate-emails-switch" data-testid="duplicate-emails-switch"
@ -166,18 +225,24 @@ export const RealmSettingsLoginTab = ({
labelOff={t("common:off")} labelOff={t("common:off")}
name="duplicateEmailsAllowed" name="duplicateEmailsAllowed"
isChecked={ isChecked={
realm?.duplicateEmailsAllowed && form.getValues().duplicateEmailsAllowed &&
!realm?.loginWithEmailAllowed && !form.getValues().loginWithEmailAllowed &&
!realm?.registrationEmailAsUsername !form.getValues().registrationEmailAsUsername
} }
onChange={(value) => { onChange={(value) => {
save({ ...realm, duplicateEmailsAllowed: value }); updateSwitchValue(
onChange,
value,
"duplicateEmailsAllowed"
);
}} }}
isDisabled={ isDisabled={
realm?.loginWithEmailAllowed || form.getValues().loginWithEmailAllowed ||
realm?.registrationEmailAsUsername form.getValues().registrationEmailAsUsername
} }
/> />
)}
/>
</FormGroup> </FormGroup>
<FormGroup <FormGroup
label={t("verifyEmail")} label={t("verifyEmail")}
@ -191,17 +256,24 @@ export const RealmSettingsLoginTab = ({
} }
hasNoPaddingTop hasNoPaddingTop
> >
<Controller
name="verifyEmail"
defaultValue={realm.verifyEmail}
control={form.control}
render={({ onChange, value }) => (
<Switch <Switch
id="kc-verify-email-switch" id="kc-verify-email-switch"
data-testid="verify-email-switch" data-testid="verify-email-switch"
name="verifyEmail" name="verifyEmail"
label={t("common:on")} label={t("common:on")}
labelOff={t("common:off")} labelOff={t("common:off")}
isChecked={realm?.verifyEmail} isChecked={value}
onChange={(value) => { onChange={(value) => {
save({ ...realm, verifyEmail: value }); updateSwitchValue(onChange, value, "verifyEmail");
}} }}
/> />
)}
/>
</FormGroup> </FormGroup>
</FormAccess> </FormAccess>
</FormPanel> </FormPanel>

View file

@ -2,7 +2,7 @@ import { Breadcrumb, BreadcrumbItem, Spinner } from "@patternfly/react-core";
import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation"; import type ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation";
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation"; import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation"; import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
import React, { useState } from "react"; import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useAdminClient, useFetch } from "../context/auth/AdminClient"; import { useAdminClient, useFetch } from "../context/auth/AdminClient";
@ -52,6 +52,20 @@ export const RealmSettingsSection = () => {
useState<ComponentRepresentation[]>(); useState<ComponentRepresentation[]>();
const [currentUser, setCurrentUser] = useState<UserRepresentation>(); const [currentUser, setCurrentUser] = useState<UserRepresentation>();
const { whoAmI } = useWhoAmI(); const { whoAmI } = useWhoAmI();
const [key, setKey] = useState(0);
const refresh = () => {
setKey(key + 1);
};
// delays realm fetch by 100ms in order to fetch newly updated value from server
useEffect(() => {
const update = async () => {
const realm = await adminClient.realms.findOne({ realm: realmName });
setRealm(realm);
};
setTimeout(update, 100);
}, [key]);
useFetch( useFetch(
async () => { async () => {
@ -82,6 +96,7 @@ export const RealmSettingsSection = () => {
return ( return (
<RealmSettingsTabs <RealmSettingsTabs
realm={realm} realm={realm}
refresh={refresh}
realmComponents={realmComponents} realmComponents={realmComponents}
currentUser={currentUser} currentUser={currentUser}
/> />

View file

@ -53,6 +53,7 @@ type RealmSettingsHeaderProps = {
value: boolean; value: boolean;
save: () => void; save: () => void;
realmName: string; realmName: string;
refresh: () => void;
}; };
const RealmSettingsHeader = ({ const RealmSettingsHeader = ({
@ -60,12 +61,12 @@ const RealmSettingsHeader = ({
onChange, onChange,
value, value,
realmName, realmName,
refresh,
}: RealmSettingsHeaderProps) => { }: RealmSettingsHeaderProps) => {
const { t } = useTranslation("realm-settings"); const { t } = useTranslation("realm-settings");
const adminClient = useAdminClient(); const adminClient = useAdminClient();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const history = useHistory(); const history = useHistory();
const { refresh } = useRealm();
const [partialImportOpen, setPartialImportOpen] = useState(false); const [partialImportOpen, setPartialImportOpen] = useState(false);
const [toggleDisableDialog, DisableConfirm] = useConfirmDialog({ const [toggleDisableDialog, DisableConfirm] = useConfirmDialog({
@ -138,6 +139,7 @@ const RealmSettingsHeader = ({
type RealmSettingsTabsProps = { type RealmSettingsTabsProps = {
realm: RealmRepresentation; realm: RealmRepresentation;
refresh: () => void;
realmComponents: ComponentRepresentation[]; realmComponents: ComponentRepresentation[];
currentUser: UserRepresentation; currentUser: UserRepresentation;
}; };
@ -146,6 +148,7 @@ export const RealmSettingsTabs = ({
realm, realm,
realmComponents, realmComponents,
currentUser, currentUser,
refresh,
}: RealmSettingsTabsProps) => { }: RealmSettingsTabsProps) => {
const { t } = useTranslation("realm-settings"); const { t } = useTranslation("realm-settings");
const adminClient = useAdminClient(); const adminClient = useAdminClient();
@ -162,7 +165,7 @@ export const RealmSettingsTabs = ({
const [activeTab, setActiveTab] = useState(0); const [activeTab, setActiveTab] = useState(0);
const [key, setKey] = useState(0); const [key, setKey] = useState(0);
const refresh = () => { const refreshHeader = () => {
setKey(new Date().getTime()); setKey(new Date().getTime());
}; };
@ -188,9 +191,14 @@ export const RealmSettingsTabs = ({
convertFormValuesToObject(realm.attributes, true) convertFormValuesToObject(realm.attributes, true)
).filter(([, v]) => v !== "") ).filter(([, v]) => v !== "")
); );
await adminClient.realms.update( await adminClient.realms.update(
{ realm: realmName }, { realm: realmName },
{ ...realm, id: realmName, attributes } {
...realm,
id: realmName,
attributes,
}
); );
setupForm(realm); setupForm(realm);
const isRealmRenamed = realmName !== realm.realm; const isRealmRenamed = realmName !== realm.realm;
@ -215,6 +223,7 @@ export const RealmSettingsTabs = ({
value={value} value={value}
onChange={onChange} onChange={onChange}
realmName={realmName} realmName={realmName}
refresh={refreshHeader}
save={() => save(getValues())} save={() => save(getValues())}
/> />
)} )}
@ -239,7 +248,11 @@ export const RealmSettingsTabs = ({
data-testid="rs-login-tab" data-testid="rs-login-tab"
aria-label="login-tab" aria-label="login-tab"
> >
<RealmSettingsLoginTab save={save} realm={realm} /> <RealmSettingsLoginTab
refresh={refresh}
save={save}
realm={realm}
/>
</Tab> </Tab>
<Tab <Tab
eventKey="email" eventKey="email"