Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
349 changes: 349 additions & 0 deletions packages/fiori/cypress/specs/UserMenu.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -988,3 +988,352 @@ describe("Footer configuration", () => {
cy.get("@signOutClicked").should("have.been.calledOnce");
});
});

describe("UserMenuItem", () => {
describe("showSelection property", () => {
it("renders two-line layout when showSelection is true and sub-item is checked", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItem text="Theme" showSelection={true}>
<UserMenuItemGroup checkMode="Single">
<UserMenuItem text="Light" checked={true}></UserMenuItem>
<UserMenuItem text="Dark"></UserMenuItem>
</UserMenuItemGroup>
</UserMenuItem>
</UserMenu>
</>
);

cy.get("[ui5-user-menu]").find("[ui5-user-menu-item][text='Theme']").as("themeItem");
cy.get("@themeItem")
.shadow()
.find(".ui5-user-menu-item-text-wrapper")
.should("exist");
cy.get("@themeItem")
.shadow()
.find(".ui5-user-menu-item-selection-text")
.should("exist")
.and("contain.text", "Light");
});

it("does not render selection text when showSelection is false", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItem text="Settings">
<UserMenuItemGroup checkMode="Single">
<UserMenuItem text="Option A" checked={true}></UserMenuItem>
</UserMenuItemGroup>
</UserMenuItem>
</UserMenu>
</>
);

cy.get("[ui5-user-menu]").find("[ui5-user-menu-item][text='Settings']").as("settingsItem");
cy.get("@settingsItem")
.shadow()
.find(".ui5-user-menu-item-text-wrapper")
.should("not.exist");
cy.get("@settingsItem")
.shadow()
.find(".ui5-user-menu-item-selection-text")
.should("not.exist");
});

it("does not render selection text when no sub-item is checked", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItem text="Theme" showSelection={true}>
<UserMenuItemGroup checkMode="Single">
<UserMenuItem text="Light"></UserMenuItem>
<UserMenuItem text="Dark"></UserMenuItem>
</UserMenuItemGroup>
</UserMenuItem>
</UserMenu>
</>
);

cy.get("[ui5-user-menu]").find("[ui5-user-menu-item][text='Theme']").as("themeItem");
cy.get("@themeItem")
.shadow()
.find(".ui5-user-menu-item-text-wrapper")
.should("exist");
cy.get("@themeItem")
.shadow()
.find(".ui5-user-menu-item-selection-text")
.should("not.exist");
});

it("updates selection text when a different sub-item is checked", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItem text="Theme" showSelection={true}>
<UserMenuItemGroup checkMode="Single">
<UserMenuItem text="Light" checked={true}></UserMenuItem>
<UserMenuItem text="Dark"></UserMenuItem>
<UserMenuItem text="High Contrast"></UserMenuItem>
</UserMenuItemGroup>
</UserMenuItem>
</UserMenu>
</>
);

cy.get("[ui5-user-menu]").find("[ui5-user-menu-item][text='Theme']").as("themeItem");
cy.get("@themeItem")
.shadow()
.find(".ui5-user-menu-item-selection-text")
.should("contain.text", "Light");

cy.get("@themeItem").click();

cy.get("[ui5-user-menu-item][text='Dark']").click();

cy.get("@themeItem")
.shadow()
.find(".ui5-user-menu-item-selection-text")
.should("contain.text", "Dark");
});
});

describe("Single-select behavior", () => {
it("prevents unchecking the only checked item in single-select mode", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItem text="Theme" showSelection={true}>
<UserMenuItemGroup checkMode="Single">
<UserMenuItem text="Light" checked={true}></UserMenuItem>
<UserMenuItem text="Dark"></UserMenuItem>
</UserMenuItemGroup>
</UserMenuItem>
</UserMenu>
</>
);

cy.get("[ui5-user-menu]").find("[ui5-user-menu-item][text='Theme']").as("themeItem");
cy.get("@themeItem").click();

cy.get("[ui5-user-menu-item][text='Light']").click();

cy.get("[ui5-user-menu-item][text='Light']")
.should("have.attr", "checked");
});

it("allows unchecking in single-select mode when showSelection is false", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItem text="Options">
<UserMenuItemGroup checkMode="Single">
<UserMenuItem text="Opt A" checked={true}></UserMenuItem>
<UserMenuItem text="Opt B"></UserMenuItem>
</UserMenuItemGroup>
</UserMenuItem>
</UserMenu>
</>
);

cy.get("[ui5-user-menu]").find("[ui5-user-menu-item][text='Options']").as("parentItem");
cy.get("@parentItem").click();

cy.get("[ui5-user-menu-item][text='Opt A']").click();

cy.get("[ui5-user-menu-item][text='Opt A']")
.should("not.have.attr", "checked");
});
});

describe("UserMenuItemGroup", () => {
it("renders items within a group with Single check mode", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItemGroup checkMode="Single">
<UserMenuItem text="Option 1" checked={true}></UserMenuItem>
<UserMenuItem text="Option 2"></UserMenuItem>
</UserMenuItemGroup>
</UserMenu>
</>
);

cy.get("[ui5-user-menu]").find("[ui5-user-menu-item-group]").should("exist");
cy.get("[ui5-user-menu-item-group]").should("have.attr", "check-mode", "Single");
cy.get("[ui5-user-menu-item]").should("have.length", 2);
});

it("renders items within a group with Multiple check mode", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItemGroup checkMode="Multiple">
<UserMenuItem text="Feature A" checked={true}></UserMenuItem>
<UserMenuItem text="Feature B" checked={true}></UserMenuItem>
<UserMenuItem text="Feature C"></UserMenuItem>
</UserMenuItemGroup>
</UserMenu>
</>
);

