From 30d9d2bb990cc6dcb2d7a6a67d6c735fd86eb371 Mon Sep 17 00:00:00 2001 From: Boyan Rakilovski Date: Tue, 24 Nov 2020 13:37:20 +0200 Subject: [PATCH] feat(ui5-date-picker): component is now aligned with the specification (#2304) Focus handling is aligned with the KBH specification: When an year is selected from the year picker the day picker is shown and focus is set to the last selected date or to the current date. When a month is selected from the month picker the day picker is shown and focus is set to the last selected date or to the current date. When month picker is opened the focus is set to the selected month or to the current month if there are no selected dates. When year picker is opened the focus is set to the selected year or to the current year if there are no selected dates. Selection is applied in compliance with the UX specification, when a picker is opened: Calendar items from the month picker and year picker are not rendered selected, when there are no selected dates. Fixes #2151 --- packages/main/src/Calendar.js | 67 ++++++++++++------- packages/main/src/DatePicker.js | 14 +++- packages/main/src/DayPicker.js | 5 ++ packages/main/src/MonthPicker.js | 17 +++-- packages/main/src/YearPicker.js | 19 ++++-- packages/main/test/specs/Calendar.spec.js | 56 ++++++++++------ packages/main/test/specs/DatePicker.spec.js | 21 +++--- .../main/test/specs/MultiComboBox.spec.js | 2 +- 8 files changed, 134 insertions(+), 67 deletions(-) diff --git a/packages/main/src/Calendar.js b/packages/main/src/Calendar.js index d181c3541f8b..5d96be05d445 100644 --- a/packages/main/src/Calendar.js +++ b/packages/main/src/Calendar.js @@ -421,6 +421,8 @@ class Calendar extends UI5Element { _handleSelectedDatesChange(event) { this.selectedDates = [...event.detail.dates]; + this.timestamp = this.selectedDates[0]; + this.fireEvent("selected-dates-change", { dates: event.detail.dates }); } @@ -438,21 +440,6 @@ class Calendar extends UI5Element { } } - _handleSelectedMonthChange(event) { - const oNewDate = this._calendarDate; - const newMonthIndex = CalendarDate.fromTimestamp( - event.detail.timestamp * 1000, - this._primaryCalendarType - ).getMonth(); - - oNewDate.setMonth(newMonthIndex); - this.timestamp = oNewDate.valueOf() / 1000; - - this._hideMonthPicker(); - - this._focusFirstDayOfMonth(oNewDate); - } - _focusFirstDayOfMonth(targetDate) { let fistDayOfMonthIndex = -1; @@ -469,19 +456,35 @@ class Calendar extends UI5Element { dayPicker._itemNav.focusCurrent(); } + _handleSelectedMonthChange(event) { + const oNewDate = this._calendarDate; + const oFocusedDate = CalendarDate.fromTimestamp(event.detail.timestamp * 1000, this._primaryCalendarType); + + oNewDate.setMonth(oFocusedDate.getMonth()); + this.timestamp = oNewDate.valueOf() / 1000; + this._monthPicker.timestamp = this.timestamp; + + this._hideMonthPicker(); + this._setDayPickerCurrentIndex(oNewDate); + } + _handleSelectedYearChange(event) { - const oNewDate = CalendarDate.fromTimestamp( - event.detail.timestamp * 1000, - this._primaryCalendarType - ); - oNewDate.setMonth(0); - oNewDate.setDate(1); + const oNewDate = this._calendarDate; + const oFocusedDate = CalendarDate.fromTimestamp(event.detail.timestamp * 1000, this._primaryCalendarType); + oNewDate.setYear(oFocusedDate.getYear()); this.timestamp = oNewDate.valueOf() / 1000; + this._yearPicker.timestamp = this.timestamp; this._hideYearPicker(); + this._setDayPickerCurrentIndex(oNewDate); + } - this._focusFirstDayOfMonth(oNewDate); + _setDayPickerCurrentIndex(calDate) { + const currentDate = new CalendarDate(calDate); + const dayPicker = this.shadowRoot.querySelector("[ui5-daypicker]"); + const currentDateIndex = dayPicker._getVisibleDays(currentDate).findIndex(date => date.valueOf() === currentDate.valueOf()); + dayPicker._itemNav.currentIndex = currentDateIndex; } _handleMonthButtonPress() { @@ -565,11 +568,9 @@ class Calendar extends UI5Element { } }); - const weekDaysCount = 7; - if (lastDayOfMonthIndex !== -1) { // find the DOM for the last day index - const lastDay = dayPicker.shadowRoot.querySelector(".ui5-dp-content").children[parseInt(lastDayOfMonthIndex / weekDaysCount) + 1].children[(lastDayOfMonthIndex % weekDaysCount)]; + const lastDay = dayPicker.shadowRoot.querySelectorAll(".ui5-dp-content .ui5-dp-item")[lastDayOfMonthIndex]; // update current item in ItemNavigation dayPicker._itemNav.current = lastDayOfMonthIndex; @@ -675,6 +676,14 @@ class Calendar extends UI5Element { this._calendarWidth = calendarRect.width.toString(); this._calendarHeight = calendarRect.height.toString(); + + const monthPicker = this.shadowRoot.querySelector("[ui5-monthpicker]"); + monthPicker._selectedDates = [...this.selectedDates]; + const currentMonthIndex = monthPicker._itemNav._getItems().findIndex(item => { + const calDate = CalendarDate.fromTimestamp(parseInt(item.timestamp) * 1000, this._primaryCalendarType); + return calDate.getMonth() === this._calendarDate.getMonth(); + }); + monthPicker._itemNav.currentIndex = currentMonthIndex; this._header._isMonthButtonHidden = true; } @@ -691,6 +700,14 @@ class Calendar extends UI5Element { this._calendarWidth = calendarRect.width.toString(); this._calendarHeight = calendarRect.height.toString(); + + const yearPicker = this.shadowRoot.querySelector("[ui5-yearpicker]"); + yearPicker._selectedDates = [...this.selectedDates]; + const currentYearIndex = yearPicker._itemNav._getItems().findIndex(item => { + const calDate = CalendarDate.fromTimestamp(parseInt(item.timestamp) * 1000, this._primaryCalendarType); + return calDate.getYear() === this._calendarDate.getYear(); + }); + yearPicker._itemNav.currentIndex = currentYearIndex; } _hideMonthPicker() { diff --git a/packages/main/src/DatePicker.js b/packages/main/src/DatePicker.js index c530d1f61702..2509a42ce83e 100644 --- a/packages/main/src/DatePicker.js +++ b/packages/main/src/DatePicker.js @@ -25,6 +25,7 @@ import { isPhone, isIE } from "@ui5/webcomponents-base/dist/Device.js"; import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; import "@ui5/webcomponents-icons/dist/appointment-2.js"; import "@ui5/webcomponents-icons/dist/decline.js"; +import RenderScheduler from "@ui5/webcomponents-base/dist/RenderScheduler.js"; import { DATEPICKER_OPEN_ICON_TITLE, DATEPICKER_DATE_ACC_TEXT, INPUT_SUGGESTIONS_TITLE } from "./generated/i18n/i18n-defaults.js"; import Icon from "./Icon.js"; import Button from "./Button.js"; @@ -419,7 +420,8 @@ class DatePicker extends UI5Element { calendar._hideYearPicker(); } }, - afterOpen: () => { + afterOpen: async () => { + await RenderScheduler.whenFinished(); const calendar = this.calendar; if (!calendar) { @@ -427,6 +429,7 @@ class DatePicker extends UI5Element { } const dayPicker = calendar.shadowRoot.querySelector(`#${calendar._id}-daypicker`); + dayPicker._inputLiveChangeTrigger = false; const selectedDay = dayPicker.shadowRoot.querySelector(".ui5-dp-item--selected"); const today = dayPicker.shadowRoot.querySelector(".ui5-dp-item--now"); let focusableDay = selectedDay || today; @@ -666,6 +669,15 @@ class DatePicker extends UI5Element { const emptyValue = nextValue === ""; const isValid = emptyValue || this._checkValueValidity(nextValue); + if (this.responsivePopover) { + const calendar = this.calendar; + const dayPicker = calendar.shadowRoot.querySelector(`#${calendar._id}-daypicker`); + // If day picker component rerendering is triggered due to a change in the date picker component input filed, + // then mark this trigger and avoid moving the focus from the date picker input field throughout the on after + // rendering hook of the day picker component + dayPicker._inputLiveChangeTrigger = true; + } + this.value = nextValue; this.fireEvent("input", { value: nextValue, valid: isValid }); } diff --git a/packages/main/src/DayPicker.js b/packages/main/src/DayPicker.js index b4f7d77fabb1..000aba442b88 100644 --- a/packages/main/src/DayPicker.js +++ b/packages/main/src/DayPicker.js @@ -389,6 +389,11 @@ class DayPicker extends UI5Element { onAfterRendering() { this._fireDayPickerRendered(); + if (this._inputLiveChangeTrigger) { + this._inputLiveChangeTrigger = false; + } else { + this._itemNav.focusCurrent(); + } } _onmousedown(event) { diff --git a/packages/main/src/MonthPicker.js b/packages/main/src/MonthPicker.js index 6cf5b5198f8e..d2bae6defc9e 100644 --- a/packages/main/src/MonthPicker.js +++ b/packages/main/src/MonthPicker.js @@ -64,6 +64,11 @@ const metadata = { type: String, }, + _selectedDates: { + type: Integer, + multiple: true, + }, + _quarters: { type: Object, multiple: true, @@ -160,15 +165,18 @@ class MonthPicker extends UI5Element { ItemNavigation.BORDER_REACH, this._handleItemNavigationBorderReach.bind(this) ); + + this._selectedDates = []; } onBeforeRendering() { const localeData = getCachedLocaleDataInstance(getLocale()); const quarters = []; - const oCalDate = CalendarDate.fromTimestamp(new Date().getTime(), this._primaryCalendarType); + const oCalDate = this._calendarDate; let timestamp; + /* eslint-disable no-loop-func */ for (let i = 0; i < 12; i++) { oCalDate.setMonth(i); timestamp = oCalDate.valueOf() / 1000; @@ -176,11 +184,12 @@ class MonthPicker extends UI5Element { const month = { timestamp: timestamp.toString(), id: `${this._id}-m${i}`, + selected: this._selectedDates.some(d => d === timestamp), name: localeData.getMonths("wide", this._primaryCalendarType)[i], classes: "ui5-mp-item", }; - if (this._month === i) { + if (month.selected) { month.classes += " ui5-mp-item--selected"; } @@ -233,8 +242,8 @@ class MonthPicker extends UI5Element { _onmousedown(event) { if (event.target.className.indexOf("ui5-mp-item") > -1) { const targetTimestamp = this.getTimestampFromDOM(event.target); - const focusedItem = this._itemNav._getItems().find(item => parseInt(item.timestamp) === targetTimestamp); - this._itemNav.currentIndex = this._itemNav._getItems().indexOf(focusedItem); + const focusedItemIndex = this._itemNav._getItems().findIndex(item => parseInt(item.timestamp) === targetTimestamp); + this._itemNav.currentIndex = focusedItemIndex; this._itemNav.focusCurrent(); } } diff --git a/packages/main/src/YearPicker.js b/packages/main/src/YearPicker.js index 2a6774479208..d08d59308ab0 100644 --- a/packages/main/src/YearPicker.js +++ b/packages/main/src/YearPicker.js @@ -66,6 +66,11 @@ const metadata = { defaultValue: undefined, }, + _selectedDates: { + type: Integer, + multiple: true, + }, + _selectedYear: { type: Integer, noAttribute: true, @@ -165,6 +170,7 @@ class YearPicker extends UI5Element { ); this._yearIntervals = []; + this._selectedDates = []; } onBeforeRendering() { @@ -190,6 +196,7 @@ class YearPicker extends UI5Element { this._selectedYear = this._year; } + /* eslint-disable no-loop-func */ for (let i = 0; i < YearPicker._ITEMS_COUNT; i++) { const intervalIndex = parseInt(i / 4); if (!intervals[intervalIndex]) { @@ -203,11 +210,15 @@ class YearPicker extends UI5Element { const year = { timestamp: timestamp.toString(), id: `${this._id}-y${timestamp}`, + selected: this._selectedDates.some(itemTimestamp => { + const date = CalendarDate.fromTimestamp(itemTimestamp * 1000, this._primaryCalendarType); + return date.getYear() === oCalDate.getYear(); + }), year: oYearFormat.format(oCalDate.toLocalJSDate()), classes: "ui5-yp-item", }; - if (oCalDate.getYear() === this._selectedYear) { + if (year.selected) { year.classes += " ui5-yp-item--selected"; } @@ -256,8 +267,8 @@ class YearPicker extends UI5Element { _onmousedown(event) { if (event.target.className.indexOf("ui5-yp-item") > -1) { const targetTimestamp = this.getTimestampFromDom(event.target); - const focusedItem = this._itemNav._getItems().find(item => parseInt(item.timestamp) === targetTimestamp); - this._itemNav.currentIndex = this._itemNav._getItems().indexOf(focusedItem); + const focusedItemIndex = this._itemNav._getItems().findIndex(item => parseInt(item.timestamp) === targetTimestamp); + this._itemNav.currentIndex = focusedItemIndex; this._itemNav.focusCurrent(); } } @@ -413,7 +424,7 @@ class YearPicker extends UI5Element { } YearPicker._ITEMS_COUNT = 20; -YearPicker._MIDDLE_ITEM_INDEX = 7; +YearPicker._MIDDLE_ITEM_INDEX = 10; YearPicker.define(); diff --git a/packages/main/test/specs/Calendar.spec.js b/packages/main/test/specs/Calendar.spec.js index 6a53a1aa50f2..ab3dfe6405d2 100644 --- a/packages/main/test/specs/Calendar.spec.js +++ b/packages/main/test/specs/Calendar.spec.js @@ -61,64 +61,80 @@ describe("Calendar general interaction", () => { const calendar = browser.$("#calendar1"); const yearPicker = calendar.shadow$("ui5-yearpicker"); const YEAR = 1997; + calendar.setAttribute("timestamp", Date.UTC(YEAR) / 1000) + calendar.shadow$("ui5-calendar-header").shadow$(`div[data-sap-show-picker="Year"]`).click(); + assert.strictEqual(yearPicker.getProperty("_selectedYear"), YEAR, "Year is set"); - browser.execute((year) => { - const calendar = document.getElementById("calendar1"); - var newTimestamp = Date.UTC(year) / 1000; - calendar.timestamp = newTimestamp; - calendar._showYearPicker(); - }, YEAR); + calendar.shadow$("ui5-yearpicker").shadow$(`div[id="ui5wc_5-y852076800"]`).click(); + }); - assert.strictEqual(yearPicker.getProperty("_selectedYear"), YEAR, "Year is set"); + it("Calendar doesn't mark year as selected when there are no selected dates", () => { + const calendar = browser.$("#calendar1"); + calendar.setAttribute("timestamp", new Date(Date.UTC(2000, 10, 1, 0, 0, 0)).valueOf() / 1000); + calendar.shadow$("ui5-calendar-header").shadow$(`div[data-sap-show-picker="Year"]`).click(); + const focusedItem = calendar.shadow$("ui5-yearpicker").shadow$(`div[id="ui5wc_5-y946684800"]`); + + assert.ok(focusedItem.isFocusedDeep(), "Current year element is the acrive element"); + assert.notOk(focusedItem.hasClass("ui5-mp-item--selected"), "Current year is not selected"); + focusedItem.click(); }); - it("Page up/down increments/decrements the month value", () => { + it("Calendar doesn't mark month as selected when there are no selected dates", () => { const calendar = browser.$("#calendar1"); - calendar.setProperty("timestamp", new Date(Date.UTC(2000, 9, 1, 0, 0, 0)).valueOf() / 1000); + calendar.setAttribute("timestamp", new Date(Date.UTC(2000, 10, 1, 0, 0, 0)).valueOf() / 1000); + calendar.shadow$("ui5-calendar-header").shadow$(`div[data-sap-show-picker="Month"]`).click(); + const focusedItem = calendar.shadow$("ui5-monthpicker").shadow$(`div[id="ui5wc_4-m10"]`); - browser.execute(() => document.getElementById("calendar1")._hideYearPicker()); + assert.ok(focusedItem.isFocusedDeep(), "Current month element is the acrive element"); + assert.notOk(focusedItem.hasClass("ui5-mp-item--selected"), "Current month is not selected"); + focusedItem.click(); + }); + + it("Page up/down increments/decrements the month value", () => { + const calendar = browser.$("#calendar1"); + calendar.setAttribute("timestamp", new Date(Date.UTC(2000, 10, 1, 0, 0, 0)).valueOf() / 1000); calendar.shadow$("ui5-daypicker").shadow$(".ui5-dp-days-names-container").click(); browser.keys('PageUp'); - assert.deepEqual(new Date(calendar.getProperty("timestamp") * 1000), new Date(Date.UTC(2000, 8, 1, 0, 0, 0))); + assert.deepEqual(new Date(calendar.getProperty("timestamp") * 1000), new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); browser.keys('PageDown'); - assert.deepEqual(new Date(calendar.getProperty("timestamp") * 1000), new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); + assert.deepEqual(new Date(calendar.getProperty("timestamp") * 1000), new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); }); it("Shift + Page up/down increments/decrements the year value by one", () => { const calendar = browser.$("#calendar1"); - calendar.setProperty("timestamp", new Date(Date.UTC(2000, 9, 1, 0, 0, 0)).valueOf() / 1000); + calendar.setAttribute("timestamp", new Date(Date.UTC(2000, 10, 1, 0, 0, 0)).valueOf() / 1000); calendar.shadow$("ui5-daypicker").shadow$(".ui5-dp-days-names-container").click(); browser.keys(['Shift', 'PageUp']); - assert.deepEqual(new Date(calendar.getProperty("timestamp") * 1000), new Date(Date.UTC(1999, 9, 1, 0, 0, 0))); + assert.deepEqual(new Date(calendar.getProperty("timestamp") * 1000), new Date(Date.UTC(1999, 10, 1, 0, 0, 0))); browser.keys(['Shift', 'PageDown']); - assert.deepEqual(new Date(calendar.getProperty("timestamp") * 1000), new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); + assert.deepEqual(new Date(calendar.getProperty("timestamp") * 1000), new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); }); it("Ctrl + Shift + Page up/down increments/decrements the year value by ten", () => { const calendar = browser.$("#calendar1"); - calendar.setProperty("timestamp", new Date(Date.UTC(2000, 9, 1, 0, 0, 0)).valueOf() / 1000); + calendar.setAttribute("timestamp", new Date(Date.UTC(2000, 10, 1, 0, 0, 0)).valueOf() / 1000); calendar.shadow$("ui5-daypicker").shadow$(".ui5-dp-days-names-container").click(); browser.keys(['Control', 'Shift', 'PageUp']); - assert.deepEqual(new Date(calendar.getProperty("timestamp") * 1000), new Date(Date.UTC(1990, 9, 1, 0, 0, 0))); + assert.deepEqual(new Date(calendar.getProperty("timestamp") * 1000), new Date(Date.UTC(1990, 10, 1, 0, 0, 0))); browser.keys(['Control', 'Shift', 'PageDown']); - assert.deepEqual(new Date(calendar.getProperty("timestamp") * 1000), new Date(Date.UTC(2000, 9, 1, 0, 0, 0))); + assert.deepEqual(new Date(calendar.getProperty("timestamp") * 1000), new Date(Date.UTC(2000, 10, 1, 0, 0, 0))); }); it("Page up/down increments/decrements the year value in the month picker", () => { const calendar = browser.$("#calendar1"); - calendar.setProperty("timestamp", new Date(Date.UTC(2000, 9, 1, 0, 0, 0)).valueOf() / 1000); + calendar.setAttribute("timestamp", new Date(Date.UTC(2000, 9, 1, 0, 0, 0)).valueOf() / 1000); browser.keys(["F4"]); browser.keys('PageUp'); @@ -132,7 +148,7 @@ describe("Calendar general interaction", () => { it("Page up/down increments/decrements the year range in the year picker", () => { const calendar = browser.$("#calendar1"); - calendar.setProperty("timestamp", new Date(Date.UTC(2000, 9, 1, 0, 0, 0)).valueOf() / 1000); + calendar.setAttribute("timestamp", new Date(Date.UTC(2000, 9, 1, 0, 0, 0)).valueOf() / 1000); browser.keys(['Shift', 'F4']); browser.keys('PageUp'); diff --git a/packages/main/test/specs/DatePicker.spec.js b/packages/main/test/specs/DatePicker.spec.js index ae8649c893ed..366690641b7f 100644 --- a/packages/main/test/specs/DatePicker.spec.js +++ b/packages/main/test/specs/DatePicker.spec.js @@ -522,7 +522,7 @@ describe("Date Picker Tests", () => { datepicker.open(); datepicker.id = "#dp12"; - datepicker.innerInput.setValue("Jan 1, 0009"); + datepicker.innerInput.setValue("Jan 1, 0012"); datepicker.valueHelpIcon.click(); datepicker.btnYear.click(); @@ -547,7 +547,7 @@ describe("Date Picker Tests", () => { datepicker.btnYear.click(); - assert.ok(datepicker.getFirstDisplayedYear().getProperty("innerHTML").indexOf("9979") > -1, "First year in the year picker is correct"); + assert.ok(datepicker.getFirstDisplayedYear().getProperty("innerHTML").indexOf("9976") > -1, "First year in the year picker is correct"); datepicker.btnNext.click(); @@ -567,20 +567,20 @@ describe("Date Picker Tests", () => { datepicker.btnYear.click(); - var tenthYear = datepicker.getDisplayedYear(9); - assert.ok(tenthYear.getProperty("innerHTML").indexOf("9988") > -1, "Tenth year in the year picker is correct"); + var tenthYear = datepicker.getDisplayedYear(10); + assert.ok(tenthYear.getProperty("innerHTML").indexOf("9986") > -1, "Tenth year in the year picker is correct"); tenthYear.click(); datepicker.btnYear.click(); - assert.ok(datepicker.getFirstDisplayedYear().getProperty("innerHTML").indexOf("9980") > -1, "First year in the year picker is correct"); + assert.ok(datepicker.getFirstDisplayedYear().getProperty("innerHTML").indexOf("9976") > -1, "First year in the year picker is correct"); }); it("yearpicker click extreme values min", () => { datepicker.open(); datepicker.id = "#dp12"; - datepicker.innerInput.setValue("Jan 1, 0009"); + datepicker.innerInput.setValue("Jan 1, 0012"); datepicker.valueHelpIcon.click(); datepicker.btnYear.click(); @@ -688,12 +688,9 @@ describe("Date Picker Tests", () => { datepicker.openPicker({ focusInput: false }); datepicker.btnYear.click(); - assert.ok(datepicker.getDisplayedYear(10).hasClass("ui5-yp-item--disabled"), "Years out of range are disabled"); - datepicker.root.keys("ArrowDown"); - datepicker.root.keys("ArrowRight"); - datepicker.root.keys("ArrowRight"); + assert.ok(datepicker.getDisplayedYear(11).hasClass("ui5-yp-item--disabled"), "Years out of range are disabled"); datepicker.root.keys("ArrowRight"); - assert.ok(datepicker.getDisplayedYear(7).isFocusedDeep(), "Years out of range can not be reached with keyboard"); + assert.ok(datepicker.getDisplayedYear(0).isFocusedDeep(), "Years out of range can not be reached with keyboard"); }); it("Months are disabled when out of range", () => { @@ -820,7 +817,7 @@ describe("Date Picker Tests", () => { assert.strictEqual(lastColumn[firstColumn.length - 1].getAttribute("role"), "gridcell", "Each day have columnheader role attribute"); }); - it("DatePcker dates and week number", ()=>{ + it("DatePicker dates and week number", () => { browser.url("http://localhost:8080/test-resources/pages/DatePicker_test_page.html?sap-ui-language=en"); datepicker.root.setAttribute("primary-calendar-type", "Gregorian"); datepicker.id = "#dp13"; diff --git a/packages/main/test/specs/MultiComboBox.spec.js b/packages/main/test/specs/MultiComboBox.spec.js index cb35dfb62476..f2ba0b162f00 100644 --- a/packages/main/test/specs/MultiComboBox.spec.js +++ b/packages/main/test/specs/MultiComboBox.spec.js @@ -31,7 +31,7 @@ describe("MultiComboBox general interaction", () => { assert.notOk(mcb.getProperty("focused"), "MultiComboBox should no longer be focused."); input.keys("ArrowRight"); - browser.pause(300); + browser.pause(500); assert.ok(mcb.getProperty("focused"), "MultiComboBox should be focused again."); });