Add XCUI new editor sandbox phase 1
This commit is contained in:
192
tests/NewEditor/test_xcui_layout_lab_runtime.cpp
Normal file
192
tests/NewEditor/test_xcui_layout_lab_runtime.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "XCUIBackend/XCUILayoutLabRuntime.h"
|
||||
|
||||
#include <XCEngine/UI/Types.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::UI::UIDrawCommand;
|
||||
using XCEngine::UI::UIDrawCommandType;
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState BuildInputState(
|
||||
float width = 960.0f,
|
||||
float height = 640.0f) {
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState input = {};
|
||||
input.canvasRect = XCEngine::UI::UIRect(0.0f, 0.0f, width, height);
|
||||
input.pointerPosition = XCEngine::UI::UIPoint(width * 0.5f, height * 0.5f);
|
||||
input.pointerInside = true;
|
||||
return input;
|
||||
}
|
||||
|
||||
std::vector<const UIDrawCommand*> CollectTextCommands(const XCEngine::UI::UIDrawData& drawData) {
|
||||
std::vector<const UIDrawCommand*> textCommands = {};
|
||||
for (const XCEngine::UI::UIDrawList& drawList : drawData.GetDrawLists()) {
|
||||
for (const UIDrawCommand& command : drawList.GetCommands()) {
|
||||
if (command.type == UIDrawCommandType::Text) {
|
||||
textCommands.push_back(&command);
|
||||
}
|
||||
}
|
||||
}
|
||||
return textCommands;
|
||||
}
|
||||
|
||||
const UIDrawCommand* FindTextCommand(
|
||||
const XCEngine::UI::UIDrawData& drawData,
|
||||
const std::string& text) {
|
||||
for (const XCEngine::UI::UIDrawList& drawList : drawData.GetDrawLists()) {
|
||||
for (const UIDrawCommand& command : drawList.GetCommands()) {
|
||||
if (command.type == UIDrawCommandType::Text && command.text == text) {
|
||||
return &command;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::size_t CountCommandsOfType(
|
||||
const XCEngine::UI::UIDrawData& drawData,
|
||||
UIDrawCommandType type) {
|
||||
std::size_t count = 0;
|
||||
for (const XCEngine::UI::UIDrawList& drawList : drawData.GetDrawLists()) {
|
||||
for (const UIDrawCommand& command : drawList.GetCommands()) {
|
||||
if (command.type == type) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(NewEditorXCUILayoutLabRuntimeTest, UpdateBuildsLayoutSmokeFrame) {
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabRuntime runtime;
|
||||
const bool reloadSucceeded = runtime.ReloadDocuments();
|
||||
|
||||
const auto& frame = runtime.Update(BuildInputState());
|
||||
EXPECT_EQ(frame.stats.documentsReady, reloadSucceeded);
|
||||
EXPECT_EQ(frame.stats.drawListCount, frame.drawData.GetDrawListCount());
|
||||
EXPECT_EQ(frame.stats.commandCount, frame.drawData.GetTotalCommandCount());
|
||||
|
||||
if (frame.stats.documentsReady) {
|
||||
EXPECT_GT(frame.stats.drawListCount, 0u);
|
||||
EXPECT_GT(frame.stats.commandCount, 0u);
|
||||
EXPECT_GE(frame.stats.rowCount, 1u);
|
||||
EXPECT_GE(frame.stats.columnCount, 1u);
|
||||
EXPECT_GE(frame.stats.overlayCount, 1u);
|
||||
EXPECT_GE(frame.stats.scrollViewCount, 2u);
|
||||
|
||||
XCEngine::UI::UIRect heroRect = {};
|
||||
EXPECT_TRUE(runtime.TryGetElementRect("heroCard", heroRect));
|
||||
EXPECT_GT(heroRect.width, 0.0f);
|
||||
EXPECT_GT(heroRect.height, 0.0f);
|
||||
} else {
|
||||
EXPECT_FALSE(frame.stats.statusMessage.empty());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NewEditorXCUILayoutLabRuntimeTest, FrameIncludesTextCommandsWithThemeFontSizes) {
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabRuntime runtime;
|
||||
ASSERT_TRUE(runtime.ReloadDocuments());
|
||||
|
||||
const auto& frame = runtime.Update(BuildInputState());
|
||||
ASSERT_TRUE(frame.stats.documentsReady);
|
||||
|
||||
const std::vector<const UIDrawCommand*> textCommands = CollectTextCommands(frame.drawData);
|
||||
ASSERT_FALSE(textCommands.empty());
|
||||
|
||||
for (const UIDrawCommand* command : textCommands) {
|
||||
ASSERT_NE(command, nullptr);
|
||||
EXPECT_FALSE(command->text.empty());
|
||||
EXPECT_GT(command->fontSize, 0.0f);
|
||||
}
|
||||
|
||||
const UIDrawCommand* titleCommand = FindTextCommand(frame.drawData, "XCUI Layout Lab");
|
||||
ASSERT_NE(titleCommand, nullptr);
|
||||
EXPECT_FLOAT_EQ(titleCommand->fontSize, 16.0f);
|
||||
|
||||
const UIDrawCommand* subtitleCommand = FindTextCommand(
|
||||
frame.drawData,
|
||||
"Editor-style panels with overlay and scroll semantics.");
|
||||
ASSERT_NE(subtitleCommand, nullptr);
|
||||
EXPECT_FLOAT_EQ(subtitleCommand->fontSize, 13.0f);
|
||||
}
|
||||
|
||||
TEST(NewEditorXCUILayoutLabRuntimeTest, HoverProbeResolvesTrackedElementRect) {
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabRuntime runtime;
|
||||
ASSERT_TRUE(runtime.ReloadDocuments());
|
||||
|
||||
const auto& baseline = runtime.Update(BuildInputState());
|
||||
ASSERT_TRUE(baseline.stats.documentsReady);
|
||||
|
||||
XCEngine::UI::UIRect probeRect = {};
|
||||
ASSERT_TRUE(runtime.TryGetElementRect("assetLighting", probeRect));
|
||||
ASSERT_GT(probeRect.width, 0.0f);
|
||||
ASSERT_GT(probeRect.height, 0.0f);
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState input = BuildInputState();
|
||||
input.pointerPosition = XCEngine::UI::UIPoint(
|
||||
probeRect.x + probeRect.width * 0.5f,
|
||||
probeRect.y + probeRect.height * 0.5f);
|
||||
const auto& frame = runtime.Update(input);
|
||||
|
||||
ASSERT_TRUE(frame.stats.documentsReady);
|
||||
EXPECT_FALSE(frame.stats.hoveredElementId.empty());
|
||||
|
||||
XCEngine::UI::UIRect hoveredRect = {};
|
||||
EXPECT_TRUE(runtime.TryGetElementRect(frame.stats.hoveredElementId, hoveredRect));
|
||||
EXPECT_GT(hoveredRect.width, 0.0f);
|
||||
EXPECT_GT(hoveredRect.height, 0.0f);
|
||||
}
|
||||
|
||||
TEST(NewEditorXCUILayoutLabRuntimeTest, ScrollViewOffsetsContentAndAddsNestedClips) {
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabRuntime runtime;
|
||||
ASSERT_TRUE(runtime.ReloadDocuments());
|
||||
|
||||
const auto& frame = runtime.Update(BuildInputState());
|
||||
ASSERT_TRUE(frame.stats.documentsReady);
|
||||
|
||||
XCEngine::UI::UIRect assetListRect = {};
|
||||
XCEngine::UI::UIRect headerRect = {};
|
||||
XCEngine::UI::UIRect visibleItemRect = {};
|
||||
ASSERT_TRUE(runtime.TryGetElementRect("assetList", assetListRect));
|
||||
ASSERT_TRUE(runtime.TryGetElementRect("assetListHeader", headerRect));
|
||||
ASSERT_TRUE(runtime.TryGetElementRect("assetLighting", visibleItemRect));
|
||||
|
||||
EXPECT_LT(headerRect.y, assetListRect.y);
|
||||
EXPECT_GT(visibleItemRect.y, assetListRect.y);
|
||||
EXPECT_LT(visibleItemRect.y, assetListRect.y + assetListRect.height);
|
||||
|
||||
EXPECT_EQ(
|
||||
CountCommandsOfType(frame.drawData, UIDrawCommandType::PushClipRect),
|
||||
frame.stats.clipPushCommandCount);
|
||||
EXPECT_EQ(
|
||||
CountCommandsOfType(frame.drawData, UIDrawCommandType::PopClipRect),
|
||||
frame.stats.clipPopCommandCount);
|
||||
EXPECT_GE(frame.stats.clipPushCommandCount, 3u);
|
||||
EXPECT_GE(frame.stats.clipPopCommandCount, 3u);
|
||||
}
|
||||
|
||||
TEST(NewEditorXCUILayoutLabRuntimeTest, HoverIgnoresClippedScrollViewContent) {
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabRuntime runtime;
|
||||
ASSERT_TRUE(runtime.ReloadDocuments());
|
||||
|
||||
const auto& baseline = runtime.Update(BuildInputState());
|
||||
ASSERT_TRUE(baseline.stats.documentsReady);
|
||||
|
||||
XCEngine::UI::UIRect assetListRect = {};
|
||||
ASSERT_TRUE(runtime.TryGetElementRect("assetList", assetListRect));
|
||||
|
||||
XCEngine::Editor::XCUIBackend::XCUILayoutLabInputState input = BuildInputState();
|
||||
input.pointerPosition = XCEngine::UI::UIPoint(
|
||||
assetListRect.x + assetListRect.width * 0.5f,
|
||||
assetListRect.y + assetListRect.height + 6.0f);
|
||||
const auto& frame = runtime.Update(input);
|
||||
|
||||
ASSERT_TRUE(frame.stats.documentsReady);
|
||||
EXPECT_TRUE(frame.stats.hoveredElementId.empty());
|
||||
}
|
||||
Reference in New Issue
Block a user