feat: add path based grouping for openapi (#5638)

* feat: add path based grouping for openapi
This commit is contained in:
Pooja
2025-10-07 13:32:11 +05:30
committed by GitHub
parent 85319769a5
commit db6a639c15
17 changed files with 967 additions and 103 deletions

View File

@@ -0,0 +1,212 @@
{
"openapi": "3.0.0",
"info": {
"title": "Simple Test API",
"version": "1.0.0",
"description": "A simple API for testing groupBy functionality"
},
"servers": [
{
"url": "https://api.example.com",
"description": "Example server"
}
],
"paths": {
"/users": {
"get": {
"summary": "Get all users",
"operationId": "getUsers",
"tags": ["users"],
"responses": {
"200": {
"description": "List of users",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" }
}
}
}
}
}
}
}
},
"post": {
"summary": "Create user",
"operationId": "createUser",
"tags": ["users"],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"name": { "type": "string" }
}
}
}
}
},
"responses": {
"201": {
"description": "User created"
}
}
}
},
"/users/{id}": {
"get": {
"summary": "Get user by ID",
"operationId": "getUserById",
"tags": ["users"],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "User details"
}
}
},
"put": {
"summary": "Update user",
"operationId": "updateUser",
"tags": ["users"],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"name": { "type": "string" }
}
}
}
}
},
"responses": {
"200": {
"description": "User updated"
}
}
}
},
"/products": {
"get": {
"summary": "Get all products",
"operationId": "getProducts",
"tags": ["products"],
"responses": {
"200": {
"description": "List of products"
}
}
}
},
"/products/{id}": {
"get": {
"summary": "Get product by ID",
"operationId": "getProductById",
"tags": ["products"],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "Product details"
}
}
}
},
"/orders": {
"get": {
"summary": "Get all orders",
"operationId": "getOrders",
"tags": ["orders"],
"responses": {
"200": {
"description": "List of orders"
}
}
},
"post": {
"summary": "Create order",
"operationId": "createOrder",
"tags": ["orders"],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"userId": { "type": "integer" },
"productId": { "type": "integer" }
}
}
}
}
},
"responses": {
"201": {
"description": "Order created"
}
}
}
},
"/orders/{id}": {
"get": {
"summary": "Get order by ID",
"operationId": "getOrderById",
"tags": ["orders"],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "Order details"
}
}
}
}
}
}

View File

@@ -0,0 +1,78 @@
import { test, expect } from '../../../../playwright';
import { execSync } from 'child_process';
import fs from 'fs';
import path from 'path';
test.describe('OpenAPI Import GroupBy Tests', () => {
test('CLI: Import OpenAPI with tags grouping', async ({ createTmpDir }) => {
const outputDir = await createTmpDir('openapi-tags');
const jsonOutputPath = path.join(outputDir, 'petstore-tags.json');
// Run OpenAPI import with tags grouping using JSON output
const cliPath = path.resolve(__dirname, '../../../../packages/bruno-cli/bin/bru.js');
const specPath = path.resolve(__dirname, './fixtures/openapi.json');
const command = `node "${cliPath}" import openapi --source "${specPath}" --output-file "${jsonOutputPath}" --collection-name "Simple API (Tags)" --group-by tags`;
try {
execSync(command, { stdio: 'pipe' });
} catch (error) {
// Continue with test even if import fails
}
// Verify JSON file was created
expect(fs.existsSync(jsonOutputPath)).toBe(true);
// Read and verify collection structure
const jsonCollection = JSON.parse(fs.readFileSync(jsonOutputPath, 'utf8'));
expect(jsonCollection.name).toBe('Simple API (Tags)');
// Verify tags grouping creates folders by OpenAPI tags
const folders = jsonCollection.items.filter((item) => item.type === 'folder');
expect(folders.length).toBe(3);
const folderNames = folders.map((folder) => folder.name);
expect(folderNames).toContain('users');
expect(folderNames).toContain('products');
expect(folderNames).toContain('orders');
// Verify tags grouping doesn't create {id} folders
const hasIdFolders = folders.some((folder) => folder.items?.some((item) => item.name === '{id}'));
expect(hasIdFolders).toBe(false);
});
test('CLI: Import OpenAPI with path grouping', async ({ createTmpDir }) => {
const outputDir = await createTmpDir('openapi-path');
const jsonOutputPath = path.join(outputDir, 'petstore-path.json');
// Run OpenAPI import with path grouping using JSON output
const cliPath = path.resolve(__dirname, '../../../../packages/bruno-cli/bin/bru.js');
const specPath = path.resolve(__dirname, './fixtures/openapi.json');
const command = `node "${cliPath}" import openapi --source "${specPath}" --output-file "${jsonOutputPath}" --collection-name "Simple API (Path)" --group-by path`;
try {
execSync(command, { stdio: 'pipe' });
} catch (error) {
// Continue with test even if import fails
}
// Verify JSON file was created
expect(fs.existsSync(jsonOutputPath)).toBe(true);
// Read and verify collection structure
const jsonCollection = JSON.parse(fs.readFileSync(jsonOutputPath, 'utf8'));
expect(jsonCollection.name).toBe('Simple API (Path)');
// Verify path grouping creates folders by URL path structure
const folders = jsonCollection.items.filter((item) => item.type === 'folder');
expect(folders.length).toBe(3); // users, products, orders
const folderNames = folders.map((folder) => folder.name);
expect(folderNames).toContain('users');
expect(folderNames).toContain('products');
expect(folderNames).toContain('orders');
// Verify path grouping creates {id} folders for parameterized paths
const hasIdFolders = folders.some((folder) => folder.items?.some((item) => item.name === '{id}'));
expect(hasIdFolders).toBe(true);
});
});