# API for installer UI tests

The install4j test API drives an actual installer UI from inside a test JVM. It lets you write automated end-to-end tests that exercise an installer, drive its screens and dialogs, and verify post-install state. The API is framework-agnostic: any test runner (JUnit, TestNG, Spock, plain `main`) works because it only exposes a session API.

Use it when you need to assert that an installer reaches the expected screens and writes the expected files, variables and configuration. For pure unattended-mode regression checks, the generated installer with the -q flag is sufficient in which case this API is not required.

The complete API documentation is in the [com.install4j.api.test package](../../reference/api/test/package-summary.md). The test API is built on top of the [installer API](installer.md). Sessions expose the `com.install4j.api.context.Context` and the `com.install4j.api.context.WizardContext` of the running installer.

### Development environment

The test API ships as a separate Maven artifact with these coordinates:

```
group: com.install4j
artifact: install4j-test
version: <install4j version>
```

where the install4j version corresponding to this manual is 13.0.2. Add it to the **test** classpath only:

```
<dependency>
    <groupId>com.install4j</groupId>
    <artifactId>install4j-test</artifactId>
    <version>13.0.2</version>
    <scope>test</scope>
</dependency>
```

Jar, source and Javadoc artifacts are published to the Maven Central repository. If a Maven dependency is not an option, the JAR file ships under

```
resource/install4j-test.jar
```

in the install4j installation, alongside `resource/i4jruntime.jar`. Both are required on the test classpath.

### Sessions

A session is the running installer, uninstaller or custom installer application process under test, wrapped as an `java.lang.AutoCloseable`. The three session types are:

- **InstallerSession** — Drives an installer from a generated media file. Created with `InstallerSessionBuilder.forMediaFile(media)`.
- **UninstallerSession** — Drives the uninstaller of an already installed installation. Created with `UninstallerSessionBuilder.forInstallation(installDir)`.
- **InstallerApplicationSession** — Drives a custom installer application (update downloader, custom maintenance tool) from an already-installed copy. Created with `InstallerApplicationSessionBuilder.forInstallation(installDir).applicationId(id)`.

All three implement `com.install4j.api.test.session.Session`, which provides the waits, screen and dialog accessors, variable access, log access, and lifecycle methods. The builders are fluent and let you set the default timeout, system properties, working directory, log file and command-line arguments before starting the session. See the [com.install4j.api.test.session package](../../reference/api/test/session/package-summary.md) for the full API.

It is recommended to use try-with-resources on the session. Closing a session terminates the installer thread, clears the extraction cache and deletes the auto-created installation directory if the session itself created it. User-supplied directories are not deleted.

### Driving the wizard

The `com.install4j.api.test.ui.ScreenHandle` returned from `session.currentScreen()` or `session.waitForScreenId(id)` is the central entry point for driving the wizard. It exposes typed accessors for every install4j form component, Next/Previous/Cancel/Finish buttons of the wizard, and UI diagnostics via `com.install4j.api.test.ui.UiContainer`.

Each form-component accessor returns a typed handle with the operations specific to that component, for example `textField("24").setText(...)` or `checkBox("31").assertNotSelected().setSelected(true)`. The handles also expose typed asserts that return the handle for chaining. See the [com.install4j.api.test.formcomponents package](../../reference/api/test/formcomponents/package-summary.md) for the complete catalogue.

Every form-component accessor comes in two flavors: a single-argument form that takes the configured form-component id, and a no-arg form that returns the unique handle of that type on the current screen. Screen ids are the values configured in the install4j IDE: the **Customized id** if set, otherwise the integer **id**.

### Modal dialogs

The wizard may show modal dialogs for alerts, file choosers, the startup language selection, password prompts and similar. The `com.install4j.api.test.session.Session` interface has a typed accessor for each such dialog (`session.alert()`, `session.fileChooser()`, `session.languageDialog()` and others) that blocks until the matching dialog is showing and returns a dedicated handle. A generic `session.dialog(predicate)` accessor matches windows shown by custom code or extensions. See the [com.install4j.api.test.ui package](../../reference/api/test/ui/package-summary.md) for the complete dialog handle API.

### Asserting state

Once the installer has reached a terminal screen and exited, sessions expose everything needed to verify what the installer did:

- **Installer variables** — `session.getVariable(name)` returns the value of any installer variable captured at the time the installer exits.
- **Installer log** — `session.getLogFile()` and `session.readLog()` give access to the full installer log for assertions or debugging.
- **Filesystem** — Inspect the installation directory directly.
- **Exit code** — `session.awaitExit()` blocks until the installer thread exits and returns its exit code.

Wait operations that time out throw a typed `com.install4j.api.test.InstallerTestException` subtype. The full list of exception types is in the [com.install4j.api.test.exceptions package](../../reference/api/test/exceptions/package-summary.md).

### How the installer runs

By default the test API launches the produced installer media as a subprocess and drives it from the test JVM over IPC. The bundled JRE, the native launcher and the actual classloader hierarchy are exercised as in a real installation. The same applies to `com.install4j.api.test.session.UninstallerSession` and `com.install4j.api.test.session.InstallerApplicationSession` where the test API locates the matching launcher inside the installation directory.

On Linux without a usable DISPLAY, the test API wraps the spawned installer subprocess in `xvfb-run` plus a reparenting window manager (`metacity`, `mutter`, `openbox`, `fluxbox` or `marco`) itself. Install one of those as well as `xvfb-run` to run UI tests on a CI machine.

### In-process debug mode

`SessionBuilder.debug(true)` switches the session to an in-process execution where the installer runs inside the test JVM. This mode requires media built with install4jc -g (or --debug) on the [install4jc](../cli/compiler.md) invocation, which additionally produces a `debug_<media-name>/` directory next to the media file with the content already unpacked. The test API throws `com.install4j.api.test.InstallerTestException` if the directory is missing. Use this mode to speed up edit-recompile-test loops or to debug the test.

### Limitations

The test API handles a language selection in-process in both modes, while the normal execution will restart the installer with the correct locale set on the command line. This means that locale-specific features for a non-primary language may be different in the test modes.

### Kotlin extensions

The `com.install4j.api.test.session` package adds idiomatic block-scoped Kotlin helpers on top of `com.install4j.api.test.session.Session`: One `session.onXxx { ... }` wrapper per screen and dialog type, plus `session["varName"]` as the operator form of `session.getVariable`. See the [com.install4j.api.test.session package](../../reference/api/test/session/package-summary.md) overview for the full list.
