diff --git a/e2e-tests/import-tests/bruno/001-import-bruno-testbench.spec.ts b/e2e-tests/import-tests/bruno/001-import-bruno-testbench.spec.ts
new file mode 100644
index 000000000..cb436c1dd
--- /dev/null
+++ b/e2e-tests/import-tests/bruno/001-import-bruno-testbench.spec.ts
@@ -0,0 +1,38 @@
+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');
+
+ 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"]', brunoFile);
+
+ // 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('bruno-testbench')).toBeVisible();
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/bruno/002-import-bruno-corrupted-fails.spec.ts b/e2e-tests/import-tests/bruno/002-import-bruno-corrupted-fails.spec.ts
new file mode 100644
index 000000000..9d6d10bf4
--- /dev/null
+++ b/e2e-tests/import-tests/bruno/002-import-bruno-corrupted-fails.spec.ts
@@ -0,0 +1,31 @@
+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');
+
+ 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"]', brunoFile);
+
+ // Wait for the loader to disappear
+ await page.locator('#import-collection-loader').waitFor({ state: 'hidden' });
+
+ // Check for JSON parsing error
+ const hasImportError = await page.getByText('Failed to parse the file – ensure it is valid JSON or YAML').first().isVisible();
+
+ // Either parsing error or import error should be shown
+ expect(hasImportError).toBe(true);
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/bruno/003-import-bruno-missing-required-schema.spec.ts b/e2e-tests/import-tests/bruno/003-import-bruno-missing-required-schema.spec.ts
new file mode 100644
index 000000000..0f76559f6
--- /dev/null
+++ b/e2e-tests/import-tests/bruno/003-import-bruno-missing-required-schema.spec.ts
@@ -0,0 +1,30 @@
+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');
+
+ 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"]', brunoFile);
+
+ // Wait for the loader to disappear
+ await page.locator('#import-collection-loader').waitFor({ state: 'hidden' });
+
+ // Check for schema validation error messages
+ const hasImportError = await page.getByText('Import collection failed').first().isVisible();
+
+ expect(hasImportError).toBe(true);
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/file-types/001-file-input-acceptance.spec.ts b/e2e-tests/import-tests/file-types/001-file-input-acceptance.spec.ts
new file mode 100644
index 000000000..903f00d68
--- /dev/null
+++ b/e2e-tests/import-tests/file-types/001-file-input-acceptance.spec.ts
@@ -0,0 +1,20 @@
+import { test, expect } from '../../../playwright';
+
+test.describe('File Input Acceptance', () => {
+ test('File input accepts expected file types', async ({ page }) => {
+ await page.getByRole('button', { name: 'Import Collection' }).click();
+
+ // Check that file input exists (even if hidden)
+ const fileInput = page.locator('input[type="file"]');
+ await expect(fileInput).toBeAttached();
+
+ // Verify it accepts the expected file types
+ const acceptValue = await fileInput.getAttribute('accept');
+ expect(acceptValue).toContain('.json');
+ expect(acceptValue).toContain('.yaml');
+ expect(acceptValue).toContain('.yml');
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/file-types/002-invalid-file-handling.spec.ts b/e2e-tests/import-tests/file-types/002-invalid-file-handling.spec.ts
new file mode 100644
index 000000000..8a655d65e
--- /dev/null
+++ b/e2e-tests/import-tests/file-types/002-invalid-file-handling.spec.ts
@@ -0,0 +1,28 @@
+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');
+
+ 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"]', invalidFile);
+
+ // 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").isVisible();
+ expect(hasError).toBe(true);
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/insomnia/001-import-insomnia-v4.spec.ts b/e2e-tests/import-tests/insomnia/001-import-insomnia-v4.spec.ts
new file mode 100644
index 000000000..1afeed306
--- /dev/null
+++ b/e2e-tests/import-tests/insomnia/001-import-insomnia-v4.spec.ts
@@ -0,0 +1,32 @@
+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');
+
+ 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"]', insomniaFile);
+
+ // 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('Test API Collection v4')).toBeVisible();
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/insomnia/002-import-insomnia-v5.spec.ts b/e2e-tests/import-tests/insomnia/002-import-insomnia-v5.spec.ts
new file mode 100644
index 000000000..b246a2454
--- /dev/null
+++ b/e2e-tests/import-tests/insomnia/002-import-insomnia-v5.spec.ts
@@ -0,0 +1,32 @@
+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');
+
+ 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"]', insomniaFile);
+
+ // 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('Test API Collection v5')).toBeVisible();
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/insomnia/003-invalid-missing-collection.spec.ts b/e2e-tests/import-tests/insomnia/003-invalid-missing-collection.spec.ts
new file mode 100644
index 000000000..0237a8240
--- /dev/null
+++ b/e2e-tests/import-tests/insomnia/003-invalid-missing-collection.spec.ts
@@ -0,0 +1,29 @@
+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');
+
+ 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"]', insomniaFile);
+
+ // Wait for the loader to disappear
+ await page.locator('#import-collection-loader').waitFor({ state: 'hidden' });
+
+ // 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();
+ });
+});
diff --git a/e2e-tests/import-tests/insomnia/004-malformed-structure.spec.ts b/e2e-tests/import-tests/insomnia/004-malformed-structure.spec.ts
new file mode 100644
index 000000000..644bd35fe
--- /dev/null
+++ b/e2e-tests/import-tests/insomnia/004-malformed-structure.spec.ts
@@ -0,0 +1,29 @@
+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');
+
+ 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"]', insomniaFile);
+
+ // Wait for the loader to disappear
+ 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();
+ expect(hasError).toBe(true);
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/openapi/001-import-openapi-yaml.spec.ts b/e2e-tests/import-tests/openapi/001-import-openapi-yaml.spec.ts
new file mode 100644
index 000000000..0d705f1b1
--- /dev/null
+++ b/e2e-tests/import-tests/openapi/001-import-openapi-yaml.spec.ts
@@ -0,0 +1,32 @@
+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');
+
+ 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"]', openApiFile);
+
+ // 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('Comprehensive API Test Collection')).toBeVisible();
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/openapi/002-import-openapi-json.spec.ts b/e2e-tests/import-tests/openapi/002-import-openapi-json.spec.ts
new file mode 100644
index 000000000..847d4c49b
--- /dev/null
+++ b/e2e-tests/import-tests/openapi/002-import-openapi-json.spec.ts
@@ -0,0 +1,32 @@
+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');
+
+ 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"]', openApiFile);
+
+ // 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('Simple Test API')).toBeVisible();
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/openapi/003-missing-info.spec.ts b/e2e-tests/import-tests/openapi/003-missing-info.spec.ts
new file mode 100644
index 000000000..aa8298dcd
--- /dev/null
+++ b/e2e-tests/import-tests/openapi/003-missing-info.spec.ts
@@ -0,0 +1,31 @@
+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');
+
+ 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"]', openApiFile);
+
+ // Wait for the loader to disappear
+ await page.locator('#import-collection-loader').waitFor({ state: 'hidden' });
+
+ // The OpenAPI parser might handle missing info gracefully with defaults
+ const hasError = await page.getByText('Import collection failed').first().isVisible();
+
+ // Either should show an error or create an "Untitled Collection"
+ expect(hasError).toBe(true);
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/openapi/004-malformed-yaml.spec.ts b/e2e-tests/import-tests/openapi/004-malformed-yaml.spec.ts
new file mode 100644
index 000000000..2f2479e9a
--- /dev/null
+++ b/e2e-tests/import-tests/openapi/004-malformed-yaml.spec.ts
@@ -0,0 +1,32 @@
+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');
+
+ 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"]', openApiFile);
+
+ // Wait for the loader to disappear
+ await page.locator('#import-collection-loader').waitFor({ state: 'hidden' });
+
+ // Check for error message - this should fail during YAML parsing
+ const hasParseError = await page.getByText('Failed to parse the file').isVisible();
+ const hasImportError = await page.getByText('Import collection failed').isVisible();
+
+ // Either parsing error or import error should be shown
+ expect(hasParseError || hasImportError).toBe(true);
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/postman/001-import-postman-v21.spec.ts b/e2e-tests/import-tests/postman/001-import-postman-v21.spec.ts
new file mode 100644
index 000000000..08a7029df
--- /dev/null
+++ b/e2e-tests/import-tests/postman/001-import-postman-v21.spec.ts
@@ -0,0 +1,32 @@
+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');
+
+ 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();
+ });
+});
diff --git a/e2e-tests/import-tests/postman/002-import-postman-v20.spec.ts b/e2e-tests/import-tests/postman/002-import-postman-v20.spec.ts
new file mode 100644
index 000000000..b6866fa3e
--- /dev/null
+++ b/e2e-tests/import-tests/postman/002-import-postman-v20.spec.ts
@@ -0,0 +1,32 @@
+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');
+
+ 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.0 Collection')).toBeVisible();
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/postman/003-invalid-missing-info.spec.ts b/e2e-tests/import-tests/postman/003-invalid-missing-info.spec.ts
new file mode 100644
index 000000000..c2ab608c8
--- /dev/null
+++ b/e2e-tests/import-tests/postman/003-invalid-missing-info.spec.ts
@@ -0,0 +1,29 @@
+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');
+
+ 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('Import collection failed').isVisible();
+ expect(hasError).toBe(true);
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/postman/004-invalid-schema.spec.ts b/e2e-tests/import-tests/postman/004-invalid-schema.spec.ts
new file mode 100644
index 000000000..34ddfa07b
--- /dev/null
+++ b/e2e-tests/import-tests/postman/004-invalid-schema.spec.ts
@@ -0,0 +1,29 @@
+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');
+
+ 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();
+ expect(hasError).toBe(true);
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/postman/005-malformed-structure.spec.ts b/e2e-tests/import-tests/postman/005-malformed-structure.spec.ts
new file mode 100644
index 000000000..2c39faf0d
--- /dev/null
+++ b/e2e-tests/import-tests/postman/005-malformed-structure.spec.ts
@@ -0,0 +1,29 @@
+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');
+
+ 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('Import collection failed').first().isVisible();
+ expect(hasError).toBe(true);
+
+ // Cleanup: close any open modals
+ await page.locator('[data-test-id="modal-close-button"]').click();
+ });
+});
diff --git a/e2e-tests/import-tests/postman/006-invalid-json.spec.ts b/e2e-tests/import-tests/postman/006-invalid-json.spec.ts
new file mode 100644
index 000000000..ef1e881ca
--- /dev/null
+++ b/e2e-tests/import-tests/postman/006-invalid-json.spec.ts
@@ -0,0 +1,29 @@
+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');
+
+ 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();
+ });
+});
diff --git a/e2e-tests/import-tests/test-data/bruno-invalid-corrupted.json b/e2e-tests/import-tests/test-data/bruno-invalid-corrupted.json
new file mode 100644
index 000000000..5f3348861
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/bruno-invalid-corrupted.json
@@ -0,0 +1,66 @@
+{
+ "version": "1",
+ "uid": "corrupted_bruno_collection",
+ "name": "Corrupted Bruno Collection",
+ "items": [
+ {
+ "uid": "corrupted_request",
+ "type": "invalid-request-type",
+ "name": "Invalid Request Type",
+ "seq": 1,
+ "request": {
+ "url": "https://example.com/api",
+ "method": "INVALID_METHOD",
+ "headers": "this should be an array not a string",
+ "params": null,
+ "body": {
+ "mode": "invalid-mode",
+ "invalidField": "this field doesn't exist in schema"
+ },
+ "auth": {
+ "mode": "unknown-auth-type",
+ "invalidAuth": {
+ "badField": "invalid value"
+ }
+ },
+ "script": "this should be an object not a string",
+ "vars": "this should be an object not a string",
+ "assertions": "this should be an array not a string",
+ "tests": 12345,
+ "docs": true
+ }
+ },
+ {
+ "uid": "missing_required_fields",
+ "type": "http-request",
+ "name": "Missing Required Fields",
+ "seq": 2
+ }
+ ],
+ "environments": [
+ {
+ "uid": "invalid_env",
+ "name": "Invalid Environment",
+ "variables": "this should be an array not a string"
+ }
+ ],
+ "activeEnvironmentUid": "non_existent_environment_id",
+ "root": {
+ "request": {
+ "headers": "invalid headers format",
+ "auth": {
+ "mode": "completely-unknown-auth"
+ },
+ "script": 42,
+ "vars": false,
+ "tests": null
+ }
+ },
+ "invalidTopLevelField": "this field doesn't belong here",
+ "brunoConfig": {
+ "version": "999",
+ "name": "Invalid Config",
+ "type": "invalid-type",
+ "invalidConfigField": true
+ }
+}
diff --git a/e2e-tests/import-tests/test-data/bruno-malformed.json b/e2e-tests/import-tests/test-data/bruno-malformed.json
new file mode 100644
index 000000000..3ae3cb16b
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/bruno-malformed.json
@@ -0,0 +1,43 @@
+{
+ "version": "1",
+ "uid": "malformed_bruno_collection",
+ "name": "Malformed Bruno Collection",
+ "items": [
+ {
+ "uid": "malformed_request",
+ "type": "http-request",
+ "name": "Malformed Request",
+ "seq": 1,
+ "request": {
+ "url": "https://example.com/api",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none"
+ },
+ "auth": {
+ "mode": "none"
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "",
+ "docs": ""
+ }
+ }
+ ],
+ "environments": [],
+ "activeEnvironmentUid": null,
+ "root": {
+ "request": {
+ "headers": [],
+ "auth": {
+ "mode": "none"
+ },
+ "script": {},
+ "vars": {},
+ "tests": ""
+ }
+ }
+ // Missing comma and closing bracket - this makes it malformed JSON
\ No newline at end of file
diff --git a/e2e-tests/import-tests/test-data/bruno-missing-required-fields.json b/e2e-tests/import-tests/test-data/bruno-missing-required-fields.json
new file mode 100644
index 000000000..6ecf37a09
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/bruno-missing-required-fields.json
@@ -0,0 +1,2939 @@
+{
+ "name": "bruno-testbench",
+ "items": [
+ {
+ "type": "http",
+ "name": "aaaaa",
+ "seq": 2,
+ "request": {
+ "url": "https://reqres.in/api/users/1",
+ "method": "PUT",
+ "headers": [
+ {
+ "name": "Accept",
+ "value": "application/json",
+ "enabled": true
+ },
+ {
+ "name": "Cookie",
+ "value": "session-id=abc123",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "console.log(req.getCookie());"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "folder",
+ "name": "auth",
+ "root": {
+ "meta": {
+ "name": "auth"
+ }
+ },
+ "items": [
+ {
+ "type": "folder",
+ "name": "basic",
+ "root": {
+ "meta": {
+ "name": "basic"
+ }
+ },
+ "items": [
+ {
+ "type": "folder",
+ "name": "via auth",
+ "root": {
+ "meta": {
+ "name": "via auth"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "Basic Auth 200",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/auth/basic/protected",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "200",
+ "enabled": true,
+ "uid": "YLpcflD1RLvdkSSvAYimh"
+ },
+ {
+ "name": "res.body.message",
+ "value": "Authentication successful",
+ "enabled": true,
+ "uid": "oqRPDS5d7CLIqBQ5OCEko"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "basic",
+ "basic": {
+ "username": "bruno",
+ "password": "{{basic_auth_password}}"
+ }
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "Basic Auth 400",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/auth/basic/protected",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "401",
+ "enabled": true,
+ "uid": "WsBvjaJuowT05ri9A8Qc5"
+ },
+ {
+ "name": "res.body",
+ "value": "Unauthorized",
+ "enabled": true,
+ "uid": "VW1wyd6hu74Yyfzhn0RuQ"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "via script",
+ "root": {
+ "meta": {
+ "name": "via script"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "Basic Auth 200",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/auth/basic/protected",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const username = \"bruno\";\nconst password = \"della\";\n\nconst authString = `${username}:${password}`;\nconst encodedAuthString = require('btoa')(authString);\n\nreq.setHeader(\"Authorization\", `Basic ${encodedAuthString}`);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "5p6vUUMuLxbA7KnYnXrkT"
+ },
+ {
+ "name": "res.body.message",
+ "value": "Authentication successful",
+ "enabled": true,
+ "uid": "Tk43KT6Hyf3h8Jfeyk2XD"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "Basic Auth 401",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/auth/basic/protected",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const username = \"bruno\";\nconst password = \"invalid\";\n\nconst authString = `${username}:${password}`;\nconst encodedAuthString = require('btoa')(authString);\n\nreq.setHeader(\"Authorization\", `Basic ${encodedAuthString}`);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "401",
+ "enabled": true,
+ "uid": "dLnctBQFSISlaooCYzp5C"
+ },
+ {
+ "name": "res.body",
+ "value": "Unauthorized",
+ "enabled": true,
+ "uid": "iWPqym01ksxrDV1gfuhWv"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "bearer",
+ "root": {
+ "meta": {
+ "name": "bearer"
+ }
+ },
+ "items": [
+ {
+ "type": "folder",
+ "name": "via auth",
+ "root": {
+ "meta": {
+ "name": "via auth"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "Bearer Auth 200",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/auth/bearer/protected",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "res": "bru.setEnvVar(\"foo\", \"bar\");"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "200",
+ "enabled": true,
+ "uid": "F01gjRjDDQefuLn2Vcyed"
+ },
+ {
+ "name": "res.body.message",
+ "value": "Authentication successful",
+ "enabled": true,
+ "uid": "Hmw3BpVyz9tDBEcdA88O0"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "bearer",
+ "bearer": {
+ "token": "{{bearer_auth_token}}"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "via headers",
+ "root": {
+ "meta": {
+ "name": "via headers"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "Bearer Auth 200",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/auth/bearer/protected",
+ "method": "GET",
+ "headers": [
+ {
+ "name": "Authorization",
+ "value": "Bearer your_secret_token",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "res": "bru.setEnvVar(\"foo\", \"bar\");"
+ },
+ "vars": {
+ "req": [
+ {
+ "name": "a-c",
+ "value": "foo",
+ "enabled": true,
+ "local": false
+ }
+ ]
+ },
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "200",
+ "enabled": true,
+ "uid": "VDQ7l9zN9WfS3lEGsJ0aw"
+ },
+ {
+ "name": "res.body.message",
+ "value": "Authentication successful",
+ "enabled": true,
+ "uid": "0n8UMinkhzOuRJCCABVz9"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "cookie",
+ "root": {
+ "meta": {
+ "name": "cookie"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "Check",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/auth/cookie/protected",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "Login",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/auth/cookie/login",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "inherit auth",
+ "root": {
+ "meta": {
+ "name": "inherit auth"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "inherit Bearer Auth 200",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/auth/bearer/protected",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "res": "bru.setEnvVar(\"foo\", \"bar\");"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "200",
+ "enabled": true,
+ "uid": "G6vVLMAqfvpa4aBtQ3WSG"
+ },
+ {
+ "name": "res.body.message",
+ "value": "Authentication successful",
+ "enabled": true,
+ "uid": "QItzfaevVVrycFox5jTlS"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "inherit"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "echo",
+ "root": {
+ "meta": {
+ "name": "echo"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "echo bigint",
+ "seq": 6,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [
+ {
+ "name": "foo",
+ "value": "bar",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": 990531470713421825,\n \"decimal\": 1.0,\n \"decimal2\": 1.00,\n \"decimal3\": 1.00200,\n \"decimal4\": 0.00\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "lCoGpuLOpVmXPfGzJqbTB"
+ }
+ ],
+ "tests": "// todo: add tests once lossless json echo server is ready",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo bom json",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/echo/bom-json-test",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo form-url-encoded",
+ "seq": 9,
+ "request": {
+ "url": "{{echo-host}}",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "formUrlEncoded",
+ "formUrlEncoded": [
+ {
+ "name": "form-data-key",
+ "value": "{{form-data-key}}",
+ "enabled": true
+ },
+ {
+ "name": "form-data-stringified-object",
+ "value": "{{form-data-stringified-object}}",
+ "enabled": true
+ }
+ ],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "let obj = JSON.stringify({foo:123});\nbru.setVar('form-data-key', 'form-data-value');\nbru.setVar('form-data-stringified-object', obj);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.body",
+ "value": "eq form-data-key=form-data-value&form-data-stringified-object=%7B%22foo%22%3A123%7D",
+ "enabled": true,
+ "uid": "V0MSBvq2iFun9gIWfgqtQ"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo json",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [
+ {
+ "name": "foo",
+ "value": "bar",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "bru.setVar(\"foo\", \"foo-world-2\");"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "FFVx1w4MstKeQfQR66Xy8"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"hello\": \"bruno\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo multipart via scripting",
+ "seq": 10,
+ "request": {
+ "url": "{{echo-host}}",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "multipartForm",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const FormData = require(\"form-data\");\nconst form = new FormData();\nform.append('form-data-key', 'form-data-value');\nreq.setBody(form);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.body",
+ "value": "contains form-data-value",
+ "enabled": true,
+ "uid": "USCnLx51IlWz6HrLxlR1r"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo multipart",
+ "seq": 8,
+ "request": {
+ "url": "{{echo-host}}",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "multipartForm",
+ "formUrlEncoded": [],
+ "multipartForm": [
+ {
+ "type": "text",
+ "name": "form-data-key",
+ "value": "{{form-data-key}}",
+ "enabled": true
+ },
+ {
+ "type": "text",
+ "name": "form-data-stringified-object",
+ "value": "{{form-data-stringified-object}}",
+ "enabled": true
+ },
+ {
+ "type": "file",
+ "name": "file",
+ "value": [
+ "bruno.png"
+ ],
+ "enabled": true
+ }
+ ],
+ "file": []
+ },
+ "script": {
+ "req": "let obj = JSON.stringify({foo:123});\nbru.setVar('form-data-key', 'form-data-value');\nbru.setVar('form-data-stringified-object', obj);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.body",
+ "value": "contains form-data-value",
+ "enabled": true,
+ "uid": "L5wrs8CJKD7skDazamdTZ"
+ },
+ {
+ "name": "res.body",
+ "value": "contains {\"foo\":123}",
+ "enabled": true,
+ "uid": "2rPiaUFbPuWPq0ew6dqVd"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo plaintext",
+ "seq": 3,
+ "request": {
+ "url": "{{host}}/api/echo/text",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "text",
+ "text": "hello",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "cW2RamEi0zqLmn84SjUoh"
+ }
+ ],
+ "tests": "test(\"should return plain text\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql(\"hello\");\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo xml parsed-self closing tags-",
+ "seq": 6,
+ "request": {
+ "url": "{{host}}/api/echo/xml-parsed",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "xml",
+ "xml": "\n bruno\n \n",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "lIbw7OdlPxbNUKdShGNvi"
+ }
+ ],
+ "tests": "test(\"should return parsed xml\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"hello\": {\n \"world\": [\n \"bruno\",\n \"\"\n ]\n }\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo xml parsed",
+ "seq": 4,
+ "request": {
+ "url": "{{host}}/api/echo/xml-parsed",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "xml",
+ "xml": "\n bruno\n",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "5yr5fbjrAre0Cp0C3PY4c"
+ }
+ ],
+ "tests": "test(\"should return parsed xml\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"hello\": {\n \"world\": [\"bruno\"]\n }\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo xml raw",
+ "seq": 5,
+ "request": {
+ "url": "{{host}}/api/echo/xml-raw",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "xml",
+ "xml": "bruno",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "graphql",
+ "root": {
+ "meta": {
+ "name": "graphql"
+ }
+ },
+ "items": [
+ {
+ "type": "graphql",
+ "name": "spacex",
+ "seq": 1,
+ "request": {
+ "url": "https://spacex-production.up.railway.app/",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\n company {\n ceo\n }\n}\n"
+ },
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "P99wa88sX4L4Zat94bHzz"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "lib",
+ "root": {
+ "meta": {
+ "name": "lib"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "ping",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "folder",
+ "name": "preview",
+ "root": {
+ "meta": {
+ "name": "preview"
+ }
+ },
+ "items": [
+ {
+ "type": "folder",
+ "name": "html",
+ "root": {
+ "meta": {
+ "name": "html"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "bruno",
+ "seq": 1,
+ "request": {
+ "url": "https://www.github.com",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "console.log(req.getCookie());\n\nconsole.log(req.getHeaders());"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "2bpXrsR3q5MBpkXbO1vfS"
+ }
+ ],
+ "tests": "test(\"should return parsed xml\", function() {\n const headers = res.getHeaders();\n expect(headers['content-type']).to.eql(\"text/html; charset=utf-8\");\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "image",
+ "root": {
+ "meta": {
+ "name": "image"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "bruno",
+ "seq": 1,
+ "request": {
+ "url": "https://www.usebruno.com/images/landing-2.png",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"should return parsed xml\", function() {\n const headers = res.getHeaders();\n expect(headers['content-type']).to.eql(\"image/png\");\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "redirects",
+ "root": {
+ "meta": {
+ "name": "redirects"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "Disable Redirect",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/redirect-to-ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "req.setMaxRedirects(0);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "302",
+ "enabled": true,
+ "uid": "Bs0jGEFFNAyyRBx6DILEN"
+ }
+ ],
+ "tests": "test(\"should disable redirect to ping\", function() {\n const data = res.getBody();\n expect(data).to.equal('Found. Redirecting to /ping');\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "Test Redirect",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/redirect-to-ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "200",
+ "enabled": true,
+ "uid": "nNRcxeANwM6VBEXR1qoM0"
+ },
+ {
+ "name": "res.body",
+ "value": "pong",
+ "enabled": true,
+ "uid": "3Y5SHtNsQHK0glgikD1IU"
+ }
+ ],
+ "tests": "test(\"should redirect to ping\", function() {\n const data = res.getBody();\n expect(data).to.equal('pong');\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "scripting",
+ "root": {
+ "meta": {
+ "name": "scripting"
+ }
+ },
+ "items": [
+ {
+ "type": "folder",
+ "name": "api",
+ "root": {
+ "meta": {
+ "name": "api"
+ }
+ },
+ "items": [
+ {
+ "type": "folder",
+ "name": "bru",
+ "root": {
+ "meta": {
+ "name": "bru"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "getEnvName",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const envName = bru.getEnvName();\nbru.setVar(\"testEnvName\", envName);"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"should get env name in scripts\", function() {\n const testEnvName = bru.getVar(\"testEnvName\");\n expect(testEnvName).to.equal(\"Prod\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getEnvVar",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"should get env var in scripts\", function() {\n const host = bru.getEnvVar(\"host\")\n expect(host).to.equal(\"https://testbench-sanity.usebruno.com\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getProcessEnv",
+ "seq": 6,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"bru.getProcessEnv()\", function() {\n const v = bru.getProcessEnv(\"PROC_ENV_VAR\");\n expect(v).to.equal(\"woof\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getVar",
+ "seq": 5,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"should get var in scripts\", function() {\n const testSetVar = bru.getVar(\"testSetVar\");\n expect(testSetVar).to.equal(\"bruno-test-87267\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setEnvVar",
+ "seq": 3,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "res": "bru.setEnvVar(\"testSetEnvVar\", \"bruno-29653\")"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"should set env var in scripts\", function() {\n const testSetEnvVar = bru.getEnvVar(\"testSetEnvVar\")\n expect(testSetEnvVar).to.equal(\"bruno-29653\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setVar",
+ "seq": 4,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "res": "bru.setVar(\"testSetVar\", \"bruno-test-87267\")"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"should get var in scripts\", function() {\n const testSetVar = bru.getVar(\"testSetVar\");\n expect(testSetVar).to.equal(\"bruno-test-87267\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "req",
+ "root": {
+ "meta": {
+ "name": "req"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "getBody",
+ "seq": 9,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "7VvXmRWwUdGYbvrQaeDMD"
+ }
+ ],
+ "tests": "test(\"req.getBody()\", function() {\n const data = res.getBody();\n expect(data).to.eql({\n \"hello\": \"bruno\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getHeader",
+ "seq": 5,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [
+ {
+ "name": "bruno",
+ "value": "is-awesome",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "HssG2g6gUaWaBFFanCozP"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "50NSDIeXgRr0TcXEdquci"
+ }
+ ],
+ "tests": "test(\"req.getHeader(name)\", function() {\n const h = req.getHeader('bruno');\n expect(h).to.equal(\"is-awesome\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getHeaders",
+ "seq": 7,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [
+ {
+ "name": "bruno",
+ "value": "is-awesome",
+ "enabled": true
+ },
+ {
+ "name": "della",
+ "value": "is-beautiful",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "9NDZWAvBS23WJAZsKl9SS"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "f9ULUob9jYiABYuEzfmgC"
+ }
+ ],
+ "tests": "test(\"req.getHeaders()\", function() {\n const h = req.getHeaders();\n expect(h.bruno).to.equal(\"is-awesome\");\n expect(h.della).to.equal(\"is-beautiful\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getMethod",
+ "seq": 3,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "EpNcKUgCYzdg8KrOLqaCX"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "qFqcLtNYbZ9nqhiwvS3Qk"
+ }
+ ],
+ "tests": "test(\"req.getMethod()()\", function() {\n const method = req.getMethod();\n expect(method).to.equal(\"GET\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getUrl",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "VaiDs2JU1NM8prTc59GdX"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "4vC9zp5XBajbYKDYM4oFN"
+ }
+ ],
+ "tests": "test(\"req.getUrl()\", function() {\n const url = req.getUrl();\n expect(url).to.equal(\"https://testbench-sanity.usebruno.com/ping\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setBody",
+ "seq": 10,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "req.setBody({\n \"bruno\": \"is awesome\"\n});"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "EGlBavIEZ2j0s2aczQxAP"
+ }
+ ],
+ "tests": "test(\"req.setBody()\", function() {\n const data = res.getBody();\n expect(data).to.eql({\n \"bruno\": \"is awesome\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setHeader",
+ "seq": 6,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [
+ {
+ "name": "bruno",
+ "value": "is-awesome",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "req.setHeader('bruno', 'is-the-future');"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "J9AUIh6CbTnIxlCyKqqq7"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "sb6dpEtw8SYyeXVqEz3OA"
+ }
+ ],
+ "tests": "test(\"req.setHeader(name)\", function() {\n const h = req.getHeader('bruno');\n expect(h).to.equal(\"is-the-future\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setHeaders",
+ "seq": 8,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [
+ {
+ "name": "bruno",
+ "value": "is-awesome",
+ "enabled": true
+ },
+ {
+ "name": "della",
+ "value": "is-beautiful",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "req.setHeaders({\n \"content-type\": \"application/text\",\n \"transaction-id\": \"foobar\"\n});"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "1djJxGMAwmAHF2ruhdQQO"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "sqvBwQilTBWnFDoIBAC4T"
+ }
+ ],
+ "tests": "test(\"req.setHeaders()\", function() {\n const h = req.getHeaders();\n expect(h['content-type']).to.equal(\"application/text\");\n expect(h['transaction-id']).to.equal(\"foobar\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setMethod",
+ "seq": 4,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "req.setMethod(\"GET\");"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "3eRRXHvWErUAC2IiBto7B"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "UAqBwv3S2607RXzgC6S1i"
+ }
+ ],
+ "tests": "test(\"req.setMethod()()\", function() {\n const method = req.getMethod();\n expect(method).to.equal(\"GET\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setUrl",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/ping/invalid",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "req.setUrl(\"https://testbench-sanity.usebruno.com/ping\");"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "sGLaBON85rqipc1VP8R3W"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "SPVLRHys6RQh1GbRWnPpT"
+ }
+ ],
+ "tests": "test(\"req.setUrl()\", function() {\n const url = req.getUrl();\n expect(url).to.equal(\"https://testbench-sanity.usebruno.com/ping\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "res",
+ "root": {
+ "meta": {
+ "name": "res"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "getBody",
+ "seq": 4,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "rQe4gitaooPrQkEqD6AvL"
+ }
+ ],
+ "tests": "test(\"res.getBody()\", function() {\n const data = res.getBody();\n expect(data).to.eql({\n \"hello\": \"bruno\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getHeader",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "LOem8LkfWBML3yI1Kh3ZU"
+ }
+ ],
+ "tests": "test(\"res.getHeader(name)\", function() {\n const server = res.getHeader('x-powered-by');\n expect(server).to.eql('Express');\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getHeaders",
+ "seq": 3,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "qF8ASpikHJzQLRS0ZqNkA"
+ }
+ ],
+ "tests": "test(\"res.getHeaders(name)\", function() {\n const h = res.getHeaders();\n expect(h['x-powered-by']).to.eql('Express');\n expect(h['content-length']).to.eql('17');\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getResponseTime",
+ "seq": 5,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "pqN8P939S4dfZ1Bmuemi7"
+ }
+ ],
+ "tests": "test(\"res.getResponseTime()\", function() {\n const responseTime = res.getResponseTime();\n expect(typeof responseTime).to.eql(\"number\");\n expect(responseTime > 0).to.be.true;\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getStatus",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "0DqeIPuHtcmaULlYG9eWu"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "WZDxwKadXkDkK3Ea1VMKW"
+ }
+ ],
+ "tests": "test(\"res.getStatus()\", function() {\n const status = res.getStatus()\n expect(status).to.equal(200);\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "inbuilt modules",
+ "root": {
+ "meta": {
+ "name": "inbuilt modules"
+ }
+ },
+ "items": [
+ {
+ "type": "folder",
+ "name": "axios",
+ "root": {
+ "meta": {
+ "name": "axios"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "axios-pre-req-script",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const axios = require(\"axios\");\n\nconst url = \"https://testbench-sanity.usebruno.com/api/echo/json\";\nconst response = await axios.post(url, {\n \"hello\": \"bruno\"\n});\n\nreq.setBody(response.data);\nreq.setMethod(\"POST\");\nreq.setUrl(url);"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"req.getBody()\", function() {\n const data = res.getBody();\n expect(data).to.eql({\n \"hello\": \"bruno\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "crypto-js",
+ "root": {
+ "meta": {
+ "name": "crypto-js"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "crypto-js-pre-request-script",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "var CryptoJS = require(\"crypto-js\");\n\n// Encrypt\nvar ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123').toString();\n\n// Decrypt\nvar bytes = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');\nvar originalText = bytes.toString(CryptoJS.enc.Utf8);\n\nbru.setVar('crypto-test-message', originalText);"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"crypto message\", function() {\n const data = bru.getVar('crypto-test-message');\n bru.setVar('crypto-test-message', null);\n expect(data).to.eql('my message');\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "nanoid",
+ "root": {
+ "meta": {
+ "name": "nanoid"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "nanoid",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const { nanoid } = require(\"nanoid\");\n \nbru.setVar(\"nanoid-test-id\", nanoid());"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"nanoid var\", function() {\n const id = bru.getVar('nanoid-test-id');\n let isValidNanoid = /^[a-zA-Z0-9_-]{21}$/.test(id)\n bru.setVar('nanoid-test-id', null);\n expect(isValidNanoid).to.eql(true);\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "uuid",
+ "root": {
+ "meta": {
+ "name": "uuid"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "uuid",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const { v4 } = require(\"uuid\");\n \nbru.setVar(\"uuid-test-id\", v4());"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"uuid var\", function() {\n const id = bru.getVar('uuid-test-id');\n let isValidUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(id);\n bru.setVar('uuid-test-id', null);\n expect(isValidUuid).to.eql(true);\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "js",
+ "root": {
+ "meta": {
+ "name": "js"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "data types - request vars",
+ "seq": 3,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"boolean\": false,\n \"number_1\": 1,\n \"number_2\": 0,\n \"number_3\": -1,\n \"string\": \"bruno\",\n \"array\": [1, 2, 3, 4, 5],\n \"object\": {\n \"hello\": \"bruno\"\n },\n \"null\": null\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "req.body.boolean",
+ "value": "isBoolean false",
+ "enabled": true,
+ "uid": "SgXkeY8p7ahXIq2kA9FzA"
+ },
+ {
+ "name": "req.body.number_1",
+ "value": "isNumber 1",
+ "enabled": true,
+ "uid": "lhS17xvEP5jzHGP2Uqfg9"
+ },
+ {
+ "name": "req.body.undefined",
+ "value": "isUndefined undefined",
+ "enabled": true,
+ "uid": "bFTk8cAUAzNnrvUhbNeyC"
+ },
+ {
+ "name": "req.body.string",
+ "value": "isString bruno",
+ "enabled": true,
+ "uid": "ohANzzhuM8E8egvoVy20M"
+ },
+ {
+ "name": "req.body.null",
+ "value": "isNull null",
+ "enabled": true,
+ "uid": "r6W6I7ATDVswqkAf7Kl1k"
+ },
+ {
+ "name": "req.body.array",
+ "value": "isArray",
+ "enabled": true,
+ "uid": "fFUuv0vldfqaAGPjhfmdl"
+ },
+ {
+ "name": "req.body.boolean",
+ "value": "eq false",
+ "enabled": true,
+ "uid": "eXPS2R19qWsPGm6usEogu"
+ },
+ {
+ "name": "req.body.number_1",
+ "value": "eq 1",
+ "enabled": true,
+ "uid": "WCKmMIqsFPwocy6LZmCcc"
+ },
+ {
+ "name": "req.body.undefined",
+ "value": "eq undefined",
+ "enabled": true,
+ "uid": "7fJRYC8ELm68Uc5CaB7B8"
+ },
+ {
+ "name": "req.body.string",
+ "value": "eq bruno",
+ "enabled": true,
+ "uid": "fXTl58gxhAUrUM8SZFxLW"
+ },
+ {
+ "name": "req.body.null",
+ "value": "eq null",
+ "enabled": true,
+ "uid": "yUhXaWTPJaUYU4zerBABN"
+ },
+ {
+ "name": "req.body.number_2",
+ "value": "eq 0",
+ "enabled": true,
+ "uid": "WWCCm6i8GzyNBH6xiQGAP"
+ },
+ {
+ "name": "req.body.number_3",
+ "value": "eq -1",
+ "enabled": true,
+ "uid": "G73JIdrxSUDpc33EfAZGW"
+ },
+ {
+ "name": "req.body.number_2",
+ "value": "isNumber",
+ "enabled": true,
+ "uid": "Dp5pdDeMEulfPB3ZDdjl4"
+ },
+ {
+ "name": "req.body.number_3",
+ "value": "isNumber",
+ "enabled": true,
+ "uid": "fWghLNcBbslVF2OJMSS6x"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "data types",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"boolean\": false,\n \"number\": 1,\n \"string\": \"bruno\",\n \"array\": [1, 2, 3, 4, 5],\n \"object\": {\n \"hello\": \"bruno\"\n },\n \"null\": null\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const reqBody = req.getBody();\n\nbru.setVar(\"dataTypeVarTest\", {\n ...reqBody,\n \"undefined\": undefined\n});"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"data types check via bru var\", function() {\n let v = bru.getVar(\"dataTypeVarTest\");\n v = {\n ...v,\n \"undefined\": undefined\n };\n expect(v).to.eql({\n \"boolean\": false,\n \"number\": 1,\n \"string\": \"bruno\",\n \"array\": [1, 2, 3, 4, 5],\n \"object\": {\n \"hello\": \"bruno\"\n },\n \"null\": null,\n \"undefined\": undefined\n })\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setTimeout",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "bru.setVar(\"test-js-set-timeout\", \"\");\nawait new Promise((resolve, reject) => {\n setTimeout(() => {\n bru.setVar(\"test-js-set-timeout\", \"bruno\");\n resolve();\n }, 1000);\n});\n\nconst v = bru.getVar(\"test-js-set-timeout\");\nbru.setVar(\"test-js-set-timeout\", v + \"-is-awesome\");\n"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"setTimeout()\", function() {\n const v = bru.getVar(\"test-js-set-timeout\")\n expect(v).to.eql(\"bruno-is-awesome\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "local modules",
+ "root": {
+ "meta": {
+ "name": "local modules"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "invalid and valid module imports",
+ "seq": 3,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "try {\n bru.setVar('invalid_module_error_thrown', false);\n // should throw an error\n const invalid = require(\"./lib/invalid\");\n}\ncatch(error) {\n bru.setVar('invalid_module_error_thrown', true);\n}\n\n\ntry {\n bru.setVar('valid_module_no_error', true);\n // should not throw an error\n const math = require(\"./lib/math\");\n}\ncatch(error) {\n bru.setVar('valid_module_no_error', false);\n}"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "invalid_module_error_thrown",
+ "value": "eq true",
+ "enabled": true,
+ "uid": "wdZ0MsGXmW7tRiX4VtQaT"
+ },
+ {
+ "name": "valid_module_no_error",
+ "value": "eq true",
+ "enabled": true,
+ "uid": "A7hwDplpc0qDp5Bk46AMJ"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "sum -without js extn-",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"a\": 1,\n \"b\": 2\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const math = require(\"./lib/math\");\nconsole.log(math, 'math');\n\nconst body = req.getBody();\nbody.sum = math.sum(body.a, body.b);\nbody.areaOfCircle = math.areaOfCircle(2);\n\nreq.setBody(body);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "R6TRM5HoxKGuC5dHFvYdH"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"a\": 1,\n \"b\": 2,\n \"sum\": 3,\n \"areaOfCircle\": 12.56\n });\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "sum",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"a\": 1,\n \"b\": 2\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const math = require(\"./lib/math.js\"); \nconst body = req.getBody();\nbody.sum = math.sum(body.a, body.b);\n\nreq.setBody(body);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "UXDIZRejDajw3j0oYHhij"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"a\": 1,\n \"b\": 2,\n \"sum\": 3\n });\n});\n\ntest(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"a\": 1,\n \"b\": 2,\n \"sum\": 3\n });\n});\n\ntest(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"a\": 1,\n \"b\": 2,\n \"sum\": 3\n });\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "npm modules",
+ "root": {
+ "meta": {
+ "name": "npm modules"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "fakerjs",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const { faker } = require('@faker-js/faker');\nconst uuid = faker.string.uuid();\n\nconst data = req.getBody();\ndata.uuid = uuid;\n\nreq.setBody(data);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "ZVuM9BByoo5XFCtUYTwfP"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n const data = res.getBody();\n const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n const isUUID = (inputString) => {\n return uuidRegex.test(inputString);\n };\n \n expect(data.hello).to.equal(\"bruno\");\n expect(isUUID(data.uuid)).to.be.true;\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "string interpolation",
+ "root": {
+ "request": {
+ "vars": {
+ "req": [
+ {
+ "name": "folder_pre_var",
+ "value": "folder_pre_var_value",
+ "enabled": true,
+ "local": false,
+ "uid": "OHd64NVOj1HQV2PLqRzy8"
+ },
+ {
+ "name": "folder_pre_var_2",
+ "value": "{{env.var1}}",
+ "enabled": true,
+ "local": false,
+ "uid": "J12VEAvPGi3R0wBKXy2jK"
+ }
+ ]
+ }
+ },
+ "meta": {
+ "name": "string interpolation"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "env vars",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"envVar1\": \"{{env.var1}}\",\n \"envVar2\": \"{{env-var2}}\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "mxXvAcLVxfpRpGqh76ugy"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n expect(res.getBody()).to.eql({\n \"envVar1\": \"envVar1\",\n \"envVar2\": \"envVar2\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "missing values",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/echo/json?foo={{undefinedVar}}",
+ "method": "POST",
+ "headers": [],
+ "params": [
+ {
+ "name": "foo",
+ "value": "{{undefinedVar}}",
+ "type": "query",
+ "enabled": true
+ }
+ ],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"{{undefinedVar2}}\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "nzPl7aN2MK9uc3SKEepG0"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n const url = req.getUrl();\n const query = url.split(\"?\")[1];\n expect(query).to.equal(\"foo={{undefinedVar}}\");\n\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"hello\": \"{{undefinedVar2}}\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "process env vars",
+ "seq": 4,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"bark\": \"{{bark}}\",\n \"bark2\": \"{{process.env.PROC_ENV_VAR}}\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "T1m34pWveQfE4Aao7Xqlt"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n expect(res.getBody()).to.eql({\n \"bark\": \"woof\",\n \"bark2\": \"woof\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "runtime vars",
+ "seq": 3,
+ "request": {
+ "url": "{{host}}/api/echo/text",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "text",
+ "json": "{\n \"envVar1\": \"{{env.var1}}\",\n \"envVar2\": \"{{env-var2}}\"\n}",
+ "text": "Hi, I am {{rUser.full_name}},\nI am {{rUser.age}} years old.\nMy favorite food is {{rUser.fav-food[0]}} and {{rUser.fav-food[1]}}.\nI like attention: {{rUser.want.attention}}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "bru.setVar(\"rUser\", {\n full_name: 'Bruno',\n age: 4,\n 'fav-food': ['egg', 'meat'],\n 'want.attention': true\n});"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "xe4IAIu4EXYOYiXmKU374"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n const expectedResponse = `Hi, I am Bruno,\nI am 4 years old.\nMy favorite food is egg and meat.\nI like attention: true`;\n expect(res.getBody()).to.equal(expectedResponse);\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "activeEnvironmentUid": "s4jJkWbb9017JXdVqOxLR",
+ "environments": [
+ {
+ "variables": [
+ {
+ "name": "host",
+ "value": "http://localhost:8080",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "bearer_auth_token",
+ "value": "your_secret_token",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "basic_auth_password",
+ "value": "della",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "client_id",
+ "value": "client_id_1",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "client_secret",
+ "value": "client_secret_1",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "auth_url",
+ "value": "http://localhost:8080/api/auth/oauth2/authorization_code/authorize",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "callback_url",
+ "value": "http://localhost:8080/api/auth/oauth2/authorization_code/callback",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "access_token_url",
+ "value": "http://localhost:8080/api/auth/oauth2/authorization_code/token",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "passwordCredentials_username",
+ "value": "foo",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "passwordCredentials_password",
+ "value": "bar",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "github_authorize_url",
+ "value": "https://github.com/login/oauth/authorize",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "github_access_token_url",
+ "value": "https://github.com/login/oauth/access_token",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "google_auth_url",
+ "value": "https://accounts.google.com/o/oauth2/auth",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "google_access_token_url",
+ "value": "https://accounts.google.com/o/oauth2/token",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "google_scope",
+ "value": "https://www.googleapis.com/auth/userinfo.email",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "github_client_secret",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "github_client_id",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "google_client_id",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "google_client_secret",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "github_authorization_code",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "passwordCredentials_access_token",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "client_credentials_access_token",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "authorization_code_access_token",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "github_access_token",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ }
+ ],
+ "name": "Local"
+ },
+ {
+ "variables": [
+ {
+ "name": "host",
+ "value": "https://testbench-sanity.usebruno.com",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "bearer_auth_token",
+ "value": "your_secret_token",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "basic_auth_password",
+ "value": "della",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "env.var1",
+ "value": "envVar1",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "env-var2",
+ "value": "envVar2",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "bark",
+ "value": "{{process.env.PROC_ENV_VAR}}",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "foo",
+ "value": "bar",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "testSetEnvVar",
+ "value": "bruno-29653",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "echo-host",
+ "value": "https://echo.usebruno.com",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ }
+ ],
+ "name": "Prod"
+ }
+ ],
+ "root": {
+ "request": {
+ "auth": {
+ "mode": "bearer",
+ "bearer": {
+ "token": "{{bearer_auth_token}}"
+ }
+ },
+ "headers": [
+ {
+ "name": "check",
+ "value": "again",
+ "enabled": true,
+ "uid": "wbTRFykhPHZwnzVUTd1gr"
+ },
+ {
+ "name": "token",
+ "value": "{{collection_pre_var_token}}",
+ "enabled": true,
+ "uid": "YGZ16VXf9NusINngKeXqn"
+ }
+ ],
+ "vars": {
+ "req": [
+ {
+ "name": "collection_pre_var",
+ "value": "collection_pre_var_value",
+ "enabled": true,
+ "local": false,
+ "uid": "HI7DgTPA1gBLB6lIl1t3O"
+ },
+ {
+ "name": "collection_pre_var_token",
+ "value": "{{request_pre_var_token}}",
+ "enabled": true,
+ "local": false,
+ "uid": "FoDj77i1KoZ6Koq9oavPy"
+ }
+ ]
+ }
+ },
+ "docs": "# bruno-testbench 🐶\n\nThis is a test collection that I am using to test various functionalities around bruno"
+ },
+ "brunoConfig": {
+ "version": "1",
+ "name": "bruno-testbench",
+ "type": "collection",
+ "proxy": {
+ "enabled": false,
+ "protocol": "http",
+ "hostname": "{{proxyHostname}}",
+ "port": 4000,
+ "auth": {
+ "enabled": false,
+ "username": "anoop"
+ },
+ "bypassProxy": ""
+ },
+ "scripts": {
+ "moduleWhitelist": [
+ "crypto",
+ "buffer",
+ "form-data"
+ ],
+ "filesystemAccess": {
+ "allow": true
+ }
+ },
+ "clientCertificates": {
+ "enabled": true,
+ "certs": []
+ },
+ "presets": {
+ "requestType": "http",
+ "requestUrl": "http://localhost:6000"
+ },
+ "ignore": [
+ "node_modules",
+ ".git"
+ ],
+ "size": 0.026633262634277344,
+ "filesCount": 96
+ }
+}
\ No newline at end of file
diff --git a/e2e-tests/import-tests/test-data/bruno-testbench.json b/e2e-tests/import-tests/test-data/bruno-testbench.json
new file mode 100644
index 000000000..02a9c29fb
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/bruno-testbench.json
@@ -0,0 +1,2940 @@
+{
+ "name": "bruno-testbench",
+ "version": "1",
+ "items": [
+ {
+ "type": "http",
+ "name": "aaaaa",
+ "seq": 2,
+ "request": {
+ "url": "https://reqres.in/api/users/1",
+ "method": "PUT",
+ "headers": [
+ {
+ "name": "Accept",
+ "value": "application/json",
+ "enabled": true
+ },
+ {
+ "name": "Cookie",
+ "value": "session-id=abc123",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "console.log(req.getCookie());"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "folder",
+ "name": "auth",
+ "root": {
+ "meta": {
+ "name": "auth"
+ }
+ },
+ "items": [
+ {
+ "type": "folder",
+ "name": "basic",
+ "root": {
+ "meta": {
+ "name": "basic"
+ }
+ },
+ "items": [
+ {
+ "type": "folder",
+ "name": "via auth",
+ "root": {
+ "meta": {
+ "name": "via auth"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "Basic Auth 200",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/auth/basic/protected",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "200",
+ "enabled": true,
+ "uid": "YLpcflD1RLvdkSSvAYimh"
+ },
+ {
+ "name": "res.body.message",
+ "value": "Authentication successful",
+ "enabled": true,
+ "uid": "oqRPDS5d7CLIqBQ5OCEko"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "basic",
+ "basic": {
+ "username": "bruno",
+ "password": "{{basic_auth_password}}"
+ }
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "Basic Auth 400",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/auth/basic/protected",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "401",
+ "enabled": true,
+ "uid": "WsBvjaJuowT05ri9A8Qc5"
+ },
+ {
+ "name": "res.body",
+ "value": "Unauthorized",
+ "enabled": true,
+ "uid": "VW1wyd6hu74Yyfzhn0RuQ"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "via script",
+ "root": {
+ "meta": {
+ "name": "via script"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "Basic Auth 200",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/auth/basic/protected",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const username = \"bruno\";\nconst password = \"della\";\n\nconst authString = `${username}:${password}`;\nconst encodedAuthString = require('btoa')(authString);\n\nreq.setHeader(\"Authorization\", `Basic ${encodedAuthString}`);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "5p6vUUMuLxbA7KnYnXrkT"
+ },
+ {
+ "name": "res.body.message",
+ "value": "Authentication successful",
+ "enabled": true,
+ "uid": "Tk43KT6Hyf3h8Jfeyk2XD"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "Basic Auth 401",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/auth/basic/protected",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const username = \"bruno\";\nconst password = \"invalid\";\n\nconst authString = `${username}:${password}`;\nconst encodedAuthString = require('btoa')(authString);\n\nreq.setHeader(\"Authorization\", `Basic ${encodedAuthString}`);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "401",
+ "enabled": true,
+ "uid": "dLnctBQFSISlaooCYzp5C"
+ },
+ {
+ "name": "res.body",
+ "value": "Unauthorized",
+ "enabled": true,
+ "uid": "iWPqym01ksxrDV1gfuhWv"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "bearer",
+ "root": {
+ "meta": {
+ "name": "bearer"
+ }
+ },
+ "items": [
+ {
+ "type": "folder",
+ "name": "via auth",
+ "root": {
+ "meta": {
+ "name": "via auth"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "Bearer Auth 200",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/auth/bearer/protected",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "res": "bru.setEnvVar(\"foo\", \"bar\");"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "200",
+ "enabled": true,
+ "uid": "F01gjRjDDQefuLn2Vcyed"
+ },
+ {
+ "name": "res.body.message",
+ "value": "Authentication successful",
+ "enabled": true,
+ "uid": "Hmw3BpVyz9tDBEcdA88O0"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "bearer",
+ "bearer": {
+ "token": "{{bearer_auth_token}}"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "via headers",
+ "root": {
+ "meta": {
+ "name": "via headers"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "Bearer Auth 200",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/auth/bearer/protected",
+ "method": "GET",
+ "headers": [
+ {
+ "name": "Authorization",
+ "value": "Bearer your_secret_token",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "res": "bru.setEnvVar(\"foo\", \"bar\");"
+ },
+ "vars": {
+ "req": [
+ {
+ "name": "a-c",
+ "value": "foo",
+ "enabled": true,
+ "local": false
+ }
+ ]
+ },
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "200",
+ "enabled": true,
+ "uid": "VDQ7l9zN9WfS3lEGsJ0aw"
+ },
+ {
+ "name": "res.body.message",
+ "value": "Authentication successful",
+ "enabled": true,
+ "uid": "0n8UMinkhzOuRJCCABVz9"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "cookie",
+ "root": {
+ "meta": {
+ "name": "cookie"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "Check",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/auth/cookie/protected",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "Login",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/auth/cookie/login",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "inherit auth",
+ "root": {
+ "meta": {
+ "name": "inherit auth"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "inherit Bearer Auth 200",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/auth/bearer/protected",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "res": "bru.setEnvVar(\"foo\", \"bar\");"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "200",
+ "enabled": true,
+ "uid": "G6vVLMAqfvpa4aBtQ3WSG"
+ },
+ {
+ "name": "res.body.message",
+ "value": "Authentication successful",
+ "enabled": true,
+ "uid": "QItzfaevVVrycFox5jTlS"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "inherit"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "echo",
+ "root": {
+ "meta": {
+ "name": "echo"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "echo bigint",
+ "seq": 6,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [
+ {
+ "name": "foo",
+ "value": "bar",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": 990531470713421825,\n \"decimal\": 1.0,\n \"decimal2\": 1.00,\n \"decimal3\": 1.00200,\n \"decimal4\": 0.00\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "lCoGpuLOpVmXPfGzJqbTB"
+ }
+ ],
+ "tests": "// todo: add tests once lossless json echo server is ready",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo bom json",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/echo/bom-json-test",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo form-url-encoded",
+ "seq": 9,
+ "request": {
+ "url": "{{echo-host}}",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "formUrlEncoded",
+ "formUrlEncoded": [
+ {
+ "name": "form-data-key",
+ "value": "{{form-data-key}}",
+ "enabled": true
+ },
+ {
+ "name": "form-data-stringified-object",
+ "value": "{{form-data-stringified-object}}",
+ "enabled": true
+ }
+ ],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "let obj = JSON.stringify({foo:123});\nbru.setVar('form-data-key', 'form-data-value');\nbru.setVar('form-data-stringified-object', obj);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.body",
+ "value": "eq form-data-key=form-data-value&form-data-stringified-object=%7B%22foo%22%3A123%7D",
+ "enabled": true,
+ "uid": "V0MSBvq2iFun9gIWfgqtQ"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo json",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [
+ {
+ "name": "foo",
+ "value": "bar",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "bru.setVar(\"foo\", \"foo-world-2\");"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "FFVx1w4MstKeQfQR66Xy8"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"hello\": \"bruno\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo multipart via scripting",
+ "seq": 10,
+ "request": {
+ "url": "{{echo-host}}",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "multipartForm",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const FormData = require(\"form-data\");\nconst form = new FormData();\nform.append('form-data-key', 'form-data-value');\nreq.setBody(form);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.body",
+ "value": "contains form-data-value",
+ "enabled": true,
+ "uid": "USCnLx51IlWz6HrLxlR1r"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo multipart",
+ "seq": 8,
+ "request": {
+ "url": "{{echo-host}}",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "multipartForm",
+ "formUrlEncoded": [],
+ "multipartForm": [
+ {
+ "type": "text",
+ "name": "form-data-key",
+ "value": "{{form-data-key}}",
+ "enabled": true
+ },
+ {
+ "type": "text",
+ "name": "form-data-stringified-object",
+ "value": "{{form-data-stringified-object}}",
+ "enabled": true
+ },
+ {
+ "type": "file",
+ "name": "file",
+ "value": [
+ "bruno.png"
+ ],
+ "enabled": true
+ }
+ ],
+ "file": []
+ },
+ "script": {
+ "req": "let obj = JSON.stringify({foo:123});\nbru.setVar('form-data-key', 'form-data-value');\nbru.setVar('form-data-stringified-object', obj);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.body",
+ "value": "contains form-data-value",
+ "enabled": true,
+ "uid": "L5wrs8CJKD7skDazamdTZ"
+ },
+ {
+ "name": "res.body",
+ "value": "contains {\"foo\":123}",
+ "enabled": true,
+ "uid": "2rPiaUFbPuWPq0ew6dqVd"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo plaintext",
+ "seq": 3,
+ "request": {
+ "url": "{{host}}/api/echo/text",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "text",
+ "text": "hello",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "cW2RamEi0zqLmn84SjUoh"
+ }
+ ],
+ "tests": "test(\"should return plain text\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql(\"hello\");\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo xml parsed-self closing tags-",
+ "seq": 6,
+ "request": {
+ "url": "{{host}}/api/echo/xml-parsed",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "xml",
+ "xml": "\n bruno\n \n",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "lIbw7OdlPxbNUKdShGNvi"
+ }
+ ],
+ "tests": "test(\"should return parsed xml\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"hello\": {\n \"world\": [\n \"bruno\",\n \"\"\n ]\n }\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo xml parsed",
+ "seq": 4,
+ "request": {
+ "url": "{{host}}/api/echo/xml-parsed",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "xml",
+ "xml": "\n bruno\n",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "5yr5fbjrAre0Cp0C3PY4c"
+ }
+ ],
+ "tests": "test(\"should return parsed xml\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"hello\": {\n \"world\": [\"bruno\"]\n }\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "echo xml raw",
+ "seq": 5,
+ "request": {
+ "url": "{{host}}/api/echo/xml-raw",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "xml",
+ "xml": "bruno",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "graphql",
+ "root": {
+ "meta": {
+ "name": "graphql"
+ }
+ },
+ "items": [
+ {
+ "type": "graphql",
+ "name": "spacex",
+ "seq": 1,
+ "request": {
+ "url": "https://spacex-production.up.railway.app/",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "graphql",
+ "graphql": {
+ "query": "{\n company {\n ceo\n }\n}\n"
+ },
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "P99wa88sX4L4Zat94bHzz"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "lib",
+ "root": {
+ "meta": {
+ "name": "lib"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "ping",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "folder",
+ "name": "preview",
+ "root": {
+ "meta": {
+ "name": "preview"
+ }
+ },
+ "items": [
+ {
+ "type": "folder",
+ "name": "html",
+ "root": {
+ "meta": {
+ "name": "html"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "bruno",
+ "seq": 1,
+ "request": {
+ "url": "https://www.github.com",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "console.log(req.getCookie());\n\nconsole.log(req.getHeaders());"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "2bpXrsR3q5MBpkXbO1vfS"
+ }
+ ],
+ "tests": "test(\"should return parsed xml\", function() {\n const headers = res.getHeaders();\n expect(headers['content-type']).to.eql(\"text/html; charset=utf-8\");\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "image",
+ "root": {
+ "meta": {
+ "name": "image"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "bruno",
+ "seq": 1,
+ "request": {
+ "url": "https://www.usebruno.com/images/landing-2.png",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"should return parsed xml\", function() {\n const headers = res.getHeaders();\n expect(headers['content-type']).to.eql(\"image/png\");\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "redirects",
+ "root": {
+ "meta": {
+ "name": "redirects"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "Disable Redirect",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/redirect-to-ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "req.setMaxRedirects(0);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "302",
+ "enabled": true,
+ "uid": "Bs0jGEFFNAyyRBx6DILEN"
+ }
+ ],
+ "tests": "test(\"should disable redirect to ping\", function() {\n const data = res.getBody();\n expect(data).to.equal('Found. Redirecting to /ping');\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "Test Redirect",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/redirect-to-ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "200",
+ "enabled": true,
+ "uid": "nNRcxeANwM6VBEXR1qoM0"
+ },
+ {
+ "name": "res.body",
+ "value": "pong",
+ "enabled": true,
+ "uid": "3Y5SHtNsQHK0glgikD1IU"
+ }
+ ],
+ "tests": "test(\"should redirect to ping\", function() {\n const data = res.getBody();\n expect(data).to.equal('pong');\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "scripting",
+ "root": {
+ "meta": {
+ "name": "scripting"
+ }
+ },
+ "items": [
+ {
+ "type": "folder",
+ "name": "api",
+ "root": {
+ "meta": {
+ "name": "api"
+ }
+ },
+ "items": [
+ {
+ "type": "folder",
+ "name": "bru",
+ "root": {
+ "meta": {
+ "name": "bru"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "getEnvName",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const envName = bru.getEnvName();\nbru.setVar(\"testEnvName\", envName);"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"should get env name in scripts\", function() {\n const testEnvName = bru.getVar(\"testEnvName\");\n expect(testEnvName).to.equal(\"Prod\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getEnvVar",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"should get env var in scripts\", function() {\n const host = bru.getEnvVar(\"host\")\n expect(host).to.equal(\"https://testbench-sanity.usebruno.com\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getProcessEnv",
+ "seq": 6,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"bru.getProcessEnv()\", function() {\n const v = bru.getProcessEnv(\"PROC_ENV_VAR\");\n expect(v).to.equal(\"woof\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getVar",
+ "seq": 5,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"should get var in scripts\", function() {\n const testSetVar = bru.getVar(\"testSetVar\");\n expect(testSetVar).to.equal(\"bruno-test-87267\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setEnvVar",
+ "seq": 3,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "res": "bru.setEnvVar(\"testSetEnvVar\", \"bruno-29653\")"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"should set env var in scripts\", function() {\n const testSetEnvVar = bru.getEnvVar(\"testSetEnvVar\")\n expect(testSetEnvVar).to.equal(\"bruno-29653\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setVar",
+ "seq": 4,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "res": "bru.setVar(\"testSetVar\", \"bruno-test-87267\")"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"should get var in scripts\", function() {\n const testSetVar = bru.getVar(\"testSetVar\");\n expect(testSetVar).to.equal(\"bruno-test-87267\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "req",
+ "root": {
+ "meta": {
+ "name": "req"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "getBody",
+ "seq": 9,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "7VvXmRWwUdGYbvrQaeDMD"
+ }
+ ],
+ "tests": "test(\"req.getBody()\", function() {\n const data = res.getBody();\n expect(data).to.eql({\n \"hello\": \"bruno\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getHeader",
+ "seq": 5,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [
+ {
+ "name": "bruno",
+ "value": "is-awesome",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "HssG2g6gUaWaBFFanCozP"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "50NSDIeXgRr0TcXEdquci"
+ }
+ ],
+ "tests": "test(\"req.getHeader(name)\", function() {\n const h = req.getHeader('bruno');\n expect(h).to.equal(\"is-awesome\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getHeaders",
+ "seq": 7,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [
+ {
+ "name": "bruno",
+ "value": "is-awesome",
+ "enabled": true
+ },
+ {
+ "name": "della",
+ "value": "is-beautiful",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "9NDZWAvBS23WJAZsKl9SS"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "f9ULUob9jYiABYuEzfmgC"
+ }
+ ],
+ "tests": "test(\"req.getHeaders()\", function() {\n const h = req.getHeaders();\n expect(h.bruno).to.equal(\"is-awesome\");\n expect(h.della).to.equal(\"is-beautiful\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getMethod",
+ "seq": 3,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "EpNcKUgCYzdg8KrOLqaCX"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "qFqcLtNYbZ9nqhiwvS3Qk"
+ }
+ ],
+ "tests": "test(\"req.getMethod()()\", function() {\n const method = req.getMethod();\n expect(method).to.equal(\"GET\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getUrl",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "VaiDs2JU1NM8prTc59GdX"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "4vC9zp5XBajbYKDYM4oFN"
+ }
+ ],
+ "tests": "test(\"req.getUrl()\", function() {\n const url = req.getUrl();\n expect(url).to.equal(\"https://testbench-sanity.usebruno.com/ping\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setBody",
+ "seq": 10,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "req.setBody({\n \"bruno\": \"is awesome\"\n});"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "EGlBavIEZ2j0s2aczQxAP"
+ }
+ ],
+ "tests": "test(\"req.setBody()\", function() {\n const data = res.getBody();\n expect(data).to.eql({\n \"bruno\": \"is awesome\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setHeader",
+ "seq": 6,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [
+ {
+ "name": "bruno",
+ "value": "is-awesome",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "req.setHeader('bruno', 'is-the-future');"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "J9AUIh6CbTnIxlCyKqqq7"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "sb6dpEtw8SYyeXVqEz3OA"
+ }
+ ],
+ "tests": "test(\"req.setHeader(name)\", function() {\n const h = req.getHeader('bruno');\n expect(h).to.equal(\"is-the-future\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setHeaders",
+ "seq": 8,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [
+ {
+ "name": "bruno",
+ "value": "is-awesome",
+ "enabled": true
+ },
+ {
+ "name": "della",
+ "value": "is-beautiful",
+ "enabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "req.setHeaders({\n \"content-type\": \"application/text\",\n \"transaction-id\": \"foobar\"\n});"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "1djJxGMAwmAHF2ruhdQQO"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "sqvBwQilTBWnFDoIBAC4T"
+ }
+ ],
+ "tests": "test(\"req.setHeaders()\", function() {\n const h = req.getHeaders();\n expect(h['content-type']).to.equal(\"application/text\");\n expect(h['transaction-id']).to.equal(\"foobar\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setMethod",
+ "seq": 4,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "req.setMethod(\"GET\");"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "3eRRXHvWErUAC2IiBto7B"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "UAqBwv3S2607RXzgC6S1i"
+ }
+ ],
+ "tests": "test(\"req.setMethod()()\", function() {\n const method = req.getMethod();\n expect(method).to.equal(\"GET\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setUrl",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/ping/invalid",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "req.setUrl(\"https://testbench-sanity.usebruno.com/ping\");"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "sGLaBON85rqipc1VP8R3W"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "SPVLRHys6RQh1GbRWnPpT"
+ }
+ ],
+ "tests": "test(\"req.setUrl()\", function() {\n const url = req.getUrl();\n expect(url).to.equal(\"https://testbench-sanity.usebruno.com/ping\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "res",
+ "root": {
+ "meta": {
+ "name": "res"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "getBody",
+ "seq": 4,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "rQe4gitaooPrQkEqD6AvL"
+ }
+ ],
+ "tests": "test(\"res.getBody()\", function() {\n const data = res.getBody();\n expect(data).to.eql({\n \"hello\": \"bruno\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getHeader",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "LOem8LkfWBML3yI1Kh3ZU"
+ }
+ ],
+ "tests": "test(\"res.getHeader(name)\", function() {\n const server = res.getHeader('x-powered-by');\n expect(server).to.eql('Express');\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getHeaders",
+ "seq": 3,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "qF8ASpikHJzQLRS0ZqNkA"
+ }
+ ],
+ "tests": "test(\"res.getHeaders(name)\", function() {\n const h = res.getHeaders();\n expect(h['x-powered-by']).to.eql('Express');\n expect(h['content-length']).to.eql('17');\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getResponseTime",
+ "seq": 5,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "pqN8P939S4dfZ1Bmuemi7"
+ }
+ ],
+ "tests": "test(\"res.getResponseTime()\", function() {\n const responseTime = res.getResponseTime();\n expect(typeof responseTime).to.eql(\"number\");\n expect(responseTime > 0).to.be.true;\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "getStatus",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "0DqeIPuHtcmaULlYG9eWu"
+ },
+ {
+ "name": "res.body",
+ "value": "eq pong",
+ "enabled": true,
+ "uid": "WZDxwKadXkDkK3Ea1VMKW"
+ }
+ ],
+ "tests": "test(\"res.getStatus()\", function() {\n const status = res.getStatus()\n expect(status).to.equal(200);\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "inbuilt modules",
+ "root": {
+ "meta": {
+ "name": "inbuilt modules"
+ }
+ },
+ "items": [
+ {
+ "type": "folder",
+ "name": "axios",
+ "root": {
+ "meta": {
+ "name": "axios"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "axios-pre-req-script",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const axios = require(\"axios\");\n\nconst url = \"https://testbench-sanity.usebruno.com/api/echo/json\";\nconst response = await axios.post(url, {\n \"hello\": \"bruno\"\n});\n\nreq.setBody(response.data);\nreq.setMethod(\"POST\");\nreq.setUrl(url);"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"req.getBody()\", function() {\n const data = res.getBody();\n expect(data).to.eql({\n \"hello\": \"bruno\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "crypto-js",
+ "root": {
+ "meta": {
+ "name": "crypto-js"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "crypto-js-pre-request-script",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "var CryptoJS = require(\"crypto-js\");\n\n// Encrypt\nvar ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123').toString();\n\n// Decrypt\nvar bytes = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');\nvar originalText = bytes.toString(CryptoJS.enc.Utf8);\n\nbru.setVar('crypto-test-message', originalText);"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"crypto message\", function() {\n const data = bru.getVar('crypto-test-message');\n bru.setVar('crypto-test-message', null);\n expect(data).to.eql('my message');\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "nanoid",
+ "root": {
+ "meta": {
+ "name": "nanoid"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "nanoid",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const { nanoid } = require(\"nanoid\");\n \nbru.setVar(\"nanoid-test-id\", nanoid());"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"nanoid var\", function() {\n const id = bru.getVar('nanoid-test-id');\n let isValidNanoid = /^[a-zA-Z0-9_-]{21}$/.test(id)\n bru.setVar('nanoid-test-id', null);\n expect(isValidNanoid).to.eql(true);\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "uuid",
+ "root": {
+ "meta": {
+ "name": "uuid"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "uuid",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const { v4 } = require(\"uuid\");\n \nbru.setVar(\"uuid-test-id\", v4());"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"uuid var\", function() {\n const id = bru.getVar('uuid-test-id');\n let isValidUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(id);\n bru.setVar('uuid-test-id', null);\n expect(isValidUuid).to.eql(true);\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "js",
+ "root": {
+ "meta": {
+ "name": "js"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "data types - request vars",
+ "seq": 3,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"boolean\": false,\n \"number_1\": 1,\n \"number_2\": 0,\n \"number_3\": -1,\n \"string\": \"bruno\",\n \"array\": [1, 2, 3, 4, 5],\n \"object\": {\n \"hello\": \"bruno\"\n },\n \"null\": null\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "req.body.boolean",
+ "value": "isBoolean false",
+ "enabled": true,
+ "uid": "SgXkeY8p7ahXIq2kA9FzA"
+ },
+ {
+ "name": "req.body.number_1",
+ "value": "isNumber 1",
+ "enabled": true,
+ "uid": "lhS17xvEP5jzHGP2Uqfg9"
+ },
+ {
+ "name": "req.body.undefined",
+ "value": "isUndefined undefined",
+ "enabled": true,
+ "uid": "bFTk8cAUAzNnrvUhbNeyC"
+ },
+ {
+ "name": "req.body.string",
+ "value": "isString bruno",
+ "enabled": true,
+ "uid": "ohANzzhuM8E8egvoVy20M"
+ },
+ {
+ "name": "req.body.null",
+ "value": "isNull null",
+ "enabled": true,
+ "uid": "r6W6I7ATDVswqkAf7Kl1k"
+ },
+ {
+ "name": "req.body.array",
+ "value": "isArray",
+ "enabled": true,
+ "uid": "fFUuv0vldfqaAGPjhfmdl"
+ },
+ {
+ "name": "req.body.boolean",
+ "value": "eq false",
+ "enabled": true,
+ "uid": "eXPS2R19qWsPGm6usEogu"
+ },
+ {
+ "name": "req.body.number_1",
+ "value": "eq 1",
+ "enabled": true,
+ "uid": "WCKmMIqsFPwocy6LZmCcc"
+ },
+ {
+ "name": "req.body.undefined",
+ "value": "eq undefined",
+ "enabled": true,
+ "uid": "7fJRYC8ELm68Uc5CaB7B8"
+ },
+ {
+ "name": "req.body.string",
+ "value": "eq bruno",
+ "enabled": true,
+ "uid": "fXTl58gxhAUrUM8SZFxLW"
+ },
+ {
+ "name": "req.body.null",
+ "value": "eq null",
+ "enabled": true,
+ "uid": "yUhXaWTPJaUYU4zerBABN"
+ },
+ {
+ "name": "req.body.number_2",
+ "value": "eq 0",
+ "enabled": true,
+ "uid": "WWCCm6i8GzyNBH6xiQGAP"
+ },
+ {
+ "name": "req.body.number_3",
+ "value": "eq -1",
+ "enabled": true,
+ "uid": "G73JIdrxSUDpc33EfAZGW"
+ },
+ {
+ "name": "req.body.number_2",
+ "value": "isNumber",
+ "enabled": true,
+ "uid": "Dp5pdDeMEulfPB3ZDdjl4"
+ },
+ {
+ "name": "req.body.number_3",
+ "value": "isNumber",
+ "enabled": true,
+ "uid": "fWghLNcBbslVF2OJMSS6x"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "data types",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"boolean\": false,\n \"number\": 1,\n \"string\": \"bruno\",\n \"array\": [1, 2, 3, 4, 5],\n \"object\": {\n \"hello\": \"bruno\"\n },\n \"null\": null\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const reqBody = req.getBody();\n\nbru.setVar(\"dataTypeVarTest\", {\n ...reqBody,\n \"undefined\": undefined\n});"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"data types check via bru var\", function() {\n let v = bru.getVar(\"dataTypeVarTest\");\n v = {\n ...v,\n \"undefined\": undefined\n };\n expect(v).to.eql({\n \"boolean\": false,\n \"number\": 1,\n \"string\": \"bruno\",\n \"array\": [1, 2, 3, 4, 5],\n \"object\": {\n \"hello\": \"bruno\"\n },\n \"null\": null,\n \"undefined\": undefined\n })\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "setTimeout",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "bru.setVar(\"test-js-set-timeout\", \"\");\nawait new Promise((resolve, reject) => {\n setTimeout(() => {\n bru.setVar(\"test-js-set-timeout\", \"bruno\");\n resolve();\n }, 1000);\n});\n\nconst v = bru.getVar(\"test-js-set-timeout\");\nbru.setVar(\"test-js-set-timeout\", v + \"-is-awesome\");\n"
+ },
+ "vars": {},
+ "assertions": [],
+ "tests": "test(\"setTimeout()\", function() {\n const v = bru.getVar(\"test-js-set-timeout\")\n expect(v).to.eql(\"bruno-is-awesome\");\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "local modules",
+ "root": {
+ "meta": {
+ "name": "local modules"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "invalid and valid module imports",
+ "seq": 3,
+ "request": {
+ "url": "{{host}}/ping",
+ "method": "GET",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "none",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "try {\n bru.setVar('invalid_module_error_thrown', false);\n // should throw an error\n const invalid = require(\"./lib/invalid\");\n}\ncatch(error) {\n bru.setVar('invalid_module_error_thrown', true);\n}\n\n\ntry {\n bru.setVar('valid_module_no_error', true);\n // should not throw an error\n const math = require(\"./lib/math\");\n}\ncatch(error) {\n bru.setVar('valid_module_no_error', false);\n}"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "invalid_module_error_thrown",
+ "value": "eq true",
+ "enabled": true,
+ "uid": "wdZ0MsGXmW7tRiX4VtQaT"
+ },
+ {
+ "name": "valid_module_no_error",
+ "value": "eq true",
+ "enabled": true,
+ "uid": "A7hwDplpc0qDp5Bk46AMJ"
+ }
+ ],
+ "tests": "",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "sum -without js extn-",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"a\": 1,\n \"b\": 2\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const math = require(\"./lib/math\");\nconsole.log(math, 'math');\n\nconst body = req.getBody();\nbody.sum = math.sum(body.a, body.b);\nbody.areaOfCircle = math.areaOfCircle(2);\n\nreq.setBody(body);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "R6TRM5HoxKGuC5dHFvYdH"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"a\": 1,\n \"b\": 2,\n \"sum\": 3,\n \"areaOfCircle\": 12.56\n });\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "sum",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"a\": 1,\n \"b\": 2\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const math = require(\"./lib/math.js\"); \nconst body = req.getBody();\nbody.sum = math.sum(body.a, body.b);\n\nreq.setBody(body);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "UXDIZRejDajw3j0oYHhij"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"a\": 1,\n \"b\": 2,\n \"sum\": 3\n });\n});\n\ntest(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"a\": 1,\n \"b\": 2,\n \"sum\": 3\n });\n});\n\ntest(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"a\": 1,\n \"b\": 2,\n \"sum\": 3\n });\n});",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "npm modules",
+ "root": {
+ "meta": {
+ "name": "npm modules"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "fakerjs",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"bruno\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "const { faker } = require('@faker-js/faker');\nconst uuid = faker.string.uuid();\n\nconst data = req.getBody();\ndata.uuid = uuid;\n\nreq.setBody(data);"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "ZVuM9BByoo5XFCtUYTwfP"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n const data = res.getBody();\n const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n const isUUID = (inputString) => {\n return uuidRegex.test(inputString);\n };\n \n expect(data.hello).to.equal(\"bruno\");\n expect(isUUID(data.uuid)).to.be.true;\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "folder",
+ "name": "string interpolation",
+ "root": {
+ "request": {
+ "vars": {
+ "req": [
+ {
+ "name": "folder_pre_var",
+ "value": "folder_pre_var_value",
+ "enabled": true,
+ "local": false,
+ "uid": "OHd64NVOj1HQV2PLqRzy8"
+ },
+ {
+ "name": "folder_pre_var_2",
+ "value": "{{env.var1}}",
+ "enabled": true,
+ "local": false,
+ "uid": "J12VEAvPGi3R0wBKXy2jK"
+ }
+ ]
+ }
+ },
+ "meta": {
+ "name": "string interpolation"
+ }
+ },
+ "items": [
+ {
+ "type": "http",
+ "name": "env vars",
+ "seq": 2,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"envVar1\": \"{{env.var1}}\",\n \"envVar2\": \"{{env-var2}}\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "mxXvAcLVxfpRpGqh76ugy"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n expect(res.getBody()).to.eql({\n \"envVar1\": \"envVar1\",\n \"envVar2\": \"envVar2\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "missing values",
+ "seq": 1,
+ "request": {
+ "url": "{{host}}/api/echo/json?foo={{undefinedVar}}",
+ "method": "POST",
+ "headers": [],
+ "params": [
+ {
+ "name": "foo",
+ "value": "{{undefinedVar}}",
+ "type": "query",
+ "enabled": true
+ }
+ ],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"hello\": \"{{undefinedVar2}}\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "nzPl7aN2MK9uc3SKEepG0"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n const url = req.getUrl();\n const query = url.split(\"?\")[1];\n expect(query).to.equal(\"foo={{undefinedVar}}\");\n\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"hello\": \"{{undefinedVar2}}\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "process env vars",
+ "seq": 4,
+ "request": {
+ "url": "{{host}}/api/echo/json",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "json",
+ "json": "{\n \"bark\": \"{{bark}}\",\n \"bark2\": \"{{process.env.PROC_ENV_VAR}}\"\n}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {},
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "T1m34pWveQfE4Aao7Xqlt"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n expect(res.getBody()).to.eql({\n \"bark\": \"woof\",\n \"bark2\": \"woof\"\n });\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ },
+ {
+ "type": "http",
+ "name": "runtime vars",
+ "seq": 3,
+ "request": {
+ "url": "{{host}}/api/echo/text",
+ "method": "POST",
+ "headers": [],
+ "params": [],
+ "body": {
+ "mode": "text",
+ "json": "{\n \"envVar1\": \"{{env.var1}}\",\n \"envVar2\": \"{{env-var2}}\"\n}",
+ "text": "Hi, I am {{rUser.full_name}},\nI am {{rUser.age}} years old.\nMy favorite food is {{rUser.fav-food[0]}} and {{rUser.fav-food[1]}}.\nI like attention: {{rUser.want.attention}}",
+ "formUrlEncoded": [],
+ "multipartForm": [],
+ "file": []
+ },
+ "script": {
+ "req": "bru.setVar(\"rUser\", {\n full_name: 'Bruno',\n age: 4,\n 'fav-food': ['egg', 'meat'],\n 'want.attention': true\n});"
+ },
+ "vars": {},
+ "assertions": [
+ {
+ "name": "res.status",
+ "value": "eq 200",
+ "enabled": true,
+ "uid": "xe4IAIu4EXYOYiXmKU374"
+ }
+ ],
+ "tests": "test(\"should return json\", function() {\n const expectedResponse = `Hi, I am Bruno,\nI am 4 years old.\nMy favorite food is egg and meat.\nI like attention: true`;\n expect(res.getBody()).to.equal(expectedResponse);\n});\n",
+ "docs": "",
+ "auth": {
+ "mode": "none"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "activeEnvironmentUid": "s4jJkWbb9017JXdVqOxLR",
+ "environments": [
+ {
+ "variables": [
+ {
+ "name": "host",
+ "value": "http://localhost:8080",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "bearer_auth_token",
+ "value": "your_secret_token",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "basic_auth_password",
+ "value": "della",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "client_id",
+ "value": "client_id_1",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "client_secret",
+ "value": "client_secret_1",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "auth_url",
+ "value": "http://localhost:8080/api/auth/oauth2/authorization_code/authorize",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "callback_url",
+ "value": "http://localhost:8080/api/auth/oauth2/authorization_code/callback",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "access_token_url",
+ "value": "http://localhost:8080/api/auth/oauth2/authorization_code/token",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "passwordCredentials_username",
+ "value": "foo",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "passwordCredentials_password",
+ "value": "bar",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "github_authorize_url",
+ "value": "https://github.com/login/oauth/authorize",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "github_access_token_url",
+ "value": "https://github.com/login/oauth/access_token",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "google_auth_url",
+ "value": "https://accounts.google.com/o/oauth2/auth",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "google_access_token_url",
+ "value": "https://accounts.google.com/o/oauth2/token",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "google_scope",
+ "value": "https://www.googleapis.com/auth/userinfo.email",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "github_client_secret",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "github_client_id",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "google_client_id",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "google_client_secret",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "github_authorization_code",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "passwordCredentials_access_token",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "client_credentials_access_token",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "authorization_code_access_token",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ },
+ {
+ "name": "github_access_token",
+ "value": "",
+ "enabled": true,
+ "secret": true,
+ "type": "text"
+ }
+ ],
+ "name": "Local"
+ },
+ {
+ "variables": [
+ {
+ "name": "host",
+ "value": "https://testbench-sanity.usebruno.com",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "bearer_auth_token",
+ "value": "your_secret_token",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "basic_auth_password",
+ "value": "della",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "env.var1",
+ "value": "envVar1",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "env-var2",
+ "value": "envVar2",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "bark",
+ "value": "{{process.env.PROC_ENV_VAR}}",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "foo",
+ "value": "bar",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "testSetEnvVar",
+ "value": "bruno-29653",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ },
+ {
+ "name": "echo-host",
+ "value": "https://echo.usebruno.com",
+ "enabled": true,
+ "secret": false,
+ "type": "text"
+ }
+ ],
+ "name": "Prod"
+ }
+ ],
+ "root": {
+ "request": {
+ "auth": {
+ "mode": "bearer",
+ "bearer": {
+ "token": "{{bearer_auth_token}}"
+ }
+ },
+ "headers": [
+ {
+ "name": "check",
+ "value": "again",
+ "enabled": true,
+ "uid": "wbTRFykhPHZwnzVUTd1gr"
+ },
+ {
+ "name": "token",
+ "value": "{{collection_pre_var_token}}",
+ "enabled": true,
+ "uid": "YGZ16VXf9NusINngKeXqn"
+ }
+ ],
+ "vars": {
+ "req": [
+ {
+ "name": "collection_pre_var",
+ "value": "collection_pre_var_value",
+ "enabled": true,
+ "local": false,
+ "uid": "HI7DgTPA1gBLB6lIl1t3O"
+ },
+ {
+ "name": "collection_pre_var_token",
+ "value": "{{request_pre_var_token}}",
+ "enabled": true,
+ "local": false,
+ "uid": "FoDj77i1KoZ6Koq9oavPy"
+ }
+ ]
+ }
+ },
+ "docs": "# bruno-testbench 🐶\n\nThis is a test collection that I am using to test various functionalities around bruno"
+ },
+ "brunoConfig": {
+ "version": "1",
+ "name": "bruno-testbench",
+ "type": "collection",
+ "proxy": {
+ "enabled": false,
+ "protocol": "http",
+ "hostname": "{{proxyHostname}}",
+ "port": 4000,
+ "auth": {
+ "enabled": false,
+ "username": "anoop"
+ },
+ "bypassProxy": ""
+ },
+ "scripts": {
+ "moduleWhitelist": [
+ "crypto",
+ "buffer",
+ "form-data"
+ ],
+ "filesystemAccess": {
+ "allow": true
+ }
+ },
+ "clientCertificates": {
+ "enabled": true,
+ "certs": []
+ },
+ "presets": {
+ "requestType": "http",
+ "requestUrl": "http://localhost:6000"
+ },
+ "ignore": [
+ "node_modules",
+ ".git"
+ ],
+ "size": 0.026633262634277344,
+ "filesCount": 96
+ }
+}
\ No newline at end of file
diff --git a/e2e-tests/import-tests/test-data/empty-file.json b/e2e-tests/import-tests/test-data/empty-file.json
new file mode 100644
index 000000000..e69de29bb
diff --git a/e2e-tests/import-tests/test-data/insomnia-malformed.json b/e2e-tests/import-tests/test-data/insomnia-malformed.json
new file mode 100644
index 000000000..8a6bcc0d8
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/insomnia-malformed.json
@@ -0,0 +1,19 @@
+{
+ "_type": "export",
+ "__export_format": 4,
+ "resources": [
+ {
+ "_id": "req_123",
+ "parentId": "wrk_456",
+ "url": "https://api.example.com/users",
+ "name": "Get Users",
+ "method": "GET",
+ "_type": "request"
+ },
+ {
+ "_id": "wrk_456",
+ "name": "Test Collection",
+ "_type": "workspace"
+ // Missing comma and closing bracket - malformed JSON
+ }
+ ]
diff --git a/e2e-tests/import-tests/test-data/insomnia-v4.json b/e2e-tests/import-tests/test-data/insomnia-v4.json
new file mode 100644
index 000000000..486e295f1
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/insomnia-v4.json
@@ -0,0 +1,113 @@
+{
+ "_type": "export",
+ "__export_format": 4,
+ "__export_date": "2025-01-01T12:00:00.000Z",
+ "__export_source": "insomnia.desktop.app:v10.3.1",
+ "resources": [
+ {
+ "_id": "req_fdedb34f7d5541d0aa7a917ce37ec067",
+ "parentId": "wrk_398c634c4fbc4774bcff39cbff44b31b",
+ "modified": 1689952276171,
+ "created": 1689951240510,
+ "url": "{{baseUrl}}/api/users",
+ "name": "Get Users",
+ "description": "Fetch all users from the API",
+ "method": "GET",
+ "body": {},
+ "parameters": [],
+ "headers": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ }
+ ],
+ "authentication": {},
+ "metaSortKey": -1689951414329,
+ "isPrivate": false,
+ "settingStoreCookies": true,
+ "settingSendCookies": true,
+ "settingDisableRenderRequestBody": false,
+ "settingEncodeUrl": true,
+ "settingRebuildPath": true,
+ "settingFollowRedirects": "global",
+ "_type": "request"
+ },
+ {
+ "_id": "req_c920d219404144e8bc6b6bd36f442974",
+ "parentId": "fld_ab2a1533f2be48c194883bf07d693292",
+ "modified": 1689952281595,
+ "created": 1689951281897,
+ "url": "{{baseUrl}}/api/auth/login",
+ "name": "Login User",
+ "description": "User authentication endpoint",
+ "method": "POST",
+ "body": {
+ "mimeType": "application/json",
+ "text": "{\n \"username\": \"admin\",\n \"password\": \"password123\"\n}"
+ },
+ "parameters": [],
+ "headers": [
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "authentication": {},
+ "metaSortKey": -1689951404530.5625,
+ "isPrivate": false,
+ "settingStoreCookies": true,
+ "settingSendCookies": true,
+ "settingDisableRenderRequestBody": false,
+ "settingEncodeUrl": true,
+ "settingRebuildPath": true,
+ "settingFollowRedirects": "global",
+ "_type": "request"
+ },
+ {
+ "_id": "fld_ab2a1533f2be48c194883bf07d693292",
+ "parentId": "wrk_398c634c4fbc4774bcff39cbff44b31b",
+ "modified": 1743683080329,
+ "created": 1743683080329,
+ "name": "Authentication",
+ "description": "Authentication related endpoints",
+ "environment": {},
+ "environmentPropertyOrder": null,
+ "metaSortKey": -1743683080329,
+ "_type": "request_group"
+ },
+ {
+ "_id": "wrk_398c634c4fbc4774bcff39cbff44b31b",
+ "parentId": null,
+ "modified": 1743678539806,
+ "created": 1743678539806,
+ "name": "Test API Collection v4",
+ "description": "Test collection for Insomnia v4 format",
+ "scope": "collection",
+ "_type": "workspace"
+ },
+ {
+ "_id": "env_93781eb62f074459bb67692112b76da0",
+ "parentId": "wrk_398c634c4fbc4774bcff39cbff44b31b",
+ "modified": 1743681240772,
+ "created": 1689951235312,
+ "name": "Base Environment",
+ "data": {
+ "baseUrl": "https://api.example.com"
+ },
+ "dataPropertyOrder": null,
+ "color": null,
+ "isPrivate": false,
+ "metaSortKey": 1689951235312,
+ "_type": "environment"
+ },
+ {
+ "_id": "jar_09963a0322c24b698ecd2f866ae9a6ab",
+ "parentId": "wrk_398c634c4fbc4774bcff39cbff44b31b",
+ "modified": 1689951235313,
+ "created": 1689951235313,
+ "name": "Default Jar",
+ "cookies": [],
+ "_type": "cookie_jar"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/e2e-tests/import-tests/test-data/insomnia-v5-invalid-missing-collection.yaml b/e2e-tests/import-tests/test-data/insomnia-v5-invalid-missing-collection.yaml
new file mode 100644
index 000000000..5214df1b2
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/insomnia-v5-invalid-missing-collection.yaml
@@ -0,0 +1,23 @@
+type: collection.insomnia.rest/5.0
+name: Invalid v5 Collection
+meta:
+ id: wrk_7faf891d273e4b7ea82bdbaa641ee17a
+ created: 1743683067888
+ modified: 1743683067888
+# Missing collection array - this should cause import to fail
+cookieJar:
+ name: Default Jar
+ meta:
+ id: jar_25f97142fa796ae37f7f4937c0ebf3a07869d0a8
+ created: 1743683067908
+ modified: 1743683833282
+ cookies: []
+environments:
+ name: Base Environment
+ meta:
+ id: env_25f97142fa796ae37f7f4937c0ebf3a07869d0a8
+ created: 1743683067895
+ modified: 1743683476058
+ isPrivate: false
+ data:
+ base_url: https://api.example.com
diff --git a/e2e-tests/import-tests/test-data/insomnia-v5.yaml b/e2e-tests/import-tests/test-data/insomnia-v5.yaml
new file mode 100644
index 000000000..09a2da4aa
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/insomnia-v5.yaml
@@ -0,0 +1,129 @@
+type: collection.insomnia.rest/5.0
+name: Test API Collection v5
+meta:
+ id: wrk_7faf891d273e4b7ea82bdbaa641ee17a
+ created: 1743683067888
+ modified: 1743683067888
+collection:
+ - name: API Tests
+ meta:
+ id: fld_ab2a1533f2be48c194883bf07d693292
+ created: 1743683080329
+ modified: 1743683080329
+ sortKey: -1743683080329
+ children:
+ - name: Authentication
+ meta:
+ id: fld_e7bcaad160254179a9c86e39a58c6893
+ created: 1743683088154
+ modified: 1743683090190
+ sortKey: -1743683090140
+ children:
+ - url: "{{ _.base_url }}/api/auth/login"
+ name: Login User
+ meta:
+ id: req_d48ab8553cff4eb486b816e064cf99a4
+ created: 1743683199141
+ modified: 1743683342872
+ isPrivate: false
+ sortKey: -1743683199141
+ method: POST
+ body:
+ mimeType: application/json
+ text: |-
+ {
+ "username": "testuser",
+ "password": "testpass123"
+ }
+ headers:
+ - name: Content-Type
+ value: application/json
+ - name: User-Agent
+ value: insomnia/10.3.1
+ settings:
+ renderRequestBody: true
+ encodeUrl: true
+ followRedirects: global
+ cookies:
+ send: true
+ store: true
+ rebuildPath: true
+ - url: "{{ _.base_url }}/api/users"
+ name: Get Users
+ meta:
+ id: req_0393b8ff4ee1454daddacdda33fd33ea
+ created: 1743683426423
+ modified: 1743683632735
+ isPrivate: false
+ description: Retrieve all users from the system
+ sortKey: -1743683429031
+ method: GET
+ headers:
+ - name: Authorization
+ value: Bearer {{ _.auth_token }}
+ - name: User-Agent
+ value: insomnia/10.3.1
+ settings:
+ renderRequestBody: true
+ encodeUrl: true
+ followRedirects: global
+ cookies:
+ send: true
+ store: true
+ rebuildPath: true
+ - name: Data Management
+ meta:
+ id: fld_4736de73a1634b16960fa9e90d78f868
+ created: 1743683403969
+ modified: 1743683403969
+ sortKey: -1743683403969
+ children:
+ - url: "{{ _.base_url }}/api/posts"
+ name: Create Post
+ meta:
+ id: req_10db7ec1332d4444aa551e70a1bfae33
+ created: 1743683795359
+ modified: 1743683832200
+ isPrivate: false
+ sortKey: -1743683429131
+ method: POST
+ body:
+ mimeType: application/json
+ text: |-
+ {
+ "title": "Test Post",
+ "content": "This is a test post content",
+ "author": "Test Author"
+ }
+ headers:
+ - name: Content-Type
+ value: application/json
+ - name: Authorization
+ value: Bearer {{ _.auth_token }}
+ - name: User-Agent
+ value: insomnia/10.3.1
+ settings:
+ renderRequestBody: true
+ encodeUrl: true
+ followRedirects: global
+ cookies:
+ send: true
+ store: true
+ rebuildPath: true
+cookieJar:
+ name: Default Jar
+ meta:
+ id: jar_25f97142fa796ae37f7f4937c0ebf3a07869d0a8
+ created: 1743683067908
+ modified: 1743683833282
+ cookies: []
+environments:
+ name: Base Environment
+ meta:
+ id: env_25f97142fa796ae37f7f4937c0ebf3a07869d0a8
+ created: 1743683067895
+ modified: 1743683476058
+ isPrivate: false
+ data:
+ base_url: https://api.example.com
+ auth_token: your_auth_token_here
diff --git a/e2e-tests/import-tests/test-data/invalid-json.json b/e2e-tests/import-tests/test-data/invalid-json.json
new file mode 100644
index 000000000..f3ca33078
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/invalid-json.json
@@ -0,0 +1 @@
+{ "invalid": json syntax }
diff --git a/e2e-tests/import-tests/test-data/invalid.txt b/e2e-tests/import-tests/test-data/invalid.txt
new file mode 100644
index 000000000..2defe8ade
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/invalid.txt
@@ -0,0 +1 @@
+This is not a valid collection file
diff --git a/e2e-tests/import-tests/test-data/openapi-comprehensive.yaml b/e2e-tests/import-tests/test-data/openapi-comprehensive.yaml
new file mode 100644
index 000000000..d55d149a9
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/openapi-comprehensive.yaml
@@ -0,0 +1,374 @@
+openapi: 3.0.3
+info:
+ title: Comprehensive API Test Collection
+ description: A comprehensive API for testing OpenAPI v3 imports with various features
+ version: 2.1.0
+ contact:
+ name: API Support
+ email: support@example.com
+ license:
+ name: MIT
+ url: https://opensource.org/licenses/MIT
+servers:
+ - url: https://api.example.com/v1
+ description: Production server
+ - url: https://staging-api.example.com/v1
+ description: Staging server
+ - url: http://localhost:3000/v1
+ description: Development server
+security:
+ - bearerAuth: []
+ - apiKey: []
+paths:
+ /users:
+ get:
+ summary: Get all users
+ description: Retrieve a paginated list of all users
+ tags:
+ - Users
+ parameters:
+ - name: page
+ in: query
+ description: Page number for pagination
+ schema:
+ type: integer
+ minimum: 1
+ default: 1
+ - name: limit
+ in: query
+ description: Number of items per page
+ schema:
+ type: integer
+ minimum: 1
+ maximum: 100
+ default: 20
+ - name: filter
+ in: query
+ description: Filter users by name or email
+ schema:
+ type: string
+ responses:
+ '200':
+ description: List of users retrieved successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ users:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+ pagination:
+ $ref: '#/components/schemas/Pagination'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ post:
+ summary: Create a new user
+ description: Create a new user account
+ tags:
+ - Users
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreateUserRequest'
+ responses:
+ '201':
+ description: User created successfully
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '409':
+ description: User already exists
+ /users/{userId}:
+ get:
+ summary: Get user by ID
+ description: Retrieve a specific user by their ID
+ tags:
+ - Users
+ parameters:
+ - name: userId
+ in: path
+ required: true
+ description: The user ID
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '200':
+ description: User retrieved successfully
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ put:
+ summary: Update user
+ description: Update an existing user
+ tags:
+ - Users
+ parameters:
+ - name: userId
+ in: path
+ required: true
+ description: The user ID
+ schema:
+ type: string
+ format: uuid
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateUserRequest'
+ responses:
+ '200':
+ description: User updated successfully
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ delete:
+ summary: Delete user
+ description: Delete a user account
+ tags:
+ - Users
+ parameters:
+ - name: userId
+ in: path
+ required: true
+ description: The user ID
+ schema:
+ type: string
+ format: uuid
+ responses:
+ '204':
+ description: User deleted successfully
+ '404':
+ $ref: '#/components/responses/NotFound'
+ /auth/login:
+ post:
+ summary: User login
+ description: Authenticate user and get access token
+ tags:
+ - Authentication
+ security: [] # No security required for login
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - email
+ - password
+ properties:
+ email:
+ type: string
+ format: email
+ password:
+ type: string
+ minLength: 8
+ responses:
+ '200':
+ description: Login successful
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ token:
+ type: string
+ expiresIn:
+ type: integer
+ user:
+ $ref: '#/components/schemas/User'
+ '401':
+ description: Invalid credentials
+ /posts:
+ get:
+ summary: Get all posts
+ description: Retrieve all blog posts
+ tags:
+ - Posts
+ parameters:
+ - name: author
+ in: query
+ description: Filter by author ID
+ schema:
+ type: string
+ - name: category
+ in: query
+ description: Filter by category
+ schema:
+ type: string
+ responses:
+ '200':
+ description: List of posts
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Post'
+ post:
+ summary: Create a new post
+ description: Create a new blog post
+ tags:
+ - Posts
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CreatePostRequest'
+ responses:
+ '201':
+ description: Post created successfully
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Post'
+components:
+ securitySchemes:
+ bearerAuth:
+ type: http
+ scheme: bearer
+ bearerFormat: JWT
+ apiKey:
+ type: apiKey
+ in: header
+ name: X-API-Key
+ schemas:
+ User:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ email:
+ type: string
+ format: email
+ name:
+ type: string
+ avatar:
+ type: string
+ format: uri
+ createdAt:
+ type: string
+ format: date-time
+ updatedAt:
+ type: string
+ format: date-time
+ CreateUserRequest:
+ type: object
+ required:
+ - email
+ - name
+ - password
+ properties:
+ email:
+ type: string
+ format: email
+ name:
+ type: string
+ minLength: 2
+ password:
+ type: string
+ minLength: 8
+ avatar:
+ type: string
+ format: uri
+ UpdateUserRequest:
+ type: object
+ properties:
+ name:
+ type: string
+ minLength: 2
+ avatar:
+ type: string
+ format: uri
+ Post:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ title:
+ type: string
+ content:
+ type: string
+ author:
+ $ref: '#/components/schemas/User'
+ category:
+ type: string
+ publishedAt:
+ type: string
+ format: date-time
+ createdAt:
+ type: string
+ format: date-time
+ CreatePostRequest:
+ type: object
+ required:
+ - title
+ - content
+ - category
+ properties:
+ title:
+ type: string
+ minLength: 5
+ content:
+ type: string
+ minLength: 10
+ category:
+ type: string
+ Pagination:
+ type: object
+ properties:
+ page:
+ type: integer
+ limit:
+ type: integer
+ total:
+ type: integer
+ totalPages:
+ type: integer
+ Error:
+ type: object
+ properties:
+ error:
+ type: string
+ message:
+ type: string
+ code:
+ type: integer
+ responses:
+ BadRequest:
+ description: Bad request
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ Unauthorized:
+ description: Unauthorized
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ NotFound:
+ description: Resource not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
diff --git a/e2e-tests/import-tests/test-data/openapi-invalid-version.yaml b/e2e-tests/import-tests/test-data/openapi-invalid-version.yaml
new file mode 100644
index 000000000..a8a496d98
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/openapi-invalid-version.yaml
@@ -0,0 +1,16 @@
+openapi: 2.0 # Invalid version - only v3 is supported
+info:
+ title: Invalid OpenAPI Version
+ description: This uses OpenAPI v2 which is not supported
+ version: 1.0.0
+host: api.example.com
+basePath: /v1
+schemes:
+ - https
+paths:
+ /users:
+ get:
+ summary: Get users
+ responses:
+ '200':
+ description: List of users
diff --git a/e2e-tests/import-tests/test-data/openapi-malformed.yaml b/e2e-tests/import-tests/test-data/openapi-malformed.yaml
new file mode 100644
index 000000000..432316f27
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/openapi-malformed.yaml
@@ -0,0 +1,16 @@
+openapi: 3.0.0
+info:
+ title: Malformed OpenAPI
+ version: 1.0.0
+paths:
+ /test:
+ get:
+ summary: Test endpoint
+ responses:
+ '200':
+ description: Success
+ # Missing closing quotes and malformed YAML
+ '400':
+ description: Bad request
+ malformed: yaml here
+ extra: indentation
diff --git a/e2e-tests/import-tests/test-data/openapi-missing-info.yaml b/e2e-tests/import-tests/test-data/openapi-missing-info.yaml
new file mode 100644
index 000000000..971860b4e
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/openapi-missing-info.yaml
@@ -0,0 +1,9 @@
+openapi: 3.0.0
+# Missing required info section
+paths:
+ /test:
+ get:
+ summary: Test endpoint
+ responses:
+ '200':
+ description: Success
diff --git a/e2e-tests/import-tests/test-data/openapi-simple.json b/e2e-tests/import-tests/test-data/openapi-simple.json
new file mode 100644
index 000000000..9aaa873e8
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/openapi-simple.json
@@ -0,0 +1,116 @@
+{
+ "openapi": "3.0.0",
+ "info": {
+ "title": "Simple Test API",
+ "description": "A simple API for basic OpenAPI testing",
+ "version": "1.0.0"
+ },
+ "servers": [
+ {
+ "url": "https://httpbin.org",
+ "description": "HTTPBin test server"
+ }
+ ],
+ "paths": {
+ "/get": {
+ "get": {
+ "summary": "HTTP GET test",
+ "description": "Test HTTP GET request",
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "args": {
+ "type": "object"
+ },
+ "headers": {
+ "type": "object"
+ },
+ "origin": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/post": {
+ "post": {
+ "summary": "HTTP POST test",
+ "description": "Test HTTP POST request",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "data": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Successful response",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "json": {
+ "type": "object"
+ },
+ "origin": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/status/{code}": {
+ "get": {
+ "summary": "Return status code",
+ "description": "Return a specific HTTP status code",
+ "parameters": [
+ {
+ "name": "code",
+ "in": "path",
+ "required": true,
+ "description": "HTTP status code to return",
+ "schema": {
+ "type": "integer",
+ "minimum": 100,
+ "maximum": 599
+ }
+ }
+ ],
+ "responses": {
+ "default": {
+ "description": "Returns the specified status code"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/e2e-tests/import-tests/test-data/postman-invalid-missing-info.json b/e2e-tests/import-tests/test-data/postman-invalid-missing-info.json
new file mode 100644
index 000000000..dd9a726af
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/postman-invalid-missing-info.json
@@ -0,0 +1,11 @@
+{
+ "item": [
+ {
+ "name": "Request without info",
+ "request": {
+ "method": "GET",
+ "url": "https://example.com"
+ }
+ }
+ ]
+}
diff --git a/e2e-tests/import-tests/test-data/postman-invalid-schema.json b/e2e-tests/import-tests/test-data/postman-invalid-schema.json
new file mode 100644
index 000000000..573976819
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/postman-invalid-schema.json
@@ -0,0 +1,7 @@
+{
+ "info": {
+ "name": "Invalid Schema Collection",
+ "schema": "https://schema.getpostman.com/json/collection/v999.0.0/collection.json"
+ },
+ "item": []
+}
diff --git a/e2e-tests/import-tests/test-data/postman-malformed.json b/e2e-tests/import-tests/test-data/postman-malformed.json
new file mode 100644
index 000000000..844fbf453
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/postman-malformed.json
@@ -0,0 +1,6 @@
+{
+ "info": {
+ "name": "Malformed Collection"
+ },
+ "item": "this should be an array, not a string"
+}
diff --git a/e2e-tests/import-tests/test-data/postman-v20.json b/e2e-tests/import-tests/test-data/postman-v20.json
new file mode 100644
index 000000000..02f38b945
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/postman-v20.json
@@ -0,0 +1,17 @@
+{
+ "info": {
+ "name": "Postman v2.0 Collection",
+ "description": "Test collection using Postman Collection Format v2.0",
+ "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json"
+ },
+ "item": [
+ {
+ "name": "Get Posts",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": "https://jsonplaceholder.typicode.com/posts"
+ }
+ }
+ ]
+}
diff --git a/e2e-tests/import-tests/test-data/postman-v21.json b/e2e-tests/import-tests/test-data/postman-v21.json
new file mode 100644
index 000000000..e922335a7
--- /dev/null
+++ b/e2e-tests/import-tests/test-data/postman-v21.json
@@ -0,0 +1,64 @@
+{
+ "info": {
+ "name": "Postman v2.1 Collection",
+ "description": "Test collection using Postman Collection Format v2.1",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+ "_postman_id": "12345678-1234-1234-1234-123456789012"
+ },
+ "item": [
+ {
+ "name": "Get Users",
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "Authorization",
+ "value": "Bearer {{token}}",
+ "type": "text"
+ }
+ ],
+ "url": {
+ "raw": "{{baseUrl}}/users",
+ "host": ["{{baseUrl}}"],
+ "path": ["users"],
+ "query": [
+ {
+ "key": "page",
+ "value": "1"
+ }
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Create User",
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/users",
+ "host": ["{{baseUrl}}"],
+ "path": ["users"]
+ }
+ },
+ "response": []
+ }
+ ],
+ "variable": [
+ {
+ "key": "baseUrl",
+ "value": "https://api.example.com"
+ }
+ ]
+}
diff --git a/packages/bruno-app/src/components/Modal/index.js b/packages/bruno-app/src/components/Modal/index.js
index 99bf1f89d..c52359711 100644
--- a/packages/bruno-app/src/components/Modal/index.js
+++ b/packages/bruno-app/src/components/Modal/index.js
@@ -9,7 +9,7 @@ const ModalHeader = ({ title, handleCancel, customHeader, hideClose }) => (
{customHeader ? customHeader : <>{title ?
{title}
: null}>}
{handleCancel && !hideClose ? (
-
handleCancel() : null}>
+
handleCancel() : null} data-test-id="modal-close-button">
×
) : null}
diff --git a/packages/bruno-app/src/components/Sidebar/TitleBar/index.js b/packages/bruno-app/src/components/Sidebar/TitleBar/index.js
index 65badf3aa..f3ec920a2 100644
--- a/packages/bruno-app/src/components/Sidebar/TitleBar/index.js
+++ b/packages/bruno-app/src/components/Sidebar/TitleBar/index.js
@@ -78,7 +78,7 @@ const TitleBar = () => {
) : null}
-