172 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			172 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
|  | import { expect, tap } from '@git.zone/tstest/tapbundle'; | ||
|  | import { DeesInputWysiwyg } from '../ts_web/elements/wysiwyg/dees-input-wysiwyg.js'; | ||
|  | 
 | ||
|  | // Initialize the element
 | ||
|  | DeesInputWysiwyg; | ||
|  | 
 | ||
|  | tap.test('wysiwyg drag and drop should work correctly', async () => { | ||
|  |   const element = document.createElement('dees-input-wysiwyg'); | ||
|  |   document.body.appendChild(element); | ||
|  |    | ||
|  |   // Wait for element to be ready
 | ||
|  |   await element.updateComplete; | ||
|  |    | ||
|  |   // Set initial content with multiple blocks
 | ||
|  |   element.blocks = [ | ||
|  |     { id: 'block1', type: 'paragraph', content: 'First paragraph' }, | ||
|  |     { id: 'block2', type: 'heading-2', content: 'Test Heading' }, | ||
|  |     { id: 'block3', type: 'paragraph', content: 'Second paragraph' }, | ||
|  |   ]; | ||
|  |   element.renderBlocksProgrammatically(); | ||
|  |    | ||
|  |   await element.updateComplete; | ||
|  |    | ||
|  |   // Check that blocks are rendered
 | ||
|  |   const editorContent = element.shadowRoot!.querySelector('.editor-content') as HTMLDivElement; | ||
|  |   expect(editorContent).toBeTruthy(); | ||
|  |    | ||
|  |   const blockWrappers = editorContent.querySelectorAll('.block-wrapper'); | ||
|  |   expect(blockWrappers.length).toEqual(3); | ||
|  |    | ||
|  |   // Test drag handles exist for non-divider blocks
 | ||
|  |   const dragHandles = editorContent.querySelectorAll('.drag-handle'); | ||
|  |   expect(dragHandles.length).toEqual(3); | ||
|  |    | ||
|  |   // Get references to specific blocks
 | ||
|  |   const firstBlock = editorContent.querySelector('[data-block-id="block1"]') as HTMLElement; | ||
|  |   const secondBlock = editorContent.querySelector('[data-block-id="block2"]') as HTMLElement; | ||
|  |   const firstDragHandle = firstBlock.querySelector('.drag-handle') as HTMLElement; | ||
|  |    | ||
|  |   expect(firstBlock).toBeTruthy(); | ||
|  |   expect(secondBlock).toBeTruthy(); | ||
|  |   expect(firstDragHandle).toBeTruthy(); | ||
|  |    | ||
|  |   // Test drag initialization
 | ||
|  |   console.log('Testing drag initialization...'); | ||
|  |    | ||
|  |   // Create drag event
 | ||
|  |   const dragStartEvent = new DragEvent('dragstart', { | ||
|  |     dataTransfer: new DataTransfer(), | ||
|  |     clientY: 100, | ||
|  |     bubbles: true | ||
|  |   }); | ||
|  |    | ||
|  |   // Simulate drag start
 | ||
|  |   firstDragHandle.dispatchEvent(dragStartEvent); | ||
|  |    | ||
|  |   // Check that drag state is initialized
 | ||
|  |   expect(element.dragDropHandler.dragState.draggedBlockId).toEqual('block1'); | ||
|  |    | ||
|  |   // Check that dragging class is applied
 | ||
|  |   await new Promise(resolve => setTimeout(resolve, 20)); // Wait for setTimeout in drag start
 | ||
|  |   expect(firstBlock.classList.contains('dragging')).toBeTrue(); | ||
|  |   expect(editorContent.classList.contains('dragging')).toBeTrue(); | ||
|  |    | ||
|  |   // Test drop indicator creation
 | ||
|  |   const dropIndicator = editorContent.querySelector('.drop-indicator'); | ||
|  |   expect(dropIndicator).toBeTruthy(); | ||
|  |    | ||
|  |   // Simulate drag over
 | ||
|  |   const dragOverEvent = new DragEvent('dragover', { | ||
|  |     dataTransfer: new DataTransfer(), | ||
|  |     clientY: 200, | ||
|  |     bubbles: true, | ||
|  |     cancelable: true | ||
|  |   }); | ||
|  |    | ||
|  |   document.dispatchEvent(dragOverEvent); | ||
|  |    | ||
|  |   // Check that blocks move out of the way
 | ||
|  |   console.log('Checking block movements...'); | ||
|  |   const blocks = Array.from(editorContent.querySelectorAll('.block-wrapper')); | ||
|  |   const hasMovedBlocks = blocks.some(block =>  | ||
|  |     block.classList.contains('move-up') || block.classList.contains('move-down') | ||
|  |   ); | ||
|  |    | ||
|  |   console.log('Blocks with move classes:', blocks.filter(block =>  | ||
|  |     block.classList.contains('move-up') || block.classList.contains('move-down') | ||
|  |   ).length); | ||
|  |    | ||
|  |   // Test drag end
 | ||
|  |   const dragEndEvent = new DragEvent('dragend', { | ||
|  |     bubbles: true | ||
|  |   }); | ||
|  |    | ||
|  |   document.dispatchEvent(dragEndEvent); | ||
|  |    | ||
|  |   // Wait for cleanup
 | ||
|  |   await new Promise(resolve => setTimeout(resolve, 150)); | ||
|  |    | ||
|  |   // Check that drag state is cleaned up
 | ||
|  |   expect(element.dragDropHandler.dragState.draggedBlockId).toBeNull(); | ||
|  |   expect(firstBlock.classList.contains('dragging')).toBeFalse(); | ||
|  |   expect(editorContent.classList.contains('dragging')).toBeFalse(); | ||
|  |    | ||
|  |   // Check that drop indicator is removed
 | ||
|  |   const dropIndicatorAfter = editorContent.querySelector('.drop-indicator'); | ||
|  |   expect(dropIndicatorAfter).toBeFalsy(); | ||
|  |    | ||
|  |   // Clean up
 | ||
|  |   document.body.removeChild(element); | ||
|  | }); | ||
|  | 
 | ||
