diff --git a/packages/main/cypress/specs/Input.cy.tsx b/packages/main/cypress/specs/Input.cy.tsx
index 67c036c394bb..1f5dd8f886e2 100644
--- a/packages/main/cypress/specs/Input.cy.tsx
+++ b/packages/main/cypress/specs/Input.cy.tsx
@@ -126,3 +126,460 @@ describe("Input Tests", () => {
.should("not.have.attr", "tabindex", "0");
});
});
+
+describe("Input general interaction", () => {
+ it("handles suggestions selection cancel with ESC", () => {
+ cy.mount(
+
+
+
+
+
+
+
+ );
+
+ cy.get("ui5-input")
+ .as("input");
+
+ cy.get("@input")
+ .shadow()
+ .find("ui5-responsive-popover")
+ .as("popover");
+
+ cy.get("@input")
+ .realClick();
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@input")
+ .realType("C");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@popover")
+ .should("have.attr", "open");
+
+ cy.get("@input")
+ .realPress("ArrowDown");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@input")
+ .should("have.attr", "value", "Titanium");
+
+ cy.get("@input")
+ .realPress("Escape");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@input")
+ .should("have.value", "C");
+ });
+
+ it("tests selection-change with custom items", () => {
+ cy.mount(
+
+
+
+
+
+
+
+ );
+
+ cy.get("ui5-input")
+ .as("input");
+
+ cy.get("@input")
+ .shadow()
+ .find("ui5-responsive-popover")
+ .as("popover");
+
+ cy.get("@input")
+ .realClick();
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@input")
+ .realType("c");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@popover")
+ .should("have.attr", "open");
+
+ cy.get("@input")
+ .realPress("ArrowDown");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@input")
+ .should("have.value", "Compact")
+ .should("not.have.attr", "focused");
+
+ cy.get("ui5-suggestion-item")
+ .eq(1)
+ .should("have.attr", "focused");
+
+ cy.get("@input")
+ .realPress("ArrowDown");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("ui5-suggestion-item")
+ .eq(2)
+ .should("have.attr", "focused");
+
+ cy.get("ui5-suggestion-item")
+ .eq(1)
+ .should("not.have.attr", "focused");
+ });
+});
+
+describe("Input arrow navigation", () => {
+ it("Value state header and group headers should be included in the arrow navigation", () => {
+ cy.mount(
+
+
+ Custom error value state message with a
Link.
+
+
+
+
+
+
+
+ );
+
+ cy.get("ui5-input")
+ .as("input");
+
+ cy.get("@input")
+ .realClick()
+ .realType("a")
+ .realPress("ArrowDown");
+
+ cy.get("@input")
+ .should("not.have.attr", "focused");
+
+ cy.get("@input")
+ .shadow()
+ .find("ui5-responsive-popover")
+ .as("ui5-responsive-popover");
+
+ cy.get("@ui5-responsive-popover")
+ .find("div")
+ .as("valueMessage")
+ .should("have.class", "ui5-responsive-popover-header--focused");
+
+ cy.get("@input")
+ .realPress("ArrowDown");
+
+ cy.get("@valueMessage")
+ .should("not.have.class", "ui5-responsive-popover-header--focused");
+
+ cy.get("ui5-suggestion-item")
+ .eq(0)
+ .should("have.attr", "focused");
+ });
+
+ it("Should navigate up and down through the suggestions popover with arrow keys", () => {
+ cy.mount(
+
+
+
+
+
+
+
+ );
+
+ cy.get("#myInput2")
+ .as("input");
+
+ cy.get("@input")
+ .shadow()
+ .find("ui5-responsive-popover")
+ .as("popover");
+
+ cy.get("@input").realClick();
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+ cy.get("@input").realType("c");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@popover")
+ .should("have.attr", "open");
+
+ cy.get("@input").realPress("ArrowDown");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("ui5-suggestion-item").eq(1).should("have.attr", "text", "Compact");
+ cy.get("@input").should("not.have.attr", "focused");
+ cy.get("ui5-suggestion-item").eq(1).should("have.attr", "focused");
+
+ cy.get("@input")
+ .realPress("ArrowDown");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("ui5-suggestion-item").eq(2).should("have.attr", "focused");
+ cy.get("ui5-suggestion-item").eq(1).should("not.have.attr", "focused");
+
+ cy.get("@input")
+ .realPress("ArrowUp");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("ui5-suggestion-item").eq(1).should("have.attr", "focused");
+ cy.get("ui5-suggestion-item").eq(2).should("not.have.attr", "focused");
+
+ cy.get("@input").realPress("ArrowUp");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+ cy.get("@input").realPress("ArrowUp");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@input").should("have.attr", "focused");
+ cy.get("ui5-suggestion-item").first().should("not.have.attr", "focused");
+ });
+});
+
+describe("Input PAGEUP/PAGEDOWN navigation", () => {
+ beforeEach(() => {
+ cy.mount(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ });
+ it("Should focus the tenth item from the suggestions popover with PAGEDOWN", () => {
+ cy.get("ui5-input")
+ .as("input");
+
+ cy.get("@input")
+ .realClick();
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@input")
+ .realType("a");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@input")
+ .realPress("ArrowDown");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@input")
+ .realPress("PageDown");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("ui5-suggestion-item")
+ .eq(11)
+ .should("have.attr", "text", "Antigua and Barbuda");
+
+ cy.get("ui5-suggestion-item")
+ .eq(11)
+ .should("have.attr", "focused");
+ });
+
+ it("Should focus the -10 item/group header from the suggestions popover with PAGEUP", () => {
+ cy.get("ui5-input")
+ .as("input");
+
+ cy.get("@input")
+ .realClick();
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@input")
+ .realType("a");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@input")
+ .realPress("ArrowUp");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("ui5-suggestion-item-group")
+ .eq(0)
+ .should("have.attr", "focused");
+
+ cy.get("@input")
+ .realPress("PageDown");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("@input")
+ .realPress("PageUp");
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(200);
+
+ cy.get("ui5-suggestion-item-group")
+ .eq(0)
+ .should("have.attr", "focused");
+ });
+});
+
+describe("Selection-change event", () => {
+ it("Selection-change event fires with null arguments when suggestion was selected but user alters input value to something else", () => {
+ cy.mount(
+
+
+
+
+
+ );
+
+ cy.get("ui5-input")
+ .as("input");
+
+ cy.get("ui5-input")
+ .shadow()
+ .find("input")
+ .as("innerInput");
+
+ let eventCount = 0;
+
+ cy.get("@input").then($input => {
+ $input[0].addEventListener("ui5-selection-change", () => {
+ eventCount++;
+ });
+ });
+
+ cy.get("@innerInput")
+ .realClick();
+ cy.get("@innerInput")
+ .type("C");
+ cy.get("@innerInput")
+ .realPress("ArrowDown");
+ cy.get("@innerInput")
+ .realPress("Enter");
+
+ cy.get("@innerInput")
+ .should("have.value", "Compact");
+
+ cy.get("@innerInput")
+ .realClick();
+ cy.get("@innerInput")
+ .clear();
+ cy.get("@innerInput")
+ .type("N");
+ cy.get("@innerInput")
+ .realPress("Enter");
+
+ cy.get("@innerInput")
+ .should("have.value", "N");
+
+ cy.then(() => {
+ expect(eventCount).to.equal(2);
+ });
+ });
+});
+
+describe("Change event behavior when selecting the same suggestion item", () => {
+ let changeCount = 0;
+
+ beforeEach(() => {
+ cy.mount(
+
+
+
+
+
+
+
+
+
+ );
+
+ cy.get("#myInput")
+ .as("input");
+
+ cy.get("@input").then($el => {
+ $el[0].addEventListener("change", () => {
+ changeCount++;
+ });
+ });
+ });
+
+ it("Change event is not fired when the same suggestion item is selected (with typeahead)", () => {
+ cy.get("@input")
+ .realClick();
+
+ cy.get("@input")
+ .realType("a");
+
+ cy.get("@input").realPress("Enter");
+ cy.get("@input").should("have.value", "Afghanistan");
+
+ cy.get("@input").realPress("Backspace");
+ cy.get("@input").realPress("ArrowDown");
+ cy.get("@input").realPress("ArrowDown");
+ cy.get("@input").realPress("Enter");
+
+ cy.get("@input").should("have.value", "Afghanistan");
+ cy.then(() => {
+ expect(changeCount).to.equal(1);
+ });
+ });
+
+ it("Change event is not fired when the same suggestion item is selected (no-typeahead)", () => {
+ cy.get("@input").invoke("attr", "value", "Afghanistan");
+ cy.get("@input").invoke("attr", "no-typeahead", true);
+
+ cy.get("@input").realPress("Backspace");
+
+ cy.get("@input").realPress("ArrowDown");
+ cy.get("@input").realPress("ArrowDown");
+ cy.get("@input").realPress("Enter");
+
+ cy.get("@input").should("have.value", "Afghanistan");
+ cy.then(() => {
+ expect(changeCount).to.equal(1);
+ });
+ });
+
+ it("Change event is not fired when the same suggestion item is selected after focus out and selecting suggestion again", () => {
+ cy.get("@input")
+ .invoke("attr", "value", "Afghanistan");
+
+ cy.get("@input")
+ .realPress("Tab");
+
+ cy.get("@input")
+ .realClick();
+ cy.get("@input")
+ .realPress("ArrowDown");
+ cy.get("@input")
+ .realPress("ArrowDown");
+ cy.get("@input")
+ .realPress("Enter");
+
+ cy.get("@input").should("have.value", "Afghanistan");
+ cy.then(() => {
+ expect(changeCount).to.equal(1);
+ });
+ });
+});
diff --git a/packages/main/src/Input.ts b/packages/main/src/Input.ts
index bdc3d63e79cb..dc07c69154b1 100644
--- a/packages/main/src/Input.ts
+++ b/packages/main/src/Input.ts
@@ -573,6 +573,7 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
_shouldAutocomplete?: boolean;
_keyDown?: boolean;
_isKeyNavigation?: boolean;
+ _indexOfSelectedItem: number;
_selectedText?: string;
_clearIconClicked?: boolean;
_focusedAfterClear: boolean;
@@ -639,6 +640,8 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
this._isChangeTriggeredBySuggestion = false;
+ this._indexOfSelectedItem = -1;
+
this._handleResizeBound = this._handleResize.bind(this);
this._keepInnerValue = false;
@@ -717,6 +720,7 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
const item = this._getFirstMatchingItem(value);
if (item) {
this._handleTypeAhead(item);
+ this._selectMatchingItem(item);
}
}
}
@@ -810,15 +814,22 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
this._keyDown = false;
}
+ get currentItemIndex() {
+ const allItems = this.Suggestions?._getItems() as IInputSuggestionItemSelectable[];
+ const currentItem = allItems.find(item => { return item.selected || item.focused; });
+ const indexOfCurrentItem = currentItem ? allItems.indexOf(currentItem) : -1;
+ return indexOfCurrentItem;
+ }
+
_handleUp(e: KeyboardEvent) {
if (this.Suggestions?.isOpened()) {
- this.Suggestions.onUp(e);
+ this.Suggestions.onUp(e, this.currentItemIndex);
}
}
_handleDown(e: KeyboardEvent) {
if (this.Suggestions?.isOpened()) {
- this.Suggestions.onDown(e);
+ this.Suggestions.onDown(e, this.currentItemIndex);
}
}
@@ -1160,6 +1171,10 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
this.Suggestions?.onItemPress(e);
}
+ _selectMatchingItem(item: IInputSuggestionItemSelectable) {
+ item.selected = true;
+ }
+
_handleTypeAhead(item: IInputSuggestionItemSelectable) {
const value = item.text ? item.text : "";
@@ -1201,10 +1216,12 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
this.focused = false;
}
- if (this._changeToBeFired) {
+ if (this._changeToBeFired && !this._isChangeTriggeredBySuggestion) {
this.fireDecoratorEvent(INPUT_EVENTS.CHANGE);
- this._changeToBeFired = false;
+ } else {
+ this._isChangeTriggeredBySuggestion = false;
}
+ this._changeToBeFired = false;
this.open = false;
this.isTyping = false;
@@ -1402,7 +1419,6 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
if (shouldFireSelectionChange) {
this.fireSelectionChange(suggestionItem, true);
}
-
this.acceptSuggestion(suggestionItem, keyboardUsed);
}
diff --git a/packages/main/src/features/InputSuggestions.ts b/packages/main/src/features/InputSuggestions.ts
index 5705e954bffe..045b60ba8918 100644
--- a/packages/main/src/features/InputSuggestions.ts
+++ b/packages/main/src/features/InputSuggestions.ts
@@ -81,15 +81,17 @@ class Suggestions {
this.selectedItemIndex = -1;
}
- onUp(e: KeyboardEvent) {
+ onUp(e: KeyboardEvent, indexOfItem: number) {
e.preventDefault();
- this._handleItemNavigation(false /* forward */);
+ const index = !this.isOpened && this._hasValueState && indexOfItem === -1 ? 0 : indexOfItem;
+ this._handleItemNavigation(false /* forward */, index);
return true;
}
- onDown(e: KeyboardEvent) {
+ onDown(e: KeyboardEvent, indexOfItem: number) {
e.preventDefault();
- this._handleItemNavigation(true /* forward */);
+ const index = !this.isOpened && this._hasValueState && indexOfItem === -1 ? 0 : indexOfItem;
+ this._handleItemNavigation(true /* forward */, index);
return true;
}
@@ -298,11 +300,12 @@ class Suggestions {
return !!(this._getPicker()?.open);
}
- _handleItemNavigation(forward: boolean) {
+ _handleItemNavigation(forward: boolean, index: number) {
+ this.selectedItemIndex = index;
+
if (!this._getItems().length) {
return;
}
-
if (forward) {
this._selectNextItem();
} else {
@@ -312,6 +315,7 @@ class Suggestions {
_selectNextItem() {
const itemsCount = this._getItems().length;
+
const previousSelectedIdx = this.selectedItemIndex;
if (this._hasValueState && previousSelectedIdx === -1 && !this.component._isValueStateFocused) {
diff --git a/packages/main/test/specs/Input.spec.js b/packages/main/test/specs/Input.spec.js
index 486cc2327ed3..8425aa111d89 100644
--- a/packages/main/test/specs/Input.spec.js
+++ b/packages/main/test/specs/Input.spec.js
@@ -390,28 +390,6 @@ describe("Input general interaction", () => {
// assert.strictEqual(await suggestionsInput.getValue(), "Portugal", "First item has been selected again");
});
- it("handles suggestions selection cancel with ESC", async () => {
- await browser.url(`test/pages/Input.html`);
-
- const suggestionsInput = await browser.$("#myInputEsc");
-
- // act
- await suggestionsInput.click();
- await suggestionsInput.keys("c");
- await suggestionsInput.keys("ArrowDown");
-
- // assert
- assert.strictEqual(await suggestionsInput.getValue(), "Chromium",
- "The value is updated as the item has been previewed.");
-
- // act
- await suggestionsInput.keys("Escape");
-
- // assert
- assert.strictEqual(await suggestionsInput.getProperty("value"), "c",
- "The value is restored as ESC has been pressed.");
- });
-
it("Input value should correspond to suggestion item when it is clicked", async () => {
await browser.url(`test/pages/Input.html`);
@@ -759,27 +737,6 @@ describe("Input general interaction", () => {
assert.ok(await helpPopover.isDisplayedInViewport(), "The help popover remains open as the focus is within.");
});
- it("tests selection-change with custom items", async () => {
- await browser.url(`test/pages/Input.html`);
-
- const selChangeFireCount = $("#custom-items-selection-change-count");
- const selChangeItemIndex = $("#custom-items-selection-item-index");
- const input = await $("#input-custom-flat").shadow$("input");
-
- await input.click();
- await input.keys("a");
-
- await input.keys("ArrowDown");
-
- assert.strictEqual(await selChangeFireCount.getHTML(false), "1", "The selection-change event is fired once");
- assert.strictEqual(await selChangeItemIndex.getHTML(false), "0", "The selected item index is correct");
-
- await input.keys("ArrowDown");
-
- assert.strictEqual(await selChangeFireCount.getHTML(false), "2", "The selection-change event is fired twice");
- assert.strictEqual(await selChangeItemIndex.getHTML(false), "1", "The selected item index is correct");
- });
-
it("fires open event when suggestions picker is opened on typing", async () => {
await browser.url(`test/pages/Input.html`);
const input = await browser.$("#myInput");
@@ -864,50 +821,6 @@ describe("Input general interaction", () => {
assert.strictEqual(await suggestionsCount.getText(), "5 results are available", "Suggestions count is available since the suggestions popover is opened");
});
- it("Suggestions announcement", async () => {
- await browser.url(`test/pages/Input.html`);
-
- const inputWithGroups = await $("#inputCompact");
- const inputSuggestions = await $("#myInput2");
- const inputWithGroupsInnerInput = await inputWithGroups.shadow$("input");
- const inputWithGroupsAnnouncement = await inputWithGroups.shadow$(`#selectionText`);
- const suggestionsAnnouncement = await inputSuggestions.shadow$(`#selectionText`);
-
- //act
- await inputWithGroups.click();
-
- //assert
- assert.strictEqual(await inputWithGroupsAnnouncement.getText(), "", "Suggestions announcement is not available on initially");
-
- //act
- await inputWithGroupsInnerInput.keys("a");
- await inputWithGroupsInnerInput.keys("ArrowDown");
-
- //assert
- assert.strictEqual(await inputWithGroupsAnnouncement.getText(), "Group Header A", "Group item announcement should not contain the position and total count.");
-
- //act
- await inputWithGroupsInnerInput.keys("ArrowDown");
-
- const announcementText = await inputWithGroupsAnnouncement.getText();
-
- //assert
- assert.ok(announcementText.includes("List item 1 of 12"), "The total count announcement and position of items should exclude group items.");
- assert.strictEqual(await inputWithGroupsAnnouncement.getText(), "explore List item 1 of 12", "The additional text is announced");
- await inputWithGroupsInnerInput.keys("Backspace");
-
- // Close suggestions to not intercept the click in the input below for the last test
- await inputWithGroupsInnerInput.keys("Escape");
-
- //act
- await inputSuggestions.click();
- await (await inputSuggestions.shadow$("input")).keys("c");
- await inputWithGroupsInnerInput.keys("ArrowDown");
-
- //assert
- assert.strictEqual(await suggestionsAnnouncement.getText(), "List item 1 of 5", "Item position and count is announced correctly");
- });
-
it("Should close the Popover when no suggestions are available", async () => {
await browser.url(`test/pages/Input.html`);
@@ -1128,81 +1041,12 @@ describe("Input general interaction", () => {
assert.strictEqual(await inner.getValue(), "", "Inner input's value should be empty");
});
- it("Change event is not fired when the same suggestion item is selected (with typeahead) - #8912", async () => {
- const suggestionsInput = await browser.$("#myInput");
-
- await suggestionsInput.click();
- await suggestionsInput.keys("a");
-
- await suggestionsInput.keys("ArrowDown");
- await suggestionsInput.keys("ArrowDown");
- await suggestionsInput.keys("Enter");
-
- const changeCount = await browser.$("#myInput-change-count");
-
- // Assert
- assert.strictEqual(await changeCount.getHTML(false), "1", "The change event is called once");
- assert.strictEqual(await suggestionsInput.getValue(), "Afghanistan", "Input's value should be the text of the selected item");
-
- await suggestionsInput.keys("Backspace");
-
- await suggestionsInput.keys("ArrowDown");
- await suggestionsInput.keys("ArrowDown");
- await suggestionsInput.keys("Enter");
-
- assert.strictEqual(await changeCount.getHTML(false), "1", "The change event is still called once");
- assert.strictEqual(await suggestionsInput.getValue(), "Afghanistan", "Input's value should be the text of the selected item");
- });
-
- it("Change event is not fired when the same suggestion item is selected (no-typeahead) - #8912", async () => {
- const suggestionsInput = await browser.$("#myInput");
- await browser.execute(() => {
- document.querySelector("#myInput").noTypeahead = true;
- });
-
- await suggestionsInput.keys("Backspace");
-
- await suggestionsInput.keys("ArrowDown");
- await suggestionsInput.keys("ArrowDown");
- await suggestionsInput.keys("Enter");
-
- const changeCount = await browser.$("#myInput-change-count");
-
- assert.strictEqual(await changeCount.getHTML(false), "1", "The change event is still called once");
- assert.strictEqual(await suggestionsInput.getValue(), "Afghanistan", "Input's value should be the text of the selected item");
-
- // restore the default property value
- await browser.execute(() => {
- document.querySelector("#myInput").noTypeahead = false;
- });
- });
-
- it("Change event is not fired when the same suggestion item is selected after focus out and selecting suggestion again - #8912", async () => {
- const suggestionsInput = await browser.$("#myInput");
- const changeCount = await browser.$("#myInput-change-count");
-
- assert.strictEqual(await changeCount.getHTML(false), "1", "The change event is called once");
- assert.strictEqual(await suggestionsInput.getValue(), "Afghanistan", "Input's value should be the text of the selected item");
-
- await suggestionsInput.keys("Tab");
-
- await suggestionsInput.click();
- await suggestionsInput.keys("Backspace");
- await suggestionsInput.keys("ArrowDown");
- await suggestionsInput.keys("ArrowDown");
- await suggestionsInput.keys("Enter");
-
- // Assert
- assert.strictEqual(await changeCount.getHTML(false), "1", "The change event is still called once");
- assert.strictEqual(await suggestionsInput.getValue(), "Afghanistan", "Input's value should be the text of the selected item");
- });
-
it("Tests prevented input event", async () => {
const input = await $("#prevent-input-event");
const innerInput = await input.shadow$("input");
await input.click();
-
+
await innerInput.keys("a");
await innerInput.keys("b");
await innerInput.keys("c");
@@ -1222,196 +1066,6 @@ describe("Input general interaction", () => {
});
});
-describe("Input arrow navigation", () => {
-
- it("Should navigate up and down through the suggestions popover with arrow keys", async () => {
- await browser.url(`test/pages/Input.html`);
-
- const suggestionsInput = await browser.$("#myInput2");
-
- await suggestionsInput.click();
- await suggestionsInput.keys("c");
- await suggestionsInput.keys("ArrowDown");
-
- const firstListItem = await suggestionsInput.$("ui5-suggestion-item");
-
- assert.strictEqual(await suggestionsInput.getValue(), "Cozy", "First item has been selected");
- assert.strictEqual(await suggestionsInput.getProperty("focused"), false, "Input is not focused");
- assert.strictEqual(await firstListItem.getProperty("focused"), true, "First list item is focused");
-
- await suggestionsInput.keys("ArrowDown");
- const secondListItem = await suggestionsInput.$$("ui5-suggestion-item")[1];
-
- assert.strictEqual(await suggestionsInput.getProperty("focused"), false, "Input is not focused");
- assert.strictEqual(await suggestionsInput.getProperty("focused"), false, "Input is not focused");
- assert.strictEqual(await secondListItem.getProperty("focused"), true, "Second list item is focused");
-
- await suggestionsInput.keys("ArrowUp");
-
- assert.strictEqual(await firstListItem.getProperty("focused"), true, "First list item is focused");
- assert.strictEqual(await secondListItem.getProperty("focused"), false, "Second list item is not focused");
-
- await suggestionsInput.keys("ArrowUp");
-
- assert.strictEqual(await suggestionsInput.getProperty("focused"), true, "Input is focused");
- assert.strictEqual(await firstListItem.getProperty("focused"), false, "First list item is not focused");
- });
-
- it("Value state header and group headers should be included in the arrow navigation", async () => {
- await browser.url(`test/pages/Input.html`);
-
- const suggestionsInput = await browser.$("#inputError");
-
- await suggestionsInput.click();
- await suggestionsInput.keys("a");
- await suggestionsInput.keys("ArrowDown");
-
- const respPopover = await suggestionsInput.shadow$("ui5-responsive-popover");
- const valueStateHeader = await respPopover.$(".ui5-responsive-popover-header.ui5-valuestatemessage-root");
- const firstListItem = suggestionsInput.$("ui5-suggestion-item");
- const groupHeader = suggestionsInput.$("ui5-suggestion-item-group");
-
- assert.strictEqual(await suggestionsInput.getValue(), "a", "Input's value should be the typed-in value");
- assert.strictEqual(await suggestionsInput.getProperty("focused"), false, "Input is not focused");
- assert.strictEqual(await firstListItem.getProperty("focused"), false, "First list item is not focused");
- assert.strictEqual(await groupHeader.getProperty("focused"), false, "Group header is not focused");
- assert.strictEqual(await suggestionsInput.getProperty("_isValueStateFocused"), true, "Value State should not be focused");
- assert.strictEqual(await valueStateHeader.hasClass("ui5-responsive-popover-header--focused"), true, "Value state header is focused");
-
- await suggestionsInput.keys("ArrowDown");
-
- assert.strictEqual(await suggestionsInput.getProperty("focused"), false, "Input is not focused");
- assert.strictEqual(await firstListItem.getProperty("focused"), false, "First list item is not focused");
- assert.strictEqual(await groupHeader.getProperty("focused"), true, "Group header is focused");
- assert.strictEqual(await valueStateHeader.hasClass("ui5-responsive-popover-header--focused"), false, "Value state header is not focused");
-
- await suggestionsInput.keys("ArrowDown");
-
- assert.strictEqual(await suggestionsInput.getValue(), "Afghanistan", "Input's value should be the text of the selected item");
- assert.strictEqual(await suggestionsInput.getProperty("focused"), false, "Input is not focused");
- assert.strictEqual(await firstListItem.getProperty("focused"), true, "First list item is focused");
- assert.strictEqual(await groupHeader.getProperty("focused"), false, "Group header is no longer focused");
- assert.strictEqual(await valueStateHeader.hasClass("ui5-responsive-popover-header--focused"), false, "Value state header is not focused");
-
- await suggestionsInput.keys("ArrowUp");
-
- assert.strictEqual(await suggestionsInput.getProperty("focused"), false, "Input is not focused");
- assert.strictEqual(await firstListItem.getProperty("focused"), false, "First list item is not focused");
- assert.strictEqual(await groupHeader.getProperty("focused"), true, "Group header is focused");
- assert.strictEqual(await valueStateHeader.hasClass("ui5-responsive-popover-header--focused"), false, "Value state header is not focused");
-
-
- await suggestionsInput.keys("ArrowUp");
-
- assert.strictEqual(await suggestionsInput.getProperty("focused"), false, "Input is not focused");
- assert.strictEqual(await firstListItem.getProperty("focused"), false, "First list item is not focused");
- assert.strictEqual(await groupHeader.getProperty("focused"), false, "Group header is not focused");
- assert.strictEqual(await suggestionsInput.getProperty("_isValueStateFocused"), true, "Value State should not be focused");
- assert.strictEqual(await valueStateHeader.hasClass("ui5-responsive-popover-header--focused"), true, "Value state header is focused");
-
- await suggestionsInput.keys("ArrowUp");
-
- assert.strictEqual(await suggestionsInput.getProperty("focused"), true, "Input is focused");
- assert.strictEqual(await firstListItem.getProperty("focused"), false, "First list item is not focused");
- assert.strictEqual(await groupHeader.getProperty("focused"), false, "Group header is not focused");
- assert.strictEqual(await valueStateHeader.hasClass("ui5-responsive-popover-header--focused"), false, "Value state header is not focused");
- });
-
- it("Items should not hide behind value state header on arrow up navigation", async () => {
- await browser.url(`test/pages/Input.html`);
- await browser.setWindowSize(1000, 400);
-
- const input = await browser.$("#inputError");
- await input.scrollIntoView();
- await input.click();
- await input.keys("a");
-
- let isInVisibleArea = await browser.executeAsync(async done => {
- const input = document.getElementById("inputError");
- const listItems = input.querySelectorAll("ui5-suggestion-item");
- const elementRect = listItems[6].getBoundingClientRect(); //Suggestion item "Angola"
-
- const popover = input.shadowRoot.querySelector("ui5-responsive-popover");
- const scrollableRect = popover.shadowRoot.querySelector(".ui5-popup-content").getBoundingClientRect();
-
- // Check if the element is within the visible area
- const isElementAboveViewport = elementRect.bottom < scrollableRect.top;
- const isElementBelowViewport = elementRect.top > scrollableRect.bottom;
- const isElementLeftOfViewport = elementRect.right < scrollableRect.left;
- const isElementRightOfViewport = elementRect.left > scrollableRect.right;
-
- const isListItemInVisibleArea = (
- !isElementAboveViewport &&
- !isElementBelowViewport &&
- !isElementLeftOfViewport &&
- !isElementRightOfViewport
- );
-
- done(isListItemInVisibleArea);
- });
-
- assert.notOk(isInVisibleArea, "Item 'Angola' should not be displayed in the viewport");
-
- // click ArrowDown 9 times - 1 time through VSH and 1 through group header and 7 times through the list items
- await input.keys(["ArrowDown", "ArrowDown", "ArrowDown", "ArrowDown", "ArrowDown", "ArrowDown", "ArrowDown", "ArrowDown", "ArrowDown"]);
-
- isInVisibleArea = isInVisibleArea = await browser.executeAsync(async done => {
- const input = document.getElementById("inputError");
- const listItems = input.querySelectorAll("ui5-suggestion-item");
- const elementRect = listItems[6].getBoundingClientRect(); //Suggestion item "Angola"
-
- const popover = input.shadowRoot.querySelector("ui5-responsive-popover");
- const scrollableRect = popover.shadowRoot.querySelector(".ui5-popup-content").getBoundingClientRect();
-
- // Check if the element is within the visible area
- const isElementAboveViewport = elementRect.bottom < scrollableRect.top;
- const isElementBelowViewport = elementRect.top > scrollableRect.bottom;
- const isElementLeftOfViewport = elementRect.right < scrollableRect.left;
- const isElementRightOfViewport = elementRect.left > scrollableRect.right;
-
- const isListItemInVisibleArea = (
- !isElementAboveViewport &&
- !isElementBelowViewport &&
- !isElementLeftOfViewport &&
- !isElementRightOfViewport
- );
-
- done(isListItemInVisibleArea);
- });
-
- assert.ok(isInVisibleArea, "Item 'Angola' should be displayed in the viewport");
-
- // click ArrowUp 6 times through the list items to trigger scrolling and reach the first suggestion item
- await input.keys(["ArrowUp", "ArrowUp", "ArrowUp", "ArrowUp", "ArrowUp", "ArrowUp"]);
-
- isInVisibleArea = await browser.executeAsync(async done => {
- const input = document.getElementById("inputError");
- const listItems = input.querySelectorAll("ui5-suggestion-item");
- const elementRect = listItems[0].getBoundingClientRect(); //Suggestion item "Afganistan"
-
- const popover = input.shadowRoot.querySelector("ui5-responsive-popover");
- const scrollableRect = popover.shadowRoot.querySelector(".ui5-popup-content").getBoundingClientRect();
-
- // Check if the element is within the visible area
- const isElementAboveViewport = elementRect.bottom < scrollableRect.top;
- const isElementBelowViewport = elementRect.top > scrollableRect.bottom;
- const isElementLeftOfViewport = elementRect.right < scrollableRect.left;
- const isElementRightOfViewport = elementRect.left > scrollableRect.right;
-
- const isListItemInVisibleArea = (
- !isElementAboveViewport &&
- !isElementBelowViewport &&
- !isElementLeftOfViewport &&
- !isElementRightOfViewport
- );
-
- done(isListItemInVisibleArea);
- });
-
- assert.ok(isInVisibleArea, "Item 'Afganistan' should be displayed in the viewport");
- });
-});
-
describe("Input HOME navigation", () => {
it("Should move caret to beginning of input with HOME if focus is on Input", async () => {
await browser.url(`test/pages/Input.html`);
@@ -1587,48 +1241,6 @@ describe("Input PAGEUP/PAGEDOWN navigation", () => {
assert.strictEqual(await firstListItem.getProperty("focused"), false, "Responsive popover remains open and first list item is not focused");
});
-
- it("Should focus the tenth item from the suggestions popover with PAGEDOWN", async () => {
- await browser.url(`test/pages/Input.html`);
-
- const suggestionsInput = await browser.$("#myInput");
-
- await suggestionsInput.click();
- await suggestionsInput.keys("a");
-
- // Moving focus to suggestions popover, because by design PAGEDOWN does nothing if focus is on input
- await suggestionsInput.keys("ArrowDown");
-
- await suggestionsInput.keys("PageDown");
-
- const tenthListItem = await suggestionsInput.$("ui5-suggestion-item:nth-of-type(10)");
-
- assert.strictEqual(await suggestionsInput.getValue(), "Azerbaijan", "Tenth item has been selected");
- assert.strictEqual(await suggestionsInput.getProperty("focused"), false, "Input is not focused");
- assert.strictEqual(await tenthListItem.getProperty("focused"), true, "Tenth list item is focused");
- });
-
- it("Should focus the -10 item/group header from the suggestions popover with PAGEUP", async () => {
- await browser.url(`test/pages/Input.html`);
-
- const suggestionsInput = await browser.$("#myInput");
- await suggestionsInput.scrollIntoView();
-
- await suggestionsInput.click();
- await suggestionsInput.keys("a");
-
- // Moving focus to suggestions popover, because by design PAGEUP does nothing if focus is on input
- await suggestionsInput.keys("ArrowDown");
-
- await suggestionsInput.keys("PageDown");
- await suggestionsInput.keys("PageUp");
-
- const groupHeader = await suggestionsInput.$("ui5-suggestion-item-group");
-
- assert.strictEqual(await suggestionsInput.getValue(), "a", "No item has been selected");
- assert.strictEqual(await suggestionsInput.getProperty("focused"), false, "Input is not focused");
- assert.strictEqual(await groupHeader.getProperty("focused"), true, "Group header is focused");
- });
});
describe("XSS tests for suggestions", () => {
@@ -1780,30 +1392,6 @@ describe("Selection-change event", () => {
assert.strictEqual(await selectionChangeCount.getText(), "1", "Selection-change event was fired once");
});
-
- it("Selection-change event fires with null arguments when suggestion was selected but user alters input value to something else", async () => {
- await browser.url(`test/pages/Input.html`);
-
- const input = await $("#input-selection-change");
- const inner = await input.shadow$("input");
- const selectionChangeCount = await $("#input-selection-change-count");
- const selectionChangeValue = await $("#input-selection-change-value");
-
- await inner.click();
- await inner.keys("C");
-
- // select first item
- await input.keys("ArrowDown");
- assert.strictEqual(await selectionChangeCount.getText(), "1", "Selection-change event was fired once");
- assert.strictEqual(await selectionChangeValue.getText(), "Cozy", "Selection-change event was fired with arguments");
-
- await inner.click();
- await inner.keys("N"); // this value is not in the suggestions
- await inner.keys("Enter");
-
- assert.strictEqual(await selectionChangeCount.getText(), "2", "Selection-change event was fired twice");
- assert.strictEqual(await selectionChangeValue.getText(), "", "Selection-change event was fired with null arguments");
- });
});
describe("Property open", () => {