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}
-