# Ui.Tick

> In a UI test, fires every `on every` clock armed on the screen once, now, and waits for their bodies — server calls included — so a test can assert what a poll brings without waiting for, or racing, the poll's timer.

<!-- id: testing-ui-tick · area: testing · stability: stable · html: https://osysharp.com/reference/testing/ui-tick/ -->

## Summary        {#summary}
`Ui.Tick()` makes the page's own `on every` clocks fire — each one once, now — and returns when their bodies have
finished, including any server call a body makes and the re-render after it. It is how a test proves what a POLL does:
a payment page that learns it was paid, a status that turns "verified", a counter that moves.

## Signature      {#signature}
```osy syntax
Ui.Tick();
```

## Description    {#description}
A clock (`on every (TimeSpan.FromSeconds(2)) { … }`, see [on every](https://osysharp.com/reference/ui/cadence/)) runs on a wall-clock timer, and **an armed
timer is not work the page reports as outstanding**. A UI assertion waits for the page to finish what it is doing and
then judges the screen; a timer that has not fired yet is not "doing" anything. So a test that asserts what the next
poll will show is racing that timer against the assertion's own patience, and on a loaded machine it loses — the
assertion answers "not there" a moment before the poll would have put it there.

`Ui.Tick()` removes the race instead of widening it. Every clock armed on the screen runs its body once, exactly as
its timer would have run it, and the verb waits for all of them:

- **It takes the timer's place.** The clock re-arms a full interval after the tick, as after any run — it does not
  fire again a moment later because its old timer was nearly due.
- **A body already running is waited for first**, so a clock never runs its body twice at once.
- **A navigation the body asks for is part of the tick.** A poll's commonest ending is to move on
  (`Navigation.Go("/paid/…")`), and the verb waits for the next page the same way a click does.
- **A clock whose last beat failed is still armed**, and the tick runs it: a body that throws does not stop its
  clock (see [on every](https://osysharp.com/reference/ui/cadence/)), so a test can fail a beat and then prove the next one recovers.
- **Nothing armed is a refusal**, not a quiet no-op: "Ui.Tick() found no `on every` clock armed on this screen". A
  tick that fired nothing would leave the next assertion judging a page that never polled.

⚑ **It does not move time.** A body that asks "has enough time passed?" — the shop asks BankID at most every two
seconds — reads the test's clock, so move it first with [TestClock.Advance and TestClock.Set](https://osysharp.com/reference/testing/clock-advance/): `TestClock.Advance(…)` then
`Ui.Tick()`. The two compose, and neither does the other's job.

⚠ **Write it where the poll is the thing under test.** Re-opening the page (`Ui.Visit`) to make an `on mount` ask
instead proves the mount, not the poll — the page a customer is actually looking at never re-opens itself.

## Examples       {#examples}

```osy title="a harbour light that sweeps every hour — the test makes it sweep twice" test app=testing-ui-tick
[Principal] entity User {
  [Required, MaxLength(200)] string Email;
  security { allow read when IsAuthenticated; }
}

[AllowAnonymous]
int NextSweep(int seen) { return seen + 1; }

[Route("/lighthouse")]
[AllowAnonymous]
[Render(CSR)]
component Lighthouse() {
  int sweeps = 0;
  // An hour: nothing but the tick can fire it inside the test, so every change the test sees is the tick's.
  on every (TimeSpan.FromHours(1)) { sweeps = NextSweep(sweeps); }
  render { Text($"The lamp has swept {sweeps} times."); }
}

[Test]
void each_tick_is_one_sweep_and_waits_for_the_server() {
  Ui.Visit("/lighthouse");
  Assert.Visible("The lamp has swept 0 times.");

  Ui.Tick();
  Assert.Visible("The lamp has swept 1 times.");

  Ui.Tick();
  Assert.Visible("The lamp has swept 2 times.");
}
```

## See also       {#see-also}
- [on every](https://osysharp.com/reference/ui/cadence/) — `on every`, the clock this fires
- [TestClock.Advance and TestClock.Set](https://osysharp.com/reference/testing/clock-advance/) — move the test's clock first when the body asks how much time has passed
- [Ui — drive the app's UI from a test](https://osysharp.com/reference/testing/ui/) — the rest of the UI verbs and how an assertion waits for a settled screen
