6#include <gmock/gmock.h>
7#include <gtest/gtest.h>
18using ::testing::Return;
26 MOCK_METHOD(absl::StatusOr<AutomationResult>, Ping, (
const std::string&));
30 (
const std::string&,
const std::string&,
bool));
32 (
const std::string&,
int,
int));
34 (
const std::string&));
43 config.
model =
"gemini-2.5-flash";
44 gemini_service_ = std::make_unique<GeminiAIService>(config);
46 gui_client_ = std::make_unique<MockGuiAutomationClient>();
48 controller_ = std::make_unique<AIGUIController>(
49 gemini_service_.get(), gui_client_.get());
55 controller_->Initialize(loop_config);
74 result.
message =
"Click successful";
77 .WillOnce(Return(result));
79 auto status = controller_->ExecuteSingleAction(action,
false);
81 ASSERT_TRUE(status.ok()) << status.status().message();
82 EXPECT_TRUE(status->action_successful);
87 action.
parameters[
"target"] =
"button:NonExistent";
91 result.
message =
"Button not found";
94 .WillOnce(Return(result));
96 auto status = controller_->ExecuteSingleAction(action,
false);
98 EXPECT_FALSE(status.ok());
99 EXPECT_THAT(status.status().message(),
100 ::testing::HasSubstr(
"Click action failed"));
115 result.
message =
"Text entered";
117 EXPECT_CALL(*gui_client_, Type(
"input:TileID",
"0x42",
true))
118 .WillOnce(Return(result));
120 auto status = controller_->ExecuteSingleAction(action,
false);
122 ASSERT_TRUE(status.ok());
123 EXPECT_TRUE(status->action_successful);
132 action.
parameters[
"condition"] =
"window:OverworldEditor";
137 result.
message =
"Condition met";
139 EXPECT_CALL(*gui_client_, Wait(
"window:OverworldEditor", 2000, 100))
140 .WillOnce(Return(result));
142 auto status = controller_->ExecuteSingleAction(action,
false);
144 ASSERT_TRUE(status.ok());
145 EXPECT_TRUE(status->action_successful);
150 action.
parameters[
"condition"] =
"window:NonExistentWindow";
155 result.
message =
"Timeout waiting for condition";
157 EXPECT_CALL(*gui_client_, Wait(
"window:NonExistentWindow", 100, 100))
158 .WillOnce(Return(result));
160 auto status = controller_->ExecuteSingleAction(action,
false);
162 EXPECT_FALSE(status.ok());
171 action.
parameters[
"condition"] =
"tile_placed";
175 result.
message =
"Assertion passed";
179 EXPECT_CALL(*gui_client_, Assert(
"tile_placed"))
180 .WillOnce(Return(result));
182 auto status = controller_->ExecuteSingleAction(action,
false);
184 ASSERT_TRUE(status.ok());
185 EXPECT_TRUE(status->action_successful);
190 action.
parameters[
"condition"] =
"tile_placed";
194 result.
message =
"Assertion failed";
198 EXPECT_CALL(*gui_client_, Assert(
"tile_placed"))
199 .WillOnce(Return(result));
201 auto status = controller_->ExecuteSingleAction(action,
false);
203 EXPECT_FALSE(status.ok());
204 EXPECT_THAT(status.status().message(),
205 ::testing::HasSubstr(
"Assert action failed"));
206 EXPECT_THAT(status.status().message(),
207 ::testing::HasSubstr(
"expected: 0x42"));
208 EXPECT_THAT(status.status().message(),
209 ::testing::HasSubstr(
"actual: 0x00"));
227 testing::InSequence seq;
230 .WillOnce(Return(result));
232 EXPECT_CALL(*gui_client_, Wait(
"window:Overworld Editor", 2000, 100))
233 .WillOnce(Return(result));
235 EXPECT_CALL(*gui_client_, Type(
"input:Map ID",
"5",
true))
236 .WillOnce(Return(result));
239 .WillOnce(Return(result));
241 auto status = controller_->ExecuteSingleAction(action,
false);
243 ASSERT_TRUE(status.ok()) << status.status().message();
244 EXPECT_TRUE(status->action_successful);
252 std::vector<AIAction> actions;
255 action1.
parameters[
"target"] =
"button:Overworld";
256 actions.push_back(action1);
259 action2.
parameters[
"condition"] =
"window:OverworldEditor";
260 actions.push_back(action2);
266 .WillOnce(Return(success_result));
268 EXPECT_CALL(*gui_client_, Wait(
"window:OverworldEditor", 5000, 100))
269 .WillOnce(Return(success_result));
271 auto result = controller_->ExecuteActions(actions);
273 ASSERT_TRUE(result.ok()) << result.status().message();
274 EXPECT_TRUE(result->success);
275 EXPECT_EQ(result->actions_executed.size(), 2);
279 std::vector<AIAction> actions;
283 actions.push_back(action1);
286 action2.
parameters[
"target"] =
"button:NeverReached";
287 actions.push_back(action2);
290 failure_result.
success =
false;
291 failure_result.
message =
"First action failed";
294 .WillOnce(Return(failure_result));
297 EXPECT_CALL(*gui_client_, Click(
"button:NeverReached", _))
300 auto result = controller_->ExecuteActions(actions);
302 EXPECT_FALSE(result.ok());
303 EXPECT_EQ(result->actions_executed.size(), 1);
313 auto status = controller_->ExecuteSingleAction(action,
false);
315 EXPECT_FALSE(status.ok());
316 EXPECT_THAT(status.status().message(),
317 ::testing::HasSubstr(
"Action type not implemented"));
324 auto status = controller_->ExecuteSingleAction(action,
false);
326 EXPECT_FALSE(status.ok());
327 EXPECT_THAT(status.status().message(),
328 ::testing::HasSubstr(
"requires map_id, x, y, and tile"));
Client for automating YAZE GUI through gRPC.
std::unique_ptr< MockGuiAutomationClient > gui_client_
std::unique_ptr< GeminiAIService > gemini_service_
std::unique_ptr< AIGUIController > controller_
MockGuiAutomationClient()
MOCK_METHOD(absl::StatusOr< AutomationResult >, Assert,(const std::string &))
MOCK_METHOD(absl::StatusOr< AutomationResult >, Click,(const std::string &, ClickType))
MOCK_METHOD(absl::StatusOr< AutomationResult >, Type,(const std::string &, const std::string &, bool))
MOCK_METHOD(absl::StatusOr< AutomationResult >, Wait,(const std::string &, int, int))
MOCK_METHOD(absl::Status, Connect,())
MOCK_METHOD(absl::StatusOr< AutomationResult >, Ping,(const std::string &))
ClickType
Type of click action to perform.
Main namespace for the application.
Result of a GUI automation action.
std::string expected_value
Represents a single action to be performed in the GUI.
std::map< std::string, std::string > parameters
Configuration for the AI GUI control loop.
bool enable_vision_verification
bool enable_iterative_refinement