# Automated UI testing

> TestCase/TestSuite running on the graphics runtime, with visual screenshot comparison (golden images).

Source: https://crossfly.dev/docs/best-practices/testes — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Automated UI testing

CrossFly's testing framework **is not JUnit**. Each `TestCase` runs **inside the graphics runtime**
(paint thread, `EventsProcessor`, GL pipeline), and the main assertion is the **visual comparison of
screenshots** against reference images (*golden images*). Gateway to Chapter 31.

## Anatomy of a `TestCase`
```java
public class LoginTest extends TestCase {
   @Override protected void load() throws Exception {
      new LoginScreen().show();        // builds the screen under test
   }
   @Override public void runTests() throws Exception {
      waitWindow(LoginScreen.class);
      type(0, TextField.class, "usuario@app.com");   // types into the 1st TextField
      type(1, TextField.class, "senha123");
      click("Entrar");                 // clicks the button with this text
      shot();                          // captures and compares against the golden
      waitWindow(HomeScreen.class);
      shot();
   }
   @Override protected void unload() { /* clears state */ }
}
```
Interaction: `click(...)`, `type(...)`, `enter()`, `penDown/penUp/penDrag(...)`, `setText(...)`.
Discovery: `find(index, Classe)` / `find(texto, Classe)`. Synchronization: `waitWindow(...)`,
`waitAnimation()`, `waitUIidle(...)`.

## Group and run — `TestSuite`
```java
TestSuite suite = new TestSuite();
suite.startTests(new TestCase[]{ new LoginTest(), new CadastroTest() });
```
The suite runs each test, compares the `shot()` captures against the goldens, and reports
(`success`/`fail`/`log`).

## ⚠️ Determinism is a prerequisite: `DeviceConfig.isTesting`
Pixel-by-pixel comparison only matches if rendering is **deterministic**. Turn on
`DeviceConfig.isTesting = true` — this pins the cursor, removes timestamps, and makes `TimePicker`/clock
stable. **Without it, the golden never matches** (blinking cursor, current time, etc. change the image).

## Without UI: `WindowlessTestCase`
For logic that doesn't need a screen (repository, formatting), extend `WindowlessTestCase` — it runs on
the runtime, but without building UI.

## Generate the doc images
The same test screenshots serve to **generate the documentation/store images**:
`Main.getScreenShot(true).toPng("prefixo_")`.

## Best practices
- **Always** `DeviceConfig.isTesting = true` in the test battery.
- Use `waitWindow(...)`/`waitAnimation()` before `shot()` — capture a **stable** frame.
- One golden per relevant visual state; regenerate when you change the UI on purpose.

## Common mistakes
- A golden that "passes sometimes, fails others" → missing `isTesting`/`waitAnimation` (unstable frame).
- `shot()` before the window is fully visible.
