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 d6ac3a263b2f1141f8c28b6c29ae246ba8b58ad4
parent 2b8135176daf1c8aa8b840a420caf46ac9ec1ed0
author Dimitrije Dobrota <mail@dimitrijedobrota.com>
date Fri, 2 May 2025 17:12:35 +0200

Test everything and general cleanup

Diffstat:
M include/hemplate/atom.hpp | +++++++ --------
M include/hemplate/classes.hpp | +++++++++ -
M include/hemplate/rss.hpp | +++++++++++++++++++ -----------------------------------------------
M include/hemplate/sitemap.hpp | +++++++ ---------
M test/CMakeLists.txt | ++++++++ ---
A test/source/atom_test.cpp | +++++++++++++++++++++++++
D test/source/attribute.cpp | -----------------------------------------------------------
D test/source/attribute_list.cpp | ---------------------------------------------------------------------------------
A test/source/attribute_list_test.cpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A test/source/attribute_test.cpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A test/source/classes_test.cpp | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D test/source/element.cpp | ---------------------------------------------------------------------------------
A test/source/element_test.cpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A test/source/html_test.cpp | ++++++++++++
A test/source/rss_test.cpp | ++++++++++++++++++++++++++++++++++++++++++
A test/source/sitemap_test.cpp | ++++++++++++++++++++++

16 files changed, 526 insertions(+), 377 deletions(-)


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

@@ -11,25 +11,24 @@ std::string format_time_now(); class HEMPLATE_EXPORT feed : public element_boolean<"feed"> {
static auto attributes(std::string_view xmlns)
static auto def_attrs()
{ return attribute_list {
{"xmlns", xmlns},
{"xmlns", "http://www.w3.org/2005/Atom"},
}; } public:
static constexpr const auto def_xmlns = "http://www.w3.org/2005/Atom";
template<typename... Args>
explicit feed(std::string_view xmlns, Args&&... args)
: element_boolean(attributes(xmlns), std::forward<Args>(args)...)
requires(!std::same_as<attribute_list, std::remove_cvref_t<Args>> && ...)
explicit feed(Args&&... args)
: element_boolean(def_attrs(), std::forward<Args>(args)...)
{ } template<typename... Args>
explicit feed(Args&&... args)
: element_boolean(attributes(def_xmlns), std::forward<Args>(args)...)
explicit feed(const attribute_list& attrs, Args&&... args)
: element_boolean(attrs, std::forward<Args>(args)...)
{ } };

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

@@ -22,6 +22,14 @@ public: class HEMPLATE_EXPORT xml : public element {
static auto attrs(std::string_view version, std::string_view encoding)
{
return attribute_list {
{"version", version},
{"encoding", encoding},
};
}
public: static constexpr const auto def_version = "1.0"; static constexpr const auto def_encoding = "UTF-8";

@@ -30,7 +38,7 @@ public: std::string_view version = def_version, std::string_view encoding = def_encoding )
: element(std::format("<? {}?>", attribute_list {version, encoding}))
: element(std::format("<? xml {}?>", attrs(version, encoding)))
{ } };

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

@@ -11,79 +11,51 @@ std::string format_time_now(); class HEMPLATE_EXPORT rss : public element_boolean<"rss"> {
static auto attributes(std::string_view version, std::string_view xmlns)
static auto def_attrs()
{ return attribute_list {
{"version", version},
{"xmlns", xmlns},
{"version", "2.0"},
{"xmlns", "http://www.w3.org/2005/Atom"},
}; } public:
static constexpr const auto def_version = "2.0";
static constexpr const auto def_xmlns = "http://www.w3.org/2005/Atom";
template<typename... Args>
explicit rss(std::string_view version, std::string_view xmlns, Args&&... args)
: element_boolean(attributes(version, xmlns), std::forward<Args>(args)...)
requires(!std::same_as<attribute_list, std::remove_cvref_t<Args>> && ...)
explicit rss(Args&&... args)
: element_boolean(def_attrs(), std::forward<Args>(args)...)
{ } template<typename... Args>
explicit rss(Args&&... args)
: element_boolean(
attributes(def_version, def_xmlns), std::forward<Args>(args)...
)
explicit rss(const attribute_list& attrs, Args&&... args)
: element_boolean(attrs, std::forward<Args>(args)...)
{ } }; class HEMPLATE_EXPORT atomLink // NOLINT(*naming*)
: public element_boolean<"atom:link">
: public element_atomic<"atom:link">
{
static auto attributes(
const attribute_list& list, std::string_view rel, std::string_view type
)
static auto def_attrs(std::string_view href)
{
return attribute_list {list, {{"rel", rel}, {"type", type}}};
return attribute_list {
{"rel", "self"},
{"type", "application/rss+xml"},
{"href", href},
};
} public:
static constexpr const auto def_rel = "self";
static constexpr const auto def_type = "application/rss+xml";
template<typename... Args>
explicit atomLink(
std::string_view rel,
std::string_view type,
const attribute_list& attrs,
Args&&... args
)
: element_boolean(
attributes(attrs, rel, type), std::forward<Args>(args)...
)
{
}
template<typename... Args>
explicit atomLink(std::string_view rel, std::string_view type, Args&&... args)
: element_boolean(
attributes({}, rel, type), {}, std::forward<Args>(args)...
)
{
}
template<typename... Args>
explicit atomLink(const attribute_list& attrs, Args&&... args)
: element_boolean(
attributes(attrs, def_rel, def_type), std::forward<Args>(args)...
)
explicit atomLink(std::string_view href)
: element_atomic(def_attrs(href))
{ } template<typename... Args>
explicit atomLink(Args&&... args)
: element_boolean(std::forward<Args>(args)...)
explicit atomLink(const attribute_list& attrs)
: element_atomic(attrs)
{ } };

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

