diff --git a/packages/bruno-converters/src/openapi/openapi-to-bruno.js b/packages/bruno-converters/src/openapi/openapi-to-bruno.js index ee7576c9eca..f911298452b 100644 --- a/packages/bruno-converters/src/openapi/openapi-to-bruno.js +++ b/packages/bruno-converters/src/openapi/openapi-to-bruno.js @@ -347,6 +347,12 @@ const BODY_TYPE_HANDLERS = [ } ]; +const getContentLevelExample = (bodyContent) => { + if (bodyContent.example !== undefined) return bodyContent.example; + const firstExample = Object.values(bodyContent.examples ?? {})[0]; + return firstExample?.value; +}; + /** * Extracts or generates an example value from an OpenAPI schema * Handles objects, arrays, primitives, and explicit examples @@ -733,7 +739,14 @@ const transformOpenapiRequestItem = (request, usedNames = new Set()) => { const content = get(_operationObject, 'requestBody.content', {}); const mimeType = Object.keys(content)[0]; const bodyContent = content[mimeType] || {}; - const bodySchema = bodyContent.schema; + let bodySchema = bodyContent.schema; + + if (bodySchema?.example === undefined) { + const contentExample = getContentLevelExample(bodyContent); + if (contentExample !== undefined) { + bodySchema = { ...bodySchema, example: contentExample }; + } + } // Normalize: lowercase (object keys may vary in case) const normalizedMimeType = typeof mimeType === 'string' ? mimeType.toLowerCase() : ''; diff --git a/packages/bruno-converters/tests/openapi/openapi-to-bruno/openapi-body.spec.js b/packages/bruno-converters/tests/openapi/openapi-to-bruno/openapi-body.spec.js index 24a319612cb..cbb8e39810d 100644 --- a/packages/bruno-converters/tests/openapi/openapi-to-bruno/openapi-body.spec.js +++ b/packages/bruno-converters/tests/openapi/openapi-to-bruno/openapi-body.spec.js @@ -909,3 +909,223 @@ paths: expect(request.request.body.json).toBe('[]'); }); }); + +describe('content-level example vs examples priority', () => { + it('should prefer singular example over examples (plural) and fall back to examples when example is absent', () => { + const spec = ` +openapi: "3.1.0" +info: + version: "1.0.0" + title: "Test" +servers: + - url: "https://api.example.com" +paths: + /both: + post: + summary: "Both example and examples" + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + example: + name: "from singular" + examples: + first: + value: + name: "from plural" + responses: + "200": + description: "OK" + /only-examples: + post: + summary: "Only examples plural" + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + examples: + first: + value: + name: "from plural" + responses: + "200": + description: "OK" + /schema-wins: + post: + summary: "Schema example wins over all" + requestBody: + content: + application/json: + schema: + type: object + example: + name: "from schema" + example: + name: "from content" + examples: + first: + value: + name: "from plural" + responses: + "200": + description: "OK" +`; + const result = openApiToBruno(spec); + + // When both example and examples exist, singular example wins + const bothBody = JSON.parse(result.items.find((i) => i.name === 'Both example and examples').request.body.json); + expect(bothBody.name).toBe('from singular'); + + // When only examples exists, it is used as fallback + const pluralBody = JSON.parse(result.items.find((i) => i.name === 'Only examples plural').request.body.json); + expect(pluralBody.name).toBe('from plural'); + + // schema.example priority over both content-level example and examples + const schemaBody = JSON.parse(result.items.find((i) => i.name === 'Schema example wins over all').request.body.json); + expect(schemaBody.name).toBe('from schema'); + }); +}); + +describe('content-level example values for each body type', () => { + const spec = ` +openapi: "3.1.0" +info: + version: "1.0.0" + title: "Test" +servers: + - url: "https://api.example.com" +paths: + /json: + post: + summary: "JSON body" + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + example: + name: "json example" + responses: + "200": + description: "OK" + /xml: + post: + summary: "XML body" + requestBody: + content: + application/xml: + schema: + type: object + properties: + name: + type: string + example: + name: "xml example" + responses: + "200": + description: "OK" + /text: + post: + summary: "Text body" + requestBody: + content: + text/plain: + schema: + type: string + example: "plain text example" + responses: + "200": + description: "OK" + /form: + post: + summary: "Form body" + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + username: + type: string + example: + username: "form_user" + responses: + "200": + description: "OK" + /multipart: + post: + summary: "Multipart body" + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + desc: + type: string + example: + desc: "multipart desc" + responses: + "200": + description: "OK" + /sparql: + post: + summary: "SPARQL body" + requestBody: + content: + application/sparql-query: + schema: + type: string + example: "SELECT * WHERE { ?s ?p ?o }" + responses: + "200": + description: "OK" +`; + + it('should import content-level example for JSON body', () => { + const result = openApiToBruno(spec); + const body = JSON.parse(result.items.find((i) => i.name === 'JSON body').request.body.json); + expect(body.name).toBe('json example'); + }); + + it('should import content-level example for XML body', () => { + const result = openApiToBruno(spec); + const xml = result.items.find((i) => i.name === 'XML body').request.body.xml; + expect(xml).toContain('xml example'); + }); + + it('should import content-level example for text/plain body', () => { + const result = openApiToBruno(spec); + const text = result.items.find((i) => i.name === 'Text body').request.body.text; + expect(text).toBe('plain text example'); + }); + + it('should import content-level example for form-urlencoded body', () => { + const result = openApiToBruno(spec); + const field = result.items.find((i) => i.name === 'Form body').request.body.formUrlEncoded.find((f) => f.name === 'username'); + expect(field.value).toBe('form_user'); + }); + + it('should import content-level example for multipart body', () => { + const result = openApiToBruno(spec); + const field = result.items.find((i) => i.name === 'Multipart body').request.body.multipartForm.find((f) => f.name === 'desc'); + expect(field.value).toBe('multipart desc'); + }); + + it('should import content-level example for SPARQL body', () => { + const result = openApiToBruno(spec); + const sparql = result.items.find((i) => i.name === 'SPARQL body').request.body.sparql; + expect(sparql).toBe('SELECT * WHERE { ?s ?p ?o }'); + }); +});