mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-27 08:25:50 +00:00
## Summary Adds e2e testing to ensure workflows are correctly loaded from each of the supported file types ## Changes - **What**: - add png generation - add mime types for missing files - add test that loads file and ensures node is present ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11522-test-add-e2e-test-for-metadata-parsing-on-workflow-load-3496d73d36508101ad67d24af1810cec) by [Unito](https://www.unito.io)
181 lines
5.1 KiB
TypeScript
181 lines
5.1 KiB
TypeScript
import { readFileSync } from 'fs'
|
|
import { basename } from 'path'
|
|
|
|
import type { Page } from '@playwright/test'
|
|
|
|
import type { Position } from '@e2e/fixtures/types'
|
|
import { getMimeType } from '@e2e/fixtures/utils/mimeTypeUtil'
|
|
import { assetPath } from '@e2e/fixtures/utils/paths'
|
|
import { nextFrame } from '@e2e/fixtures/utils/timing'
|
|
|
|
export class DragDropHelper {
|
|
constructor(private readonly page: Page) {}
|
|
|
|
async dragAndDropExternalResource(
|
|
options: {
|
|
fileName?: string
|
|
filePath?: string
|
|
url?: string
|
|
dropPosition?: Position
|
|
waitForUpload?: boolean
|
|
preserveNativePropagation?: boolean
|
|
} = {}
|
|
): Promise<void> {
|
|
const {
|
|
dropPosition = { x: 100, y: 100 },
|
|
fileName,
|
|
filePath,
|
|
url,
|
|
waitForUpload = false,
|
|
preserveNativePropagation = false
|
|
} = options
|
|
|
|
if (!fileName && !filePath && !url)
|
|
throw new Error('Must provide fileName, filePath, or url')
|
|
|
|
const evaluateParams: {
|
|
dropPosition: Position
|
|
fileName?: string
|
|
fileType?: string
|
|
buffer?: Uint8Array | number[]
|
|
url?: string
|
|
preserveNativePropagation: boolean
|
|
} = { dropPosition, preserveNativePropagation }
|
|
|
|
if (fileName || filePath) {
|
|
const resolvedPath = filePath ?? assetPath(fileName!)
|
|
const displayName = fileName ?? basename(resolvedPath)
|
|
let buffer: Buffer
|
|
try {
|
|
buffer = readFileSync(resolvedPath)
|
|
} catch (error) {
|
|
const reason = error instanceof Error ? error.message : String(error)
|
|
throw new Error(
|
|
`Failed to read drag-and-drop fixture at "${resolvedPath}": ${reason}`,
|
|
{ cause: error }
|
|
)
|
|
}
|
|
|
|
evaluateParams.fileName = displayName
|
|
evaluateParams.fileType = getMimeType(displayName)
|
|
evaluateParams.buffer = [...new Uint8Array(buffer)]
|
|
}
|
|
|
|
if (url) evaluateParams.url = url
|
|
|
|
const uploadResponsePromise = waitForUpload
|
|
? this.page.waitForResponse(
|
|
(resp) => resp.url().includes('/upload/') && resp.status() === 200,
|
|
{ timeout: 10000 }
|
|
)
|
|
: null
|
|
|
|
await this.page.evaluate(async (params) => {
|
|
const dataTransfer = new DataTransfer()
|
|
|
|
if (params.buffer && params.fileName && params.fileType) {
|
|
const file = new File(
|
|
[new Uint8Array(params.buffer)],
|
|
params.fileName,
|
|
{
|
|
type: params.fileType
|
|
}
|
|
)
|
|
dataTransfer.items.add(file)
|
|
}
|
|
|
|
if (params.url) {
|
|
dataTransfer.setData('text/uri-list', params.url)
|
|
dataTransfer.setData('text/x-moz-url', params.url)
|
|
}
|
|
|
|
const targetElement = document.elementFromPoint(
|
|
params.dropPosition.x,
|
|
params.dropPosition.y
|
|
)
|
|
|
|
if (!targetElement) {
|
|
throw new Error(
|
|
`No element found at drop position: (${params.dropPosition.x}, ${params.dropPosition.y}). ` +
|
|
`document.elementFromPoint returned null. Ensure the target is visible and not obscured.`
|
|
)
|
|
}
|
|
|
|
const eventOptions = {
|
|
bubbles: true,
|
|
cancelable: true,
|
|
dataTransfer,
|
|
clientX: params.dropPosition.x,
|
|
clientY: params.dropPosition.y
|
|
}
|
|
|
|
const dragOverEvent = new DragEvent('dragover', eventOptions)
|
|
const dropEvent = new DragEvent('drop', eventOptions)
|
|
|
|
const graphCanvasElement = document.querySelector('#graph-canvas')
|
|
|
|
// Keep Litegraph's drag-over node tracking in sync when the drop target is a
|
|
// Vue node DOM overlay outside of the graph canvas element.
|
|
if (graphCanvasElement && !graphCanvasElement.contains(targetElement)) {
|
|
graphCanvasElement.dispatchEvent(
|
|
new DragEvent('dragover', eventOptions)
|
|
)
|
|
}
|
|
|
|
if (!params.preserveNativePropagation) {
|
|
Object.defineProperty(dropEvent, 'preventDefault', {
|
|
value: () => {},
|
|
writable: false
|
|
})
|
|
|
|
Object.defineProperty(dropEvent, 'stopPropagation', {
|
|
value: () => {},
|
|
writable: false
|
|
})
|
|
}
|
|
|
|
targetElement.dispatchEvent(dragOverEvent)
|
|
targetElement.dispatchEvent(dropEvent)
|
|
|
|
return {
|
|
success: true,
|
|
targetInfo: {
|
|
tagName: targetElement.tagName,
|
|
id: targetElement.id,
|
|
classList: Array.from(targetElement.classList)
|
|
}
|
|
}
|
|
}, evaluateParams)
|
|
|
|
if (uploadResponsePromise) {
|
|
await uploadResponsePromise
|
|
}
|
|
|
|
await nextFrame(this.page)
|
|
}
|
|
|
|
async dragAndDropFile(
|
|
fileName: string,
|
|
options: { dropPosition?: Position; waitForUpload?: boolean } = {}
|
|
): Promise<void> {
|
|
return this.dragAndDropExternalResource({ fileName, ...options })
|
|
}
|
|
|
|
async dragAndDropFilePath(
|
|
filePath: string,
|
|
options: { dropPosition?: Position; waitForUpload?: boolean } = {}
|
|
): Promise<void> {
|
|
return this.dragAndDropExternalResource({ filePath, ...options })
|
|
}
|
|
|
|
async dragAndDropURL(
|
|
url: string,
|
|
options: {
|
|
dropPosition?: Position
|
|
preserveNativePropagation?: boolean
|
|
} = {}
|
|
): Promise<void> {
|
|
return this.dragAndDropExternalResource({ url, ...options })
|
|
}
|
|
}
|