From f1d527aa9ccf35a7e670f20205f2790c80506b36 Mon Sep 17 00:00:00 2001 From: Pragadesh-45 Date: Thu, 10 Apr 2025 18:05:17 +0545 Subject: [PATCH 01/10] feat: implement support for various authentication types in Postman to Bruno converter --- .../src/postman/postman-to-bruno.js | 230 ++++++++++-------- 1 file changed, 131 insertions(+), 99 deletions(-) diff --git a/packages/bruno-converters/src/postman/postman-to-bruno.js b/packages/bruno-converters/src/postman/postman-to-bruno.js index c22898d6f..1f61045d4 100644 --- a/packages/bruno-converters/src/postman/postman-to-bruno.js +++ b/packages/bruno-converters/src/postman/postman-to-bruno.js @@ -140,6 +140,110 @@ const importCollectionLevelVariables = (variables, requestObject) => { requestObject.vars.req = vars; }; +const processAuth = (auth, requestObject) => { + if (!auth || !auth.type || auth.type === 'noauth') { + return; + } + + let authValues = auth[auth.type]; + if (Array.isArray(authValues)) { + authValues = convertV21Auth(authValues); + } + + if (auth.type === 'basic') { + requestObject.auth.mode = 'basic'; + requestObject.auth.basic = { + username: authValues.username || '', + password: authValues.password || '' + }; + } else if (auth.type === 'bearer') { + requestObject.auth.mode = 'bearer'; + requestObject.auth.bearer = { + token: authValues.token || '' + }; + } else if (auth.type === 'awsv4') { + requestObject.auth.mode = 'awsv4'; + requestObject.auth.awsv4 = { + accessKeyId: authValues.accessKey || '', + secretAccessKey: authValues.secretKey || '', + sessionToken: authValues.sessionToken || '', + service: authValues.service || '', + region: authValues.region || '', + profileName: '' + }; + } else if (auth.type === 'apikey') { + requestObject.auth.mode = 'apikey'; + requestObject.auth.apikey = { + key: authValues.key || '', + value: authValues.value?.toString() || '', // Convert the value to a string as Postman's schema does not rigidly define the type of it, + placement: 'header' //By default we are placing the apikey values in headers! + }; + } else if (auth.type === 'digest') { + requestObject.auth.mode = 'digest'; + requestObject.auth.digest = { + username: authValues.username || '', + password: authValues.password || '' + }; + } else if (auth.type === 'oauth2') { + const findValueUsingKey = (key) => { + return auth?.oauth2?.find((v) => v?.key == key)?.value || ''; + }; + const oauth2GrantTypeMaps = { + authorization_code_with_pkce: 'authorization_code', + authorization_code: 'authorization_code', + client_credentials: 'client_credentials', + password_credentials: 'password_credentials' + }; + const grantType = oauth2GrantTypeMaps[findValueUsingKey('grant_type')] || 'authorization_code'; + + requestObject.auth.mode = 'oauth2'; + if (grantType === 'authorization_code') { + requestObject.auth.oauth2 = { + grantType: 'authorization_code', + authorizationUrl: findValueUsingKey('authUrl'), + callbackUrl: findValueUsingKey('redirect_uri'), + accessTokenUrl: findValueUsingKey('accessTokenUrl'), + refreshTokenUrl: findValueUsingKey('refreshTokenUrl'), + clientId: findValueUsingKey('clientId'), + clientSecret: findValueUsingKey('clientSecret'), + scope: findValueUsingKey('scope'), + state: findValueUsingKey('state'), + pkce: Boolean(findValueUsingKey('grant_type') == 'authorization_code_with_pkce'), + tokenPlacement: findValueUsingKey('addTokenTo') == 'header' ? 'header' : 'url', + credentialsPlacement: findValueUsingKey('client_authentication') == 'body' ? 'body' : 'basic_auth_header' + }; + } else if (grantType === 'password_credentials') { + requestObject.auth.oauth2 = { + grantType: 'password', + accessTokenUrl: findValueUsingKey('accessTokenUrl'), + refreshTokenUrl: findValueUsingKey('refreshTokenUrl'), + username: findValueUsingKey('username'), + password: findValueUsingKey('password'), + clientId: findValueUsingKey('clientId'), + clientSecret: findValueUsingKey('clientSecret'), + scope: findValueUsingKey('scope'), + state: findValueUsingKey('state'), + tokenPlacement: findValueUsingKey('addTokenTo') == 'header' ? 'header' : 'url', + credentialsPlacement: findValueUsingKey('client_authentication') == 'body' ? 'body' : 'basic_auth_header' + }; + } else if (grantType === 'client_credentials') { + requestObject.auth.oauth2 = { + grantType: 'client_credentials', + accessTokenUrl: findValueUsingKey('accessTokenUrl'), + refreshTokenUrl: findValueUsingKey('refreshTokenUrl'), + clientId: findValueUsingKey('clientId'), + clientSecret: findValueUsingKey('clientSecret'), + scope: findValueUsingKey('scope'), + state: findValueUsingKey('state'), + tokenPlacement: findValueUsingKey('addTokenTo') == 'header' ? 'header' : 'url', + credentialsPlacement: findValueUsingKey('client_authentication') == 'body' ? 'body' : 'basic_auth_header' + }; + } + } else { + console.warn('Unexpected auth.type', auth.type); + } +}; + const importPostmanV2CollectionItem = (brunoParent, item, parentAuth) => { brunoParent.items = brunoParent.items || []; const folderMap = {}; @@ -172,7 +276,10 @@ const importPostmanV2CollectionItem = (brunoParent, item, parentAuth) => { mode: 'none', basic: null, bearer: null, - awsv4: null + awsv4: null, + apikey: null, + oauth2: null, + digest: null }, headers: [], script: {}, @@ -181,6 +288,15 @@ const importPostmanV2CollectionItem = (brunoParent, item, parentAuth) => { } } }; + + // Folder level auth + if (i.auth) { + processAuth(i.auth, brunoFolderItem.root.request); + } else if (parentAuth) { + // Inherit parent auth if folder doesn't define its own + processAuth(parentAuth, brunoFolderItem.root.request); + } + if (i.item && i.item.length) { importPostmanV2CollectionItem(brunoFolderItem, i.item, i.auth ?? parentAuth); } @@ -221,7 +337,10 @@ const importPostmanV2CollectionItem = (brunoParent, item, parentAuth) => { mode: 'none', basic: null, bearer: null, - awsv4: null + awsv4: null, + apikey: null, + oauth2: null, + digest: null }, headers: [], params: [], @@ -356,102 +475,9 @@ const importPostmanV2CollectionItem = (brunoParent, item, parentAuth) => { }); }); + // Handle request-level auth or inherit from parent const auth = i.request.auth ?? parentAuth; - if (auth?.[auth.type] && auth.type !== 'noauth') { - let authValues = auth[auth.type]; - if (Array.isArray(authValues)) { - authValues = convertV21Auth(authValues); - } - if (auth.type === 'basic') { - brunoRequestItem.request.auth.mode = 'basic'; - brunoRequestItem.request.auth.basic = { - username: authValues.username, - password: authValues.password - }; - } else if (auth.type === 'bearer') { - brunoRequestItem.request.auth.mode = 'bearer'; - brunoRequestItem.request.auth.bearer = { - token: authValues.token - }; - } else if (auth.type === 'awsv4') { - brunoRequestItem.request.auth.mode = 'awsv4'; - brunoRequestItem.request.auth.awsv4 = { - accessKeyId: authValues.accessKey, - secretAccessKey: authValues.secretKey, - sessionToken: authValues.sessionToken, - service: authValues.service, - region: authValues.region, - profileName: '' - }; - } else if (auth.type === 'apikey'){ - brunoRequestItem.request.auth.mode = 'apikey'; - brunoRequestItem.request.auth.apikey = { - key: authValues.key, - value: authValues.value?.toString(), // Convert the value to a string as Postman's schema does not rigidly define the type of it, - placement: "header" //By default we are placing the apikey values in headers! - } - } else if (auth.type === 'oauth2'){ - const findValueUsingKey = (key) => { - return auth?.oauth2?.find(v => v?.key == key)?.value || '' - } - const oauth2GrantTypeMaps = { - 'authorization_code_with_pkce': 'authorization_code', - 'authorization_code': 'authorization_code', - 'client_credentials': 'client_credentials', - 'password_credentials': 'password_credentials' - } - const grantType = oauth2GrantTypeMaps[findValueUsingKey('grant_type')] || 'authorization_code'; - if (grantType) { - brunoRequestItem.request.auth.mode = 'oauth2'; - switch(grantType) { - case 'authorization_code': - brunoRequestItem.request.auth.oauth2 = { - grantType: 'authorization_code', - authorizationUrl: findValueUsingKey('authUrl'), - callbackUrl: findValueUsingKey('redirect_uri'), - accessTokenUrl: findValueUsingKey('accessTokenUrl'), - refreshTokenUrl: findValueUsingKey('refreshTokenUrl'), - clientId: findValueUsingKey('clientId'), - clientSecret: findValueUsingKey('clientSecret'), - scope: findValueUsingKey('scope'), - state: findValueUsingKey('state'), - pkce: Boolean(findValueUsingKey('grant_type') == 'authorization_code_with_pkce'), - tokenPlacement: findValueUsingKey('addTokenTo') == 'header' ? 'header' : 'url', - credentialsPlacement: findValueUsingKey('client_authentication') == 'body' ? 'body' : 'basic_auth_header' - }; - break; - case 'password_credentials': - brunoRequestItem.request.auth.oauth2 = { - grantType: 'password', - accessTokenUrl: findValueUsingKey('accessTokenUrl'), - refreshTokenUrl: findValueUsingKey('refreshTokenUrl'), - username: findValueUsingKey('username'), - password: findValueUsingKey('password'), - clientId: findValueUsingKey('clientId'), - clientSecret: findValueUsingKey('clientSecret'), - scope: findValueUsingKey('scope'), - state: findValueUsingKey('state'), - tokenPlacement: findValueUsingKey('addTokenTo') == 'header' ? 'header' : 'url', - credentialsPlacement: findValueUsingKey('client_authentication') == 'body' ? 'body' : 'basic_auth_header' - }; - break; - case 'client_credentials': - brunoRequestItem.request.auth.oauth2 = { - grantType: 'client_credentials', - accessTokenUrl: findValueUsingKey('accessTokenUrl'), - refreshTokenUrl: findValueUsingKey('refreshTokenUrl'), - clientId: findValueUsingKey('clientId'), - clientSecret: findValueUsingKey('clientSecret'), - scope: findValueUsingKey('scope'), - state: findValueUsingKey('state'), - tokenPlacement: findValueUsingKey('addTokenTo') == 'header' ? 'header' : 'url', - credentialsPlacement: findValueUsingKey('client_authentication') == 'body' ? 'body' : 'basic_auth_header' - }; - break; - } - } - } - } + processAuth(auth, brunoRequestItem.request); each(get(i, 'request.url.query'), (param) => { brunoRequestItem.request.params.push({ @@ -519,7 +545,10 @@ const importPostmanV2Collection = (collection) => { mode: 'none', basic: null, bearer: null, - awsv4: null + awsv4: null, + apikey: null, + oauth2: null, + digest: null }, headers: [], script: {}, @@ -533,10 +562,13 @@ const importPostmanV2Collection = (collection) => { importScriptsFromEvents(collection.event, brunoCollection.root.request); } - if (collection?.variable){ + if (collection?.variable) { importCollectionLevelVariables(collection.variable, brunoCollection.root.request); } + // Collection level auth + processAuth(collection.auth, brunoCollection.root.request); + importPostmanV2CollectionItem(brunoCollection, collection.item, collection.auth); return brunoCollection; From 73fa2e19e45ef2a89cad16996b7158645b5a18e5 Mon Sep 17 00:00:00 2001 From: Pragadesh-45 Date: Thu, 10 Apr 2025 18:26:29 +0545 Subject: [PATCH 02/10] fix: enhance error handling for unsupported Postman schema versions and invalid JSON format --- .../src/postman/postman-to-bruno.js | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/bruno-converters/src/postman/postman-to-bruno.js b/packages/bruno-converters/src/postman/postman-to-bruno.js index 1f61045d4..8ab9e9917 100644 --- a/packages/bruno-converters/src/postman/postman-to-bruno.js +++ b/packages/bruno-converters/src/postman/postman-to-bruno.js @@ -310,8 +310,8 @@ const importPostmanV2CollectionItem = (brunoParent, item, parentAuth) => { } else { if (i.request) { - if(!requestMethods.includes(i?.request?.method.toUpperCase())){ - console.warn("Unexpected request.method") + if (!requestMethods.includes(i?.request?.method.toUpperCase())) { + console.warn('Unexpected request.method', i?.request?.method); return; } @@ -589,28 +589,28 @@ const parsePostmanCollection = (collection) => { return importPostmanV2Collection(collection); } - throw new Error('Unknown postman schema'); + throw new Error('Unsupported Postman schema version. Only Postman Collection v2.0 and v2.1 are supported.'); } catch (err) { console.log(err); if (err instanceof Error) { throw err; } - throw new Error('Unable to parse the postman collection json file'); + throw new Error('Invalid Postman collection format. Please check your JSON file.'); } }; const postmanToBruno = (postmanCollection) => { - try { - const parsedPostmanCollection = parsePostmanCollection(postmanCollection); - const transformedCollection = transformItemsInCollection(parsedPostmanCollection); - const hydratedCollection = hydrateSeqInCollection(transformedCollection); - const validatedCollection = validateSchema(hydratedCollection); - return validatedCollection; - } catch(err) { - console.log(err); - throw new Error('Import collection failed'); - } + try { + const parsedPostmanCollection = parsePostmanCollection(postmanCollection); + const transformedCollection = transformItemsInCollection(parsedPostmanCollection); + const hydratedCollection = hydrateSeqInCollection(transformedCollection); + const validatedCollection = validateSchema(hydratedCollection); + return validatedCollection; + } catch (err) { + console.log(err); + throw new Error(`Import collection failed: ${err.message}`); + } }; export default postmanToBruno; \ No newline at end of file From 811c492bcea9da89e7ba526f5775d2243d4561d9 Mon Sep 17 00:00:00 2001 From: Pragadesh-45 Date: Thu, 10 Apr 2025 18:39:26 +0545 Subject: [PATCH 03/10] fix: improve URL construction by handling empty input and filtering invalid query parameters --- packages/bruno-converters/src/postman/postman-to-bruno.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/bruno-converters/src/postman/postman-to-bruno.js b/packages/bruno-converters/src/postman/postman-to-bruno.js index 8ab9e9917..d9f5c4cf3 100644 --- a/packages/bruno-converters/src/postman/postman-to-bruno.js +++ b/packages/bruno-converters/src/postman/postman-to-bruno.js @@ -43,6 +43,8 @@ const convertV21Auth = (array) => { }; const constructUrlFromParts = (url) => { + if (!url) return ''; + const { protocol = 'http', host, path, port, query, hash } = url || {}; const hostStr = Array.isArray(host) ? host.filter(Boolean).join('.') : host || ''; const pathStr = Array.isArray(path) ? path.filter(Boolean).join('/') : path || ''; @@ -50,7 +52,7 @@ const constructUrlFromParts = (url) => { const queryStr = query && Array.isArray(query) && query.length > 0 ? `?${query - .filter((q) => q.key) + .filter((q) => q && q.key) .map((q) => `${q.key}=${q.value || ''}`) .join('&')}` : ''; From 92925648e634675f580af52b09274d9c09c356d7 Mon Sep 17 00:00:00 2001 From: Pragadesh-45 Date: Thu, 10 Apr 2025 20:20:56 +0545 Subject: [PATCH 04/10] fix: OAuth2 key value retrieval --- packages/bruno-converters/src/postman/postman-to-bruno.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bruno-converters/src/postman/postman-to-bruno.js b/packages/bruno-converters/src/postman/postman-to-bruno.js index d9f5c4cf3..31b2f3929 100644 --- a/packages/bruno-converters/src/postman/postman-to-bruno.js +++ b/packages/bruno-converters/src/postman/postman-to-bruno.js @@ -188,7 +188,7 @@ const processAuth = (auth, requestObject) => { }; } else if (auth.type === 'oauth2') { const findValueUsingKey = (key) => { - return auth?.oauth2?.find((v) => v?.key == key)?.value || ''; + return authValues[key] || ''; }; const oauth2GrantTypeMaps = { authorization_code_with_pkce: 'authorization_code', From 3dcc12042f1fb98ffffea4d2630432b28e629e87 Mon Sep 17 00:00:00 2001 From: Pragadesh-45 Date: Thu, 10 Apr 2025 21:10:28 +0545 Subject: [PATCH 05/10] fix: add watch script for bruno-converters workspace --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index f7d4996dd..a63cdbed4 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ }, "scripts": { "setup": "node ./scripts/setup.js", + "watch:converters": "npm run watch --workspace=packages/bruno-converters", "dev": "concurrently --kill-others \"npm run dev:web\" \"npm run dev:electron\"", "dev:web": "npm run dev --workspace=packages/bruno-app", "build:web": "npm run build --workspace=packages/bruno-app", From 6a7750d354923d89d233fa4c622810b99017930f Mon Sep 17 00:00:00 2001 From: Pragadesh-45 Date: Tue, 22 Apr 2025 15:19:04 +0545 Subject: [PATCH 06/10] refactor: rename test files and update import paths for postman-to-bruno tests --- .../postman/{ => postman-to-bruno}/postman-to-bruno.spec.js | 2 +- .../postman-translations/postman-request.spec.js | 2 +- .../postman-translations/postman-response.spec.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename packages/bruno-converters/tests/postman/{ => postman-to-bruno}/postman-to-bruno.spec.js (99%) rename packages/bruno-converters/tests/postman/{ => postman-to-bruno}/postman-translations/postman-request.spec.js (89%) rename packages/bruno-converters/tests/postman/{ => postman-to-bruno}/postman-translations/postman-response.spec.js (91%) diff --git a/packages/bruno-converters/tests/postman/postman-to-bruno.spec.js b/packages/bruno-converters/tests/postman/postman-to-bruno/postman-to-bruno.spec.js similarity index 99% rename from packages/bruno-converters/tests/postman/postman-to-bruno.spec.js rename to packages/bruno-converters/tests/postman/postman-to-bruno/postman-to-bruno.spec.js index 2ad195eda..643a2bcf8 100644 --- a/packages/bruno-converters/tests/postman/postman-to-bruno.spec.js +++ b/packages/bruno-converters/tests/postman/postman-to-bruno/postman-to-bruno.spec.js @@ -1,5 +1,5 @@ import { describe, it, expect } from '@jest/globals'; -import postmanToBruno from '../../src/postman/postman-to-bruno'; +import postmanToBruno from '../../../src/postman/postman-to-bruno'; describe('postman-collection', () => { it('should correctly import a valid Postman collection file', async () => { diff --git a/packages/bruno-converters/tests/postman/postman-translations/postman-request.spec.js b/packages/bruno-converters/tests/postman/postman-to-bruno/postman-translations/postman-request.spec.js similarity index 89% rename from packages/bruno-converters/tests/postman/postman-translations/postman-request.spec.js rename to packages/bruno-converters/tests/postman/postman-to-bruno/postman-translations/postman-request.spec.js index 5b1305f73..3ee071640 100644 --- a/packages/bruno-converters/tests/postman/postman-translations/postman-request.spec.js +++ b/packages/bruno-converters/tests/postman/postman-to-bruno/postman-translations/postman-request.spec.js @@ -1,4 +1,4 @@ -const { default: postmanTranslation } = require("../../../src/postman/postman-translations"); +const { default: postmanTranslation } = require("../../../../src/postman/postman-translations"); describe('postmanTranslations - request commands', () => { test('should handle request commands', () => { diff --git a/packages/bruno-converters/tests/postman/postman-translations/postman-response.spec.js b/packages/bruno-converters/tests/postman/postman-to-bruno/postman-translations/postman-response.spec.js similarity index 91% rename from packages/bruno-converters/tests/postman/postman-translations/postman-response.spec.js rename to packages/bruno-converters/tests/postman/postman-to-bruno/postman-translations/postman-response.spec.js index 6e54af13b..4f365589c 100644 --- a/packages/bruno-converters/tests/postman/postman-translations/postman-response.spec.js +++ b/packages/bruno-converters/tests/postman/postman-to-bruno/postman-translations/postman-response.spec.js @@ -1,4 +1,4 @@ -const { default: postmanTranslation } = require("../../../src/postman/postman-translations"); +const { default: postmanTranslation } = require("../../../../src/postman/postman-translations"); describe('postmanTranslations - response commands', () => { test('should handle response commands', () => { From 049de84cbb30bee7b5ba21ce849e33cbd228ab72 Mon Sep 17 00:00:00 2001 From: Pragadesh-45 Date: Tue, 22 Apr 2025 18:00:49 +0545 Subject: [PATCH 07/10] test: refactor `postman-to-bruno.spec.js` by adding a simple collection --- .../postman-to-bruno/postman-to-bruno.spec.js | 840 +++--------------- 1 file changed, 146 insertions(+), 694 deletions(-) diff --git a/packages/bruno-converters/tests/postman/postman-to-bruno/postman-to-bruno.spec.js b/packages/bruno-converters/tests/postman/postman-to-bruno/postman-to-bruno.spec.js index 643a2bcf8..7eac3906c 100644 --- a/packages/bruno-converters/tests/postman/postman-to-bruno/postman-to-bruno.spec.js +++ b/packages/bruno-converters/tests/postman/postman-to-bruno/postman-to-bruno.spec.js @@ -8,727 +8,179 @@ describe('postman-collection', () => { }); }); +// Simple Collection (postman) +// ├── folder +// │ └── request (GET) +// └── request (GET) + const postmanCollection = { "info": { - "_postman_id": "0596d399-cfd2-4f8f-9869-65238eb40a45", - "name": "CRUD", - "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json", - "_exporter_id": "32111649", - "_collection_link": "https://www.postman.com/fudzi9/workspace/nodejs/collection/16541095-0596d399-cfd2-4f8f-9869-65238eb40a45?action=share&source=collection_link&creator=32111649" + "_postman_id": "7f91bbd8-cb97-41ac-8d0b-e1fcd8bb4ce9", + "name": "simple collection", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "21992467", + "_collection_link": "https://random-user-007.postman.co/workspace/testing~7523f559-3d5f-4c30-8315-3cb3c3ff98b7/collection/21992467-7f91bbd8-cb97-41ac-8d0b-e1fcd8bb4ce9?action=share&source=collection_link&creator=007" }, "item": [ { - "name": "GET", + "name": "folder", + "item": [ + { + "name": "request", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "https://usebruno.com", + "protocol": "https", + "host": [ + "usebruno", + "com" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "request", "request": { "method": "GET", "header": [], - "url": "https://node-task2.herokuapp.com/api/notes/" + "url": { + "raw": "https://usebruno.com", + "protocol": "https", + "host": [ + "usebruno", + "com" + ] + } }, - "response": [ - { - "name": "1.GET", - "originalRequest": { - "method": "GET", - "header": [], - "url": "https://node-task2.herokuapp.com/api/notes/" - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Server", - "value": "Cowboy" - }, - { - "key": "Connection", - "value": "keep-alive" - }, - { - "key": "X-Powered-By", - "value": "Express" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "2" - }, - { - "key": "Etag", - "value": "W/\"2-l9Fw4VUO7kr8CvBlt4zaMCqXZ0w\"" - }, - { - "key": "Date", - "value": "Tue, 06 Jul 2021 21:30:45 GMT" - }, - { - "key": "Via", - "value": "1.1 vegur" - } - ], - "cookie": [], - "body": "[]" - }, - { - "name": "3.GET", - "originalRequest": { - "method": "GET", - "header": [], - "url": "https://node-task2.herokuapp.com/api/notes/" - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Server", - "value": "Cowboy" - }, - { - "key": "Connection", - "value": "keep-alive" - }, - { - "key": "X-Powered-By", - "value": "Express" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "96" - }, - { - "key": "Etag", - "value": "W/\"60-ixboSJswZpL0hV7rJrY1IE5nQlM\"" - }, - { - "key": "Date", - "value": "Tue, 06 Jul 2021 21:58:32 GMT" - }, - { - "key": "Via", - "value": "1.1 vegur" - } - ], - "cookie": [], - "body": "[\n {\n \"id\": 1,\n \"title\": \"first\",\n \"content\": \"some text\",\n \"createdAt\": \"some date\",\n \"updatedAt\": \"some date\"\n }\n]" - }, - { - "name": "5.GET", - "originalRequest": { - "method": "GET", - "header": [], - "url": "https://node-task2.herokuapp.com/api/notes/" - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Server", - "value": "Cowboy" - }, - { - "key": "Connection", - "value": "keep-alive" - }, - { - "key": "X-Powered-By", - "value": "Express" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "192" - }, - { - "key": "Etag", - "value": "W/\"c0-rg+VAYKuV+nAzdAnddMXRNSM3tg\"" - }, - { - "key": "Date", - "value": "Tue, 06 Jul 2021 22:01:36 GMT" - }, - { - "key": "Via", - "value": "1.1 vegur" - } - ], - "cookie": [], - "body": "[\n {\n \"id\": 1,\n \"title\": \"first\",\n \"content\": \"some text\",\n \"createdAt\": \"some date\",\n \"updatedAt\": \"some date\"\n },\n {\n \"id\": 2,\n \"title\": \"second\",\n \"content\": \"some text\",\n \"createdAt\": \"some date\",\n \"updatedAt\": \"some date\"\n }\n]" - }, - { - "name": "7.GET", - "originalRequest": { - "method": "GET", - "header": [], - "url": "https://node-task2.herokuapp.com/api/notes/" - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Server", - "value": "Cowboy" - }, - { - "key": "Connection", - "value": "keep-alive" - }, - { - "key": "X-Powered-By", - "value": "Express" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "199" - }, - { - "key": "Etag", - "value": "W/\"c7-SBFGBh+BSdmKqSUIW4VDODIOnaI\"" - }, - { - "key": "Date", - "value": "Tue, 06 Jul 2021 22:38:51 GMT" - }, - { - "key": "Via", - "value": "1.1 vegur" - } - ], - "cookie": [], - "body": "[\n {\n \"id\": 2,\n \"title\": \"second\",\n \"content\": \"some text\",\n \"createdAt\": \"some date\",\n \"updatedAt\": \"some date\"\n },\n {\n \"id\": 1,\n \"title\": \"first changed\",\n \"content\": \"new text\",\n \"createdAt\": \"some date\",\n \"updatedAt\": \"some date\"\n }\n]" - }, - { - "name": "9.GET", - "originalRequest": { - "method": "GET", - "header": [], - "url": "https://node-task2.herokuapp.com/api/notes/" - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Server", - "value": "Cowboy" - }, - { - "key": "Connection", - "value": "keep-alive" - }, - { - "key": "X-Powered-By", - "value": "Express" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "103" - }, - { - "key": "Etag", - "value": "W/\"67-aR9NxSbB5ab73lSksdIWZNuQyq8\"" - }, - { - "key": "Date", - "value": "Tue, 06 Jul 2021 22:40:55 GMT" - }, - { - "key": "Via", - "value": "1.1 vegur" - } - ], - "cookie": [], - "body": "[\n {\n \"id\": 1,\n \"title\": \"first changed\",\n \"content\": \"new text\",\n \"createdAt\": \"some date\",\n \"updatedAt\": \"some date\"\n }\n]" - } - ] - }, - { - "name": "POST", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\"id\": 1, \"title\": \"first\", \"content\": \"some text\", \"createdAt\": \"some date\", \"updatedAt\": \"some date\"}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "https://node-task2.herokuapp.com/api/notes/" - }, - "response": [ - { - "name": "2.POST", - "originalRequest": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\"id\": 1, \"title\": \"first\", \"content\": \"some text\", \"createdAt\": \"some date\", \"updatedAt\": \"some date\"}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "https://node-task2.herokuapp.com/api/notes/" - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Server", - "value": "Cowboy" - }, - { - "key": "Connection", - "value": "keep-alive" - }, - { - "key": "X-Powered-By", - "value": "Express" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "123" - }, - { - "key": "Etag", - "value": "W/\"7b-Zs+ZSZvDSG55ZK90aBqfAjoxdAg\"" - }, - { - "key": "Date", - "value": "Tue, 06 Jul 2021 21:58:17 GMT" - }, - { - "key": "Via", - "value": "1.1 vegur" - } - ], - "cookie": [], - "body": "\"{\\\"id\\\": 1, \\\"title\\\": \\\"first\\\", \\\"content\\\": \\\"some text\\\", \\\"createdAt\\\": \\\"some date\\\", \\\"updatedAt\\\": \\\"some date\\\"}\"" - } - ] - }, - { - "name": "POST", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\"id\": 2, \"title\": \"second\", \"content\": \"some text\", \"createdAt\": \"some date\", \"updatedAt\": \"some date\"}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "https://node-task2.herokuapp.com/api/notes/" - }, - "response": [ - { - "name": "4.POST", - "originalRequest": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\"id\": 2, \"title\": \"second\", \"content\": \"some text\", \"createdAt\": \"some date\", \"updatedAt\": \"some date\"}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "https://node-task2.herokuapp.com/api/notes/" - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Server", - "value": "Cowboy" - }, - { - "key": "Connection", - "value": "keep-alive" - }, - { - "key": "X-Powered-By", - "value": "Express" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "124" - }, - { - "key": "Etag", - "value": "W/\"7c-vtAEN2HlKwhD6OkasvICg9Ni+g0\"" - }, - { - "key": "Date", - "value": "Tue, 06 Jul 2021 22:00:49 GMT" - }, - { - "key": "Via", - "value": "1.1 vegur" - } - ], - "cookie": [], - "body": "\"{\\\"id\\\": 2, \\\"title\\\": \\\"second\\\", \\\"content\\\": \\\"some text\\\", \\\"createdAt\\\": \\\"some date\\\", \\\"updatedAt\\\": \\\"some date\\\"}\"" - } - ] - }, - { - "name": "PUT", - "request": { - "method": "PUT", - "header": [], - "body": { - "mode": "raw", - "raw": "{\"id\": 1, \"title\": \"first changed\", \"content\": \"new text\", \"createdAt\": \"some date\", \"updatedAt\": \"some date\"}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "https://node-task2.herokuapp.com/api/notes/1" - }, - "response": [ - { - "name": "6.PUT", - "originalRequest": { - "method": "PUT", - "header": [], - "body": { - "mode": "raw", - "raw": "{\"id\": 1, \"title\": \"first changed\", \"content\": \"new text\", \"createdAt\": \"some date\", \"updatedAt\": \"some date\"}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": "https://node-task2.herokuapp.com/api/notes/1" - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Server", - "value": "Cowboy" - }, - { - "key": "Connection", - "value": "keep-alive" - }, - { - "key": "X-Powered-By", - "value": "Express" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "130" - }, - { - "key": "Etag", - "value": "W/\"82-QdzTirfdP1+K+iNOkslStk0OPpg\"" - }, - { - "key": "Date", - "value": "Tue, 06 Jul 2021 22:03:36 GMT" - }, - { - "key": "Via", - "value": "1.1 vegur" - } - ], - "cookie": [], - "body": "\"{\\\"id\\\": 1, \\\"title\\\": \\\"first changed\\\", \\\"content\\\": \\\"new text\\\", \\\"createdAt\\\": \\\"some date\\\", \\\"updatedAt\\\": \\\"some date\\\"}\"" - } - ] - }, - { - "name": "DELETE", - "request": { - "method": "DELETE", - "header": [], - "url": "https://node-task2.herokuapp.com/api/notes/2" - }, - "response": [ - { - "name": "8.DELETE", - "originalRequest": { - "method": "DELETE", - "header": [], - "url": "https://node-task2.herokuapp.com/api/notes/2" - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Server", - "value": "Cowboy" - }, - { - "key": "Connection", - "value": "keep-alive" - }, - { - "key": "X-Powered-By", - "value": "Express" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "23" - }, - { - "key": "Etag", - "value": "W/\"17-bCXlhEBJSVIeQ+m1i+6p7+rrNak\"" - }, - { - "key": "Date", - "value": "Tue, 06 Jul 2021 22:40:08 GMT" - }, - { - "key": "Via", - "value": "1.1 vegur" - } - ], - "cookie": [], - "body": "{\n \"success\": true,\n \"id\": 2\n}" - } - ] + "response": [] } ] }; +// Simple Collection (bruno) +// ├── folder +// │ └── request (GET) +// └── request (GET) + const expectedOutput = { - "name": "CRUD", + "name": "simple collection", "uid": "mockeduuidvalue123456", "version": "1", "items": [ - { + { + "uid": "mockeduuidvalue123456", + "name": "folder", + "type": "folder", + "items": [ + { "uid": "mockeduuidvalue123456", - "name": "GET", + "name": "request", "type": "http-request", "request": { - "url": "https://node-task2.herokuapp.com/api/notes/", - "method": "GET", - "auth": { - "mode": "none", - "basic": null, - "bearer": null, - "awsv4": null - }, - "headers": [], - "params": [], - "body": { - "mode": "none", - "json": null, - "text": null, - "xml": null, - "formUrlEncoded": [], - "multipartForm": [] - }, - "docs": "" - }, - "seq": 1 - }, - { - "uid": "mockeduuidvalue123456", - "name": "POST", - "type": "http-request", - "request": { - "url": "https://node-task2.herokuapp.com/api/notes/", - "method": "POST", - "auth": { - "mode": "none", - "basic": null, - "bearer": null, - "awsv4": null - }, - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\"id\": 1, \"title\": \"first\", \"content\": \"some text\", \"createdAt\": \"some date\", \"updatedAt\": \"some date\"}", - "text": null, - "xml": null, - "formUrlEncoded": [], - "multipartForm": [] - }, - "docs": "", - "script": { - "req": "" - }, - "tests": "" - }, - "seq": 2 - }, - { - "uid": "mockeduuidvalue123456", - "name": "POST_1", - "type": "http-request", - "request": { - "url": "https://node-task2.herokuapp.com/api/notes/", - "method": "POST", - "auth": { - "mode": "none", - "basic": null, - "bearer": null, - "awsv4": null - }, - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\"id\": 2, \"title\": \"second\", \"content\": \"some text\", \"createdAt\": \"some date\", \"updatedAt\": \"some date\"}", - "text": null, - "xml": null, - "formUrlEncoded": [], - "multipartForm": [] - }, - "docs": "" - }, - "seq": 3 - }, - { - "uid": "mockeduuidvalue123456", - "name": "PUT", - "type": "http-request", - "request": { - "url": "https://node-task2.herokuapp.com/api/notes/1", - "method": "PUT", - "auth": { - "mode": "none", - "basic": null, - "bearer": null, - "awsv4": null - }, - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\"id\": 1, \"title\": \"first changed\", \"content\": \"new text\", \"createdAt\": \"some date\", \"updatedAt\": \"some date\"}", - "text": null, - "xml": null, - "formUrlEncoded": [], - "multipartForm": [] - }, - "docs": "" - }, - "seq": 4 - }, - { - "uid": "mockeduuidvalue123456", - "name": "DELETE", - "type": "http-request", - "request": { - "url": "https://node-task2.herokuapp.com/api/notes/2", - "method": "DELETE", - "auth": { - "mode": "none", - "basic": null, - "bearer": null, - "awsv4": null - }, - "headers": [], - "params": [], - "body": { - "mode": "none", - "json": null, - "text": null, - "xml": null, - "formUrlEncoded": [], - "multipartForm": [] - }, - "docs": "" - }, - "seq": 5 - } - ], - "environments": [], - "root": { - "docs": "", - "meta": { - "name": "CRUD" - }, - "request": { - "auth": { + "url": "https://usebruno.com", + "method": "GET", + "auth": { "mode": "none", "basic": null, "bearer": null, - "awsv4": null + "awsv4": null, + "apikey": null, + "oauth2": null, + "digest": null + }, + "headers": [], + "params": [], + "body": { + "mode": "none", + "json": null, + "text": null, + "xml": null, + "formUrlEncoded": [], + "multipartForm": [] + }, + "docs": "" + }, + "seq": 1 + } + ], + "root": { + "docs": "", + "meta": { + "name": "folder" + }, + "request": { + "auth": { + "mode": "none", + "basic": null, + "bearer": null, + "awsv4": null, + "apikey": null, + "oauth2": null, + "digest": null }, "headers": [], "script": {}, "tests": "", "vars": {} + } } + }, + { + "uid": "mockeduuidvalue123456", + "name": "request", + "type": "http-request", + "request": { + "url": "https://usebruno.com", + "method": "GET", + "auth": { + "mode": "none", + "basic": null, + "bearer": null, + "awsv4": null, + "apikey": null, + "oauth2": null, + "digest": null + }, + "headers": [], + "params": [], + "body": { + "mode": "none", + "json": null, + "text": null, + "xml": null, + "formUrlEncoded": [], + "multipartForm": [] + }, + "docs": "" + }, + "seq": 1 + } + ], + "environments": [], + "root": { + "docs": "", + "meta": { + "name": "simple collection" + }, + "request": { + "auth": { + "mode": "none", + "basic": null, + "bearer": null, + "awsv4": null, + "apikey": null, + "oauth2": null, + "digest": null + }, + "headers": [], + "script": {}, + "tests": "", + "vars": {} + } } -}; \ No newline at end of file + }; \ No newline at end of file From 932d2b77dc54c3f12babea0bb7ac691dfc6815a9 Mon Sep 17 00:00:00 2001 From: Pragadesh-45 Date: Tue, 22 Apr 2025 19:10:28 +0545 Subject: [PATCH 08/10] test: add collection authentication tests for basic, bearer, API key, and digest auth --- .../postman-to-bruno/collection-auth.spec.js | 238 ++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 packages/bruno-converters/tests/postman/postman-to-bruno/collection-auth.spec.js diff --git a/packages/bruno-converters/tests/postman/postman-to-bruno/collection-auth.spec.js b/packages/bruno-converters/tests/postman/postman-to-bruno/collection-auth.spec.js new file mode 100644 index 000000000..ef98774de --- /dev/null +++ b/packages/bruno-converters/tests/postman/postman-to-bruno/collection-auth.spec.js @@ -0,0 +1,238 @@ +import { describe, it, expect } from '@jest/globals'; +import postmanToBruno from '../../../src/postman/postman-to-bruno'; + +describe('Collection Authentication', () => { + it('should handle basic auth at collection level', () => { + const postmanCollection = { + info: { + name: 'Collection level basic auth', + schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json' + }, + item: [], + auth: { + type: 'basic', + basic: [ + { + key: 'password', + value: 'testpass', + type: 'string' + }, + { + key: 'username', + value: 'testuser', + type: 'string' + } + ] + }, + event: [ + { + listen: 'prerequest', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + }, + { + listen: 'test', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + } + ] + }; + + const result = postmanToBruno(postmanCollection); + // console.log('result', JSON.stringify(result, null, 2)); + + expect(result.root.request.auth).toEqual({ + mode: 'basic', + basic: { + username: 'testuser', + password: 'testpass' + }, + bearer: null, + awsv4: null, + apikey: null, + oauth2: null, + digest: null + }); + }); + + it('should handle bearer token auth at collection level', () => { + const postmanCollection = { + info: { + name: 'Collection level bearer token', + schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json' + }, + item: [], + auth: { + type: 'bearer', + bearer: [ + { + key: 'token', + value: 'token', + type: 'string' + } + ] + }, + event: [ + { + listen: 'prerequest', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + }, + { + listen: 'test', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + } + ] + }; + + const result = postmanToBruno(postmanCollection); + // console.log('result', JSON.stringify(result, null, 2)); + + expect(result.root.request.auth).toEqual({ + mode: 'bearer', + basic: null, + bearer: { + token: 'token' + }, + awsv4: null, + apikey: null, + oauth2: null, + digest: null + }); + }); + + it('should handle API key auth at collection level', () => { + const postmanCollection = { + info: { + name: 'Collection level api key', + schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json' + }, + item: [], + auth: { + type: 'apikey', + apikey: [ + { + key: 'value', + value: 'apikey', + type: 'string' + }, + { + key: 'key', + value: 'apikey', + type: 'string' + } + ] + }, + event: [ + { + listen: 'prerequest', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + }, + { + listen: 'test', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + } + ] + }; + + const result = postmanToBruno(postmanCollection); + + expect(result.root.request.auth).toEqual({ + mode: 'apikey', + basic: null, + bearer: null, + awsv4: null, + apikey: { + key: 'apikey', + value: 'apikey', + placement: 'header' + }, + oauth2: null, + digest: null + }); + }); + + it('should handle digest auth at collection level', () => { + const postmanCollection = { + info: { + name: 'Collection level digest auth', + schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json' + }, + item: [], + auth: { + type: 'digest', + digest: [ + { + key: 'password', + value: 'digest auth', + type: 'string' + }, + { + key: 'username', + value: 'digest auth', + type: 'string' + }, + { + key: 'algorithm', + value: 'MD5', + type: 'string' + } + ] + }, + event: [ + { + listen: 'prerequest', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + }, + { + listen: 'test', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + } + ] + }; + + const result = postmanToBruno(postmanCollection); + + expect(result.root.request.auth).toEqual({ + mode: 'digest', + basic: null, + bearer: null, + awsv4: null, + apikey: null, + oauth2: null, + digest: { + username: 'digest auth', + password: 'digest auth' + } + }); + }); +}); From c7e8c07d40dbd25b7b9af3b75fe1aa28ff501c43 Mon Sep 17 00:00:00 2001 From: Pragadesh-45 Date: Tue, 22 Apr 2025 19:56:03 +0545 Subject: [PATCH 09/10] test: add folder authentication tests for basic, bearer, API key, and digest auth --- .../postman-to-bruno/folder-auth.spec.js | 247 ++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 packages/bruno-converters/tests/postman/postman-to-bruno/folder-auth.spec.js diff --git a/packages/bruno-converters/tests/postman/postman-to-bruno/folder-auth.spec.js b/packages/bruno-converters/tests/postman/postman-to-bruno/folder-auth.spec.js new file mode 100644 index 000000000..b403d22d8 --- /dev/null +++ b/packages/bruno-converters/tests/postman/postman-to-bruno/folder-auth.spec.js @@ -0,0 +1,247 @@ +import { describe, it, expect } from '@jest/globals'; +import postmanToBruno from '../../../src/postman/postman-to-bruno'; + +describe('Folder Authentication', () => { + it('should handle basic auth at folder level', () => { + const postmanCollection = { + info: { + name: 'Folder level basic auth', + schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json' + }, + item: [ + { + name: 'folder', + item: [], + auth: { + type: 'basic', + basic: [ + { + key: 'password', + value: 'testpass', + type: 'string' + }, + { + key: 'username', + value: 'testuser', + type: 'string' + } + ] + }, + event: [ + { + listen: 'prerequest', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + }, + { + listen: 'test', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + } + ] + } + ] + }; + + const result = postmanToBruno(postmanCollection); + + expect(result.items[0].root.request.auth).toEqual({ + mode: 'basic', + basic: { + username: 'testuser', + password: 'testpass' + }, + bearer: null, + awsv4: null, + apikey: null, + oauth2: null, + digest: null + }); + }); + + it('should handle bearer token auth at folder level', () => { + const postmanCollection = { + info: { + name: 'Folder level bearer token', + schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json' + }, + item: [ + { + name: 'folder', + item: [], + auth: { + type: 'bearer', + bearer: [ + { + key: 'token', + value: 'token', + type: 'string' + } + ] + }, + event: [ + { + listen: 'prerequest', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + }, + { + listen: 'test', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + } + ] + } + ] + }; + + const result = postmanToBruno(postmanCollection); + + expect(result.items[0].root.request.auth).toEqual({ + mode: 'bearer', + basic: null, + bearer: { token: 'token' }, + awsv4: null, + apikey: null, + oauth2: null, + digest: null + }); + }); + + it('should handle API key auth at folder level', () => { + const postmanCollection = { + info: { + name: 'Folder level API key', + schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json' + }, + item: [ + { + name: 'folder', + item: [], + auth: { + type: 'apikey', + apikey: [ + { + key: 'value', + value: 'apikey', + type: 'string' + }, + { + key: 'key', + value: 'apikey', + type: 'string' + } + ] + }, + event: [ + { + listen: 'prerequest', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + }, + { + listen: 'test', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + } + ] + } + ] + }; + + const result = postmanToBruno(postmanCollection); + + expect(result.items[0].root.request.auth).toEqual({ + mode: 'apikey', + basic: null, + bearer: null, + awsv4: null, + apikey: { key: 'apikey', value: 'apikey', placement: 'header' }, + oauth2: null, + digest: null + }); + }); + + it('should handle digest auth at folder level', () => { + const postmanCollection = { + info: { + name: 'Folder level digest auth', + schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json' + }, + item: [ + { + name: 'folder', + item: [], + auth: { + type: 'digest', + digest: [ + { + key: 'password', + value: 'digest pass', + type: 'string' + }, + { + key: 'username', + value: 'digest user', + type: 'string' + }, + { + key: 'algorithm', + value: 'MD5', + type: 'string' + } + ] + }, + event: [ + { + listen: 'prerequest', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + }, + { + listen: 'test', + script: { + type: 'text/javascript', + packages: {}, + exec: [''] + } + } + ] + } + ] + }; + + const result = postmanToBruno(postmanCollection); + + expect(result.items[0].root.request.auth).toEqual({ + mode: 'digest', + basic: null, + bearer: null, + awsv4: null, + apikey: null, + oauth2: null, + digest: { username: 'digest user', password: 'digest pass' } + }); + }); +}); From 46dab6e4746c1131ada545ed07f50768271e89e6 Mon Sep 17 00:00:00 2001 From: Pragadesh-45 Date: Tue, 22 Apr 2025 20:25:27 +0545 Subject: [PATCH 10/10] test: add request authentication tests for basic and bearer auth handling --- .../postman-to-bruno/request-auth.spec.js | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 packages/bruno-converters/tests/postman/postman-to-bruno/request-auth.spec.js diff --git a/packages/bruno-converters/tests/postman/postman-to-bruno/request-auth.spec.js b/packages/bruno-converters/tests/postman/postman-to-bruno/request-auth.spec.js new file mode 100644 index 000000000..a542a6b61 --- /dev/null +++ b/packages/bruno-converters/tests/postman/postman-to-bruno/request-auth.spec.js @@ -0,0 +1,134 @@ +import { describe, it, expect } from '@jest/globals'; +import postmanToBruno from '../../../src/postman/postman-to-bruno'; + +describe('Request Authentication', () => { + it('should handle basic auth at request level', () => { + const postmanCollection = { + info: { + name: 'Request Auth Collection', + schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json' + }, + item: [ + { + name: 'Basic Auth Request', + request: { + method: 'GET', + url: 'https://api.example.com/test', + auth: { + type: 'basic', + basic: [ + { key: 'username', value: 'requestuser' }, + { key: 'password', value: 'requestpass' } + ] + } + } + } + ] + }; + + const result = postmanToBruno(postmanCollection); + + expect(result.items[0].request.auth).toEqual({ + mode: 'basic', + basic: { + username: 'requestuser', + password: 'requestpass' + }, + bearer: null, + awsv4: null, + apikey: null, + oauth2: null, + digest: null + }); + }); + + it('should inherit folder auth when request has no auth', () => { + const postmanCollection = { + info: { + name: 'Inherit Request Auth Collection', + schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json' + }, + item: [ + { + name: 'Auth Folder', + auth: { + type: 'bearer', + bearer: [{ key: 'token', value: 'foldertoken' }] + }, + item: [ + { + name: 'No Auth Request', + request: { + method: 'GET', + url: 'https://api.example.com/test' + } + } + ] + } + ] + }; + + const result = postmanToBruno(postmanCollection); + + expect(result.items[0].items[0].request.auth).toEqual({ + mode: 'bearer', + basic: null, + bearer: { + token: 'foldertoken' + }, + awsv4: null, + apikey: null, + oauth2: null, + digest: null + }); + }); + + it('should override folder auth with request auth', () => { + const postmanCollection = { + info: { + name: 'Override Request Auth Collection', + schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json' + }, + item: [ + { + name: 'Auth Folder', + auth: { + type: 'basic', + basic: [ + { key: 'username', value: 'folderuser' }, + { key: 'password', value: 'folderpass' } + ] + }, + item: [ + { + name: 'Override Auth Request', + request: { + method: 'GET', + url: 'https://api.example.com/test', + auth: { + type: 'bearer', + bearer: [{ key: 'token', value: 'requesttoken' }] + } + } + } + ] + } + ] + }; + + const result = postmanToBruno(postmanCollection); + + expect(result.items[0].items[0].request.auth).toEqual({ + mode: 'bearer', + basic: null, + bearer: { + token: 'requesttoken' + }, + awsv4: null, + apikey: null, + oauth2: null, + digest: null + }); + }); + +});