|  | tap.test('wysiwyg drag and drop visual feedback', async () => { | ||
|  |   const element = document.createElement('dees-input-wysiwyg'); | ||
|  |   document.body.appendChild(element); | ||
|  |    | ||
|  |   await element.updateComplete; | ||
|  |    | ||
|  |   // Set initial content
 | ||
|  |   element.blocks = [ | ||
|  |     { id: 'block1', type: 'paragraph', content: 'Block 1' }, | ||
|  |     { id: 'block2', type: 'paragraph', content: 'Block 2' }, | ||
|  |     { id: 'block3', type: 'paragraph', content: 'Block 3' }, | ||
|  |   ]; | ||
|  |   element.renderBlocksProgrammatically(); | ||
|  |    | ||
|  |   await element.updateComplete; | ||
|  |    | ||
|  |   const editorContent = element.shadowRoot!.querySelector('.editor-content') as HTMLDivElement; | ||
|  |   const block1 = editorContent.querySelector('[data-block-id="block1"]') as HTMLElement; | ||
|  |   const dragHandle1 = block1.querySelector('.drag-handle') as HTMLElement; | ||
|  |    | ||
|  |   // Start dragging block 1
 | ||
|  |   const dragStartEvent = new DragEvent('dragstart', { | ||
|  |     dataTransfer: new DataTransfer(), | ||
|  |     clientY: 50, | ||
|  |     bubbles: true | ||
|  |   }); | ||
|  |    | ||
|  |   dragHandle1.dispatchEvent(dragStartEvent); | ||
|  |    | ||
|  |   // Wait for dragging class
 | ||
|  |   await new Promise(resolve => setTimeout(resolve, 20)); | ||
|  |    | ||
|  |   // Simulate dragging down
 | ||
|  |   const dragOverEvent = new DragEvent('dragover', { | ||
|  |     dataTransfer: new DataTransfer(), | ||
|  |     clientY: 150, // Move down past block 2
 | ||
|  |     bubbles: true, | ||
|  |     cancelable: true | ||
|  |   }); | ||
|  |    | ||
|  |   // Trigger the global drag over handler
 | ||
|  |   element.dragDropHandler['handleGlobalDragOver'](dragOverEvent); | ||
|  |    | ||
|  |   // Check that transform is applied to dragged block
 | ||
|  |   const transform = block1.style.transform; | ||
|  |   console.log('Dragged block transform:', transform); | ||
|  |   expect(transform).toContain('translateY'); | ||
|  |    | ||
|  |   // Check drop indicator position
 | ||
|  |   const dropIndicator = editorContent.querySelector('.drop-indicator') as HTMLElement; | ||
|  |   if (dropIndicator) { | ||
|  |     const indicatorStyle = dropIndicator.style; | ||
|  |     console.log('Drop indicator position:', indicatorStyle.top, 'display:', indicatorStyle.display); | ||
|  |   } | ||
|  |    | ||
|  |   // Clean up
 | ||
|  |   document.body.removeChild(element); | ||
|  | }); | ||
|  | 
 | ||
|  | tap.start(); |