feat: implement item sorting for Postman export (#7581)

- Added functions to sort items by sequence and name, ensuring folders are prioritized over requests in the export output.
- Enhanced the `brunoToPostman` function to utilize the new sorting logic.
- Introduced comprehensive tests to validate the sorting behavior for folders and requests, including nested structures.
This commit is contained in:
Abhishek S Lal
2026-03-26 20:16:14 +05:30
committed by GitHub
parent c8d835ef4d
commit 03dcb6b7b9
2 changed files with 158 additions and 1 deletions

View File

@@ -2,6 +2,51 @@ import map from 'lodash/map';
import { deleteSecretsInEnvs, deleteUidsInEnvs, deleteUidsInItems, isItemARequest } from '../common';
import translateBruToPostman from '../utils/bruno-to-postman-translator';
const isItemAFolder = (item) => item.type === 'folder';
const sortItemsBySequence = (items) => [...items].sort((a, b) => a.seq - b.seq);
const sortByNameThenSequence = (items) => {
const isSeqValid = (seq) => Number.isFinite(seq) && Number.isInteger(seq) && seq > 0;
const alphabeticallySorted = [...items].sort((a, b) => a.name && b.name && a.name.localeCompare(b.name));
const withoutSeq = alphabeticallySorted.filter((f) => !isSeqValid(f['seq']));
const withSeq = alphabeticallySorted.filter((f) => isSeqValid(f['seq'])).sort((a, b) => a.seq - b.seq);
const sortedItems = withoutSeq;
withSeq.forEach((item) => {
const position = item.seq - 1;
const existingItem = withoutSeq[position];
const hasItemWithSameSeq = Array.isArray(existingItem)
? existingItem?.[0]?.seq === item.seq
: existingItem?.seq === item.seq;
if (hasItemWithSameSeq) {
const newGroup = Array.isArray(existingItem) ? [...existingItem, item] : [existingItem, item];
withoutSeq.splice(position, 1, newGroup);
} else {
withoutSeq.splice(position, 0, item);
}
});
return sortedItems.flat();
};
const sortItemsForExport = (items) => {
if (!items || !Array.isArray(items)) return [];
const folders = items.filter((item) => item && isItemAFolder(item));
const requests = items.filter((item) => item && isItemARequest(item));
const sortedFolders = sortByNameThenSequence(folders);
const sortedRequests = sortItemsBySequence(requests);
return [...sortedFolders, ...sortedRequests];
};
/**
* Transforms a given URL string into an object representing the protocol, host, path, query, and variables.
*
@@ -497,7 +542,9 @@ export const brunoToPostman = (collection) => {
return [];
}
return map(itemsArray, (item) => {
const sortedItems = sortItemsForExport(itemsArray);
return map(sortedItems, (item) => {
if (!item) {
return null;
}

View File

@@ -937,3 +937,113 @@ describe('brunoToPostman event handling', () => {
expect(nestedRequest.event[0].script.exec).toEqual(['console.log("nested pre");']);
});
});
describe('brunoToPostman item ordering', () => {
const makeRequest = (name, seq) => ({
type: 'http-request',
name,
seq,
request: {
method: 'GET',
url: 'https://example.com',
headers: [],
params: [],
body: { mode: 'none' },
auth: { mode: 'none' }
}
});
const makeFolder = (name, seq, items = []) => ({
type: 'folder',
name,
seq,
items
});
it('should place folders before requests in export output', () => {
const collection = {
items: [
makeRequest('Request A', 1),
makeFolder('Folder B'),
makeRequest('Request C', 2),
makeFolder('Folder A')
]
};
const result = brunoToPostman(collection);
const names = result.item.map((i) => i.name);
// Folders first (alphabetical since no seq), then requests (by seq)
expect(names[0]).toBe('Folder A');
expect(names[1]).toBe('Folder B');
expect(names[2]).toBe('Request A');
expect(names[3]).toBe('Request C');
});
it('should sort requests by seq ascending', () => {
const collection = {
items: [
makeRequest('Third', 3),
makeRequest('First', 1),
makeRequest('Second', 2)
]
};
const result = brunoToPostman(collection);
const names = result.item.map((i) => i.name);
expect(names).toEqual(['First', 'Second', 'Third']);
});
it('should sort folders by name then sequence', () => {
const collection = {
items: [
makeFolder('Gamma', undefined),
makeFolder('Alpha', undefined),
makeFolder('Beta', 1)
]
};
const result = brunoToPostman(collection);
const names = result.item.map((i) => i.name);
// Beta has seq=1, so it goes to position 0; Alpha and Gamma are alphabetical
expect(names[0]).toBe('Beta');
expect(names[1]).toBe('Alpha');
expect(names[2]).toBe('Gamma');
});
it('should sort items recursively within nested folders', () => {
const collection = {
items: [
makeFolder('Parent', 1, [
makeRequest('Nested C', 3),
makeFolder('Nested Folder', 1),
makeRequest('Nested A', 1)
])
]
};
const result = brunoToPostman(collection);
const parent = result.item[0];
const nestedNames = parent.item.map((i) => i.name);
// Folder first, then requests sorted by seq
expect(nestedNames).toEqual(['Nested Folder', 'Nested A', 'Nested C']);
});
it('should handle folders without seq (older collections) alphabetically', () => {
const collection = {
items: [
makeFolder('Zebra', undefined),
makeFolder('Apple', undefined),
makeFolder('Mango', undefined)
]
};
const result = brunoToPostman(collection);
const names = result.item.map((i) => i.name);
expect(names).toEqual(['Apple', 'Mango', 'Zebra']);
});
});