const { _electron: electron } = require('@playwright/test') const { test: it } = require('@playwright/test') const { describe } = it it.setTimeout(10000000) const delay = require('./common/wait') const log = require('./common/log') const appOptions = require('./common/app-options') const extendClient = require('./common/client-extend') const { expect } = require('./common/expect') const { setupSftpConnection, createFile, createFolder, deleteItem, enterFolder, navigateToParentFolder, verifyFileExists, verifyFileTransfersComplete, selectAllContextMenu, // Added missing import closeApp } = require('./common/common') describe('file-transfer-local-remote', function () { it('should test file and folder transfer including folders with files', async function () { const electronApp = await electron.launch(appOptions) const client = await electronApp.firstWindow() extendClient(client, electronApp) await delay(3500) log('018.file-transfer.spec.js: app launched') await setupSftpConnection(client) log('018.file-transfer.spec.js: sftp connected') // Test transfer local->remote and remote->local await testFileTransfer(client) log('018.file-transfer.spec.js: file transfer tested') await closeApp(electronApp, __filename) log('018.file-transfer.spec.js: app closed') }) }) async function testFileTransfer (client) { const timestamp = Date.now() // Create main test folders in both local and remote const mainFolder = `transfer-test-${timestamp}` await createFolder(client, 'local', mainFolder) await createFolder(client, 'remote', mainFolder) // Enter the test folder in local await enterFolder(client, 'local', mainFolder) await delay(2000) // Create test files in local with specific prefixes for easier identification const localFiles = [ `local-file-1-${timestamp}.txt`, `local-file-2-${timestamp}.txt`, `local-file-3-${timestamp}.txt` ] // Create test folders in local const localFolders = [ `local-folder-1-${timestamp}`, `local-folder-2-${timestamp}`, `local-folder-3-${timestamp}` ] // Create all test items in local for (const fileName of localFiles) { await createFile(client, 'local', fileName) await delay(800) } for (const folderName of localFolders) { await createFolder(client, 'local', folderName) await delay(800) } // Drag a file into one of the folders in local const localSourceElement = await client.locator(`.session-current .file-list.local .sftp-item[title="${localFiles[0]}"]`) const localTargetElement = await client.locator(`.session-current .file-list.local .sftp-item[title="${localFolders[0]}"]`) // Get bounding boxes for drag operation const localSourceBound = await localSourceElement.boundingBox() const localTargetBound = await localTargetElement.boundingBox() // Perform drag operation await client.mouse.move(localSourceBound.x + localSourceBound.width / 2, localSourceBound.y + localSourceBound.height / 2) await client.mouse.down() await delay(500) await client.mouse.move(localTargetBound.x + localTargetBound.width / 2, localTargetBound.y + localTargetBound.height / 2, { steps: 20 }) await delay(500) await client.mouse.up() await delay(3000) // Wait for drag-drop operation to complete // Enter the test folder in remote await enterFolder(client, 'remote', mainFolder) await delay(2000) // Create test files in remote with specific prefixes const remoteFiles = [ `remote-file-1-${timestamp}.txt`, `remote-file-2-${timestamp}.txt`, `remote-file-3-${timestamp}.txt` ] // Create test folders in remote const remoteFolders = [ `remote-folder-1-${timestamp}`, `remote-folder-2-${timestamp}`, `remote-folder-3-${timestamp}` ] // Create all test items in remote for (const fileName of remoteFiles) { await createFile(client, 'remote', fileName) await delay(800) } for (const folderName of remoteFolders) { await createFolder(client, 'remote', folderName) await delay(800) } // Drag a file into one of the folders in remote const remoteSourceElement = await client.locator(`.session-current .file-list.remote .sftp-item[title="${remoteFiles[0]}"]`) const remoteTargetElement = await client.locator(`.session-current .file-list.remote .sftp-item[title="${remoteFolders[0]}"]`) // Get bounding boxes for drag operation const remoteSourceBound = await remoteSourceElement.boundingBox() const remoteTargetBound = await remoteTargetElement.boundingBox() // Perform drag operation await client.mouse.move(remoteSourceBound.x + remoteSourceBound.width / 2, remoteSourceBound.y + remoteSourceBound.height / 2) await client.mouse.down() await delay(500) await client.mouse.move(remoteTargetBound.x + remoteTargetBound.width / 2, remoteTargetBound.y + remoteTargetBound.height / 2, { steps: 20 }) await delay(500) await client.mouse.up() await delay(3000) // Wait for drag-drop operation to complete // PART 1: LOCAL TO REMOTE TRANSFER (using context menu select all) // Since one file is now in a folder, combine remaining visible items const localVisibleItems = [localFiles[1], localFiles[2], ...localFolders] // Use context menu to select all visible items in local await selectAllContextMenu(client, 'local') await delay(1000) // Verify we selected the correct number of items const selectedLocalItems = await client.locator('.session-current .file-list.local .sftp-item.selected') const selectedLocalCount = await selectedLocalItems.count() expect(selectedLocalCount).toBe(5) // 2 files + 3 folders // Use context menu to upload to remote await client.rightClick('.session-current .file-list.local .sftp-item.selected', 10, 10) await delay(1000) // Click the upload menu item await client.click('.ant-dropdown:not(.ant-dropdown-hidden) .ant-dropdown-menu-item .anticon.anticon-cloud-upload') await delay(10000) // Increased delay for folders with files to transfer // Verify fileTransfers array is empty after the operation await verifyFileTransfersComplete(client) // Verify all local items were transferred to remote, including folder structure for (const itemName of localVisibleItems) { expect(await verifyFileExists(client, 'remote', itemName)).toBe(true) } // Verify the file inside the transferred folder await enterFolder(client, 'remote', localFolders[0]) await delay(2000) expect(await verifyFileExists(client, 'remote', localFiles[0])).toBe(true) await navigateToParentFolder(client, 'remote') await delay(2000) // PART 2: REMOTE TO LOCAL TRANSFER (using ctrl/cmd-select) // Since one file is now in a folder, combine remaining visible items const remoteVisibleItems = [remoteFiles[1], remoteFiles[2], ...remoteFolders] // Use ctrl/cmd-select for remote items await client.click(`.session-current .file-list.remote .sftp-item[title="${remoteVisibleItems[0]}"]`) await delay(500) // Use keyboard modifier to select the rest of the items const isMac = process.platform === 'darwin' const modifier = isMac ? 'Meta' : 'Control' for (let i = 1; i < remoteVisibleItems.length; i++) { const itemElement = await client.locator(`.session-current .file-list.remote .sftp-item[title="${remoteVisibleItems[i]}"]`) await itemElement.click({ modifiers: [modifier] }) await delay(500) } // Verify we selected the correct number of items const selectedRemoteItems = await client.locator('.session-current .file-list.remote .sftp-item.selected') const selectedRemoteCount = await selectedRemoteItems.count() expect(selectedRemoteCount).toBe(5) // 2 files + 3 folders // Use context menu to download to local await client.rightClick('.session-current .file-list.remote .sftp-item.selected', 10, 10) await delay(1000) // Click the download menu item await client.click('.ant-dropdown:not(.ant-dropdown-hidden) .ant-dropdown-menu-item .anticon.anticon-cloud-download') await delay(10000) // Increased delay for folders with files to transfer // Verify fileTransfers array is empty after the operation await verifyFileTransfersComplete(client) // Verify all remote items were transferred to local, including folder structure for (const itemName of remoteVisibleItems) { expect(await verifyFileExists(client, 'local', itemName)).toBe(true) } // Verify the file inside the transferred folder await enterFolder(client, 'local', remoteFolders[0]) await delay(2000) expect(await verifyFileExists(client, 'local', remoteFiles[0])).toBe(true) await navigateToParentFolder(client, 'local') await delay(2000) // Navigate back to parent folders await navigateToParentFolder(client, 'local') await delay(2000) await navigateToParentFolder(client, 'remote') await delay(2000) // Clean up - delete both test folders await deleteItem(client, 'local', mainFolder) await deleteItem(client, 'remote', mainFolder) await delay(2000) }