Brobot AI Implementation Guide - Complete Reference
๐ฅ QUICK REFERENCE CARDโ
Do's and Don'ts at a Glanceโ
โ DO | โ DON'T |
---|---|
Use Navigation.openState("Menu") | Create a TransitionManager class |
States: Objects only (StateImage, StateString) | States: Add methods like clickButton() or isActive() |
Transitions: Methods only | Transitions: Create StateImage objects |
One TransitionSet per State | Multiple transition classes per state |
Use ClickOptions.setPauseAfterEnd(2.0) | Use Thread.sleep(2000) |
State class: MenuState | State class: Menu |
Navigate with: openState("Menu") | Navigate with: openState("MenuState") |
@State annotation only | @State + @Component |
Use Brobot's Action service | Use SikuliX directly or java.awt.Robot |
FUNDAMENTAL PRINCIPLESโ
The Brobot Architecture Philosophyโ
Brobot follows a strict separation of concerns:
Component | Purpose | What it Contains | What it NEVER Contains |
---|---|---|---|
State Classes | Data containers | StateImage/StateString objects only | Methods, business logic, actions |
TransitionSet Classes | Navigation logic | Methods for state transitions | StateImage objects, state data |
Navigation Service | Orchestrates transitions | Path finding and execution | Direct state manipulation |
Action Service | Performs UI operations | Click, type, find methods | Thread.sleep(), direct SikuliX calls |
Key Architecture Rulesโ
- States are Pure Data - Think of them as structs or POJOs. They hold UI element definitions, nothing else.
- One TransitionSet Per State - Each state has exactly ONE TransitionSet class managing ALL its transitions.
- Never Create a TransitionManager - Use Navigation service. A central TransitionManager is an anti-pattern.
- State Names are Automatic - Derived from class name minus "State" suffix. No StateEnum field needed.
- @State Includes @Component - Never add @Component to State classes.
- ActionHistory is Optional - Only needed for mock mode testing, not required for production.
CRITICAL RULES - NEVER VIOLATE THESEโ
Rule 1: NEVER Use External Functionsโ
These will BREAK the entire model-based automation system:
// โ ABSOLUTELY FORBIDDEN - These break everything:
Thread.sleep(2000); // Breaks mock testing completely
action.pause(2.0); // This method DOES NOT EXIST in Brobot
java.awt.Robot robot = new Robot(); // Circumvents automation model
org.sikuli.script.Screen.wait(pattern, 5); // Bypasses wrapper functions
org.sikuli.script.Mouse.move(location); // Direct SikuliX calls break mocking
// โ
CORRECT - Always use Brobot's ActionConfig options:
ClickOptions clickWithPause = new ClickOptions.Builder()
.setPauseBeforeBegin(1.0) // Wait 1 second before clicking
.setPauseAfterEnd(2.0) // Wait 2 seconds after clicking
.build();
action.click(stateImage, clickWithPause);
PatternFindOptions findWithPause = new PatternFindOptions.Builder()
.setPauseBeforeBegin(0.5)
.setPauseAfterEnd(1.0)
.setWaitTime(5.0) // Wait up to 5 seconds for pattern to appear
.build();
action.find(stateImage, findWithPause);
Rule 2: NEVER Call Transitions Directlyโ
// โ WRONG - Never call transition methods directly:
@Component
public class WrongApplication {
@Autowired
private MenuToPricingTransition transition;
public void run() {
transition.execute(); // โ NEVER DO THIS
transition.fromMenu(); // โ NEVER DO THIS
transition.verifyArrival(); // โ NEVER DO THIS
}
}
// โ
CORRECT - Always use Navigation service:
@Component
@RequiredArgsConstructor
public class CorrectApplication {
private final Navigation navigation;
private final Action action;
private final PricingState pricingState;
public void run() {
// Navigate using state name (WITHOUT "State" suffix)
navigation.openState("Pricing"); // โ
CORRECT
// Then perform actions on the state
action.click(pricingState.getStartButton());
}
}
Rule 3: State Naming Convention Is Mandatoryโ
// Class names MUST end with "State"
public class MenuState { } // โ
CORRECT
public class PricingState { } // โ
CORRECT
public class Menu { } // โ WRONG
// Navigation uses name WITHOUT "State"
navigation.openState("Menu"); // โ
CORRECT - for MenuState class
navigation.openState("Pricing"); // โ
CORRECT - for PricingState class
navigation.openState("MenuState"); // โ WRONG - don't include "State"
Rule 4: State Classes Have Objects, Not Methodsโ
CRITICAL: State classes are pure data containers
// โ
CORRECT State class - ONLY objects, NO methods
@State // @State includes @Component, don't add it separately
@Getter
public class MenuState {
// ONLY StateImage/StateString objects
private final StateImage logo;
private final StateImage pricingButton;
public MenuState() {
// Initialize objects in constructor
logo = new StateImage.Builder()
.addPatterns("menu/menu-logo")
.setName("Menu Logo")
.build();
pricingButton = new StateImage.Builder()
.addPatterns("menu/menu-pricing")
.setName("Pricing Button")
.build();
}
// NO ACTION METHODS HERE!
}
// โ WRONG State class - has methods
@State
public class MenuState {
private final StateImage logo;
// โ WRONG - States should NOT have action methods
public void clickLogo() {
action.click(logo);
}
// โ WRONG - States should NOT have business logic
public boolean isActive() {
return action.find(logo).isSuccess();
}
}
Rule 5: Transition Classes Have Methods, Not State Objectsโ
CRITICAL: Transition classes contain navigation logic only
// โ
CORRECT Transition class - methods only, receives state via DI
@TransitionSet(state = MenuState.class)
@RequiredArgsConstructor
public class MenuTransitions {
// Only inject the state and action service
private final MenuState menuState; // The state this TransitionSet manages
private final Action action;
// Methods for navigation
@OutgoingTransition(to = PricingState.class)
public boolean toPricing() {
return action.click(menuState.getPricingButton()).isSuccess();
}
@IncomingTransition
public boolean verifyArrival() {
return action.find(menuState.getLogo()).isSuccess();
}
}
// โ WRONG Transition class - has StateImage objects
@TransitionSet(state = MenuState.class)
public class MenuTransitions {
// โ WRONG - Don't define StateImages in transitions
private final StateImage pricingButton;
// โ WRONG - Don't initialize objects here
public MenuTransitions() {
pricingButton = new StateImage.Builder()...
}
}
COMPLETE PROJECT STRUCTUREโ
my-automation-project/
โโโ images/
โ โโโ menu/
โ โ โโโ menu-logo.png
โ โ โโโ menu-pricing.png
โ โ โโโ menu-home.png
โ โโโ pricing/
โ โ โโโ pricing-start_for_free.png
โ โ โโโ pricing-header.png
โ โโโ homepage/
โ โโโ start_for_free_big.png
โ โโโ enter_your_email.png
โโโ src/
โ โโโ main/
โ โ โโโ java/
โ โ โ โโโ com/example/automation/
โ โ โ โโโ Application.java # Spring Boot main class
โ โ โ โโโ states/
โ โ โ โ โโโ MenuState.java
โ โ โ โ โโโ PricingState.java
โ โ โ โ โโโ HomepageState.java
โ โ โ โโโ transitions/
โ โ โ โ โโโ MenuTransitions.java # ALL transitions for Menu
โ โ โ โ โโโ PricingTransitions.java # ALL transitions for Pricing
โ โ โ โ โโโ HomepageTransitions.java # ALL transitions for Homepage
โ โ โ โโโ runner/