Files
bruno/packages/bruno-converters/tests/openapi/openapi-with-examples.spec.js
shubh-bruno 234d0df449 fix: storing status in example for yml file (#6876)
* fix: storing status in example for yml file

* fix: temporary check for tests

* fix: temporary check for tests

* fix: temporary check for tests

* fix: temporary check for tests

* fix: temporary check for tests

* fix: temporary check for tests

* fix: temporary check for tests

* fix: temporary check for tests

* fix: temporary check for tests

* fix: temporary check for tests

* fix: temporary check for tests

* fix: temporary check for tests

* fix: test cases for status and statusText

* chore: removed logs

* fix: test cases for response status and text

* fix: test cases for response status and text

* fix: resolved comments

* fix: openapi test import test cases

* chore: removed console logs

* fix: status type in response example while import/export of collection

* fix: postman to bruno import

---------

Co-authored-by: shubh-bruno <shubh-bruno@shubh-bruno.local>
2026-02-26 17:33:02 +05:30

812 lines
26 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, it, expect } from '@jest/globals';
import openApiToBruno from '../../src/openapi/openapi-to-bruno';
import * as fs from 'fs';
import * as path from 'path';
describe('OpenAPI with Examples', () => {
const openApiWithExamples = fs.readFileSync(path.resolve(__dirname, '../../../../tests/import/openapi/fixtures/openapi-with-examples.yaml'),
'utf8');
it('should import OpenAPI collection with response examples', () => {
const brunoCollection = openApiToBruno(openApiWithExamples);
expect(brunoCollection).toBeDefined();
expect(brunoCollection.name).toBe('API with Examples');
expect(brunoCollection.items).toHaveLength(3); // Three separate requests
// Test GET /users endpoint
const getUsersRequest = brunoCollection.items.find((item) => item.name === 'Get all users');
expect(getUsersRequest).toBeDefined();
expect(getUsersRequest.examples).toBeDefined();
expect(getUsersRequest.examples).toHaveLength(4);
// Check specific examples
const successExample = getUsersRequest.examples.find((ex) => ex.name === 'Success Response');
expect(successExample).toBeDefined();
expect(successExample.response.status).toEqual(200);
expect(successExample.response.statusText).toBe('OK');
expect(successExample.response.headers).toHaveLength(1);
expect(successExample.response.headers[0].name).toBe('Content-Type');
expect(successExample.response.headers[0].value).toBe('application/json');
expect(JSON.parse(successExample.response.body.content)).toEqual({
users: [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }
]
});
const emptyExample = getUsersRequest.examples.find((ex) => ex.name === 'Empty Response');
expect(emptyExample.response.status).toEqual(200);
expect(JSON.parse(emptyExample.response.body.content)).toEqual({ users: [] });
const validationErrorExample = getUsersRequest.examples.find((ex) => ex.name === 'Validation Error');
expect(validationErrorExample).toBeDefined();
expect(validationErrorExample.response.status).toEqual(400);
expect(validationErrorExample.response.statusText).toBe('Bad Request');
const serverErrorExample = getUsersRequest.examples.find((ex) => ex.name === 'Server Error');
expect(serverErrorExample).toBeDefined();
expect(serverErrorExample.response.status).toEqual(500);
expect(serverErrorExample.response.statusText).toBe('Internal Server Error');
// Test POST /users endpoint
const createUserRequest = brunoCollection.items.find((item) => item.name === 'Create a new user');
expect(createUserRequest).toBeDefined();
expect(createUserRequest.examples).toBeDefined();
expect(createUserRequest.examples).toHaveLength(4);
// Check response examples
const createdExample = createUserRequest.examples.find((ex) => ex.name === 'User Created (Valid User)');
expect(createdExample).toBeDefined();
expect(createdExample.response.status).toEqual(201);
expect(createdExample.response.statusText).toBe('Created');
expect(JSON.parse(createdExample.response.body.content)).toEqual({
id: 123,
name: 'John Doe',
email: 'john@example.com',
created_at: '2023-01-01T00:00:00Z'
});
});
it('should handle OpenAPI examples with different content types', () => {
const openApiWithDifferentContentTypes = `
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'API with Different Content Types'
paths:
/data:
get:
summary: 'Get data'
operationId: 'getData'
responses:
'200':
description: 'Successful response'
content:
application/json:
examples:
json_response:
summary: 'JSON Response'
value:
message: 'Hello World'
text/plain:
examples:
text_response:
summary: 'Text Response'
value: 'Hello World'
servers:
- url: 'https://api.example.com'
`;
const brunoCollection = openApiToBruno(openApiWithDifferentContentTypes);
const request = brunoCollection.items[0];
expect(request.examples).toHaveLength(2);
const jsonExample = request.examples.find((ex) => ex.name === 'JSON Response');
expect(jsonExample).toBeDefined();
expect(jsonExample.response.headers[0].value).toBe('application/json');
const textExample = request.examples.find((ex) => ex.name === 'Text Response');
expect(textExample).toBeDefined();
expect(textExample.response.headers[0].value).toBe('text/plain');
expect(textExample.response.body.content).toBe('Hello World');
expect(textExample.response.body.type).toBe('text');
});
it('should handle OpenAPI examples without summary or description', () => {
const openApiWithMinimalExamples = `
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'API with Minimal Examples'
paths:
/test:
get:
summary: 'Test endpoint'
operationId: 'test'
responses:
'200':
description: 'OK'
content:
application/json:
examples:
example1:
value:
message: 'test'
servers:
- url: 'https://api.example.com'
`;
const brunoCollection = openApiToBruno(openApiWithMinimalExamples);
const request = brunoCollection.items[0];
expect(request.examples).toHaveLength(1);
const example = request.examples[0];
expect(example.name).toBe('example1');
expect(example.description).toBe('');
expect(example.response.body.type).toBe('json');
expect(JSON.parse(example.response.body.content)).toEqual({ message: 'test' });
});
it('should create examples without specified request body, when response is present', () => {
const openApiWithoutExamples = `
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'API without Examples'
paths:
/test:
get:
summary: 'Test endpoint'
operationId: 'test'
responses:
'200':
description: 'OK'
content:
application/json:
schema:
type: object
servers:
- url: 'https://api.example.com'
`;
const brunoCollection = openApiToBruno(openApiWithoutExamples);
const request = brunoCollection.items[0];
expect(request.examples).toHaveLength(1);
const example = request.examples[0];
expect(example.name).toBe('200 Response');
expect(example.description).toBe('OK');
expect(example.response.body.type).toBe('json');
});
it('should support path-based grouping when specified', () => {
const openApiWithPathGrouping = `
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'API with Path Grouping'
paths:
/users:
get:
summary: 'Get all users'
operationId: 'getUsers'
responses:
'200':
description: 'OK'
content:
application/json:
examples:
success:
summary: 'Success Response'
value:
users: []
post:
summary: 'Create user'
operationId: 'createUser'
responses:
'201':
description: 'Created'
content:
application/json:
examples:
created:
summary: 'User Created'
value:
id: 123
/products:
get:
summary: 'Get all products'
operationId: 'getProducts'
responses:
'200':
description: 'OK'
content:
application/json:
examples:
success:
summary: 'Products Response'
value:
products: []
servers:
- url: 'https://api.example.com'
`;
// Test with path-based grouping
const brunoCollection = openApiToBruno(openApiWithPathGrouping, { groupBy: 'path' });
expect(brunoCollection).toBeDefined();
expect(brunoCollection.name).toBe('API with Path Grouping');
// Should have 2 folders: users and products (without leading slash)
expect(brunoCollection.items).toHaveLength(2);
const usersFolder = brunoCollection.items.find((item) => item.name === 'users');
expect(usersFolder).toBeDefined();
expect(usersFolder.type).toBe('folder');
expect(usersFolder.items).toHaveLength(2); // GET and POST /users
const productsFolder = brunoCollection.items.find((item) => item.name === 'products');
expect(productsFolder).toBeDefined();
expect(productsFolder.type).toBe('folder');
expect(productsFolder.items).toHaveLength(1); // GET /products
// Verify examples are preserved in path-based grouping
const getUsersRequest = usersFolder.items.find((item) => item.name === 'Get all users');
expect(getUsersRequest.examples).toBeDefined();
expect(getUsersRequest.examples).toHaveLength(1);
expect(getUsersRequest.examples[0].name).toBe('Success Response');
});
it('should default to tag-based grouping when no groupBy option is specified', () => {
const openApiWithTags = `
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'API with Tags'
paths:
/users:
get:
summary: 'Get all users'
operationId: 'getUsers'
tags: ['Users']
responses:
'200':
description: 'OK'
/products:
get:
summary: 'Get all products'
operationId: 'getProducts'
tags: ['Products']
responses:
'200':
description: 'OK'
servers:
- url: 'https://api.example.com'
`;
// Test with default grouping (tags)
const brunoCollection = openApiToBruno(openApiWithTags);
expect(brunoCollection).toBeDefined();
expect(brunoCollection.name).toBe('API with Tags');
// Should have 2 folders based on tags: Users and Products
expect(brunoCollection.items).toHaveLength(2);
const usersFolder = brunoCollection.items.find((item) => item.name === 'Users');
expect(usersFolder).toBeDefined();
expect(usersFolder.type).toBe('folder');
expect(usersFolder.items).toHaveLength(1); // GET /users
const productsFolder = brunoCollection.items.find((item) => item.name === 'Products');
expect(productsFolder).toBeDefined();
expect(productsFolder.type).toBe('folder');
expect(productsFolder.items).toHaveLength(1); // GET /products
});
describe('Request Body Examples', () => {
it('should match request body examples by key when response example key matches', () => {
const openApiWithMatchingKeys = `
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'API with Matching Keys'
paths:
/users:
post:
summary: 'Create user'
operationId: 'createUser'
requestBody:
required: true
content:
application/json:
examples:
valid_user:
summary: 'Valid User'
value:
name: 'John Doe'
email: 'john@example.com'
invalid_user:
summary: 'Invalid User'
value:
name: ''
email: 'invalid'
responses:
'201':
description: 'Created'
content:
application/json:
examples:
valid_user:
summary: 'User Created'
value:
id: 123
name: 'John Doe'
invalid_user:
summary: 'Validation Error'
value:
error: 'Invalid input'
servers:
- url: 'https://api.example.com'
`;
const brunoCollection = openApiToBruno(openApiWithMatchingKeys);
const request = brunoCollection.items[0];
expect(request.examples).toBeDefined();
expect(request.examples).toHaveLength(2);
// Check that matching keys are used
const validUserExample = request.examples.find((ex) => ex.name === 'User Created');
expect(validUserExample).toBeDefined();
expect(validUserExample.request.body.mode).toBe('json');
expect(JSON.parse(validUserExample.request.body.json)).toEqual({
name: 'John Doe',
email: 'john@example.com'
});
expect(JSON.parse(validUserExample.response.body.content)).toEqual({
id: 123,
name: 'John Doe'
});
const invalidUserExample = request.examples.find((ex) => ex.name === 'Validation Error');
expect(invalidUserExample).toBeDefined();
expect(JSON.parse(invalidUserExample.request.body.json)).toEqual({
name: '',
email: 'invalid'
});
expect(JSON.parse(invalidUserExample.response.body.content)).toEqual({
error: 'Invalid input'
});
});
it('should create all combinations when response example keys do not match request body examples', () => {
const openApiWithNonMatchingKeys = `
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'API with Non-Matching Keys'
paths:
/users:
post:
summary: 'Create user'
operationId: 'createUser'
requestBody:
required: true
content:
application/json:
examples:
valid_user:
summary: 'Valid User'
value:
name: 'John Doe'
email: 'john@example.com'
invalid_user:
summary: 'Invalid User'
value:
name: ''
email: 'invalid'
responses:
'201':
description: 'Created'
content:
application/json:
examples:
created:
summary: 'User Created'
value:
id: 123
400:
description: 'Bad Request'
content:
application/json:
examples:
error:
summary: 'Validation Error'
value:
error: 'Invalid input'
servers:
- url: 'https://api.example.com'
`;
const brunoCollection = openApiToBruno(openApiWithNonMatchingKeys);
const request = brunoCollection.items[0];
expect(request.examples).toBeDefined();
// Should have 4 examples: 2 response examples × 2 request body examples
expect(request.examples).toHaveLength(4);
// Check combinations for 201 response
const createdWithValid = request.examples.find((ex) => ex.name === 'User Created (Valid User)');
expect(createdWithValid).toBeDefined();
expect(createdWithValid.response.status).toEqual(201);
expect(JSON.parse(createdWithValid.request.body.json)).toEqual({
name: 'John Doe',
email: 'john@example.com'
});
const createdWithInvalid = request.examples.find((ex) => ex.name === 'User Created (Invalid User)');
expect(createdWithInvalid).toBeDefined();
expect(createdWithInvalid.response.status).toEqual(201);
expect(JSON.parse(createdWithInvalid.request.body.json)).toEqual({
name: '',
email: 'invalid'
});
// Check combinations for 400 response
const errorWithValid = request.examples.find((ex) => ex.name === 'Validation Error (Valid User)');
expect(errorWithValid).toBeDefined();
expect(errorWithValid.response.status).toEqual(400);
const errorWithInvalid = request.examples.find((ex) => ex.name === 'Validation Error (Invalid User)');
expect(errorWithInvalid).toBeDefined();
expect(errorWithInvalid.response.status).toEqual(400);
});
it('should use single request body example for all response examples', () => {
const openApiWithSingleRequestBody = `
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'API with Single Request Body'
paths:
/users:
post:
summary: 'Create user'
operationId: 'createUser'
requestBody:
required: true
content:
application/json:
example:
name: 'John Doe'
email: 'john@example.com'
responses:
'201':
description: 'Created'
content:
application/json:
examples:
created:
summary: 'User Created'
value:
id: 123
duplicate:
summary: 'Duplicate User'
value:
error: 'User already exists'
servers:
- url: 'https://api.example.com'
`;
const brunoCollection = openApiToBruno(openApiWithSingleRequestBody);
const request = brunoCollection.items[0];
expect(request.examples).toBeDefined();
expect(request.examples).toHaveLength(2);
// Both examples should have the same request body
const createdExample = request.examples.find((ex) => ex.name === 'User Created');
expect(createdExample).toBeDefined();
expect(createdExample.request.body.mode).toBe('json');
expect(JSON.parse(createdExample.request.body.json)).toEqual({
name: 'John Doe',
email: 'john@example.com'
});
const duplicateExample = request.examples.find((ex) => ex.name === 'Duplicate User');
expect(duplicateExample).toBeDefined();
expect(JSON.parse(duplicateExample.request.body.json)).toEqual({
name: 'John Doe',
email: 'john@example.com'
});
});
it('should use schema-based request body for all response examples', () => {
const openApiWithSchemaRequestBody = `
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'API with Schema Request Body'
paths:
/users:
post:
summary: 'Create user'
operationId: 'createUser'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- name
- email
properties:
name:
type: string
example: 'John Doe'
email:
type: string
format: email
example: 'john@example.com'
responses:
'201':
description: 'Created'
content:
application/json:
examples:
created:
summary: 'User Created'
value:
id: 123
error:
summary: 'Error Response'
value:
error: 'Something went wrong'
servers:
- url: 'https://api.example.com'
`;
const brunoCollection = openApiToBruno(openApiWithSchemaRequestBody);
const request = brunoCollection.items[0];
expect(request.examples).toBeDefined();
expect(request.examples).toHaveLength(2);
// Both examples should have request body generated from schema
const createdExample = request.examples.find((ex) => ex.name === 'User Created');
expect(createdExample).toBeDefined();
expect(createdExample.request.body.mode).toBe('json');
const requestBody = JSON.parse(createdExample.request.body.json);
expect(requestBody).toHaveProperty('name');
expect(requestBody).toHaveProperty('email');
const errorExample = request.examples.find((ex) => ex.name === 'Error Response');
expect(errorExample).toBeDefined();
expect(JSON.parse(errorExample.request.body.json)).toEqual(requestBody);
});
it('should handle request body examples with different content types', () => {
const openApiWithDifferentRequestBodyTypes = `
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'API with Different Request Body Types'
paths:
/data:
post:
summary: 'Post data'
operationId: 'postData'
requestBody:
required: true
content:
application/json:
examples:
json_data:
summary: 'JSON Data'
value:
message: 'Hello'
text/plain:
examples:
text_data:
summary: 'Text Data'
value: 'Hello World'
responses:
'200':
description: 'OK'
content:
application/json:
examples:
success:
summary: 'Success'
value:
status: 'ok'
servers:
- url: 'https://api.example.com'
`;
const brunoCollection = openApiToBruno(openApiWithDifferentRequestBodyTypes);
const request = brunoCollection.items[0];
expect(request.examples).toBeDefined();
// Should create combinations: 1 response × 2 request body examples = 2 examples
expect(request.examples).toHaveLength(2);
const jsonExample = request.examples.find((ex) => ex.name === 'Success (JSON Data)');
expect(jsonExample).toBeDefined();
expect(jsonExample.request.body.mode).toBe('json');
expect(JSON.parse(jsonExample.request.body.json)).toEqual({ message: 'Hello' });
const textExample = request.examples.find((ex) => ex.name === 'Success (Text Data)');
expect(textExample).toBeDefined();
expect(textExample.request.body.mode).toBe('text');
expect(textExample.request.body.text).toBe('Hello World');
});
it('should handle mixed matching and non-matching request body examples', () => {
const openApiWithMixedMatching = `
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'API with Mixed Matching'
paths:
/users:
post:
summary: 'Create user'
operationId: 'createUser'
requestBody:
required: true
content:
application/json:
examples:
valid_user:
summary: 'Valid User'
value:
name: 'John Doe'
email: 'john@example.com'
invalid_user:
summary: 'Invalid User'
value:
name: ''
email: 'invalid'
responses:
'201':
description: 'Created'
content:
application/json:
examples:
valid_user:
summary: 'User Created'
value:
id: 123
unmatched:
summary: 'Unmatched Response'
value:
id: 456
servers:
- url: 'https://api.example.com'
`;
const brunoCollection = openApiToBruno(openApiWithMixedMatching);
const request = brunoCollection.items[0];
expect(request.examples).toBeDefined();
// Should have: 1 matched (valid_user) + 2 combinations for unmatched (unmatched × 2 request body examples) = 3
expect(request.examples).toHaveLength(3);
// Matched example
const matchedExample = request.examples.find((ex) => ex.name === 'User Created');
expect(matchedExample).toBeDefined();
expect(JSON.parse(matchedExample.request.body.json)).toEqual({
name: 'John Doe',
email: 'john@example.com'
});
// Unmatched combinations
const unmatchedWithValid = request.examples.find((ex) => ex.name === 'Unmatched Response (Valid User)');
expect(unmatchedWithValid).toBeDefined();
const unmatchedWithInvalid = request.examples.find((ex) => ex.name === 'Unmatched Response (Invalid User)');
expect(unmatchedWithInvalid).toBeDefined();
});
it('should not create request body when no request body is defined', () => {
const openApiWithoutRequestBody = `
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'API without Request Body'
paths:
/users:
get:
summary: 'Get users'
operationId: 'getUsers'
responses:
'200':
description: 'OK'
content:
application/json:
examples:
success:
summary: 'Success'
value:
users: []
servers:
- url: 'https://api.example.com'
`;
const brunoCollection = openApiToBruno(openApiWithoutRequestBody);
const request = brunoCollection.items[0];
expect(request.examples).toBeDefined();
expect(request.examples).toHaveLength(1);
const example = request.examples[0];
expect(example.request.body.mode).toBe('none');
expect(example.request.body.json).toBeNull();
});
it('should handle request body with singular example and multiple response examples', () => {
const openApiWithSingularExample = `
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'API with Singular Example'
paths:
/users:
post:
summary: 'Create user'
operationId: 'createUser'
requestBody:
required: true
content:
application/json:
example:
name: 'Jane Doe'
email: 'jane@example.com'
responses:
'201':
description: 'Created'
content:
application/json:
examples:
created:
summary: 'User Created'
value:
id: 1
duplicate:
summary: 'Duplicate'
value:
id: 2
400:
description: 'Bad Request'
content:
application/json:
examples:
error:
summary: 'Error'
value:
error: 'Bad request'
servers:
- url: 'https://api.example.com'
`;
const brunoCollection = openApiToBruno(openApiWithSingularExample);
const request = brunoCollection.items[0];
expect(request.examples).toBeDefined();
expect(request.examples).toHaveLength(3);
// All examples should have the same request body
const requestBodyValue = { name: 'Jane Doe', email: 'jane@example.com' };
request.examples.forEach((example) => {
expect(example.request.body.mode).toBe('json');
expect(JSON.parse(example.request.body.json)).toEqual(requestBodyValue);
});
});
});
});