DEV Community

Ryan Reynolds
Ryan Reynolds

Posted on • Originally published at blog.usebruno.com

How to Use External Libraries in Bruno Test Scripts

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:

  • 💡 Why using external libraries in your test scripts matters
  • 🔍 What Zod is and why it’s useful
  • 🧪 Real-world examples using a pet-themed API and zod
  • 🛠 How to install libraries into your Bruno collection safely

Let’s dive in!

🛑 Heads up: Leveraging external libraries requires using 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).


🤔 Why Use External Libraries in API Tests?

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:

  • Format or manipulate data (dayjs)
  • Validate conditions (joi, zod)
  • Generate dynamic content (uuid, faker)
  • Do complex math or logic (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.


📚 What Is Zod?

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:

  • Defining strict schemas for expected objects
  • Parsing and validating incoming data
  • Throwing clear, readable errors when validation fails

📦 Installing External Libraries in Bruno

To use an external package like zod in your test scripts:

  1. Navigate to your Bruno collection folder:

    cd path/to/your/bruno-collection
    
  2. Initialize a package.json file:

    npm init -y
    
  3. Install the external package:

    npm install zod
    

Bruno will now be able to use the installed package inside your test scripts just like any regular Node.js project.


🐾 Real-World Examples

Let’s walk through two playful but practical examples using Bruno, Zod, and our echo server. You can follow along or grab the collection from GitHub.

Fetch in Bruno

📄 Request 1: Validating Response for Name and Type

{
  "users": [
    { "name": "Bruno", "type": "dog" },
    { "name": "Luna", "type": "cat" },
    { "name": "Ziggy", "type": "bird" }
  ]
}
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

Test Result 1


📄 Request 2: Detailed Pet Validation

{
  "pets": [
    {
      "id": "pet_001",
      "name": "Bruno",
      "age": 4,
      "vaccinated": true,
      "tags": ["friendly", "energetic"]
    },
    {
      "id": "pet_002",
      "name": "Luna",
      "age": 2,
      "vaccinated": false,
      "tags": ["quiet"]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Test Script:

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(", ")}`);
  }
});
Enter fullscreen mode Exit fullscreen mode

Test Result 2


✅ Why Bruno’s Approach Wins

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. 🎉


🔗 Try the Demo Yourself

Fetch the full working collection from GitHub or click the button below:

Fetch in Bruno

You’ll see the request go out to the echo server, the response come back, and your Zod-powered tests validate the schema.


💬 Final Thoughts

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! 🐶

Top comments (0)