import { UniDriver } from '@wix/wix-ui-test-utils/unidriver'; import { ToolbarCollectionErrorStateUniDriver } from '../ErrorState/ToolbarCollectionErrorState.uni.driver'; import { CollectionToolbarUniDriver } from '../CollectionToolbar/CollectionToolbar.uni.driver'; import { AppliedFiltersTagListUniDriver } from '../AppliedFiltersTagList/AppliedFiltersTagList.uni.driver'; import TableUniDriver from '../Table/Table.uni.driver'; import { NestedTableParentCellUniDriver } from './NestedTableParentCell.uni.driver'; import { NestedTableFlatModeMainCellUniDriver } from './NestedTableFlatModeMainCell.uni.driver'; import { NestedTableRowPlaceholderStatesUniDriver } from './NestedTableRowPlaceholderStates.uni.driver'; import { CollectionItemActionsUniDriver } from '../CollectionItemActions/CollectionItemActions.uni.driver'; import { SummaryBarUniDriver } from '../SummaryBar/SummaryBar.uni.driver'; import { DragAndDropUniDriver } from '../DragAndDrop/DragAndDrop.uni.driver'; import { NestedTableGhostRowUniDriver } from '../NestedTableDragAndDrop/NestedTableGhostRow.uni.driver'; import { NestedTableDragOverlayUniDriver } from '../NestedTableDragAndDrop/NestedTableDragOverlay.uni.driver'; import { NestedTableRowUniDriver } from './NestedTableRow.uni.driver'; import { ExpandCollapseAllButtonUniDriver } from './ExpandCollapseAllButton.uni.driver'; export interface DragAndDropFullFlowOptions { horizontalPlacement?: 'child' | 'sibling' | 'parentSibling'; scrollDirectionToTarget?: 'up' | 'down'; } export function NestedTableUniDriver(base: UniDriver, body: UniDriver) { const toolbarBase = () => base.$('[data-hook="collection-toolbar"]'); const toolbar = () => CollectionToolbarUniDriver(toolbarBase(), body); const table = TableUniDriver(base, body); const loadingStateExists = () => base.$('[data-hook="placeholder-states-loading-state"]').exists(); const getSummaryBar = () => SummaryBarUniDriver(base, body); const dragAndDropFullFlow = async ( sourceRowBase: UniDriver, targetRowBase: UniDriver | null, options: DragAndDropFullFlowOptions = {}, ) => { const { horizontalPlacement = 'sibling', scrollDirectionToTarget } = options; const shiftLevel = horizontalPlacement === 'child' ? 1 : horizontalPlacement === 'parentSibling' ? -1 : 0; const dragAndDropDriver = DragAndDropUniDriver(base); const sourceNestedTableRow = NestedTableRowUniDriver(sourceRowBase, body); const sourceLevel = await sourceNestedTableRow.getLevel(); const sourceKey = await sourceNestedTableRow.getKey(); const sourceIndex = await table.getRenderedItemIndexByKey( sourceKey as string, ); const indentationWidth = await sourceNestedTableRow.getIndentationWidth(); await dragAndDropDriver.dragStart(sourceRowBase); if (targetRowBase == null) { await table.scrollToTop(); } else if (scrollDirectionToTarget === 'down') { await table.scrollDownTo(targetRowBase); } else if (scrollDirectionToTarget === 'up') { await table.scrollUpTo(targetRowBase); } const getTarget = async (targetRowBase: UniDriver) => { const targetNestedTableRow = NestedTableRowUniDriver(targetRowBase, body); const targetLevel = await targetNestedTableRow.getLevel(); const targetKey = await targetNestedTableRow.getKey(); const targetIndex = await table.getRenderedItemIndexByKey( targetKey as string, ); const indentationDiff = targetLevel - sourceLevel; const overIndex = targetIndex > sourceIndex ? targetIndex : targetIndex + 1; const deltaX = (indentationDiff + shiftLevel) * indentationWidth; return { targetLevel, targetIndex, indentationDiff, overIndex, deltaX, }; }; const target = targetRowBase ? await getTarget(targetRowBase) : { overIndex: 0, deltaX: 0, }; const overRowBase = table.getRowByIndex(target.overIndex); await dragAndDropDriver.moveOver(overRowBase, { delta: { x: target.deltaX, }, }); await dragAndDropDriver.dragEnd(overRowBase); }; return { ...table, toolbar: () => toolbar(), loadingStateExists, getRootErrorStateByDataHook: ( dataHook = 'placeholder-states-error-state', ) => ToolbarCollectionErrorStateUniDriver( base.$(`[data-hook="${dataHook}"]`), body, ), subToolbar: () => AppliedFiltersTagListUniDriver( base.$('[data-hook="collection-table-sub-toolbar"]'), body, ), isRowExpandable: async (rowKey: string) => (await table._getRowByKey(rowKey).attr('class'))?.includes('expandable'), getMainColumnAt: (row: number) => NestedTableParentCellUniDriver( table._getCellByRowIndexAndCellKey(row, 'nested-mode-main-column'), body, ), _getDragAndDropDriver: () => DragAndDropUniDriver(base), /** * Drag and drop a row by its key to a target row by its key. Possible options: * - sourceKey: The ID of the item being moved. * - targetKey: The ID of the target item (the one the moved item will be placed vertically after). If null - move the item to the top of the table (i.e no "target" item) * - options.placement: Defines the position of the moved item relative to the target: * - 'child': Places the moved item as a child of the target. * - 'sibling': Places the moved item as a sibling immediately after the target. - This is the default if options.placement is not provided by the developer * - 'parentSibling': Places the moved item as a sibling of the target's parent. * - options.scrollDirectionToTarget: Scroll to the target item before trying to drop. If not provided, no scroll will be done. * - 'down' * - 'up' */ dragAndDropRowByKey: async ( sourceKey: string, targetKey: string | null, options?: DragAndDropFullFlowOptions, ) => { return dragAndDropFullFlow( table._getRowByKey(sourceKey), targetKey ? table._getRowByKey(targetKey) : null, options, ); }, /** * Drag and drop a row by its index to a target row by its index. Possible options: * - sourceKey: The ID of the item being moved. * - targetKey: The ID of the target item (the one the moved item will be placed vertically after). If null - move the item to the top of the table (i.e no "target" item) * - options.placement: Defines the position of the moved item relative to the target: * - 'child': Places the moved item as a child of the target. * - 'sibling': Places the moved item as a sibling immediately after the target. - This is the default if options.placement is not provided by the developer * - 'parentSibling': Places the moved item as a sibling of the target's parent. * - options.scrollDirectionToTarget: Scroll to the target item before trying to drop. If not provided, will be determined by the indexes. * - 'down' * - 'up' */ dragAndDropRowAt: async ( sourceIndex: number, targetIndex: number | null, options: DragAndDropFullFlowOptions, ) => { return dragAndDropFullFlow( table.getRow(sourceIndex), targetIndex ? table.getRow(targetIndex) : null, { ...options, scrollDirectionToTarget: options.scrollDirectionToTarget ?? (targetIndex != null ? targetIndex > sourceIndex ? 'down' : 'up' : undefined), }, ); }, getActionCellByKey: (rowKey: string) => CollectionItemActionsUniDriver(table._getRowByKey(rowKey), body), getMainColumnByKey: (rowKey: string) => NestedTableParentCellUniDriver( table._getCellByKey(rowKey, 'nested-mode-main-column'), body, ), getRenderedRowsByParentKey: (parentId: string | null) => (parentId ? base.$$( `tbody tr[data-table-row="dataTableRow"][data-parent-key="${parentId}"]`, ) : base.$$( `tbody tr[data-table-row="dataTableRow"]:not([data-parent-key])`, ) ).map(async (row) => NestedTableRowUniDriver(row, body)), getRenderedRowsByLevel: (level: number) => base .$$(`tbody tr[data-table-row="dataTableRow"][data-level="${level}"]`) .map(async (row) => NestedTableRowUniDriver(row, body)), getRenderedRowByKey: (rowKey: string) => NestedTableRowUniDriver(table._getRowByKey(rowKey), body), getRowParentKey: (rowKey: string) => table._getRowByKey(rowKey).attr('data-parent-key'), getRowIndexInParent: async (rowKey: string) => Number(await table._getRowByKey(rowKey).attr('data-index-in-parent')), getFlatModeMainColumnByKey: (rowKey: string) => NestedTableFlatModeMainCellUniDriver( table._getCellByKey(rowKey, 'flat-mode-main-column'), body, ), getFlatModeMainColumnAt: (row: number) => NestedTableFlatModeMainCellUniDriver( table._getCellByRowIndexAndCellKey(row, 'flat-mode-main-column'), body, ), getPlaceholderStatesByRowKey: (rowKey: string) => NestedTableRowPlaceholderStatesUniDriver( table._getRowByKey(`placeholder-states-${rowKey}`), body, ), /** * Gets collection summary bar */ getSummaryBar, getGhostRow: () => NestedTableGhostRowUniDriver( base.$('[data-hook="ghost-indentation-cell"]'), body, ), getDragOverlay: () => NestedTableDragOverlayUniDriver( body.$('[data-hook="nested-table-dnd-overlay-wrapper"]'), body, ), getExpandCollapseAllButton: () => ExpandCollapseAllButtonUniDriver(base, body), }; } export default NestedTableUniDriver;