@@ -8,26 +8,24 @@ namespace hemplate::sitemap class HEMPLATE_EXPORT urlset : public element_boolean<"urlset"> {
static auto attributes(std::string_view xmlns)
static auto def_attrs()
{ return attribute_list {
{"xmlns", xmlns},
{"xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9"},
}; } public:
static constexpr const auto def_xmlns =
"http://www.sitemaps.org/schemas/sitemap/0.9";
template<typename... Args>
explicit urlset(std::string_view xmlns, Args&&... args)
: element_boolean(attributes(xmlns), std::forward<Args>(args)...)
explicit urlset(Args&&... args)
requires(!std::same_as<attribute_list, std::remove_cvref_t<Args>> && ...)
: element_boolean(def_attrs(), std::forward<Args>(args)...)
{ } template<typename... Args>
explicit urlset(Args&&... args)
: element_boolean(attributes(def_xmlns), std::forward<Args>(args)...)
explicit urlset(const attribute_list& attrs, Args&&... args)
: element_boolean(attrs, std::forward<Args>(args)...)
{ } };

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

@@ -21,9 +21,14 @@ function(add_test NAME) catch_discover_tests("${NAME}") endfunction()
add_test(attribute)
add_test(attribute_list)
add_test(element)
add_test(attribute_test)
add_test(attribute_list_test)
add_test(element_test)
add_test(classes_test)
add_test(html_test)
add_test(atom_test)
add_test(rss_test)
add_test(sitemap_test)
# ---- End-of-file commands ----

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

@@ -0,0 +1,25 @@
#include "hemplate/atom.hpp"
#include <catch2/catch_test_macros.hpp>
using namespace hemplate; // NOLINT
TEST_CASE("feed", "[atom/feed]")
{
SECTION("default")
{
const atom::feed feed;
REQUIRE(
std::string(feed)
== "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n</feed>\n"
);
}
SECTION("custom")
{
const atom::feed feed {{{"hello", "world"}}};
REQUIRE(std::string(feed) == "<feed hello=\"world\">\n</feed>\n");
}
}

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

@@ -1,59 +0,0 @@
#include "hemplate/attribute.hpp"
#include <catch2/catch_test_macros.hpp>
TEST_CASE("constructor", "[attribute]")
{
SECTION("name")
{
const hemplate::attribute attr {"class"};
REQUIRE(attr.name() == "class");
REQUIRE(attr.empty());
REQUIRE(std::string(attr) == "class");
}
SECTION("name, value")
{
const hemplate::attribute attr {"class", "test"};
REQUIRE(attr.name() == "class");
REQUIRE(attr.value() == "test");
REQUIRE(!attr.empty());
REQUIRE(std::string(attr) == R"(class="test")");
}
}
TEST_CASE("append", "[attribute]")
{
hemplate::attribute attr {"class"};
SECTION("empty")
{
attr.append(" ", "");
REQUIRE(attr.name() == "class");
REQUIRE(attr.empty());
REQUIRE(std::string(attr) == R"(class)");
}
SECTION("first")
{
attr.append(" ", "first");
REQUIRE(attr.name() == "class");
REQUIRE(attr.value() == "first");
REQUIRE(!attr.empty());
REQUIRE(std::string(attr) == R"(class="first")");
SECTION("second")
{
attr.append(" ", "second");
REQUIRE(attr.name() == "class");
REQUIRE(attr.value() == "first second");
REQUIRE(!attr.empty());
REQUIRE(std::string(attr) == R"(class="first second")");
}
}
}

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

