---
kind: guide
zz: "0.8.0"
updated: 2026-10-10
state: live
rules: https://zriz.io/llms.txt
---
# Test a login flow from sign-up to token

Chain three calls in one zriz pipeline: sign up, log in, then use the token of the login. The flow passes only when each part works with the next.

## The problem {#problem}

Each endpoint can pass its own test while the flow is broken. The login gives a token that the next endpoint refuses. A user cannot work, and no unit test fails.

## The test {#test}

The example is a shop API. The test saves the token of the login and sends it to `GET /api/auth/me`.

Start from a project that `zz init` made: the [quick start](https://zriz.io/docs.md) gives the commands. Add three actions to the resource file.

`.zriz/resources/target.json`:

```json
{
  "type": "http",
  "description": "Your app under test",
  "base-url": "${env.TARGET_URL}",
  "headers": { "Content-Type": "application/json" },
  "actions": {
    "check": { "method": "GET", "path": "/api/health" },
    "register": { "method": "POST", "path": "/api/auth/register" },
    "login": { "method": "POST", "path": "/api/auth/login" },
    "me": { "method": "GET", "path": "/api/auth/me" }
  }
}
```

`.zriz/pipelines/login-flow.json`:

```json
{
  "description": "Sign up, log in, then use the token",
  "steps": [
    { "set": { "email": "u-${gen.uuid}@test.com", "password": "secret123" } },
    {
      "call": "target/register",
      "body": { "email": "${ctx.email}", "password": "${ctx.password}", "name": "Ann" },
      "expect": [["status", "==", 201]]
    },
    {
      "call": "target/login",
      "body": { "email": "${ctx.email}", "password": "${ctx.password}" },
      "expect": [["status", "==", 200], ["body.token", "not-empty"]],
      "save": { "token": "body.token" }
    },
    {
      "call": "target/me",
      "headers": { "Authorization": "Bearer ${ctx.token}" },
      "expect": [["status", "==", 200], ["body.email", "==", "${ctx.email}"]]
    },
    {
      "call": "target/login",
      "body": { "email": "${ctx.email}", "password": "wrong-password" },
      "expect": [["status", "==", 401], ["body.token", "not-exists"]]
    }
  ]
}
```

## Run it {#run}

```sh
zz run login-flow
```

```text
"status":"pass"
```

## What it proves {#proves}

- `save`: the token of the login goes to `ctx`. The next step sends it, as a client does.
- `body.email == ${ctx.email}` on the call with the token: the token names the correct user, not a different one.
- The last call, `status == 401`: a wrong password gives no token.

> Common mistake: A test that uses the token of the sign-up never tests the login. Save the token from the login step.

## Next {#next}

- [Test that a password is stored as a hash](https://zriz.io/learn/test-password-stored-as-hash.md)
- [Pipelines](https://zriz.io/docs/pipelines.md) gives the keys `save` and `headers`.
