Event listeners (#1533)
* fixed a breadcrum for edit profile * edit executor - wip * edit executor - wip * edit executor - wip * edit executor - wip * edit executor - wip * edit executor - wip * edit executor - wip * edit executor - wip * edit executor - wip * edit executor - wip * edit executor - wip * edit executor - wip * executor details - wip * fixed executors list * fixed multivaluedList and List components * fixed displaying default vals for global profile executors, fixed unclicking executors without congigs for global profiles * added edit executor * improved edit executor * added tests for editing executors * renamed obj * skipping client policies tests as unstable * feedback fixes * fix multiValuedlist defaults - wip * fixed defaultValues for multiValuedList * resolved and fixed conflict for test * added event listeners * added event listeners * added success and error mssgs for event listeners saving * added tests for event listeners * added tests for event listeners * improved error mssg * fixed events tests as LOGIN type no longer available * uncommented test, but using .skip Co-authored-by: Agnieszka Gancarczyk <agancarc@redhat.com>
This commit is contained in:
parent
7786e6d463
commit
2b45a83109
8 changed files with 262 additions and 24 deletions
|
@ -24,10 +24,11 @@ describe("Events tests", () => {
|
|||
it("Check search dropdown display", () => {
|
||||
sidebarPage.goToRealmSettings();
|
||||
cy.findByTestId("rs-realm-events-tab").click();
|
||||
cy.findByTestId("rs-events-tab").click();
|
||||
|
||||
realmSettingsPage
|
||||
.toggleSwitch(realmSettingsPage.enableEvents)
|
||||
.save(realmSettingsPage.eventsUserSave);
|
||||
.save(realmSettingsPage.modalConfirm);
|
||||
|
||||
masthead.signOut();
|
||||
loginPage.logIn();
|
||||
|
@ -77,7 +78,7 @@ describe("Events tests", () => {
|
|||
|
||||
realmSettingsPage
|
||||
.toggleSwitch(realmSettingsPage.enableAdminEvents)
|
||||
.save(realmSettingsPage.eventsAdminSave);
|
||||
.save(realmSettingsPage.modalConfirm);
|
||||
|
||||
sidebarPage.goToEvents();
|
||||
cy.findByTestId("admin-events-tab").click();
|
||||
|
|
|
@ -118,8 +118,7 @@ describe("Realm settings tests", () => {
|
|||
masthead.checkNotificationMessage("Realm successfully updated");
|
||||
});
|
||||
|
||||
/*
|
||||
it("Go to login tab", () => {
|
||||
it.skip("Go to login tab", () => {
|
||||
sidebarPage.goToRealmSettings();
|
||||
cy.findByTestId("rs-login-tab").click();
|
||||
realmSettingsPage.toggleSwitch(realmSettingsPage.userRegSwitch);
|
||||
|
@ -127,7 +126,7 @@ describe("Realm settings tests", () => {
|
|||
realmSettingsPage.toggleSwitch(realmSettingsPage.rememberMeSwitch);
|
||||
});
|
||||
|
||||
it("Check login tab values", () => {
|
||||
it.skip("Check login tab values", () => {
|
||||
sidebarPage.goToRealmSettings();
|
||||
cy.findByTestId("rs-login-tab").click();
|
||||
|
||||
|
@ -135,7 +134,6 @@ describe("Realm settings tests", () => {
|
|||
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", () => {
|
||||
sidebarPage.goToRealmSettings();
|
||||
|
@ -178,30 +176,24 @@ describe("Realm settings tests", () => {
|
|||
|
||||
describe("Events tab", () => {
|
||||
const listingPage = new ListingPage();
|
||||
|
||||
it("Enable user events", () => {
|
||||
cy.intercept("GET", `/auth/admin/realms/${realmName}/keys`).as("load");
|
||||
sidebarPage.goToRealmSettings();
|
||||
cy.findByTestId("rs-realm-events-tab").click();
|
||||
cy.findByTestId("rs-events-tab").click();
|
||||
cy.wait(["@load"]);
|
||||
|
||||
realmSettingsPage
|
||||
.toggleSwitch(realmSettingsPage.enableEvents)
|
||||
.save(realmSettingsPage.eventsUserSave);
|
||||
masthead.checkNotificationMessage("Successfully saved configuration");
|
||||
|
||||
realmSettingsPage.clearEvents("user");
|
||||
|
||||
modalUtils
|
||||
.checkModalMessage(
|
||||
"If you clear all events of this realm, all records will be permanently cleared in the database"
|
||||
)
|
||||
.confirmModal();
|
||||
|
||||
masthead.checkNotificationMessage("The user events have been cleared");
|
||||
|
||||
const events = ["Client info", "Client info error"];
|
||||
|
||||
cy.intercept("GET", `/auth/admin/realms/${realmName}/events/config`).as(
|
||||
"fetchConfig"
|
||||
);
|
||||
|
@ -209,7 +201,6 @@ describe("Realm settings tests", () => {
|
|||
masthead.checkNotificationMessage("Successfully saved configuration");
|
||||
cy.wait(["@fetchConfig"]);
|
||||
sidebarPage.waitForPageLoad();
|
||||
|
||||
for (const event of events) {
|
||||
listingPage.searchItem(event, false).itemExist(event);
|
||||
}
|
||||
|
@ -439,6 +430,38 @@ describe("Realm settings tests", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("Realm settings events tab tests", () => {
|
||||
beforeEach(() => {
|
||||
keycloakBefore();
|
||||
loginPage.logIn();
|
||||
sidebarPage.goToRealmSettings();
|
||||
cy.findByTestId("rs-realm-events-tab").click();
|
||||
cy.findByTestId("rs-event-listeners-tab").click();
|
||||
});
|
||||
|
||||
it("Should display event listeners form", () => {
|
||||
realmSettingsPage.shouldDisplayEventListenersForm();
|
||||
});
|
||||
|
||||
it("Should revert saving event listener", () => {
|
||||
realmSettingsPage.shouldRevertSavingEventListener();
|
||||
});
|
||||
|
||||
it("Should save event listener", () => {
|
||||
realmSettingsPage.shouldSaveEventListener();
|
||||
});
|
||||
|
||||
it("Should remove event from event listener", () => {
|
||||
realmSettingsPage.shouldRemoveEventFromEventListener();
|
||||
});
|
||||
|
||||
it("Should remove all events from event listener and re-save original", () => {
|
||||
realmSettingsPage.shouldSaveEventListener();
|
||||
realmSettingsPage.shouldRemoveAllEventListeners();
|
||||
realmSettingsPage.shouldReSaveEventListener();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Realm settings client profiles tab tests", () => {
|
||||
beforeEach(() => {
|
||||
keycloakBefore();
|
||||
|
@ -611,9 +634,9 @@ describe("Realm settings tests", () => {
|
|||
});
|
||||
|
||||
/* it("Check saving changed JSON policies", () => {
|
||||
realmSettingsPage.shouldSaveChangedJSONPolicies();
|
||||
realmSettingsPage.shouldDeleteClientPolicyDialog();
|
||||
}); */
|
||||
realmSettingsPage.shouldSaveChangedJSONPolicies();
|
||||
realmSettingsPage.shouldDeleteClientPolicyDialog();
|
||||
}); */
|
||||
|
||||
it("Should not create duplicate client profile", () => {
|
||||
realmSettingsPage.shouldCompleteAndCreateNewClientPolicyFromEmptyState();
|
||||
|
|
|
@ -40,14 +40,14 @@ export default class UserEventsTab {
|
|||
|
||||
shouldDoSearchAndRemoveChips() {
|
||||
cy.findByTestId(this.searchEventDrpDwnBtn).click();
|
||||
cy.get(this.eventTypeInputFld).type("LOGIN");
|
||||
cy.get(this.eventTypeOption).contains("LOGIN").click();
|
||||
cy.get(this.eventTypeInputFld).type("LOGOUT");
|
||||
cy.get(this.eventTypeOption).contains("LOGOUT").click();
|
||||
|
||||
cy.intercept("/auth/admin/realms/master/events*").as("eventsFetch");
|
||||
cy.findByTestId(this.searchEventsBtn).click();
|
||||
cy.wait("@eventsFetch");
|
||||
|
||||
cy.get("table").contains("td", "LOGIN");
|
||||
cy.get("table").contains("td", "LOGOUT");
|
||||
cy.get("table").should("not.have.text", "CODE_TO_TOKEN");
|
||||
cy.get("table").should("not.have.text", "CODE_TO_TOKEN_ERROR");
|
||||
cy.get("table").should("not.have.text", "LOGIN_ERROR");
|
||||
|
@ -55,7 +55,7 @@ export default class UserEventsTab {
|
|||
|
||||
cy.get("[id^=remove_group]").click();
|
||||
cy.wait("@eventsFetch");
|
||||
cy.get("table").should("be.visible").contains("td", "LOGIN");
|
||||
cy.get("table").should("be.visible").contains("td", "LOGOUT");
|
||||
}
|
||||
|
||||
shouldHaveSearchBtnEnabled() {
|
||||
|
|
|
@ -196,6 +196,16 @@ export default class RealmSettingsPage {
|
|||
private addConditionSaveBtn = "addCondition-saveBtn";
|
||||
private conditionTypeLink = "condition-type-link";
|
||||
private addValue = "addValue";
|
||||
private eventListenersFormLabel = ".pf-c-form__label-text";
|
||||
private eventListenersDrpDwn = ".pf-c-select.kc_eventListeners_select";
|
||||
private eventListenersSaveBtn = "saveEventListenerBtn";
|
||||
private eventListenersRevertBtn = "revertEventListenerBtn";
|
||||
private eventListenersInputFld =
|
||||
".pf-c-form-control.pf-c-select__toggle-typeahead";
|
||||
private eventListenersDrpDwnOption = ".pf-c-select__menu-item";
|
||||
private eventListenersDrwDwnSelect =
|
||||
".pf-c-button.pf-c-select__toggle-button.pf-m-plain";
|
||||
private eventListenerRemove = '[data-ouia-component-id="Remove"]';
|
||||
|
||||
selectLoginThemeType(themeType: string) {
|
||||
cy.get(this.selectLoginTheme).click();
|
||||
|
@ -505,6 +515,58 @@ export default class RealmSettingsPage {
|
|||
return this;
|
||||
}
|
||||
|
||||
shouldDisplayEventListenersForm() {
|
||||
cy.get(this.eventListenersFormLabel)
|
||||
.should("be.visible")
|
||||
.contains("Event listeners");
|
||||
cy.get(this.eventListenersDrpDwn).should("exist");
|
||||
cy.findByTestId(this.eventListenersSaveBtn).should("exist");
|
||||
cy.findAllByTestId(this.eventListenersRevertBtn).should("exist");
|
||||
}
|
||||
|
||||
shouldRevertSavingEventListener() {
|
||||
cy.get(this.eventListenersInputFld).click().type("email");
|
||||
cy.get(this.eventListenersDrpDwnOption).click();
|
||||
cy.get(this.eventListenersDrwDwnSelect).click();
|
||||
cy.findByTestId(this.eventListenersRevertBtn).click();
|
||||
cy.get(this.eventListenersDrpDwn).should("not.have.text", "email");
|
||||
}
|
||||
|
||||
shouldSaveEventListener() {
|
||||
cy.get(this.eventListenersInputFld).click().type("email");
|
||||
cy.get(this.eventListenersDrpDwnOption).click();
|
||||
cy.get(this.eventListenersDrwDwnSelect).click();
|
||||
cy.findByTestId(this.eventListenersSaveBtn).click();
|
||||
cy.get(this.alertMessage).should(
|
||||
"be.visible",
|
||||
"Event listener has been updated."
|
||||
);
|
||||
}
|
||||
|
||||
shouldRemoveEventFromEventListener() {
|
||||
cy.get(this.eventListenerRemove).first().click();
|
||||
cy.findByTestId(this.eventListenersSaveBtn).click();
|
||||
cy.get(this.alertMessage).should(
|
||||
"be.visible",
|
||||
"Event listener has been updated."
|
||||
);
|
||||
cy.get(this.eventListenersDrpDwn).should("not.have.text", "jboss-logging");
|
||||
}
|
||||
|
||||
shouldRemoveAllEventListeners() {
|
||||
cy.get(".pf-c-button.pf-m-plain.pf-c-select__toggle-clear").click();
|
||||
cy.findByTestId(this.eventListenersSaveBtn).click();
|
||||
cy.get(this.eventListenersDrpDwn).should("not.have.text", "jboss-logging");
|
||||
cy.get(this.eventListenersDrpDwn).should("not.have.text", "email");
|
||||
}
|
||||
|
||||
shouldReSaveEventListener() {
|
||||
cy.get(this.eventListenersInputFld).click().type("jboss-logging");
|
||||
cy.get(this.eventListenersDrpDwnOption).click();
|
||||
cy.get(this.eventListenersDrwDwnSelect).click();
|
||||
cy.findByTestId(this.eventListenersSaveBtn).click();
|
||||
}
|
||||
|
||||
shouldDisplayProfilesTab() {
|
||||
cy.findByTestId(this.createProfileBtn).should("exist");
|
||||
cy.findByTestId(this.formViewSelect).should("exist");
|
||||
|
|
|
@ -247,4 +247,8 @@ article.pf-c-card.pf-m-flat.kc-login-settings-template
|
|||
|
||||
.kc-conditionType-trash-icon:hover {
|
||||
filter: brightness(55%);
|
||||
}
|
||||
|
||||
.kc_eventListeners_select {
|
||||
width: 35rem;
|
||||
}
|
113
src/realm-settings/event-config/EventListenersForm.tsx
Normal file
113
src/realm-settings/event-config/EventListenersForm.tsx
Normal file
|
@ -0,0 +1,113 @@
|
|||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, UseFormMethods } from "react-hook-form";
|
||||
import {
|
||||
ActionGroup,
|
||||
Button,
|
||||
FormGroup,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
} from "@patternfly/react-core";
|
||||
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
||||
|
||||
type EventListenersFormProps = {
|
||||
form: UseFormMethods;
|
||||
reset: () => void;
|
||||
};
|
||||
|
||||
export const EventListenersForm = ({
|
||||
form,
|
||||
reset,
|
||||
}: EventListenersFormProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const {
|
||||
control,
|
||||
formState: { isDirty },
|
||||
} = form;
|
||||
|
||||
const [selectEventListenerOpen, setSelectEventListenerOpen] = useState(false);
|
||||
const serverInfo = useServerInfo();
|
||||
const eventListeners = serverInfo.providers?.eventsListener.providers;
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormGroup
|
||||
hasNoPaddingTop
|
||||
label={t("eventListeners")}
|
||||
fieldId={"kc-eventListeners"}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("eventListenersHelpText")}
|
||||
forLabel={t("eventListeners")}
|
||||
forID={t(`common:helpLabel`, { label: t("eventListeners") })}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="eventsListeners"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({
|
||||
onChange,
|
||||
value,
|
||||
}: {
|
||||
onChange: (newValue: string[]) => void;
|
||||
value: string[];
|
||||
}) => (
|
||||
<Select
|
||||
name="eventsListeners"
|
||||
className="kc_eventListeners_select"
|
||||
data-testid="eventListeners-select"
|
||||
chipGroupProps={{
|
||||
numChips: 3,
|
||||
expandedText: t("common:hide"),
|
||||
collapsedText: t("common:showRemaining"),
|
||||
}}
|
||||
variant={SelectVariant.typeaheadMulti}
|
||||
typeAheadAriaLabel="Select"
|
||||
onToggle={(isOpen) => setSelectEventListenerOpen(isOpen)}
|
||||
selections={value}
|
||||
onSelect={(_, selectedValue) => {
|
||||
const option = selectedValue.toString();
|
||||
const changedValue = value.includes(option)
|
||||
? value.filter((item) => item !== option)
|
||||
: [...value, option];
|
||||
onChange(changedValue);
|
||||
}}
|
||||
onClear={(operation) => {
|
||||
operation.stopPropagation();
|
||||
onChange([]);
|
||||
}}
|
||||
isOpen={selectEventListenerOpen}
|
||||
aria-labelledby={"eventsListeners"}
|
||||
>
|
||||
{Object.keys(eventListeners!).map((event) => (
|
||||
<SelectOption key={event} value={event} />
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<ActionGroup>
|
||||
<Button
|
||||
variant="primary"
|
||||
type="submit"
|
||||
data-testid={"saveEventListenerBtn"}
|
||||
isDisabled={!isDirty}
|
||||
>
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button
|
||||
variant="link"
|
||||
data-testid={"revertEventListenerBtn"}
|
||||
onClick={reset}
|
||||
>
|
||||
{t("common:revert")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -20,6 +20,7 @@ import { EventConfigForm, EventsType } from "./EventConfigForm";
|
|||
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
|
||||
import { EventsTypeTable, EventType } from "./EventsTypeTable";
|
||||
import { AddEventTypesDialog } from "./AddEventTypesDialog";
|
||||
import { EventListenersForm } from "./EventListenersForm";
|
||||
|
||||
export const EventsTab = () => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
|
@ -31,7 +32,7 @@ export const EventsTab = () => {
|
|||
const [tableKey, setTableKey] = useState(0);
|
||||
const reload = () => setTableKey(new Date().getTime());
|
||||
|
||||
const [activeTab, setActiveTab] = useState("user");
|
||||
const [activeTab, setActiveTab] = useState("event");
|
||||
const [events, setEvents] = useState<RealmEventsConfigRepresentation>();
|
||||
const [type, setType] = useState<EventsType>();
|
||||
const [addEventType, setAddEventType] = useState(false);
|
||||
|
@ -85,12 +86,25 @@ export const EventsTab = () => {
|
|||
);
|
||||
|
||||
const save = async (eventConfig: RealmEventsConfigRepresentation) => {
|
||||
const updatedEventListener =
|
||||
events?.eventsListeners !== eventConfig.eventsListeners;
|
||||
|
||||
try {
|
||||
await adminClient.realms.updateConfigEvents({ realm }, eventConfig);
|
||||
setupForm({ ...events, ...eventConfig });
|
||||
addAlert(t("eventConfigSuccessfully"), AlertVariant.success);
|
||||
addAlert(
|
||||
updatedEventListener
|
||||
? t("realm-settings:saveEventListenersSuccess")
|
||||
: t("realm-settings:eventConfigSuccessfully"),
|
||||
AlertVariant.success
|
||||
);
|
||||
} catch (error) {
|
||||
addError("realm-settings:eventConfigError", error);
|
||||
addError(
|
||||
updatedEventListener
|
||||
? t("realm-settings:saveEventListenersError")
|
||||
: t("realm-settings:eventConfigError"),
|
||||
error
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -122,6 +136,21 @@ export const EventsTab = () => {
|
|||
activeKey={activeTab}
|
||||
onSelect={(_, key) => setActiveTab(key as string)}
|
||||
>
|
||||
<Tab
|
||||
eventKey="event"
|
||||
title={<TabTitleText>{t("eventListeners")}</TabTitleText>}
|
||||
data-testid="rs-event-listeners-tab"
|
||||
>
|
||||
<PageSection>
|
||||
<FormAccess
|
||||
role="manage-events"
|
||||
isHorizontal
|
||||
onSubmit={handleSubmit(save)}
|
||||
>
|
||||
<EventListenersForm form={form} reset={() => setupForm(events)} />
|
||||
</FormAccess>
|
||||
</PageSection>
|
||||
</Tab>
|
||||
<Tab
|
||||
eventKey="user"
|
||||
title={<TabTitleText>{t("userEventsSettings")}</TabTitleText>}
|
||||
|
|
|
@ -32,6 +32,12 @@ export default {
|
|||
login: "Login",
|
||||
themes: "Themes",
|
||||
events: "Events",
|
||||
eventListeners: "Event listeners",
|
||||
eventListenersHelpText:
|
||||
"Configure what listeners receive events for the realm.",
|
||||
saveEventListeners: "Save Event Listeners",
|
||||
saveEventListenersSuccess: "Event listener has been updated.",
|
||||
saveEventListenersError: "Error saving event listener: {{error}}",
|
||||
userEventsConfig: "User events configuration",
|
||||
userEventsSettings: "User events settings",
|
||||
adminEventsConfig: "Admin events configuration",
|
||||
|
|
Loading…
Reference in a new issue