Updated the test ldap settings with second button (#1275)
Co-authored-by: Jon Koops <jonkoops@gmail.com>
This commit is contained in:
parent
fae250f13e
commit
9180b18652
7 changed files with 106 additions and 39 deletions
|
@ -1,13 +1,18 @@
|
||||||
/**
|
/**
|
||||||
* @jest-environment jsdom
|
* @jest-environment jsdom
|
||||||
*/
|
*/
|
||||||
import { Button } from "@patternfly/react-core";
|
|
||||||
import { fireEvent, render, screen } from "@testing-library/react";
|
|
||||||
import type { ServerInfoRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/serverInfoRepesentation";
|
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
import { fireEvent, render, screen } from "@testing-library/react";
|
||||||
|
import { Button } from "@patternfly/react-core";
|
||||||
|
|
||||||
|
import type { ServerInfoRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/serverInfoRepesentation";
|
||||||
|
import type WhoAmIRepresentation from "@keycloak/keycloak-admin-client/lib/defs/whoAmIRepresentation";
|
||||||
import { ServerInfoContext } from "../../context/server-info/ServerInfoProvider";
|
import { ServerInfoContext } from "../../context/server-info/ServerInfoProvider";
|
||||||
import serverInfo from "../../context/server-info/__tests__/mock.json";
|
import serverInfo from "../../context/server-info/__tests__/mock.json";
|
||||||
import { AddMapperDialog, AddMapperDialogModalProps } from "./MapperDialog";
|
import { AddMapperDialog, AddMapperDialogModalProps } from "./MapperDialog";
|
||||||
|
import { WhoAmI, WhoAmIContext } from "../../context/whoami/WhoAmI";
|
||||||
|
|
||||||
|
import whoami from "../../context/whoami/__tests__/mock-whoami.json";
|
||||||
|
|
||||||
describe("MapperDialog", () => {
|
describe("MapperDialog", () => {
|
||||||
const Test = (args: AddMapperDialogModalProps) => {
|
const Test = (args: AddMapperDialogModalProps) => {
|
||||||
|
@ -16,13 +21,22 @@ describe("MapperDialog", () => {
|
||||||
return (
|
return (
|
||||||
<ServerInfoContext.Provider
|
<ServerInfoContext.Provider
|
||||||
value={serverInfo as unknown as ServerInfoRepresentation}
|
value={serverInfo as unknown as ServerInfoRepresentation}
|
||||||
|
>
|
||||||
|
<WhoAmIContext.Provider
|
||||||
|
value={{
|
||||||
|
refresh: () => {},
|
||||||
|
whoAmI: new WhoAmI(whoami as WhoAmIRepresentation),
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<AddMapperDialog
|
<AddMapperDialog
|
||||||
{...args}
|
{...args}
|
||||||
open={open}
|
open={open}
|
||||||
toggleDialog={() => setOpen(!open)}
|
toggleDialog={() => setOpen(!open)}
|
||||||
/>
|
/>
|
||||||
<Button onClick={() => setOpen(true)}>{!open ? "Show" : "Hide"}</Button>
|
<Button onClick={() => setOpen(true)}>
|
||||||
|
{!open ? "Show" : "Hide"}
|
||||||
|
</Button>
|
||||||
|
</WhoAmIContext.Provider>
|
||||||
</ServerInfoContext.Provider>
|
</ServerInfoContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -59,7 +73,7 @@ describe("MapperDialog", () => {
|
||||||
render(<Test protocol={protocol} onConfirm={onConfirm} />);
|
render(<Test protocol={protocol} onConfirm={onConfirm} />);
|
||||||
|
|
||||||
fireEvent.click(screen.getByText("Show"));
|
fireEvent.click(screen.getByText("Show"));
|
||||||
fireEvent.click(screen.getByLabelText("User Realm Role"));
|
fireEvent.click(screen.getByLabelText("Allowed Web Origins"));
|
||||||
|
|
||||||
expect(onConfirm).toBeCalledWith(
|
expect(onConfirm).toBeCalledWith(
|
||||||
serverInfo.protocolMapperTypes[protocol][0]
|
serverInfo.protocolMapperTypes[protocol][0]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState } from "react";
|
import React, { useMemo, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
ButtonVariant,
|
ButtonVariant,
|
||||||
|
@ -11,6 +11,7 @@ import {
|
||||||
ModalVariant,
|
ModalVariant,
|
||||||
Text,
|
Text,
|
||||||
TextContent,
|
TextContent,
|
||||||
|
TextVariants,
|
||||||
} from "@patternfly/react-core";
|
} from "@patternfly/react-core";
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
|
@ -23,6 +24,7 @@ import type ProtocolMapperRepresentation from "@keycloak/keycloak-admin-client/l
|
||||||
import type { ProtocolMapperTypeRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/serverInfoRepesentation";
|
import type { ProtocolMapperTypeRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/serverInfoRepesentation";
|
||||||
|
|
||||||
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
||||||
|
import { useWhoAmI } from "../../context/whoami/WhoAmI";
|
||||||
import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState";
|
import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState";
|
||||||
|
|
||||||
export type AddMapperDialogModalProps = {
|
export type AddMapperDialogModalProps = {
|
||||||
|
@ -42,12 +44,17 @@ export const AddMapperDialog = (props: AddMapperDialogProps) => {
|
||||||
const { t } = useTranslation("client-scopes");
|
const { t } = useTranslation("client-scopes");
|
||||||
|
|
||||||
const serverInfo = useServerInfo();
|
const serverInfo = useServerInfo();
|
||||||
|
const { whoAmI } = useWhoAmI();
|
||||||
const protocol = props.protocol;
|
const protocol = props.protocol;
|
||||||
const protocolMappers = serverInfo.protocolMapperTypes![protocol];
|
const protocolMappers = serverInfo.protocolMapperTypes![protocol];
|
||||||
const builtInMappers = serverInfo.builtinProtocolMappers![protocol];
|
const builtInMappers = serverInfo.builtinProtocolMappers![protocol];
|
||||||
const [filter, setFilter] = useState<ProtocolMapperRepresentation[]>([]);
|
const [filter, setFilter] = useState<ProtocolMapperRepresentation[]>([]);
|
||||||
|
|
||||||
const allRows = builtInMappers.map((mapper) => {
|
const allRows = useMemo(
|
||||||
|
() =>
|
||||||
|
builtInMappers
|
||||||
|
.sort((a, b) => a.name!.localeCompare(b.name!, whoAmI.getLocale()))
|
||||||
|
.map((mapper) => {
|
||||||
const mapperType = protocolMappers.filter(
|
const mapperType = protocolMappers.filter(
|
||||||
(type) => type.id === mapper.protocolMapper
|
(type) => type.id === mapper.protocolMapper
|
||||||
)[0];
|
)[0];
|
||||||
|
@ -56,7 +63,9 @@ export const AddMapperDialog = (props: AddMapperDialogProps) => {
|
||||||
selected: false,
|
selected: false,
|
||||||
cells: [mapper.name, mapperType.helpText],
|
cells: [mapper.name, mapperType.helpText],
|
||||||
};
|
};
|
||||||
});
|
}),
|
||||||
|
[]
|
||||||
|
);
|
||||||
const [rows, setRows] = useState(allRows);
|
const [rows, setRows] = useState(allRows);
|
||||||
|
|
||||||
if (props.filter && props.filter.length !== filter.length) {
|
if (props.filter && props.filter.length !== filter.length) {
|
||||||
|
@ -68,12 +77,29 @@ export const AddMapperDialog = (props: AddMapperDialogProps) => {
|
||||||
const selectedRows = rows
|
const selectedRows = rows
|
||||||
.filter((row) => row.selected)
|
.filter((row) => row.selected)
|
||||||
.map((row) => row.item);
|
.map((row) => row.item);
|
||||||
|
|
||||||
|
const sortedProtocolMappers = useMemo(
|
||||||
|
() =>
|
||||||
|
protocolMappers.sort((a, b) =>
|
||||||
|
a.name!.localeCompare(b.name!, whoAmI.getLocale())
|
||||||
|
),
|
||||||
|
[protocolMappers]
|
||||||
|
);
|
||||||
|
|
||||||
const isBuiltIn = !!props.filter;
|
const isBuiltIn = !!props.filter;
|
||||||
|
|
||||||
|
const header = [t("common:name"), t("common:description")];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
|
aria-labelledby={t("chooseAMapperType")}
|
||||||
variant={ModalVariant.medium}
|
variant={ModalVariant.medium}
|
||||||
title={t("chooseAMapperType")}
|
header={
|
||||||
|
<TextContent>
|
||||||
|
<Text component={TextVariants.h1}>{t("chooseAMapperType")}</Text>
|
||||||
|
<Text>{t("predefinedMappingDescription")}</Text>
|
||||||
|
</TextContent>
|
||||||
|
}
|
||||||
isOpen={props.open}
|
isOpen={props.open}
|
||||||
onClose={props.toggleDialog}
|
onClose={props.toggleDialog}
|
||||||
actions={
|
actions={
|
||||||
|
@ -105,9 +131,6 @@ export const AddMapperDialog = (props: AddMapperDialogProps) => {
|
||||||
: []
|
: []
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<TextContent>
|
|
||||||
<Text>{t("predefinedMappingDescription")}</Text>
|
|
||||||
</TextContent>
|
|
||||||
{!isBuiltIn && (
|
{!isBuiltIn && (
|
||||||
<DataList
|
<DataList
|
||||||
onSelectDataListItem={(id) => {
|
onSelectDataListItem={(id) => {
|
||||||
|
@ -118,7 +141,18 @@ export const AddMapperDialog = (props: AddMapperDialogProps) => {
|
||||||
aria-label={t("chooseAMapperType")}
|
aria-label={t("chooseAMapperType")}
|
||||||
isCompact
|
isCompact
|
||||||
>
|
>
|
||||||
{protocolMappers.map((mapper) => (
|
<DataListItem aria-labelledby="headerName" id="header">
|
||||||
|
<DataListItemRow>
|
||||||
|
<DataListItemCells
|
||||||
|
dataListCells={header.map((name) => (
|
||||||
|
<DataListCell style={{ fontWeight: 700 }} key={name}>
|
||||||
|
{name}
|
||||||
|
</DataListCell>
|
||||||
|
))}
|
||||||
|
/>
|
||||||
|
</DataListItemRow>
|
||||||
|
</DataListItem>
|
||||||
|
{sortedProtocolMappers.map((mapper) => (
|
||||||
<DataListItem
|
<DataListItem
|
||||||
aria-label={mapper.name}
|
aria-label={mapper.name}
|
||||||
key={mapper.id}
|
key={mapper.id}
|
||||||
|
@ -143,7 +177,7 @@ export const AddMapperDialog = (props: AddMapperDialogProps) => {
|
||||||
{isBuiltIn && rows.length > 0 && (
|
{isBuiltIn && rows.length > 0 && (
|
||||||
<Table
|
<Table
|
||||||
variant={TableVariant.compact}
|
variant={TableVariant.compact}
|
||||||
cells={[t("common:name"), t("common:description")]}
|
cells={header}
|
||||||
onSelect={(_, isSelected, rowIndex) => {
|
onSelect={(_, isSelected, rowIndex) => {
|
||||||
rows[rowIndex].selected = isSelected;
|
rows[rowIndex].selected = isSelected;
|
||||||
setRows([...rows]);
|
setRows([...rows]);
|
||||||
|
|
|
@ -49,6 +49,7 @@ export default {
|
||||||
enableHelpMode: "Enable help mode",
|
enableHelpMode: "Enable help mode",
|
||||||
learnMore: "Learn more",
|
learnMore: "Learn more",
|
||||||
test: "Test",
|
test: "Test",
|
||||||
|
testConnection: "Test connection",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
role: "Role",
|
role: "Role",
|
||||||
description: "Description",
|
description: "Description",
|
||||||
|
|
|
@ -50,7 +50,7 @@ export const AddUserEmailModal = ({
|
||||||
form="email-form"
|
form="email-form"
|
||||||
isDisabled={!watchEmailInput}
|
isDisabled={!watchEmailInput}
|
||||||
>
|
>
|
||||||
{t("realm-settings:testConnection")}
|
{t("common:testConnection")}
|
||||||
</Button>,
|
</Button>,
|
||||||
<Button
|
<Button
|
||||||
id="modal-cancel"
|
id="modal-cancel"
|
||||||
|
|
|
@ -390,7 +390,7 @@ export const RealmSettingsEmailTab = ({
|
||||||
!(emailRegexPattern.test(watchFromValue) && watchHostValue)
|
!(emailRegexPattern.test(watchFromValue) && watchHostValue)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{t("realm-settings:testConnection")}
|
{t("common:testConnection")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="link" onClick={reset}>
|
<Button variant="link" onClick={reset}>
|
||||||
{t("common:revert")}
|
{t("common:revert")}
|
||||||
|
|
|
@ -40,6 +40,19 @@ const testLdapProperties: Array<keyof TestLdapConnectionRepresentation> = [
|
||||||
"authType",
|
"authType",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
type TestTypes = "testConnection" | "testAuthentication";
|
||||||
|
|
||||||
|
const convertFormToSettings = (form: UseFormMethods) => {
|
||||||
|
const settings: TestLdapConnectionRepresentation = {};
|
||||||
|
|
||||||
|
testLdapProperties.forEach((key) => {
|
||||||
|
const value = _.get(form.getValues(), `config.${key}`);
|
||||||
|
settings[key] = Array.isArray(value) ? value[0] : "";
|
||||||
|
});
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
};
|
||||||
|
|
||||||
export const LdapSettingsConnection = ({
|
export const LdapSettingsConnection = ({
|
||||||
form,
|
form,
|
||||||
showSectionHeading = false,
|
showSectionHeading = false,
|
||||||
|
@ -52,17 +65,12 @@ export const LdapSettingsConnection = ({
|
||||||
const { realm } = useRealm();
|
const { realm } = useRealm();
|
||||||
const { addAlert, addError } = useAlerts();
|
const { addAlert, addError } = useAlerts();
|
||||||
|
|
||||||
const testLdap = async () => {
|
const testLdap = async (testType: TestTypes) => {
|
||||||
try {
|
try {
|
||||||
const settings: TestLdapConnectionRepresentation = {};
|
const settings = convertFormToSettings(form);
|
||||||
|
|
||||||
testLdapProperties.forEach((key) => {
|
|
||||||
const value = _.get(form.getValues(), `config.${key}`);
|
|
||||||
settings[key] = _.isArray(value) ? value[0] : "";
|
|
||||||
});
|
|
||||||
await adminClient.realms.testLDAPConnection(
|
await adminClient.realms.testLDAPConnection(
|
||||||
{ realm },
|
{ realm },
|
||||||
{ ...settings, action: "testConnection" }
|
{ ...settings, action: testType }
|
||||||
);
|
);
|
||||||
addAlert(t("testSuccess"), AlertVariant.success);
|
addAlert(t("testSuccess"), AlertVariant.success);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -235,6 +243,15 @@ export const LdapSettingsConnection = ({
|
||||||
ref={form.register}
|
ref={form.register}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
<FormGroup fieldId="kc-test-button">
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
id="kc-connection-test-button"
|
||||||
|
onClick={() => testLdap("testConnection")}
|
||||||
|
>
|
||||||
|
{t("common:testConnection")}
|
||||||
|
</Button>
|
||||||
|
</FormGroup>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("bindType")}
|
label={t("bindType")}
|
||||||
labelIcon={
|
labelIcon={
|
||||||
|
@ -337,9 +354,9 @@ export const LdapSettingsConnection = ({
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
id="kc-test-button"
|
id="kc-test-button"
|
||||||
onClick={() => testLdap()}
|
onClick={() => testLdap("testAuthentication")}
|
||||||
>
|
>
|
||||||
{t("common:test")}
|
{t("testAuthentication")}
|
||||||
</Button>
|
</Button>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</FormAccess>
|
</FormAccess>
|
||||||
|
|
|
@ -90,6 +90,7 @@ export default {
|
||||||
saveError: "User federation provider could not be saved: {{error}}",
|
saveError: "User federation provider could not be saved: {{error}}",
|
||||||
createSuccess: "User federation provider successfully created",
|
createSuccess: "User federation provider successfully created",
|
||||||
createError: "User federation provider could not be created: {{error}}",
|
createError: "User federation provider could not be created: {{error}}",
|
||||||
|
testAuthentication: "Test authentication",
|
||||||
testSuccess: "Successfully connected to LDAP",
|
testSuccess: "Successfully connected to LDAP",
|
||||||
testError:
|
testError:
|
||||||
"Error when trying to connect to LDAP. See server.log for details. {{error}}",
|
"Error when trying to connect to LDAP. See server.log for details. {{error}}",
|
||||||
|
|
Loading…
Reference in a new issue