@@ -1,92 +0,0 @@
#include "hemplate/attribute.hpp"
#include <catch2/catch_test_macros.hpp>
// NOLINTBEGIN(*readability-container-size-empty*)
TEST_CASE("set class", "[attribute_list]")
{
hemplate::attribute_list attrs = hemplate::attribute {"class", "first"};
REQUIRE(std::string(attrs) == R"(class="first")");
SECTION("second")
{
attrs.set({"class", "second"});
REQUIRE(std::string(attrs) == R"(class="first second")");
}
SECTION("random")
{
attrs.set({"test"});
REQUIRE(std::string(attrs) == R"(class="first" test)");
}
}
TEST_CASE("set style", "[attribute_list]")
{
hemplate::attribute_list attrs = hemplate::attribute {"style", "first"};
REQUIRE(std::string(attrs) == R"(style="first")");
SECTION("second")
{
attrs.set({"style", "second"});
REQUIRE(std::string(attrs) == R"(style="first; second")");
}
SECTION("random")
{
attrs.set({"test"});
REQUIRE(std::string(attrs) == R"(style="first" test)");
}
}
TEST_CASE("set list", "[attribute_list]")
{
hemplate::attribute_list attrs {
{"class", "first"},
{"style", "first"},
{"test_first"},
{"class", "second"},
{"style", "second"},
{"test_second"},
};
REQUIRE(
std::string(attrs)
== R"(class="first second" style="first; second" test_first test_second)"
);
SECTION("set")
{
attrs.set({
{"class", "third"},
{"style", "third"},
{"test_third"},
});
REQUIRE(
std::string(attrs)
== R"(class="first second third" style="first; second; third" test_first test_second test_third)"
);
}
}
TEST_CASE("add", "[attribute_list]")
{
using namespace std::literals::string_view_literals;
const auto tmp = hemplate::attribute_list {{"class", "first"}};
const auto attrs = hemplate::attribute_list {
tmp, {{"class"sv, "second"sv}, {"class"sv, "third"sv}}
};
REQUIRE(std::string(attrs) == R"(class="first second third")");
}
// NOLINTEND(*readability-container-size-empty*)

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

@@ -0,0 +1,92 @@
#include "hemplate/attribute.hpp"
#include <catch2/catch_test_macros.hpp>
// NOLINTBEGIN(*readability-container-size-empty*)
TEST_CASE("set class", "[attribute_list]")
{
hemplate::attribute_list attrs = hemplate::attribute {"class", "first"};
REQUIRE(std::string(attrs) == R"(class="first")");
SECTION("second")
{
attrs.set({"class", "second"});
REQUIRE(std::string(attrs) == R"(class="first second")");
}
SECTION("random")
{
attrs.set({"test"});
REQUIRE(std::string(attrs) == R"(class="first" test)");
}
}
TEST_CASE("set style", "[attribute_list]")
{
hemplate::attribute_list attrs = hemplate::attribute {"style", "first"};
REQUIRE(std::string(attrs) == R"(style="first")");
SECTION("second")
{
attrs.set({"style", "second"});
REQUIRE(std::string(attrs) == R"(style="first; second")");
}
SECTION("random")
{
attrs.set({"test"});
REQUIRE(std::string(attrs) == R"(style="first" test)");
}
}
TEST_CASE("set list", "[attribute_list]")
{
hemplate::attribute_list attrs {
{"class", "first"},
{"style", "first"},
{"test_first"},
{"class", "second"},
{"style", "second"},
{"test_second"},
};
REQUIRE(
std::string(attrs)
== R"(class="first second" style="first; second" test_first test_second)"
);
SECTION("set")
{
attrs.set({
{"class", "third"},
{"style", "third"},
{"test_third"},
});
REQUIRE(
std::string(attrs)
== R"(class="first second third" style="first; second; third" test_first test_second test_third)"
);
}
}
TEST_CASE("add", "[attribute_list]")
{
using namespace std::literals::string_view_literals;
const auto tmp = hemplate::attribute_list {{"class", "first"}};
const auto attrs = hemplate::attribute_list {
tmp, {{"class"sv, "second"sv}, {"class"sv, "third"sv}}
};
REQUIRE(std::string(attrs) == R"(class="first second third")");
}
// NOLINTEND(*readability-container-size-empty*)

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

