UNPKG

wix-style-react

Version:
165 lines • 8.86 kB
import ReactTestUtils from 'react-dom/test-utils'; import values from '../utils/operators/values'; import { DATA_HOOKS, DATA_OPTION, DATA_SHOWN, DATA_DIRECTION, DROPDOWN_LAYOUT_DIRECTIONS, OPTION_DATA_HOOKS, DATA_SELECTED_OPTION_ID, } from './DataAttr'; const dropdownLayoutDriverFactory = ({ element, wrapper }) => { const byDataHook = dataHook => element.querySelector(`[data-hook="${dataHook}"]`); const contentContainer = byDataHook(DATA_HOOKS.CONTENT_CONTAINER); const infiniteScrollContainer = byDataHook(DATA_HOOKS.INFINITE_SCROLL_CONTAINER); const optionElementsContainer = byDataHook(DATA_HOOKS.DROPDOWN_LAYOUT_OPTIONS); const optionElements = infiniteScrollContainer ? infiniteScrollContainer : optionElementsContainer; const getListItemPositionAtSelector = position => `[data-list-type="action"] [data-hook=${DATA_HOOKS.DROPDOWN_LAYOUT_OPTIONS}] > *:nth-child(${position + 1}) > *`; const optionElementAt = position => { return (element.querySelector(getListItemPositionAtSelector(position)) || optionElements.childNodes[position]); }; const optionsLength = () => optionElements.childNodes.length; const doIfOptionExists = (position, onSuccess) => { if (optionsLength() <= position) { throw new Error(`index out of bounds, try to get option ${position} while only ${optionsLength()} options exists`); } return onSuccess(); }; const getOptionDriver = position => doIfOptionExists(position, () => createOptionDriver(optionElementAt(position))); const options = () => values(optionElements.childNodes); return { /** @deprecated */ classes: () => optionElementsContainer.className, clickAtOption: position => doIfOptionExists(position, () => { const optionDriver = getOptionDriver(position); return optionDriver.click(); }), clickAtOptionWithValue: value => { for (const _option of options()) { const optionDriver = createOptionDriver(_option); if (optionDriver.content() === value) { return optionDriver.click(); } } }, exists: () => !!element, /** @deprecated deprecated prop */ hasTopArrow: () => !!element.querySelector(`[data-hook="${DATA_HOOKS.TOP_ARROW}"]`), /** @deprecated deprecated prop */ isDown: () => contentContainer.getAttribute(DATA_DIRECTION) === DROPDOWN_LAYOUT_DIRECTIONS.DOWN, /** @deprecated deprecated prop */ isUp: () => contentContainer.getAttribute(DATA_DIRECTION) === DROPDOWN_LAYOUT_DIRECTIONS.UP, isLinkOption: position => doIfOptionExists(position, () => { const optionDriver = getOptionDriver(position); return optionDriver.isLink(); }), isOptionADivider: position => doIfOptionExists(position, () => { const optionDriver = getOptionDriver(position); return optionDriver.isDivider(); }), isOptionExists: optionText => [].filter.call(optionElements.childNodes, opt => opt.textContent === optionText).length > 0, /** returns if an option is hovered. notice that it checks by index and __not__ by id */ isOptionHovered: position => doIfOptionExists(position, () => { const optionDriver = getOptionDriver(position); return optionDriver.isHovered(); }), isOptionSelected: position => doIfOptionExists(position, () => { const optionDriver = getOptionDriver(position); return optionDriver.isSelected(); }), /** @deprecated */ isOptionHeightSmall: position => doIfOptionExists(position, () => optionElementAt(position).getAttribute(DATA_OPTION.SIZE) === 'small'), /** @deprecated */ isOptionHeightBig: position => doIfOptionExists(position, () => optionElementAt(position).getAttribute(DATA_OPTION.SIZE) === 'big'), isListItemFocused: position => document.activeElement === element.querySelector(getListItemPositionAtSelector(position)), isShown: () => contentContainer.hasAttribute(DATA_SHOWN), mouseEnter: () => ReactTestUtils.Simulate.mouseEnter(element), mouseEnterAtOption: position => doIfOptionExists(position, () => { const optionDriver = getOptionDriver(position); return optionDriver.mouseEnter(); }), mouseLeave: () => ReactTestUtils.Simulate.mouseLeave(element), /** @deprecated deprecated prop */ mouseClickOutside: () => document.body.dispatchEvent(new Event('mouseup', { cancelable: true, bubbles: true })), mouseLeaveAtOption: position => doIfOptionExists(position, () => { const optionDriver = getOptionDriver(position); return optionDriver.mouseLeave(); }), /** @deprecated Use optionDriver*/ optionAt: optionElementAt, /** @deprecated This should be a private method since the hook include internal parts ('dropdown-divider-{id}, dropdown-item-{id})') */ optionByHook: hook => { const option = optionElements.querySelector(`[data-hook=${hook}]`); if (!option) { throw new Error(`an option with data-hook ${hook} was not found`); } return createOptionDriver(option); }, optionById(optionId) { return this.optionByHook(`dropdown-item-${optionId}`); }, optionContentAt: position => doIfOptionExists(position, () => { const optionDriver = getOptionDriver(position); return optionDriver.content(); }), /** Get option driver given an option index */ optionDriver: createOptionDriver, /** Get an array of all options including dividers (drivers) */ options: () => { const drivers = []; for (let position = 0; position < optionsLength(); position++) { drivers.push(getOptionDriver(position)); } return drivers; }, optionsContent: () => { const contentArray = []; for (const option of options()) { const optionDriver = createOptionDriver(option); contentArray.push(optionDriver.content()); } return contentArray; }, markedOption: async () => { const hoveredOption = optionElements.querySelector(`[${DATA_OPTION.HOVERED}="true"]`); return ((hoveredOption && createOptionDriver(hoveredOption).content()) || null); }, getSelectedOptionId: () => contentContainer.getAttribute(DATA_SELECTED_OPTION_ID), optionsLength, /** @deprecated should be private */ optionsScrollTop: () => optionElements.scrollTop, pressDownKey: () => ReactTestUtils.Simulate.keyDown(element, { key: 'ArrowDown' }), pressUpKey: () => ReactTestUtils.Simulate.keyDown(element, { key: 'ArrowUp' }), pressEnterKey: () => ReactTestUtils.Simulate.keyDown(element, { key: 'Enter' }), pressSpaceKey: () => ReactTestUtils.Simulate.keyDown(element, { key: ' ' }), pressTabKey: () => ReactTestUtils.Simulate.keyDown(element, { key: 'Tab' }), pressEscKey: () => ReactTestUtils.Simulate.keyDown(element, { key: 'Escape' }), keyDownListItem: (position, key) => doIfOptionExists(position, () => { return ReactTestUtils.Simulate.keyDown(element.querySelector(getListItemPositionAtSelector(position)), { key, }); }), tabIndex: () => element.tabIndex, getListItemAttribute: (position, attribute) => optionElementAt(position).getAttribute(attribute), getListType: async (dataHook) => wrapper .querySelector(`[data-hook="${dataHook}"]`) .getAttribute('data-list-type'), getOptionsContainerRole: () => optionElementsContainer.getAttribute('role'), }; }; const createOptionDriver = option => ({ element: () => option, mouseEnter: () => ReactTestUtils.Simulate.mouseEnter(option), mouseLeave: () => ReactTestUtils.Simulate.mouseLeave(option), isHovered: () => option.hasAttribute(DATA_OPTION.HOVERED), isSelected: () => option.hasAttribute(DATA_OPTION.SELECTED), content: () => option.textContent, click: () => ReactTestUtils.Simulate.click(option), isDivider: () => { const divider = option.querySelector(`[data-hook="${OPTION_DATA_HOOKS.DIVIDER}"]`); return !!divider; }, isDisabled: () => option.hasAttribute(DATA_OPTION.DISABLED), isLink: () => option.tagName.toLowerCase() === 'a', }); export default dropdownLayoutDriverFactory; //# sourceMappingURL=DropdownLayout.driver.js.map