diff --git a/packages/main/cypress/specs/ComboBox.cy.tsx b/packages/main/cypress/specs/ComboBox.cy.tsx index 3b241da6809b4..81ebd3acc83b4 100644 --- a/packages/main/cypress/specs/ComboBox.cy.tsx +++ b/packages/main/cypress/specs/ComboBox.cy.tsx @@ -4274,3 +4274,95 @@ describe("ComboBoxItemCustom - Accessibility", () => { cy.get("[ui5-cb-item-custom]").shadow().find("li").should("not.have.attr", "tabindex", "0"); }); }); + +describe("Newline normalization in item text", () => { + it("should fire change event twice when selecting two different items with newlines via keyboard", () => { + cy.mount( + + + + + ); + + cy.get("[ui5-combobox]") + .as("combobox") + .invoke("on", "ui5-change", cy.spy().as("changeSpy")); + + cy.get("@combobox") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("@combobox") + .shadow() + .find("[ui5-responsive-popover]") + .should("have.attr", "open"); + + cy.get("@combobox").realPress("ArrowDown"); + cy.get("@combobox").realPress("Enter"); + + cy.get("@changeSpy").should("have.been.calledOnce"); + + cy.get("@combobox") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("@combobox") + .shadow() + .find("[ui5-responsive-popover]") + .should("have.attr", "open"); + + cy.get("@combobox").realPress("ArrowDown"); + cy.get("@combobox").realPress("ArrowDown"); + cy.get("@combobox").realPress("Enter"); + + cy.get("@changeSpy").should("have.been.calledTwice"); + }); + + it("should fire change event when selecting items with identical normalized display text but different values", () => { + cy.mount( + + + + + ); + + cy.get("[ui5-combobox]") + .as("combobox") + .invoke("on", "ui5-change", cy.spy().as("changeSpy")); + + cy.get("[ui5-cb-item]").should("have.length", 2); + + cy.get("@combobox") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("@combobox") + .shadow() + .find("[ui5-responsive-popover]") + .should("have.attr", "open"); + + cy.get("@combobox").realPress("ArrowDown"); + cy.get("@combobox").realPress("Enter"); + + cy.get("@changeSpy").should("have.been.calledOnce"); + + cy.get("@combobox") + .shadow() + .find("[ui5-icon]") + .realClick(); + + cy.get("@combobox") + .shadow() + .find("[ui5-responsive-popover]") + .should("have.attr", "open"); + + cy.get("@combobox").realPress("ArrowDown"); + cy.get("@combobox").realPress("ArrowDown"); + cy.get("@combobox").realPress("Enter"); + + cy.get("@changeSpy").should("have.been.calledTwice"); + }); +}); diff --git a/packages/main/src/ComboBox.ts b/packages/main/src/ComboBox.ts index 4924702d5ac99..af122d5e4feed 100644 --- a/packages/main/src/ComboBox.ts +++ b/packages/main/src/ComboBox.ts @@ -519,6 +519,7 @@ class ComboBox extends UI5Element implements IFormInputElement { _selectionPerformed = false; _selectionTrigger?: ComboBoxSelectionChangeTrigger; _lastValue: string; + _lastSelectedValue?: string; _selectedItemText = ""; _userTypedValue = ""; _useSelectedValue = false; @@ -650,6 +651,7 @@ class ComboBox extends UI5Element implements IFormInputElement { if (!e.relatedTarget || (e.relatedTarget !== this.shadowRoot!.querySelector(".ui5-input-clear-icon"))) { this._lastValue = this.value; + this._lastSelectedValue = this.selectedValue; } !isPhone() && (e.target as HTMLInputElement).setSelectionRange(0, this.value.length); @@ -713,6 +715,7 @@ class ComboBox extends UI5Element implements IFormInputElement { if (this._selectionPerformed) { this._lastValue = this.value; + this._lastSelectedValue = this.selectedValue; this._selectionPerformed = false; } @@ -782,6 +785,7 @@ class ComboBox extends UI5Element implements IFormInputElement { if (isPhone() && this.value && !this._lastValue) { this._lastValue = this.value; + this._lastSelectedValue = this.selectedValue; } this._toggleRespPopover(); @@ -1400,9 +1404,13 @@ class ComboBox extends UI5Element implements IFormInputElement { } _fireChangeEvent() { - if (this.value !== this._lastValue) { + const valueChanged = this.value !== this._lastValue; + const selectedValueChanged = this._useSelectedValue && this.selectedValue !== this._lastSelectedValue; + + if (valueChanged || selectedValueChanged) { this.fireDecoratorEvent("change"); this._lastValue = this.value; + this._lastSelectedValue = this.selectedValue; } } @@ -1500,6 +1508,7 @@ class ComboBox extends UI5Element implements IFormInputElement { if (this._isPhone) { this._lastValue = ""; + this._lastSelectedValue = undefined; this.fireDecoratorEvent("change"); } else { this.focus(); diff --git a/packages/main/test/pages/ComboBox.html b/packages/main/test/pages/ComboBox.html index 96b7eb59f53e5..dae7010c1efc3 100644 --- a/packages/main/test/pages/ComboBox.html +++ b/packages/main/test/pages/ComboBox.html @@ -890,6 +890,37 @@

ComboBox with Mixed Items

+
+

Newline Normalization Test

+

Items with newlines in text that normalize to same display. Use Arrow keys + Enter to test.

+ +

+
Change events: 0
+
+ +
+