Skip to content
Snippets Groups Projects
Commit ddc75aca authored by Artur Fedorov's avatar Artur Fedorov :three: Committed by Phil Hughes
Browse files

This MR migrates legacy GlDropdown

This MR migrates legacy GlDropdown component
to newly created GlCollapsibleListbox which
is more suitable for the use case

Changelog: changed
EE: true
parent cbe61160
No related branches found
No related tags found
1 merge request!121309Migrate legacy GlDropdown in timezone_dropdown
<script>
import { GlDropdown, GlDropdownItem, GlSearchBoxByType } from '@gitlab/ui';
import { GlCollapsibleListbox } from '@gitlab/ui';
import { __ } from '~/locale';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
import { formatTimezone } from '~/lib/utils/datetime_utility';
export default {
name: 'TimezoneDropdown',
components: {
GlDropdown,
GlDropdownItem,
GlSearchBoxByType,
},
directives: {
autofocusonshow,
GlCollapsibleListbox,
},
props: {
value: {
......@@ -52,11 +46,10 @@ export default {
identifier: timezone.identifier,
}));
},
filteredResults() {
const lowerCasedSearchTerm = this.searchTerm.toLowerCase();
return this.timezones.filter((timezone) =>
timezone.formattedTimezone.toLowerCase().includes(lowerCasedSearchTerm),
);
filteredListboxItems() {
return this.timezones
.filter((timezone) => timezone.formattedTimezone.toLowerCase().includes(this.searchTerm))
.map(({ formattedTimezone }) => ({ value: formattedTimezone, text: formattedTimezone }));
},
selectedTimezoneLabel() {
return this.tzValue || __('Select timezone');
......@@ -68,14 +61,14 @@ export default {
},
},
methods: {
selectTimezone(selectedTimezone) {
this.tzValue = selectedTimezone.formattedTimezone;
selectTimezone(formattedTimezone) {
const selectedTimezone = this.timezones.find(
(timezone) => timezone.formattedTimezone === formattedTimezone,
);
this.tzValue = formattedTimezone;
this.$emit('input', selectedTimezone);
this.searchTerm = '';
},
isSelected(timezone) {
return this.tzValue === timezone.formattedTimezone;
},
initialTimezone(timezones, value) {
if (!value) {
return undefined;
......@@ -89,6 +82,9 @@ export default {
return undefined;
},
setSearchTerm(value) {
this.searchTerm = value?.toLowerCase();
},
},
};
</script>
......@@ -101,31 +97,16 @@ export default {
:value="timezoneIdentifier || value"
type="hidden"
/>
<gl-dropdown
:text="selectedTimezoneLabel"
:class="additionalClass"
<gl-collapsible-listbox
:items="filteredListboxItems"
:toggle-text="selectedTimezoneLabel"
:toggle-class="additionalClass"
:no-results-text="$options.translations.noResultsText"
:selected="tzValue"
block
lazy
menu-class="gl-w-full!"
v-bind="$attrs"
>
<gl-search-box-by-type v-model.trim="searchTerm" v-autofocusonshow autofocus />
<gl-dropdown-item
v-for="timezone in filteredResults"
:key="timezone.formattedTimezone"
:is-checked="isSelected(timezone)"
is-check-item
@click="selectTimezone(timezone)"
>
{{ timezone.formattedTimezone }}
</gl-dropdown-item>
<gl-dropdown-item
v-if="!filteredResults.length"
class="gl-pointer-events-none"
data-testid="noMatchingResults"
>
{{ $options.translations.noResultsText }}
</gl-dropdown-item>
</gl-dropdown>
searchable
@search="setSearchTerm"
@select="selectTimezone"
/>
</div>
</template>
......@@ -28,7 +28,7 @@
fill_in 'schedule-description', with: 'Test schedule description'
click_button 'Select timezone'
click_button '[UTC-12] International Date Line West'
page.find("li", text: "[UTC-12] International Date Line West").click
within_element(id: 'addScheduleModal') do
click_button 'Add schedule'
end
......
......@@ -529,13 +529,13 @@ def set_user_status_in_modal
end
it 'allows the user to select a time zone from a dropdown list of options' do
expect(page.find('.user-time-preferences .dropdown')).not_to have_css('.show')
expect(page).not_to have_selector('.user-time-preferences [data-testid="base-dropdown-menu"]')
page.find('.user-time-preferences .dropdown').click
page.find('.user-time-preferences .gl-new-dropdown-toggle').click
expect(page.find('.user-time-preferences .dropdown')).to have_css('.show')
expect(page.find('.user-time-preferences [data-testid="base-dropdown-menu"]')).to be_visible
page.find("button", text: "Arizona").click
page.find("li", text: "Arizona").click
expect(page).to have_field(:user_timezone, with: 'America/Phoenix', type: :hidden)
end
......
......@@ -413,8 +413,8 @@ def visit_pipelines_schedules
end
def select_timezone
find('[data-testid="schedule-timezone"] .dropdown-toggle').click
find("button", text: "Arizona").click
find('[data-testid="schedule-timezone"] .gl-new-dropdown-toggle').click
find("li", text: "Arizona").click
end
def select_target_branch
......
import { GlDropdownItem, GlDropdown, GlSearchBoxByType } from '@gitlab/ui';
import { GlCollapsibleListbox, GlListboxItem } from '@gitlab/ui';
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown/timezone_dropdown.vue';
......@@ -9,7 +9,8 @@ describe('Deploy freeze timezone dropdown', () => {
let wrapper;
let store;
const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType);
const findDropdown = () => wrapper.findComponent(GlCollapsibleListbox);
const findSearchBox = () => wrapper.findByTestId('listbox-search-input');
const createComponent = async (searchTerm, selectedTimezone) => {
wrapper = shallowMountExtended(TimezoneDropdown, {
......@@ -19,15 +20,18 @@ describe('Deploy freeze timezone dropdown', () => {
timezoneData: timezoneDataFixture,
name: 'user[timezone]',
},
stubs: {
GlCollapsibleListbox,
},
});
findSearchBox().vm.$emit('input', searchTerm);
await nextTick();
};
const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
const findDropdownItemByIndex = (index) => wrapper.findAllComponents(GlDropdownItem).at(index);
const findEmptyResultsItem = () => wrapper.findByTestId('noMatchingResults');
const findAllDropdownItems = () => wrapper.findAllComponents(GlListboxItem);
const findDropdownItemByIndex = (index) => findAllDropdownItems().at(index);
const findEmptyResultsItem = () => wrapper.findByTestId('listbox-no-results-text');
const findHiddenInput = () => wrapper.find('input');
describe('No time zones found', () => {
......@@ -36,7 +40,8 @@ describe('Deploy freeze timezone dropdown', () => {
});
it('renders empty results message', () => {
expect(findDropdownItemByIndex(0).text()).toBe('No matching results');
expect(findEmptyResultsItem().exists()).toBe(true);
expect(findEmptyResultsItem().text()).toBe('No matching results');
});
});
......@@ -69,11 +74,13 @@ describe('Deploy freeze timezone dropdown', () => {
const selectedTz = findTzByName('Alaska');
it('should emit input if a time zone is clicked', () => {
findDropdownItemByIndex(0).vm.$emit('click');
const payload = formatTimezone(selectedTz);
findDropdown().vm.$emit('select', payload);
expect(wrapper.emitted('input')).toEqual([
[
{
formattedTimezone: formatTimezone(selectedTz),
formattedTimezone: payload,
identifier: selectedTz.identifier,
},
],
......@@ -88,7 +95,7 @@ describe('Deploy freeze timezone dropdown', () => {
});
it('renders empty selections', () => {
expect(wrapper.findComponent(GlDropdown).props().text).toBe('Select timezone');
expect(findDropdown().props('toggleText')).toBe('Select timezone');
});
it('preserves initial value in the associated input', () => {
......@@ -102,14 +109,14 @@ describe('Deploy freeze timezone dropdown', () => {
});
it('renders selected time zone as dropdown label', () => {
expect(wrapper.findComponent(GlDropdown).props().text).toBe('[UTC+2] Berlin');
expect(findDropdown().props('toggleText')).toBe('[UTC+2] Berlin');
});
it('adds a checkmark to the selected option', async () => {
const selectedTZOption = findAllDropdownItems().at(0);
selectedTZOption.vm.$emit('click');
findDropdown().vm.$emit('select', formatTimezone(findTzByName('Abu Dhabi')));
await nextTick();
expect(selectedTZOption.attributes('ischecked')).toBe('true');
expect(findDropdownItemByIndex(0).props('isSelected')).toBe(true);
});
});
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment