Skip to content

Getting Started

Tugkan Boz edited this page Jun 4, 2026 · 1 revision

Getting Started

Install

npm install two-go --save-dev

Node 18 or newer (it uses the native fetch). ESM only, so use import or a dynamic import() from CommonJS. Zero runtime dependencies.

Your first test

go() takes a base URL, or an options object for defaults:

import { go } from "two-go";

const api = go({
  baseURL: "https://api.example.com",
  headers: { "x-api-key": "secret" },
  timeout: 10000,
});

const res = await api.get("/users").query({ page: 1 }).expectStatus(200);
console.log(res.status, res.time, res.get("data[0].name"));

Every verb (get, put, post, patch, delete, head, options) returns a chainable, thenable builder. Awaiting it sends the request and replays the checks. The resolved GoResponse has status, statusText, headers (lowercase keys), body (parsed JSON or text), text, time, url, method, and get(path).

Building a request

await api.post("/users")
  .header("x-request-id", "abc")
  .headers({ "x-trace": "1" })
  .query({ page: 1, tags: ["a", "b"] })
  .bearer("TOKEN")
  .json({ name: "Ada" })
  .timeout(5000)
  .expectStatus(201);

Body helpers: .json(obj), .form(obj), .text(str). Absolute http(s):// paths bypass the base URL.

Running tests

Because checks throw, there is no adapter. With node:test:

import { test } from "node:test";
import { go } from "two-go";

const api = go("https://api.example.com");
test("GET /users", async () => {
  await api.get("/users").expectStatus(200).expectJson("data[0].id");
});
node --test

Jest, Vitest, and Mocha work the same way. There is also a built-in runner and CLI: put suites in *.twogo.mjs files and run npx two-go.

// test/users.twogo.mjs
import { go, suite } from "two-go";
const api = go("https://api.example.com");
suite("users", ({ test }) => {
  test("lists users", async () => {
    await api.get("/users").expectStatus(200);
  });
});

For machine-readable output: npx two-go --reporter junit --out results.xml.

Clone this wiki locally