Skip to content

Commit

Permalink
Fixed unconditional render function HTMLElement operator.
Browse files Browse the repository at this point in the history
  • Loading branch information
5cript committed Jan 23, 2024
1 parent 04b8031 commit cf58009
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 23 deletions.
16 changes: 10 additions & 6 deletions nui/include/nui/frontend/elements/impl/html_element.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,18 +267,22 @@ namespace Nui
requires(!InvocableReturns<GeneratorT, std::string>)
auto operator()(GeneratorT&& elementRenderer) &&
{
return [self = this->clone(),
elementRenderer = std::forward<GeneratorT>(elementRenderer)](auto& parentElement, Renderer const&) {
return elementRenderer()(parentElement, Renderer{.type = RendererType::Append});
return [self = this->clone(), elementRenderer = std::forward<GeneratorT>(elementRenderer)](
auto& parentElement, Renderer const& gen) {
auto materialized = renderElement(gen, parentElement, self);
elementRenderer()(*materialized, Renderer{.type = RendererType::Append});
return materialized;
};
}
template <typename T, std::invocable<T&, Renderer const&> GeneratorT>
requires InvocableReturns<GeneratorT, std::string>
auto operator()(GeneratorT&& elementRenderer) &&
{
return [self = this->clone(),
elementRenderer = std::forward<GeneratorT>(elementRenderer)](auto& parentElement, Renderer const&) {
return elementRenderer(parentElement, Renderer{.type = RendererType::Append});
return [self = this->clone(), elementRenderer = std::forward<GeneratorT>(elementRenderer)](
auto& parentElement, Renderer const& gen) {
auto materialized = renderElement(gen, parentElement, self);
materialized->setTextContent(elementRenderer(*materialized, Renderer{.type = RendererType::Append}));
return materialized;
};
}

Expand Down
110 changes: 93 additions & 17 deletions nui/test/nui/test_render.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<long long>(), 1);
EXPECT_EQ(Nui::val::global("document")["body"]["children"][0]["textContent"].as<std::string>(), "Hello World");
EXPECT_EQ(Nui::val::global("document")["body"]["children"][0]["textContent"].as<std::string>(), "Hello
World");
}

TEST_F(TestRender, TextBodyCanBeObservedVariable)
Expand Down Expand Up @@ -406,7 +407,8 @@ namespace Nui::Tests
globalEventContext.executeActiveEventsImmediately();

EXPECT_EQ(
Nui::val::global("document")["body"]["children"][0]["attributes"]["id"].as<std::string>(), "changed again");
Nui::val::global("document")["body"]["children"][0]["attributes"]["id"].as<std::string>(), "changed
again");
}

TEST_F(TestRender, StableFragmentCreatesPhantomDiv)
Expand Down Expand Up @@ -484,7 +486,7 @@ namespace Nui::Tests
else
{
const auto s = stabilize(
stable,
stable,
span{id = once}(button{class_ = onceClass}())
);
once = "X";
Expand Down Expand Up @@ -547,7 +549,8 @@ namespace Nui::Tests
render(div{}(text{"Hello World"}()));

ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as<long long>(), 1);
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as<std::string>(), "Hello World");
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as<std::string>(), "Hello
World");
}

TEST_F(TestRender, PlainTextCanBeUpdated)
Expand All @@ -559,7 +562,8 @@ namespace Nui::Tests
render(div{}(text{textContent}()));

ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as<long long>(), 1);
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as<std::string>(), "Hello World");
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as<std::string>(), "Hello
World");

textContent = "Changed";
globalEventContext.executeActiveEventsImmediately();
Expand All @@ -576,11 +580,13 @@ namespace Nui::Tests
render(div{}(text{textContent}()));

ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as<long long>(), 1);
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as<std::string>(), "Hello World");
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as<std::string>(), "Hello
World");

textContent = "Changed";

EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as<std::string>(), "Hello World");
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as<std::string>(), "Hello
World");
}

