Debugging
Glubean tests are real Node.js code. You can import any npm package — crypto libraries, database clients, file parsers, third-party SDKs — and debug them with the full power of VS Code’s debugger. This is something GUI tools like Postman fundamentally cannot do: when a crypto function returns an unexpected hash, or a third-party SDK throws a cryptic error, you need to set a breakpoint and inspect the actual runtime state.
Breakpoints in test code
Glubean tests run on Node, which exposes the V8 inspector that VS Code already understands.
To debug a test:
- Set a breakpoint anywhere in your
*.test.tsfile — click the gutter to the left of a line number. - Right-click the Play button next to the
test(call and choose Debug Test, or select it from the Test Explorer context menu. - Execution pauses at your breakpoint.
Tip: Right-click any Play button and select “Debug Test” to enter debug mode. You can also use the bug icon in Test Explorer.
From there you can:
- Step through lines with
F10/F11 - Inspect variables in the Run and Debug sidebar
- Evaluate expressions in the Debug Console
- Hover over any variable in the editor to see its current value
When debugging matters most
Third-party libraries and crypto
When your test involves npm packages beyond HTTP, the debugger is essential — you can’t “trace” a crypto function or a database query the way you trace an HTTP call.
import { createHmac } from "node:crypto";
import { test } from "@glubean/sdk";
export const verifyWebhook = test("verify-webhook", async (ctx) => {
const secret = ctx.secrets.require("WEBHOOK_SECRET");
const payload = '{"event":"order.created"}';
const signature = createHmac("sha256", secret)
.update(payload)
.digest("hex"); // set a breakpoint here — inspect the actual hash
const res = await ctx.http.post("/webhooks", {
body: payload,
headers: {
"x-signature": signature,
"content-type": "application/json",
},
});
ctx.expect(res).toHaveStatus(200);
});Inspecting HTTP responses
export const createAndFetch = test("create-and-fetch")
.step("create", async (ctx) => {
const res = await ctx.http.post("/api/users", { json: { name: "Alice" } });
const body = await res.json(); // set a breakpoint here
return { id: body.id };
})
.step("fetch", async (ctx, { id }) => {
const res = await ctx.http.get(`/api/users/${id}`);
ctx.expect(res.status).toBe(200);
});Pause after any await and inspect the result directly in the debug console — response body, intermediate variables, computed values — before the assertion runs.
Tips
Use ctx.log() for lightweight tracing — if you just want to understand the flow without stopping execution, ctx.log() writes structured output to the trace file and the terminal. No debugger needed.
ctx.log("User created", { id: body.id, status: res.status });Step over await calls — use F10 to step over async calls and land on the next line after the promise resolves, rather than stepping into the runtime internals.
Debug Console expressions — while paused, type any expression in the Debug Console to evaluate it in the current scope:
> res.status
200
> JSON.stringify(body, null, 2)
'{\n "id": 42,\n "name": "Alice"\n}'One test at a time — the debugger runs a single test per session. This is inherent to how debugging works.
What’s next?
- Result Viewer — Inspect results without stopping execution
- CLI Debugging