import { UniDriver } from '@wix/wix-ui-test-utils/unidriver'; import { SlidingModalUniDriver } from '../SlidingModal/SlidingModal.uni.driver'; import { AccordionUniDriver, ButtonUniDriver, DropdownBaseUniDriver, FieldSetUniDriver, FormFieldUniDriver, InputUniDriver, InputWithOptionsUniDriver, MessageModalLayoutUniDriver, MultiSelectUniDriver, SearchUniDriver, SidePanelUniDriver, TextButtonUniDriver, TextUniDriver, } from '@wix/design-system/dist/testkit/unidriver'; import { CollectionDropdownFilterUniDriver } from '../DropdownFilter/CollectionDropdownFilter.uni.driver'; import { MultiInlineCheckboxUniDriver } from '../MultiInlineCheckbox/MultiInlineCheckbox.uni.driver'; import { DateRangePickerUniDriver } from '../DateRangePicker/DateRangeFilter.uni.driver'; import { RadioGroupFilterUniDriver } from '../RadioGroupFilter/RadioGroupFilter.uni.driver'; export const FiltersPanelUniDriver = (base: UniDriver, body: UniDriver) => { const slidingModal = SlidingModalUniDriver( base.$('[data-hook="cairo-side-panel-modal"]'), body, ); const sidePanel = SidePanelUniDriver( base.$('[data-hook="filters-side-panel"]'), body, ); const accordionBase = base.$('[data-hook="filters-panel-accordion"]'); const accordion = AccordionUniDriver(accordionBase, body); const getInlineCheckboxFilter = (filterName: string) => MultiInlineCheckboxUniDriver( accordionBase.$(`[data-hook="collection-filter-${filterName}"]`), body, ); const getDateRangeFilter = (filterName: string) => DateRangePickerUniDriver( accordionBase.$(`[data-hook="date-range-filter-${filterName}"]`), body, ); const getRadioGroupFilter = (filterName: string) => RadioGroupFilterUniDriver( accordionBase.$(`[data-hook="radio-group-filter-${filterName}"]`), body, ); const getAccordionItemTitle = (filterName: string) => accordionBase.$(`[data-hook="accordion-item-title-${filterName}"]`); const getAccordionItem = async (filterName: string) => { const items = accordionBase.$$('[data-hook="accordion-item"]'); const count = await items.count(); for (let i = 0; i < count; i++) { const item = items.get(i); if ( await item .$(`[data-hook="accordion-item-title-${filterName}"]`) .exists() ) { return item; } } throw new Error(`Accordion item for filter: "${filterName}" was not found`); }; const getAccordionItemAt = (index: number) => accordionBase.$$('[data-hook="accordion-item"]').get(index); const isFilterExpanded = async (filterName: string) => (await getAccordionItem(filterName)).$('[data-hook="children"]').exists(); const isFilterExpandedAt = (index: number) => getAccordionItemAt(index).$('[data-hook="children"]').exists(); const clickFilter = async (filterName: string) => { if (!(await isFilterExpanded(filterName))) { await clickFilterTitle(filterName); } }; const checkFilterInlineCheckboxes = async ( filterName: string, ids: string[], { closePanel = true, closeAccordionItem = true, }: { closePanel?: boolean; closeAccordionItem?: boolean } = {}, ) => { await clickFilter(filterName); await getInlineCheckboxFilter(filterName).checkOptions(ids); if (closeAccordionItem) { await clickFilterTitle(filterName); } if (closePanel) { await sidePanel.clickClose(); } }; const chooseDatesFilterDateRange = async ( filterName: string, { dates = undefined, closePanel = true, closeAccordionItem = true, }: { closePanel?: boolean; closeAccordionItem?: boolean; dates?: Date[]; } = {}, ) => { await clickFilter(filterName); const dateRange = await getDateRangeFilter(filterName); let datesResult; if (dates && dates.length > 1) { const from = await dateRange.chooseDate('from', dates[0]); const to = await dateRange.chooseDate('to', dates[1]); datesResult = { from, to }; } else { datesResult = await dateRange.chooseRandomDates(); } if (closeAccordionItem) { await clickFilterTitle(filterName); } if (closePanel) { await sidePanel.clickClose(); } return datesResult; }; const getInputWithOptionsDriver = (filterName: string) => { const dataHook = `collection-filter-${filterName}`; const optionsBase = accordionBase.$( `[data-hook="collection-filter-${filterName}"]`, ); const inputWithOptionsDriver = InputWithOptionsUniDriver(optionsBase, body); return CollectionDropdownFilterUniDriver( inputWithOptionsDriver, dataHook, optionsBase, body, ); }; const selectFilterOptions = async ( filterName: string, ids: string[], { closePanel = true, closeAccordionItem = true, closeDropdown = true, }: { closePanel?: boolean; closeAccordionItem?: boolean; closeDropdown?: boolean; } = {}, ) => { if (!(await isFilterExpanded(filterName))) { await clickFilterTitle(filterName); } await getInputWithOptionsDriver(filterName).selectOptions(ids, { closeDropdown, }); if (closeAccordionItem) { await clickFilterTitle(filterName); } if (closePanel) { await sidePanel.clickClose(); } }; const selectFilterRandomOptions = async ( filterName: string, count: number, { closePanel = true, closeAccordionItem = true, closeDropdown = true, }: { closePanel?: boolean; closeAccordionItem?: boolean; closeDropdown?: boolean; } = {}, ) => { if (!(await isFilterExpanded(filterName))) { await clickFilterTitle(filterName); } const ids = await getInputWithOptionsDriver(filterName).selectRandomOptions( count, { closeDropdown, }, ); if (closeAccordionItem) { await getAccordionItemTitle(filterName).click(); } if (closePanel) { await sidePanel.clickClose(); } return ids; }; const getFilterTitleText = (filterName: string) => TextUniDriver(getAccordionItemTitle(filterName), body).getText(); const getFilterAppliedText = () => TextUniDriver(body.$('[data-hook="applied-filters"]'), body).getText(); const clickFilterTitle = (filterName: string) => getAccordionItemTitle(filterName).click(); const getCustomFilter = async ( filterName: string, fn: (element: E) => T, ) => { if (!(await isFilterExpanded(filterName))) { await clickFilterTitle(filterName); } return fn(await accordion.element()); }; const clickClearAllFilters = () => getClearAllFiltersButton().click(); const getClearAllFiltersButton = () => TextButtonUniDriver(base.$('[data-hook="clear-all-filters"]'), body); const getPanelFiltersCount = () => { const items = accordionBase.$$('[data-hook="accordion-item"]'); return items.count(); }; const getItemTextAt = (index: number) => { return accordionBase.$$(':scope > div').get(index).text(); }; const getItemsCount = () => { return accordionBase.$$(':scope > div').count(); }; const filterSearchBase = base.$('[data-hook="filters-panel-search"]'); const filterSearch = () => SearchUniDriver(filterSearchBase, body); const noResultsBase = base.$('[data-hook="filters-panel-search-no-results"]'); const noResultsTitle = base.$( '[data-hook="filters-panel-search-no-results-title"]', ); const clearSearchButton = () => TextButtonUniDriver( base.$('[data-hook="filters-panel-search-clear-button"]'), body, ); return { isOpen: slidingModal.isOpen, clickCloseButton: async () => { if (await sidePanel.isCloseButtonExists()) { return sidePanel.clickClose(); } if (await sidePanel.isBackButtonExists()) { return sidePanel.clickBack(); } }, getTitleText: sidePanel.getTitleText, selectFilterOptions, selectFilterRandomOptions, checkFilterInlineCheckboxes, chooseDatesFilterDateRange, getFilterTitleText, getFilterAppliedText, clickFilterTitle, isFilterExpanded, isFilterExpandedAt, getCustomFilter, getInputWithOptionsDriver, clickClearAllFilters, getClearAllFiltersButton, getPanelFiltersCount, getDateRangeFilter, getNumberRangeDriver: (filterName: string) => { const getNumberRangeFilter = () => accordionBase.$(`[data-hook="number-range-filter-${filterName}"]`); const getNumberRangeFilterFromInput = () => InputUniDriver( getNumberRangeFilter().$( '[data-hook="number-range-filter-from-input"]', ), body, ); const getNumberRangeFilterToInput = () => InputUniDriver( getNumberRangeFilter().$( '[data-hook="number-range-filter-to-input"]', ), body, ); const getNumberRangeFilterFromError = () => { const fieldsetDriver = FieldSetUniDriver(getNumberRangeFilter(), body); return { exists: () => fieldsetDriver.hasStatus('error'), getText: () => fieldsetDriver.getStatusMessage(), }; }; const getNumberRangeFilterToError = () => { const formField = FormFieldUniDriver( getNumberRangeFilter().$( '[data-hook="number-range-filter-to-form-field"]', ), body, ); return { exists: () => formField.hasStatus('error'), getText: () => formField.getStatusMessage(), }; }; return { getNumberRangeFilter, getNumberRangeFilterFromInput, getNumberRangeFilterToInput, getNumberRangeFilterFromError, getNumberRangeFilterToError, }; }, getRadioGroupFilter, getOperatorPickerDriver: (filterName: string) => { const getOperatorPicker = () => accordionBase.$(`[data-hook="operator-picker-${filterName}"]`); const getOperatorDropdown = () => DropdownBaseUniDriver( getOperatorPicker().$( '[data-hook="operator-picker-operator-dropdown"]', ), body, ); const getValueInput = () => InputUniDriver( getOperatorPicker().$('[data-hook="operator-picker-value-input"]'), body, ); return { exists: () => getOperatorPicker().exists(), getOperatorPicker, getOperatorDropdown, getValueInput, selectOperator: async (optionIndex: number) => { const dropdown = getOperatorDropdown(); await dropdown.clickTargetElement('operator-picker-trigger'); await dropdown.selectOption(optionIndex); }, getSelectedOperator: async () => { const dropdown = getOperatorDropdown(); return dropdown.getSelectedOptionId(); }, enterValue: async (value: string) => { const input = getValueInput(); await input.enterText(value); }, getValue: () => getValueInput().getText(), blur: () => getValueInput().blur(), }; }, getItemTextAt, getItemsCount, applyButton: () => ButtonUniDriver(base.$('[data-hook="apply-button"]'), body), discardChangesModal: () => MessageModalLayoutUniDriver( body.$('[data-hook="discard-changes-modal"]'), body, ), getFiltersPanelMultiSelect: (filterName: string) => MultiSelectUniDriver( accordionBase.$(`[data-hook="collection-filter-${filterName}"]`), base, ), _getAccordionItemTitle: ( filterName: string, { index = 0 }: { index?: number } = {}, ) => accordionBase .$$(`[data-hook="accordion-item-title-${filterName}"]`) .get(index), _getInlineCheckboxFilter: getInlineCheckboxFilter, isFilterSearchVisible: () => filterSearchBase.exists(), enterFilterSearch: (term: string) => filterSearch().inputDriver.enterText(term), clearFilterSearchInput: () => filterSearch().inputDriver.clearText(), getFilterSearchValue: () => filterSearch().inputDriver.getText(), isNoFiltersMatchVisible: () => noResultsBase.exists(), getNoFiltersMatchText: () => TextUniDriver(noResultsTitle, body).getText(), clickClearSearchButton: () => clearSearchButton().click(), }; };