mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-28 15:14:06 +00:00
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:
@@ -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 && (
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -88,4 +88,8 @@ test.describe('Multiline Variables - Write Test', () => {
|
||||
|
||||
fs.writeFileSync(testBruPath, content);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ page }) => {
|
||||
await page.locator('.bruno-logo').click();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
50
tests/import/openapi/duplicate-operation-names-fix.spec.ts
Normal file
50
tests/import/openapi/duplicate-operation-names-fix.spec.ts
Normal 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();
|
||||
});
|
||||
});
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
{ "invalid": json syntax }
|
||||
0
tests/utils/pageUtils/index.js
Normal file
0
tests/utils/pageUtils/index.js
Normal file
0
tests/utils/pageUtils/navigation.js
Normal file
0
tests/utils/pageUtils/navigation.js
Normal file
Reference in New Issue
Block a user