@@ -0,0 +1,59 @@
#include "hemplate/attribute.hpp"
#include <catch2/catch_test_macros.hpp>
TEST_CASE("constructor", "[attribute]")
{
SECTION("name")
{
const hemplate::attribute attr {"class"};
REQUIRE(attr.name() == "class");
REQUIRE(attr.empty());
REQUIRE(std::string(attr) == "class");
}
SECTION("name, value")
{
const hemplate::attribute attr {"class", "test"};
REQUIRE(attr.name() == "class");
REQUIRE(attr.value() == "test");
REQUIRE(!attr.empty());
REQUIRE(std::string(attr) == R"(class="test")");
}
}
TEST_CASE("append", "[attribute]")
{
hemplate::attribute attr {"class"};
SECTION("empty")
{
attr.append(" ", "");
REQUIRE(attr.name() == "class");
REQUIRE(attr.empty());
REQUIRE(std::string(attr) == R"(class)");
}
SECTION("first")
{
attr.append(" ", "first");
REQUIRE(attr.name() == "class");
REQUIRE(attr.value() == "first");
REQUIRE(!attr.empty());
REQUIRE(std::string(attr) == R"(class="first")");
SECTION("second")
{
attr.append(" ", "second");
REQUIRE(attr.name() == "class");
REQUIRE(attr.value() == "first second");
REQUIRE(!attr.empty());
REQUIRE(std::string(attr) == R"(class="first second")");
}
}
}

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

@@ -0,0 +1,58 @@
#include "hemplate/classes.hpp"
#include <catch2/catch_test_macros.hpp>
TEST_CASE("comment", "[classes/comment]")
{
const hemplate::comment comment {"hello world"};
REQUIRE(std::string(comment) == "<-- hello world -->\n");
}
TEST_CASE("xml", "[classes/xml]")
{
SECTION("default")
{
const hemplate::xml xml;
REQUIRE(
std::string(xml) == "<? xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
);
}
SECTION("version")
{
const hemplate::xml xml {"ver"};
REQUIRE(
std::string(xml) == "<? xml version=\"ver\" encoding=\"UTF-8\"?>\n"
);
}
SECTION("version encoding")
{
const hemplate::xml xml {"ver", "utf"};
REQUIRE(std::string(xml) == "<? xml version=\"ver\" encoding=\"utf\"?>\n");
}
}
TEST_CASE("transform", "[classes/transform]")
{
using tag = hemplate::element_boolean<"t">;
using child = hemplate::element_boolean<"c">;
const std::vector<std::string> vec = {"1", "2"};
const auto t = tag {hemplate::transform(
vec,
[](const auto& e)
{
return child {e};
}
)};
REQUIRE(
std::string(t)
== "<t>\n <c>\n 1\n </c>\n <c>\n 2\n </c>\n</t>\n"
);
}

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

@@ -1,158 +0,0 @@
#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");
}
}

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

@@ -0,0 +1,166 @@
#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"
);
}
SECTION("range")
{
const std::vector<std::string> vec = {"hello", "world"};
const auto t = tag {vec};
REQUIRE(std::string(t) == "<tag>\n hello\n world\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");
}
}

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

@@ -0,0 +1,12 @@
#include "hemplate/html.hpp"
#include <catch2/catch_test_macros.hpp>
using namespace hemplate; // NOLINT
TEST_CASE("doctype", "[html/doctype]")
{
const html::doctype doctype;
REQUIRE(std::string(doctype) == "<!DOCTYPE html>\n");
}

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

@@ -0,0 +1,42 @@
#include "hemplate/rss.hpp"
#include <catch2/catch_test_macros.hpp>
using namespace hemplate; // NOLINT
TEST_CASE("rss", "[rss/rss]")
{
SECTION("default")
{
const rss::rss rss;
REQUIRE(std::string(rss) == "<rss version=\"2.0\" xmlns=\"http://www.w3.org/2005/Atom\">\n</rss>\n");
}
SECTION("random")
{
const rss::rss rss {{{"hello", "world"}}};
REQUIRE(std::string(rss) == "<rss hello=\"world\">\n</rss>\n");
}
}
TEST_CASE("atomLink", "[rss/atomLink]")
{
SECTION("href")
{
const rss::atomLink link {"hi"};
REQUIRE(
std::string(link)
== "<atom:link rel=\"self\" type=\"application/rss+xml\" href=\"hi\" />\n"
);
}
SECTION("random")
{
const rss::atomLink link {{{"hello", "world"}}};
REQUIRE(std::string(link) == "<atom:link hello=\"world\" />\n");
}
}

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

@@ -0,0 +1,22 @@
#include "hemplate/sitemap.hpp"
#include <catch2/catch_test_macros.hpp>
using namespace hemplate; // NOLINT
TEST_CASE("urlset", "[sitemap/urlset]")
{
SECTION("default")
{
const sitemap::urlset urlset;
REQUIRE(std::string(urlset) == "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n</urlset>\n");
}
SECTION("random")
{
const sitemap::urlset urlset {{{"hello", "world"}}};
REQUIRE(std::string(urlset) == "<urlset hello=\"world\">\n</urlset>\n");
}
}