Files
yaze/test/e2e/imgui_test_engine_demo.cc
2025-12-22 14:49:04 -05:00

289 lines
7.9 KiB
C++

#define IMGUI_DEFINE_MATH_OPERATORS
#include "e2e/imgui_test_engine_demo.h"
#include "app/controller.h"
#include "app/test/screenshot_assertion.h"
#include "imgui.h"
#include "imgui_test_engine/imgui_te_context.h"
#include "imgui_test_engine/imgui_te_engine.h" // Added include for ImGuiTestEngine
#include "test_utils.h"
namespace yaze {
namespace test {
/**
* @brief Demo: Basic ImGui Test Engine interaction patterns.
*
* This test demonstrates fundamental ImGui Test Engine features:
* - Window focus and navigation
* - Menu interaction
* - Button clicks
* - Keyboard input
* - Mouse movement and dragging
*/
void E2ETest_ImGuiBasicInteraction(ImGuiTestContext* ctx) {
// Set reference window for navigation
ctx->SetRef("Yaze");
// Test 1: Menu navigation
ctx->LogInfo("Testing menu navigation...");
ctx->MenuCheck("View/Show Demo Window");
ctx->Yield(5);
// Test 2: Window focus
ctx->WindowFocus("Dear ImGui Demo");
ctx->Yield(3);
// Test 3: Tree node expansion
ctx->ItemOpen("Widgets");
ctx->Yield(2);
// Test 4: Button click
ctx->ItemClick("Basic/Button");
ctx->Yield(2);
// Test 5: Close the demo window
ctx->WindowClose("Dear ImGui Demo");
ctx->LogInfo("Basic interaction test completed");
}
/**
* @brief Demo: Mouse interaction and coordinate verification.
*
* Shows how to:
* - Move mouse to specific coordinates
* - Perform drag operations
* - Verify mouse position
*/
void E2ETest_ImGuiMouseInteraction(ImGuiTestContext* ctx) {
ctx->SetRef("Yaze");
// Open a canvas-based editor
ctx->MenuClick("View/Overworld Editor");
ctx->Yield(10);
ctx->WindowFocus("Overworld Editor");
// Find a canvas widget
ImGuiTestItemInfo canvas = ctx->ItemInfo("##OverworldCanvas");
if (canvas.ID != 0) {
// Get canvas bounds
ImRect bounds = canvas.RectClipped;
// Test: Click at canvas center
ImVec2 center((bounds.Min.x + bounds.Max.x) / 2,
(bounds.Min.y + bounds.Max.y) / 2);
ctx->MouseMoveToPos(center);
ctx->MouseClick(0);
ctx->LogInfo("Clicked canvas at (%.1f, %.1f)", center.x, center.y);
// Test: Drag selection
ImVec2 drag_start(bounds.Min.x + 50, bounds.Min.y + 50);
ImVec2 drag_end(bounds.Min.x + 150, bounds.Min.y + 150);
ctx->MouseMoveToPos(drag_start);
ctx->MouseDown(0);
ctx->MouseMoveToPos(drag_end);
ctx->MouseUp(0);
ctx->LogInfo("Dragged from (%.1f, %.1f) to (%.1f, %.1f)", drag_start.x,
drag_start.y, drag_end.x, drag_end.y);
} else {
ctx->LogWarning("Canvas not found - skipping mouse interaction test");
}
}
/**
* @brief Demo: Keyboard shortcuts and input.
*
* Tests common keyboard shortcuts like:
* - Ctrl+S (Save)
* - Ctrl+Z (Undo)
* - Ctrl+Y (Redo)
* - Arrow keys for navigation
*/
void E2ETest_ImGuiKeyboardShortcuts(ImGuiTestContext* ctx) {
gui::LoadRomInTest(ctx, yaze::test::TestRomManager::GetTestRomPath());
ctx->SetRef("Yaze");
ctx->WindowFocus("Overworld Editor");
ctx->Yield(5);
// Test: Undo shortcut
ctx->LogInfo("Testing Ctrl+Z (Undo)...");
ctx->KeyDown(ImGuiMod_Ctrl);
ctx->KeyPress(ImGuiKey_Z);
ctx->KeyUp(ImGuiMod_Ctrl);
ctx->Yield(2);
// Test: Redo shortcut
ctx->LogInfo("Testing Ctrl+Y (Redo)...");
ctx->KeyDown(ImGuiMod_Ctrl);
ctx->KeyPress(ImGuiKey_Y);
ctx->KeyUp(ImGuiMod_Ctrl);
ctx->Yield(2);
// Test: Arrow key navigation
ctx->LogInfo("Testing arrow key navigation...");
ctx->KeyPress(ImGuiKey_RightArrow);
ctx->KeyPress(ImGuiKey_DownArrow);
ctx->KeyPress(ImGuiKey_LeftArrow);
ctx->KeyPress(ImGuiKey_UpArrow);
ctx->LogInfo("Keyboard shortcuts test completed");
}
/**
* @brief Demo: Widget state verification.
*
* Demonstrates how to check widget states:
* - Checkbox states
* - Input field values
* - Combo box selection
*/
void E2ETest_ImGuiWidgetState(ImGuiTestContext* ctx) {
ctx->SetRef("Yaze");
// Open settings dialog
ctx->MenuClick("Edit/Settings");
ctx->Yield(5);
ctx->WindowFocus("Settings");
// Test: Check if a checkbox exists and interact with it
ImGuiTestItemInfo item = ctx->ItemInfo("**/Dark Mode");
if (item.ID != 0) {
// Toggle the checkbox
ctx->ItemClick("**/Dark Mode");
ctx->Yield(2);
ctx->LogInfo("Toggled Dark Mode checkbox");
}
// Close settings
ctx->WindowClose("Settings");
}
/**
* @brief Demo: Combining ImGui Test Engine with Screenshot Assertions.
*
* This test shows how to integrate our AI test infrastructure with
* the ImGui Test Engine for comprehensive visual verification.
*/
void E2ETest_ImGuiWithScreenshotAssertion(ImGuiTestContext* ctx) {
gui::LoadRomInTest(ctx, yaze::test::TestRomManager::GetTestRomPath());
ctx->SetRef("Yaze");
ctx->MenuClick("View/Graphics Editor");
ctx->Yield(10);
ctx->WindowFocus("Graphics Editor");
// Set up screenshot assertion (would need actual framebuffer capture)
ComparisonConfig config;
config.tolerance = 0.95f;
config.algorithm = ComparisonConfig::Algorithm::kPixelExact;
ScreenshotAssertion asserter;
asserter.SetConfig(config);
// Register capture callback that uses ImGui's framebuffer
// In real implementation, this would capture from SDL/OpenGL
asserter.SetCaptureCallback([]() -> absl::StatusOr<Screenshot> {
Screenshot shot;
// Would capture actual framebuffer here
shot.width = 1280;
shot.height = 720;
shot.data.resize(shot.width * shot.height * 4, 128);
return shot;
});
// Capture baseline before interaction
auto baseline_status = asserter.CaptureBaseline("graphics_baseline");
IM_CHECK(baseline_status.ok());
ctx->LogInfo("Captured baseline screenshot");
// Perform an action - click on a graphics sheet
ctx->ItemClick("**/Sheet_0");
ctx->Yield(5);
// Verify the UI changed
auto change_result = asserter.AssertChanged("graphics_baseline");
if (change_result.ok()) {
ctx->LogInfo("Change detection: %s (similarity: %.2f%%)",
change_result->passed ? "CHANGED" : "UNCHANGED",
change_result->similarity * 100.0f);
// In a real test, we'd assert change->passed is true
}
ctx->LogInfo("Screenshot assertion test completed");
}
/**
* @brief Demo: Test timing and synchronization.
*
* Shows how to handle timing-sensitive operations:
* - Waiting for UI updates
* - Yielding for animations
* - Verifying state after delays
*/
void E2ETest_ImGuiTimingDemo(ImGuiTestContext* ctx) {
ctx->SetRef("Yaze");
// Test speed affects how long Yield() waits
ctx->LogInfo("Current test speed: %d", ImGuiTestEngine_GetIO(ctx->Engine).ConfigRunSpeed);
// Open an editor that has loading time
ctx->MenuClick("View/Dungeon Editor");
// Yield for the editor to fully load
ctx->LogInfo("Waiting for editor to load...");
ctx->Yield(20);
// Check if the editor window appeared
ImGuiWindow* window = ctx->GetWindowByRef("Dungeon Editor");
if (window) {
ctx->LogInfo("Dungeon Editor loaded successfully");
IM_CHECK(window->Active || window->WasActive);
} else {
ctx->LogWarning("Dungeon Editor window not found");
}
// Yield can also be used with frame counts
ctx->LogInfo("Yielding for 10 frames...");
ctx->Yield(10);
ctx->LogInfo("Timing demo completed");
}
/**
* @brief Demo: Error handling and recovery.
*
* Shows how to handle:
* - Missing widgets gracefully
* - Failed operations
* - Test recovery
*/
void E2ETest_ImGuiErrorHandling(ImGuiTestContext* ctx) {
ctx->SetRef("Yaze");
// Attempt to interact with a non-existent widget
ctx->LogInfo("Testing missing widget handling...");
ImGuiTestItemInfo item = ctx->ItemInfo("NonExistentWidget");
if (item.ID == 0) {
ctx->LogInfo("Correctly detected missing widget");
}
// Try to click something that might not exist
// Using ItemClick with ImGuiTestOpFlags_NoError to suppress errors
ctx->ItemClick("**/MaybeExistsButton", 0, ImGuiTestOpFlags_NoError);
// Recovery: ensure we're in a known good state
ctx->SetRef("Yaze");
ctx->WindowFocus(""); // Focus main window
ctx->LogInfo("Error handling demo completed");
}
} // namespace test
} // namespace yaze