Package Exports
- bruno-api-schema-validator
- bruno-api-schema-validator/lib/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (bruno-api-schema-validator) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
bruno-api-schema-validator
A flexible JSON schema validation library for API testing with automatic schema generation and synchronous/asynchronous validation support. Perfect for Bruno API client and automated testing.
🚀 Features
- ✅ Auto-Detection - Automatically detects Bruno environment (no manual
bru.cwd()needed!) - ✅ Automatic Schema Generation - Generate JSON schemas from API responses
- ✅ Auto-Create on Validation - NEW! Use
createSchema: trueto auto-generate schemas during validation - ✅ Synchronous & Asynchronous Validation - Choose the right method for your use case
- ✅ Bruno API Testing Integration - Perfect for Bruno .bru test files
- ✅ Detailed Error Reporting - Know exactly what failed and where
- ✅ Array Validation - Validates all array items uniformly
- ✅ Flexible Schema Storage - Organize schemas by endpoint/version
- ✅ Draft-07 JSON Schema - Standards-compliant validation
- ✅ Zero Configuration - Works out of the box with sensible defaults
📦 Installation
npm install bruno-api-schema-validator🎯 Quick Start
Basic Usage
const SchemaValidator = require('bruno-api-schema-validator');
// For Bruno: Super simple - no parameters needed!
// Automatically uses bru.cwd() and 'api-schemas' folder
const validator = new SchemaValidator();
// Your API response from https://jsonplaceholder.typicode.com/users
const apiResponse = [
{
id: 1,
name: "Leanne Graham",
username: "Bret",
email: "Sincere@april.biz",
address: {
street: "Kulas Light",
suite: "Apt. 556",
city: "Gwenborough",
zipcode: "92998-3874"
}
}
];
// Step 1: Generate schema (one-time)
await validator.createJsonSchema('jsonplaceholder', 'Users', apiResponse);
// Step 2: Validate responses
const isValid = validator.validateJsonSchemaSync('jsonplaceholder', 'Users', apiResponse);
console.log(isValid); // trueBruno API Testing Integration
// In your .bru file: GetUsers.bru
// GET https://jsonplaceholder.typicode.com/users
tests {
const jsonData = res.getBody();
const SchemaValidator = require('bruno-api-schema-validator');
// Super simple - auto-detects Bruno environment!
const validator = new SchemaValidator();
test("Valid response JSON schema - Users", function(){
const result = validator.validateJsonSchemaSync(
'jsonplaceholder',
'Users',
jsonData,
{ verbose: true }
);
expect(result).to.equal(true);
});
test("Status code is 200", function () {
expect(res.getStatus()).to.equal(200);
});
test("Response is an array", function () {
expect(jsonData).to.be.an("array");
});
}Folder Structure:
bruno-collection/
├── api-schemas/ ← Default folder (auto-detected)
│ └── jsonplaceholder/
│ └── Users_schema.json
└── GetUsers.bru ← Your test file💡 Pro Tip: The validator automatically detects Bruno environment and uses
bru.cwd()internally! No manual path construction needed. Just callnew SchemaValidator()and you're done!
🆕 Auto-Create Schemas (New in v1.1.0!)
No schema file yet? No problem! Use createSchema: true to automatically generate schemas on first run:
tests {
const jsonData = res.getBody();
const SchemaValidator = require('bruno-api-schema-validator');
const validator = new SchemaValidator();
test("Auto-create and validate schema", function(){
// First run: Creates schema automatically
// Subsequent runs: Validates against existing schema
const result = validator.validateJsonSchemaSync(
'jsonplaceholder',
'Users',
jsonData,
{ createSchema: true } // 🎉 Magic happens here!
);
expect(result).to.equal(true);
});
}Benefits:
- ✅ No manual schema creation needed
- ✅ Automatically creates folder structure
- ✅ Perfect for new tests - just add
createSchema: true - ✅ Works in both Bruno and Node.js environments
📚 API Documentation
Constructor
new SchemaValidator([schemaPathOrFolderName])
Creates a new validator instance with automatic environment detection.
Parameters:
schemaPathOrFolderName(string, optional) - Default:'api-schemas'- In Bruno: Folder name within your collection (e.g.,
'api-schemas','my-schemas') - In Node.js: Full path to schema directory (absolute or relative)
- In Bruno: Folder name within your collection (e.g.,
Behavior:
- Bruno Environment: Automatically detects
bru.cwd()and constructs path - Node.js Environment: Treats parameter as full directory path
Examples:
// ========================================
// BRUNO USAGE (Automatic Detection!)
// ========================================
// Default: Uses 'api-schemas' folder in your Bruno collection
const validator = new SchemaValidator();
// Custom folder name in your Bruno collection
const validator = new SchemaValidator('my-custom-schemas');
// ========================================
// NODE.JS USAGE
// ========================================
// Absolute path
const validator = new SchemaValidator('C:/projects/my-api/api-schemas');
// Relative path with __dirname
const path = require('path');
const validator = new SchemaValidator(path.join(__dirname, 'api-schemas'));Methods
createJsonSchema(folderName, fileName, json)
Generates a JSON schema from a response and saves it to disk.
Parameters:
folderName(string) - Subdirectory path (e.g.,'vpp/Asset Manager')fileName(string) - Schema file base name (e.g.,'RegisteredAssets')json(object/array) - JSON data to generate schema from
Returns: Promise<string> - Path to created schema file
Example:
// Fetch data from JSONPlaceholder API
const response = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await response.json();
await validator.createJsonSchema('jsonplaceholder', 'Users', users);
// Creates: ./api-schemas/jsonplaceholder/Users_schema.jsonvalidateJsonSchemaSync(folderName, fileName, body, options)
Synchronously validates data against a schema. Use this in Bruno tests.
Parameters:
folderName(string) - Subdirectory pathfileName(string) - Schema file base namebody(object/array) - Data to validateoptions(object, optional):createSchema(boolean) - Auto-create schema if it doesn't exist. Default:falseverbose(boolean) - Show detailed errors. Default:truethrowOnError(boolean) - Throw exception on validation failure. Default:false
Returns: boolean - true if valid, false otherwise
Examples:
// Standard validation
const isValid = validator.validateJsonSchemaSync(
'jsonplaceholder',
'Users',
usersData,
{ verbose: true, throwOnError: false }
);
// Auto-create schema on first run (perfect for new tests!)
const isValid = validator.validateJsonSchemaSync(
'jsonplaceholder',
'Users',
usersData,
{ createSchema: true } // Creates schema if missing
);validateJsonSchema(folderName, fileName, body, options)
Asynchronously validates data against a schema. Use this in Node.js test frameworks (Jest, Mocha, Vitest) and automation scripts.
⚠️ Note: Bruno doesn't support async/await in tests. Use
validateJsonSchemaSync()for Bruno instead.
Parameters:
folderName(string) - Subdirectory pathfileName(string) - Schema file base namebody(object/array) - Data to validateoptions(object, optional):createSchema(boolean) - Create schema if it doesn't exist. Default:falseverbose(boolean) - Show detailed errors. Default:truethrowOnError(boolean) - Throw exception on validation failure. Default:false
Returns: Promise<boolean> - true if valid, false otherwise
Use Cases:
- ✅ Jest/Mocha/Vitest test suites
- ✅ CI/CD validation scripts
- ✅ Node.js automation scripts
- ✅ Integration test frameworks
- ❌ Bruno API tests (use sync version)
Example:
// Jest/Mocha test example
describe('API Schema Validation', () => {
it('should validate users endpoint', async () => {
const validator = new SchemaValidator('./api-schemas');
const response = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await response.json();
const isValid = await validator.validateJsonSchema(
'jsonplaceholder',
'Users',
users,
{ createSchema: true, verbose: true }
);
expect(isValid).toBe(true);
});
});
// CI/CD script example
async function validateContract() {
const validator = new SchemaValidator('./schemas');
const data = await fetchApiData();
await validator.validateJsonSchema('api/v1', 'Users', data, {
throwOnError: true // Fail CI if validation fails
});
}schemaExists(folderName, fileName)
Check if a schema file exists.
Parameters:
folderName(string) - Subdirectory pathfileName(string) - Schema file base name
Returns: boolean - true if schema exists
Example:
if (validator.schemaExists('api/v1', 'Users')) {
console.log('Schema exists!');
}getSchemaPath(folderName, fileName)
Get the full path to a schema file.
Parameters:
folderName(string) - Subdirectory pathfileName(string) - Schema file base name
Returns: string - Full path to schema file
Example:
const path = validator.getSchemaPath('api/v1', 'Users');
console.log(path); // ./api-schemas/api/v1/Users_schema.json📁 Folder Structure
When you use this package, schemas are organized like this:
your-project/
├── package.json
├── node_modules/
│ └── bruno-api-schema-validator/
├── api-schemas/ ← Your schemas here
│ ├── jsonplaceholder/
│ │ ├── Users_schema.json
│ │ ├── Posts_schema.json
│ │ └── Comments_schema.json
│ └── api/
│ └── v1/
│ ├── Products_schema.json
│ └── Orders_schema.json
└── tests/
└── api/
└── users.test.js🔄 How It Works
Schema Generation & Validation Flow
Step 1: First API Call - Generate Schema
┌─────────────────┐
│ API Response │
│ (JSON data) │
└────────┬────────┘
│
▼
createJsonSchema()
│
▼
┌─────────────────────────────────┐
│ RegisteredAssets_schema.json │
│ (Stored in api-schemas/) │
└─────────────────────────────────┘
Step 2: Subsequent Calls - Validate
┌─────────────────┐ ┌─────────────────────────┐
│ API Response │ │ Stored Schema File │
└────────┬────────┘ └───────────┬─────────────┘
│ │
└──────────┬────────────────────┘
▼
validateJsonSchemaSync()
│
┌──────────┴──────────┐
▼ ▼
✓ PASS ✗ FAIL
(Shows exactly
what's wrong)💡 Use Cases
1. API Contract Testing
Ensure your API maintains its contract across deployments.
test("API contract validation", function(){
const result = validator.validateJsonSchemaSync('api/v1', 'Users', jsonData);
expect(result).to.equal(true);
});2. Regression Detection
Catch breaking changes before they reach production.
// If API structure changes, test fails immediately
const isValid = validator.validateJsonSchemaSync('api/v1', 'Products', response);
if (!isValid) {
console.error('Breaking change detected in Products API!');
}3. Multi-Environment Testing
Same schema validates DEV, TEST, ACC, and PROD.
// Works across all environments
test("Schema consistent across environments", function(){
const result = validator.validateJsonSchemaSync('vpp/Asset Manager', 'Assets', jsonData);
expect(result).to.equal(true);
});4. Documentation as Code
Schema files serve as living API documentation.
# Your schema files document the API structure
cat api-schemas/api/v1/Users_schema.json🎨 Advanced Examples
Example 1: First-Time Schema Creation
const SchemaValidator = require('bruno-api-schema-validator');
// Super clean - no path construction needed!
const validator = new SchemaValidator();
// First time: Create schema from JSONPlaceholder API response
const response = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await response.json();
await validator.createJsonSchema('jsonplaceholder', 'Users', users);
console.log('✓ Schema created successfully');
// Now use it in tests
const isValid = validator.validateJsonSchemaSync('jsonplaceholder', 'Users', users);
console.log('Validation:', isValid); // trueExample 2: Multiple Endpoints
// Auto-detected environment
const validator = new SchemaValidator();
// Test multiple JSONPlaceholder endpoints with separate schemas
test("Users endpoint schema", async () => {
const users = await fetch('https://jsonplaceholder.typicode.com/users').then(r => r.json());
expect(validator.validateJsonSchemaSync('jsonplaceholder', 'Users', users)).toBe(true);
});
test("Posts endpoint schema", async () => {
const posts = await fetch('https://jsonplaceholder.typicode.com/posts').then(r => r.json());
expect(validator.validateJsonSchemaSync('jsonplaceholder', 'Posts', posts)).toBe(true);
});
test("Comments endpoint schema", async () => {
const comments = await fetch('https://jsonplaceholder.typicode.com/comments').then(r => r.json());
expect(validator.validateJsonSchemaSync('jsonplaceholder', 'Comments', comments)).toBe(true);
});Example 3: Custom Error Handling
// One line initialization
const validator = new SchemaValidator();
const response = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await response.json();
try {
const isValid = validator.validateJsonSchemaSync(
'jsonplaceholder',
'Users',
users,
{ verbose: true, throwOnError: true }
);
console.log('✓ Validation passed');
} catch (error) {
console.error('Validation failed:', error.message);
// Send alert, log to monitoring system, etc.
sendAlert('API schema validation failed');
}Example 4: Conditional Schema Creation
// Clean and simple
const validator = new SchemaValidator();
// Fetch users from JSONPlaceholder
const response = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await response.json();
// Create schema only if it doesn't exist
if (!validator.schemaExists('jsonplaceholder', 'Users')) {
await validator.createJsonSchema('jsonplaceholder', 'Users', users);
console.log('✓ New schema created for Users endpoint');
} else {
console.log('Schema already exists, validating...');
const isValid = validator.validateJsonSchemaSync('jsonplaceholder', 'Users', users);
console.log('Valid:', isValid);
}Example 5: Bruno - Complete Integration
// File: GetUsers.bru
meta {
name: Get Users
type: http
seq: 1
}
get {
url: https://jsonplaceholder.typicode.com/users
body: none
auth: none
}
docs {
This request retrieves a list of users from the JSONPlaceholder API.
}
tests {
const jsonData = res.getBody();
const SchemaValidator = require('bruno-api-schema-validator');
// One line - that's it!
const validator = new SchemaValidator();
// Schema validation test
test("Valid response JSON schema - Users", function(){
const result = validator.validateJsonSchemaSync(
'jsonplaceholder',
'Users',
jsonData,
{ verbose: true }
);
expect(result).to.equal(true);
});
// Traditional tests
test("Status code is 200", function () {
expect(res.getStatus()).to.equal(200);
});
test("Response is an array", function () {
expect(jsonData).to.be.an("array");
});
test("At least one user returned", function () {
expect(jsonData.length).to.be.greaterThan(0);
});
test("First user has required fields", function () {
expect(jsonData[0]).to.have.property('id');
expect(jsonData[0]).to.have.property('name');
expect(jsonData[0]).to.have.property('email');
});
}🐛 Troubleshooting
Issue: Schema file not found (ENOENT)
Error:
Error loading or validating schema file: ENOENT: no such file or directorySolution:
Ensure schema was created first:
await validator.createJsonSchema('api/v1', 'Users', sampleResponse);
Verify the schema path:
console.log(validator.getSchemaPath('api/v1', 'Users'));
Issue: Validation fails unexpectedly
Check the console output for detailed errors:
✗ SCHEMA VALIDATION ERRORS:
Schema: api/v1/Users
File: ./api-schemas/api/v1/Users_schema.json
1. At /0/id: must be string
Expected type: string
Actual value: 12345Solution: Fix the data type or update the schema if API changed legitimately.
Issue: Schema too strict
Problem: Schema doesn't allow null values or optional fields.
Solution: Manually edit the schema file:
{
"properties": {
"optionalField": {
"type": ["string", "null"]
}
},
"required": ["name", "id"]
}📊 Comparison: Before vs After
Before (Traditional Testing)
test("Check all properties", () => {
for (let i = 0; i < jsonData.length; i++) {
expect(jsonData[i]).to.have.keys('name', 'id', 'fullName', 'assetConfiguration');
expect(jsonData[i].name).to.be.a("string");
expect(jsonData[i].id).to.be.a("string");
expect(jsonData[i].fullName).to.be.a("string");
// ... 20+ more assertions
}
});Issues:
- 🔴 Verbose and repetitive
- 🔴 Doesn't catch unexpected fields
- 🔴 Hard to maintain
- 🔴 Manual effort for every field
After (Schema Validation)
test("Schema validation", function(){
const result = validator.validateJsonSchemaSync('api/v1', 'Assets', jsonData);
expect(result).to.equal(true);
});Benefits:
- ✅ One line of code
- ✅ Comprehensive validation
- ✅ Catches all structural changes
- ✅ Easy to maintain
🚀 Getting Started Checklist
- Install package:
npm install bruno-api-schema-validator - Create validator instance in your tests
- Generate schemas from good API responses
- Add schema validation tests to critical endpoints
- Run tests and verify they pass
- Commit schema files to version control
- Document schema organization in team wiki
- Set up CI/CD to run schema validation tests
📝 Best Practices
- Version Control: Commit schema files to Git
- Schema Organization: Use meaningful folder structures (e.g.,
api/v1,api/v2) - One Schema Per Endpoint: Don't reuse schemas unless endpoints are truly identical
- Update Schemas Carefully: Review changes before updating schemas
- Test First: Generate schemas from known-good responses
- Document Changes: Add comments to schema files when needed
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
MIT © Happy Testing!!
🔗 Links
📞 Support
For issues, questions, or suggestions:
- Open an issue on GitHub
- Contact: vikas.yadav@eneco.com
Made with ❤️ by Vikas