feat(xcui): advance core and editor validation flow
This commit is contained in:
@@ -1,19 +1,19 @@
|
||||
set(EDITOR_UI_UNIT_TEST_SOURCES
|
||||
test_editor_shell_asset_validation.cpp
|
||||
test_input_modifier_tracker.cpp
|
||||
test_editor_validation_registry.cpp
|
||||
test_structured_editor_shell.cpp
|
||||
test_ui_editor_panel_registry.cpp
|
||||
test_ui_editor_collection_primitives.cpp
|
||||
test_ui_editor_panel_chrome.cpp
|
||||
test_ui_editor_workspace_controller.cpp
|
||||
test_ui_editor_workspace_model.cpp
|
||||
# Migration bridge: editor-facing XCUI primitive tests still reuse the
|
||||
# legacy source location until they are relocated under tests/UI/Editor/unit.
|
||||
${CMAKE_SOURCE_DIR}/tests/Core/UI/test_ui_editor_collection_primitives.cpp
|
||||
${CMAKE_SOURCE_DIR}/tests/Core/UI/test_ui_editor_panel_chrome.cpp
|
||||
test_ui_editor_workspace_session.cpp
|
||||
)
|
||||
|
||||
add_executable(editor_ui_tests ${EDITOR_UI_UNIT_TEST_SOURCES})
|
||||
|
||||
target_link_libraries(editor_ui_tests
|
||||
PRIVATE
|
||||
editor_ui_validation_registry
|
||||
XCNewEditorLib
|
||||
GTest::gtest_main
|
||||
)
|
||||
@@ -23,7 +23,6 @@ target_include_directories(editor_ui_tests
|
||||
${CMAKE_SOURCE_DIR}/new_editor/include
|
||||
${CMAKE_SOURCE_DIR}/new_editor/src
|
||||
${CMAKE_SOURCE_DIR}/engine/include
|
||||
${CMAKE_SOURCE_DIR}/tests/UI/Editor/integration/shared/src
|
||||
)
|
||||
|
||||
if(MSVC)
|
||||
|
||||
53
tests/UI/Editor/unit/test_editor_shell_asset_validation.cpp
Normal file
53
tests/UI/Editor/unit/test_editor_shell_asset_validation.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "editor/EditorShellAsset.h"
|
||||
|
||||
#include <XCNewEditor/Editor/UIEditorPanelRegistry.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::NewEditor::BuildDefaultEditorShellAsset;
|
||||
using XCEngine::NewEditor::EditorShellAssetValidationCode;
|
||||
using XCEngine::NewEditor::FindUIEditorPanelDescriptor;
|
||||
using XCEngine::NewEditor::ValidateEditorShellAsset;
|
||||
|
||||
TEST(EditorShellAssetValidationTest, DefaultShellAssetPassesValidation) {
|
||||
const auto shellAsset = BuildDefaultEditorShellAsset(".");
|
||||
|
||||
const auto validation = ValidateEditorShellAsset(shellAsset);
|
||||
EXPECT_TRUE(validation.IsValid()) << validation.message;
|
||||
}
|
||||
|
||||
TEST(EditorShellAssetValidationTest, ValidationRejectsWorkspacePanelMissingFromRegistry) {
|
||||
auto shellAsset = BuildDefaultEditorShellAsset(".");
|
||||
|
||||
auto* documentPanel =
|
||||
const_cast<XCEngine::NewEditor::UIEditorPanelDescriptor*>(
|
||||
FindUIEditorPanelDescriptor(shellAsset.panelRegistry, "editor-foundation-root"));
|
||||
ASSERT_NE(documentPanel, nullptr);
|
||||
documentPanel->panelId = "editor-foundation-root-renamed";
|
||||
|
||||
const auto validation = ValidateEditorShellAsset(shellAsset);
|
||||
EXPECT_EQ(validation.code, EditorShellAssetValidationCode::MissingPanelDescriptor)
|
||||
<< validation.message;
|
||||
}
|
||||
|
||||
TEST(EditorShellAssetValidationTest, ValidationRejectsWorkspaceTitleDriftFromRegistry) {
|
||||
auto shellAsset = BuildDefaultEditorShellAsset(".");
|
||||
shellAsset.workspace.activePanelId = "editor-foundation-root";
|
||||
shellAsset.workspace.root.panel.title = "Drifted Title";
|
||||
|
||||
const auto validation = ValidateEditorShellAsset(shellAsset);
|
||||
EXPECT_EQ(validation.code, EditorShellAssetValidationCode::PanelTitleMismatch);
|
||||
}
|
||||
|
||||
TEST(EditorShellAssetValidationTest, ValidationRejectsInvalidWorkspaceSessionState) {
|
||||
auto shellAsset = BuildDefaultEditorShellAsset(".");
|
||||
ASSERT_EQ(shellAsset.workspaceSession.panelStates.size(), 1u);
|
||||
shellAsset.workspaceSession.panelStates.front().open = false;
|
||||
|
||||
const auto validation = ValidateEditorShellAsset(shellAsset);
|
||||
EXPECT_EQ(validation.code, EditorShellAssetValidationCode::InvalidWorkspaceSession);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -1,66 +0,0 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "EditorValidationScenario.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::Tests::EditorUI::FindEditorValidationScenario;
|
||||
using XCEngine::Tests::EditorUI::GetDefaultEditorValidationScenario;
|
||||
using XCEngine::Tests::EditorUI::UIValidationDomain;
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(EditorValidationRegistryTest, KnownEditorValidationScenariosResolveToExistingResources) {
|
||||
const auto* pointerScenario = FindEditorValidationScenario("editor.input.pointer_states");
|
||||
const auto* keyboardScenario = FindEditorValidationScenario("editor.input.keyboard_focus");
|
||||
const auto* scrollScenario = FindEditorValidationScenario("editor.input.scroll_view");
|
||||
const auto* shortcutScenario = FindEditorValidationScenario("editor.input.shortcut_scope");
|
||||
const auto* splitterScenario = FindEditorValidationScenario("editor.layout.splitter_resize");
|
||||
const auto* tabStripScenario = FindEditorValidationScenario("editor.layout.tab_strip_selection");
|
||||
const auto* workspaceScenario = FindEditorValidationScenario("editor.layout.workspace_compose");
|
||||
|
||||
ASSERT_NE(pointerScenario, nullptr);
|
||||
ASSERT_NE(keyboardScenario, nullptr);
|
||||
ASSERT_NE(scrollScenario, nullptr);
|
||||
ASSERT_NE(shortcutScenario, nullptr);
|
||||
ASSERT_NE(splitterScenario, nullptr);
|
||||
ASSERT_NE(tabStripScenario, nullptr);
|
||||
ASSERT_NE(workspaceScenario, nullptr);
|
||||
EXPECT_EQ(pointerScenario->domain, UIValidationDomain::Editor);
|
||||
EXPECT_EQ(keyboardScenario->domain, UIValidationDomain::Editor);
|
||||
EXPECT_EQ(scrollScenario->domain, UIValidationDomain::Editor);
|
||||
EXPECT_EQ(shortcutScenario->domain, UIValidationDomain::Editor);
|
||||
EXPECT_EQ(splitterScenario->domain, UIValidationDomain::Editor);
|
||||
EXPECT_EQ(tabStripScenario->domain, UIValidationDomain::Editor);
|
||||
EXPECT_EQ(workspaceScenario->domain, UIValidationDomain::Editor);
|
||||
EXPECT_EQ(pointerScenario->categoryId, "input");
|
||||
EXPECT_EQ(keyboardScenario->categoryId, "input");
|
||||
EXPECT_EQ(scrollScenario->categoryId, "input");
|
||||
EXPECT_EQ(shortcutScenario->categoryId, "input");
|
||||
EXPECT_EQ(splitterScenario->categoryId, "layout");
|
||||
EXPECT_EQ(tabStripScenario->categoryId, "layout");
|
||||
EXPECT_EQ(workspaceScenario->categoryId, "layout");
|
||||
EXPECT_TRUE(std::filesystem::exists(pointerScenario->documentPath));
|
||||
EXPECT_TRUE(std::filesystem::exists(pointerScenario->themePath));
|
||||
EXPECT_TRUE(std::filesystem::exists(keyboardScenario->documentPath));
|
||||
EXPECT_TRUE(std::filesystem::exists(keyboardScenario->themePath));
|
||||
EXPECT_TRUE(std::filesystem::exists(scrollScenario->documentPath));
|
||||
EXPECT_TRUE(std::filesystem::exists(scrollScenario->themePath));
|
||||
EXPECT_TRUE(std::filesystem::exists(shortcutScenario->documentPath));
|
||||
EXPECT_TRUE(std::filesystem::exists(shortcutScenario->themePath));
|
||||
EXPECT_TRUE(std::filesystem::exists(splitterScenario->documentPath));
|
||||
EXPECT_TRUE(std::filesystem::exists(splitterScenario->themePath));
|
||||
EXPECT_TRUE(std::filesystem::exists(tabStripScenario->documentPath));
|
||||
EXPECT_TRUE(std::filesystem::exists(tabStripScenario->themePath));
|
||||
EXPECT_TRUE(std::filesystem::exists(workspaceScenario->documentPath));
|
||||
EXPECT_TRUE(std::filesystem::exists(workspaceScenario->themePath));
|
||||
}
|
||||
|
||||
TEST(EditorValidationRegistryTest, DefaultScenarioPointsToKeyboardFocusBatch) {
|
||||
const auto& scenario = GetDefaultEditorValidationScenario();
|
||||
EXPECT_EQ(scenario.id, "editor.input.keyboard_focus");
|
||||
EXPECT_EQ(scenario.domain, UIValidationDomain::Editor);
|
||||
EXPECT_TRUE(std::filesystem::exists(scenario.documentPath));
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCEngine/UI/Style/Theme.h>
|
||||
#include <XCEngine/UI/Style/StyleTypes.h>
|
||||
#include <XCNewEditor/Widgets/UIEditorCollectionPrimitives.h>
|
||||
|
||||
namespace {
|
||||
|
||||
namespace Style = XCEngine::UI::Style;
|
||||
namespace UIWidgets = XCEngine::UI::Widgets;
|
||||
|
||||
Style::UITheme BuildEditorPrimitiveTheme() {
|
||||
Style::UIThemeDefinition definition = {};
|
||||
definition.SetToken("space.cardInset", Style::UIStyleValue(14.0f));
|
||||
definition.SetToken("size.treeItemHeight", Style::UIStyleValue(30.0f));
|
||||
definition.SetToken("size.listItemHeight", Style::UIStyleValue(64.0f));
|
||||
definition.SetToken("size.fieldRowHeight", Style::UIStyleValue(36.0f));
|
||||
definition.SetToken("size.propertySectionHeight", Style::UIStyleValue(156.0f));
|
||||
definition.SetToken("size.treeIndent", Style::UIStyleValue(20.0f));
|
||||
return Style::BuildTheme(definition);
|
||||
}
|
||||
|
||||
TEST(UIEditorCollectionPrimitivesTest, ClassifyAndFlagsMatchEditorCollectionTags) {
|
||||
using Kind = UIWidgets::UIEditorCollectionPrimitiveKind;
|
||||
|
||||
EXPECT_EQ(UIWidgets::ClassifyUIEditorCollectionPrimitive("ScrollView"), Kind::ScrollView);
|
||||
EXPECT_EQ(UIWidgets::ClassifyUIEditorCollectionPrimitive("TreeView"), Kind::TreeView);
|
||||
EXPECT_EQ(UIWidgets::ClassifyUIEditorCollectionPrimitive("TreeItem"), Kind::TreeItem);
|
||||
EXPECT_EQ(UIWidgets::ClassifyUIEditorCollectionPrimitive("ListView"), Kind::ListView);
|
||||
EXPECT_EQ(UIWidgets::ClassifyUIEditorCollectionPrimitive("ListItem"), Kind::ListItem);
|
||||
EXPECT_EQ(UIWidgets::ClassifyUIEditorCollectionPrimitive("PropertySection"), Kind::PropertySection);
|
||||
EXPECT_EQ(UIWidgets::ClassifyUIEditorCollectionPrimitive("FieldRow"), Kind::FieldRow);
|
||||
EXPECT_EQ(UIWidgets::ClassifyUIEditorCollectionPrimitive("Column"), Kind::None);
|
||||
|
||||
EXPECT_TRUE(UIWidgets::IsUIEditorCollectionPrimitiveContainer(Kind::ScrollView));
|
||||
EXPECT_TRUE(UIWidgets::IsUIEditorCollectionPrimitiveContainer(Kind::TreeView));
|
||||
EXPECT_TRUE(UIWidgets::IsUIEditorCollectionPrimitiveContainer(Kind::ListView));
|
||||
EXPECT_TRUE(UIWidgets::IsUIEditorCollectionPrimitiveContainer(Kind::PropertySection));
|
||||
EXPECT_FALSE(UIWidgets::IsUIEditorCollectionPrimitiveContainer(Kind::TreeItem));
|
||||
|
||||
EXPECT_TRUE(UIWidgets::UsesUIEditorCollectionPrimitiveColumnLayout(Kind::TreeView));
|
||||
EXPECT_TRUE(UIWidgets::UsesUIEditorCollectionPrimitiveColumnLayout(Kind::ListView));
|
||||
EXPECT_TRUE(UIWidgets::UsesUIEditorCollectionPrimitiveColumnLayout(Kind::PropertySection));
|
||||
EXPECT_FALSE(UIWidgets::UsesUIEditorCollectionPrimitiveColumnLayout(Kind::ScrollView));
|
||||
|
||||
EXPECT_TRUE(UIWidgets::DoesUIEditorCollectionPrimitiveClipChildren(Kind::ScrollView));
|
||||
EXPECT_TRUE(UIWidgets::DoesUIEditorCollectionPrimitiveClipChildren(Kind::TreeView));
|
||||
EXPECT_TRUE(UIWidgets::DoesUIEditorCollectionPrimitiveClipChildren(Kind::ListView));
|
||||
EXPECT_FALSE(UIWidgets::DoesUIEditorCollectionPrimitiveClipChildren(Kind::PropertySection));
|
||||
|
||||
EXPECT_TRUE(UIWidgets::IsUIEditorCollectionPrimitiveHoverable(Kind::TreeItem));
|
||||
EXPECT_TRUE(UIWidgets::IsUIEditorCollectionPrimitiveHoverable(Kind::ListItem));
|
||||
EXPECT_TRUE(UIWidgets::IsUIEditorCollectionPrimitiveHoverable(Kind::PropertySection));
|
||||
EXPECT_TRUE(UIWidgets::IsUIEditorCollectionPrimitiveHoverable(Kind::FieldRow));
|
||||
EXPECT_FALSE(UIWidgets::IsUIEditorCollectionPrimitiveHoverable(Kind::TreeView));
|
||||
}
|
||||
|
||||
TEST(UIEditorCollectionPrimitivesTest, ResolveMetricsUseThemeTokensAndFallbacks) {
|
||||
using Kind = UIWidgets::UIEditorCollectionPrimitiveKind;
|
||||
|
||||
const Style::UITheme themed = BuildEditorPrimitiveTheme();
|
||||
const Style::UITheme fallback = Style::UITheme();
|
||||
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitivePadding(Kind::TreeView, themed), 14.0f);
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitivePadding(Kind::ListView, themed), 14.0f);
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitivePadding(Kind::PropertySection, themed), 14.0f);
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitivePadding(Kind::ScrollView, themed), 0.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitiveDefaultHeight(Kind::TreeItem, themed), 30.0f);
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitiveDefaultHeight(Kind::ListItem, themed), 64.0f);
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitiveDefaultHeight(Kind::FieldRow, themed), 36.0f);
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitiveDefaultHeight(Kind::PropertySection, themed), 156.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitiveDefaultHeight(Kind::TreeItem, fallback), 28.0f);
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitiveDefaultHeight(Kind::ListItem, fallback), 60.0f);
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitiveDefaultHeight(Kind::FieldRow, fallback), 32.0f);
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitiveDefaultHeight(Kind::PropertySection, fallback), 148.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitiveIndent(Kind::TreeItem, themed, 2.0f), 40.0f);
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitiveIndent(Kind::TreeItem, fallback, 2.0f), 36.0f);
|
||||
EXPECT_FLOAT_EQ(UIWidgets::ResolveUIEditorCollectionPrimitiveIndent(Kind::ListItem, themed, 2.0f), 0.0f);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
126
tests/UI/Editor/unit/test_ui_editor_panel_chrome.cpp
Normal file
126
tests/UI/Editor/unit/test_ui_editor_panel_chrome.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCEngine/UI/DrawData.h>
|
||||
#include <XCNewEditor/Widgets/UIEditorPanelChrome.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::UI::UIColor;
|
||||
using XCEngine::UI::UIDrawCommandType;
|
||||
using XCEngine::UI::UIDrawList;
|
||||
using XCEngine::UI::UIRect;
|
||||
using XCEngine::UI::Widgets::AppendUIEditorPanelChromeBackground;
|
||||
using XCEngine::UI::Widgets::AppendUIEditorPanelChromeForeground;
|
||||
using XCEngine::UI::Widgets::BuildUIEditorPanelChromeHeaderRect;
|
||||
using XCEngine::UI::Widgets::ResolveUIEditorPanelChromeBorderColor;
|
||||
using XCEngine::UI::Widgets::ResolveUIEditorPanelChromeBorderThickness;
|
||||
using XCEngine::UI::Widgets::UIEditorPanelChromePalette;
|
||||
using XCEngine::UI::Widgets::UIEditorPanelChromeState;
|
||||
using XCEngine::UI::Widgets::UIEditorPanelChromeText;
|
||||
|
||||
void ExpectColorEq(
|
||||
const UIColor& actual,
|
||||
const UIColor& expected) {
|
||||
EXPECT_FLOAT_EQ(actual.r, expected.r);
|
||||
EXPECT_FLOAT_EQ(actual.g, expected.g);
|
||||
EXPECT_FLOAT_EQ(actual.b, expected.b);
|
||||
EXPECT_FLOAT_EQ(actual.a, expected.a);
|
||||
}
|
||||
|
||||
TEST(UIEditorPanelChromeTest, HeaderRectAndBorderPolicyMatchNativeShellCardChrome) {
|
||||
const UIRect panelRect(100.0f, 200.0f, 320.0f, 180.0f);
|
||||
const UIEditorPanelChromePalette palette = {};
|
||||
|
||||
const auto headerRect = BuildUIEditorPanelChromeHeaderRect(panelRect);
|
||||
EXPECT_FLOAT_EQ(headerRect.x, 100.0f);
|
||||
EXPECT_FLOAT_EQ(headerRect.y, 200.0f);
|
||||
EXPECT_FLOAT_EQ(headerRect.width, 320.0f);
|
||||
EXPECT_FLOAT_EQ(headerRect.height, 42.0f);
|
||||
|
||||
ExpectColorEq(
|
||||
ResolveUIEditorPanelChromeBorderColor(UIEditorPanelChromeState(), palette),
|
||||
palette.borderColor);
|
||||
ExpectColorEq(
|
||||
ResolveUIEditorPanelChromeBorderColor(UIEditorPanelChromeState{ false, true }, palette),
|
||||
palette.hoveredAccentColor);
|
||||
ExpectColorEq(
|
||||
ResolveUIEditorPanelChromeBorderColor(UIEditorPanelChromeState{ true, true }, palette),
|
||||
palette.accentColor);
|
||||
|
||||
EXPECT_FLOAT_EQ(ResolveUIEditorPanelChromeBorderThickness(UIEditorPanelChromeState()), 1.0f);
|
||||
EXPECT_FLOAT_EQ(ResolveUIEditorPanelChromeBorderThickness(UIEditorPanelChromeState{ true, false }), 2.0f);
|
||||
}
|
||||
|
||||
TEST(UIEditorPanelChromeTest, BackgroundAppendEmitsSurfaceOutlineAndHeaderFill) {
|
||||
UIDrawList drawList("PanelChrome");
|
||||
const UIRect panelRect(40.0f, 60.0f, 400.0f, 280.0f);
|
||||
const UIEditorPanelChromeState state{ true, false };
|
||||
const UIEditorPanelChromePalette palette = {};
|
||||
|
||||
AppendUIEditorPanelChromeBackground(drawList, panelRect, state, palette);
|
||||
|
||||
ASSERT_EQ(drawList.GetCommandCount(), 3u);
|
||||
const auto& commands = drawList.GetCommands();
|
||||
EXPECT_EQ(commands[0].type, UIDrawCommandType::FilledRect);
|
||||
EXPECT_EQ(commands[1].type, UIDrawCommandType::RectOutline);
|
||||
EXPECT_EQ(commands[2].type, UIDrawCommandType::FilledRect);
|
||||
|
||||
EXPECT_FLOAT_EQ(commands[0].rect.x, 40.0f);
|
||||
EXPECT_FLOAT_EQ(commands[0].rounding, 18.0f);
|
||||
ExpectColorEq(commands[0].color, palette.surfaceColor);
|
||||
|
||||
EXPECT_FLOAT_EQ(commands[1].thickness, 2.0f);
|
||||
EXPECT_FLOAT_EQ(commands[1].rounding, 18.0f);
|
||||
ExpectColorEq(commands[1].color, palette.accentColor);
|
||||
|
||||
EXPECT_FLOAT_EQ(commands[2].rect.height, 42.0f);
|
||||
EXPECT_FLOAT_EQ(commands[2].rounding, 18.0f);
|
||||
ExpectColorEq(commands[2].color, palette.headerColor);
|
||||
}
|
||||
|
||||
TEST(UIEditorPanelChromeTest, ForegroundAppendPlacesTitleSubtitleAndFooterAtCurrentOffsets) {
|
||||
UIDrawList drawList("PanelChromeText");
|
||||
const UIRect panelRect(100.0f, 200.0f, 320.0f, 180.0f);
|
||||
const UIEditorPanelChromePalette palette = {};
|
||||
const UIEditorPanelChromeText text{
|
||||
"XCUI Demo",
|
||||
"native queued offscreen surface",
|
||||
"Active | 42 elements | 9 cmds"
|
||||
};
|
||||
|
||||
AppendUIEditorPanelChromeForeground(drawList, panelRect, text, palette);
|
||||
|
||||
ASSERT_EQ(drawList.GetCommandCount(), 3u);
|
||||
const auto& commands = drawList.GetCommands();
|
||||
EXPECT_EQ(commands[0].type, UIDrawCommandType::Text);
|
||||
EXPECT_EQ(commands[1].type, UIDrawCommandType::Text);
|
||||
EXPECT_EQ(commands[2].type, UIDrawCommandType::Text);
|
||||
|
||||
EXPECT_EQ(commands[0].text, "XCUI Demo");
|
||||
EXPECT_FLOAT_EQ(commands[0].position.x, 116.0f);
|
||||
EXPECT_FLOAT_EQ(commands[0].position.y, 212.0f);
|
||||
ExpectColorEq(commands[0].color, palette.textPrimary);
|
||||
|
||||
EXPECT_EQ(commands[1].text, "native queued offscreen surface");
|
||||
EXPECT_FLOAT_EQ(commands[1].position.x, 116.0f);
|
||||
EXPECT_FLOAT_EQ(commands[1].position.y, 228.0f);
|
||||
ExpectColorEq(commands[1].color, palette.textSecondary);
|
||||
|
||||
EXPECT_EQ(commands[2].text, "Active | 42 elements | 9 cmds");
|
||||
EXPECT_FLOAT_EQ(commands[2].position.x, 116.0f);
|
||||
EXPECT_FLOAT_EQ(commands[2].position.y, 362.0f);
|
||||
ExpectColorEq(commands[2].color, palette.textMuted);
|
||||
}
|
||||
|
||||
TEST(UIEditorPanelChromeTest, ForegroundAppendSkipsEmptyStrings) {
|
||||
UIDrawList drawList("PanelChromeEmptyText");
|
||||
|
||||
AppendUIEditorPanelChromeForeground(
|
||||
drawList,
|
||||
UIRect(0.0f, 0.0f, 320.0f, 180.0f),
|
||||
UIEditorPanelChromeText{});
|
||||
|
||||
EXPECT_EQ(drawList.GetCommandCount(), 0u);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
49
tests/UI/Editor/unit/test_ui_editor_panel_registry.cpp
Normal file
49
tests/UI/Editor/unit/test_ui_editor_panel_registry.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCNewEditor/Editor/UIEditorPanelRegistry.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::NewEditor::BuildDefaultEditorShellPanelRegistry;
|
||||
using XCEngine::NewEditor::FindUIEditorPanelDescriptor;
|
||||
using XCEngine::NewEditor::UIEditorPanelDescriptor;
|
||||
using XCEngine::NewEditor::UIEditorPanelRegistry;
|
||||
using XCEngine::NewEditor::UIEditorPanelRegistryValidationCode;
|
||||
using XCEngine::NewEditor::ValidateUIEditorPanelRegistry;
|
||||
|
||||
TEST(UIEditorPanelRegistryTest, DefaultRegistryContainsShellDescriptors) {
|
||||
const UIEditorPanelRegistry registry = BuildDefaultEditorShellPanelRegistry();
|
||||
|
||||
ASSERT_EQ(registry.panels.size(), 1u);
|
||||
const UIEditorPanelDescriptor* descriptor =
|
||||
FindUIEditorPanelDescriptor(registry, "editor-foundation-root");
|
||||
ASSERT_NE(descriptor, nullptr);
|
||||
EXPECT_FALSE(descriptor->canHide);
|
||||
EXPECT_FALSE(descriptor->canClose);
|
||||
EXPECT_EQ(FindUIEditorPanelDescriptor(registry, "missing-panel"), nullptr);
|
||||
}
|
||||
|
||||
TEST(UIEditorPanelRegistryTest, ValidationRejectsEmptyPanelIdAndTitle) {
|
||||
UIEditorPanelRegistry emptyIdRegistry = {};
|
||||
emptyIdRegistry.panels.push_back(UIEditorPanelDescriptor{ "", "Panel", {}, true });
|
||||
EXPECT_EQ(
|
||||
ValidateUIEditorPanelRegistry(emptyIdRegistry).code,
|
||||
UIEditorPanelRegistryValidationCode::EmptyPanelId);
|
||||
|
||||
UIEditorPanelRegistry emptyTitleRegistry = {};
|
||||
emptyTitleRegistry.panels.push_back(UIEditorPanelDescriptor{ "panel-a", "", {}, true });
|
||||
EXPECT_EQ(
|
||||
ValidateUIEditorPanelRegistry(emptyTitleRegistry).code,
|
||||
UIEditorPanelRegistryValidationCode::EmptyDefaultTitle);
|
||||
}
|
||||
|
||||
TEST(UIEditorPanelRegistryTest, ValidationRejectsDuplicatePanelId) {
|
||||
UIEditorPanelRegistry registry = {};
|
||||
registry.panels.push_back(UIEditorPanelDescriptor{ "panel-a", "Panel A", {}, true });
|
||||
registry.panels.push_back(UIEditorPanelDescriptor{ "panel-a", "Panel A Duplicate", {}, true });
|
||||
|
||||
const auto validation = ValidateUIEditorPanelRegistry(registry);
|
||||
EXPECT_EQ(validation.code, UIEditorPanelRegistryValidationCode::DuplicatePanelId);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
148
tests/UI/Editor/unit/test_ui_editor_workspace_controller.cpp
Normal file
148
tests/UI/Editor/unit/test_ui_editor_workspace_controller.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCNewEditor/Editor/UIEditorWorkspaceController.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::NewEditor::BuildDefaultUIEditorWorkspaceController;
|
||||
using XCEngine::NewEditor::BuildDefaultUIEditorWorkspaceSession;
|
||||
using XCEngine::NewEditor::BuildUIEditorWorkspacePanel;
|
||||
using XCEngine::NewEditor::BuildUIEditorWorkspaceSplit;
|
||||
using XCEngine::NewEditor::BuildUIEditorWorkspaceTabStack;
|
||||
using XCEngine::NewEditor::GetUIEditorWorkspaceCommandKindName;
|
||||
using XCEngine::NewEditor::GetUIEditorWorkspaceCommandStatusName;
|
||||
using XCEngine::NewEditor::UIEditorPanelRegistry;
|
||||
using XCEngine::NewEditor::UIEditorWorkspaceCommand;
|
||||
using XCEngine::NewEditor::UIEditorWorkspaceCommandKind;
|
||||
using XCEngine::NewEditor::UIEditorWorkspaceCommandStatus;
|
||||
using XCEngine::NewEditor::UIEditorWorkspaceControllerValidationCode;
|
||||
using XCEngine::NewEditor::UIEditorWorkspaceController;
|
||||
using XCEngine::NewEditor::UIEditorWorkspaceModel;
|
||||
using XCEngine::NewEditor::UIEditorWorkspaceSplitAxis;
|
||||
|
||||
UIEditorPanelRegistry BuildPanelRegistry() {
|
||||
UIEditorPanelRegistry registry = {};
|
||||
registry.panels = {
|
||||
{ "doc-a", "Document A", {}, true, true, true },
|
||||
{ "doc-b", "Document B", {}, true, true, true },
|
||||
{ "details", "Details", {}, true, true, true },
|
||||
{ "root", "Root", {}, true, false, false }
|
||||
};
|
||||
return registry;
|
||||
}
|
||||
|
||||
UIEditorWorkspaceModel BuildWorkspace() {
|
||||
UIEditorWorkspaceModel workspace = {};
|
||||
workspace.root = BuildUIEditorWorkspaceSplit(
|
||||
"root-split",
|
||||
UIEditorWorkspaceSplitAxis::Horizontal,
|
||||
0.66f,
|
||||
BuildUIEditorWorkspaceTabStack(
|
||||
"document-tabs",
|
||||
{
|
||||
BuildUIEditorWorkspacePanel("doc-a-node", "doc-a", "Document A", true),
|
||||
BuildUIEditorWorkspacePanel("doc-b-node", "doc-b", "Document B", true)
|
||||
},
|
||||
0u),
|
||||
BuildUIEditorWorkspacePanel("details-node", "details", "Details", true));
|
||||
workspace.activePanelId = "doc-a";
|
||||
return workspace;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(UIEditorWorkspaceControllerTest, CommandNameHelpersExposeStableDebugNames) {
|
||||
EXPECT_EQ(GetUIEditorWorkspaceCommandKindName(UIEditorWorkspaceCommandKind::HidePanel), "HidePanel");
|
||||
EXPECT_EQ(GetUIEditorWorkspaceCommandStatusName(UIEditorWorkspaceCommandStatus::Changed), "Changed");
|
||||
}
|
||||
|
||||
TEST(UIEditorWorkspaceControllerTest, ValidateStateUsesControllerLevelErrorClassification) {
|
||||
UIEditorPanelRegistry registry = BuildPanelRegistry();
|
||||
UIEditorWorkspaceModel workspace = BuildWorkspace();
|
||||
workspace.activePanelId = "missing-panel";
|
||||
|
||||
UIEditorWorkspaceController controller(
|
||||
registry,
|
||||
workspace,
|
||||
BuildDefaultUIEditorWorkspaceSession(registry, workspace));
|
||||
|
||||
const auto validation = controller.ValidateState();
|
||||
EXPECT_EQ(validation.code, UIEditorWorkspaceControllerValidationCode::InvalidWorkspace);
|
||||
}
|
||||
|
||||
TEST(UIEditorWorkspaceControllerTest, HideCommandChangesStateAndRepeatedHideBecomesNoOp) {
|
||||
UIEditorWorkspaceController controller =
|
||||
BuildDefaultUIEditorWorkspaceController(BuildPanelRegistry(), BuildWorkspace());
|
||||
|
||||
const auto first = controller.Dispatch({ UIEditorWorkspaceCommandKind::HidePanel, "doc-a" });
|
||||
EXPECT_EQ(first.status, UIEditorWorkspaceCommandStatus::Changed);
|
||||
EXPECT_EQ(first.activePanelId, "doc-b");
|
||||
ASSERT_EQ(first.visiblePanelIds.size(), 2u);
|
||||
EXPECT_EQ(first.visiblePanelIds[0], "doc-b");
|
||||
EXPECT_EQ(first.visiblePanelIds[1], "details");
|
||||
|
||||
const auto second = controller.Dispatch({ UIEditorWorkspaceCommandKind::HidePanel, "doc-a" });
|
||||
EXPECT_EQ(second.status, UIEditorWorkspaceCommandStatus::NoOp);
|
||||
EXPECT_EQ(second.message, "Panel is already hidden.");
|
||||
}
|
||||
|
||||
TEST(UIEditorWorkspaceControllerTest, ClosedPanelCannotBeActivatedUntilOpenedAgain) {
|
||||
UIEditorWorkspaceController controller =
|
||||
BuildDefaultUIEditorWorkspaceController(BuildPanelRegistry(), BuildWorkspace());
|
||||
|
||||
EXPECT_EQ(
|
||||
controller.Dispatch({ UIEditorWorkspaceCommandKind::ClosePanel, "doc-b" }).status,
|
||||
UIEditorWorkspaceCommandStatus::Changed);
|
||||
|
||||
const auto activateClosed =
|
||||
controller.Dispatch({ UIEditorWorkspaceCommandKind::ActivatePanel, "doc-b" });
|
||||
EXPECT_EQ(activateClosed.status, UIEditorWorkspaceCommandStatus::Rejected);
|
||||
EXPECT_EQ(activateClosed.activePanelId, "doc-a");
|
||||
|
||||
const auto reopen =
|
||||
controller.Dispatch({ UIEditorWorkspaceCommandKind::OpenPanel, "doc-b" });
|
||||
EXPECT_EQ(reopen.status, UIEditorWorkspaceCommandStatus::Changed);
|
||||
EXPECT_EQ(reopen.activePanelId, "doc-b");
|
||||
}
|
||||
|
||||
TEST(UIEditorWorkspaceControllerTest, ResetCommandRestoresBaselineState) {
|
||||
UIEditorWorkspaceController controller =
|
||||
BuildDefaultUIEditorWorkspaceController(BuildPanelRegistry(), BuildWorkspace());
|
||||
|
||||
EXPECT_EQ(
|
||||
controller.Dispatch({ UIEditorWorkspaceCommandKind::HidePanel, "doc-a" }).status,
|
||||
UIEditorWorkspaceCommandStatus::Changed);
|
||||
EXPECT_EQ(
|
||||
controller.Dispatch({ UIEditorWorkspaceCommandKind::ClosePanel, "doc-b" }).status,
|
||||
UIEditorWorkspaceCommandStatus::Changed);
|
||||
EXPECT_EQ(controller.GetWorkspace().activePanelId, "details");
|
||||
|
||||
const auto reset = controller.Dispatch({ UIEditorWorkspaceCommandKind::ResetWorkspace, {} });
|
||||
EXPECT_EQ(reset.status, UIEditorWorkspaceCommandStatus::Changed);
|
||||
EXPECT_EQ(reset.activePanelId, "doc-a");
|
||||
ASSERT_EQ(reset.visiblePanelIds.size(), 2u);
|
||||
EXPECT_EQ(reset.visiblePanelIds[0], "doc-a");
|
||||
EXPECT_EQ(reset.visiblePanelIds[1], "details");
|
||||
|
||||
const auto repeatReset = controller.Dispatch({ UIEditorWorkspaceCommandKind::ResetWorkspace, {} });
|
||||
EXPECT_EQ(repeatReset.status, UIEditorWorkspaceCommandStatus::NoOp);
|
||||
}
|
||||
|
||||
TEST(UIEditorWorkspaceControllerTest, RejectsUnknownPanelAndNonCloseablePanelCommands) {
|
||||
UIEditorWorkspaceController controller =
|
||||
BuildDefaultUIEditorWorkspaceController(BuildPanelRegistry(), BuildWorkspace());
|
||||
|
||||
const auto unknown = controller.Dispatch({ UIEditorWorkspaceCommandKind::ShowPanel, "missing" });
|
||||
EXPECT_EQ(unknown.status, UIEditorWorkspaceCommandStatus::Rejected);
|
||||
|
||||
UIEditorWorkspaceModel rootWorkspace = {};
|
||||
rootWorkspace.root = BuildUIEditorWorkspacePanel("root-node", "root", "Root", true);
|
||||
rootWorkspace.activePanelId = "root";
|
||||
UIEditorWorkspaceController rootController =
|
||||
BuildDefaultUIEditorWorkspaceController(BuildPanelRegistry(), rootWorkspace);
|
||||
|
||||
const auto nonCloseable =
|
||||
rootController.Dispatch({ UIEditorWorkspaceCommandKind::ClosePanel, "root" });
|
||||
EXPECT_EQ(nonCloseable.status, UIEditorWorkspaceCommandStatus::Rejected);
|
||||
EXPECT_EQ(rootController.GetWorkspace().activePanelId, "root");
|
||||
}
|
||||
183
tests/UI/Editor/unit/test_ui_editor_workspace_session.cpp
Normal file
183
tests/UI/Editor/unit/test_ui_editor_workspace_session.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCNewEditor/Editor/UIEditorPanelRegistry.h>
|
||||
#include <XCNewEditor/Editor/UIEditorWorkspaceModel.h>
|
||||
#include <XCNewEditor/Editor/UIEditorWorkspaceSession.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::NewEditor::BuildDefaultUIEditorWorkspaceSession;
|
||||
using XCEngine::NewEditor::BuildUIEditorWorkspacePanel;
|
||||
using XCEngine::NewEditor::BuildUIEditorWorkspaceSplit;
|
||||
using XCEngine::NewEditor::BuildUIEditorWorkspaceTabStack;
|
||||
using XCEngine::NewEditor::CollectUIEditorWorkspaceVisiblePanels;
|
||||
using XCEngine::NewEditor::FindUIEditorPanelDescriptor;
|
||||
using XCEngine::NewEditor::FindUIEditorPanelSessionState;
|
||||
using XCEngine::NewEditor::TryActivateUIEditorWorkspacePanel;
|
||||
using XCEngine::NewEditor::TryCloseUIEditorWorkspacePanel;
|
||||
using XCEngine::NewEditor::TryHideUIEditorWorkspacePanel;
|
||||
using XCEngine::NewEditor::TryOpenUIEditorWorkspacePanel;
|
||||
using XCEngine::NewEditor::TryShowUIEditorWorkspacePanel;
|
||||
using XCEngine::NewEditor::UIEditorPanelRegistry;
|
||||
using XCEngine::NewEditor::UIEditorWorkspaceModel;
|
||||
using XCEngine::NewEditor::UIEditorWorkspaceSession;
|
||||
using XCEngine::NewEditor::UIEditorWorkspaceSessionValidationCode;
|
||||
using XCEngine::NewEditor::UIEditorWorkspaceSplitAxis;
|
||||
using XCEngine::NewEditor::ValidateUIEditorWorkspaceSession;
|
||||
|
||||
UIEditorPanelRegistry BuildPanelRegistry() {
|
||||
UIEditorPanelRegistry registry = {};
|
||||
registry.panels = {
|
||||
{ "doc-a", "Document A", {}, true, true, true },
|
||||
{ "doc-b", "Document B", {}, true, true, true },
|
||||
{ "details", "Details", {}, true, true, true },
|
||||
{ "root", "Root", {}, true, false, false }
|
||||
};
|
||||
return registry;
|
||||
}
|
||||
|
||||
UIEditorWorkspaceModel BuildWorkspace() {
|
||||
UIEditorWorkspaceModel workspace = {};
|
||||
workspace.root = BuildUIEditorWorkspaceSplit(
|
||||
"root-split",
|
||||
UIEditorWorkspaceSplitAxis::Horizontal,
|
||||
0.66f,
|
||||
BuildUIEditorWorkspaceTabStack(
|
||||
"document-tabs",
|
||||
{
|
||||
BuildUIEditorWorkspacePanel("doc-a-node", "doc-a", "Document A", true),
|
||||
BuildUIEditorWorkspacePanel("doc-b-node", "doc-b", "Document B", true)
|
||||
},
|
||||
0u),
|
||||
BuildUIEditorWorkspacePanel("details-node", "details", "Details", true));
|
||||
workspace.activePanelId = "doc-a";
|
||||
return workspace;
|
||||
}
|
||||
|
||||
std::vector<std::string> CollectVisiblePanelIds(
|
||||
const UIEditorWorkspaceModel& workspace,
|
||||
const UIEditorWorkspaceSession& session) {
|
||||
const auto panels = CollectUIEditorWorkspaceVisiblePanels(workspace, session);
|
||||
std::vector<std::string> ids = {};
|
||||
ids.reserve(panels.size());
|
||||
for (const auto& panel : panels) {
|
||||
ids.push_back(panel.panelId);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(UIEditorWorkspaceSessionTest, DefaultSessionTracksEveryWorkspacePanelAsOpenAndVisible) {
|
||||
const UIEditorPanelRegistry registry = BuildPanelRegistry();
|
||||
const UIEditorWorkspaceModel workspace = BuildWorkspace();
|
||||
|
||||
const UIEditorWorkspaceSession session =
|
||||
BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
|
||||
const auto validation = ValidateUIEditorWorkspaceSession(registry, workspace, session);
|
||||
ASSERT_TRUE(validation.IsValid()) << validation.message;
|
||||
|
||||
ASSERT_EQ(session.panelStates.size(), 3u);
|
||||
ASSERT_NE(FindUIEditorPanelSessionState(session, "doc-a"), nullptr);
|
||||
ASSERT_NE(FindUIEditorPanelSessionState(session, "doc-b"), nullptr);
|
||||
ASSERT_NE(FindUIEditorPanelSessionState(session, "details"), nullptr);
|
||||
|
||||
const auto visibleIds = CollectVisiblePanelIds(workspace, session);
|
||||
ASSERT_EQ(visibleIds.size(), 2u);
|
||||
EXPECT_EQ(visibleIds[0], "doc-a");
|
||||
EXPECT_EQ(visibleIds[1], "details");
|
||||
}
|
||||
|
||||
TEST(UIEditorWorkspaceSessionTest, HidingActiveDocumentSelectsNextVisiblePanelInTabStack) {
|
||||
const UIEditorPanelRegistry registry = BuildPanelRegistry();
|
||||
UIEditorWorkspaceModel workspace = BuildWorkspace();
|
||||
UIEditorWorkspaceSession session =
|
||||
BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
|
||||
ASSERT_TRUE(TryHideUIEditorWorkspacePanel(registry, workspace, session, "doc-a"));
|
||||
|
||||
const auto* hiddenState = FindUIEditorPanelSessionState(session, "doc-a");
|
||||
ASSERT_NE(hiddenState, nullptr);
|
||||
EXPECT_TRUE(hiddenState->open);
|
||||
EXPECT_FALSE(hiddenState->visible);
|
||||
EXPECT_EQ(workspace.activePanelId, "doc-b");
|
||||
EXPECT_EQ(workspace.root.children.front().selectedTabIndex, 1u);
|
||||
|
||||
const auto visibleIds = CollectVisiblePanelIds(workspace, session);
|
||||
ASSERT_EQ(visibleIds.size(), 2u);
|
||||
EXPECT_EQ(visibleIds[0], "doc-b");
|
||||
EXPECT_EQ(visibleIds[1], "details");
|
||||
}
|
||||
|
||||
TEST(UIEditorWorkspaceSessionTest, ShowingHiddenPanelRestoresVisibilityAndActivation) {
|
||||
const UIEditorPanelRegistry registry = BuildPanelRegistry();
|
||||
UIEditorWorkspaceModel workspace = BuildWorkspace();
|
||||
UIEditorWorkspaceSession session =
|
||||
BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
|
||||
ASSERT_TRUE(TryHideUIEditorWorkspacePanel(registry, workspace, session, "doc-a"));
|
||||
ASSERT_TRUE(TryShowUIEditorWorkspacePanel(registry, workspace, session, "doc-a"));
|
||||
|
||||
EXPECT_EQ(workspace.activePanelId, "doc-a");
|
||||
EXPECT_EQ(workspace.root.children.front().selectedTabIndex, 0u);
|
||||
|
||||
const auto* restoredState = FindUIEditorPanelSessionState(session, "doc-a");
|
||||
ASSERT_NE(restoredState, nullptr);
|
||||
EXPECT_TRUE(restoredState->open);
|
||||
EXPECT_TRUE(restoredState->visible);
|
||||
}
|
||||
|
||||
TEST(UIEditorWorkspaceSessionTest, ClosingPanelPreventsActivationUntilReopened) {
|
||||
const UIEditorPanelRegistry registry = BuildPanelRegistry();
|
||||
UIEditorWorkspaceModel workspace = BuildWorkspace();
|
||||
UIEditorWorkspaceSession session =
|
||||
BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
|
||||
ASSERT_TRUE(TryCloseUIEditorWorkspacePanel(registry, workspace, session, "doc-a"));
|
||||
EXPECT_FALSE(TryActivateUIEditorWorkspacePanel(registry, workspace, session, "doc-a"));
|
||||
EXPECT_EQ(workspace.activePanelId, "doc-b");
|
||||
|
||||
ASSERT_TRUE(TryOpenUIEditorWorkspacePanel(registry, workspace, session, "doc-a"));
|
||||
EXPECT_EQ(workspace.activePanelId, "doc-a");
|
||||
EXPECT_EQ(workspace.root.children.front().selectedTabIndex, 0u);
|
||||
}
|
||||
|
||||
TEST(UIEditorWorkspaceSessionTest, NonCloseablePanelCannotBeClosedOrHidden) {
|
||||
UIEditorPanelRegistry registry = BuildPanelRegistry();
|
||||
UIEditorWorkspaceModel workspace = {};
|
||||
workspace.root = BuildUIEditorWorkspacePanel("root-node", "root", "Root", true);
|
||||
workspace.activePanelId = "root";
|
||||
UIEditorWorkspaceSession session =
|
||||
BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
|
||||
ASSERT_NE(FindUIEditorPanelDescriptor(registry, "root"), nullptr);
|
||||
EXPECT_FALSE(TryCloseUIEditorWorkspacePanel(registry, workspace, session, "root"));
|
||||
EXPECT_FALSE(TryHideUIEditorWorkspacePanel(registry, workspace, session, "root"));
|
||||
|
||||
const auto* rootState = FindUIEditorPanelSessionState(session, "root");
|
||||
ASSERT_NE(rootState, nullptr);
|
||||
EXPECT_TRUE(rootState->open);
|
||||
EXPECT_TRUE(rootState->visible);
|
||||
}
|
||||
|
||||
TEST(UIEditorWorkspaceSessionTest, ValidationRejectsMissingPanelStateAndInvalidActivePanel) {
|
||||
const UIEditorPanelRegistry registry = BuildPanelRegistry();
|
||||
UIEditorWorkspaceModel workspace = BuildWorkspace();
|
||||
UIEditorWorkspaceSession session =
|
||||
BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
|
||||
session.panelStates.pop_back();
|
||||
auto validation = ValidateUIEditorWorkspaceSession(registry, workspace, session);
|
||||
EXPECT_EQ(validation.code, UIEditorWorkspaceSessionValidationCode::MissingPanelState);
|
||||
|
||||
session = BuildDefaultUIEditorWorkspaceSession(registry, workspace);
|
||||
ASSERT_TRUE(TryHideUIEditorWorkspacePanel(registry, workspace, session, "doc-a"));
|
||||
ASSERT_TRUE(TryHideUIEditorWorkspacePanel(registry, workspace, session, "doc-b"));
|
||||
workspace.activePanelId = "doc-a";
|
||||
|
||||
validation = ValidateUIEditorWorkspaceSession(registry, workspace, session);
|
||||
EXPECT_EQ(validation.code, UIEditorWorkspaceSessionValidationCode::InvalidActivePanelId);
|
||||
}
|
||||
Reference in New Issue
Block a user