-
Notifications
You must be signed in to change notification settings - Fork 167
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Unit Test Case for useDraggableTable
- Loading branch information
Showing
2 changed files
with
423 additions
and
81 deletions.
There are no files selected for viewing
322 changes: 322 additions & 0 deletions
322
frontend/src/utilities/__tests__/useDraggableTable.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,322 @@ | ||
import { act } from '@testing-library/react'; | ||
import useDraggableTable from '~/utilities/useDraggableTable'; | ||
import { testHook } from '~/__tests__/unit/testUtils/hooks'; | ||
|
||
let setItemOrder = jest.fn(); | ||
beforeEach(() => { | ||
setItemOrder = jest.fn(); | ||
}); | ||
|
||
afterEach(() => { | ||
setItemOrder.mockReset(); | ||
}); | ||
|
||
const generateRowsWithItems = (itemOrder: string[]) => { | ||
const tbody = document.createElement('tbody'); | ||
|
||
itemOrder.forEach((itemId) => { | ||
const row = document.createElement('tr'); | ||
row.id = itemId; | ||
tbody.appendChild(row); | ||
}); | ||
|
||
return tbody; | ||
}; | ||
describe('initializeState', () => { | ||
it('should initialize state and return tableProps and rowProps', async () => { | ||
const renderResult = testHook(useDraggableTable)(['item1', 'item2', 'item3'], setItemOrder); | ||
expect(renderResult).hookToHaveUpdateCount(1); | ||
renderResult.rerender(['item1', 'item2', 'item3'], setItemOrder); | ||
|
||
expect(renderResult).hookToHaveUpdateCount(2); | ||
expect(renderResult.result.current.tableProps.tbodyProps.ref.current).toBe(null); | ||
expect(renderResult.result.current.tableProps.className).toBe(undefined); | ||
|
||
expect(renderResult).hookToBeStable({ | ||
rowProps: { onDragEnd: false, onDragStart: false, onDrop: false }, | ||
tableProps: { | ||
className: false, | ||
tbodyProps: { | ||
onDragLeave: false, | ||
onDragOver: false, | ||
ref: false, | ||
}, | ||
}, | ||
}); | ||
}); | ||
}); | ||
describe('dragStart', () => { | ||
it('should handle drag start behaviour correctly and setDraggedItemId accurately', () => { | ||
const itemOrder = ['item1', 'item2', 'item3']; | ||
const tableElement = generateRowsWithItems(itemOrder); | ||
document.body.appendChild(tableElement); | ||
|
||
const renderResult = testHook(useDraggableTable)(itemOrder, setItemOrder); | ||
const { rowProps, tableProps } = renderResult.result.current; | ||
const { onDragStart } = rowProps; | ||
const { ref } = tableProps.tbodyProps; | ||
|
||
ref.current = document.body.querySelector('tbody'); | ||
|
||
const dragStartEvent = { | ||
dataTransfer: { effectAllowed: 'none', setData: jest.fn() }, | ||
currentTarget: { | ||
id: 'item3', | ||
classList: { add: jest.fn() }, | ||
setAttribute: jest.fn(), | ||
}, | ||
} as unknown as React.DragEvent<HTMLTableRowElement>; | ||
|
||
expect(renderResult.result.current.tableProps.tbodyProps.ref.current).toBe(ref.current); | ||
expect(renderResult).hookToHaveUpdateCount(1); | ||
|
||
act(() => { | ||
onDragStart(dragStartEvent); | ||
}); | ||
|
||
expect(renderResult).hookToHaveUpdateCount(2); | ||
expect(dragStartEvent.dataTransfer.effectAllowed).toBe('move'); | ||
expect(dragStartEvent.dataTransfer.setData).toHaveBeenCalledWith('text/plain', 'item3'); | ||
expect(dragStartEvent.currentTarget.classList.add).toHaveBeenCalledWith('pf-m-ghost-row'); | ||
expect(dragStartEvent.currentTarget.setAttribute).toHaveBeenCalledWith('aria-pressed', 'true'); | ||
expect(renderResult.result.current.tableProps.className).toBe('pf-m-drag-over'); | ||
|
||
tableProps.tbodyProps.ref.current = null; | ||
}); | ||
}); | ||
describe('onDrop', () => { | ||
it('should handle onDrop behaviour with valid ref and event', () => { | ||
const itemOrder = ['item3', 'item1', 'item2']; | ||
const tableElement = generateRowsWithItems(itemOrder); | ||
document.body.appendChild(tableElement); | ||
|
||
const renderResult = testHook(useDraggableTable)(itemOrder, setItemOrder); | ||
|
||
const { rowProps, tableProps } = renderResult.result.current; | ||
const { onDrop } = rowProps; | ||
const { ref } = tableProps.tbodyProps; | ||
ref.current = document.body.querySelector('tbody'); | ||
|
||
if (ref.current) { | ||
ref.current.getBoundingClientRect = jest.fn().mockReturnValue({ | ||
x: 40, | ||
y: 40, | ||
width: 20, | ||
height: 20, | ||
} as DOMRect); | ||
} | ||
|
||
act(() => { | ||
onDrop({ | ||
clientX: 45, | ||
clientY: 45, | ||
} as unknown as React.DragEvent<HTMLTableRowElement>); | ||
}); | ||
|
||
expect(renderResult).hookToHaveUpdateCount(1); | ||
expect(setItemOrder).toHaveBeenCalledWith(itemOrder); | ||
expect(renderResult.result.current.tableProps.tbodyProps.ref.current).toBe(ref.current); | ||
expect(renderResult.result.current.tableProps.className).toBe(undefined); | ||
}); | ||
|
||
it('should call onDragCancel when event is invalid and ref is null', () => { | ||
const renderResult = testHook(useDraggableTable)(['item1', 'item2', 'item3'], setItemOrder); | ||
|
||
const { rowProps, tableProps } = renderResult.result.current; | ||
const { onDrop } = rowProps; | ||
const { ref } = tableProps.tbodyProps; | ||
ref.current = null; | ||
|
||
expect(renderResult.result.current.tableProps.tbodyProps.ref.current).toBe(null); | ||
|
||
act(() => { | ||
onDrop({} as unknown as React.DragEvent<HTMLTableRowElement>); | ||
}); | ||
|
||
expect(renderResult).hookToHaveUpdateCount(1); | ||
expect(setItemOrder).not.toHaveBeenCalled(); | ||
|
||
tableProps.tbodyProps.ref.current = null; | ||
}); | ||
|
||
it('should call onDragCancel when event is invalid but ref is not null', () => { | ||
const itemOrder = ['item1', 'item2', 'item3']; | ||
const tableElement = generateRowsWithItems(itemOrder); | ||
document.body.appendChild(tableElement); | ||
|
||
const renderResult = testHook(useDraggableTable)(itemOrder, setItemOrder); | ||
|
||
const { rowProps, tableProps } = renderResult.result.current; | ||
const { onDrop } = rowProps; | ||
const { ref } = tableProps.tbodyProps; | ||
ref.current = document.body.querySelector('tbody'); | ||
|
||
act(() => { | ||
onDrop({} as unknown as React.DragEvent<HTMLTableRowElement>); | ||
}); | ||
|
||
expect(renderResult).hookToHaveUpdateCount(1); | ||
expect(setItemOrder).not.toHaveBeenCalled(); | ||
expect(renderResult.result.current.tableProps.tbodyProps.ref.current).toBe(ref.current); | ||
|
||
tableProps.tbodyProps.ref.current = null; | ||
}); | ||
}); | ||
describe('onDragOver', () => { | ||
it('should handle dragover behaviour correctly with different item id', () => { | ||
const itemOrder = ['item1', 'item2', 'item3']; | ||
const tableElement = generateRowsWithItems(itemOrder); | ||
document.body.appendChild(tableElement); | ||
|
||
const renderResult = testHook(useDraggableTable)(itemOrder, setItemOrder); | ||
|
||
const { tableProps } = renderResult.result.current; | ||
const { onDragOver, ref } = tableProps.tbodyProps; | ||
ref.current = document.body.querySelector('tbody'); | ||
|
||
act(() => { | ||
onDragOver({ | ||
preventDefault: jest.fn(), | ||
clientX: 50, | ||
clientY: 50, | ||
target: document.body.querySelector('tbody tr:first-child'), | ||
} as unknown as React.DragEvent<HTMLTableSectionElement>); | ||
}); | ||
|
||
expect(tableProps.tbodyProps.ref).toBe(ref); | ||
}); | ||
it('should handle dragover behaviour correctly with same item id', () => { | ||
const itemOrder = ['item1', 'item2', 'item3']; | ||
const tableElement = generateRowsWithItems(itemOrder); | ||
document.body.appendChild(tableElement); | ||
|
||
const renderResult = testHook(useDraggableTable)(itemOrder, setItemOrder); | ||
|
||
const { tableProps } = renderResult.result.current; | ||
const { onDragOver, ref } = tableProps.tbodyProps; | ||
ref.current = document.body.querySelector('tbody'); | ||
|
||
act(() => { | ||
onDragOver({ | ||
preventDefault: jest.fn(), | ||
clientX: 50, | ||
clientY: 50, | ||
target: document.body.querySelector('tbody tr:first-child'), | ||
} as unknown as React.DragEvent<HTMLTableSectionElement>); | ||
}); | ||
expect(tableProps.tbodyProps.ref).toBe(ref); | ||
}); | ||
it('should handle dragover behaviour correctly when bodyRef is null', async () => { | ||
const itemOrder = ['item1', 'item2', 'item3']; | ||
const tableElement = generateRowsWithItems(itemOrder); | ||
document.body.appendChild(tableElement); | ||
|
||
const renderResult = testHook(useDraggableTable)(['item1', 'item2', 'item3'], setItemOrder); | ||
|
||
const { tableProps } = renderResult.result.current; | ||
const { onDragOver, ref } = tableProps.tbodyProps; | ||
ref.current = null; | ||
|
||
act(() => { | ||
onDragOver({ | ||
preventDefault: jest.fn(), | ||
clientX: 50, | ||
clientY: 50, | ||
target: document.body.querySelector('tbody tr:first-child'), | ||
} as unknown as React.DragEvent<HTMLTableSectionElement>); | ||
}); | ||
}); | ||
it('should handle drag and drop behavior correctly with invalid element', async () => { | ||
const itemOrder = ['item1', 'item2', 'item3']; | ||
const inValidElement = document.createElement('td'); | ||
inValidElement.id = 'item3'; | ||
document.body.appendChild(inValidElement); | ||
|
||
const renderResult = testHook(useDraggableTable)(itemOrder, setItemOrder); | ||
|
||
const { tableProps } = renderResult.result.current; | ||
const { onDragOver, ref } = tableProps.tbodyProps; | ||
|
||
ref.current = document.body.querySelector('tbody'); | ||
|
||
act(() => { | ||
onDragOver({ | ||
preventDefault: jest.fn(), | ||
clientX: 50, | ||
clientY: 50, | ||
target: inValidElement, | ||
} as unknown as React.DragEvent<HTMLTableSectionElement>); | ||
}); | ||
|
||
expect(tableProps.tbodyProps.ref).toBe(ref); | ||
}); | ||
}); | ||
describe('onDragEnd', () => { | ||
it('should handle drag end behaviour correctly', () => { | ||
const itemOrder = ['item3', 'item1', 'item2']; | ||
const tableElement = generateRowsWithItems(itemOrder); | ||
document.body.appendChild(tableElement); | ||
|
||
const renderResult = testHook(useDraggableTable)(itemOrder, setItemOrder); | ||
|
||
const { rowProps, tableProps } = renderResult.result.current; | ||
const { onDragEnd } = rowProps; | ||
const { ref } = tableProps.tbodyProps; | ||
ref.current = document.body.querySelector('tbody'); | ||
|
||
expect(renderResult.result.current.tableProps.tbodyProps.ref.current).toBe(ref.current); | ||
|
||
const dragEndEvent = { | ||
target: { | ||
id: 'item3', | ||
classList: { remove: jest.fn() }, | ||
setAttribute: jest.fn(), | ||
}, | ||
} as unknown as React.DragEvent<HTMLTableRowElement>; | ||
|
||
act(() => { | ||
onDragEnd(dragEndEvent); | ||
}); | ||
expect(renderResult).hookToHaveUpdateCount(1); | ||
expect((dragEndEvent.target as HTMLTableRowElement).classList.remove).toHaveBeenCalled(); | ||
expect((dragEndEvent.target as HTMLTableRowElement).setAttribute).toHaveBeenCalledWith( | ||
'aria-pressed', | ||
'false', | ||
); | ||
}); | ||
}); | ||
describe('onDragLeave', () => { | ||
const dragLeaveEvent = {} as unknown as React.DragEvent<HTMLTableSectionElement>; | ||
|
||
it('should handle drag leave behaviour correctly with invalid event', () => { | ||
const itemOrder = ['item1', 'item2', 'item3']; | ||
const renderResult = testHook(useDraggableTable)(itemOrder, setItemOrder); | ||
|
||
const { tableProps } = renderResult.result.current; | ||
const { onDragLeave, ref } = tableProps.tbodyProps; | ||
ref.current = null; | ||
|
||
act(() => { | ||
onDragLeave(dragLeaveEvent); | ||
}); | ||
expect(renderResult.result.current.tableProps.tbodyProps.ref.current).toBe(null); | ||
expect(renderResult.result.current.tableProps.className).toBe(undefined); | ||
expect(renderResult).hookToHaveUpdateCount(1); | ||
}); | ||
|
||
it('should remove the last child if ulNode has children', () => { | ||
const itemOrder = ['item4']; | ||
const tableElement = generateRowsWithItems(itemOrder); | ||
document.body.appendChild(tableElement); | ||
|
||
const renderResult = testHook(useDraggableTable)(itemOrder, setItemOrder); | ||
const { tableProps } = renderResult.result.current; | ||
const { onDragLeave, ref } = tableProps.tbodyProps; | ||
|
||
ref.current = document.body.querySelector('tbody'); | ||
expect(renderResult.result.current.tableProps.tbodyProps.ref.current).toBe(ref.current); | ||
act(() => { | ||
onDragLeave(dragLeaveEvent); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.