Documentation Index Fetch the complete documentation index at: https://mintlify.com/usebruno/bruno/llms.txt
Use this file to discover all available pages before exploring further.
Bruno provides a comprehensive assertion system for validating API responses. Use assertions to verify status codes, check response data, validate schemas, and ensure your APIs behave correctly.
Assertion Methods
Bruno supports two ways to write assertions:
Inline Assertions Quick assertions in the assert block
Test Scripts Complex validations using JavaScript and Chai
Inline Assertions
Inline assertions provide a simple, declarative way to validate responses without writing JavaScript.
Basic Syntax
assert {
res.status: eq 200
res.body.message: eq Authentication successful
res.body.user.email: contains @example.com
}
Assertion Operators
Bruno supports a rich set of operators for different validation needs:
Equal to res.body.string: eq foo
res.body.number: eq 123
res.body.null: eq null
res.body.true: eq true
res.body.false: eq false
Not equal to res.body.status: neq pending
res.body.count: neq 0
Greater than res.body.age: gt 18
res.body.score: gt 0
Greater than or equal to res.body.quantity: gte 1
res.body.percentage: gte 0
Less than res.body.price: lt 100
res.body.timeout: lt 5000
Less than or equal to res.body.maxUsers: lte 1000
res.getResponseTime(): lte 2000
Value is in list res.body.status: in active,pending,completed
res.body.type: in [user, admin, guest]
res.body.code: in 200,201,204
Value is not in list res.body.status: notIn deleted,archived
res.body.role: notIn [banned, suspended]
String/array contains value res.body.message: contains success
res.body.email: contains @example.com
res.body: contains form-data-value
String/array does not contain value res.body.message: notContains error
res.body.description: notContains deprecated
String starts with value res.body.url: startsWith https://
res.body.prefix: startsWith API_
String ends with value res.body.filename: endsWith .pdf
res.body.email: endsWith @example.com
Matches regular expression res.body.email: matches ^[^\s@]+@[^\s@]+\.[^\s@]+$
res.body.phone: matches /^\d{3}-\d{3}-\d{4}$/
res.body.uuid: matches [0-9a-f]{8}-[0-9a-f]{4}
Does not match regular expression res.body.username: notMatches \s
res.body.code: notMatches [^a-zA-Z0-9]
Length equals value res.body.items: length 10
res.body.code: length 6
res.body.apiKey: length 32
Value is between min and max (inclusive) res.body.age: between 18,65
res.body.price: between 9.99,99.99
res.getResponseTime(): between 0,2000
Value is null res.body.deletedAt: isNull
res.body.optional: isNull
Value is undefined res.body.nonexistent: isUndefined
Value is not undefined res.body.userId: isDefined
res.body.email: isDefined
Value is a JSON object res.body.metadata: isJson
res.body.config: isJson
Value is a number res.body.count: isNumber
res.body.price: isNumber
Value is a string res.body.name: isString
res.body.email: isString
Value is a boolean res.body.isActive: isBoolean
res.body.verified: isBoolean
Value is an array res.body.items: isArray
res.body.tags: isArray
Value is empty (string, array, or object) res.body.description: isEmpty
res.body.items: isEmpty
Value is not empty res.body.message: isNotEmpty
res.body.results: isNotEmpty
Value is truthy (true, non-zero number, non-empty string) res.body.success: isTruthy
Value is falsy (false, 0, empty string, null, undefined)
Real-World Examples
String Assertions
Number Assertions
Boolean & Null Assertions
Complex Validations
assert {
res.body.string: eq foo
res.body.string: eq 'foo'
res.body.string: eq "foo"
res.body.stringWithSQuotes: eq "'foo'"
res.body.stringWithDQuotes: eq '"foo"'
res.body.stringWithCurlyBraces: eq "{foo}"
res.body.stringWithDoubleCurlyBraces: eq "{{foobar}}"
}
Test Scripts
For complex validations, use test scripts with the full power of JavaScript and Chai assertion library.
Basic Test Structure
test ( "test description" , function () {
// Your assertions here
expect ( res . getStatus ()). to . equal ( 200 );
expect ( res . getBody ()). to . have . property ( 'success' , true );
});
Chai Assertions
Bruno includes the Chai assertion library with three assertion styles:
Expect (BDD)
Assert (TDD)
test ( "validate response structure" , function () {
const data = res . getBody ();
// Equality
expect ( res . getStatus ()). to . equal ( 200 );
expect ( data . name ). to . eql ( 'John Doe' );
// Type checking
expect ( data ). to . be . an ( 'object' );
expect ( data . items ). to . be . an ( 'array' );
expect ( data . count ). to . be . a ( 'number' );
// Properties
expect ( data ). to . have . property ( 'id' );
expect ( data ). to . have . property ( 'email' , 'user@example.com' );
expect ( data ). to . include . keys ( 'id' , 'name' , 'email' );
// Arrays
expect ( data . roles ). to . include ( 'user' );
expect ( data . roles ). to . have . lengthOf ( 3 );
expect ( data . items ). to . be . empty ;
// Strings
expect ( data . message ). to . contain ( 'success' );
expect ( data . email ). to . match ( / ^ [ ^ \s@ ] + @/ );
// Numbers
expect ( data . age ). to . be . above ( 18 );
expect ( data . score ). to . be . within ( 0 , 100 );
// Negation
expect ( data . error ). to . not . exist ;
expect ( data . deleted ). to . be . false ;
});
test ( "validate using assert style" , function () {
const data = res . getBody ();
// Equality
assert . equal ( res . getStatus (), 200 );
assert . deepEqual ( data . user , { id: 1 , name: 'John' });
// Type checking
assert . isObject ( data );
assert . isArray ( data . items );
assert . isNumber ( data . count );
assert . isString ( data . message );
assert . isBoolean ( data . success );
// Truthiness
assert . isTrue ( data . verified );
assert . isFalse ( data . deleted );
assert . isNull ( data . error );
assert . isUndefined ( data . optional );
// Properties
assert . property ( data , 'id' );
assert . propertyVal ( data , 'status' , 'active' );
// Strings
assert . include ( data . message , 'success' );
assert . match ( data . email , / ^ [ ^ \s@ ] + @/ );
// Numbers
assert . isAbove ( data . score , 0 );
assert . isAtMost ( data . percentage , 100 );
});
Advanced Validation Patterns
test ( "validate nested object structure" , function () {
const data = res . getBody ();
expect ( data ). to . have . nested . property ( 'user.profile.email' );
expect ( data ). to . have . nested . property ( 'settings.notifications.email' , true );
// Deep equality
expect ( data . user ). to . deep . include ({
id: 123 ,
role: 'admin'
});
// Validate entire structure
expect ( data ). to . deep . equal ({
success: true ,
user: {
id: 123 ,
name: 'John Doe' ,
email: 'john@example.com'
},
metadata: {
timestamp: data . metadata . timestamp // dynamic value
}
});
});
test ( "validate array contents" , function () {
const data = res . getBody ();
// Array length
expect ( data . items ). to . have . lengthOf ( 10 );
expect ( data . items ). to . have . length . above ( 0 );
// Array membership
expect ( data . tags ). to . include ( 'javascript' );
expect ( data . tags ). to . include . members ([ 'node' , 'api' ]);
expect ( data . tags ). to . have . members ([ 'node' , 'api' , 'rest' ]);
// Array of objects
expect ( data . users ). to . be . an ( 'array' ). that . is . not . empty ;
expect ( data . users [ 0 ]). to . have . property ( 'id' );
// Every item matches condition
data . items . forEach ( item => {
expect ( item ). to . have . property ( 'id' );
expect ( item . id ). to . be . a ( 'number' );
});
});
test ( "response time is acceptable" , function () {
const responseTime = res . getResponseTime ();
expect ( responseTime ). to . be . below ( 2000 );
expect ( responseTime ). to . be . within ( 0 , 5000 );
});
test ( "response size is reasonable" , function () {
const size = res . getSize ();
expect ( size . total ). to . be . below ( 1024 * 1024 ); // < 1MB
expect ( size . body ). to . be . above ( 0 );
});
test ( "validate JSON schema" , function () {
const tv4 = require ( 'tv4' );
const data = res . getBody ();
const schema = {
type: 'object' ,
required: [ 'id' , 'name' , 'email' ],
properties: {
id: { type: 'number' },
name: { type: 'string' , minLength: 1 },
email: { type: 'string' , format: 'email' },
age: { type: 'number' , minimum: 0 },
roles: {
type: 'array' ,
items: { type: 'string' }
}
}
};
const valid = tv4 . validate ( data , schema );
expect ( valid ). to . be . true ;
if ( ! valid ) {
console . error ( 'Schema validation error:' , tv4 . error );
}
});
test ( "validate JWT token" , function () {
const jwt = require ( 'jsonwebtoken' );
const token = res . getBody (). token ;
// Decode without verification
const decoded = jwt . decode ( token );
expect ( decoded ). to . have . property ( 'exp' );
expect ( decoded . exp ). to . be . greaterThan ( Date . now () / 1000 );
// Validate claims
expect ( decoded . userId ). to . equal ( bru . getVar ( 'expectedUserId' ));
expect ( decoded . role ). to . be . oneOf ([ 'user' , 'admin' ]);
// Store for later use
bru . setVar ( 'authToken' , token );
});
Async Test Validations
// Make additional requests within tests
await test ( "verify created resource" , async () => {
const createResponse = res . getBody ();
const resourceId = createResponse . id ;
// Fetch the created resource
const getResponse = await bru . sendRequest ({
url: `https://api.example.com/resources/ ${ resourceId } ` ,
method: 'GET'
});
expect ( getResponse . status ). to . equal ( 200 );
expect ( getResponse . data . id ). to . equal ( resourceId );
expect ( getResponse . data . name ). to . equal ( createResponse . name );
});
Error Handling in Tests
// Test expected errors
test ( "should handle 404 gracefully" , function () {
expect ( res . getStatus ()). to . equal ( 404 );
expect ( res . getBody ()). to . have . property ( 'error' );
expect ( res . getBody (). error ). to . include ( 'not found' );
});
// Conditional assertions
test ( "conditional validation" , function () {
const data = res . getBody ();
if ( res . getStatus () === 200 ) {
expect ( data ). to . have . property ( 'result' );
} else if ( res . getStatus () === 404 ) {
expect ( data ). to . have . property ( 'error' );
} else {
throw new Error ( `Unexpected status: ${ res . getStatus () } ` );
}
});
Best Practices
Use Descriptive Test Names
// Good
test ( "should return user profile with all required fields" , function () { ... });
// Bad
test ( "test1" , function () { ... });
Test One Thing Per Assertion
// Good - focused tests
test ( "response status is 200" , function () {
expect ( res . getStatus ()). to . equal ( 200 );
});
test ( "response contains user data" , function () {
expect ( res . getBody ()). to . have . property ( 'user' );
});
// Avoid - testing too much
test ( "everything works" , function () {
expect ( res . getStatus ()). to . equal ( 200 );
expect ( res . getBody ()). to . have . property ( 'user' );
expect ( res . getBody (). user . email ). to . be . a ( 'string' );
// ...
});
Validate Data Types and Structure
test ( "validate response structure" , function () {
const data = res . getBody ();
// Check types first
expect ( data ). to . be . an ( 'object' );
expect ( data . items ). to . be . an ( 'array' );
// Then validate values
expect ( data . success ). to . be . true ;
expect ( data . items ). to . have . lengthOf . at . least ( 1 );
});
Use Inline Assertions for Simple Checks
# Simple validations - use inline assertions
assert {
res.status: eq 200
res.body.success: eq true
}
# Complex validations - use test scripts
tests {
test("validate complex data structure", function() {
// Complex validation logic
});
}
Common Patterns
Status Code Validation assert {
res.status: eq 200
res.status: in 200,201,204
res.status: gte 200
res.status: lt 300
}
Email Validation assert {
res.body.email: matches ^[^\s@]+@[^\s@]+\.[^\s@]+$
res.body.email: contains @
res.body.email: endsWith @example.com
}
Array Validation test ( "validate array" , function () {
expect ( res . body . items ). to . be . an ( 'array' );
expect ( res . body . items ). to . not . be . empty ;
expect ( res . body . items [ 0 ]). to . have . property ( 'id' );
});
Performance Checks assert {
res.getResponseTime(): lt 2000
res.getResponseTime(): between 0,5000
}
Scripting Learn advanced scripting techniques
Variables Understand variable scopes and usage
Workflows Build complex request workflows
Testing APIs Testing fundamentals and best practices