mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-26 06:05:45 +00:00
fix: circular recursion for openapi import (#4729)
This commit is contained in:
@@ -8,14 +8,22 @@ const ensureUrl = (url) => {
|
||||
return url.replace(/([^:])\/{2,}/g, '$1/');
|
||||
};
|
||||
|
||||
const buildEmptyJsonBody = (bodySchema) => {
|
||||
const buildEmptyJsonBody = (bodySchema, visited = new Map()) => {
|
||||
// Check for circular references
|
||||
if (visited.has(bodySchema)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Add this schema to visited map
|
||||
visited.set(bodySchema, true);
|
||||
|
||||
let _jsonBody = {};
|
||||
each(bodySchema.properties || {}, (prop, name) => {
|
||||
if (prop.type === 'object') {
|
||||
_jsonBody[name] = buildEmptyJsonBody(prop);
|
||||
_jsonBody[name] = buildEmptyJsonBody(prop, visited);
|
||||
} else if (prop.type === 'array') {
|
||||
if (prop.items && prop.items.type === 'object') {
|
||||
_jsonBody[name] = [buildEmptyJsonBody(prop.items)];
|
||||
_jsonBody[name] = [buildEmptyJsonBody(prop.items, visited)];
|
||||
} else {
|
||||
_jsonBody[name] = [];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
import { describe, it, expect } from '@jest/globals';
|
||||
import openApiToBruno from '../../../src/openapi/openapi-to-bruno';
|
||||
|
||||
describe('openapi-circular-references', () => {
|
||||
it('should handle simple circular references in schema correctly', async () => {
|
||||
const brunoCollection = openApiToBruno(circularRefsData);
|
||||
|
||||
expect(brunoCollection).toMatchObject(circularRefsOutput);
|
||||
});
|
||||
|
||||
it('should handle complex circular reference chains correctly', async () => {
|
||||
const brunoCollection = openApiToBruno(complexCircularRefsData);
|
||||
|
||||
expect(brunoCollection).toMatchObject(circularRefsOutput);
|
||||
});
|
||||
});
|
||||
|
||||
const circularRefsData = {
|
||||
"components": {
|
||||
"schemas": {
|
||||
"schema_1": {
|
||||
"additionalProperties": false,
|
||||
"description": "schema_1",
|
||||
"properties": {
|
||||
"conditions": {
|
||||
"$ref": "#/components/schemas/schema_1"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"schema_2": {
|
||||
"additionalProperties": false,
|
||||
"description": "schema_2",
|
||||
"properties": {
|
||||
"conditionGroup": {
|
||||
"description": "nested schema_1",
|
||||
"items": { "$ref": "#/components/schemas/schema_1" },
|
||||
"type": "array"
|
||||
},
|
||||
"operation": {
|
||||
"description": "operation",
|
||||
"enum": ["ANY", "ALL"],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"info": {
|
||||
"description": "circular reference openapi sample json spec",
|
||||
"title": "circular reference openapi sample json spec",
|
||||
"version": "0.1"
|
||||
},
|
||||
"openapi": "3.0.1",
|
||||
"paths": {
|
||||
"/": {
|
||||
"post": {
|
||||
"deprecated": false,
|
||||
"description": "echo ping api",
|
||||
"operationId": "echo ping",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/schema_1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "echo ping api",
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"example": "ping"
|
||||
}
|
||||
},
|
||||
"description": "Returned if the request is successful."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"servers": [{ "url": "https://echo.usebruno.com" }]
|
||||
};
|
||||
|
||||
// More complex circular reference test with a longer chain
|
||||
const complexCircularRefsData = {
|
||||
"components": {
|
||||
"schemas": {
|
||||
"schema_1": {
|
||||
"additionalProperties": false,
|
||||
"description": "schema_1",
|
||||
"properties": {
|
||||
"conditionGroup": {
|
||||
"description": "nested schema_1",
|
||||
"items": { "$ref": "#/components/schemas/schema_2" },
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"schema_2": {
|
||||
"additionalProperties": false,
|
||||
"description": "schema_2",
|
||||
"properties": {
|
||||
"conditionGroup": {
|
||||
"description": "nested schema_2",
|
||||
"items": { "$ref": "#/components/schemas/schema_3" },
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"schema_3": {
|
||||
"additionalProperties": false,
|
||||
"description": "schema_3",
|
||||
"properties": {
|
||||
"conditionGroup": {
|
||||
"description": "nested schema_3",
|
||||
"items": { "$ref": "#/components/schemas/schema_4" },
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"schema_4": {
|
||||
"additionalProperties": false,
|
||||
"description": "schema_4",
|
||||
"properties": {
|
||||
"conditionGroup": {
|
||||
"description": "nested schema_4",
|
||||
"items": { "$ref": "#/components/schemas/schema_5" },
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"schema_5": {
|
||||
"additionalProperties": false,
|
||||
"description": "schema_4",
|
||||
"properties": {
|
||||
"conditionGroup": {
|
||||
"description": "nested schema_5",
|
||||
"items": { "$ref": "#/components/schemas/schema_1" },
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"schema_6": {
|
||||
"additionalProperties": false,
|
||||
"description": "schema_3",
|
||||
"properties": {
|
||||
"conditionGroup": {
|
||||
"description": "nested schema_3",
|
||||
"items": { "$ref": "#/components/schemas/schema_1" },
|
||||
"type": "array"
|
||||
},
|
||||
"operation": {
|
||||
"description": "operation",
|
||||
"enum": ["ANY", "ALL"],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"info": {
|
||||
"description": "circular reference openapi sample json spec",
|
||||
"title": "circular reference openapi sample json spec",
|
||||
"version": "0.1"
|
||||
},
|
||||
"openapi": "3.0.1",
|
||||
"paths": {
|
||||
"/": {
|
||||
"post": {
|
||||
"deprecated": false,
|
||||
"description": "echo ping api",
|
||||
"operationId": "echo ping",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/schema_1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "echo ping api",
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"example": "ping"
|
||||
}
|
||||
},
|
||||
"description": "Returned if the request is successful."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"servers": [{ "url": "https://echo.usebruno.com" }]
|
||||
};
|
||||
|
||||
const circularRefsOutput = {
|
||||
"environments": [
|
||||
{
|
||||
"name": "Environment 1",
|
||||
"variables": [
|
||||
{
|
||||
"enabled": true,
|
||||
"name": "baseUrl",
|
||||
"secret": false,
|
||||
"type": "text",
|
||||
"value": "https://echo.usebruno.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"name": "echo ping",
|
||||
"type": "http-request",
|
||||
"request": {
|
||||
"url": "{{baseUrl}}/",
|
||||
"method": "POST",
|
||||
"auth": {
|
||||
"mode": "none",
|
||||
},
|
||||
"headers": [],
|
||||
"params": [],
|
||||
"body": {
|
||||
"mode": "json",
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
"name": "circular reference openapi sample json spec",
|
||||
"version": "1",
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from '@jest/globals';
|
||||
import openApiToBruno from '../../src/openapi/openapi-to-bruno';
|
||||
import openApiToBruno from '../../../src/openapi/openapi-to-bruno';
|
||||
|
||||
describe('openapi-collection', () => {
|
||||
it('should correctly import a valid OpenAPI file', async () => {
|
||||
Reference in New Issue
Block a user