diff --git a/packages/main/cypress/specs/MultiComboBox.cy.tsx b/packages/main/cypress/specs/MultiComboBox.cy.tsx index 2d551bc09259..4fd77461990f 100644 --- a/packages/main/cypress/specs/MultiComboBox.cy.tsx +++ b/packages/main/cypress/specs/MultiComboBox.cy.tsx @@ -219,8 +219,10 @@ describe("MultiComboBox RTL/LTR Arrow Navigation", () => { .find("[ui5-tokenizer]") .find("[ui5-token]") .last() - .should("be.visible") - .should("be.focused"); + .as ("lastToken"); + + cy.get("@lastToken").should("be.visible"); + cy.get("@lastToken").should("be.focused"); }); it("should focus last token on arrow left in LTR mode when input is at start", () => { @@ -263,8 +265,10 @@ describe("MultiComboBox RTL/LTR Arrow Navigation", () => { .find("[ui5-tokenizer]") .find("[ui5-token]") .last() - .should("be.visible") - .should("be.focused"); + .as ("lastToken"); + + cy.get("@lastToken").should("be.visible"); + cy.get("@lastToken").should("be.focused"); }); it("should not focus token when cursor is not at start of input in RTL mode", () => { @@ -283,7 +287,6 @@ describe("MultiComboBox RTL/LTR Arrow Navigation", () => { .realClick(); cy.get("@mcb").should("be.focused"); - cy.get("@mcb") .shadow() @@ -297,23 +300,14 @@ describe("MultiComboBox RTL/LTR Arrow Navigation", () => { cy.get("@mcb").realPress("ArrowRight"); - cy.get("@mcb") - .shadow() - .find("input") - .as("input") - .realClick(); - - cy.get("@input") - .should("be.focused") - .should(($input) => { - expect(($input[0] as HTMLInputElement).selectionStart).to.equal(3); - }); - cy.get("@mcb") .shadow() .find("[ui5-tokenizer]") .find("[ui5-token]") - .should("not.be.focused"); + .as ("lastToken"); + + cy.get("@lastToken").should("be.visible"); + cy.get("@lastToken").should("not.be.focused"); }); it("should not focus token when text is selected in RTL mode", () => { @@ -350,7 +344,10 @@ describe("MultiComboBox RTL/LTR Arrow Navigation", () => { .shadow() .find("[ui5-tokenizer]") .find("[ui5-token]") - .should("not.have.focus"); + .as ("lastToken"); + + cy.get("@lastToken").should("be.visible"); + cy.get("@lastToken").should("not.be.focused"); }); it("should navigate from last token back to input with arrow left in RTL mode", () => { @@ -378,17 +375,13 @@ describe("MultiComboBox RTL/LTR Arrow Navigation", () => { .find("[ui5-tokenizer]") .find("[ui5-token]") .last() - .as("lastToken") - .should("have.focus"); + .as("lastToken"); - cy.get("@lastToken") - .should("be.focused") - .realPress("ArrowLeft"); + cy.get("@lastToken").should("be.visible"); + cy.get("@lastToken").should("be.focused"); + cy.get("@lastToken").realPress("ArrowLeft"); - cy.get("@mcb") - .shadow() - .find("input") - .should("be.focused"); + cy.get("@mcb").should("be.focused"); }); it("should navigate from last token back to input with arrow right in LTR mode", () => { @@ -416,15 +409,10 @@ describe("MultiComboBox RTL/LTR Arrow Navigation", () => { .find("[ui5-tokenizer]") .find("[ui5-token]") .last() - .as("lastToken") - .should("be.focused"); - - cy.get("@lastToken").realPress("ArrowRight"); + .realPress("ArrowRight"); - cy.get("@mcb") - .shadow() - .find("input") - .should("be.focused"); + cy.get("@mcb").should("be.visible"); + cy.get("@mcb").should("be.focused"); }); it("should handle empty input case in RTL mode", () => { @@ -464,7 +452,11 @@ describe("MultiComboBox RTL/LTR Arrow Navigation", () => { .find("[ui5-tokenizer]") .find("[ui5-token]") .last() - .should("have.focus"); + .as("lastToken"); + + cy.get("@lastToken").should("be.visible"); + cy.get("@lastToken").should("be.focused"); + }); }); diff --git a/packages/main/cypress/specs/Tokenizer.cy.tsx b/packages/main/cypress/specs/Tokenizer.cy.tsx index dbc36b53f1ef..1c46d56e94ec 100644 --- a/packages/main/cypress/specs/Tokenizer.cy.tsx +++ b/packages/main/cypress/specs/Tokenizer.cy.tsx @@ -208,3 +208,99 @@ describe("Tokenizer - multi-line and Clear All", () => { }); }); +describe("Tokenizer - Popover List Item Text Updates", () => { + it("updates list item text in popover when token text changes", () => { + cy.mount( + + + + + + + + + + ); + + cy.get("[ui5-tokenizer]") + .shadow() + .find(".ui5-tokenizer-more-text") + .realClick(); + + cy.get("[ui5-tokenizer]") + .shadow() + .find("[ui5-responsive-popover]") + .should("be.visible"); + + cy.get("[ui5-tokenizer]") + .shadow() + .find("[ui5-responsive-popover] [ui5-list] [ui5-li]") + .eq(0) + .should("have.attr", "text", "Original Text"); + + cy.get("#token-to-modify").invoke("prop", "text", "Updated Text"); + + cy.get("[ui5-tokenizer]") + .shadow() + .find("[ui5-responsive-popover] [ui5-list] [ui5-li]") + .eq(0) + .should("have.attr", "text", "Updated Text"); + + cy.get("#test-token-text-update") + .shadow() + .find("[ui5-responsive-popover] [ui5-list] [ui5-li]") + .eq(0) + .should("not.have.attr", "text", "Original Text"); + }); + + it("updates multiple list items when multiple token texts change", () => { + cy.mount( + + + + + + + + ); + + cy.get("[ui5-tokenizer]") + .shadow() + .find(".ui5-tokenizer-more-text") + .realClick(); + + cy.get("[ui5-tokenizer]") + .shadow() + .find("[ui5-responsive-popover] [ui5-list] [ui5-li]") + .eq(0) + .should("have.attr", "text", "Token 1"); + + cy.get("[ui5-tokenizer]") + .shadow() + .find("[ui5-responsive-popover] [ui5-list] [ui5-li]") + .eq(1) + .should("have.attr", "text", "Token 2"); + + cy.get("[ui5-token]").eq(0).invoke("prop", "text", "Modified Token 1"); + cy.get("[ui5-token]").eq(1).invoke("prop", "text", "Modified Token 2"); + + cy.get("[ui5-tokenizer]") + .shadow() + .find("[ui5-responsive-popover] [ui5-list] [ui5-li]") + .eq(0) + .should("have.attr", "text", "Modified Token 1"); + + cy.get("[ui5-tokenizer]") + .shadow() + .find("[ui5-responsive-popover] [ui5-list] [ui5-li]") + .eq(1) + .should("have.attr", "text", "Modified Token 2"); + + // Verify unchanged token remains the same + cy.get("[ui5-tokenizer]") + .shadow() + .find("[ui5-responsive-popover] [ui5-list] [ui5-li]") + .eq(2) + .should("have.attr", "text", "Token 3"); + }); +}); diff --git a/packages/main/src/Tokenizer.ts b/packages/main/src/Tokenizer.ts index da74d3d498bb..9cad4b2c9e98 100644 --- a/packages/main/src/Tokenizer.ts +++ b/packages/main/src/Tokenizer.ts @@ -333,6 +333,10 @@ class Tokenizer extends UI5Element { type: HTMLElement, "default": true, individualSlots: true, + invalidateOnChildChange: { + properties: ["text"], + slots: false, + }, }) tokens!: Array; diff --git a/packages/main/src/TokenizerPopoverTemplate.tsx b/packages/main/src/TokenizerPopoverTemplate.tsx index 4fb138b0a7b9..58fa75b7b8d1 100644 --- a/packages/main/src/TokenizerPopoverTemplate.tsx +++ b/packages/main/src/TokenizerPopoverTemplate.tsx @@ -42,7 +42,7 @@ export default function TokenizerPopoverTemplate(this: Tokenizer) { onItemDelete={this.itemDelete} > {this._tokens - .map(token => {token.text})} + .map(token => )} {this._isPhone &&