Skip to main content

Documentation Index

Fetch the complete documentation index at: https://bruno-a6972042-mintlify-testing-jsonbody-jsonschema-1777266.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Bruno uses the Chai library for assertions. All Chai expect syntax works in Bruno tests.
Write JavaScript test scripts to validate API responses, handle complex logic, and automate testing workflows. bru test script

Basic Test Structure

test("test name", function () {
  expect(res.getStatus()).to.equal(200);
});

Common Test Examples

Testing Status Codes

test("should return success", function () {
  expect(res.getStatus()).to.equal(200);
});

test("should not return server error", function () {
  expect(res.getStatus()).to.not.equal(500);
});

Testing Response Body

test("should return user data", function () {
  const body = res.getBody();
  
  expect(body).to.have.property("id");
  expect(body.name).to.equal("John Doe");
  expect(body.email).to.contain("@example.com");
});

test("should return array of users", function () {
  const users = res.getBody();
  
  expect(users).to.be.an("array");
  expect(users).to.have.lengthOf(3);
  expect(users[0]).to.have.property("id");
});

Testing Nested Objects

test("should validate nested user profile", function () {
  const body = res.getBody();
  
  expect(body.user.profile.name).to.equal("Alice");
  expect(body.user.settings.theme).to.equal("dark");
  expect(body.user.settings.notifications).to.be.true;
});

Testing with Conditional Logic

test("should validate response based on status", function () {
  const status = res.getStatus();
  const body = res.getBody();
  
  if (status === 200) {
    expect(body).to.have.property("data");
    expect(body.data).to.not.be.empty;
  } else if (status === 404) {
    expect(body).to.have.property("error");
    expect(body.error.message).to.contain("not found");
  } else {
    throw new Error(`Unexpected status code: ${status}`);
  }
});

test("should validate user role permissions", function () {
  const body = res.getBody();
  
  if (body.user.role === "admin") {
    expect(body.user.permissions).to.include("write");
    expect(body.user.permissions).to.include("delete");
  } else if (body.user.role === "user") {
    expect(body.user.permissions).to.include("read");
    expect(body.user.permissions).to.not.include("delete");
  }
});

Testing Arrays and Loops

test("should validate all users have required fields", function () {
  const users = res.getBody();
  
  users.forEach((user) => {
    expect(user).to.have.property("id");
    expect(user).to.have.property("email");
    expect(user.email).to.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
  });
});

test("should find user by id", function () {
  const users = res.getBody();
  const targetUser = users.find((u) => u.id === 123);
  
  expect(targetUser).to.exist;
  expect(targetUser.name).to.equal("John");
});

Testing Response Headers

test("should have correct content type", function () {
  expect(res.getHeader("content-type")).to.contain("application/json");
});

test("should include authentication headers", function () {
  expect(res.getHeader("x-api-key")).to.exist;
  expect(res.getHeader("authorization")).to.not.be.empty;
});

Testing Response Time

test("should respond quickly", function () {
  expect(res.getResponseTime()).to.be.lessThan(1000);
});

Advanced: Saving Values for Next Request

test("should save token for next request", function () {
  const body = res.getBody();
  
  expect(body).to.have.property("token");
  expect(body.token).to.not.be.empty;
  
  // Save token to environment variable
  bru.setVar("authToken", body.token);
});

test("should extract and save user ID", function () {
  const body = res.getBody();
  
  if (body.users && body.users.length > 0) {
    const firstUserId = body.users[0].id;
    bru.setVar("userId", firstUserId);
  }
});

Error Handling

test("should handle missing fields gracefully", function () {
  const body = res.getBody();
  
  if (!body.data) {
    expect(body).to.have.property("error");
    expect(body.error.code).to.be.oneOf([400, 404, 422]);
  }
});

test("should validate error response structure", function () {
  const status = res.getStatus();
  
  if (status >= 400) {
    const body = res.getBody();
    expect(body).to.have.property("error");
    expect(body.error).to.have.property("message");
    expect(body.error.message).to.be.a("string");
  }
});

Common Chai Assertions

// Equality
expect(value).to.equal(expected);
expect(value).to.not.equal(expected);
expect(value).to.eql(expected); // deep equality

// Type checking
expect(value).to.be.a("string");
expect(value).to.be.an("array");
expect(value).to.be.true;
expect(value).to.be.null;

// Property checks
expect(obj).to.have.property("key");
expect(obj).to.have.all.keys("name", "email");

// String checks
expect(str).to.contain("substring");
expect(str).to.match(/regex/);

// Number comparisons
expect(num).to.be.above(10);
expect(num).to.be.below(100);
expect(num).to.be.within(10, 100);

// Array checks
expect(arr).to.be.an("array");
expect(arr).to.have.lengthOf(3);
expect(arr).to.include("item");
expect(arr).to.be.empty;

Bruno-specific assertions

In addition to the standard Chai assertions, Bruno registers custom assertions for working with JSON response bodies.

jsonBody

Use jsonBody to validate the response body against a value or to check for the existence of a nested property. This assertion mirrors Postman’s pm.response.to.have.jsonBody(...) API and is convenient for collections imported from Postman.
test("body is valid JSON", function () {
  // Passes when the body is a JSON object or array
  expect(res.getBody()).to.have.jsonBody();
});

test("body deep equals expected object", function () {
  expect(res.getBody()).to.have.jsonBody({
    id: 1,
    name: "Alice"
  });
});

test("body has a nested property", function () {
  // Supports dot notation, numeric brackets, and quoted bracket keys
  expect(res.getBody()).to.have.jsonBody("user.profile.email");
  expect(res.getBody()).to.have.jsonBody("items[0].id");
  expect(res.getBody()).to.have.jsonBody('data["a.b"].name');
});

test("nested property equals value", function () {
  expect(res.getBody()).to.have.jsonBody("user.profile.name", "Alice");
});

test("body should not have property", function () {
  expect(res.getBody()).to.not.have.jsonBody("error");
});
CallBehavior
jsonBody()Asserts the body is a JSON object or array
jsonBody(object)Deep equality against the supplied object
jsonBody("path")Asserts the nested property exists
jsonBody("path", value)Asserts the nested property equals the supplied value
All variants support negation via .not (for example, to.not.have.jsonBody("key")).

jsonSchema

Use jsonSchema to validate a response body against a JSON Schema. Bruno uses Ajv under the hood, so any JSON Schema draft supported by Ajv works here. An optional second argument forwards options to the Ajv instance.
test("body matches schema", function () {
  const schema = {
    type: "object",
    required: ["id", "name", "email"],
    properties: {
      id: { type: "number" },
      name: { type: "string" },
      email: { type: "string", format: "email" }
    }
  };

  expect(res.getBody()).to.have.jsonSchema(schema);
});

test("body matches schema with Ajv options", function () {
  const schema = {
    type: "object",
    properties: {
      createdAt: { type: "string", format: "date-time" }
    }
  };

  // Pass Ajv options as the second argument
  expect(res.getBody()).to.have.jsonSchema(schema, { strict: false });
});
When the body fails validation, the assertion error includes the Ajv validation errors so you can quickly see which fields are missing or have the wrong type.

Next Steps

For more advanced scripting capabilities, see: