diff --git a/packages/bruno-converters/src/postman/bruno-to-postman.js b/packages/bruno-converters/src/postman/bruno-to-postman.js index b63b00fb3..9db0e40ae 100644 --- a/packages/bruno-converters/src/postman/bruno-to-postman.js +++ b/packages/bruno-converters/src/postman/bruno-to-postman.js @@ -171,10 +171,13 @@ export const brunoToPostman = (collection) => { }; const generateHeaders = (headersArray) => { + if (!headersArray || !Array.isArray(headersArray)) { + return []; + } return map(headersArray, (item) => { return { - key: item.name, - value: item.value, + key: item.name || '', + value: item.value || '', disabled: !item.enabled, type: 'default' }; @@ -182,14 +185,21 @@ export const brunoToPostman = (collection) => { }; const generateBody = (body) => { + if (!body || !body.mode) { + return { + mode: 'raw', + raw: '' + }; + } + switch (body.mode) { case 'formUrlEncoded': return { mode: 'urlencoded', - urlencoded: map(body.formUrlEncoded, (bodyItem) => { + urlencoded: map(body.formUrlEncoded || [], (bodyItem) => { return { - key: bodyItem.name, - value: bodyItem.value, + key: bodyItem.name || '', + value: bodyItem.value || '', disabled: !bodyItem.enabled, type: 'default' }; @@ -198,10 +208,10 @@ export const brunoToPostman = (collection) => { case 'multipartForm': return { mode: 'formdata', - formdata: map(body.multipartForm, (bodyItem) => { + formdata: map(body.multipartForm || [], (bodyItem) => { return { - key: bodyItem.name, - value: bodyItem.value, + key: bodyItem.name || '', + value: bodyItem.value || '', disabled: !bodyItem.enabled, type: 'default' }; @@ -210,7 +220,7 @@ export const brunoToPostman = (collection) => { case 'json': return { mode: 'raw', - raw: body.json, + raw: body.json || '', options: { raw: { language: 'json' @@ -220,7 +230,7 @@ export const brunoToPostman = (collection) => { case 'xml': return { mode: 'raw', - raw: body.xml, + raw: body.xml || '', options: { raw: { language: 'xml' @@ -230,7 +240,7 @@ export const brunoToPostman = (collection) => { case 'text': return { mode: 'raw', - raw: body.text, + raw: body.text || '', options: { raw: { language: 'text' @@ -240,7 +250,12 @@ export const brunoToPostman = (collection) => { case 'graphql': return { mode: 'graphql', - graphql: body.graphql + graphql: body.graphql || {} + }; + default: + return { + mode: 'raw', + raw: '' }; } }; @@ -252,7 +267,7 @@ export const brunoToPostman = (collection) => { type: 'bearer', bearer: { key: 'token', - value: itemAuth.bearer.token, + value: itemAuth.bearer?.token || '', type: 'string' } }; @@ -262,12 +277,12 @@ export const brunoToPostman = (collection) => { basic: [ { key: 'password', - value: itemAuth.basic.password, + value: itemAuth.basic?.password || '', type: 'string' }, { key: 'username', - value: itemAuth.basic.username, + value: itemAuth.basic?.username || '', type: 'string' } ] @@ -279,12 +294,12 @@ export const brunoToPostman = (collection) => { apikey: [ { key: 'key', - value: itemAuth.apikey.key, + value: itemAuth.apikey?.key || '', type: 'string' }, { key: 'value', - value: itemAuth.apikey.value, + value: itemAuth.apikey?.value || '', type: 'string' } ] @@ -299,31 +314,43 @@ export const brunoToPostman = (collection) => { }; const generateRequestSection = (itemRequest) => { + if (!itemRequest) { + return {}; + } + const requestObject = { - method: itemRequest.method, + method: itemRequest.method || 'GET', header: generateHeaders(itemRequest.headers), auth: generateAuth(itemRequest.auth), - description: itemRequest.docs, + description: itemRequest.docs || '', // We sanitize the URL to make sure it's in the right format before passing it to the transformUrl func. This means changing backslashes to forward slashes and reducing multiple slashes to a single one, except in the protocol part. - url: transformUrl(sanitizeUrl(itemRequest.url), itemRequest.params) + url: transformUrl(sanitizeUrl(itemRequest.url || ''), itemRequest.params || []) }; - if (itemRequest.body.mode !== 'none') { + if (itemRequest.body && itemRequest.body.mode !== 'none') { requestObject.body = generateBody(itemRequest.body); } return requestObject; }; const generateItemSection = (itemsArray) => { + if (!itemsArray || !Array.isArray(itemsArray)) { + return []; + } + return map(itemsArray, (item) => { + if (!item) { + return null; + } + if (item.type === 'folder') { return { - name: item.name, - item: item.items.length ? generateItemSection(item.items) : [] + name: item.name || 'Untitled Folder', + item: item.items && item.items.length ? generateItemSection(item.items) : [] }; } else { return { - name: item.name, + name: item.name || 'Untitled Request', event: generateEventSection(item), request: generateRequestSection(item.request) }; diff --git a/packages/bruno-converters/tests/postman/bruno-to-postman.spec.js b/packages/bruno-converters/tests/postman/bruno-to-postman.spec.js index b153a98af..7d5018997 100644 --- a/packages/bruno-converters/tests/postman/bruno-to-postman.spec.js +++ b/packages/bruno-converters/tests/postman/bruno-to-postman.spec.js @@ -1,4 +1,4 @@ -import { sanitizeUrl, transformUrl } from "../../src/postman/bruno-to-postman"; +import { sanitizeUrl, transformUrl, brunoToPostman } from "../../src/postman/bruno-to-postman"; describe('transformUrl', () => { it('should handle basic URL with path variables', () => { @@ -78,4 +78,417 @@ describe('sanitizeUrl', () => { const expected = 'http://example.com/path/to/file'; expect(sanitizeUrl(input)).toBe(expected); }); -}) +}); + +describe('brunoToPostman null checks and fallbacks', () => { + it('should handle null or undefined headers', () => { + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + method: 'GET', + url: 'https://example.com', + headers: null + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].request.header).toEqual([]); + }); + + it('should handle null or undefined items in headers', () => { + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + method: 'GET', + url: 'https://example.com', + headers: [ + { name: null, value: 'test-value', enabled: true }, + { name: 'Content-Type', value: null, enabled: true } + ] + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].request.header).toEqual([ + { key: '', value: 'test-value', disabled: false, type: 'default' }, + { key: 'Content-Type', value: '', disabled: false, type: 'default' } + ]); + }); + + it('should handle null or undefined body', () => { + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + method: 'GET', + url: 'https://example.com', + body: null + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + // Should not have body property since we're checking for body before adding it + expect(result.item[0].request.body).toBeUndefined(); + }); + + it('should handle null or undefined body mode', () => { + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + method: 'GET', + url: 'https://example.com', + body: {} + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + // Should use default raw mode for undefined body mode + expect(result.item[0].request.body).toEqual({ + mode: 'raw', + raw: '' + }); + }); + + it('should handle null or undefined formUrlEncoded array', () => { + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + method: 'POST', + url: 'https://example.com', + body: { + mode: 'formUrlEncoded', + formUrlEncoded: null + } + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].request.body).toEqual({ + mode: 'urlencoded', + urlencoded: [] + }); + }); + + it('should handle null or undefined multipartForm array', () => { + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + method: 'POST', + url: 'https://example.com', + body: { + mode: 'multipartForm', + multipartForm: null + } + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].request.body).toEqual({ + mode: 'formdata', + formdata: [] + }); + }); + + it('should handle null or undefined items in form data', () => { + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + method: 'POST', + url: 'https://example.com', + body: { + mode: 'formUrlEncoded', + formUrlEncoded: [ + { name: null, value: 'test-value', enabled: true }, + { name: 'field', value: null, enabled: true } + ] + } + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].request.body.urlencoded).toEqual([ + { key: '', value: 'test-value', disabled: false, type: 'default' }, + { key: 'field', value: '', disabled: false, type: 'default' } + ]); + }); + + it('should handle null or undefined method', () => { + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + url: 'https://example.com', + method: null + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].request.method).toBe('GET'); + }); + + it('should handle null or undefined url', () => { + // Mock console.error to prevent it from logging during test + const originalConsoleError = console.error; + console.error = jest.fn(); + + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + method: 'GET', + url: null + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].request.url.raw).toBe(''); + }); + + it('should handle null or undefined params', () => { + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + method: 'GET', + url: 'https://example.com', + params: null + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].request.url.variable).toEqual([]); + }); + + it('should handle null or undefined docs', () => { + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + method: 'GET', + url: 'https://example.com', + docs: null + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].request.description).toBe(''); + }); + + it('should handle null or undefined folder name', () => { + const simpleCollection = { + items: [ + { + type: 'folder', + name: null, + items: [] + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].name).toBe('Untitled Folder'); + }); + + it('should handle null or undefined request name', () => { + const simpleCollection = { + items: [ + { + type: 'http-request', + name: null, + request: { + method: 'GET', + url: 'https://example.com' + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].name).toBe('Untitled Request'); + }); + + it('should handle null or undefined folder items', () => { + const simpleCollection = { + items: [ + { + type: 'folder', + name: 'Test Folder', + items: null + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].item).toEqual([]); + }); + + it('should handle null or undefined auth object', () => { + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + method: 'GET', + url: 'https://example.com', + auth: null + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].request.auth).toEqual({ type: 'noauth' }); + }); + + it('should handle missing token in bearer auth', () => { + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + method: 'GET', + url: 'https://example.com', + auth: { + mode: 'bearer', + bearer: { token: null } + } + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].request.auth).toEqual({ + type: 'bearer', + bearer: { + key: 'token', + value: '', + type: 'string' + } + }); + }); + + it('should handle missing username/password in basic auth', () => { + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + method: 'GET', + url: 'https://example.com', + auth: { + mode: 'basic', + basic: { username: null, password: undefined } + } + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].request.auth).toEqual({ + type: 'basic', + basic: [ + { + key: 'password', + value: '', + type: 'string' + }, + { + key: 'username', + value: '', + type: 'string' + } + ] + }); + }); + + it('should handle missing key/value in apikey auth', () => { + const simpleCollection = { + items: [ + { + name: 'Test Request', + type: 'http-request', + request: { + method: 'GET', + url: 'https://example.com', + auth: { + mode: 'apikey', + apikey: { key: null, value: undefined } + } + } + } + ] + }; + + const result = brunoToPostman(simpleCollection); + expect(result.item[0].request.auth).toEqual({ + type: 'apikey', + apikey: [ + { + key: 'key', + value: '', + type: 'string' + }, + { + key: 'value', + value: '', + type: 'string' + } + ] + }); + }); +});