mirror of
https://github.com/usebruno/bruno.git
synced 2025-05-05 15:32:58 +00:00
fix: Add null checks and fallbacks to Bruno-to-Postman
converter to… (#4525)
This commit is contained in:
parent
220da6b58e
commit
317ccccfc6
@ -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)
|
||||
};
|
||||
|
@ -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'
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user