Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[tests-only][full-ci]add test to upload folder via drag-n-drop #11322

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion tests/e2e/cucumber/features/smoke/upload.feature
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ Feature: Upload
| resource |
| simple.pdf |
And "Alice" closes the file viewer

#upload folder via drag-n-drop
And "Alice" uploads the following resources via drag-n-drop
| resource |
| Folder,With,Comma |
# upload empty folder
And "Alice" uploads the following resources
| resource | type |
Expand Down
121 changes: 95 additions & 26 deletions tests/e2e/support/utils/dragDrop.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,106 @@
import { readFileSync } from 'fs'
import { Page } from '@playwright/test'
import fs from 'fs'
import path from 'path'
import { promises as fsPromises } from 'fs'

interface File {
name: string
path: string
name: string
path: string
}

interface FileBuffer {
name: string
bufferString: string
name: string
bufferString: string
}


async function getAllFiles(dirPath: string, baseName: string = ''): Promise<File[]> {
const results: File[] = []
const items = await fsPromises.readdir(dirPath)

// Add the root directory to results
results.push({
name: baseName ? `${baseName}/` : '', // Add '/' to denote directory if baseName is not empty
path: dirPath
})
for (const item of items) {
const fullPath = path.join(dirPath, item)
const stats = await fsPromises.stat(fullPath)
if (stats.isDirectory()) {
// results.push({
// name: path.join(baseName, item),
// path: fullPath
// })
// Recursively process subdirectories
results.push(...(await getAllFiles(fullPath, path.join(baseName, item))))
} else if (stats.isFile()) {
results.push({
name: path.join(baseName, item),
path: fullPath
})
}
}
// console.log(results)
return results
}

export const dragDropFiles = async (page: Page, resources: File[], targetSelector: string) => {
const files = resources.map((file) => ({
name: file.name,
bufferString: JSON.stringify(Array.from(readFileSync(file.path)))
}))

await page.evaluate<Promise<void>, [FileBuffer[], string]>(
([files, targetSelector]) => {
const dropArea = document.querySelector(targetSelector)
const dt = new DataTransfer()

for (const file of files) {
const buffer = Buffer.from(JSON.parse(file.bufferString))
const blob = new Blob([buffer])
dt.items.add(new File([blob], file.name))
}

dropArea.dispatchEvent(new DragEvent('drop', { dataTransfer: dt }))

return Promise.resolve()
},
[files, targetSelector]
)
const allFiles: File[] = []

for (const resource of resources) {
const stats = await fsPromises.stat(resource.path)
if (stats.isDirectory()) {
const filesInDir = await getAllFiles(resource.path, resource.name)
allFiles.push(...filesInDir)
} else if (stats.isFile()) {
allFiles.push(resource)
}
}
console.log(allFiles)
const filesBuffer: FileBuffer[] = await Promise.all(
allFiles.map(async (file) => {
if (fs.statSync(file.path).isDirectory()) {
return {
name: file.name,
bufferString: null
}
} else {
const buffer = await fsPromises.readFile(file.path)
return {
name: file.name,
bufferString: JSON.stringify(Array.from(buffer))
}
}
})
)

await page.evaluate<Promise<void>, [FileBuffer[], string]>(
async ([filesBuffer, targetSelector]) => {
const dropArea = document.querySelector(targetSelector)
if (!dropArea) {
throw new Error(`Drop area with selector ${targetSelector} not found.`)
}

const dt = new DataTransfer()

for (const file of filesBuffer) {
if (file.bufferString === null) {
// Placeholder for handling directory upload
const dirBlob = new Blob([])
dt.items.add(new File([dirBlob], file.name))
} else {
const buffer = new Uint8Array(JSON.parse(file.bufferString))
const blob = new Blob([buffer])
const fileObj = new File([blob], file.name)
dt.items.add(fileObj)
}
}

dropArea.dispatchEvent(new DragEvent('drop', { dataTransfer: dt }))

return Promise.resolve()
},
[filesBuffer, targetSelector]
)
}