Special States Tutorial
This tutorial demonstrates the use of special state markers in Brobot for handling dynamic transitions and overlays.
What You'll Learnโ
- How to use PreviousState for returning to hidden states
- How to use CurrentState for self-transitions
- How hidden state management works automatically
- Best practices for overlay handling
Project Structureโ
The complete example project is located in examples/03-core-library/guides/dynamic-transitions/special-states-example/ and includes:
special-states-example/
โโโ src/main/java/com/example/specialstates/
โ โโโ states/
โ โ โโโ MainPageState.java # Main page that can be hidden by modal
โ โ โโโ ModalDialogState.java # Modal that overlays other states
โ โ โโโ SettingsPageState.java # Settings page that can also be hidden
โ โโโ transitions/
โ โ โโโ MainPageTransitions.java # Includes CurrentState transitions
โ โ โโโ ModalDialogTransitions.java # Uses PreviousState to return
โ โ โโโ SettingsPageTransitions.java # Can open modal and self-transition
โ โโโ runner/
โ โ โโโ SpecialStatesTestRunner.java # Test scenarios
โ โโโ SpecialStatesApplication.java # Main Spring Boot application
โโโ src/main/resources/
โโโ application.properties # Mock mode configuration
Key Concepts Demonstratedโ
PreviousState - Dynamic Returnsโ
When a modal dialog opens over any page, it "hides" that page. Using PreviousState as the target allows the modal to return to whatever was hidden, without hard-coding specific states:
@OutgoingTransition(
activate = {PreviousState.class}, // Returns to whatever was hidden
staysVisible = false, // Modal closes
pathCost = 0
)
public boolean closeModal() {
// This returns to MainPage OR SettingsPage
// depending on what was hidden
return action.click(closeButton).isSuccess();
}
CurrentState - Self-Transitionsโ
Actions that modify the current page without navigation use CurrentState:
@OutgoingTransition(
activate = {CurrentState.class}, // Stay in current state
pathCost = 2,
description = "Refresh page"
)
public boolean refresh() {
// Executes action but stays on same page
return action.type("{F5}").isSuccess();
}
Test Scenariosโ
The example includes three test scenarios that demonstrate these concepts:
Test 1: PreviousState with MainPage Hiddenโ
- Navigate to MainPage
- Open Modal (MainPage becomes hidden)
- Navigate to MainPage target (triggers PreviousState transition from Modal)
- Verify return to MainPage
Test 2: PreviousState with SettingsPage Hiddenโ
- Navigate to SettingsPage
- Open Modal (SettingsPage becomes hidden)
- Navigate to SettingsPage target (triggers PreviousState transition from Modal)
- Verify return to SettingsPage
Test 3: CurrentState Self-Transitionsโ
- Navigate to MainPage
- Execute refresh (CurrentState transition)
- Navigate to SettingsPage
- Execute save settings (CurrentState transition)
Running the Exampleโ
From the brobot root directory:
# Build the example
./gradlew :examples:03-core-library:guides:dynamic-transitions:special-states-example:build
# Run the example
./gradlew :examples:03-core-library:guides:dynamic-transitions:special-states-example:bootRun
The application runs in mock mode (no real GUI required) and demonstrates:
- โ PreviousState returns to correct hidden state
- โ CurrentState maintains current state
- โ Hidden states are tracked automatically
Configurationโ
The application.properties enables mock mode for testing:
# Enable mock mode for testing without GUI
brobot.mock=true
# Enable verbose logging to see state transitions
brobot.logging.verbosity=VERBOSE
brobot.console.actions.enabled=true
brobot.console.actions.level=VERBOSE
# Fast mock timings
brobot.action.maxWait=0.04
brobot.action.pauseTime=0.01
Integration with Your Projectโ
To use special states in your own Brobot project:
- Import the special marker classes:
import io.github.jspinak.brobot.model.state.special.PreviousState;
import io.github.jspinak.brobot.model.state.special.CurrentState;
- Use them in your transitions:
@OutgoingTransition(activate = {PreviousState.class}, ...)
@OutgoingTransition(activate = {CurrentState.class}, ...)
- Configure states that can be hidden:
@OutgoingTransition(
activate = {OverlayState.class},
staysVisible = true, // Current state stays visible (hidden)
...
)
Best Practicesโ
- Use PreviousState for true overlays - dialogs, menus, popups
- Use CurrentState for in-page actions - refresh, pagination, sorting
- Set staysVisible correctly - determines if a state becomes hidden
- Test with mock mode first - ensures logic works before GUI automation
- Use StateNavigator.openState() - leverages the state management system
Learn Moreโ
- Dynamic Transitions Guide - Complete reference
- Core Concepts - Understanding states
- Transitions Overview - Transition basics
Source Codeโ
The complete source code for this tutorial is available in the examples/03-core-library/guides/dynamic-transitions/special-states-example/ directory.