API Clients are usually powerful… until you try to use the tools you already know—like external libraries (or...cough... Git).
Other platforms require workarounds, sandboxes, and script injections to get basic utilities working. But Bruno takes a different approach.
Bruno runs your test scripts in a real Node.js environment.
That means you can npm install
your favorite packages and require()
them like you would in any local project.
In this post, we’ll walk through:
zod
Let’s dive in!
Developer Mode
. It's important to be cautious when using this mode as it allows script execution on your machine. Only use Developer Mode
when you trust the author of the collection (or if you are the author, of course).Real-world APIs can get complex: nested responses, dynamic data, or custom validations. Instead of writing that logic from scratch, external libraries give you reliable, well-tested tools to:
dayjs
)joi
, zod
)uuid
, faker
)mathjs
)In Bruno, you don’t need to hack these in. You just install them.
Bonus: Bruno also includes built-in libraries like chai, axios, ajv, and lodash
— no install needed. Learn more in our inbuilt libraries docs.
zod
is a TypeScript-first schema validation library for JavaScript. It’s lightweight, powerful, and works great for validating API responses in tests.
Here’s what Zod is great at:
To use an external package like zod
in your test scripts, you'll first need to initialize a package.json
file in your Bruno collection directory and install the package.
cd path/to/your/bruno-collection
package.json
file:
npm init -y
npm install zod
Bruno will now be able to use the installed package inside your test scripts just like any regular Node.js project.
Let’s walk through two playful but practical examples using Bruno, Zod, and our echo server. Each request sends a pet-related payload, and we validate the responses with Zod-powered tests.
You can follow along and create your own or grab the collection directly from GitHub by clicking the button below:
Name
and Type
This one’s simple: we’re validating that each animal in the response has a name and a recognized type (dog
, cat
, or bird
).
{
"users": [
{ "name": "Bruno", "type": "dog" },
{ "name": "Luna", "type": "cat" },
{ "name": "Ziggy", "type": "bird" }
]
}
Test Script:
const { z } = require("zod");
const response = res.getBody();
const UserSchema = z.object({
name: z.string(),
type: z.enum(["dog", "cat", "bird"])
});
const Schema = z.object({
users: z.array(UserSchema)
});
test("Validate response schema structure", () => {
Schema.parse(response);
});
Perfect! Looks like we're returning the proper structure in our response.
Let’s add some extra validation here. We’re not only validating the response structure, but also asserting that all pets are vaccinated. Bruno doesn't want to get kennel cough! 🐶
{
"pets": [
{
"id": "pet_001",
"name": "Bruno",
"age": 4,
"vaccinated": true,
"tags": ["friendly", "energetic"]
},
{
"id": "pet_002",
"name": "Luna",
"age": 2,
"vaccinated": false,
"tags": ["quiet"]
}
]
}
Test Scripts:
const { z } = require("zod");
const response = res.getBody();
const PetSchema = z.object({
id: z.string().startsWith("pet_"),
name: z.string(),
age: z.number().int().nonnegative(),
vaccinated: z.boolean(),
tags: z.array(z.string())
});
const PetsResponseSchema = z.object({
pets: z.array(PetSchema)
});
test("Valid response structure for pets", () => {
PetsResponseSchema.parse(response);
});
test("All pets must be vaccinated", () => {
const unvaccinated = response.pets.filter(pet => !pet.vaccinated);
if (unvaccinated.length > 0) {
throw new Error(`Found unvaccinated pets: ${unvaccinated.map(p => p.name).join(", ")}`);
}
});
Looks like Luna may not be the best play date for Bruno 😔 , but we are getting a valid response structure for the pet details!
Here’s what makes this experience better than other tools:
Feature | Bruno | Others |
---|---|---|
Use require() like normal Node.js |
✅ | ❌ |
Install npm packages | ✅ | ❌ |
Supports any external module (even private) | ✅ | Limited |
Local-first (no cloud storage of secrets/code) | ✅ | ❌ |
No sandboxes. No evals. No headaches. 🎉
We’ve published the full working collection on GitHub. You can either clone this, or simply click the Fetch in Bruno button below!
You’ll see the request go out to the echo server, the response come back, and your Zod-powered tests validate the response schema.
Using external libraries in test scripts shouldn’t be a hassle. Bruno treats your code like actual code—because it is.
We’d love to see what libraries you end up using in Bruno collections. Got something cool to share? Tag us or contribute to docs.usebruno.com.
Happy testing! 🐶