From f816dbcc91ec96865582e15c6984a328dd69be5a Mon Sep 17 00:00:00 2001 From: Nikola Anachkov Date: Mon, 30 Jun 2025 12:59:46 +0300 Subject: [PATCH 1/6] chore(ui5-avatar): migrate wdio tests to cypress --- packages/main/cypress/specs/Avatar.cy.tsx | 186 +++++++++++++++++++++- packages/main/test/specs/Avatar.spec.js | 156 ------------------ 2 files changed, 183 insertions(+), 159 deletions(-) delete mode 100644 packages/main/test/specs/Avatar.spec.js diff --git a/packages/main/cypress/specs/Avatar.cy.tsx b/packages/main/cypress/specs/Avatar.cy.tsx index ce6689467345..69b423778716 100644 --- a/packages/main/cypress/specs/Avatar.cy.tsx +++ b/packages/main/cypress/specs/Avatar.cy.tsx @@ -39,9 +39,9 @@ describe("Accessibility", () => { cy.mount(
- - - + + +
@@ -306,3 +306,183 @@ describe("Fallback Logic", () => { .should("have.class", "ui5-avatar-fallback-icon-hidden"); }); }); + +describe("Avatar", () => { + let sharedInputValue = 0; + let sharedInputValue2 = 0; + + beforeEach(() => { + cy.mount( +
+ + Woman image + + + + Woman image + + + + + + + + + + +
+ ); + + cy.get("#interactive-avatar").then(($avatar) => { + $avatar[0].addEventListener("ui5-click", function() { + const input = document.getElementById("click-event") as HTMLInputElement; + input.value = `${++sharedInputValue}`; + }); + }); + + cy.get("#non-interactive-avatar").then(($avatar) => { + $avatar[0].addEventListener("ui5-click", function() { + const input = document.getElementById("click-event") as HTMLInputElement; + input.value = `${++sharedInputValue}`; + }); + }); + + cy.get("#myInteractiveAvatar").then(($avatar) => { + $avatar[0].addEventListener("ui5-click", function() { + const input = document.getElementById("click-event-2") as HTMLInputElement; + input.value = `${++sharedInputValue2}`; + }); + }); + }); + + it("tests rendering of image", () => { + cy.get("#myAvatar1") + .shadow() + .find('slot:not([name="badge"])') + .should("exist"); + + cy.get("#myAvatar1") + .shadow() + .find("ui5-avatar-icon") + .should("not.exist"); + }); + + it("tests rendering of icon", () => { + cy.get("#myAvatar2") + .shadow() + .find(".ui5-avatar-icon") + .should("exist"); + + cy.get("#myAvatar2") + .shadow() + .find('slot:not([name="badge"])') + .should("not.exist"); + }); + + it("tests rendering of image, when all set", () => { + cy.get("#myAvatar3") + .shadow() + .find('slot:not([name="badge"])') + .should("exist"); + + cy.get("#myAvatar3") + .shadow() + .find(".ui5-avatar-icon") + .should("not.exist"); + + cy.get("#myAvatar3") + .shadow() + .find(".ui5-avatar-initials") + .should("not.exist"); + }); + + it("tests rendering of initials", () => { + cy.get("#myAvatar4") + .shadow() + .find(".ui5-avatar-initials") + .should("exist"); + }); + + it("tests rendering of accented characters", () => { + cy.get("#myAvatar6") + .shadow() + .find(".ui5-avatar-initials") + .should("exist"); + }); + + it("tests rendering of default fallback icon when initials are overflowing", () => { + cy.get("#myAvatar5") + .shadow() + .find(".ui5-avatar-icon") + .should("exist") + .should("have.attr", "name", "employee"); + }); + + it("tests rendering of custom fallback icon when initials are overflowing", () => { + cy.get("#myAvatar7") + .shadow() + .find(".ui5-avatar-icon-fallback") + .should("exist") + .should("have.attr", "name", "alert"); + }); + + it("Tests noConflict 'ui5-click' event for interactive avatars", () => { + cy.get("#interactive-avatar") + .shadow() + .find(".ui5-avatar-root") + .realClick(); + + cy.get("#click-event") + .should("have.value", "1"); + + cy.get("#interactive-avatar") + .shadow() + .find(".ui5-avatar-root") + .realPress("Enter"); + + cy.get("#click-event") + .should("have.value", "2"); + + cy.get("#interactive-avatar") + .shadow() + .find(".ui5-avatar-root") + .realPress("Space"); + + cy.get("#click-event") + .should("have.value", "3"); + }); + + it("Tests noConflict 'ui5-click' event for non interactive avatars", () => { + cy.get("#non-interactive-avatar") + .shadow() + .find(".ui5-avatar-root") + .realClick(); + + cy.get("#click-event") + .should("have.value", "4"); + + cy.get("#non-interactive-avatar") + .shadow() + .find(".ui5-avatar-root") + .realPress("Enter"); + + cy.get("#click-event") + .should("have.value", "4"); + + cy.get("#non-interactive-avatar") + .shadow() + .find(".ui5-avatar-root") + .realPress("Space"); + + cy.get("#click-event") + .should("have.value", "4"); + }); + + it("Tests native 'click' event thrown", () => { + cy.get("#myInteractiveAvatar") + .realClick(); + + cy.get("#click-event-2") + .should("have.value", "1"); + }); +}); \ No newline at end of file diff --git a/packages/main/test/specs/Avatar.spec.js b/packages/main/test/specs/Avatar.spec.js deleted file mode 100644 index 8dc0b0214b3a..000000000000 --- a/packages/main/test/specs/Avatar.spec.js +++ /dev/null @@ -1,156 +0,0 @@ -import { assert } from "chai"; - -describe("Avatar", () => { - before(async () => { - await browser.url(`test/pages/Avatar.html`); - }); - - it("tests rendering of image", async () => { - const avatar = await browser.$("#myAvatar1"); - const image = await avatar.shadow$('slot:not([name="badge"])'); - const icon = await avatar.shadow$("ui5-avatar-icon"); - - // img tag is rendered, ui5-icon - not - assert.ok(await image.isExisting(), "img is rendered"); - assert.notOk(await icon.isExisting(), "icon is not rendered"); - }); - - it("tests rendering of icon", async () => { - const avatar = await browser.$("#myAvatar2"); - const image = await avatar.shadow$('slot:not([name="badge"])'); - const icon = await avatar.shadow$(".ui5-avatar-icon"); - - // ui5-icon tag is rendered, img - not - assert.notOk(await image.isExisting(), "img is not rendered"); - assert.ok(await icon.isExisting(), "icon is rendered"); - }); - - it("tests rendering of image, when all set", async () => { - const avatar = await browser.$("#myAvatar3"); - const image = await avatar.shadow$('slot:not([name="badge"])'); - const icon = await avatar.shadow$(".ui5-avatar-icon"); - const initials = await avatar.shadow$(".ui5-avatar-initials"); - - // ui5-icon tag is rendered, img - not - assert.ok(await image.isExisting(), "img is rendered"); - assert.notOk(await icon.isExisting(), "icon is not rendered"); - assert.notOk(await initials.isExisting(), "initials are not rendered"); - }); - - it("tests rendering of initials", async () => { - const avatar = await browser.$("#myAvatar4"); - const initials = await avatar.shadow$(".ui5-avatar-initials"); - - // initials are rendered - assert.ok(await initials.isExisting(), "initials are rendered"); - }); - - it("tests rendering of accented characters", async () => { - const avatar = await browser.$("#myAvatar6"); - const initials = await avatar.shadow$(".ui5-avatar-initials"); - - // initials are rendered - assert.ok(await initials.isExisting(), "initials are rendered"); - }); - - it("tests rendering of default fallback icon when initials are overflowing ", async () => { - const avatar = await browser.$("#myAvatar5"); - const icon = await avatar.shadow$(".ui5-avatar-icon"); - const iconName = await icon.getAttribute("name"); - - // icon is rendered - assert.ok(await icon.isExisting(), "icon should be rendered, when the initials are overflowing"); - assert.strictEqual(await iconName, "employee", "the default fallback icon is renderen"); - - }); - - it("tests rendering of custom fallback icon when initials are overflowing ", async () => { - const avatar = await browser.$("#myAvatar7"); - const fbIcon = await avatar.shadow$(".ui5-avatar-icon-fallback"); - const fbIconName = await fbIcon.getAttribute("name"); - - // icon is rendered - assert.ok(await fbIcon.isExisting(), "fallback icon should be rendered, when it is set and the initials are overflowing"); - assert.strictEqual(await fbIconName, "alert", "the custom fallback icon is renderen"); - - }); - - it("Tests noConflict 'ui5-click' event for interactive avatars", async () => { - const avatarRoot = await browser.$("#interactive-avatar").shadow$(".ui5-avatar-root"); - const input = await browser.$("#click-event"); - - await avatarRoot.click(); - assert.strictEqual(await input.getAttribute("value"), "1", "Mouse click throws event"); - - await avatarRoot.keys("Enter"); - assert.strictEqual(await input.getAttribute("value"), "2", "Enter throws event"); - - await avatarRoot.keys("Space"); - assert.strictEqual(await input.getAttribute("value"), "3", "Space throws event"); - }); - - it("Tests noConflict 'ui5-click' event for non interactive avatars", async () => { - const avatarRoot = await browser.$("#non-interactive-avatar").shadow$(".ui5-avatar-root");; - const input = await browser.$("#click-event"); - - await avatarRoot.click(); - assert.strictEqual(await input.getAttribute("value"), "4", "Mouse click thrown"); - - await avatarRoot.keys("Enter"); - assert.strictEqual(await input.getAttribute("value"), "4", "Enter does not throw event"); - - await avatarRoot.keys("Space"); - assert.strictEqual(await input.getAttribute("value"), "4", "Space does not throw event"); - }); - - it("Tests native 'click' event thrown", async () => { - await browser.executeAsync(function(done) { - window["sap-ui-webcomponents-bundle"].configuration.setNoConflict(false); - done(); - }); - - const avatar = await browser.$("#myInteractiveAvatar"); - const input = await browser.$("#click-event-2"); - - await avatar.click(); - assert.strictEqual(await input.getAttribute("value"), "1", "Mouse click throws event"); - }); -}); - -describe("ARIA attributes", () => { - before(async () => { - await browser.url(`test/pages/Avatar.html`); - }); - - it ("role set correctly", async () => { - const avatar = await $("#myInteractiveAvatar");; - const avatarRoot = await avatar.shadow$(".ui5-avatar-root"); - const nonInteractiveAvatar = await $("#non-interactive-avatar");; - const nonInteractiveavatarRoot = await nonInteractiveAvatar.shadow$(".ui5-avatar-root"); - - assert.strictEqual(await avatarRoot.getAttribute("role"), "button", "should have role button for interactive avatar"); - - assert.strictEqual(await nonInteractiveavatarRoot.getAttribute("role"), "img", "should have role img for non-interactive avatar"); - }); - - it ("aria-haspopup is correct for interactive avatar", async () => { - const avatar = await $("#myInteractiveAvatar");; - const ariaHasPopup = await avatar.getProperty("_ariaHasPopup"); - - assert.strictEqual(ariaHasPopup, "menu", "should have aria-haspopup set"); - }); - - it ("aria-haspopup is correct for non-interactive avatar", async () => { - const avatar = await $("#non-interactive-avatar");; - const ariaHasPopup = await avatar.getProperty("_ariaHasPopup"); - - assert.notExists(ariaHasPopup, "should not have aria-haspopup set"); - }); - - it ("aria-label is correctly set", async () => { - const avatar = await $("#interactive-avatar"), - avatarRoot = avatar.shadow$(".ui5-avatar-root"); - - assert.equal(await avatarRoot.getAttribute("aria-label"), await avatar.getAttribute("accessible-name"), "aria-label should be set according to accessibleName property"); - }); -}); From be6a471e48a2b27896de523c62c3e2e96c8371c3 Mon Sep 17 00:00:00 2001 From: Nikola Anachkov Date: Mon, 30 Jun 2025 13:55:17 +0300 Subject: [PATCH 2/6] refactor: change the slot we need to find --- packages/main/cypress/specs/Avatar.cy.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/main/cypress/specs/Avatar.cy.tsx b/packages/main/cypress/specs/Avatar.cy.tsx index 69b423778716..051b1e381183 100644 --- a/packages/main/cypress/specs/Avatar.cy.tsx +++ b/packages/main/cypress/specs/Avatar.cy.tsx @@ -358,7 +358,7 @@ describe("Avatar", () => { it("tests rendering of image", () => { cy.get("#myAvatar1") .shadow() - .find('slot:not([name="badge"])') + .find("slot:not([name])") .should("exist"); cy.get("#myAvatar1") @@ -375,14 +375,14 @@ describe("Avatar", () => { cy.get("#myAvatar2") .shadow() - .find('slot:not([name="badge"])') + .find("slot:not([name])") .should("not.exist"); }); it("tests rendering of image, when all set", () => { cy.get("#myAvatar3") .shadow() - .find('slot:not([name="badge"])') + .find("slot:not([name])") .should("exist"); cy.get("#myAvatar3") From f1d373000fc2e6d4cde7c71cfaed693e57fc0a5b Mon Sep 17 00:00:00 2001 From: Nikola Anachkov Date: Mon, 30 Jun 2025 15:11:45 +0300 Subject: [PATCH 3/6] chore: migrate avatarGroup tests --- .../main/cypress/specs/AvatarGroup.cy.tsx | 307 ++++++++++++++++++ packages/main/test/specs/AvatarGroup.spec.js | 203 ------------ 2 files changed, 307 insertions(+), 203 deletions(-) delete mode 100644 packages/main/test/specs/AvatarGroup.spec.js diff --git a/packages/main/cypress/specs/AvatarGroup.cy.tsx b/packages/main/cypress/specs/AvatarGroup.cy.tsx index 0919ff327bdf..392ee1ffac9d 100644 --- a/packages/main/cypress/specs/AvatarGroup.cy.tsx +++ b/packages/main/cypress/specs/AvatarGroup.cy.tsx @@ -122,4 +122,311 @@ describe("Accessibility", () => { cy.get(`#${labelId}`).should("exist"); }); +}); + +describe("avatar-group rendering", () => { + beforeEach(() => { + cy.mount( +
+ + + + + + + + + + + + + + + + +
+ ); + + // Set up event listener for individual avatar group + cy.get("#avatar-group-individual").then(($avatarGroup) => { + $avatarGroup[0].addEventListener("ui5-click", function(event: CustomEvent) { + const eventTargetRef = document.getElementById("event-target") as HTMLInputElement; + const eventOverflowButtonClicked = document.getElementById("event-overflow-button-clicked") as HTMLInputElement; + + eventTargetRef.value = event.detail.targetRef.tagName; + eventOverflowButtonClicked.value = event.detail.overflowButtonClicked.toString(); + }); + }); + + // Set up event listener for group avatar group - SAME handler as individual + cy.get("#avatar-group-group").then(($avatarGroup) => { + $avatarGroup[0].addEventListener("ui5-click", function(event: CustomEvent) { + const eventTargetRef = document.getElementById("event-target") as HTMLInputElement; + const eventOverflowButtonClicked = document.getElementById("event-overflow-button-clicked") as HTMLInputElement; + + // For group type, use tagName + className + eventTargetRef.value = event.detail.targetRef.tagName + "." + event.detail.targetRef.className; + eventOverflowButtonClicked.value = event.detail.overflowButtonClicked.toString(); + }); + }); + + // Set up reset functionality + cy.get("#reset-btn").then(($btn) => { + $btn[0].addEventListener("click", function() { + (document.getElementById("event-target") as HTMLInputElement).value = ""; + (document.getElementById("event-overflow-button-clicked") as HTMLInputElement).value = ""; + }); + }); + }); + + it("tests if web component is correctly rendered", () => { + cy.get("#avatar-group-individual") + .shadow() + .find("div") + .should("exist"); + + cy.get("#avatar-group-group") + .shadow() + .find("div") + .should("exist"); + }); + + it("tests click event when avatar is clicked", () => { + cy.get("#reset-btn").realClick(); + cy.get("#avatar-1").realClick(); + + cy.get("#event-target") + .should("have.value", "UI5-AVATAR"); + + cy.get("#event-overflow-button-clicked") + .should("have.value", "false"); + }); + + it("tests click event when overflow button is clicked", () => { + cy.get("#reset-btn").realClick(); + + cy.get("#avatar-group-individual") + .shadow() + .find("ui5-button") + .realClick(); + + cy.get("#event-target") + .should("have.value", "UI5-BUTTON"); + + cy.get("#event-overflow-button-clicked") + .should("have.value", "true"); + }); + + it("tests click event avatar group with type group is clicked", () => { + cy.get("#reset-btn").realClick(); + + cy.get("#avatar-group-group") + .shadow() + .find(".ui5-avatar-group-items") + .realClick(); + + cy.get("#event-target") + .should("have.value", "DIV.ui5-avatar-group-items"); + + cy.get("#event-overflow-button-clicked") + .should("have.value", "false"); + }); + + it("tests if hiddenItems is correctly displayed in the overflow button", () => { + cy.viewport(200, 1080); + + cy.get("#avatar-group-individual") + .shadow() + .find("ui5-button") + .should("not.have.text", "") + .invoke("text") + .then((buttonText) => { + cy.get("#avatar-group-individual") + .then(($avatarGroup) => { + const avatarGroup = $avatarGroup[0] as AvatarGroup; + const hiddenItemsCount = avatarGroup.hiddenItems.length; + expect(buttonText).to.equal(`+${hiddenItemsCount}`); + }); + }); + }); + + it("tests if click event is firing only once", () => { + let eventCounter = 0; + + cy.mount( +
+ + + + + + + + + + + + + +
+ ); + + cy.get("#avatar-group-individual-events").then(($avatarGroup) => { + $avatarGroup[0].addEventListener("ui5-click", function() { + const eventAvatarsClicked = document.getElementById("event-avatars-clicked") as HTMLInputElement; + eventAvatarsClicked.value = (parseInt(eventAvatarsClicked.value) + 1).toString(); + }); + }); + + cy.get("#avatar-group-group-events").then(($avatarGroup) => { + $avatarGroup[0].addEventListener("ui5-click", function() { + const eventAvatarsClicked = document.getElementById("event-avatars-clicked") as HTMLInputElement; + eventAvatarsClicked.value = (parseInt(eventAvatarsClicked.value) + 1).toString(); + }); + }); + + cy.get("#avatar-1-test-events").realClick(); + cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); + + cy.get("#avatar-1-test-events").realPress("Enter"); + cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); + + cy.get("#avatar-1-test-events").realPress("Space"); + cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); + + cy.get("#avatar-group-individual-events") + .shadow() + .find("ui5-button") + .realClick(); + cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); + + cy.get("#avatar-group-individual-events") + .shadow() + .find("ui5-button") + .realPress("Enter"); + cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); + + cy.get("#avatar-group-individual-events") + .shadow() + .find("ui5-button") + .realPress("Space"); + cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); + + cy.get("#avatar-group-group-events").realClick(); + cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); + + cy.get("#avatar-group-group-events").realPress("Enter"); + cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); + + cy.get("#avatar-group-group-events").realPress("Space"); + cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); + }); +}); + +describe("ARIA attributes", () => { + describe("Type Individual", () => { + beforeEach(() => { + cy.mount( +
+ + + + + + + + + + +
+ ); + }); + + it("role is correct", () => { + cy.get("#avatar-group-individual") + .should("have.prop", "_role", "group"); + }); + + it("aria-haspopup is correct", () => { + cy.get("#avatar-group-individual").then(($avatarGroup) => { + ($avatarGroup[0] as any).accessibilityAttributes = { hasPopup: "menu" }; + }); + + + cy.get("#avatar-group-individual") + .then(($avatarGroup) => { + const avatarGroup = $avatarGroup[0] as AvatarGroup; + + expect(avatarGroup._containerAriaHasPopup).to.be.undefined; + + expect(avatarGroup._overflowButtonAccAttributes).to.exist; + expect(avatarGroup._overflowButtonAccAttributes.hasPopup).to.equal("menu"); + }); + }); + + it("aria-label is correct", () => { + cy.get("#avatar-group-individual") + .then(($avatarGroup) => { + const ariaLabel = ($avatarGroup[0] as AvatarGroup)._ariaLabelText; + expect(ariaLabel).to.include("Individual avatars"); + expect(ariaLabel).to.not.include("Show complete list"); + expect(ariaLabel).to.include("Press ARROW keys"); + }); + + cy.get("#avatar-group-individual") + .then(($avatarGroup) => { + const overflowButtonLabel = ($avatarGroup[0] as AvatarGroup)._overflowButtonAriaLabelText; + expect(overflowButtonLabel).to.include("Activate for complete list"); + }); + }); + }); + + describe("Type Group", () => { + beforeEach(() => { + cy.mount( + + + + + + ); + }); + + it("role is correct", () => { + cy.get("#avatar-group-group") + .should("have.prop", "_role", "button"); + }); + + it("aria-haspopup is correct", () => { + cy.get("#avatar-group-group").then(($avatarGroup) => { + ($avatarGroup[0] as AvatarGroup).accessibilityAttributes = { hasPopup: "menu" }; + }); + + cy.get("#avatar-group-group") + .then(($avatarGroup) => { + const avatarGroup = $avatarGroup[0] as AvatarGroup; + + expect(avatarGroup._containerAriaHasPopup).to.equal("menu"); + + if (avatarGroup._overflowButtonAccAttributes) { + expect(avatarGroup._overflowButtonAccAttributes.hasPopup).to.be.undefined; + } + }); + }); + + it("aria-label is correct", () => { + cy.get("#avatar-group-group") + .then(($avatarGroup) => { + const avatarGroup = $avatarGroup[0] as AvatarGroup; + const ariaLabel = avatarGroup._ariaLabelText; + const overflowButtonLabel = avatarGroup._overflowButtonAriaLabelText; + + expect(ariaLabel).to.include("Conjoined avatars"); + expect(ariaLabel).to.include("Activate for complete list"); + expect(ariaLabel).to.not.include("Press ARROW keys"); + + expect(overflowButtonLabel).to.be.undefined; + }); + }); + }); }); \ No newline at end of file diff --git a/packages/main/test/specs/AvatarGroup.spec.js b/packages/main/test/specs/AvatarGroup.spec.js deleted file mode 100644 index ce8176a92844..000000000000 --- a/packages/main/test/specs/AvatarGroup.spec.js +++ /dev/null @@ -1,203 +0,0 @@ -import { assert } from "chai"; - -async function getResourceBundleTexts(keys) { - return browser.executeAsync((keys, done) => { - const avatarGroup = document.getElementById("avatar-group-group"); - - const texts = keys.reduce((result, key) => { - result[key] = avatarGroup.constructor.i18nBundle.getText(window["sap-ui-webcomponents-bundle"].defaultTexts[key]) - return result; - }, {}); - done(texts); - - }, keys); -} - -describe("avatar-group rendering", () => { - before(async () => { - await browser.url(`test/pages/AvatarGroup.html`); - }); - - it("tests if web component is correctly rendered", async () => { - const avatarGroupIndividual = await browser.$("#avatar-group-individual").shadow$("div"); - const avatarGroupGroup = await browser.$("#avatar-group-group").shadow$("div"); - - assert.ok(avatarGroupIndividual, "AvatarGroup mode 'Individual' rendered"); - assert.ok(avatarGroupGroup, "AvatarGroup mode 'Group' rendered"); - }); - - it("tests click event when avatar is clicked", async () => { - const avatar = await browser.$("#avatar-1"); - - const eventTargetRef = await browser.$("#event-target"); - const eventOverflowButtonClicked = await browser.$("#event-overflow-button-clicked"); - const resetBtn = await browser.$("#reset-btn"); - - - await resetBtn.click(); - await avatar.click(); - - assert.strictEqual(await eventTargetRef.getValue(), await avatar.getProperty("tagName"), "Event should be called with ui5-avatar as targetRef"); - assert.strictEqual(await eventOverflowButtonClicked.getValue(), "false", "Event should be called with overflowButtonClicked equal to false"); - }); - - it("tests click event when overflow button is clicked", async () => { - const overflowButton = await browser.$("#avatar-group-individual").shadow$("ui5-button"); - - const eventTargetRef = await browser.$("#event-target"); - const eventOverflowButtonClicked = await browser.$("#event-overflow-button-clicked"); - const resetBtn = await browser.$("#reset-btn"); - - await resetBtn.click(); - await overflowButton.click(); - - assert.strictEqual(await eventTargetRef.getValue(), await overflowButton.getProperty("tagName"), "Event should be called with ui5-button as targetRef"); - assert.strictEqual(await eventOverflowButtonClicked.getValue(), "true", "Event should be called with overflowButtonClicked equal to true"); - }); - - it("tests click event avatar group with type group is clicked", async () => { - const avatarGroup = await browser.$("#avatar-group-group"); - - const eventTargetRef = await browser.$("#event-target"); - const eventOverflowButtonClicked = await browser.$("#event-overflow-button-clicked"); - const resetBtn = await browser.$("#reset-btn"); - - await resetBtn.click(); - await avatarGroup.click(); - - assert.strictEqual(await eventTargetRef.getValue(), "DIV.ui5-avatar-group-items", "Event should be called with ui5-button as targetRef"); - assert.strictEqual(await eventOverflowButtonClicked.getValue(), "false", "Event should be called with overflowButtonClicked equal to false"); - }); - - it("tests if hiddenItems is correctly displayed in the overflow button", async () => { - await browser.setWindowSize(200, 1080); - - const avatarGroup = await browser.$("#avatar-group-individual"); - const overflowButton = await browser.$("#avatar-group-individual").shadow$("ui5-button"); - - const hiddenItemsCount = (await avatarGroup.getProperty("hiddenItems")).length; - const overflowButtonText = await overflowButton.getText(); - - assert.strictEqual(`+${hiddenItemsCount}`, overflowButtonText, "Overflow button shows the hidden items count correctly"); - }); - - it("tests if click event is firing only once", async () => { - await browser.url(`test/pages/AvatarGroup.html`); - let eventCounter = 0; - - const avatar = await browser.$("#avatar-1-test-events"); - const overflowButton = await browser.$("#avatar-group-individual-events").shadow$("ui5-button"); - const avatarGroupTypeGroup = await browser.$("#avatar-group-group-events"); - const eventAvatarsClicked = await browser.$("#event-avatars-clicked"); - const getEventsCount = async () => parseInt(await eventAvatarsClicked.getValue()); - - await avatar.click() // set focus (important for the keys interaction to take action) - assert.strictEqual(await getEventsCount(), ++eventCounter, "Avatar group 'click' event only fires once per mouse click interaction - Avatar"); - await avatar.keys('Enter'); - assert.strictEqual(await getEventsCount(), ++eventCounter, "Avatar group 'click' event only fires once per keyboard 'Enter' interaction - Avatar"); - await avatar.keys('Space'); - assert.strictEqual(await getEventsCount(), ++eventCounter, "Avatar group 'click' event only fires once per keyboard 'Space' interaction - Avatar"); - - await overflowButton.click() // set focus (important for the keys interaction to take action) - assert.strictEqual(await getEventsCount(), ++eventCounter, "Avatar group 'click' event only fires once per mouse click interaction - Overflow Button"); - await overflowButton.keys('Enter'); - assert.strictEqual(await getEventsCount(), ++eventCounter, "Avatar group 'click' event only fires once per keyboard 'Enter' interaction - Overflow Button"); - await overflowButton.keys('Space'); - assert.strictEqual(await getEventsCount(), ++eventCounter, "Avatar group 'click' event only fires once per keyboard 'Space' interaction - Overflow Button"); - - await avatarGroupTypeGroup.click() // set focus (important for the keys interaction to take action) - assert.strictEqual(await getEventsCount(), ++eventCounter, "Avatar group 'click' event only fires once per mouse click interaction - Avatar Group type Group"); - await avatarGroupTypeGroup.keys('Enter'); - assert.strictEqual(await getEventsCount(), ++eventCounter, "Avatar group 'click' event only fires once per keyboard 'Enter' interaction - Avatar Group type Group"); - await avatarGroupTypeGroup.keys('Space'); - assert.strictEqual(await getEventsCount(), ++eventCounter, "Avatar group 'click' event only fires once per keyboard 'Space' interaction - Avatar Group type Group"); - }); -}); - -describe("ARIA attributes", () => { - before(async () => { - await browser.url(`test/pages/AvatarGroup.html`); - }); - - describe("Type Individual", () => { - - it("role is correct", async () => { - const avatarGroup = await browser.$("#avatar-group-individual"); - const role = await avatarGroup.getProperty("_role"); - - assert.strictEqual(role, "group", "should have role group for individual avatars"); - }); - - it("aria-haspopup is correct", async () => { - const avatarGroup = await browser.$("#avatar-group-individual"); - const ariaHasPopupContainer = await avatarGroup.getProperty("_containerAriaHasPopup"); - const overflowButtonAccAttributes = await avatarGroup.getProperty("_overflowButtonAccAttributes"); - - // container - assert.notExists(ariaHasPopupContainer, "should not have aria-haspopup attribute"); - // overflow button - assert.strictEqual(overflowButtonAccAttributes.hasPopup, "menu", "overflow button should have aria-haspopup for type individual"); - }); - - it("aria-label is correct", async () => { - const avatarGroup = await browser.$("#avatar-group-individual"); - const ariaLabel = await avatarGroup.getProperty("_ariaLabelText"); - const overflowButtonLabel = await avatarGroup.getProperty("_overflowButtonAriaLabelText"); - - const keys = [ - "AVATAR_GROUP_SHOW_COMPLETE_LIST_LABEL", - "AVATAR_GROUP_ARIA_LABEL_INDIVIDUAL", - "AVATAR_GROUP_MOVE", - ]; - const texts = await getResourceBundleTexts(keys); - - // container - assert.include(ariaLabel, texts.AVATAR_GROUP_ARIA_LABEL_INDIVIDUAL, "aria-label type message reference is correct"); - assert.notInclude(ariaLabel, texts.AVATAR_GROUP_SHOW_COMPLETE_LIST_LABEL, "should not have aria-label activate message"); - assert.include(ariaLabel, texts.AVATAR_GROUP_MOVE, "aria-label navigation message reference is correct"); - // overflow button - assert.include(overflowButtonLabel, texts.AVATAR_GROUP_SHOW_COMPLETE_LIST_LABEL, "overflow button should have aria-label for type individual"); - }); - }); - - describe("Type Group", () => { - - it("role is correct", async () => { - const avatarGroup = await browser.$("#avatar-group-group"); - const role = await avatarGroup.getProperty("_role"); - - assert.strictEqual(role, "button", "should have role button for grouped avatars"); - }); - - it("aria-haspopup is correct", async () => { - const avatarGroup = await browser.$("#avatar-group-group"); - const ariaHasPopupContainer = await avatarGroup.getProperty("_containerAriaHasPopup"); - const overflowButtonAccAttributes = await avatarGroup.getProperty("_overflowButtonAccAttributes"); - - // container - assert.strictEqual(ariaHasPopupContainer, "menu", "should have 'menu' set to aria-haspopup attribute"); - // overflow button - assert.notExists(overflowButtonAccAttributes.ariaHaspopup, "overflow button should not have aria-haspopup for type group"); - }); - - it("aria-label is correct", async () => { - const avatarGroup = await browser.$("#avatar-group-group"); - const ariaLabel = await avatarGroup.getProperty("_ariaLabelText"); - const overflowButtonLabel = await avatarGroup.getProperty("_overflowButtonAriaLabelText"); - - const keys = [ - "AVATAR_GROUP_SHOW_COMPLETE_LIST_LABEL", - "AVATAR_GROUP_ARIA_LABEL_GROUP", - "AVATAR_GROUP_MOVE" - ]; - const texts = await getResourceBundleTexts(keys); - - // container - assert.include(ariaLabel, texts.AVATAR_GROUP_ARIA_LABEL_GROUP, "aria-label type message reference is correct"); - assert.include(ariaLabel, texts.AVATAR_GROUP_SHOW_COMPLETE_LIST_LABEL, "should have aria-label activate message"); - assert.notInclude(ariaLabel, texts.AVATAR_GROUP_MOVE, "should not have aria-label navigation message"); - // overflow button - assert.notExists(overflowButtonLabel, "overflow button should not have aria-label activate message"); - }); - }); -}); From 5ffbfcfbc3dab9a78217b31668c73e4056bb29fe Mon Sep 17 00:00:00 2001 From: Nikola Anachkov Date: Mon, 30 Jun 2025 15:33:44 +0300 Subject: [PATCH 4/6] refactor: add prefix for failing tests --- packages/main/cypress/specs/Avatar.cy.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/main/cypress/specs/Avatar.cy.tsx b/packages/main/cypress/specs/Avatar.cy.tsx index 051b1e381183..6bbbbeeca557 100644 --- a/packages/main/cypress/specs/Avatar.cy.tsx +++ b/packages/main/cypress/specs/Avatar.cy.tsx @@ -358,9 +358,9 @@ describe("Avatar", () => { it("tests rendering of image", () => { cy.get("#myAvatar1") .shadow() - .find("slot:not([name])") + .find(".ui5-avatar-root slot:not([name])") .should("exist"); - + cy.get("#myAvatar1") .shadow() .find("ui5-avatar-icon") @@ -382,7 +382,7 @@ describe("Avatar", () => { it("tests rendering of image, when all set", () => { cy.get("#myAvatar3") .shadow() - .find("slot:not([name])") + .find(".ui5-avatar-root slot:not([name])") .should("exist"); cy.get("#myAvatar3") From 52af4ec616aab14cc9853e734ca5da0bce243dd6 Mon Sep 17 00:00:00 2001 From: Nikola Anachkov Date: Mon, 30 Jun 2025 16:34:29 +0300 Subject: [PATCH 5/6] refactor: change the image src --- packages/main/cypress/specs/Avatar.cy.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/main/cypress/specs/Avatar.cy.tsx b/packages/main/cypress/specs/Avatar.cy.tsx index 6bbbbeeca557..58c8160ae20e 100644 --- a/packages/main/cypress/specs/Avatar.cy.tsx +++ b/packages/main/cypress/specs/Avatar.cy.tsx @@ -315,11 +315,11 @@ describe("Avatar", () => { cy.mount(
- Woman image + Woman image - Woman image + Woman image @@ -360,7 +360,7 @@ describe("Avatar", () => { .shadow() .find(".ui5-avatar-root slot:not([name])") .should("exist"); - + cy.get("#myAvatar1") .shadow() .find("ui5-avatar-icon") From 32e6f59dcac56949ae71a1d0298eda0c867cb9f7 Mon Sep 17 00:00:00 2001 From: Nikola Anachkov Date: Mon, 4 Aug 2025 11:31:33 +0300 Subject: [PATCH 6/6] chore: address comments --- packages/main/cypress/specs/Avatar.cy.tsx | 169 +++++---- .../main/cypress/specs/AvatarGroup.cy.tsx | 343 +++++++++++------- 2 files changed, 297 insertions(+), 215 deletions(-) diff --git a/packages/main/cypress/specs/Avatar.cy.tsx b/packages/main/cypress/specs/Avatar.cy.tsx index 58c8160ae20e..1c956c632729 100644 --- a/packages/main/cypress/specs/Avatar.cy.tsx +++ b/packages/main/cypress/specs/Avatar.cy.tsx @@ -307,111 +307,92 @@ describe("Fallback Logic", () => { }); }); -describe("Avatar", () => { - let sharedInputValue = 0; - let sharedInputValue2 = 0; - - beforeEach(() => { +describe("Avatar Rendering and Interaction", () => { + it("tests rendering of image", () => { cy.mount( -
- - Woman image - - - + Woman image - - - - - - - - - - -
+ ); - cy.get("#interactive-avatar").then(($avatar) => { - $avatar[0].addEventListener("ui5-click", function() { - const input = document.getElementById("click-event") as HTMLInputElement; - input.value = `${++sharedInputValue}`; - }); - }); - - cy.get("#non-interactive-avatar").then(($avatar) => { - $avatar[0].addEventListener("ui5-click", function() { - const input = document.getElementById("click-event") as HTMLInputElement; - input.value = `${++sharedInputValue}`; - }); - }); - - cy.get("#myInteractiveAvatar").then(($avatar) => { - $avatar[0].addEventListener("ui5-click", function() { - const input = document.getElementById("click-event-2") as HTMLInputElement; - input.value = `${++sharedInputValue2}`; - }); - }); - }); - - it("tests rendering of image", () => { - cy.get("#myAvatar1") + cy.get("[ui5-avatar]") .shadow() .find(".ui5-avatar-root slot:not([name])") .should("exist"); - cy.get("#myAvatar1") + cy.get("[ui5-avatar]") .shadow() .find("ui5-avatar-icon") .should("not.exist"); }); it("tests rendering of icon", () => { - cy.get("#myAvatar2") + cy.mount( + + ); + + cy.get("[ui5-avatar]") .shadow() .find(".ui5-avatar-icon") .should("exist"); - cy.get("#myAvatar2") + cy.get("[ui5-avatar]") .shadow() .find("slot:not([name])") .should("not.exist"); }); it("tests rendering of image, when all set", () => { - cy.get("#myAvatar3") + cy.mount( + + Woman image + + ); + + cy.get("[ui5-avatar]") .shadow() .find(".ui5-avatar-root slot:not([name])") .should("exist"); - cy.get("#myAvatar3") + cy.get("[ui5-avatar]") .shadow() .find(".ui5-avatar-icon") .should("not.exist"); - cy.get("#myAvatar3") + cy.get("[ui5-avatar]") .shadow() .find(".ui5-avatar-initials") .should("not.exist"); }); it("tests rendering of initials", () => { - cy.get("#myAvatar4") + cy.mount( + + ); + + cy.get("[ui5-avatar]") .shadow() .find(".ui5-avatar-initials") .should("exist"); }); it("tests rendering of accented characters", () => { - cy.get("#myAvatar6") + cy.mount( + + ); + + cy.get("[ui5-avatar]") .shadow() .find(".ui5-avatar-initials") .should("exist"); }); it("tests rendering of default fallback icon when initials are overflowing", () => { - cy.get("#myAvatar5") + cy.mount( + + ); + + cy.get("[ui5-avatar]") .shadow() .find(".ui5-avatar-icon") .should("exist") @@ -419,7 +400,11 @@ describe("Avatar", () => { }); it("tests rendering of custom fallback icon when initials are overflowing", () => { - cy.get("#myAvatar7") + cy.mount( + + ); + + cy.get("[ui5-avatar]") .shadow() .find(".ui5-avatar-icon-fallback") .should("exist") @@ -427,62 +412,92 @@ describe("Avatar", () => { }); it("Tests noConflict 'ui5-click' event for interactive avatars", () => { - cy.get("#interactive-avatar") + cy.mount( + + ); + + cy.get("[ui5-avatar]") + .as("avatar") + .then(($avatar) => { + $avatar[0].addEventListener("ui5-click", cy.stub().as("clickStub")); + }); + + cy.get("@avatar") .shadow() .find(".ui5-avatar-root") .realClick(); - cy.get("#click-event") - .should("have.value", "1"); + cy.get("@clickStub") + .should("have.been.calledOnce"); - cy.get("#interactive-avatar") + cy.get("@avatar") .shadow() .find(".ui5-avatar-root") .realPress("Enter"); - cy.get("#click-event") - .should("have.value", "2"); + cy.get("@clickStub") + .should("have.been.calledTwice"); - cy.get("#interactive-avatar") + cy.get("@avatar") .shadow() .find(".ui5-avatar-root") .realPress("Space"); - cy.get("#click-event") - .should("have.value", "3"); + cy.get("@clickStub") + .should("have.been.calledThrice"); }); it("Tests noConflict 'ui5-click' event for non interactive avatars", () => { - cy.get("#non-interactive-avatar") + cy.mount( + + ); + + cy.get("[ui5-avatar]") + .as("avatar") + .then(($avatar) => { + $avatar[0].addEventListener("ui5-click", cy.stub().as("clickStub")); + }); + + cy.get("@avatar") .shadow() .find(".ui5-avatar-root") .realClick(); - cy.get("#click-event") - .should("have.value", "4"); + cy.get("@clickStub") + .should("have.been.calledOnce"); - cy.get("#non-interactive-avatar") + cy.get("@avatar") .shadow() .find(".ui5-avatar-root") .realPress("Enter"); - cy.get("#click-event") - .should("have.value", "4"); + cy.get("@clickStub") + .should("have.been.calledOnce"); - cy.get("#non-interactive-avatar") + cy.get("@avatar") .shadow() .find(".ui5-avatar-root") .realPress("Space"); - cy.get("#click-event") - .should("have.value", "4"); + cy.get("@clickStub") + .should("have.been.calledOnce"); }); it("Tests native 'click' event thrown", () => { - cy.get("#myInteractiveAvatar") + cy.mount( + + ); + + cy.get("[ui5-avatar]") + .as("avatar") + .then(($avatar) => { + $avatar[0].addEventListener("ui5-click", cy.stub().as("clickStub")); + }); + + cy.get("@avatar") .realClick(); - cy.get("#click-event-2") - .should("have.value", "1"); + cy.get("@clickStub") + .should("have.been.calledOnce"); }); }); \ No newline at end of file diff --git a/packages/main/cypress/specs/AvatarGroup.cy.tsx b/packages/main/cypress/specs/AvatarGroup.cy.tsx index 6145acbb3fe4..3ce5dc3ce8fd 100644 --- a/packages/main/cypress/specs/AvatarGroup.cy.tsx +++ b/packages/main/cypress/specs/AvatarGroup.cy.tsx @@ -173,124 +173,152 @@ describe("Accessibility", () => { }); }); -describe("avatar-group rendering", () => { - beforeEach(() => { +describe("AvatarGroup Rendering and Events", () => { + it("tests if web component is correctly rendered", () => { cy.mount(
- - - - - + + - + - - -
); - // Set up event listener for individual avatar group - cy.get("#avatar-group-individual").then(($avatarGroup) => { - $avatarGroup[0].addEventListener("ui5-click", function(event: CustomEvent) { - const eventTargetRef = document.getElementById("event-target") as HTMLInputElement; - const eventOverflowButtonClicked = document.getElementById("event-overflow-button-clicked") as HTMLInputElement; - - eventTargetRef.value = event.detail.targetRef.tagName; - eventOverflowButtonClicked.value = event.detail.overflowButtonClicked.toString(); - }); - }); - - // Set up event listener for group avatar group - SAME handler as individual - cy.get("#avatar-group-group").then(($avatarGroup) => { - $avatarGroup[0].addEventListener("ui5-click", function(event: CustomEvent) { - const eventTargetRef = document.getElementById("event-target") as HTMLInputElement; - const eventOverflowButtonClicked = document.getElementById("event-overflow-button-clicked") as HTMLInputElement; - - // For group type, use tagName + className - eventTargetRef.value = event.detail.targetRef.tagName + "." + event.detail.targetRef.className; - eventOverflowButtonClicked.value = event.detail.overflowButtonClicked.toString(); - }); - }); - - // Set up reset functionality - cy.get("#reset-btn").then(($btn) => { - $btn[0].addEventListener("click", function() { - (document.getElementById("event-target") as HTMLInputElement).value = ""; - (document.getElementById("event-overflow-button-clicked") as HTMLInputElement).value = ""; - }); - }); - }); - - it("tests if web component is correctly rendered", () => { - cy.get("#avatar-group-individual") + cy.get("[ui5-avatar-group]").eq(0) .shadow() .find("div") .should("exist"); - cy.get("#avatar-group-group") + cy.get("[ui5-avatar-group]").eq(1) .shadow() .find("div") .should("exist"); }); it("tests click event when avatar is clicked", () => { - cy.get("#reset-btn").realClick(); - cy.get("#avatar-1").realClick(); + cy.mount( +
+ + + + +
+ ); - cy.get("#event-target") - .should("have.value", "UI5-AVATAR"); + cy.get("[ui5-avatar-group]") + .as("avatarGroup") + .then(($avatarGroup) => { + $avatarGroup[0].addEventListener("ui5-click", cy.stub().as("clickStub")); + }); - cy.get("#event-overflow-button-clicked") - .should("have.value", "false"); + cy.get("[ui5-avatar]").first().realClick(); + + cy.get("@clickStub") + .should("have.been.calledOnce") + .its("firstCall.args.0.detail") + .should("deep.include", { + overflowButtonClicked: false + }) + .its("targetRef.tagName") + .should("equal", "UI5-AVATAR"); }); it("tests click event when overflow button is clicked", () => { - cy.get("#reset-btn").realClick(); + cy.mount( +
+ + + + + + + + +
+ ); + + cy.get("[ui5-avatar-group]") + .as("avatarGroup") + .then(($avatarGroup) => { + $avatarGroup[0].addEventListener("ui5-click", cy.stub().as("clickStub")); + }); - cy.get("#avatar-group-individual") + cy.get("@avatarGroup") .shadow() .find("ui5-button") .realClick(); - cy.get("#event-target") - .should("have.value", "UI5-BUTTON"); - - cy.get("#event-overflow-button-clicked") - .should("have.value", "true"); + cy.get("@clickStub") + .should("have.been.calledOnce") + .its("firstCall.args.0.detail") + .should("deep.include", { + overflowButtonClicked: true + }) + .its("targetRef.tagName") + .should("equal", "UI5-BUTTON"); }); it("tests click event avatar group with type group is clicked", () => { - cy.get("#reset-btn").realClick(); + cy.mount( + + + + + + ); + + cy.get("[ui5-avatar-group]") + .as("avatarGroup") + .then(($avatarGroup) => { + $avatarGroup[0].addEventListener("ui5-click", cy.stub().as("clickStub")); + }); - cy.get("#avatar-group-group") + cy.get("@avatarGroup") .shadow() .find(".ui5-avatar-group-items") .realClick(); - - cy.get("#event-target") - .should("have.value", "DIV.ui5-avatar-group-items"); - - cy.get("#event-overflow-button-clicked") - .should("have.value", "false"); + + cy.get("@clickStub") + .should("have.been.calledOnce") + .its("firstCall.args.0.detail") + .should("deep.include", { + overflowButtonClicked: false + }) + .its("targetRef") + .then((targetRef) => { + expect(targetRef.tagName + "." + targetRef.className).to.equal("DIV.ui5-avatar-group-items"); + }); }); it("tests if hiddenItems is correctly displayed in the overflow button", () => { cy.viewport(200, 1080); + + cy.mount( +
+ + + + + + + + +
+ ); - cy.get("#avatar-group-individual") + cy.get("[ui5-avatar-group]") .shadow() .find("ui5-button") .should("not.have.text", "") .invoke("text") .then((buttonText) => { - cy.get("#avatar-group-individual") + cy.get("[ui5-avatar-group]") .then(($avatarGroup) => { const avatarGroup = $avatarGroup[0] as AvatarGroup; const hiddenItemsCount = avatarGroup.hiddenItems.length; @@ -300,84 +328,82 @@ describe("avatar-group rendering", () => { }); it("tests if click event is firing only once", () => { - let eventCounter = 0; - cy.mount(
- - + + - + -
); - - cy.get("#avatar-group-individual-events").then(($avatarGroup) => { - $avatarGroup[0].addEventListener("ui5-click", function() { - const eventAvatarsClicked = document.getElementById("event-avatars-clicked") as HTMLInputElement; - eventAvatarsClicked.value = (parseInt(eventAvatarsClicked.value) + 1).toString(); + + cy.get("[ui5-avatar-group]").eq(0) + .as("individualGroup") + .then(($avatarGroup) => { + $avatarGroup[0].addEventListener("ui5-click", cy.stub().as("individualClickStub")); }); - }); - - cy.get("#avatar-group-group-events").then(($avatarGroup) => { - $avatarGroup[0].addEventListener("ui5-click", function() { - const eventAvatarsClicked = document.getElementById("event-avatars-clicked") as HTMLInputElement; - eventAvatarsClicked.value = (parseInt(eventAvatarsClicked.value) + 1).toString(); + + cy.get("[ui5-avatar-group]").eq(1) + .as("groupType") + .then(($avatarGroup) => { + $avatarGroup[0].addEventListener("ui5-click", cy.stub().as("groupClickStub")); }); - }); - - cy.get("#avatar-1-test-events").realClick(); - cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); - - cy.get("#avatar-1-test-events").realPress("Enter"); - cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); - - cy.get("#avatar-1-test-events").realPress("Space"); - cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); - - cy.get("#avatar-group-individual-events") + + // Test individual avatar clicks + cy.get("[ui5-avatar]").first().realClick(); + cy.get("@individualClickStub").should("have.been.calledOnce"); + + cy.get("[ui5-avatar]").first().realPress("Enter"); + cy.get("@individualClickStub").should("have.been.calledTwice"); + + cy.get("[ui5-avatar]").first().realPress("Space"); + cy.get("@individualClickStub").should("have.been.calledThrice"); + + // Test overflow button clicks + cy.get("@individualGroup") .shadow() .find("ui5-button") .realClick(); - cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); - - cy.get("#avatar-group-individual-events") + cy.get("@individualClickStub").should("have.callCount", 4); + + cy.get("@individualGroup") .shadow() .find("ui5-button") .realPress("Enter"); - cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); - - cy.get("#avatar-group-individual-events") + cy.get("@individualClickStub").should("have.callCount", 5); + + cy.get("@individualGroup") .shadow() .find("ui5-button") .realPress("Space"); - cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); - - cy.get("#avatar-group-group-events").realClick(); - cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); - - cy.get("#avatar-group-group-events").realPress("Enter"); - cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); - - cy.get("#avatar-group-group-events").realPress("Space"); - cy.get("#event-avatars-clicked").should("have.value", (++eventCounter).toString()); + cy.get("@individualClickStub").should("have.callCount", 6); + + // Test group avatar clicks + cy.get("@groupType").realClick(); + cy.get("@groupClickStub").should("have.been.calledOnce"); + + cy.get("@groupType").realPress("Enter"); + cy.get("@groupClickStub").should("have.been.calledTwice"); + + cy.get("@groupType").realPress("Space"); + cy.get("@groupClickStub").should("have.been.calledThrice"); }); }); -describe("ARIA attributes", () => { +describe("AvatarGroup ARIA Attributes", () => { describe("Type Individual", () => { - beforeEach(() => { + it("role is correct", () => { cy.mount(
- + @@ -389,20 +415,32 @@ describe("ARIA attributes", () => {
); - }); - it("role is correct", () => { - cy.get("#avatar-group-individual") + cy.get("[ui5-avatar-group]") .should("have.prop", "_role", "group"); }); it("aria-haspopup is correct", () => { - cy.get("#avatar-group-individual").then(($avatarGroup) => { + cy.mount( +
+ + + + + + + + + + +
+ ); + + cy.get("[ui5-avatar-group]").then(($avatarGroup) => { ($avatarGroup[0] as any).accessibilityAttributes = { hasPopup: "menu" }; }); - - cy.get("#avatar-group-individual") + cy.get("[ui5-avatar-group]") .then(($avatarGroup) => { const avatarGroup = $avatarGroup[0] as AvatarGroup; @@ -414,7 +452,22 @@ describe("ARIA attributes", () => { }); it("aria-label is correct", () => { - cy.get("#avatar-group-individual") + cy.mount( +
+ + + + + + + + + + +
+ ); + + cy.get("[ui5-avatar-group]") .then(($avatarGroup) => { const ariaLabel = ($avatarGroup[0] as AvatarGroup)._ariaLabelText; expect(ariaLabel).to.include("Individual avatars"); @@ -422,7 +475,7 @@ describe("ARIA attributes", () => { expect(ariaLabel).to.include("Press ARROW keys"); }); - cy.get("#avatar-group-individual") + cy.get("[ui5-avatar-group]") .then(($avatarGroup) => { const overflowButtonLabel = ($avatarGroup[0] as AvatarGroup)._overflowButtonAriaLabelText; expect(overflowButtonLabel).to.include("Activate for complete list"); @@ -431,27 +484,33 @@ describe("ARIA attributes", () => { }); describe("Type Group", () => { - beforeEach(() => { + it("role is correct", () => { cy.mount( - + ); - }); - - it("role is correct", () => { - cy.get("#avatar-group-group") + + cy.get("[ui5-avatar-group]") .should("have.prop", "_role", "button"); }); - + it("aria-haspopup is correct", () => { - cy.get("#avatar-group-group").then(($avatarGroup) => { + cy.mount( + + + + + + ); + + cy.get("[ui5-avatar-group]").then(($avatarGroup) => { ($avatarGroup[0] as AvatarGroup).accessibilityAttributes = { hasPopup: "menu" }; }); - - cy.get("#avatar-group-group") + + cy.get("[ui5-avatar-group]") .then(($avatarGroup) => { const avatarGroup = $avatarGroup[0] as AvatarGroup; @@ -462,14 +521,22 @@ describe("ARIA attributes", () => { } }); }); - + it("aria-label is correct", () => { - cy.get("#avatar-group-group") + cy.mount( + + + + + + ); + + cy.get("[ui5-avatar-group]") .then(($avatarGroup) => { const avatarGroup = $avatarGroup[0] as AvatarGroup; const ariaLabel = avatarGroup._ariaLabelText; const overflowButtonLabel = avatarGroup._overflowButtonAriaLabelText; - + expect(ariaLabel).to.include("Conjoined avatars"); expect(ariaLabel).to.include("Activate for complete list"); expect(ariaLabel).to.not.include("Press ARROW keys");