feat: Introduce automatic widget registration for ImGui with test engine integration
This commit is contained in:
417
test/imgui/dungeon_editor_tests.cc
Normal file
417
test/imgui/dungeon_editor_tests.cc
Normal file
@@ -0,0 +1,417 @@
|
||||
#include "imgui.h"
|
||||
|
||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
||||
#include "imgui_test_engine/imgui_te_context.h"
|
||||
#include "imgui_test_engine/imgui_te_engine.h"
|
||||
#include "imgui_test_engine/imgui_te_ui.h"
|
||||
#endif
|
||||
|
||||
#include "app/editor/dungeon/dungeon_editor.h"
|
||||
#include "app/gui/widget_id_registry.h"
|
||||
#include "app/rom.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace test {
|
||||
|
||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
||||
|
||||
/**
|
||||
* @file dungeon_editor_tests.cc
|
||||
* @brief Comprehensive ImGui Test Engine tests for the Dungeon Editor
|
||||
*
|
||||
* These tests cover:
|
||||
* - Canvas rendering and visibility
|
||||
* - Room selection and loading
|
||||
* - Object placement and manipulation
|
||||
* - Property editing
|
||||
* - Layer management
|
||||
* - Graphics and palette loading
|
||||
*/
|
||||
|
||||
// ============================================================================
|
||||
// Test Variables and Fixtures
|
||||
// ============================================================================
|
||||
|
||||
struct DungeonEditorTestVars {
|
||||
editor::DungeonEditor* editor = nullptr;
|
||||
Rom* rom = nullptr;
|
||||
bool rom_loaded = false;
|
||||
int selected_room_id = 0;
|
||||
bool canvas_visible = false;
|
||||
ImVec2 canvas_size = ImVec2(0, 0);
|
||||
int object_count = 0;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Canvas Rendering Tests
|
||||
// ============================================================================
|
||||
|
||||
void RegisterDungeonCanvasTests(ImGuiTestEngine* engine) {
|
||||
// Test: Canvas should be visible after room selection
|
||||
ImGuiTest* t =
|
||||
IM_REGISTER_TEST(engine, "dungeon_editor", "canvas_visibility");
|
||||
t->SetVarsDataType<DungeonEditorTestVars>();
|
||||
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
DungeonEditorTestVars& vars = ctx->GetVars<DungeonEditorTestVars>();
|
||||
|
||||
// Wait for the dungeon editor window to be available
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// Verify canvas is present
|
||||
ctx->ItemInfo("Dungeon/Canvas/canvas:DungeonCanvas");
|
||||
IM_CHECK(ctx->ItemInfo("Dungeon/Canvas/canvas:DungeonCanvas").ID != 0);
|
||||
|
||||
// Canvas should be visible
|
||||
ImGuiWindow* canvas_window = ctx->GetWindowByRef("Dungeon/Canvas");
|
||||
IM_CHECK(canvas_window != nullptr);
|
||||
IM_CHECK(canvas_window->Active);
|
||||
|
||||
vars.canvas_visible = true;
|
||||
};
|
||||
|
||||
// Test: Canvas should render after loading ROM
|
||||
t = IM_REGISTER_TEST(engine, "dungeon_editor", "canvas_rendering_after_load");
|
||||
t->SetVarsDataType<DungeonEditorTestVars>();
|
||||
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
DungeonEditorTestVars& vars = ctx->GetVars<DungeonEditorTestVars>();
|
||||
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// Click "Load ROM" button if available
|
||||
if (ctx->ItemExists("File/button:LoadROM")) {
|
||||
ctx->ItemClick("File/button:LoadROM");
|
||||
ctx->Yield(); // Wait for ROM to load
|
||||
}
|
||||
|
||||
// Verify canvas renders something (not blank)
|
||||
// We can check if the canvas texture was created
|
||||
auto canvas_info = ctx->ItemInfo("Dungeon/Canvas/canvas:DungeonCanvas");
|
||||
IM_CHECK(canvas_info.RectFull.GetSize().x > 0 &&
|
||||
canvas_info.RectFull.GetSize().y > 0);
|
||||
|
||||
// Check that the canvas has non-zero size
|
||||
vars.canvas_size = canvas_info.RectFull.GetSize();
|
||||
IM_CHECK(vars.canvas_size.x > 0);
|
||||
IM_CHECK(vars.canvas_size.y > 0);
|
||||
};
|
||||
|
||||
// Test: Canvas should update when room changes
|
||||
t = IM_REGISTER_TEST(engine, "dungeon_editor",
|
||||
"canvas_updates_on_room_change");
|
||||
t->SetVarsDataType<DungeonEditorTestVars>();
|
||||
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// Select room 0
|
||||
ctx->ItemClick("Dungeon/RoomSelector/selectable:Room_0");
|
||||
ctx->Yield();
|
||||
|
||||
// Capture initial canvas state
|
||||
ImVec2 size1 =
|
||||
ctx->ItemInfo("Dungeon/Canvas/canvas:DungeonCanvas").RectFull.GetSize();
|
||||
|
||||
// Select room 1
|
||||
ctx->ItemClick("Dungeon/RoomSelector/selectable:Room_1");
|
||||
ctx->Yield();
|
||||
|
||||
// Canvas should still be valid (may have different content, but same size)
|
||||
ImVec2 size2 =
|
||||
ctx->ItemInfo("Dungeon/Canvas/canvas:DungeonCanvas").RectFull.GetSize();
|
||||
IM_CHECK(size2.x > 0 && size2.y > 0);
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Room Selection Tests
|
||||
// ============================================================================
|
||||
|
||||
void RegisterDungeonRoomSelectorTests(ImGuiTestEngine* engine) {
|
||||
// Test: Room selector should be visible
|
||||
ImGuiTest* t =
|
||||
IM_REGISTER_TEST(engine, "dungeon_editor", "room_selector_visible");
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// Verify room selector table exists
|
||||
ctx->ItemInfo("Dungeon/RoomSelector/table:RoomList");
|
||||
IM_CHECK(ctx->ItemInfo("Dungeon/RoomSelector/table:RoomList").ID != 0);
|
||||
};
|
||||
|
||||
// Test: Clicking room should change selection
|
||||
t = IM_REGISTER_TEST(engine, "dungeon_editor", "room_selection_click");
|
||||
t->SetVarsDataType<DungeonEditorTestVars>();
|
||||
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
DungeonEditorTestVars& vars = ctx->GetVars<DungeonEditorTestVars>();
|
||||
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// Click on room 5
|
||||
ctx->ItemClick("Dungeon/RoomSelector/selectable:Room_5");
|
||||
vars.selected_room_id = 5;
|
||||
|
||||
// Verify the room is now selected (visual feedback should exist)
|
||||
// We can check if the canvas updates or if selection state changes
|
||||
ctx->Yield();
|
||||
|
||||
// Success if we got here without errors
|
||||
IM_CHECK(vars.selected_room_id == 5);
|
||||
};
|
||||
|
||||
// Test: Multiple room tabs should work
|
||||
t = IM_REGISTER_TEST(engine, "dungeon_editor", "room_tabs_switching");
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// Open room 0
|
||||
ctx->ItemClick("Dungeon/RoomSelector/selectable:Room_0");
|
||||
ctx->Yield();
|
||||
|
||||
// Open room 10 (should create a new tab)
|
||||
ctx->ItemClick("Dungeon/RoomSelector/selectable:Room_10");
|
||||
ctx->Yield();
|
||||
|
||||
// Switch back to room 0 tab
|
||||
if (ctx->ItemExists("Dungeon/Canvas/tab:Room_0")) {
|
||||
ctx->ItemClick("Dungeon/Canvas/tab:Room_0");
|
||||
ctx->Yield();
|
||||
|
||||
// Verify we're on room 0
|
||||
IM_CHECK(ctx->ItemInfo("Dungeon/Canvas/tab:Room_0").StatusFlags &
|
||||
ImGuiItemStatusFlags_Opened);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Object Editor Tests
|
||||
// ============================================================================
|
||||
|
||||
void RegisterDungeonObjectEditorTests(ImGuiTestEngine* engine) {
|
||||
// Test: Object selector should be visible
|
||||
ImGuiTest* t =
|
||||
IM_REGISTER_TEST(engine, "dungeon_editor", "object_selector_visible");
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// Verify object selector exists
|
||||
IM_CHECK(ctx->ItemExists("Dungeon/ObjectSelector"));
|
||||
};
|
||||
|
||||
// Test: Selecting object should enable placement mode
|
||||
t = IM_REGISTER_TEST(engine, "dungeon_editor", "object_selection");
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// Click on an object in the selector
|
||||
if (ctx->ItemExists("Dungeon/ObjectSelector/selectable:Object_0")) {
|
||||
ctx->ItemClick("Dungeon/ObjectSelector/selectable:Object_0");
|
||||
ctx->Yield();
|
||||
|
||||
// Object should be selected (visual feedback should exist)
|
||||
// Success if no errors
|
||||
}
|
||||
};
|
||||
|
||||
// Test: Object property panel should show when object selected
|
||||
t = IM_REGISTER_TEST(engine, "dungeon_editor", "object_property_panel");
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// Place or select an object
|
||||
ctx->ItemClick("Dungeon/Canvas/canvas:DungeonCanvas",
|
||||
ImGuiMouseButton_Left);
|
||||
ctx->Yield();
|
||||
|
||||
// Property panel should appear
|
||||
// (This might be conditional on having objects in the room)
|
||||
if (ctx->ItemExists("Dungeon/ObjectEditor/input_int:ObjectID")) {
|
||||
// Can edit object ID
|
||||
ctx->ItemInputValue("Dungeon/ObjectEditor/input_int:ObjectID", 42);
|
||||
ctx->Yield();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Layer Management Tests
|
||||
// ============================================================================
|
||||
|
||||
void RegisterDungeonLayerTests(ImGuiTestEngine* engine) {
|
||||
// Test: Layer controls should be visible
|
||||
ImGuiTest* t =
|
||||
IM_REGISTER_TEST(engine, "dungeon_editor", "layer_controls_visible");
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// Verify layer checkboxes exist
|
||||
if (ctx->ItemExists("Dungeon/ObjectEditor/checkbox:ShowBG1")) {
|
||||
IM_CHECK(ctx->ItemInfo("Dungeon/ObjectEditor/checkbox:ShowBG1").ID != 0);
|
||||
}
|
||||
|
||||
if (ctx->ItemExists("Dungeon/ObjectEditor/checkbox:ShowBG2")) {
|
||||
IM_CHECK(ctx->ItemInfo("Dungeon/ObjectEditor/checkbox:ShowBG2").ID != 0);
|
||||
}
|
||||
};
|
||||
|
||||
// Test: Toggling layer visibility
|
||||
t = IM_REGISTER_TEST(engine, "dungeon_editor", "layer_toggle");
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// Toggle BG1 layer
|
||||
if (ctx->ItemExists("Dungeon/ObjectEditor/checkbox:ShowBG1")) {
|
||||
ctx->ItemClick("Dungeon/ObjectEditor/checkbox:ShowBG1");
|
||||
ctx->Yield();
|
||||
|
||||
// Toggle it back
|
||||
ctx->ItemClick("Dungeon/ObjectEditor/checkbox:ShowBG1");
|
||||
ctx->Yield();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Palette and Graphics Tests
|
||||
// ============================================================================
|
||||
|
||||
void RegisterDungeonGraphicsTests(ImGuiTestEngine* engine) {
|
||||
// Test: Palette editor should open
|
||||
ImGuiTest* t = IM_REGISTER_TEST(engine, "dungeon_editor", "palette_editor");
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// Click "Palette Editor" button if available
|
||||
if (ctx->ItemExists("Dungeon/Toolset/button:PaletteEditor")) {
|
||||
ctx->ItemClick("Dungeon/Toolset/button:PaletteEditor");
|
||||
ctx->Yield();
|
||||
|
||||
// Palette window should open
|
||||
IM_CHECK(ctx->WindowInfo("Palette Editor").Window != nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
// Test: Graphics should load for selected room
|
||||
t = IM_REGISTER_TEST(engine, "dungeon_editor", "graphics_loading");
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// Select a room
|
||||
ctx->ItemClick("Dungeon/RoomSelector/selectable:Room_0");
|
||||
ctx->Yield(2); // Wait for graphics to load
|
||||
|
||||
// Canvas should have valid content
|
||||
auto canvas_info = ctx->ItemInfo("Dungeon/Canvas/canvas:DungeonCanvas");
|
||||
IM_CHECK(canvas_info.RectFull.GetWidth() > 0);
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Integration Tests
|
||||
// ============================================================================
|
||||
|
||||
void RegisterDungeonIntegrationTests(ImGuiTestEngine* engine) {
|
||||
// Test: Full workflow - load ROM, select room, place object
|
||||
ImGuiTest* t =
|
||||
IM_REGISTER_TEST(engine, "dungeon_editor", "full_edit_workflow");
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// 1. Load ROM (if needed)
|
||||
ctx->Yield(2);
|
||||
|
||||
// 2. Select a room
|
||||
ctx->ItemClick("Dungeon/RoomSelector/selectable:Room_5");
|
||||
ctx->Yield(2);
|
||||
|
||||
// 3. Select an object type
|
||||
if (ctx->ItemExists("Dungeon/ObjectSelector/selectable:Object_1")) {
|
||||
ctx->ItemClick("Dungeon/ObjectSelector/selectable:Object_1");
|
||||
ctx->Yield();
|
||||
}
|
||||
|
||||
// 4. Click on canvas to place object
|
||||
ctx->ItemClick("Dungeon/Canvas/canvas:DungeonCanvas",
|
||||
ImGuiMouseButton_Left);
|
||||
ctx->Yield();
|
||||
|
||||
// 5. Verify object was placed (property panel should appear)
|
||||
// This is a basic workflow test - success if no crashes
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Widget Discovery Tests
|
||||
// ============================================================================
|
||||
|
||||
void RegisterDungeonWidgetDiscoveryTests(ImGuiTestEngine* engine) {
|
||||
// Test: Widget registry should capture all dungeon editor widgets
|
||||
ImGuiTest* t =
|
||||
IM_REGISTER_TEST(engine, "dungeon_editor", "widget_registry_complete");
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
|
||||
// Yield a few frames to let widgets register
|
||||
ctx->Yield(3);
|
||||
|
||||
// Query the widget registry
|
||||
auto& registry = gui::WidgetIdRegistry::Instance();
|
||||
auto all_widgets = registry.GetAllWidgets();
|
||||
|
||||
// Should have multiple widgets registered
|
||||
IM_CHECK(all_widgets.size() > 10);
|
||||
|
||||
// Essential widgets should be present
|
||||
IM_CHECK(registry.GetWidgetId("Dungeon/RoomSelector/table:RoomList") != 0);
|
||||
IM_CHECK(registry.GetWidgetId("Dungeon/Canvas/canvas:DungeonCanvas") != 0);
|
||||
};
|
||||
|
||||
// Test: Export widget catalog
|
||||
t = IM_REGISTER_TEST(engine, "dungeon_editor", "widget_catalog_export");
|
||||
t->TestFunc = [](ImGuiTestContext* ctx) {
|
||||
ctx->SetRef("Dungeon Editor");
|
||||
ctx->Yield(2);
|
||||
|
||||
auto& registry = gui::WidgetIdRegistry::Instance();
|
||||
|
||||
// Export to JSON
|
||||
std::string json_catalog = registry.ExportCatalog("json");
|
||||
IM_CHECK(!json_catalog.empty());
|
||||
IM_CHECK(json_catalog.find("\"widgets\"") != std::string::npos);
|
||||
|
||||
// Export to YAML
|
||||
std::string yaml_catalog = registry.ExportCatalog("yaml");
|
||||
IM_CHECK(!yaml_catalog.empty());
|
||||
IM_CHECK(yaml_catalog.find("widgets:") != std::string::npos);
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Registration Function
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* @brief Register all dungeon editor tests with the ImGui Test Engine
|
||||
*
|
||||
* Call this function during application initialization to register all
|
||||
* automated tests for the dungeon editor.
|
||||
*
|
||||
* @param engine The ImGuiTestEngine instance
|
||||
*/
|
||||
void RegisterDungeonEditorTests(ImGuiTestEngine* engine) {
|
||||
RegisterDungeonCanvasTests(engine);
|
||||
RegisterDungeonRoomSelectorTests(engine);
|
||||
RegisterDungeonObjectEditorTests(engine);
|
||||
RegisterDungeonLayerTests(engine);
|
||||
RegisterDungeonGraphicsTests(engine);
|
||||
RegisterDungeonIntegrationTests(engine);
|
||||
RegisterDungeonWidgetDiscoveryTests(engine);
|
||||
}
|
||||
|
||||
#endif // IMGUI_ENABLE_TEST_ENGINE
|
||||
|
||||
} // namespace test
|
||||
} // namespace yaze
|
||||
Reference in New Issue
Block a user