fix: openapi request import (#5586)

* fix: openapi request import
* fix: js sandbox mode selector doesn't show up while opening new collections in playwright tests

---------

Co-authored-by: Bijin Bruno <bijin@usebruno.com>
This commit is contained in:
Pooja
2025-09-25 13:06:02 +05:30
committed by GitHub
parent 9c9cfdf0b2
commit e1b4043ca5
50 changed files with 253 additions and 88 deletions

View File

@@ -9,6 +9,7 @@ import Dropdown from 'components/Dropdown';
import { toggleCollection } from 'providers/ReduxStore/slices/collections';
import { mountCollection, moveCollectionAndPersist, handleCollectionItemDrop } from 'providers/ReduxStore/slices/collections/actions';
import { useDispatch, useSelector } from 'react-redux';
import { hideHomePage } from 'providers/ReduxStore/slices/app';
import { addTab, makeTabPermanent } from 'providers/ReduxStore/slices/tabs';
import NewRequest from 'components/Sidebar/NewRequest';
import NewFolder from 'components/Sidebar/NewFolder';
@@ -92,6 +93,7 @@ const Collection = ({ collection, searchText }) => {
}
if(!isChevronClick) {
dispatch(hideHomePage()); // @TODO Playwright tests are often stuck on home page, rather than collection settings tab. Revisit for a proper fix.
dispatch(
addTab({
uid: collection.uid,
@@ -209,7 +211,7 @@ const Collection = ({ collection, searchText }) => {
const folderItems = sortByNameThenSequence(filter(collection.items, (i) => isItemAFolder(i)));
return (
<StyledWrapper className="flex flex-col">
<StyledWrapper className="flex flex-col" id={`collection-${collection.name.replace(/\s+/g, '-').toLowerCase()}`}>
{showNewRequestModal && <NewRequest collectionUid={collection.uid} onClose={() => setShowNewRequestModal(false)} />}
{showNewFolderModal && <NewFolder collectionUid={collection.uid} onClose={() => setShowNewFolderModal(false)} />}
{showRenameCollectionModal && (

View File

@@ -38,7 +38,7 @@ const buildEmptyJsonBody = (bodySchema, visited = new Map()) => {
return _jsonBody;
};
const transformOpenapiRequestItem = (request) => {
const transformOpenapiRequestItem = (request, usedNames = new Set()) => {
let _operationObject = request.operationObject;
let operationName = _operationObject.summary || _operationObject.operationId || _operationObject.description;
@@ -46,6 +46,27 @@ const transformOpenapiRequestItem = (request) => {
operationName = `${request.method} ${request.path}`;
}
// Sanitize operation name to prevent Bruno parsing issues
if (operationName) {
// Replace line breaks and normalize whitespace
operationName = operationName.replace(/[\r\n\s]+/g, ' ').trim();
}
if (usedNames.has(operationName)) {
// Make name unique to prevent filename collisions
// Try adding method info first
let uniqueName = `${operationName} (${request.method.toUpperCase()})`;
// If still not unique, add counter
let counter = 1;
while (usedNames.has(uniqueName)) {
uniqueName = `${operationName} (${counter})`;
counter++;
}
operationName = uniqueName;
}
usedNames.add(operationName);
// replace OpenAPI links in path by Bruno variables
let path = request.path.replace(/{([a-zA-Z]+)}/g, `{{${_operationObject.operationId}_$1}}`);
@@ -419,6 +440,8 @@ const openAPIRuntimeExpressionToScript = (expression) => {
};
export const parseOpenApiCollection = (data) => {
const usedNames = new Set();
const brunoCollection = {
name: '',
uid: uuid(),
@@ -512,11 +535,11 @@ export const parseOpenApiCollection = (data) => {
name: group.name
}
},
items: group.requests.map(transformOpenapiRequestItem)
items: group.requests.map(req => transformOpenapiRequestItem(req, usedNames)),
};
});
let ungroupedItems = ungroupedRequests.map(transformOpenapiRequestItem);
let ungroupedItems = ungroupedRequests.map(req => transformOpenapiRequestItem(req, usedNames));
let brunoCollectionItems = brunoFolders.concat(ungroupedItems);
brunoCollection.items = brunoCollectionItems;

View File

@@ -63,7 +63,7 @@ test.describe('Global Environment Import Tests', () => {
await page.getByText('×').click();
// Test GET request with global environment
await page.locator('.collection-item-name').first().click();
await page.locator('#collection-environment-test-collection .collection-item-name').first().click();
await expect(page.locator('#request-url .CodeMirror-line')).toContainText('{{host}}/posts/{{userId}}');
await page.locator('[data-testid="send-arrow-icon"]').click();
await page.locator('[data-testid="response-status-code"]').waitFor({ state: 'visible' });
@@ -74,7 +74,7 @@ test.describe('Global Environment Import Tests', () => {
await expect(responsePane).toContainText('"userId": 1');
// Test POST request
await page.locator('.collection-item-name').nth(1).click();
await page.locator('#collection-environment-test-collection .collection-item-name').nth(1).click();
await expect(page.locator('#request-url .CodeMirror-line')).toContainText('{{host}}/posts');
await page.locator('[data-testid="send-arrow-icon"]').click();
await page.locator('[data-testid="response-status-code"]').waitFor({ state: 'visible' });
@@ -89,7 +89,5 @@ test.describe('Global Environment Import Tests', () => {
.click();
await page.locator('.dropdown-item').filter({ hasText: 'Close' }).click();
await page.getByRole('button', { name: 'Close' }).click();
await page.locator('.bruno-logo').click();
});
});

View File

@@ -88,4 +88,8 @@ test.describe('Multiline Variables - Write Test', () => {
fs.writeFileSync(testBruPath, content);
});
test.afterAll(async ({ page }) => {
await page.locator('.bruno-logo').click();
});
});

View File

@@ -2,10 +2,8 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Import Corrupted Bruno Collection - Should Fail', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Import Bruno collection with invalid JSON structure should fail', async ({ page }) => {
const brunoFile = path.join(testDataDir, 'bruno-malformed.json');
const brunoFile = path.resolve(__dirname, 'fixtures', 'bruno-malformed.json');
await page.getByRole('button', { name: 'Import Collection' }).click();

View File

@@ -2,10 +2,8 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Import Bruno Collection - Missing Required Schema Fields', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Import Bruno collection missing required version field should fail', async ({ page }) => {
const brunoFile = path.join(testDataDir, 'bruno-missing-required-fields.json');
const brunoFile = path.resolve(__dirname, 'fixtures', 'bruno-missing-required-fields.json');
await page.getByRole('button', { name: 'Import Collection' }).click();

View File

@@ -1,17 +1,14 @@
import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Import Bruno Testbench Collection', () => {
const testDataDir = path.join(__dirname, '../test-data');
test.beforeAll(async ({ page }) => {
// Navigate back to homescreen after all tests
await page.locator('.bruno-logo').click();
});
test('Import Bruno Testbench collection successfully', async ({ page }) => {
const brunoFile = path.join(testDataDir, 'bruno-testbench.json');
const brunoFile = path.resolve(__dirname, 'fixtures', 'bruno-testbench.json');
await page.getByRole('button', { name: 'Import Collection' }).click();

View File

@@ -2,10 +2,8 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Invalid File Handling', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Handle invalid file without crashing', async ({ page }) => {
const invalidFile = path.join(testDataDir, 'invalid.txt');
const invalidFile = path.resolve(__dirname, 'fixtures', 'invalid.txt');
await page.getByRole('button', { name: 'Import Collection' }).click();
@@ -19,7 +17,7 @@ test.describe('Invalid File Handling', () => {
// Wait for the loader to disappear
await page.locator('#import-collection-loader').waitFor({ state: 'hidden' });
const hasError = await page.getByText("Failed to parse the file ensure it is valid JSON or YAML").first().isVisible();
const hasError = await page.getByText('Failed to parse the file ensure it is valid JSON or YAML').first().isVisible();
expect(hasError).toBe(true);
// Cleanup: close any open modals

View File

@@ -2,10 +2,8 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Import Insomnia Collection v4', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Import Insomnia Collection v4 successfully', async ({ page }) => {
const insomniaFile = path.join(testDataDir, 'insomnia-v4.json');
const insomniaFile = path.resolve(__dirname, 'fixtures', 'insomnia-v4.json');
await page.getByRole('button', { name: 'Import Collection' }).click();

View File

@@ -2,10 +2,8 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Import Insomnia Collection v5', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Import Insomnia Collection v5 successfully', async ({ page }) => {
const insomniaFile = path.join(testDataDir, 'insomnia-v5.yaml');
const insomniaFile = path.resolve(__dirname, 'fixtures', 'insomnia-v5.yaml');
await page.getByRole('button', { name: 'Import Collection' }).click();

View File

@@ -2,10 +2,8 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Invalid Insomnia Collection - Missing Collection Array', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Handle Insomnia v5 collection missing collection array', async ({ page }) => {
const insomniaFile = path.join(testDataDir, 'insomnia-v5-invalid-missing-collection.yaml');
const insomniaFile = path.resolve(__dirname, 'fixtures', 'insomnia-v5-invalid-missing-collection.yaml');
await page.getByRole('button', { name: 'Import Collection' }).click();

View File

@@ -2,10 +2,8 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Invalid Insomnia Collection - Malformed Structure', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Handle malformed Insomnia collection structure', async ({ page }) => {
const insomniaFile = path.join(testDataDir, 'insomnia-malformed.json');
const insomniaFile = path.resolve(__dirname, 'fixtures', 'insomnia-malformed.json');
await page.getByRole('button', { name: 'Import Collection' }).click();
@@ -20,7 +18,7 @@ test.describe('Invalid Insomnia Collection - Malformed Structure', () => {
await page.locator('#import-collection-loader').waitFor({ state: 'hidden' });
// Check for error message - this should fail during JSON parsing
const hasError = await page.getByText('Failed to parse the file').isVisible();
const hasError = await page.getByText('Failed to parse the file').first().isVisible();
expect(hasError).toBe(true);
// Cleanup: close any open modals

View File

@@ -0,0 +1,50 @@
import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('OpenAPI Duplicate Names Handling', () => {
test('should handle duplicate operation names', async ({ page, createTmpDir }) => {
const openApiFile = path.resolve(__dirname, 'fixtures', 'openapi-duplicate-operation-name.yaml');
// start the import process
await page.getByRole('button', { name: 'Import Collection' }).click();
// wait for the import collection modal to appear
const importModal = page.getByTestId('import-collection-modal');
await importModal.waitFor({ state: 'visible' });
// upload the OpenAPI file with duplicate operation names
await page.setInputFiles('input[type="file"]', openApiFile);
// wait for the file processing to complete
await page.locator('#import-collection-loader').waitFor({ state: 'hidden' });
// verify that the collection location modal appears (OpenAPI files go directly to location modal)
const locationModal = page.getByTestId('import-collection-location-modal');
// verify the collection name is correctly parsed despite duplicate operation names
await expect(locationModal.getByText('Duplicate Test Collection')).toBeVisible();
// select a location
await page.locator('#collection-location').fill(await createTmpDir('duplicate-test'));
await page.getByRole('button', { name: 'Import', exact: true }).click();
// verify the collection was imported successfully
await expect(page.locator('#sidebar-collection-name').getByText('Duplicate Test Collection')).toBeVisible();
// configure the collection settings
await page.locator('#sidebar-collection-name').getByText('Duplicate Test Collection').click();
await page.getByLabel('Safe Mode').check();
await page.getByRole('button', { name: 'Save' }).click();
// verify that all 3 requests were imported correctly despite duplicate operation names
await expect(page.locator('#collection-duplicate-test-collection .collection-item-name')).toHaveCount(3);
// cleanup: close the collection
await page
.locator('.collection-name')
.filter({ has: page.locator('#sidebar-collection-name:has-text("Duplicate Test Collection")') })
.locator('.collection-actions')
.click();
await page.locator('.dropdown-item').getByText('Close').click();
await page.getByRole('button', { name: 'Close' }).click();
});
});

View File

@@ -0,0 +1,44 @@
openapi: 3.0.0
info:
title: Duplicate Test Collection
version: 1.0.0
description: Test collection for handling duplicate operation names
servers:
- url: https://api.example.com
description: Example server
paths:
/users:
get:
summary: 'Get Users'
description: 'Get all users'
operationId: getUsers
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
post:
summary: 'Get Users'
description: 'Create a new user (same summary as GET)'
operationId: createUser
responses:
'201':
description: Created
content:
application/json:
schema:
type: object
/products:
get:
summary: 'Get Users'
description: 'Get all products (same summary as users GET)'
operationId: getProducts
responses:
'200':
description: Success
content:
application/json:
schema:
type: object

View File

@@ -0,0 +1,32 @@
openapi: 3.0.0
info:
title: Newline Test Collection
version: 1.0.0
description: Test collection for operation names with newlines
servers:
- url: https://api.example.com
description: Example server
paths:
/users:
get:
summary: "Get users\nwith newline"
description: 'This operation has newlines in the summary'
operationId: getUsersWithNewline
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
post:
summary: "Create user\n\nwith multiple\n\nnewlines"
description: 'This operation has multiple consecutive newlines'
operationId: createUserWithNewlines
responses:
'201':
description: Created
content:
application/json:
schema:
type: object

View File

@@ -2,10 +2,8 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Import OpenAPI v3 JSON Collection', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Import simple OpenAPI v3 JSON successfully', async ({ page }) => {
const openApiFile = path.join(testDataDir, 'openapi-simple.json');
const openApiFile = path.resolve(__dirname, 'fixtures', 'openapi-simple.json');
await page.getByRole('button', { name: 'Import Collection' }).click();

View File

@@ -2,10 +2,8 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Import OpenAPI v3 YAML Collection', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Import comprehensive OpenAPI v3 YAML successfully', async ({ page }) => {
const openApiFile = path.join(testDataDir, 'openapi-comprehensive.yaml');
const openApiFile = path.resolve(__dirname, 'fixtures', 'openapi-comprehensive.yaml');
await page.getByRole('button', { name: 'Import Collection' }).click();

View File

@@ -2,10 +2,8 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Invalid OpenAPI - Malformed YAML', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Handle malformed OpenAPI YAML structure', async ({ page }) => {
const openApiFile = path.join(testDataDir, 'openapi-malformed.yaml');
const openApiFile = path.resolve(__dirname, 'fixtures', 'openapi-malformed.yaml');
await page.getByRole('button', { name: 'Import Collection' }).click();

View File

@@ -2,10 +2,8 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Invalid OpenAPI - Missing Info Section', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Handle OpenAPI specification missing required info section', async ({ page }) => {
const openApiFile = path.join(testDataDir, 'openapi-missing-info.yaml');
const openApiFile = path.resolve(__dirname, 'fixtures', 'openapi-missing-info.yaml');
await page.getByRole('button', { name: 'Import Collection' }).click();

View File

@@ -0,0 +1,50 @@
import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('OpenAPI Newline Handling', () => {
test('should handle operation names with newlines', async ({ page, createTmpDir }) => {
const openApiFile = path.resolve(__dirname, 'fixtures', 'openapi-newline-in-operation-name.yaml');
// start the import process
await page.getByRole('button', { name: 'Import Collection' }).click();
// wait for the import collection modal to appear
const importModal = page.getByTestId('import-collection-modal');
await importModal.waitFor({ state: 'visible' });
// upload the OpenAPI file with problematic operation names
await page.setInputFiles('input[type="file"]', openApiFile);
// wait for the file processing to complete
await page.locator('#import-collection-loader').waitFor({ state: 'hidden' });
// verify that the collection location modal appears (OpenAPI files go directly to location modal)
const locationModal = page.getByTestId('import-collection-location-modal');
await expect(locationModal.getByText('Newline Test Collection')).toBeVisible();
// select a location
await page.locator('#collection-location').fill(await createTmpDir('newline-test'));
await page.getByRole('button', { name: 'Import', exact: true }).click();
// verify the collection was imported successfully
await expect(page.locator('#sidebar-collection-name').getByText('Newline Test Collection')).toBeVisible();
// configure the collection settings
await page.locator('#sidebar-collection-name').getByText('Newline Test Collection').click();
await page.getByLabel('Safe Mode').check();
await page.getByRole('button', { name: 'Save' }).click();
// verify that all requests were imported correctly despite newlines in operation names
// the parser should clean up the operation names and create valid request names
await expect(page.locator('#collection-newline-test-collection .collection-item-name')).toHaveCount(2);
// cleanup: close the collection
await page
.locator('.collection-name')
.filter({ has: page.locator('#sidebar-collection-name:has-text("Newline Test Collection")') })
.locator('.collection-actions')
.click();
await page.locator('.dropdown-item').getByText('Close').click();
await page.getByRole('button', { name: 'Close' }).click();
});
});

View File

@@ -2,18 +2,16 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Import Postman Collection v2.0', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Import Postman Collection v2.0 successfully', async ({ page }) => {
const postmanFile = path.join(testDataDir, 'postman-v20.json');
const postmanFile = path.resolve(__dirname, 'fixtures', 'postman-v20.json');
await page.getByRole('button', { name: 'Import Collection' }).click();
// Wait for import collection modal to be ready
const importModal = page.getByRole('dialog');
await importModal.waitFor({ state: 'visible' });
await expect(importModal.locator('.bruno-modal-header-title')).toContainText('Import Collection');
await page.setInputFiles('input[type="file"]', postmanFile);
// Wait for the loader to disappear
@@ -22,10 +20,10 @@ test.describe('Import Postman Collection v2.0', () => {
// Verify that the Import Collection modal is displayed (for location selection)
const locationModal = page.getByRole('dialog');
await expect(locationModal.locator('.bruno-modal-header-title')).toContainText('Import Collection');
// Wait for collection to appear in the location modal
await expect(locationModal.getByText('Postman v2.0 Collection')).toBeVisible();
// Cleanup: close any open modals
await page.locator('[data-test-id="modal-close-button"]').click();
});

View File

@@ -2,30 +2,28 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Import Postman Collection v2.1', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Import Postman Collection v2.1 successfully', async ({ page }) => {
const postmanFile = path.join(testDataDir, 'postman-v21.json');
const postmanFile = path.resolve(__dirname, 'fixtures', 'postman-v21.json');
await page.getByRole('button', { name: 'Import Collection' }).click();
// Wait for import collection modal to be ready
const importModal = page.getByRole('dialog');
await importModal.waitFor({ state: 'visible' });
await expect(importModal.locator('.bruno-modal-header-title')).toContainText('Import Collection');
await page.setInputFiles('input[type="file"]', postmanFile);
// Wait for the loader to disappear
await page.locator('#import-collection-loader').waitFor({ state: 'hidden' });
// Verify that the Import Collection modal is displayed (for location selection)
const locationModal = page.getByRole('dialog');
await expect(locationModal.locator('.bruno-modal-header-title')).toContainText('Import Collection');
// Wait for collection to appear in the location modal
await expect(locationModal.getByText('Postman v2.1 Collection')).toBeVisible();
// Cleanup: close any open modals
await page.locator('[data-test-id="modal-close-button"]').click();
});

View File

@@ -2,27 +2,25 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Invalid Postman Collection - Invalid JSON', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Handle invalid JSON syntax', async ({ page }) => {
const postmanFile = path.join(testDataDir, 'postman-invalid-schema.json');
const postmanFile = path.resolve(__dirname, 'fixtures', 'postman-invalid-schema.json');
await page.getByRole('button', { name: 'Import Collection' }).click();
// Wait for import collection modal to be ready
const importModal = page.getByRole('dialog');
await importModal.waitFor({ state: 'visible' });
await expect(importModal.locator('.bruno-modal-header-title')).toContainText('Import Collection');
await page.setInputFiles('input[type="file"]', postmanFile);
// Wait for the loader to disappear
await page.locator('#import-collection-loader').waitFor({ state: 'hidden' });
// Check for error message
const hasError = await page.getByText('Conversion failed').first().isVisible();
expect(hasError).toBe(true);
// Cleanup: close any open modals
await page.locator('[data-test-id="modal-close-button"]').click();
});

View File

@@ -2,10 +2,8 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Invalid Postman Collection - Missing Info', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Handle Postman collection missing required info field', async ({ page }) => {
const postmanFile = path.join(testDataDir, 'postman-invalid-missing-info.json');
const postmanFile = path.resolve(__dirname, 'fixtures', 'postman-invalid-missing-info.json');
await page.getByRole('button', { name: 'Import Collection' }).click();

View File

@@ -2,27 +2,25 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Invalid Postman Collection - Invalid Schema', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Handle Postman collection with invalid schema version', async ({ page }) => {
const postmanFile = path.join(testDataDir, 'postman-invalid-schema.json');
const postmanFile = path.resolve(__dirname, 'fixtures', 'postman-invalid-schema.json');
await page.getByRole('button', { name: 'Import Collection' }).click();
// Wait for import collection modal to be ready
const importModal = page.getByRole('dialog');
await importModal.waitFor({ state: 'visible' });
await expect(importModal.locator('.bruno-modal-header-title')).toContainText('Import Collection');
await page.setInputFiles('input[type="file"]', postmanFile);
// Wait for the loader to disappear
await page.locator('#import-collection-loader').waitFor({ state: 'hidden' });
// Check for error message
const hasError = await page.getByText('Conversion failed').isVisible();
const hasError = await page.getByText('Conversion failed').first().isVisible();
expect(hasError).toBe(true);
// Cleanup: close any open modals
await page.locator('[data-test-id="modal-close-button"]').click();
});

View File

@@ -2,18 +2,16 @@ import { test, expect } from '../../../playwright';
import * as path from 'path';
test.describe('Invalid Postman Collection - Malformed Structure', () => {
const testDataDir = path.join(__dirname, '../test-data');
test('Handle malformed Postman collection structure', async ({ page }) => {
const postmanFile = path.join(testDataDir, 'postman-malformed.json');
const postmanFile = path.resolve(__dirname, 'fixtures', 'postman-malformed.json');
await page.getByRole('button', { name: 'Import Collection' }).click();
// Wait for import collection modal to be ready
const importModal = page.getByRole('dialog');
await importModal.waitFor({ state: 'visible' });
await expect(importModal.locator('.bruno-modal-header-title')).toContainText('Import Collection');
await page.setInputFiles('input[type="file"]', postmanFile);
// Wait for the loader to disappear
@@ -22,7 +20,7 @@ test.describe('Invalid Postman Collection - Malformed Structure', () => {
// Check for error message
const hasError = await page.getByText('Import collection failed').first().isVisible();
expect(hasError).toBe(true);
// Cleanup: close any open modals
await page.locator('[data-test-id="modal-close-button"]').click();
});

View File

@@ -1 +0,0 @@
{ "invalid": json syntax }

View File

View File