cy.get("[ui5-user-menu]").find("[ui5-user-menu-item-group]").should("exist");
cy.get("[ui5-user-menu-item-group]").should("have.attr", "check-mode", "Multiple");
cy.get("[ui5-user-menu-item]").should("have.length", 3);
cy.get("[ui5-user-menu-item][text='Feature A']").should("have.attr", "checked");
cy.get("[ui5-user-menu-item][text='Feature B']").should("have.attr", "checked");
cy.get("[ui5-user-menu-item][text='Feature C']").should("not.have.attr", "checked");
});

it("fires ui5-check event when item is checked in a group", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItemGroup checkMode="Single">
<UserMenuItem text="Item 1"></UserMenuItem>
<UserMenuItem text="Item 2"></UserMenuItem>
</UserMenuItemGroup>
</UserMenu>
</>
);

cy.get("[ui5-user-menu]").as("userMenu");
cy.get("@userMenu")
.then($userMenu => {
$userMenu.get(0).addEventListener("ui5-check", cy.stub().as("checked"));
});

cy.get("[ui5-user-menu-item]").first().click();

cy.get("@checked").should("have.been.calledOnce");
});
});

describe("CSS styling", () => {
it("has show-selection attribute when showSelection is true", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItem text="Theme" showSelection={true}>
<UserMenuItemGroup checkMode="Single">
<UserMenuItem text="Light" checked={true}></UserMenuItem>
<UserMenuItem text="Dark"></UserMenuItem>
</UserMenuItemGroup>
</UserMenuItem>
</UserMenu>
</>
);

cy.get("[ui5-user-menu-item][text='Theme']")
.should("have.attr", "show-selection");
});

it("does not have show-selection attribute when showSelection is false", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItem text="Settings"></UserMenuItem>
</UserMenu>
</>
);

cy.get("[ui5-user-menu-item][text='Settings']")
.should("not.have.attr", "show-selection");
});

it("selection text has correct styling", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItem text="Theme" showSelection={true}>
<UserMenuItemGroup checkMode="Single">
<UserMenuItem text="Light" checked={true}></UserMenuItem>
</UserMenuItemGroup>
</UserMenuItem>
</UserMenu>
</>
);

cy.get("[ui5-user-menu-item][text='Theme']")
.shadow()
.find(".ui5-user-menu-item-selection-text")
.should("have.css", "font-weight", "400")
.and("have.css", "white-space", "nowrap")
.and("have.css", "overflow", "hidden")
.and("have.css", "text-overflow", "ellipsis");
});

it("text wrapper has column layout with gap", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItem text="Theme" showSelection={true}>
<UserMenuItemGroup checkMode="Single">
<UserMenuItem text="Light" checked={true}></UserMenuItem>
</UserMenuItemGroup>
</UserMenuItem>
</UserMenu>
</>
);

cy.get("[ui5-user-menu-item][text='Theme']")
.shadow()
.find(".ui5-user-menu-item-text-wrapper")
.should("have.css", "flex-direction", "column")
.and("have.css", "gap", "4px");
});
});

describe("Nested submenu items", () => {
it("renders nested UserMenuItem hierarchy", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItem text="Legal Information">
<UserMenuItem text="Privacy Policy"></UserMenuItem>
<UserMenuItem text="Terms of Use"></UserMenuItem>
</UserMenuItem>
</UserMenu>
</>
);

cy.get("[ui5-user-menu]").find("[ui5-user-menu-item][text='Legal Information']").as("parentItem");
cy.get("@parentItem").find("[ui5-user-menu-item]").should("have.length", 2);
});

it("does not show selection text for non-single-select groups", () => {
cy.mount(
<>
<Button id="openUserMenuBtn">Open User Menu</Button>
<UserMenu open={true} opener="openUserMenuBtn">
<UserMenuItem text="Features" showSelection={true}>
<UserMenuItemGroup checkMode="Multiple">
<UserMenuItem text="Feature A" checked={true}></UserMenuItem>
<UserMenuItem text="Feature B" checked={true}></UserMenuItem>
</UserMenuItemGroup>
</UserMenuItem>
</UserMenu>
</>
);

cy.get("[ui5-user-menu-item][text='Features']")
.shadow()
.find(".ui5-user-menu-item-selection-text")
.should("not.exist");
});
});
});
6 changes: 3 additions & 3 deletions packages/fiori/src/NavigationMenuItemTemplate.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import type NavigationMenuItem from "./NavigationMenuItem.js";
import MenuItemTemplate from "@ui5/webcomponents/dist/MenuItemTemplate.js";
import type { MenuItemHooks } from "@ui5/webcomponents/dist/MenuItemTemplate.js";
import Icon from "@ui5/webcomponents/dist/Icon.js";
import slimArrowRightIcon from "@ui5/webcomponents-icons/dist/slim-arrow-right.js";
import arrowRightIcon from "@ui5/webcomponents-icons/dist/arrow-right.js";
import type { ListItemHooks } from "@ui5/webcomponents/dist/ListItemTemplate.js";

const predefinedHooks: Partial<ListItemHooks> = {
const predefinedHooks: Partial<MenuItemHooks> = {
listItemContent,
iconBegin,
iconEnd,
};

export default function NavigationMenuItemTemplate(this: NavigationMenuItem, hooks?: Partial<ListItemHooks>) {
export default function NavigationMenuItemTemplate(this: NavigationMenuItem, hooks?: Partial<MenuItemHooks>) {
const currentHooks = { ...predefinedHooks, ...hooks, };

return <>
Expand Down
Loading
Loading