Skip to Content
SDK & PluginsAssertions

Assertions

Glubean gives you four verification tools with different failure behavior.

ctx.expect

Soft assertion by default. Several failures can be collected in one run without stopping execution.

ctx.expect(body.role).toBe("admin"); ctx.expect(body.features).toContain("beta-access");

If a particular expectation should stop execution immediately, chain .orFail():

ctx.expect(res.status).toBe(200).orFail();

Available matchers

// Equality ctx.expect(x).toBe(y); ctx.expect(x).toEqual(y); // Truthiness ctx.expect(x).toBeTruthy(); ctx.expect(x).toBeFalsy(); ctx.expect(x).toBeNull(); ctx.expect(x).toBeUndefined(); ctx.expect(x).toBeDefined(); // Numeric ctx.expect(n).toBeGreaterThan(5); ctx.expect(n).toBeGreaterThanOrEqual(5); ctx.expect(n).toBeLessThan(10); ctx.expect(n).toBeLessThanOrEqual(10); ctx.expect(n).toBeWithin(1, 10); // Strings & collections ctx.expect(s).toContain("sub"); ctx.expect(s).toMatch(/regex/); ctx.expect(s).toStartWith("pre"); ctx.expect(s).toEndWith("suf"); ctx.expect(arr).toHaveLength(3); // Objects ctx.expect(obj).toMatchObject({ key: "val" }); ctx.expect(obj).toHaveProperty("path.to.key", expectedValue); ctx.expect(obj).toHaveProperties(["a", "b"]); // HTTP responses ctx.expect(res).toHaveStatus(200); await ctx.expect(res).toHaveJsonBody({ key: "val" }); ctx.expect(res).toHaveHeader("content-type", /json/); // Modifiers ctx.expect(x).not.toBe(y); ctx.expect(x).toSatisfy(v => v > 0); ctx.expect(x).toBeType("string");

ctx.assert

Hard assertion. Stops execution immediately on failure.

ctx.assert(res.ok, "Request should succeed"); ctx.assert(body.id > 0, "User ID should be positive", { actual: body.id, expected: "> 0", });

ctx.validate

Schema validation using Zod, Valibot, ArkType, or other parse-style validators.

import { z } from "zod"; const UserSchema = z.object({ id: z.number(), name: z.string(), email: z.string().email(), }); ctx.validate(responseBody, UserSchema, "user response");

contract.http uses ctx.validate under the hood for both expect.schema (response body) and expect.headers (response headers). You rarely need to call it manually inside a contract — the declarative form is preferred.

Response header normalization

When contract.http validates expect.headers, it normalizes the response headers before calling ctx.validate:

  • Keys are lowercased (HTTP spec: header names are case-insensitive)
  • Values keep string | string[] shape (multi-value headers like Set-Cookie come through as arrays)

Your header schema should therefore use lowercase keys:

headers: z.object({ "content-type": z.string().regex(/^application\/json/), "x-request-id": z.string().uuid(), "set-cookie": z.array(z.string()).optional(), }),

If you validate headers manually via ctx.validate(res.headers, schema, label), the raw res.headers object is not pre-normalized — you’d need to lowercase-transform it yourself. Prefer expect.headers in contract.http cases.

ctx.warn

Non-failing tests for budgets and best-practice monitoring:

ctx.warn(durationMs < 500, "Response should stay under 500ms");

Warnings are visible in the Result Viewer and Cloud dashboard without failing the run.

Next

Last updated on