1008 lines
25 KiB
Markdown
1008 lines
25 KiB
Markdown
# Dungeon Editor GUI Test Design Document
|
|
|
|
## Overview
|
|
|
|
This document outlines a comprehensive E2E (end-to-end) test suite for the yaze dungeon editor (DungeonEditorV2). The tests are designed to validate the card-based architecture, canvas interactions, object management, and multi-room workflows using ImGuiTestEngine.
|
|
|
|
**Target Test Location**: `test/e2e/dungeon_editor_comprehensive_test.cc`
|
|
|
|
**Existing Tests**:
|
|
- `test/e2e/dungeon_editor_smoke_test.cc` - Basic card open/close
|
|
- `test/e2e/dungeon_visual_verification_test.cc` - Basic room rendering, layer visibility
|
|
|
|
---
|
|
|
|
## Architecture Reference
|
|
|
|
### Card Components (DungeonEditorV2)
|
|
|
|
| Card | Widget ID | Description |
|
|
|------|-----------|-------------|
|
|
| Dungeon Controls | `Dungeon Controls` | Master visibility toggles |
|
|
| Room Selector | `Room Selector` | List of 296 rooms with filtering |
|
|
| Room Matrix | `Room Matrix` | Visual 16x19 grid navigation |
|
|
| Object Editor | `Object Editor` | Object selection and placement |
|
|
| Palette Editor | `Palette Editor` | Color management |
|
|
| Room Cards | `Room 0x00`, `Room 0x01`, ... | Individual room canvases |
|
|
| Entrances | `Entrances` | Entrance configuration |
|
|
| Room Graphics | `Room Graphics` | Graphics sheet viewer |
|
|
| Debug Controls | `Debug Controls` | Development tools |
|
|
|
|
### Canvas Components (DungeonCanvasViewer)
|
|
|
|
| Component | Widget ID | Description |
|
|
|-----------|-----------|-------------|
|
|
| Canvas | `##DungeonCanvas` | Main drawing surface (512x512) |
|
|
| BG1 Toggle | `Show BG1` | Layer 1 visibility |
|
|
| BG2 Toggle | `Show BG2` | Layer 2 visibility |
|
|
|
|
### Object Interaction (DungeonObjectInteraction)
|
|
|
|
| Action | Trigger | Result |
|
|
|--------|---------|--------|
|
|
| Select | Click on object | Sets selected_object_indices_ |
|
|
| Box Select | Drag on empty area | Creates selection rectangle |
|
|
| Place | Click with preview object | Adds object to room |
|
|
| Delete | Delete key | Removes selected objects |
|
|
| Copy/Paste | Ctrl+C/V | Clipboard operations |
|
|
| Context Menu | Right-click | Shows object options |
|
|
|
|
---
|
|
|
|
## Test Scenarios
|
|
|
|
### 1. Object Drawing Tests
|
|
|
|
#### 1.1 Place Single Object on Canvas [P0]
|
|
|
|
**Description**: Verify that an object can be selected from the palette and placed on the canvas.
|
|
|
|
**Preconditions**:
|
|
- ROM loaded
|
|
- Dungeon Editor open
|
|
- Room card active (e.g., Room 0x00)
|
|
- Object Editor visible
|
|
|
|
**Steps**:
|
|
1. Open Object Editor card via Dungeon Controls
|
|
2. Navigate to object category (e.g., "Standard Objects")
|
|
3. Click on object ID 0x01 in object list
|
|
4. Verify preview object is loaded (has_preview_object_ = true)
|
|
5. Click at position (100, 100) on room canvas
|
|
6. Verify object is added to room.GetTileObjects()
|
|
|
|
**Expected Outcome**:
|
|
- Object appears at clicked position
|
|
- Room re-renders with new object
|
|
- Object count increases by 1
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_PlaceSingleObject(ImGuiTestContext* ctx) {
|
|
ctx->LogInfo("=== Test: Place Single Object on Canvas ===");
|
|
|
|
// Setup
|
|
gui::LoadRomInTest(ctx, yaze::test::TestRomManager::GetTestRomPath());
|
|
gui::OpenEditorInTest(ctx, "Dungeon");
|
|
ctx->Yield(20);
|
|
|
|
// Open Room Selector and select room
|
|
ctx->SetRef("Dungeon Controls");
|
|
ctx->ItemClick("Rooms");
|
|
ctx->Yield(5);
|
|
|
|
ctx->SetRef("Room Selector");
|
|
ctx->ItemDoubleClick("Room 0x00");
|
|
ctx->Yield(20);
|
|
|
|
// Open Object Editor
|
|
ctx->SetRef("Dungeon Controls");
|
|
ctx->ItemClick("Objects");
|
|
ctx->Yield(10);
|
|
|
|
// Select object from palette
|
|
if (ctx->WindowInfo("Object Editor").Window != nullptr) {
|
|
ctx->SetRef("Object Editor");
|
|
// Click on first object in list
|
|
if (ctx->ItemExists("##ObjectList/Object 0x01")) {
|
|
ctx->ItemClick("##ObjectList/Object 0x01");
|
|
ctx->Yield(5);
|
|
}
|
|
}
|
|
|
|
// Click on canvas to place object
|
|
if (ctx->WindowInfo("Room 0x00").Window != nullptr) {
|
|
ctx->SetRef("Room 0x00");
|
|
// Click at canvas position
|
|
ctx->MouseMove("##DungeonCanvas", ImVec2(100, 100));
|
|
ctx->MouseClick(ImGuiMouseButton_Left);
|
|
ctx->Yield(10);
|
|
|
|
ctx->LogInfo("Object placed - verifying render");
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### 1.2 Verify Object Positioning Accuracy [P0]
|
|
|
|
**Description**: Ensure objects are placed at the exact grid-snapped coordinates.
|
|
|
|
**Preconditions**:
|
|
- Room with no objects loaded
|
|
- Object selected for placement
|
|
|
|
**Steps**:
|
|
1. Click at position (64, 128) on canvas (8px grid)
|
|
2. Verify object x_ = 8 (64/8), y_ = 16 (128/8)
|
|
3. Click at position (65, 130) (non-grid aligned)
|
|
4. Verify snapping: x_ = 8, y_ = 16 (snapped to grid)
|
|
|
|
**Expected Outcome**:
|
|
- Objects snap to 8px grid boundaries
|
|
- Object coordinates match expected values
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_ObjectPositioning(ImGuiTestContext* ctx) {
|
|
// ... setup code ...
|
|
|
|
ctx->SetRef("Room 0x00");
|
|
|
|
// Test grid-aligned click
|
|
ctx->MouseMove("##DungeonCanvas", ImVec2(64, 128));
|
|
ctx->MouseClick(ImGuiMouseButton_Left);
|
|
ctx->Yield(5);
|
|
|
|
// Verify via object count change (internal state)
|
|
ctx->LogInfo("Placed object at grid position (8, 16)");
|
|
|
|
// Test non-aligned click - should snap
|
|
ctx->MouseMove("##DungeonCanvas", ImVec2(65, 130));
|
|
ctx->MouseClick(ImGuiMouseButton_Left);
|
|
ctx->Yield(5);
|
|
|
|
ctx->LogInfo("Placed object - should snap to (8, 16)");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### 1.3 Multi-Layer Object Rendering [P1]
|
|
|
|
**Description**: Verify objects on different layers (BG1, BG2, BG3) render correctly and in proper order.
|
|
|
|
**Preconditions**:
|
|
- Room loaded with objects on multiple layers
|
|
|
|
**Steps**:
|
|
1. Load Room 0x01 (or room with multi-layer objects)
|
|
2. Verify BG1 objects visible when "Show BG1" checked
|
|
3. Toggle "Show BG1" off
|
|
4. Verify BG1 objects hidden
|
|
5. Toggle "Show BG2" off
|
|
6. Verify BG2 objects hidden
|
|
7. Toggle both back on
|
|
8. Verify rendering order (BG1 behind BG2)
|
|
|
|
**Expected Outcome**:
|
|
- Layer toggles affect only their respective layers
|
|
- Rendering order is correct (BG1 -> BG2 -> BG3)
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_MultiLayerRendering(ImGuiTestContext* ctx) {
|
|
// ... setup and open room ...
|
|
|
|
ctx->SetRef("Room 0x01");
|
|
|
|
// Test BG1 toggle
|
|
if (ctx->ItemExists("Show BG1")) {
|
|
ctx->ItemClick("Show BG1"); // Toggle off
|
|
ctx->Yield(10);
|
|
ctx->LogInfo("BG1 layer hidden");
|
|
|
|
ctx->ItemClick("Show BG1"); // Toggle on
|
|
ctx->Yield(10);
|
|
ctx->LogInfo("BG1 layer visible");
|
|
}
|
|
|
|
// Test BG2 toggle
|
|
if (ctx->ItemExists("Show BG2")) {
|
|
ctx->ItemClick("Show BG2");
|
|
ctx->Yield(10);
|
|
ctx->ItemClick("Show BG2");
|
|
ctx->Yield(10);
|
|
ctx->LogInfo("BG2 layer toggle complete");
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### 1.4 Object Deletion and Undo [P0]
|
|
|
|
**Description**: Verify objects can be deleted and restored via undo.
|
|
|
|
**Preconditions**:
|
|
- Room with at least one object
|
|
- Object selected
|
|
|
|
**Steps**:
|
|
1. Select an object by clicking on it
|
|
2. Press Delete key
|
|
3. Verify object removed from room
|
|
4. Press Ctrl+Z (Undo)
|
|
5. Verify object restored
|
|
6. Press Ctrl+Y (Redo)
|
|
7. Verify object removed again
|
|
|
|
**Expected Outcome**:
|
|
- Delete removes selected objects
|
|
- Undo restores deleted objects
|
|
- Redo re-applies deletion
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_ObjectDeletionUndo(ImGuiTestContext* ctx) {
|
|
// ... setup and place object ...
|
|
|
|
ctx->SetRef("Room 0x00");
|
|
|
|
// Select object (click on it)
|
|
ctx->MouseMove("##DungeonCanvas", ImVec2(100, 100));
|
|
ctx->MouseClick(ImGuiMouseButton_Left);
|
|
ctx->Yield(5);
|
|
|
|
// Delete
|
|
ctx->KeyPress(ImGuiKey_Delete);
|
|
ctx->Yield(10);
|
|
ctx->LogInfo("Object deleted");
|
|
|
|
// Undo (Ctrl+Z)
|
|
ctx->KeyDown(ImGuiMod_Ctrl);
|
|
ctx->KeyPress(ImGuiKey_Z);
|
|
ctx->KeyUp(ImGuiMod_Ctrl);
|
|
ctx->Yield(10);
|
|
ctx->LogInfo("Undo executed - object should be restored");
|
|
|
|
// Redo (Ctrl+Y)
|
|
ctx->KeyDown(ImGuiMod_Ctrl);
|
|
ctx->KeyPress(ImGuiKey_Y);
|
|
ctx->KeyUp(ImGuiMod_Ctrl);
|
|
ctx->Yield(10);
|
|
ctx->LogInfo("Redo executed - object should be deleted again");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 2. Canvas Interaction Tests
|
|
|
|
#### 2.1 Pan and Zoom Functionality [P1]
|
|
|
|
**Description**: Verify canvas can be panned and zoomed.
|
|
|
|
**Preconditions**:
|
|
- Room card open
|
|
- Canvas visible
|
|
|
|
**Steps**:
|
|
1. Middle-mouse drag to pan canvas
|
|
2. Verify scrolling_ values change
|
|
3. Mouse wheel to zoom in
|
|
4. Verify global_scale_ increases
|
|
5. Mouse wheel to zoom out
|
|
6. Verify global_scale_ decreases
|
|
7. Double-click to reset view
|
|
|
|
**Expected Outcome**:
|
|
- Pan moves canvas view
|
|
- Zoom scales canvas content
|
|
- Reset returns to default view
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_PanZoom(ImGuiTestContext* ctx) {
|
|
// ... setup ...
|
|
|
|
ctx->SetRef("Room 0x00");
|
|
|
|
// Pan test (middle-mouse drag)
|
|
ctx->MouseMove("##DungeonCanvas", ImVec2(256, 256));
|
|
ctx->MouseDown(ImGuiMouseButton_Middle);
|
|
ctx->MouseMove("##DungeonCanvas", ImVec2(200, 200));
|
|
ctx->MouseUp(ImGuiMouseButton_Middle);
|
|
ctx->Yield(5);
|
|
ctx->LogInfo("Pan complete");
|
|
|
|
// Zoom in
|
|
ctx->MouseMove("##DungeonCanvas", ImVec2(256, 256));
|
|
ctx->MouseWheel(1.0f); // Scroll up
|
|
ctx->Yield(5);
|
|
ctx->LogInfo("Zoom in complete");
|
|
|
|
// Zoom out
|
|
ctx->MouseWheel(-1.0f); // Scroll down
|
|
ctx->Yield(5);
|
|
ctx->LogInfo("Zoom out complete");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### 2.2 Object Selection via Click [P0]
|
|
|
|
**Description**: Verify clicking on an object selects it.
|
|
|
|
**Preconditions**:
|
|
- Room with objects loaded
|
|
- No current selection
|
|
|
|
**Steps**:
|
|
1. Click on visible object
|
|
2. Verify object_select_active_ = true
|
|
3. Verify selected_object_indices_ contains object index
|
|
4. Click on empty area
|
|
5. Verify selection cleared
|
|
|
|
**Expected Outcome**:
|
|
- Click on object selects it
|
|
- Selection highlight visible
|
|
- Click elsewhere clears selection
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_ObjectSelection(ImGuiTestContext* ctx) {
|
|
// ... setup room with objects ...
|
|
|
|
ctx->SetRef("Room 0x00");
|
|
|
|
// Click on object position
|
|
ctx->MouseMove("##DungeonCanvas", ImVec2(100, 100));
|
|
ctx->MouseClick(ImGuiMouseButton_Left);
|
|
ctx->Yield(5);
|
|
ctx->LogInfo("Object selection attempted");
|
|
|
|
// Click on empty area to deselect
|
|
ctx->MouseMove("##DungeonCanvas", ImVec2(400, 400));
|
|
ctx->MouseClick(ImGuiMouseButton_Left);
|
|
ctx->Yield(5);
|
|
ctx->LogInfo("Selection cleared");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### 2.3 Drag to Reposition Objects [P1]
|
|
|
|
**Description**: Verify objects can be dragged to new positions.
|
|
|
|
**Preconditions**:
|
|
- Object selected
|
|
- Canvas in select mode
|
|
|
|
**Steps**:
|
|
1. Select an object
|
|
2. Click and drag object
|
|
3. Release at new position
|
|
4. Verify object coordinates updated
|
|
5. Verify room re-renders
|
|
|
|
**Expected Outcome**:
|
|
- Object moves with cursor during drag
|
|
- Final position reflects drop location
|
|
- Undo captures original position
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_DragReposition(ImGuiTestContext* ctx) {
|
|
// ... setup with object at (100, 100) ...
|
|
|
|
ctx->SetRef("Room 0x00");
|
|
|
|
// Select object
|
|
ctx->MouseMove("##DungeonCanvas", ImVec2(100, 100));
|
|
ctx->MouseClick(ImGuiMouseButton_Left);
|
|
ctx->Yield(5);
|
|
|
|
// Drag to new position
|
|
ctx->MouseDown(ImGuiMouseButton_Left);
|
|
ctx->MouseMove("##DungeonCanvas", ImVec2(200, 200));
|
|
ctx->MouseUp(ImGuiMouseButton_Left);
|
|
ctx->Yield(10);
|
|
|
|
ctx->LogInfo("Object dragged from (100,100) to (200,200)");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### 2.4 Copy/Paste Objects [P1]
|
|
|
|
**Description**: Verify objects can be copied and pasted.
|
|
|
|
**Preconditions**:
|
|
- Object selected
|
|
|
|
**Steps**:
|
|
1. Select an object
|
|
2. Press Ctrl+C (Copy)
|
|
3. Click at new position
|
|
4. Press Ctrl+V (Paste)
|
|
5. Verify new object created at position
|
|
6. Verify original object unchanged
|
|
|
|
**Expected Outcome**:
|
|
- Copied object stored in clipboard_
|
|
- Paste creates duplicate at cursor position
|
|
- Original object preserved
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_CopyPaste(ImGuiTestContext* ctx) {
|
|
// ... setup with selected object ...
|
|
|
|
// Copy
|
|
ctx->KeyDown(ImGuiMod_Ctrl);
|
|
ctx->KeyPress(ImGuiKey_C);
|
|
ctx->KeyUp(ImGuiMod_Ctrl);
|
|
ctx->Yield(5);
|
|
ctx->LogInfo("Object copied");
|
|
|
|
// Move to new position
|
|
ctx->MouseMove("##DungeonCanvas", ImVec2(300, 300));
|
|
|
|
// Paste
|
|
ctx->KeyDown(ImGuiMod_Ctrl);
|
|
ctx->KeyPress(ImGuiKey_V);
|
|
ctx->KeyUp(ImGuiMod_Ctrl);
|
|
ctx->Yield(10);
|
|
ctx->LogInfo("Object pasted at new position");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### 2.5 Box Selection [P2]
|
|
|
|
**Description**: Verify multiple objects can be selected via drag rectangle.
|
|
|
|
**Preconditions**:
|
|
- Room with multiple objects
|
|
|
|
**Steps**:
|
|
1. Click and drag on empty area
|
|
2. Create selection rectangle encompassing multiple objects
|
|
3. Release
|
|
4. Verify all enclosed objects selected
|
|
|
|
**Expected Outcome**:
|
|
- Selection rectangle visible during drag
|
|
- All objects within rectangle selected
|
|
- Selection persists after mouse release
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_BoxSelection(ImGuiTestContext* ctx) {
|
|
// ... setup room with multiple objects ...
|
|
|
|
ctx->SetRef("Room 0x00");
|
|
|
|
// Start selection drag
|
|
ctx->MouseMove("##DungeonCanvas", ImVec2(50, 50));
|
|
ctx->MouseDown(ImGuiMouseButton_Left);
|
|
ctx->MouseMove("##DungeonCanvas", ImVec2(250, 250));
|
|
ctx->Yield(5); // Let selection rect draw
|
|
ctx->MouseUp(ImGuiMouseButton_Left);
|
|
ctx->Yield(10);
|
|
|
|
ctx->LogInfo("Box selection completed");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 3. Room Navigation Tests
|
|
|
|
#### 3.1 Open Multiple Room Cards [P0]
|
|
|
|
**Description**: Verify multiple rooms can be opened simultaneously.
|
|
|
|
**Preconditions**:
|
|
- Dungeon Editor loaded
|
|
- Room Selector visible
|
|
|
|
**Steps**:
|
|
1. Double-click Room 0x00 in selector
|
|
2. Verify Room 0x00 card opens
|
|
3. Double-click Room 0x01 in selector
|
|
4. Verify Room 0x01 card opens
|
|
5. Verify both cards visible and functional
|
|
6. Verify active_rooms_ contains both IDs
|
|
|
|
**Expected Outcome**:
|
|
- Multiple room cards can coexist
|
|
- Each card is independent
|
|
- Closing one does not affect others
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_MultipleRoomCards(ImGuiTestContext* ctx) {
|
|
// ... setup ...
|
|
|
|
ctx->SetRef("Room Selector");
|
|
|
|
// Open first room
|
|
ctx->ItemDoubleClick("Room 0x00");
|
|
ctx->Yield(20);
|
|
|
|
// Verify first room card
|
|
IM_CHECK(ctx->WindowInfo("Room 0x00").Window != nullptr);
|
|
ctx->LogInfo("Room 0x00 card opened");
|
|
|
|
// Open second room
|
|
ctx->SetRef("Room Selector");
|
|
ctx->ItemDoubleClick("Room 0x01");
|
|
ctx->Yield(20);
|
|
|
|
// Verify both cards exist
|
|
IM_CHECK(ctx->WindowInfo("Room 0x00").Window != nullptr);
|
|
IM_CHECK(ctx->WindowInfo("Room 0x01").Window != nullptr);
|
|
ctx->LogInfo("Both room cards opened successfully");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### 3.2 Side-by-Side Room Comparison [P2]
|
|
|
|
**Description**: Verify two rooms can be viewed side by side for comparison.
|
|
|
|
**Preconditions**:
|
|
- Two room cards open
|
|
|
|
**Steps**:
|
|
1. Open Room 0x00 and Room 0x01
|
|
2. Dock Room 0x01 next to Room 0x00 (side by side)
|
|
3. Verify both render correctly
|
|
4. Verify independent scroll/zoom per room
|
|
|
|
**Expected Outcome**:
|
|
- Both rooms visible simultaneously
|
|
- Operations on one room do not affect other
|
|
- Docking works correctly
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_SideBySideComparison(ImGuiTestContext* ctx) {
|
|
// ... open two rooms ...
|
|
|
|
// Verify both windows exist
|
|
IM_CHECK(ctx->WindowInfo("Room 0x00").Window != nullptr);
|
|
IM_CHECK(ctx->WindowInfo("Room 0x01").Window != nullptr);
|
|
|
|
// Focus and interact with each
|
|
ctx->WindowFocus("Room 0x00");
|
|
ctx->Yield(5);
|
|
ctx->LogInfo("Room 0x00 focused");
|
|
|
|
ctx->WindowFocus("Room 0x01");
|
|
ctx->Yield(5);
|
|
ctx->LogInfo("Room 0x01 focused");
|
|
|
|
// Verify layer toggles are independent
|
|
ctx->SetRef("Room 0x00");
|
|
if (ctx->ItemExists("Show BG1")) {
|
|
ctx->ItemClick("Show BG1"); // Toggle in Room 0
|
|
}
|
|
|
|
ctx->SetRef("Room 0x01");
|
|
// BG1 in Room 0x01 should still be enabled
|
|
ctx->LogInfo("Verified independent layer controls");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### 3.3 Room Switching Performance [P2]
|
|
|
|
**Description**: Verify switching between rooms is responsive.
|
|
|
|
**Preconditions**:
|
|
- Multiple room cards open (3+)
|
|
|
|
**Steps**:
|
|
1. Open rooms 0x00, 0x01, 0x02
|
|
2. Focus Room 0x00
|
|
3. Time: Focus Room 0x02
|
|
4. Verify switch < 100ms
|
|
5. Repeat for other rooms
|
|
|
|
**Expected Outcome**:
|
|
- Room switching is instantaneous (< 100ms)
|
|
- No UI freeze during switch
|
|
- Graphics load progressively if needed
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_RoomSwitchPerformance(ImGuiTestContext* ctx) {
|
|
// ... open multiple rooms ...
|
|
|
|
// Rapid room switching
|
|
for (int i = 0; i < 5; i++) {
|
|
ctx->WindowFocus("Room 0x00");
|
|
ctx->Yield(2);
|
|
ctx->WindowFocus("Room 0x01");
|
|
ctx->Yield(2);
|
|
ctx->WindowFocus("Room 0x02");
|
|
ctx->Yield(2);
|
|
}
|
|
|
|
ctx->LogInfo("Rapid room switching completed without freeze");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 4. Layer System Tests
|
|
|
|
#### 4.1 Toggle Individual Layers [P0]
|
|
|
|
**Description**: Verify each layer can be toggled independently.
|
|
|
|
**Preconditions**:
|
|
- Room card open with objects on multiple layers
|
|
|
|
**Steps**:
|
|
1. Verify "Show BG1" checkbox exists
|
|
2. Toggle BG1 off - verify BG1 objects hidden
|
|
3. Toggle BG1 on - verify BG1 objects visible
|
|
4. Repeat for BG2
|
|
|
|
**Expected Outcome**:
|
|
- Each layer toggle only affects its layer
|
|
- Toggle state persists per room
|
|
- Canvas re-renders on toggle
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_LayerToggles(ImGuiTestContext* ctx) {
|
|
// ... setup room ...
|
|
|
|
ctx->SetRef("Room 0x00");
|
|
|
|
// BG1 toggle test
|
|
if (ctx->ItemExists("Show BG1")) {
|
|
// Get initial state
|
|
bool initial_state = true; // Assume default on
|
|
|
|
ctx->ItemClick("Show BG1"); // Toggle
|
|
ctx->Yield(5);
|
|
ctx->LogInfo("BG1 toggled off");
|
|
|
|
ctx->ItemClick("Show BG1"); // Toggle back
|
|
ctx->Yield(5);
|
|
ctx->LogInfo("BG1 toggled on");
|
|
}
|
|
|
|
// BG2 toggle test
|
|
if (ctx->ItemExists("Show BG2")) {
|
|
ctx->ItemClick("Show BG2");
|
|
ctx->Yield(5);
|
|
ctx->ItemClick("Show BG2");
|
|
ctx->Yield(5);
|
|
ctx->LogInfo("BG2 toggle complete");
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### 4.2 Layer Rendering Order Verification [P1]
|
|
|
|
**Description**: Verify layers render in correct order (BG1 behind BG2).
|
|
|
|
**Preconditions**:
|
|
- Room with overlapping objects on BG1 and BG2
|
|
|
|
**Steps**:
|
|
1. Load room with overlapping layer content
|
|
2. Visually verify BG2 overlays BG1
|
|
3. Toggle BG2 off
|
|
4. Verify BG1 content now visible where previously occluded
|
|
5. Toggle BG2 on
|
|
6. Verify occlusion restored
|
|
|
|
**Expected Outcome**:
|
|
- BG1 renders first (background)
|
|
- BG2 renders on top
|
|
- Toggling reveals underlying layer
|
|
|
|
**Note**: Full verification requires visual inspection or AI vision analysis. Test validates toggle behavior; visual order requires screenshot comparison.
|
|
|
|
---
|
|
|
|
#### 4.3 Per-Room Layer Settings [P1]
|
|
|
|
**Description**: Verify layer settings are independent per room card.
|
|
|
|
**Preconditions**:
|
|
- Two room cards open (Room 0x00, Room 0x01)
|
|
|
|
**Steps**:
|
|
1. In Room 0x00, toggle BG1 off
|
|
2. Switch to Room 0x01
|
|
3. Verify Room 0x01 BG1 is still on
|
|
4. Toggle Room 0x01 BG2 off
|
|
5. Switch back to Room 0x00
|
|
6. Verify Room 0x00 layer states unchanged
|
|
|
|
**Expected Outcome**:
|
|
- Each room maintains its own layer visibility state
|
|
- Switching rooms does not affect layer settings
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_PerRoomLayerSettings(ImGuiTestContext* ctx) {
|
|
// ... open Room 0x00 and Room 0x01 ...
|
|
|
|
// Toggle BG1 off in Room 0x00
|
|
ctx->SetRef("Room 0x00");
|
|
ctx->ItemClick("Show BG1");
|
|
ctx->Yield(5);
|
|
|
|
// Verify Room 0x01 BG1 is unaffected
|
|
ctx->SetRef("Room 0x01");
|
|
// Would need to check checkbox state - ImGuiTestEngine may support this
|
|
ctx->LogInfo("Room 0x01 layer settings should be independent");
|
|
|
|
// Return to Room 0x00, verify state persisted
|
|
ctx->SetRef("Room 0x00");
|
|
ctx->LogInfo("Room 0x00 BG1 should still be off");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 5. Object Editor Integration Tests
|
|
|
|
#### 5.1 Browse Object Categories [P1]
|
|
|
|
**Description**: Verify object categories can be browsed in Object Editor.
|
|
|
|
**Preconditions**:
|
|
- Object Editor card open
|
|
|
|
**Steps**:
|
|
1. Verify object list/tree is visible
|
|
2. Navigate to different object types (Standard, Extended, Special)
|
|
3. Verify objects load for each category
|
|
4. Verify object preview updates when selecting different objects
|
|
|
|
**Expected Outcome**:
|
|
- Object list displays all categories
|
|
- Selecting category shows objects in that category
|
|
- Object preview renders correctly
|
|
|
|
**ImGuiTestEngine Approach**:
|
|
```cpp
|
|
void E2ETest_DungeonEditor_ObjectCategories(ImGuiTestContext* ctx) {
|
|
// ... setup ...
|
|
|
|
ctx->SetRef("Object Editor");
|
|
|
|
// Check for object list
|
|
if (ctx->ItemExists("##ObjectList")) {
|
|
ctx->LogInfo("Object list found");
|
|
|
|
// Try selecting different objects
|
|
if (ctx->ItemExists("##ObjectList/Object 0x00")) {
|
|
ctx->ItemClick("##ObjectList/Object 0x00");
|
|
ctx->Yield(5);
|
|
}
|
|
if (ctx->ItemExists("##ObjectList/Object 0x10")) {
|
|
ctx->ItemClick("##ObjectList/Object 0x10");
|
|
ctx->Yield(5);
|
|
}
|
|
|
|
ctx->LogInfo("Object selection navigation complete");
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### 5.2 Select Object from Palette [P0]
|
|
|
|
**Description**: Verify selecting an object in the palette prepares it for placement.
|
|
|
|
**Preconditions**:
|
|
- Object Editor visible
|
|
- Room card open
|
|
|
|
**Steps**:
|
|
1. Click on object in Object Editor list
|
|
2. Verify SetPreviewObject() called
|
|
3. Verify canvas shows ghost preview when hovering
|
|
4. Verify cursor indicates placement mode
|
|
|
|
**Expected Outcome**:
|
|
- Object selection sets preview object
|
|
- Canvas shows placement ghost
|
|
- Clicking canvas places object
|
|
|
|
---
|
|
|
|
#### 5.3 Preview Object Before Placement [P2]
|
|
|
|
**Description**: Verify object preview shows accurate representation before placement.
|
|
|
|
**Preconditions**:
|
|
- Object selected for placement
|
|
- Canvas hovered
|
|
|
|
**Steps**:
|
|
1. Select object from palette
|
|
2. Move mouse over canvas
|
|
3. Verify ghost preview follows cursor
|
|
4. Verify preview matches object dimensions
|
|
5. Move to invalid area
|
|
6. Verify preview indicates invalid placement
|
|
|
|
**Expected Outcome**:
|
|
- Ghost preview accurate
|
|
- Preview follows cursor
|
|
- Invalid areas indicated
|
|
|
|
---
|
|
|
|
#### 5.4 Place Object on Canvas [P0]
|
|
|
|
**Description**: Verify object placement workflow from selection to canvas.
|
|
|
|
**Preconditions**:
|
|
- Object Editor open
|
|
- Room card open
|
|
|
|
**Steps**:
|
|
1. Open Object Editor
|
|
2. Select object ID 0x05
|
|
3. Click on canvas at position (128, 64)
|
|
4. Verify object added to room
|
|
5. Verify object has correct ID (0x05)
|
|
6. Verify object has correct position (16, 8 in room coords)
|
|
|
|
**Expected Outcome**:
|
|
- Full workflow completes successfully
|
|
- Object placed with correct attributes
|
|
- Room re-renders with new object
|
|
|
|
---
|
|
|
|
## Priority Summary
|
|
|
|
### P0 - Critical (Must Pass)
|
|
1. Place Single Object on Canvas (1.1)
|
|
2. Verify Object Positioning Accuracy (1.2)
|
|
3. Object Deletion and Undo (1.4)
|
|
4. Object Selection via Click (2.2)
|
|
5. Open Multiple Room Cards (3.1)
|
|
6. Toggle Individual Layers (4.1)
|
|
7. Select Object from Palette (5.2)
|
|
8. Place Object on Canvas (5.4)
|
|
|
|
### P1 - Important (Should Pass)
|
|
1. Multi-Layer Object Rendering (1.3)
|
|
2. Pan and Zoom Functionality (2.1)
|
|
3. Drag to Reposition Objects (2.3)
|
|
4. Copy/Paste Objects (2.4)
|
|
5. Layer Rendering Order Verification (4.2)
|
|
6. Per-Room Layer Settings (4.3)
|
|
7. Browse Object Categories (5.1)
|
|
|
|
### P2 - Nice to Have
|
|
1. Box Selection (2.5)
|
|
2. Side-by-Side Room Comparison (3.2)
|
|
3. Room Switching Performance (3.3)
|
|
4. Preview Object Before Placement (5.3)
|
|
|
|
---
|
|
|
|
## Test Infrastructure Requirements
|
|
|
|
### Test Helpers Needed
|
|
|
|
```cpp
|
|
// test/test_utils.h additions
|
|
namespace yaze::test::gui {
|
|
|
|
// Load ROM and wait for initialization
|
|
void LoadRomInTest(ImGuiTestContext* ctx, const std::string& rom_path);
|
|
|
|
// Open specific editor
|
|
void OpenEditorInTest(ImGuiTestContext* ctx, const std::string& editor_name);
|
|
|
|
// Wait for room to fully load (graphics + objects)
|
|
void WaitForRoomLoad(ImGuiTestContext* ctx, int room_id);
|
|
|
|
// Get object count in current room (via automation API)
|
|
int GetRoomObjectCount(ImGuiTestContext* ctx, int room_id);
|
|
|
|
// Verify layer visibility state
|
|
bool IsLayerVisible(ImGuiTestContext* ctx, int room_id, int layer);
|
|
|
|
} // namespace yaze::test::gui
|
|
```
|
|
|
|
### Test Registration
|
|
|
|
```cpp
|
|
// In test/yaze_test.cc
|
|
void RegisterDungeonEditorComprehensiveTests(ImGuiTestEngine* e) {
|
|
// P0 Tests
|
|
ImGuiTest* t;
|
|
|
|
t = IM_REGISTER_TEST(e, "DungeonEditor", "PlaceSingleObject");
|
|
t->TestFunc = E2ETest_DungeonEditor_PlaceSingleObject;
|
|
|
|
t = IM_REGISTER_TEST(e, "DungeonEditor", "ObjectPositioning");
|
|
t->TestFunc = E2ETest_DungeonEditor_ObjectPositioning;
|
|
|
|
// ... register all tests ...
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Notes on ImGuiTestEngine Usage
|
|
|
|
### Widget Reference Patterns
|
|
|
|
```cpp
|
|
// Window reference
|
|
ctx->SetRef("Window Name");
|
|
|
|
// Item within window
|
|
ctx->ItemClick("Button Label");
|
|
ctx->ItemClick("##hidden_id");
|
|
|
|
// Nested items (child windows, lists)
|
|
ctx->ItemClick("##ParentList/Item Label");
|
|
|
|
// Canvas interaction
|
|
ctx->MouseMove("##CanvasId", ImVec2(x, y));
|
|
ctx->MouseClick(ImGuiMouseButton_Left);
|
|
```
|
|
|
|
### Common Assertions
|
|
|
|
```cpp
|
|
// Window exists
|
|
IM_CHECK(ctx->WindowInfo("Window Name").Window != nullptr);
|
|
|
|
// Item exists
|
|
IM_CHECK(ctx->ItemExists("##ItemId"));
|
|
|
|
// Item is visible
|
|
IM_CHECK(ctx->ItemInfo("##ItemId").NavRect.GetArea() > 0);
|
|
```
|
|
|
|
### Timing Considerations
|
|
|
|
- Use `ctx->Yield(N)` for frame-dependent operations
|
|
- N=5 for simple UI updates
|
|
- N=10-20 for graphics loading
|
|
- N=30+ for complex room rendering
|
|
|
|
---
|
|
|
|
## Future Enhancements
|
|
|
|
1. **AI Visual Verification**: Integrate Gemini Vision for screenshot analysis
|
|
2. **Performance Benchmarks**: Add timing assertions for critical operations
|
|
3. **Stress Tests**: Test with maximum objects, all rooms open
|
|
4. **Regression Suite**: Capture known-good screenshots for comparison
|
|
5. **Fuzzing**: Random object placement and manipulation sequences
|