Files
bruno/tests/collection/moving-requests/cross-collection-drag-drop-request.spec.ts
Chirag Chandrashekhar ff975c44f2 fix: cross-collection drag and drop tab and format issues (#7584)
Close the open tab when a request is moved to a different collection
via drag and drop, preventing the "Request no longer exists" error.

Add format conversion when dragging requests between collections with
different formats (.bru vs .yml). A new IPC handler parses the source
file and re-serializes it in the target collection's format. Folder
cross-format moves are blocked with a toast error.

Co-authored-by: Chirag Chandrashekhar <cchirag85@gmail.com>
2026-03-26 20:32:29 +05:30

138 lines
6.4 KiB
TypeScript

import { test, expect } from '../../../playwright';
import { closeAllCollections, createCollection, createRequest } from '../../utils/page';
test.describe('Cross-Collection Drag and Drop', () => {
test.afterEach(async ({ page }) => {
// cleanup: close all collections
await closeAllCollections(page);
});
test('Verify request drag and drop', async ({ page, createTmpDir }) => {
const requestName = 'drag-drop-request';
// Create first collection - open with sandbox mode
await createCollection(page, 'source-collection', await createTmpDir('source-collection'));
// Create a request in the first collection using the dialog/modal flow
await createRequest(page, requestName, 'source-collection', { url: 'https://echo.usebruno.com' });
// Create second collection - open with sandbox mode
await createCollection(page, 'target-collection', await createTmpDir('target-collection'));
await expect(page.locator('#sidebar-collection-name').filter({ hasText: 'source-collection' })).toBeVisible();
await expect(page.locator('#sidebar-collection-name').filter({ hasText: 'target-collection' })).toBeVisible();
// Locate the request in source collection
const sourceCollectionContainer = page
.locator('.collection-name')
.filter({ hasText: 'source-collection' })
.locator('..');
const sourceRequest = sourceCollectionContainer.locator('.collection-item-name').filter({ hasText: requestName }).first();
await expect(sourceRequest).toBeVisible();
// Locate the target collection area (the collection name element)
const targetCollection = page.locator('.collection-name').filter({ hasText: 'target-collection' });
await expect(targetCollection).toBeVisible();
// Perform drag and drop operation
await sourceRequest.dragTo(targetCollection);
// Verify the request has been moved to the target collection
// Check that the request now appears under target collection
const targetCollectionContainer = page
.locator('.collection-name')
.filter({ hasText: 'target-collection' })
.locator('..');
await expect(targetCollectionContainer.locator('.collection-item-name').filter({ hasText: requestName })).toBeVisible();
// Verify the request is no longer in the source collection
await page.locator('#sidebar-collection-name').filter({ hasText: 'source-collection' }).click();
await expect(sourceCollectionContainer.locator('.collection-item-name').filter({ hasText: requestName })).toHaveCount(0);
});
test('Expected to show error toast message, when duplicate request found in drop location', async ({
page,
createTmpDir
}) => {
const requestName = 'duplicate-request';
// Create first collection (source-collection)
await createCollection(page, 'source-collection', await createTmpDir('source-collection'));
// Create a request in the first collection using the dialog/modal flow
await createRequest(page, requestName, 'source-collection', { url: 'https://echo.usebruno.com' });
// Create second collection (target-collection)
await createCollection(page, 'target-collection', await createTmpDir('target-collection'));
// Create a request with the same name in the target collection using the dialog/modal flow
await createRequest(page, requestName, 'target-collection', { url: 'https://echo.usebruno.com' });
// Go back to source collection to drag the request
await page.locator('#sidebar-collection-name').filter({ hasText: 'source-collection' }).click();
const sourceCollectionContainer = page
.locator('.collection-name')
.filter({ hasText: 'source-collection' })
.locator('..');
const targetCollectionContainer = page
.locator('.collection-name')
.filter({ hasText: 'target-collection' })
.locator('..');
const sourceRequest = sourceCollectionContainer.locator('.collection-item-name').filter({ hasText: requestName }).first();
await expect(sourceRequest).toBeVisible();
// Locate the target collection area
const targetCollection = page.locator('.collection-name').filter({ hasText: 'target-collection' });
await expect(targetCollection).toBeVisible();
// Perform drag and drop operation to target-collection
await sourceRequest.dragTo(targetCollection);
// check for error toast notification
await expect(page.getByText(/Error: Cannot copy.*already exists/i)).toBeVisible();
// source and target collection request should remain unchanged
await expect(sourceCollectionContainer.locator('.collection-item-name').filter({ hasText: requestName }).first()).toBeVisible();
await page.locator('#sidebar-collection-name').filter({ hasText: 'target-collection' }).click();
await expect(targetCollectionContainer.locator('.collection-item-name').filter({ hasText: requestName }).first()).toBeVisible();
});
test('Tab should be closed after cross-collection drag and drop', async ({ page, createTmpDir }) => {
const requestName = 'tab-close-request';
// Create source and target collections
await createCollection(page, 'source-collection', await createTmpDir('source-collection'));
await createRequest(page, requestName, 'source-collection', { url: 'https://echo.usebruno.com' });
await createCollection(page, 'target-collection', await createTmpDir('target-collection'));
// Open the request to create a tab
const sourceCollectionContainer = page
.locator('.collection-name')
.filter({ hasText: 'source-collection' })
.locator('..');
const sourceRequest = sourceCollectionContainer.locator('.collection-item-name').filter({ hasText: requestName }).first();
await sourceRequest.click();
// Verify the tab is open
const requestTab = page.locator('.request-tab .tab-label').filter({ hasText: requestName });
await expect(requestTab).toBeVisible();
// Drag the request to target collection
const targetCollection = page.locator('.collection-name').filter({ hasText: 'target-collection' });
await sourceRequest.dragTo(targetCollection);
// Verify the tab is closed after cross-collection move
await expect(requestTab).not.toBeVisible();
// Verify the request appears in the target collection
const targetCollectionContainer = page
.locator('.collection-name')
.filter({ hasText: 'target-collection' })
.locator('..');
await expect(targetCollectionContainer.locator('.collection-item-name').filter({ hasText: requestName })).toBeVisible();
});
});