Contract Flow
Use contract.flow() to verify that multiple endpoints work together correctly — create then retrieve, purchase then refund, register then login.
When to use
- Cross-endpoint verification: one endpoint’s output feeds the next
- Lifecycle testing: create → read → update → delete
- State machines: order placed → paid → shipped → delivered
For single-endpoint specs, use contract.http() instead.
Basic flow
import { contract, configure } from "@glubean/sdk";
const { api } = configure({
http: { prefixUrl: "{{BASE_URL}}" },
});
export const userLifecycle = contract.flow("user-lifecycle")
.http("create", {
endpoint: "POST /users",
client: api,
body: { email: "flow@example.com", password: "secure123" },
expect: { status: 201 },
})
.returns((res) => ({ id: res.id }))
.http("retrieve", {
endpoint: "GET /users/:id",
client: api,
params: (state) => ({ id: state.id }),
expect: { status: 200 },
})
.returns((res) => ({ id: res.id }))
.http("delete", {
endpoint: "DELETE /users/:id",
client: api,
params: (state) => ({ id: state.id }),
expect: { status: 204 },
})
.build();How it works
- Each
.http()step sends one HTTP request .returns(res => state)extracts data from the response for the next stepparams,body, andheaderscan be functions that receive the current state- Steps execute in order — the flow stops on the first failure
State passing
The flow carries state between steps via .returns():
.http("create-order", {
endpoint: "POST /orders",
client: api,
body: { items: [{ productId: "p1", qty: 2 }] },
expect: { status: 201 },
})
.returns((res) => ({ orderId: res.id, total: res.total }))
.http("pay", {
endpoint: "POST /orders/:id/pay",
client: api,
params: (state) => ({ id: state.orderId }),
body: (state) => ({ amount: state.total }),
expect: { status: 200 },
})Combining with contract.http()
Each endpoint in a flow should also have its own contract.http() for comprehensive case coverage. The flow verifies that endpoints work together; contract.http() verifies that each endpoint handles all cases.
// Spec cases for the create endpoint
export const createUser = contract.http("create-user", {
endpoint: "POST /users",
client: api,
cases: {
success: { description: "...", body: {...}, expect: { status: 201 } },
duplicate: { description: "...", body: {...}, expect: { status: 409 } },
},
});
// Flow verifying endpoints work together
export const userLifecycle = contract.flow("user-lifecycle")
.http("create", { endpoint: "POST /users", ... })
.returns(res => ({ id: res.id }))
.http("get", { endpoint: "GET /users/:id", ... })
.build();Last updated on