diff --git a/packages/main/cypress/specs/ComboBox.cy.tsx b/packages/main/cypress/specs/ComboBox.cy.tsx index f3e727c24cf2..69862539d967 100644 --- a/packages/main/cypress/specs/ComboBox.cy.tsx +++ b/packages/main/cypress/specs/ComboBox.cy.tsx @@ -258,6 +258,57 @@ describe("General Interaction", () => { .should("have.text", "Canada"); }); + it("should highlight entire value when navigating to item that doesn't start with typed text", () => { + cy.mount( + + + + + + ); + + cy.get("[ui5-combobox]") + .as("combo") + .shadow() + .find("input") + .as("input"); + + cy.get("@input").realClick(); + cy.get("@input").realType("a"); + + cy.get("@combo") + .shadow() + .find("ui5-responsive-popover") + .should("have.attr", "open"); + + cy.get("@input").should("have.value", "Algeria"); + cy.get("@input").then(($input) => { + const input = $input[0] as HTMLInputElement; + + expect(input.selectionStart).to.equal(1); + expect(input.selectionEnd).to.equal("Algeria".length); + }); + + cy.get("@input").realPress("ArrowDown"); + + cy.get("@input").should("have.value", "Bulgaria"); + cy.get("@input").then(($input) => { + const input = $input[0] as HTMLInputElement; + + expect(input.selectionStart).to.equal(0); + expect(input.selectionEnd).to.equal("Bulgaria".length); + }); + + cy.get("@input").realPress("ArrowDown"); + + cy.get("@input").should("have.value", "Canada"); + cy.get("@input").then(($input) => { + const input = $input[0] as HTMLInputElement; + expect(input.selectionStart).to.equal(0); + expect(input.selectionEnd).to.equal("Canada".length); + }); + }); + it("tests Combo with startswith filter", () => { cy.mount( @@ -3336,3 +3387,158 @@ describe("SelectedValue API", () => { cy.get("[ui5-cb-item]").eq(2).should("have.prop", "selected", false); }); }); + +describe("Case-Insensitive Selection", () => { + it("should select item with case-insensitive matching", () => { + cy.mount( + + + + + + ); + + cy.get("[ui5-combobox]") + .as("combobox") + .shadow() + .find("input") + .as("input"); + + cy.get("@input").realClick(); + cy.get("@input").realType("b"); + cy.get("@input").realType("u"); + cy.get("@input").realType("l"); + cy.get("@input").realType("g"); + cy.get("@input").realType("a"); + cy.get("@input").realType("r"); + cy.get("@input").realType("i"); + cy.get("@input").realType("a"); + + cy.get("@combobox").should("have.prop", "value", "bulgaria"); + cy.get("[ui5-cb-item]").eq(1).should("have.prop", "selected", true); + }); + + it("should select item case-insensitively with Contains filter", () => { + cy.mount( + + + + + + ); + + cy.get("[ui5-combobox]") + .as("combobox") + .shadow() + .find("input") + .as("input"); + + cy.get("@input").realClick(); + cy.get("@input").realType("u"); + cy.get("@input").realType("n"); + cy.get("@input").realType("i"); + cy.get("@input").realType("t"); + cy.get("@input").realType("e"); + cy.get("@input").realType("d"); + cy.get("@input").realType(" "); + cy.get("@input").realType("s"); + cy.get("@input").realType("t"); + cy.get("@input").realType("a"); + cy.get("@input").realType("t"); + cy.get("@input").realType("e"); + cy.get("@input").realType("s"); + + cy.get("@combobox").should("have.prop", "value", "United States"); + cy.get("[ui5-cb-item]").eq(1).should("have.prop", "selected", true); + }); + + it("should select matching item of a group case-insensitively", () => { + cy.mount( + + + + + + + + + + + ); + + cy.get("[ui5-combobox]") + .as("combobox") + .shadow() + .find("input") + .as("input"); + + cy.get("@input").realClick(); + cy.get("@input").realType("a"); + cy.get("@input").realType("r"); + cy.get("@input").realType("g"); + cy.get("@input").realType("e"); + cy.get("@input").realType("n"); + cy.get("@input").realType("t"); + cy.get("@input").realType("i"); + cy.get("@input").realType("n"); + cy.get("@input").realType("a"); + + cy.get("@combobox").should("have.prop", "value", "Argentina"); + cy.get("[ui5-cb-item]").eq(0).should("have.prop", "selected", true); + }); + + it("should select item case-insensitively when using selectedValue", () => { + cy.mount( + + + + + + ); + + cy.get("[ui5-combobox]") + .as("combobox") + .shadow() + .find("input") + .as("input"); + + cy.get("@input").realClick(); + cy.get("@input").realType("i"); + cy.get("@input").realType("t"); + cy.get("@input").realType("e"); + cy.get("@input").realType("m"); + cy.get("@input").realType(" "); + cy.get("@input").realType("2"); + + cy.get("@combobox").should("have.prop", "value", "Item 2"); + cy.get("[ui5-cb-item]").eq(1).should("have.prop", "selected", true); + cy.get("@combobox").should("have.prop", "selectedValue", "item-2"); + }); + + it("should handle progressive typing with mixed case", () => { + cy.mount( + + + + + + ); + + cy.get("[ui5-combobox]") + .as("combobox") + .shadow() + .find("input") + .as("input"); + + cy.get("@input").realClick(); + cy.get("@input").realType("B"); + cy.get("@combobox").should("have.prop", "value", "Belgium"); + + cy.get("@input").realType("u"); + cy.get("@combobox").should("have.prop", "value", "Bulgaria"); + + cy.get("@input").realType("l"); + cy.get("@combobox").should("have.prop", "value", "Bulgaria"); + cy.get("[ui5-cb-item]").eq(1).should("have.prop", "selected", true); + }); +}); diff --git a/packages/main/src/ComboBox.ts b/packages/main/src/ComboBox.ts index 262527a37bef..44ea07993ce6 100644 --- a/packages/main/src/ComboBox.ts +++ b/packages/main/src/ComboBox.ts @@ -1229,9 +1229,9 @@ class ComboBox extends UI5Element implements IFormInputElement { if (matchingItems.length) { let exactMatch; if (this._useSelectedValue) { - exactMatch = matchingItems.find(item => item.value === (currentlyFocusedItem?.value || this.selectedValue) && item.text === current); + exactMatch = matchingItems.find(item => item.value === (currentlyFocusedItem?.value || this.selectedValue) && item.text?.toLowerCase() === current.toLowerCase()); } else { - exactMatch = matchingItems.find(item => item.text === current); + exactMatch = matchingItems.find(item => item.text?.toLowerCase() === current.toLowerCase()); } return exactMatch ?? matchingItems[0]; @@ -1242,7 +1242,11 @@ class ComboBox extends UI5Element implements IFormInputElement { const value = (item && item.text) || ""; this.inner.value = value; - this.inner.setSelectionRange(filterValue.length, value.length); + + // select the whole value if it doesn't start with the filterValue, otherwise select only the autocompleted part + const startsWithFilter = value.toLowerCase().startsWith(filterValue.toLowerCase()); + const selectionStart = startsWithFilter ? filterValue.length : 0; + this.inner.setSelectionRange(selectionStart, value.length); this.value = value; if (this._useSelectedValue) { @@ -1275,16 +1279,16 @@ class ComboBox extends UI5Element implements IFormInputElement { if (!shouldSelectionBeCleared && !itemToBeSelected) { if (isInstanceOfComboBoxItemGroup(item)) { if (this._useSelectedValue) { - itemToBeSelected = item.items.find(i => i.value === valueToMatch && (this.value === "" || this.value === i.text)); + itemToBeSelected = item.items.find(i => i.value === valueToMatch && (this.value === "" || i.text?.toLowerCase() === this.value.toLowerCase())); } else { - itemToBeSelected = item.items?.find(i => i.text === this.value); + itemToBeSelected = item.items?.find(i => i.text?.toLowerCase() === this.value.toLowerCase()); } } else { if (this._useSelectedValue) { - itemToBeSelected = this.items.find(i => i.value === valueToMatch && (this.value === "" || this.value === i.text)); + itemToBeSelected = this.items.find(i => i.value === valueToMatch && (this.value === "" || i.text?.toLowerCase() === this.value.toLowerCase())); return; } - itemToBeSelected = item.text === this.value ? item : undefined; + itemToBeSelected = item.text?.toLowerCase() === this.value.toLowerCase() ? item : undefined; } } }); @@ -1405,7 +1409,7 @@ class ComboBox extends UI5Element implements IFormInputElement { _clear() { const selectedItem = this.items.find(item => item.selected); - if (selectedItem?.text === this.value) { + if (selectedItem?.text?.toLowerCase() === this.value.toLowerCase()) { this.fireDecoratorEvent("change"); } diff --git a/packages/main/test/pages/ComboBox.html b/packages/main/test/pages/ComboBox.html index 98423f3a6da0..88ca8ec15825 100644 --- a/packages/main/test/pages/ComboBox.html +++ b/packages/main/test/pages/ComboBox.html @@ -495,6 +495,15 @@

ComboBox Composition

}); +
+ ComboBox - items with lower case and upper case + + + + + + +