ADD: LayoutEngineTests

This commit is contained in:
sebastian 2026-04-17 11:02:22 +02:00
parent 4137db0c1f
commit b5ddbcf9c4
3 changed files with 150 additions and 1 deletions

View File

@ -18,6 +18,28 @@ target_include_directories(glad PUBLIC
find_package(Freetype REQUIRED) find_package(Freetype REQUIRED)
include_directories(${FREETYPE_INCLUDE_DIRS}) include_directories(${FREETYPE_INCLUDE_DIRS})
include(FetchContent)
FetchContent_Declare(
Catch2
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
GIT_TAG v3.7.1
)
FetchContent_MakeAvailable(Catch2)
add_executable(LayoutEngineTests
tests/layout/LayoutEngineTest.cpp
)
target_include_directories(LayoutEngineTests PRIVATE
src
lib/glm
)
target_link_libraries(LayoutEngineTests PRIVATE Catch2::Catch2WithMain)
include(CTest)
include(Catch)
catch_discover_tests(LayoutEngineTests)
add_executable(Dicewars_Siedler src/main.cpp add_executable(Dicewars_Siedler src/main.cpp
src/engine/core/Window.cpp src/engine/core/Window.cpp

View File

@ -18,7 +18,7 @@ void UiPositioner::applyLayout(const ::LayoutEngine::ComputedLayout &layout) {
void UiPositioner::compute(const Dimensions &parent) { void UiPositioner::compute(const Dimensions &parent) {
LayoutEngine::NodeLayout node = buildNodeLayout(); LayoutEngine::NodeLayout node = buildNodeLayout();
LayoutEngine::ComputedLayout result = LayoutEngine::compute(node, parent); LayoutEngine::ComputedLayout result = LayoutEngine::compute(node, parent, Application::getInstance().getWindow().GetWidth(), Application::getInstance().getWindow().GetHeight());
applyLayout(result); applyLayout(result);
} }

View File

@ -0,0 +1,127 @@
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_floating_point.hpp>
#include "engine/core/gui/uiComponent/layout/LayoutEngine.h"
using namespace LayoutEngine;
using Catch::Matchers::WithinAbs;
const float EPS = 0.001f;
static NodeLayout makeNode(float x, float y, float w, float h) {
NodeLayout n;
n.layoutStyle.width = { w, SizeUnit::Percent };
n.layoutStyle.height = { h, SizeUnit::Percent };
n.layoutStyle.margin.left = { x, SizeUnit::Percent };
n.layoutStyle.margin.top = { y, SizeUnit::Percent };
return n;
}
static Dimensions screen800x600() {
return { 0.f, 0.f, 1.0f, 1.0f };
}
// ── Basisfälle ───────────────────────────────────────────────────────────────
TEST_CASE("SizeUnit::Pixels wird korrekt normalisiert", "[layout][pixels]") {
NodeLayout root;
root.layoutStyle.width = { 400.f, SizeUnit::Pixels };
root.layoutStyle.height = { 300.f, SizeUnit::Pixels };
auto result = compute(root, screen800x600(), 800.f, 600.f);
REQUIRE_THAT(result.self.width, WithinAbs(0.5f, EPS)); // 400/800
REQUIRE_THAT(result.self.height, WithinAbs(0.5f, EPS)); // 300/600
}
TEST_CASE("Eigene Dimensionen werden korrekt berechnet", "[layout][self]") {
NodeLayout root = makeNode(0.1f, 0.2f, 0.5f, 0.4f);
auto result = compute(root, screen800x600(), 800.f, 600.f);
REQUIRE_THAT(result.self.x, WithinAbs(0.1f, EPS));
REQUIRE_THAT(result.self.y, WithinAbs(0.2f, EPS));
REQUIRE_THAT(result.self.width, WithinAbs(0.5f, EPS));
REQUIRE_THAT(result.self.height, WithinAbs(0.4f, EPS));
}
TEST_CASE("Kein Kind → leere children-Liste", "[layout][children]") {
NodeLayout root = makeNode(0.f, 0.f, 0.5f, 0.5f);
auto result = compute(root, screen800x600(), 800.f, 600.f);
REQUIRE(result.children.empty());
}
// ── JustifyContent ───────────────────────────────────────────────────────────
TEST_CASE("JustifyContent::Start Kinder beginnen bei 0", "[layout][justify]") {
NodeLayout root = makeNode(0.f, 0.f, 1.0f, 1.0f);
root.layoutStyle.flexDirection = FlexDirection::Row;
root.layoutStyle.justifyContent = JustifyContent::Start;
root.children.push_back(makeNode(0.f, 0.f, 0.2f, 1.0f));
root.children.push_back(makeNode(0.f, 0.f, 0.2f, 1.0f));
auto result = compute(root, screen800x600(), 800.f, 600.f);
REQUIRE_THAT(result.children[0].self.x, WithinAbs(0.0f, EPS));
REQUIRE_THAT(result.children[1].self.x, WithinAbs(0.2f, EPS));
}
TEST_CASE("JustifyContent::Center Kind horizontal zentriert", "[layout][justify]") {
NodeLayout root = makeNode(0.f, 0.f, 1.0f, 1.0f);
root.layoutStyle.flexDirection = FlexDirection::Row;
root.layoutStyle.justifyContent = JustifyContent::Center;
root.children.push_back(makeNode(0.f, 0.f, 0.4f, 1.0f));
auto result = compute(root, screen800x600(), 800.f, 600.f);
// remaining = 1.0 - 0.4 = 0.6 → offset = 0.3
REQUIRE_THAT(result.children[0].self.x, WithinAbs(0.3f, EPS));
}
TEST_CASE("JustifyContent::SpaceBetween Gap korrekt verteilt", "[layout][justify]") {
NodeLayout root = makeNode(0.f, 0.f, 1.0f, 1.0f);
root.layoutStyle.flexDirection = FlexDirection::Row;
root.layoutStyle.justifyContent = JustifyContent::SpaceBetween;
root.children.push_back(makeNode(0.f, 0.f, 0.2f, 1.0f));
root.children.push_back(makeNode(0.f, 0.f, 0.2f, 1.0f));
root.children.push_back(makeNode(0.f, 0.f, 0.2f, 1.0f));
auto result = compute(root, screen800x600(), 800.f, 600.f);
// remaining = 1.0 - 0.6 = 0.4, gap = 0.2
REQUIRE_THAT(result.children[0].self.x, WithinAbs(0.0f, EPS));
REQUIRE_THAT(result.children[1].self.x, WithinAbs(0.4f, EPS));
REQUIRE_THAT(result.children[2].self.x, WithinAbs(0.8f, EPS));
}
// ── AlignItems ───────────────────────────────────────────────────────────────
TEST_CASE("AlignItems::Center Kind vertikal zentriert (Row)", "[layout][align]") {
NodeLayout root = makeNode(0.f, 0.f, 1.0f, 1.0f);
root.layoutStyle.flexDirection = FlexDirection::Row;
root.layoutStyle.alignItems = AlignItems::Center;
root.children.push_back(makeNode(0.f, 0.f, 0.5f, 0.4f));
auto result = compute(root, screen800x600(), 800.f, 600.f);
// remaining = 1.0 - 0.4 = 0.6 → y = 0.3
REQUIRE_THAT(result.children[0].self.y, WithinAbs(0.3f, EPS));
}
TEST_CASE("AlignItems::End Kind am unteren Rand (Row)", "[layout][align]") {
NodeLayout root = makeNode(0.f, 0.f, 1.0f, 1.0f);
root.layoutStyle.flexDirection = FlexDirection::Row;
root.layoutStyle.alignItems = AlignItems::End;
root.children.push_back(makeNode(0.f, 0.f, 0.5f, 0.4f));
auto result = compute(root, screen800x600(), 800.f, 600.f);
// remaining = 1.0 - 0.4 = 0.6 → y = 0.6
REQUIRE_THAT(result.children[0].self.y, WithinAbs(0.6f, EPS));
}
// ── FlexDirection::Column ────────────────────────────────────────────────────
TEST_CASE("Column: Kinder werden vertikal gestapelt", "[layout][column]") {
NodeLayout root = makeNode(0.f, 0.f, 1.0f, 1.0f);
root.layoutStyle.flexDirection = FlexDirection::Column;
root.layoutStyle.justifyContent = JustifyContent::Start;
root.children.push_back(makeNode(0.f, 0.f, 1.0f, 0.3f));
root.children.push_back(makeNode(0.f, 0.f, 1.0f, 0.3f));
auto result = compute(root, screen800x600(), 800.f, 600.f);
REQUIRE_THAT(result.children[0].self.y, WithinAbs(0.0f, EPS));
REQUIRE_THAT(result.children[1].self.y, WithinAbs(0.3f, EPS));
}