# Scenario tests

URL: /code/file-conventions/tests · Id: `page:code/file-conventions/tests`

> A file in tests/ walks the whole Startup in the test environment, as a buyer would, before a Change merges.

A file in `tests/` walks the whole [Startup](/business/nouns/startup) in the test environment, as a buyer would: sign up, pay, use, renew.

```text
tests/
└── first-renewal.test.ts
```

## Reference
TypeScript with `startup-builder/test`.

| Export | Type | Holds |
| --- | --- | --- |
| `walk(persona)` | function | A synthetic buyer that drives every [Interface](/business/nouns/interface) |
| `clock.advance(duration)` | function | Moves the test clock; everything due in between fires in order |
| `test`, `expect` | function | Cases and assertions |

## Examples
### Minimal
```ts title="tests/first-renewal.test.ts"
import { expect, test, walk } from 'startup-builder/test'

test('a manager can subscribe', async () => {
  const manager = await walk('manager')
  expect(await manager.subscribe('pro')).toBeTruthy()
})
```

### Leaseline
```ts title="tests/first-renewal.test.ts"
import { clock, expect, test, walk } from 'startup-builder/test'

test('a lease ending in 60 days gets its notice', async () => {
  const manager = await walk('manager')
  await manager.subscribe('pro')
  await manager.import('mappings/rent-roll', 'fixtures/rent-roll.csv')
  await clock.advance('1 day')
  expect(await manager.inbox()).toContainMessage('Your lease at 4B ends')
})
```

## What it builds
The [StartupBuilder](/code/builders/startup) runs every scenario on each [Change](/business/nouns/change)'s preview.

- a check result per scenario; `Change.merge` refuses while one fails
- no live money and no live [Messages](/business/nouns/message): the test environment fakes Stripe and mail

## Good to know
- The same clock moves from the CLI: `npx startup-builder clock advance --by 30d`.