From cf580099b2ad211547ebcad96bb8f5eddc77d493 Mon Sep 17 00:00:00 2001 From: "Tim.Ebbeke" Date: Tue, 23 Jan 2024 12:03:40 +0100 Subject: [PATCH] Fixed unconditional render function HTMLElement operator. --- .../frontend/elements/impl/html_element.hpp | 16 ++- nui/test/nui/test_render.hpp | 110 +++++++++++++++--- 2 files changed, 103 insertions(+), 23 deletions(-) diff --git a/nui/include/nui/frontend/elements/impl/html_element.hpp b/nui/include/nui/frontend/elements/impl/html_element.hpp index 5484558e..52023f30 100644 --- a/nui/include/nui/frontend/elements/impl/html_element.hpp +++ b/nui/include/nui/frontend/elements/impl/html_element.hpp @@ -267,18 +267,22 @@ namespace Nui requires(!InvocableReturns) auto operator()(GeneratorT&& elementRenderer) && { - return [self = this->clone(), - elementRenderer = std::forward(elementRenderer)](auto& parentElement, Renderer const&) { - return elementRenderer()(parentElement, Renderer{.type = RendererType::Append}); + return [self = this->clone(), elementRenderer = std::forward(elementRenderer)]( + auto& parentElement, Renderer const& gen) { + auto materialized = renderElement(gen, parentElement, self); + elementRenderer()(*materialized, Renderer{.type = RendererType::Append}); + return materialized; }; } template GeneratorT> requires InvocableReturns auto operator()(GeneratorT&& elementRenderer) && { - return [self = this->clone(), - elementRenderer = std::forward(elementRenderer)](auto& parentElement, Renderer const&) { - return elementRenderer(parentElement, Renderer{.type = RendererType::Append}); + return [self = this->clone(), elementRenderer = std::forward(elementRenderer)]( + auto& parentElement, Renderer const& gen) { + auto materialized = renderElement(gen, parentElement, self); + materialized->setTextContent(elementRenderer(*materialized, Renderer{.type = RendererType::Append})); + return materialized; }; } diff --git a/nui/test/nui/test_render.hpp b/nui/test/nui/test_render.hpp index 8cd9953a..d3841ef0 100644 --- a/nui/test/nui/test_render.hpp +++ b/nui/test/nui/test_render.hpp @@ -68,7 +68,8 @@ namespace Nui::Tests using Nui::Elements::span; render(div{}(span{}("Hello World"))); ASSERT_EQ(Nui::val::global("document")["body"]["children"]["length"].as(), 1); - EXPECT_EQ(Nui::val::global("document")["body"]["children"][0]["textContent"].as(), "Hello World"); + EXPECT_EQ(Nui::val::global("document")["body"]["children"][0]["textContent"].as(), "Hello + World"); } TEST_F(TestRender, TextBodyCanBeObservedVariable) @@ -406,7 +407,8 @@ namespace Nui::Tests globalEventContext.executeActiveEventsImmediately(); EXPECT_EQ( - Nui::val::global("document")["body"]["children"][0]["attributes"]["id"].as(), "changed again"); + Nui::val::global("document")["body"]["children"][0]["attributes"]["id"].as(), "changed + again"); } TEST_F(TestRender, StableFragmentCreatesPhantomDiv) @@ -484,7 +486,7 @@ namespace Nui::Tests else { const auto s = stabilize( - stable, + stable, span{id = once}(button{class_ = onceClass}()) ); once = "X"; @@ -547,7 +549,8 @@ namespace Nui::Tests render(div{}(text{"Hello World"}())); ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as(), 1); - EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as(), "Hello World"); + EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as(), "Hello + World"); } TEST_F(TestRender, PlainTextCanBeUpdated) @@ -559,7 +562,8 @@ namespace Nui::Tests render(div{}(text{textContent}())); ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as(), 1); - EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as(), "Hello World"); + EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as(), "Hello + World"); textContent = "Changed"; globalEventContext.executeActiveEventsImmediately(); @@ -576,11 +580,13 @@ namespace Nui::Tests render(div{}(text{textContent}())); ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as(), 1); - EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as(), "Hello World"); + EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as(), "Hello + World"); textContent = "Changed"; - EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as(), "Hello World"); + EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as(), "Hello + World"); } TEST_F(TestRender, PlainTextCanAppearAnywhereBetweenRegularElements) @@ -591,8 +597,12 @@ namespace Nui::Tests ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as(), 3); EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["tagName"].as(), "span"); - EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as(), "Hello World"); - EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][2]["tagName"].as(), "div"); + EXPECT_EQ( + Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as(), + "Hello + World "); EXPECT_EQ(Nui::val::global(" document ")[" body "][" childNodes "][2][" tagName + "].as(), + "div"); } TEST_F(TestRender, PlainTextCanBeChangedAlongsideRegularElements) @@ -605,8 +615,12 @@ namespace Nui::Tests ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as(), 3); EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["tagName"].as(), "span"); - EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as(), "Hello World"); - EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][2]["tagName"].as(), "div"); + EXPECT_EQ( + Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as(), + "Hello + World "); EXPECT_EQ(Nui::val::global(" document ")[" body "][" childNodes "][2][" tagName + "].as(), + "div"); textContent = "Changed"; globalEventContext.executeActiveEventsImmediately(); @@ -625,8 +639,12 @@ namespace Nui::Tests ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as(), 3); EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["tagName"].as(), "span"); - EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as(), "Hello World"); - EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][2]["tagName"].as(), "div"); + EXPECT_EQ( + Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as(), + "Hello + World "); EXPECT_EQ(Nui::val::global(" document ")[" body "][" childNodes "][2][" tagName + "].as(), + "div"); textContent = "Changed"; globalEventContext.executeActiveEventsImmediately(); @@ -641,7 +659,8 @@ namespace Nui::Tests render(div{}(fragment(text{"Hello World"}()))); ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as(), 1); - EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as(), "Hello World"); + EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as(), "Hello + World"); } TEST_F(TestRender, PlainTextCanBeUpdatedInsideFragment) @@ -653,7 +672,8 @@ namespace Nui::Tests render(div{}(fragment(text{textContent}()))); ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as(), 1); - EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as(), "Hello World"); + EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as(), "Hello + World"); textContent = "Changed"; globalEventContext.executeActiveEventsImmediately(); @@ -671,8 +691,12 @@ namespace Nui::Tests ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as(), 3); EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["tagName"].as(), "span"); - EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as(), "Hello World"); - EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][2]["tagName"].as(), "div"); + EXPECT_EQ( + Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as(), + "Hello + World "); EXPECT_EQ(Nui::val::global(" document ")[" body "][" childNodes "][2][" tagName + "].as(), + "div"); textContent = "Changed"; globalEventContext.executeActiveEventsImmediately(); @@ -733,4 +757,56 @@ namespace Nui::Tests EXPECT_EQ( Nui::val::global("document")["body"]["children"][0]["children"][0]["attributes"]["cx"].as(), 10); } + + TEST_F(TestRender, CanUseUnconditionalRendererFunction) + { + using namespace Nui::Elements; + using namespace Nui::Attributes; + using div = Nui::Elements::div; + + render(body{id = "body"}([]() -> Nui::ElementRenderer { + return div{ + id = "inner", + }(); + })); + + EXPECT_EQ(Nui::val::global("document")["body"]["children"]["length"].as(), 1); + EXPECT_EQ(Nui::val::global("document")["body"]["children"][0]["attributes"]["id"].as(), "inner"); + } + + TEST_F(TestRender, AttributesArePresentOnRangeChildWithRendererFunctionChildren) + { + using namespace Nui::Elements; + using namespace Nui::Attributes; + using div = Nui::Elements::div; + using span = Nui::Elements::span; + + Nui::Observed> range{std::vector{"A", "B", "C", "D"}}; + + render(body{ + class_ = "range-parent", + }(range.map([](long long, auto const& element) { + return div{ + class_ = "range-child", + id = element, + }([]() -> Nui::ElementRenderer { + return span{ + class_ = "range-child-child", + }(); + }); + }))); + + auto children = Nui::val::global("document")["body"]["children"].as(); + ASSERT_EQ(children.size(), range.value().size()); + + for (size_t i = 0; i < children.size(); ++i) + { + auto& child = children[i]; + std::string expectedId = range.value()[i]; + std::string expectedClass = "range-child"; + + EXPECT_EQ(child["attributes"]["id"].as(), expectedId); + EXPECT_EQ(child["attributes"]["class"].as(), expectedClass); + } + } } \ No newline at end of file