import { UniDriver } from '@wix/wix-ui-test-utils/unidriver'; import { CollectionToolbarUniDriver } from '../CollectionToolbar/CollectionToolbar.uni.driver'; import { baseUniDriverFactory } from '../../unidriver/baseUniDriverFactory'; import { isSled2, isSled3 } from '../../unidriver/nativeEnv'; import { SledPage } from '@wix/sled-test-runner'; import { AddItemUniDriver, BoxUniDriver, ButtonUniDriver, CounterBadgeUniDriver, IconButtonUniDriver, MessageModalLayoutUniDriver, PopoverMenuUniDriver, TagListUniDriver, TagUniDriver, TextUniDriver, TooltipUniDriver, } from '@wix/design-system/dist/testkit/unidriver'; import { DragAndDropUniDriver } from '../DragAndDrop/DragAndDrop.uni.driver'; import { ManageTagsModalUniDriver } from '../Tags/ManageTags/ManageTagsModal/ManageTagsModal.uni.driver'; import { CustomFieldPanelUniDriver } from '../CustomFieldsPanel/CustomFieldPanel.uni.driver'; export function KanbanUniDriver(base: UniDriver, body: UniDriver) { const toolbarBase = () => base.$('[data-hook="collection-toolbar"]'); const toolbar = () => CollectionToolbarUniDriver(toolbarBase(), body); const dragAndDrop = () => DragAndDropUniDriver(base); const dragCardToStage = async ({ sourceStageKey, cardKey, targetStageKey, }: { sourceStageKey: string; cardKey: string; targetStageKey: string; }) => { const targetStageElement = base.$( `[data-hook^="kanban-stage-container-${targetStageKey}"]`, ); if (!(await targetStageElement.exists())) { throw new Error(`Target stage with key ${targetStageKey} not found`); } const sourceStageElement = base.$( `[data-hook^="kanban-stage-container-${sourceStageKey}"]`, ); if (!(await sourceStageElement.exists())) { throw new Error(`Source stage with key ${sourceStageKey} not found`); } const cardElement = base.$( `[data-hook^="kanban-card-drag-item-${sourceStageKey}-##-${cardKey}"]`, ); if (!(await cardElement.exists())) { throw new Error( `Card with key ${cardKey} not found in stage ${sourceStageKey}`, ); } const driverDragAndDrop = dragAndDrop(); await driverDragAndDrop.dragStart(cardElement); await driverDragAndDrop.dragEnd(targetStageElement); }; return { ...baseUniDriverFactory(base), toolbar: () => toolbar(), enterSearchText: (text: string) => toolbar().enterSearchText(text), clearSearchText: () => toolbar().clearSearchText(), isKanbanLoading: () => base.$('[data-hook="kanban-stages-skeleton"]').exists(), getCustomFieldPanel: () => CustomFieldPanelUniDriver(body, body), getManageTagsModal: () => ManageTagsModalUniDriver(base, body), stages: { count: () => base.$$('[data-hook^="kanban-stage-container"]').count(), doneDividerExists: async () => { const count = await base .$$(`[data-hook^="kanban-stages-done-divider"]`) .count(); return count > 0; }, stageTitle: (stageId: string) => { return TextUniDriver( base.$(`[data-hook^="kanban-stage-title-${stageId}"]`), body, ); }, stageSummary: (stageId: string) => { const counterBadge = CounterBadgeUniDriver( base.$(`[data-hook^="kanban-stage-title-total-${stageId}"]`), body, ); return { ...counterBadge, exists: () => counterBadge.exists(), totalItems: () => counterBadge.getContentText(), }; }, scrollToEndOfStageCardsContainer: async (stageKey: string) => { const scrollableElementDataHook = `kanban-stage-cards-container-${stageKey}`; const scrollableDriver = body.$( `[data-hook="${scrollableElementDataHook}"]`, ); const native = await scrollableDriver.getNative(); // puppeteer if (isSled2(native)) { const { page } = native as { page: SledPage['page'] }; await page.evaluate((_dataHook: string) => { const scrollableElement = document.querySelector( `[data-hook="${_dataHook}"]`, )!; scrollableElement.scrollBy({ behavior: 'smooth', top: scrollableElement.scrollHeight, }); }, scrollableElementDataHook); await page.waitForTimeout(1000); // delay scroll resolve by 1 sec } // playwright else if (isSled3(native)) { const locator = (await scrollableDriver.unwrap()) as { evaluate: (fn: (el: HTMLElement) => void) => Promise; page: () => { waitForTimeout: (ms: number) => Promise }; }; await locator.evaluate((scrollableElement) => { scrollableElement.scrollBy({ behavior: 'smooth', top: scrollableElement.scrollHeight, }); }); await locator.page().waitForTimeout(1000); } // jsdom else if (await scrollableDriver.exists()) { // Scroll to the end by setting scrollTop to (scrollHeight - clientHeight) native.scrollTop = native.scrollHeight - native.clientHeight; await native.dispatchEvent(new Event('scroll')); } }, stageSummaryBadge: (stageId: string) => { const counterBadge = CounterBadgeUniDriver( base.$(`[data-hook^="kanban-stage-title-total-${stageId}"]`), body, ); return { ...counterBadge, exists: () => counterBadge.exists(), totalItems: () => counterBadge.getContentText(), }; }, addCardButton: (stageKey: string) => AddItemUniDriver( base.$(`[data-hook="kanban-stage-add-card-${stageKey}"]`), body, ), getSecondaryActions: (stageKey: string) => { const popoverMenu = PopoverMenuUniDriver( base.$(`[data-hook="kanban-stage-more-actions-${stageKey}"]`), body, ); const triggerButton = popoverMenu.getTriggerElement( `kanban-stage-more-actions-trigger-${stageKey}`, ); const iconButton = IconButtonUniDriver(triggerButton, base); return { ...popoverMenu, clickTriggerElement: () => iconButton.click(), }; }, getActionModal: () => MessageModalLayoutUniDriver( body.$('[data-hook="collection-action-modal"]'), body, ), tagList: (stageKey: string, itemId: string) => TagListUniDriver( base.$(`[data-hook="kanban-card-tags-${stageKey}-${itemId}"]`), body, ), tagInList: (stageKey: string, itemId: string, tagId: string) => TagUniDriver( base.$( `[data-hook="kanban-card-tags-${stageKey}-${itemId}-${tagId}"]`, ), body, ), toggleHiddenTagsCounter: (stageKey: string, itemId: string) => TagUniDriver( base.$(`[data-hook="kanban-card-tags-${stageKey}-${itemId}-toggle"]`), body, ), stagesSkeleton: () => BoxUniDriver(base.$('[data-hook="kanban-stages-skeleton"]'), body), noResultsBox: (stageKey: string) => BoxUniDriver( base.$(`[data-hook="kanban-stage-no-results-${stageKey}"]`), body, ), cardsSkeleton: (stageKey: string) => BoxUniDriver( base.$(`[data-hook="kanban-cards-skeleton-${stageKey}"]`), body, ), }, cards: { count: (stageKey: string) => base.$$(`[data-hook^="kanban-card-${stageKey}-"]`).count(), exists: ({ stageKey, cardKey }: { stageKey: string; cardKey: string }) => base.$(`[data-hook^="kanban-card-${stageKey}-${cardKey}"]`).exists(), getTitle: ({ stageKey, cardKey, }: { stageKey: string; cardKey: string; }) => { return TextUniDriver( base.$(`[data-hook^="kanban-card-title-${stageKey}-${cardKey}"]`), body, ); }, getPrimaryAction: ({ stageKey, cardKey, }: { stageKey: string; cardKey: string; }) => { const tooltip = TooltipUniDriver( base.$( `[data-hook="kanban-card-primary-action-tooltip-${stageKey}-${cardKey}"]`, ), body, ); const button = ButtonUniDriver( base.$( `[data-hook="kanban-card-primary-action-${stageKey}-${cardKey}"]`, ), body, ); return { ...button, exists: () => button.exists(), text: () => button.getButtonTextContent(), tooltip: () => tooltip, }; }, getSecondaryActions: ({ stageKey, cardKey, }: { stageKey: string; cardKey: string; }) => { const popoverMenu = PopoverMenuUniDriver( base.$( `[data-hook="kanban-card-more-actions-${stageKey}-${cardKey}"]`, ), body, ); const triggerButton = popoverMenu.getTriggerElement( `kanban-card-more-actions-trigger-${stageKey}-${cardKey}`, ); const iconButton = IconButtonUniDriver(triggerButton, base); return { ...popoverMenu, clickTriggerElement: () => iconButton.click(), }; }, getActionModal: () => MessageModalLayoutUniDriver( body.$('[data-hook="collection-action-modal"]'), body, ), dragCardToStage, }, }; } export default KanbanUniDriver;