Skip to main content
Version: Latest

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โ€‹

  1. Navigate to MainPage
  2. Open Modal (MainPage becomes hidden)
  3. Navigate to MainPage target (triggers PreviousState transition from Modal)
  4. Verify return to MainPage

Test 2: PreviousState with SettingsPage Hiddenโ€‹

  1. Navigate to SettingsPage
  2. Open Modal (SettingsPage becomes hidden)
  3. Navigate to SettingsPage target (triggers PreviousState transition from Modal)
  4. Verify return to SettingsPage

Test 3: CurrentState Self-Transitionsโ€‹

  1. Navigate to MainPage
  2. Execute refresh (CurrentState transition)
  3. Navigate to SettingsPage
  4. 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:

  1. Import the special marker classes:
import io.github.jspinak.brobot.model.state.special.PreviousState;
import io.github.jspinak.brobot.model.state.special.CurrentState;
  1. Use them in your transitions:
@OutgoingTransition(activate = {PreviousState.class}, ...)
@OutgoingTransition(activate = {CurrentState.class}, ...)
  1. Configure states that can be hidden:
@OutgoingTransition(
activate = {OverlayState.class},
staysVisible = true, // Current state stays visible (hidden)
...
)

Best Practicesโ€‹

  1. Use PreviousState for true overlays - dialogs, menus, popups
  2. Use CurrentState for in-page actions - refresh, pagination, sorting
  3. Set staysVisible correctly - determines if a state becomes hidden
  4. Test with mock mode first - ensures logic works before GUI automation
  5. Use StateNavigator.openState() - leverages the state management system

Learn Moreโ€‹

Source Codeโ€‹

The complete source code for this tutorial is available in the examples/03-core-library/guides/dynamic-transitions/special-states-example/ directory.