TEST_F(TestRender, PlainTextCanAppearAnywhereBetweenRegularElements)
Expand All @@ -591,8 +597,12 @@ namespace Nui::Tests

ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as<long long>(), 3);
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["tagName"].as<std::string>(), "span");
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as<std::string>(), "Hello World");
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][2]["tagName"].as<std::string>(), "div");
EXPECT_EQ(
Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as<std::string>(),
"Hello
World "); EXPECT_EQ(Nui::val::global(" document ")[" body "][" childNodes "][2][" tagName
"].as<std::string>(),
"div");
}

TEST_F(TestRender, PlainTextCanBeChangedAlongsideRegularElements)
Expand All @@ -605,8 +615,12 @@ namespace Nui::Tests

ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as<long long>(), 3);
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["tagName"].as<std::string>(), "span");
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as<std::string>(), "Hello World");
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][2]["tagName"].as<std::string>(), "div");
EXPECT_EQ(
Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as<std::string>(),
"Hello
World "); EXPECT_EQ(Nui::val::global(" document ")[" body "][" childNodes "][2][" tagName
"].as<std::string>(),
"div");

textContent = "Changed";
globalEventContext.executeActiveEventsImmediately();
Expand All @@ -625,8 +639,12 @@ namespace Nui::Tests

ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as<long long>(), 3);
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["tagName"].as<std::string>(), "span");
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as<std::string>(), "Hello World");
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][2]["tagName"].as<std::string>(), "div");
EXPECT_EQ(
Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as<std::string>(),
"Hello
World "); EXPECT_EQ(Nui::val::global(" document ")[" body "][" childNodes "][2][" tagName
"].as<std::string>(),
"div");

textContent = "Changed";
globalEventContext.executeActiveEventsImmediately();
Expand All @@ -641,7 +659,8 @@ namespace Nui::Tests
render(div{}(fragment(text{"Hello World"}())));

ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as<long long>(), 1);
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as<std::string>(), "Hello World");
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as<std::string>(), "Hello
World");
}

TEST_F(TestRender, PlainTextCanBeUpdatedInsideFragment)
Expand All @@ -653,7 +672,8 @@ namespace Nui::Tests
render(div{}(fragment(text{textContent}())));

ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as<long long>(), 1);
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as<std::string>(), "Hello World");
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["nodeValue"].as<std::string>(), "Hello
World");

textContent = "Changed";
globalEventContext.executeActiveEventsImmediately();
Expand All @@ -671,8 +691,12 @@ namespace Nui::Tests

ASSERT_EQ(Nui::val::global("document")["body"]["childNodes"]["length"].as<long long>(), 3);
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][0]["tagName"].as<std::string>(), "span");
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as<std::string>(), "Hello World");
EXPECT_EQ(Nui::val::global("document")["body"]["childNodes"][2]["tagName"].as<std::string>(), "div");
EXPECT_EQ(
Nui::val::global("document")["body"]["childNodes"][1]["nodeValue"].as<std::string>(),
"Hello
World "); EXPECT_EQ(Nui::val::global(" document ")[" body "][" childNodes "][2][" tagName
"].as<std::string>(),
"div");

textContent = "Changed";
globalEventContext.executeActiveEventsImmediately();
Expand Down Expand Up @@ -733,4 +757,56 @@ namespace Nui::Tests
EXPECT_EQ(
Nui::val::global("document")["body"]["children"][0]["children"][0]["attributes"]["cx"].as<long long>(), 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<long long>(), 1);
EXPECT_EQ(Nui::val::global("document")["body"]["children"][0]["attributes"]["id"].as<std::string>(), "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<std::vector<std::string>> range{std::vector<std::string>{"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<Nui::Tests::Engine::Array>();
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<std::string>(), expectedId);
EXPECT_EQ(child["attributes"]["class"].as<std::string>(), expectedClass);
}
}
}

0 comments on commit cf58009

Please sign in to comment.