hemplate

Simple XML template engine
git clone git://git.dimitrijedobrota.com/hemplate.git
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING

commit 2b8135176daf1c8aa8b840a420caf46ac9ec1ed0
parent b4542f4193872af8947e244cd166d5e11dc441bb
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Fri, 2 May 2025 15:36:54 +0200

Add element tests

Diffstat:
M include/hemplate/element.hpp | ++++++++ --------
M test/CMakeLists.txt | +
A test/source/element.cpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

3 files changed, 167 insertions(+), 8 deletions(-)


diff --git a/ include/hemplate/element.hpp b/ include/hemplate/element.hpp

@@ -35,19 +35,19 @@ class HEMPLATE_EXPORT element_base

using child_t = std::variant<element_base, std::string>;
std::vector<child_t> m_cdn;

void add(const std::ranges::forward_range auto& range)
void add(std::ranges::forward_range auto range)
requires(!std::constructible_from<std::string_view, decltype(range)>)
{
m_cdn.reserve(std::size(m_cdn) + std::size(range));
m_cdn.insert(std::end(m_cdn), std::begin(range), std::end(range));
m_cdn.insert(
std::end(m_cdn),
std::make_move_iterator(std::begin(range)),
std::make_move_iterator(std::end(range))
);
}

void add(const std::string_view data)
{
m_cdn.emplace_back(std::string(data));
}

void add(const element_base& elem) { m_cdn.emplace_back(elem); }
void add(std::string_view data) { m_cdn.emplace_back(std::string(data)); }
void add(element_base elem) { m_cdn.emplace_back(std::move(elem)); }

template<typename... Args>
explicit element_base(

diff --git a/ test/CMakeLists.txt b/ test/CMakeLists.txt

@@ -23,6 +23,7 @@ endfunction()


add_test(attribute)
add_test(attribute_list)
add_test(element)

# ---- End-of-file commands ----

diff --git a/ test/source/element.cpp b/ test/source/element.cpp

@@ -0,0 +1,158 @@

#include "hemplate/element.hpp"

#include <catch2/catch_test_macros.hpp>

using namespace hemplate; // NOLINT

TEST_CASE("boolean", "[element]")
{
using tag = element_boolean<"tag">;
using child = element_boolean<"child">;

SECTION("empty")
{
const auto t = tag {};

REQUIRE(std::string(t) == "<tag>\n</tag>\n");
}

SECTION("attribute")
{
const auto t = tag {{{"attr", "val"}}};

REQUIRE(std::string(t) == "<tag attr=\"val\">\n</tag>\n");
}

SECTION("data")
{
const auto t = tag {"text"};

REQUIRE(std::string(t) == "<tag>\n text\n</tag>\n");
}

SECTION("attribute data")
{
const auto t = tag {{{"attr", "val"}}, "text"};

REQUIRE(std::string(t) == "<tag attr=\"val\">\n text\n</tag>\n");
}

SECTION("child")
{
const auto t = tag {
child {},
};

REQUIRE(std::string(t) == "<tag>\n <child>\n </child>\n</tag>\n");
}

SECTION("attribute child")
{
const auto t = tag {
{{"attr", "val"}},
child {},
};

REQUIRE(
std::string(t) == "<tag attr=\"val\">\n <child>\n </child>\n</tag>\n"
);
}

SECTION("child data")
{
const auto t = tag {
child {"text"},
};

REQUIRE(
std::string(t) == "<tag>\n <child>\n text\n </child>\n</tag>\n"
);
}

SECTION("attribute child data")
{
const auto t = tag {
{{"attr", "val"}},
child {"text"},
};

REQUIRE(
std::string(t)
== "<tag attr=\"val\">\n <child>\n text\n </child>\n</tag>\n"
);
}
}

TEST_CASE("atomic", "[element]")
{
using tag = element_atomic<"tag">;

SECTION("empty")
{
const auto t = tag {};

REQUIRE(std::string(t) == "<tag />\n");
}

SECTION("attribute")
{
const auto t = tag {{{"attr", "val"}}};

REQUIRE(std::string(t) == "<tag attr=\"val\" />\n");
}
}

TEST_CASE("element", "[element]")
{
using child = element_boolean<"child">;

SECTION("empty")
{
const auto t = element {};

REQUIRE(std::string(t) == ""); // NOLINT
}

SECTION("data")
{
const auto t = element {"text"};

REQUIRE(std::string(t) == "text\n");
}

SECTION("child")
{
const auto t = element {
child {},
};

REQUIRE(std::string(t) == "<child>\n</child>\n");
}

SECTION("child element")
{
const auto t = child {
element {},
};

REQUIRE(std::string(t) == "<child>\n</child>\n");
}

SECTION("element child data")
{
const auto t = element {
child {"text"},
};

REQUIRE(std::string(t) == "<child>\n text\n</child>\n");
}

SECTION("child element data")
{
const auto t = child {
element {"text"},
};

REQUIRE(std::string(t) == "<child>\n text\n</child>\n");
}
}