wix-style-react
Version:
wix-style-react
221 lines • 10.9 kB
JavaScript
import { baseUniDriverFactory, ReactBase, findByHook, getDataAttributeValue, isElementFocused, } from '../test-utils/utils/unidriver';
import { DATA_OPTION, DATA_HOOKS, DATA_DIRECTION, DATA_SHOWN, DROPDOWN_LAYOUT_DIRECTIONS, OPTION_DATA_HOOKS, DATA_SELECTED_OPTION_ID, } from './DataAttr';
export const dropdownLayoutDriverFactory = (base, body) => {
const reactBase = ReactBase(base);
const contentContainer = () => findByHook(base, DATA_HOOKS.CONTENT_CONTAINER);
const infiniteScrollContainer = () => findByHook(base, DATA_HOOKS.INFINITE_SCROLL_CONTAINER);
const optionsElement = () => findByHook(base, DATA_HOOKS.DROPDOWN_LAYOUT_OPTIONS);
async function getOptionsContainerDataHook() {
return (await infiniteScrollContainer().exists())
? DATA_HOOKS.INFINITE_SCROLL_CONTAINER
: DATA_HOOKS.DROPDOWN_LAYOUT_OPTIONS;
}
const optionElementAt = async (position) => await base.$(`[data-hook=${await getOptionsContainerDataHook()}] > *:nth-child(${position + 1})`);
const optionElementContentAt = async (position) => await base.$(`[data-list-type="action"] [data-hook=${await getOptionsContainerDataHook()}] > *:nth-child(${position + 1}) > *`);
const optionElementByDataHook = async (dataHook) => await base.$(`[data-hook=${await getOptionsContainerDataHook()}] [data-hook="${dataHook}"]`);
const options = async () => base
.$$(`[data-hook=${await getOptionsContainerDataHook()}] > *`)
.map(i => i);
const optionsLength = async () => (await options()).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, async () => {
const optionElementContent = await optionElementContentAt(position);
return createOptionDriver((await optionElementContent.exists())
? optionElementContent
: await optionElementAt(position));
});
return {
...baseUniDriverFactory(base),
/** @deprecated should be private */
classes: () => optionsElement()._prop('className'),
/** Clicks on an option at a specific index
* @param {number} option index
* @return {Promise<void>}
*/
clickAtOption: async (index) => (await getOptionDriver(index)).click(),
/** Clicks on an option with a specific dataHook
* @param {string} dataHook
* @return {Promise<void>}
*/
clickAtOptionByDataHook: async (dataHook) => (await optionElementByDataHook(dataHook)).click(),
/** Clicks on an option with a specific value
* @param {string} value
* @return {Promise<void>}
*/
clickAtOptionWithValue: async (value) => {
for (const _option of await options()) {
const optionDriver = await createOptionDriver(_option);
if ((await optionDriver.content()) === value) {
return optionDriver.click();
}
}
},
/** @deprecated deprecated prop */
hasTopArrow: async () => await (await findByHook(base, DATA_HOOKS.TOP_ARROW)).exists(),
/** @deprecated deprecated prop */
isDown: async () => (await (await contentContainer()).attr(DATA_DIRECTION)) ===
DROPDOWN_LAYOUT_DIRECTIONS.DOWN,
/** @deprecated deprecated prop */
isUp: async () => (await (await contentContainer()).attr(DATA_DIRECTION)) ===
DROPDOWN_LAYOUT_DIRECTIONS.UP,
isLinkOption: async (position) => doIfOptionExists(position, async () => {
const optionDriver = await getOptionDriver(position);
return optionDriver.isLink();
}),
isOptionADivider: position => doIfOptionExists(position, async () => {
const optionDriver = await getOptionDriver(position);
return optionDriver.isDivider();
}),
isOptionExists: async (optionText) => {
for (const _option of await options()) {
if ((await _option.text()) === optionText) {
return true;
}
}
return false;
},
isOptionHovered: async (index) => doIfOptionExists(index, async () => {
const optionDriver = await getOptionDriver(index);
return optionDriver.isHovered();
}),
isOptionSelected: async (index) => doIfOptionExists(index, async () => {
const optionDriver = await getOptionDriver(index);
return optionDriver.isSelected();
}),
/** @deprecated */
isOptionHeightSmall: position => doIfOptionExists(position, async () => (await (await optionElementAt(position)).attr(DATA_OPTION.SIZE)) ===
'small'),
/** @deprecated */
isOptionHeightBig: position => doIfOptionExists(position, async () => (await (await optionElementAt(position)).attr(DATA_OPTION.SIZE)) ===
'big'),
isListItemFocused: async (position) => isElementFocused(await optionElementContentAt(position)),
isShown: async () => !!(await (await contentContainer()).attr(DATA_SHOWN)),
mouseEnter: () => base.hover(),
mouseEnterAtOption: position => doIfOptionExists(position, async () => {
const optionDriver = await getOptionDriver(position);
return optionDriver.mouseEnter();
}),
mouseLeave: async () => {
switch (base.type) {
case 'react':
reactBase.mouseLeave();
return;
case 'puppeteer':
const { element } = await baseUniDriverFactory(base).element();
page.evaluate(element => {
element.dispatchEvent(new MouseEvent('mouseout', {
bubbles: true,
view: window,
cancelable: true,
}));
}, element);
return;
default:
return;
}
},
/** @deprecated deprecated prop */
mouseClickOutside: () => ReactBase.clickBody(),
mouseLeaveAtOption: position => doIfOptionExists(position, async () => {
const optionDriver = await getOptionDriver(position);
return optionDriver.mouseLeave();
}),
/** @deprecated Use optionDriver*/
optionAt: () => {
return optionElementAt.getNative(); // eslint-disable-line no-restricted-properties
},
// This should be a private method since the hook include internal parts ('dropdown-divider-{id}, dropdown-item-{id})') */
/** @deprecated */
optionByHook: async (hook) => {
const option = optionsElement().$(`[data-hook=${hook}]`);
if (!(await option.exists())) {
throw new Error(`an option with data-hook ${hook} was not found`);
}
return createOptionDriver(option);
},
/**
* Get Option by id
* @returns {Promise<any>}
*/
optionById(optionId) {
return this.optionByHook(`dropdown-item-${optionId}`);
},
optionContentAt: position => doIfOptionExists(position, async () => {
const optionDriver = await getOptionDriver(position);
return optionDriver.content();
}),
optionDriver: createOptionDriver,
/** Get Options drivers */
options: async () => {
const drivers = [];
for (let position = 0; position < (await optionsLength()); position++) {
drivers.push(await getOptionDriver(position));
}
return drivers;
},
optionsContent: async () => {
const contentArray = [];
for (const option of await options()) {
const optionDriver = await createOptionDriver(option);
contentArray.push(await optionDriver.content());
}
return contentArray;
},
markedOption: async () => {
const allOptions = await options();
const optionsWithHovered = await Promise.all(allOptions.map(async (option) => ({
option,
hovered: !!(await option.attr(DATA_OPTION.HOVERED)),
})));
const hoveredOptions = optionsWithHovered
.filter(option => option.hovered)
.map(option => option.option);
return ((hoveredOptions.length &&
createOptionDriver(hoveredOptions[0]).content()) ||
null);
},
getSelectedOptionId: async () => await getDataAttributeValue(await contentContainer(), DATA_SELECTED_OPTION_ID),
optionsLength,
/** @deprecated should be private */
optionsScrollTop: () => optionsElement()._prop('scrollTop'),
pressDownKey: () => base.pressKey('ArrowDown'),
pressUpKey: () => base.pressKey('ArrowUp'),
pressEnterKey: () => base.pressKey('Enter'),
pressSpaceKey: () => base.pressKey(' '),
pressTabKey: () => base.pressKey('Tab'),
pressEscKey: () => base.pressKey('Escape'),
keyDownListItem: async (position, key) => {
const optionDriver = await getOptionDriver(position);
return (await optionDriver.element()).pressKey(key);
},
tabIndex: () => base._prop('tabIndex'),
getListItemAttribute: async (position, attribute) => {
const optionDriver = await getOptionDriver(position);
return (await optionDriver.element()).attr(attribute);
},
/** Returns the list type prop value */
getListType: dataHook => findByHook(body, dataHook).attr('data-list-type'),
getOptionsContainerRole: () => optionsElement().attr('role'),
};
};
const createOptionDriver = option => ({
element: () => option,
mouseEnter: () => option.hover(),
mouseLeave: () => ReactBase(option).mouseLeave(),
isHovered: async () => !!(await option.attr(DATA_OPTION.HOVERED)),
isSelected: async () => !!(await option.attr(DATA_OPTION.SELECTED)),
content: () => option.text(),
click: () => option.click(),
isDivider: async () => {
const divider = await findByHook(option, OPTION_DATA_HOOKS.DIVIDER);
return divider.exists();
},
isDisabled: async () => !!(await option.attr(DATA_OPTION.DISABLED)),
isLink: async () => (await option._prop('tagName')).toLowerCase() === 'a',
});
//# sourceMappingURL=DropdownLayout.uni.driver.js.map