srctree

Robin Linden parent 4b6692a1 381814fc
css/test: Migrate to etest2

inlinesplit
css/parser_test.cpp added: 445, removed: 446, total 0
@@ -9,7 +9,7 @@
#include "css/property_id.h"
#include "css/rule.h"
 
#include "etest/etest.h"
#include "etest/etest2.h"
 
#include <fmt/format.h>
 
@@ -25,10 +25,6 @@
#include <vector>
 
using namespace std::literals;
using etest::expect;
using etest::expect_eq;
using etest::require;
using etest::require_eq;
 
namespace {
 
@@ -78,19 +74,21 @@ bool check_initial_font_values(std::map<css::PropertyId, std::string> const &dec
}
 
template<class KeyT, class ValueT>
ValueT get_and_erase(
std::map<KeyT, ValueT> &map, KeyT key, std::source_location const &loc = std::source_location::current()) {
require(map.contains(key), {}, loc);
ValueT get_and_erase(etest::IActions &a,
std::map<KeyT, ValueT> &map,
KeyT key,
std::source_location const &loc = std::source_location::current()) {
a.require(map.contains(key), {}, loc);
ValueT value = map.at(key);
map.erase(key);
return value;
}
 
void text_decoration_tests() {
etest::test("parser: text-decoration, line", [] {
void text_decoration_tests(etest::Suite &s) {
s.add_test("parser: text-decoration, line", [](etest::IActions &a) {
auto rules = css::parse("p { text-decoration: underline; }").rules;
auto const &p = rules.at(0);
expect_eq(p.declarations,
a.expect_eq(p.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::TextDecorationColor, "currentcolor"},
{css::PropertyId::TextDecorationLine, "underline"},
@@ -98,10 +96,10 @@ void text_decoration_tests() {
});
});
 
etest::test("parser: text-decoration, line & style", [] {
s.add_test("parser: text-decoration, line & style", [](etest::IActions &a) {
auto rules = css::parse("p { text-decoration: underline dotted; }").rules;
auto const &p = rules.at(0);
expect_eq(p.declarations,
a.expect_eq(p.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::TextDecorationColor, "currentcolor"},
{css::PropertyId::TextDecorationLine, "underline"},
@@ -109,36 +107,36 @@ void text_decoration_tests() {
});
});
 
etest::test("parser: text-decoration, duplicate line", [] {
s.add_test("parser: text-decoration, duplicate line", [](etest::IActions &a) {
auto rules = css::parse("p { text-decoration: underline overline; }").rules;
auto const &p = rules.at(0);
expect_eq(p.declarations, std::map<css::PropertyId, std::string>{});
a.expect_eq(p.declarations, std::map<css::PropertyId, std::string>{});
});
 
etest::test("parser: text-decoration, duplicate style", [] {
s.add_test("parser: text-decoration, duplicate style", [](etest::IActions &a) {
auto rules = css::parse("p { text-decoration: dotted dotted; }").rules;
auto const &p = rules.at(0);
expect_eq(p.declarations, std::map<css::PropertyId, std::string>{});
a.expect_eq(p.declarations, std::map<css::PropertyId, std::string>{});
});
 
// This will fail once we support text-decoration-thickness.
etest::test("parser: text-decoration, line & thickness", [] {
s.add_test("parser: text-decoration, line & thickness", [](etest::IActions &a) {
auto rules = css::parse("p { text-decoration: underline 3px; }").rules;
auto const &p = rules.at(0);
expect_eq(p.declarations, std::map<css::PropertyId, std::string>{});
a.expect_eq(p.declarations, std::map<css::PropertyId, std::string>{});
});
 
// This will fail once we support text-decoration-color.
etest::test("parser: text-decoration, line & color", [] {
s.add_test("parser: text-decoration, line & color", [](etest::IActions &a) {
auto rules = css::parse("p { text-decoration: overline blue; }").rules;
auto const &p = rules.at(0);
expect_eq(p.declarations, std::map<css::PropertyId, std::string>{});
a.expect_eq(p.declarations, std::map<css::PropertyId, std::string>{});
});
 
etest::test("parser: text-decoration, global value", [] {
s.add_test("parser: text-decoration, global value", [](etest::IActions &a) {
auto rules = css::parse("p { text-decoration: inherit; }").rules;
auto const &p = rules.at(0);
expect_eq(p.declarations,
a.expect_eq(p.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::TextDecorationColor, "inherit"},
{css::PropertyId::TextDecorationLine, "inherit"},
@@ -147,11 +145,11 @@ void text_decoration_tests() {
});
}
 
void outline_tests() {
etest::test("parser: outline shorthand, all values", [] {
void outline_tests(etest::Suite &s) {
s.add_test("parser: outline shorthand, all values", [](etest::IActions &a) {
auto rules = css::parse("p { outline: 5px black solid; }").rules;
auto const &p = rules.at(0);
expect_eq(p.declarations,
a.expect_eq(p.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::OutlineColor, "black"s},
{css::PropertyId::OutlineStyle, "solid"s},
@@ -159,10 +157,10 @@ void outline_tests() {
});
});
 
etest::test("parser: outline shorthand, color+style", [] {
s.add_test("parser: outline shorthand, color+style", [](etest::IActions &a) {
auto rules = css::parse("p { outline: #123 dotted; }").rules;
auto const &p = rules.at(0);
expect_eq(p.declarations,
a.expect_eq(p.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::OutlineColor, "#123"s},
{css::PropertyId::OutlineStyle, "dotted"s},
@@ -170,10 +168,10 @@ void outline_tests() {
});
});
 
etest::test("parser: outline shorthand, width+style", [] {
s.add_test("parser: outline shorthand, width+style", [](etest::IActions &a) {
auto rules = css::parse("p { outline: ridge 30em; }").rules;
auto const &p = rules.at(0);
expect_eq(p.declarations,
a.expect_eq(p.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::OutlineColor, "currentcolor"s},
{css::PropertyId::OutlineStyle, "ridge"s},
@@ -181,10 +179,10 @@ void outline_tests() {
});
});
 
etest::test("parser: outline shorthand, width", [] {
s.add_test("parser: outline shorthand, width", [](etest::IActions &a) {
auto rules = css::parse("p { outline: thin; }").rules;
auto const &p = rules.at(0);
expect_eq(p.declarations,
a.expect_eq(p.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::OutlineColor, "currentcolor"s},
{css::PropertyId::OutlineStyle, "none"s},
@@ -192,10 +190,10 @@ void outline_tests() {
});
});
 
etest::test("parser: outline shorthand, width, first character a dot", [] {
s.add_test("parser: outline shorthand, width, first character a dot", [](etest::IActions &a) {
auto rules = css::parse("p { outline: .3em; }").rules;
auto const &p = rules.at(0);
expect_eq(p.declarations,
a.expect_eq(p.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::OutlineColor, "currentcolor"s},
{css::PropertyId::OutlineStyle, "none"s},
@@ -203,161 +201,162 @@ void outline_tests() {
});
});
 
etest::test("parser: outline shorthand, too many values", [] {
s.add_test("parser: outline shorthand, too many values", [](etest::IActions &a) {
auto rules = css::parse("p { outline: outset #123 none solid; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &p = rules[0];
expect_eq(p.declarations, std::map<css::PropertyId, std::string>{});
a.expect_eq(p.declarations, std::map<css::PropertyId, std::string>{});
});
}
 
} // namespace
 
int main() {
text_decoration_tests();
outline_tests();
etest::Suite s{};
text_decoration_tests(s);
outline_tests(s);
 
etest::test("parser: simple rule", [] {
s.add_test("parser: simple rule", [](etest::IActions &a) {
auto rules = css::parse("body { width: 50px; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.selectors == std::vector{"body"s});
expect(body.declarations.size() == 1);
expect(body.declarations.at(css::PropertyId::Width) == "50px"s);
a.expect(body.selectors == std::vector{"body"s});
a.expect(body.declarations.size() == 1);
a.expect(body.declarations.at(css::PropertyId::Width) == "50px"s);
});
 
etest::test("parser: important rule", [] {
s.add_test("parser: important rule", [](etest::IActions &a) {
auto rules = css::parse("body { width: 50px !important; }"sv).rules;
require_eq(rules.size(), std::size_t{1});
a.require_eq(rules.size(), std::size_t{1});
 
auto body = rules[0];
expect_eq(body.selectors, std::vector{"body"s});
expect(body.declarations.empty());
expect_eq(body.important_declarations.size(), std::size_t{1});
expect_eq(body.important_declarations.at(css::PropertyId::Width), "50px"s);
a.expect_eq(body.selectors, std::vector{"body"s});
a.expect(body.declarations.empty());
a.expect_eq(body.important_declarations.size(), std::size_t{1});
a.expect_eq(body.important_declarations.at(css::PropertyId::Width), "50px"s);
});
 
etest::test("selector with spaces", [] {
s.add_test("selector with spaces", [](etest::IActions &a) {
auto rules = css::parse("p a { color: green; }").rules;
expect_eq(rules,
a.expect_eq(rules,
std::vector<css::Rule>{{
.selectors{{"p a"}},
.declarations{{css::PropertyId::Color, "green"}},
}});
});
 
etest::test("property value with spaces", [] {
s.add_test("property value with spaces", [](etest::IActions &a) {
auto rules = css::parse("p { color: green ; }").rules;
expect_eq(rules,
a.expect_eq(rules,
std::vector<css::Rule>{{
.selectors{{"p"}},
.declarations{{css::PropertyId::Color, "green"}},
}});
});
 
etest::test("parser: minified", [] {
s.add_test("parser: minified", [](etest::IActions &a) {
auto rules = css::parse("body{width:50px;font-family:inherit}head,p{display:none}"sv).rules;
require(rules.size() == 2);
a.require(rules.size() == 2);
 
auto first = rules[0];
expect(first.selectors == std::vector{"body"s});
expect(first.declarations.size() == 2);
expect(first.declarations.at(css::PropertyId::Width) == "50px"s);
expect(first.declarations.at(css::PropertyId::FontFamily) == "inherit"s);
a.expect(first.selectors == std::vector{"body"s});
a.expect(first.declarations.size() == 2);
a.expect(first.declarations.at(css::PropertyId::Width) == "50px"s);
a.expect(first.declarations.at(css::PropertyId::FontFamily) == "inherit"s);
 
auto second = rules[1];
expect(second.selectors == std::vector{"head"s, "p"s});
expect(second.declarations.size() == 1);
expect(second.declarations.at(css::PropertyId::Display) == "none"s);
a.expect(second.selectors == std::vector{"head"s, "p"s});
a.expect(second.declarations.size() == 1);
a.expect(second.declarations.at(css::PropertyId::Display) == "none"s);
});
 
etest::test("parser: multiple rules", [] {
s.add_test("parser: multiple rules", [](etest::IActions &a) {
auto rules = css::parse("body { width: 50px; }\np { font-size: 8em; }"sv).rules;
require(rules.size() == 2);
a.require(rules.size() == 2);
 
auto body = rules[0];
expect(body.selectors == std::vector{"body"s});
expect(body.declarations.size() == 1);
expect(body.declarations.at(css::PropertyId::Width) == "50px"s);
a.expect(body.selectors == std::vector{"body"s});
a.expect(body.declarations.size() == 1);
a.expect(body.declarations.at(css::PropertyId::Width) == "50px"s);
 
auto p = rules[1];
expect(p.selectors == std::vector{"p"s});
expect(p.declarations.size() == 1);
expect(p.declarations.at(css::PropertyId::FontSize) == "8em"s);
a.expect(p.selectors == std::vector{"p"s});
a.expect(p.declarations.size() == 1);
a.expect(p.declarations.at(css::PropertyId::FontSize) == "8em"s);
});
 
etest::test("parser: multiple selectors", [] {
s.add_test("parser: multiple selectors", [](etest::IActions &a) {
auto rules = css::parse("body, p { width: 50px; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.selectors == std::vector{"body"s, "p"s});
expect(body.declarations.size() == 1);
expect(body.declarations.at(css::PropertyId::Width) == "50px"s);
a.expect(body.selectors == std::vector{"body"s, "p"s});
a.expect(body.declarations.size() == 1);
a.expect(body.declarations.at(css::PropertyId::Width) == "50px"s);
});
 
etest::test("parser: multiple declarations", [] {
s.add_test("parser: multiple declarations", [](etest::IActions &a) {
auto rules = css::parse("body { width: 50px; height: 300px; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.selectors == std::vector{"body"s});
expect(body.declarations.size() == 2);
expect(body.declarations.at(css::PropertyId::Width) == "50px"s);
expect(body.declarations.at(css::PropertyId::Height) == "300px"s);
a.expect(body.selectors == std::vector{"body"s});
a.expect(body.declarations.size() == 2);
a.expect(body.declarations.at(css::PropertyId::Width) == "50px"s);
a.expect(body.declarations.at(css::PropertyId::Height) == "300px"s);
});
 
etest::test("parser: class", [] {
s.add_test("parser: class", [](etest::IActions &a) {
auto rules = css::parse(".cls { width: 50px; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.selectors == std::vector{".cls"s});
expect(body.declarations.size() == 1);
expect(body.declarations.at(css::PropertyId::Width) == "50px"s);
a.expect(body.selectors == std::vector{".cls"s});
a.expect(body.declarations.size() == 1);
a.expect(body.declarations.at(css::PropertyId::Width) == "50px"s);
});
 
etest::test("parser: id", [] {
s.add_test("parser: id", [](etest::IActions &a) {
auto rules = css::parse("#cls { width: 50px; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.selectors == std::vector{"#cls"s});
expect(body.declarations.size() == 1);
expect(body.declarations.at(css::PropertyId::Width) == "50px"s);
a.expect(body.selectors == std::vector{"#cls"s});
a.expect(body.declarations.size() == 1);
a.expect(body.declarations.at(css::PropertyId::Width) == "50px"s);
});
 
etest::test("parser: empty rule", [] {
s.add_test("parser: empty rule", [](etest::IActions &a) {
auto rules = css::parse("body {}"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.selectors == std::vector{"body"s});
expect(body.declarations.empty());
a.expect(body.selectors == std::vector{"body"s});
a.expect(body.declarations.empty());
});
 
etest::test("parser: no rules", [] {
s.add_test("parser: no rules", [](etest::IActions &a) {
auto rules = css::parse(""sv).rules;
expect(rules.empty());
a.expect(rules.empty());
});
 
etest::test("parser: top-level comments", [] {
s.add_test("parser: top-level comments", [](etest::IActions &a) {
auto rules = css::parse("body { width: 50px; }/* comment. */ p { font-size: 8em; } /* comment. */"sv).rules;
require(rules.size() == 2);
a.require(rules.size() == 2);
 
auto body = rules[0];
expect(body.selectors == std::vector{"body"s});
expect(body.declarations.size() == 1);
expect(body.declarations.at(css::PropertyId::Width) == "50px"s);
a.expect(body.selectors == std::vector{"body"s});
a.expect(body.declarations.size() == 1);
a.expect(body.declarations.at(css::PropertyId::Width) == "50px"s);
 
auto p = rules[1];
expect(p.selectors == std::vector{"p"s});
expect(p.declarations.size() == 1);
expect(p.declarations.at(css::PropertyId::FontSize) == "8em"s);
a.expect(p.selectors == std::vector{"p"s});
a.expect(p.declarations.size() == 1);
a.expect(p.declarations.at(css::PropertyId::FontSize) == "8em"s);
});
 
etest::test("parser: comments almost everywhere", [] {
s.add_test("parser: comments almost everywhere", [](etest::IActions &a) {
// body { width: 50px; } p { padding: 8em 4em; } with comments added everywhere currently supported.
auto rules = css::parse(R"(/**/body {/**/width:50px;/**/}/*
*/p {/**/padding:/**/8em 4em;/**//**/}/**/)"sv)
@@ -365,23 +364,23 @@ int main() {
// TODO(robinlinden): Support comments in more places.
// auto rules = css::parse(R"(/**/body/**/{/**/width/**/:/**/50px/**/;/**/}/*
// */p/**/{/**/padding/**/:/**/8em/**/4em/**/;/**//**/}/**/)"sv).rules;
require_eq(rules.size(), 2UL);
a.require_eq(rules.size(), 2UL);
 
auto body = rules[0];
expect_eq(body.selectors, std::vector{"body"s});
expect_eq(body.declarations.size(), 1UL);
expect_eq(body.declarations.at(css::PropertyId::Width), "50px"s);
a.expect_eq(body.selectors, std::vector{"body"s});
a.expect_eq(body.declarations.size(), 1UL);
a.expect_eq(body.declarations.at(css::PropertyId::Width), "50px"s);
 
auto p = rules[1];
expect_eq(p.selectors, std::vector{"p"s});
expect_eq(p.declarations.size(), 4UL);
expect_eq(p.declarations.at(css::PropertyId::PaddingTop), "8em"s);
expect_eq(p.declarations.at(css::PropertyId::PaddingBottom), "8em"s);
expect_eq(p.declarations.at(css::PropertyId::PaddingLeft), "4em"s);
expect_eq(p.declarations.at(css::PropertyId::PaddingRight), "4em"s);
a.expect_eq(p.selectors, std::vector{"p"s});
a.expect_eq(p.declarations.size(), 4UL);
a.expect_eq(p.declarations.at(css::PropertyId::PaddingTop), "8em"s);
a.expect_eq(p.declarations.at(css::PropertyId::PaddingBottom), "8em"s);
a.expect_eq(p.declarations.at(css::PropertyId::PaddingLeft), "4em"s);
a.expect_eq(p.declarations.at(css::PropertyId::PaddingRight), "4em"s);
});
 
etest::test("parser: media query", [] {
s.add_test("parser: media query", [](etest::IActions &a) {
auto rules = css::parse(R"(
@media (min-width: 900px) {
article { width: 50px; }
@@ -389,214 +388,214 @@ int main() {
}
a { background-color: indigo; })"sv)
.rules;
require(rules.size() == 3);
a.require(rules.size() == 3);
 
auto article = rules[0];
expect(article.selectors == std::vector{"article"s});
require(article.declarations.contains(css::PropertyId::Width));
expect(article.declarations.at(css::PropertyId::Width) == "50px"s);
expect_eq(article.media_query, css::MediaQuery{css::MediaQuery::Width{.min = 900}});
a.expect(article.selectors == std::vector{"article"s});
a.require(article.declarations.contains(css::PropertyId::Width));
a.expect(article.declarations.at(css::PropertyId::Width) == "50px"s);
a.expect_eq(article.media_query, css::MediaQuery{css::MediaQuery::Width{.min = 900}});
 
auto p = rules[1];
expect(p.selectors == std::vector{"p"s});
require(p.declarations.contains(css::PropertyId::FontSize));
expect(p.declarations.at(css::PropertyId::FontSize) == "9em"s);
expect_eq(p.media_query, css::MediaQuery{css::MediaQuery::Width{.min = 900}});
a.expect(p.selectors == std::vector{"p"s});
a.require(p.declarations.contains(css::PropertyId::FontSize));
a.expect(p.declarations.at(css::PropertyId::FontSize) == "9em"s);
a.expect_eq(p.media_query, css::MediaQuery{css::MediaQuery::Width{.min = 900}});
 
auto a = rules[2];
expect(a.selectors == std::vector{"a"s});
require(a.declarations.contains(css::PropertyId::BackgroundColor));
expect(a.declarations.at(css::PropertyId::BackgroundColor) == "indigo"s);
expect(!a.media_query.has_value());
auto a_ele = rules[2];
a.expect(a_ele.selectors == std::vector{"a"s});
a.require(a_ele.declarations.contains(css::PropertyId::BackgroundColor));
a.expect(a_ele.declarations.at(css::PropertyId::BackgroundColor) == "indigo"s);
a.expect(!a_ele.media_query.has_value());
});
 
etest::test("parser: minified media query", [] {
s.add_test("parser: minified media query", [](etest::IActions &a) {
auto rules = css::parse("@media(max-width:300px){p{font-size:10px;}}").rules;
require_eq(rules.size(), std::size_t{1});
a.require_eq(rules.size(), std::size_t{1});
auto const &rule = rules[0];
expect_eq(rule.media_query, css::MediaQuery{css::MediaQuery::Width{.max = 300}});
expect_eq(rule.selectors, std::vector{"p"s});
require_eq(rule.declarations.size(), std::size_t{1});
expect_eq(rule.declarations.at(css::PropertyId::FontSize), "10px");
a.expect_eq(rule.media_query, css::MediaQuery{css::MediaQuery::Width{.max = 300}});
a.expect_eq(rule.selectors, std::vector{"p"s});
a.require_eq(rule.declarations.size(), std::size_t{1});
a.expect_eq(rule.declarations.at(css::PropertyId::FontSize), "10px");
});
 
etest::test("parser: bad media query", [] {
s.add_test("parser: bad media query", [](etest::IActions &a) {
auto rules = css::parse("@media (rip: 0) { p { font-size: 10px; } }").rules;
auto const &rule = rules.at(0);
expect_eq(rule.media_query, css::MediaQuery{css::MediaQuery::False{}});
expect_eq(rule.selectors, std::vector{"p"s});
require_eq(rule.declarations.size(), std::size_t{1});
expect_eq(rule.declarations.at(css::PropertyId::FontSize), "10px");
a.expect_eq(rule.media_query, css::MediaQuery{css::MediaQuery::False{}});
a.expect_eq(rule.selectors, std::vector{"p"s});
a.require_eq(rule.declarations.size(), std::size_t{1});
a.expect_eq(rule.declarations.at(css::PropertyId::FontSize), "10px");
});
 
etest::test("parser: 2 media queries in a row", [] {
s.add_test("parser: 2 media queries in a row", [](etest::IActions &a) {
auto rules = css::parse(
"@media (max-width: 1px) { p { font-size: 1em; } } @media (min-width: 2px) { a { color: blue; } }")
.rules;
require_eq(rules.size(), std::size_t{2});
expect_eq(rules[0],
a.require_eq(rules.size(), std::size_t{2});
a.expect_eq(rules[0],
css::Rule{.selectors{{"p"}},
.declarations{{css::PropertyId::FontSize, "1em"}},
.media_query{css::MediaQuery{css::MediaQuery::Width{.max = 1}}}});
expect_eq(rules[1],
a.expect_eq(rules[1],
css::Rule{.selectors{{"a"}},
.declarations{{css::PropertyId::Color, "blue"}},
.media_query{css::MediaQuery{css::MediaQuery::Width{.min = 2}}}});
});
 
auto box_shorthand_one_value = [](std::string property, std::string value, std::string post_fix = "") {
return [=]() mutable {
return [=](etest::IActions &a) mutable {
auto rules = css::parse(fmt::format("p {{ {}: {}; }}"sv, property, value)).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
if (property == "border-style" || property == "border-color" || property == "border-width") {
property = "border";
}
 
auto body = rules[0];
expect(body.declarations.size() == 4);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-top{}", property, post_fix)))
a.expect(body.declarations.size() == 4);
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-top{}", property, post_fix)))
== value);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-bottom{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-bottom{}", property, post_fix)))
== value);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-left{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-left{}", property, post_fix)))
== value);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-right{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-right{}", property, post_fix)))
== value);
};
};
 
{
std::string size_value{"10px"};
etest::test("parser: shorthand padding, one value", box_shorthand_one_value("padding", size_value));
etest::test("parser: shorthand margin, one value", box_shorthand_one_value("margin", size_value));
s.add_test("parser: shorthand padding, one value", box_shorthand_one_value("padding", size_value));
s.add_test("parser: shorthand margin, one value", box_shorthand_one_value("margin", size_value));
 
std::string border_style{"dashed"};
etest::test("parser: shorthand border-style, one value",
s.add_test("parser: shorthand border-style, one value",
box_shorthand_one_value("border-style", border_style, "-style"));
 
etest::test(
s.add_test(
"parser: shorthand border-color, one value", box_shorthand_one_value("border-color", "red", "-color"));
 
etest::test(
s.add_test(
"parser: shorthand border-width, one value", box_shorthand_one_value("border-width", "10px", "-width"));
}
 
auto box_shorthand_two_values = [](std::string property,
std::array<std::string, 2> values,
std::string post_fix = "") {
return [=]() mutable {
return [=](etest::IActions &a) mutable {
auto rules = css::parse(fmt::format("p {{ {}: {} {}; }}"sv, property, values[0], values[1])).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
if (property == "border-style") {
property = "border";
}
 
auto body = rules[0];
expect(body.declarations.size() == 4);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-top{}", property, post_fix)))
a.expect(body.declarations.size() == 4);
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-top{}", property, post_fix)))
== values[0]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-bottom{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-bottom{}", property, post_fix)))
== values[0]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-left{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-left{}", property, post_fix)))
== values[1]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-right{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-right{}", property, post_fix)))
== values[1]);
};
};
 
{
auto size_values = std::array{"12em"s, "36em"s};
etest::test("parser: shorthand padding, two values", box_shorthand_two_values("padding", size_values));
etest::test("parser: shorthand margin, two values", box_shorthand_two_values("margin", size_values));
s.add_test("parser: shorthand padding, two values", box_shorthand_two_values("padding", size_values));
s.add_test("parser: shorthand margin, two values", box_shorthand_two_values("margin", size_values));
 
auto border_styles = std::array{"dashed"s, "solid"s};
etest::test("parser: shorthand border-style, two values",
s.add_test("parser: shorthand border-style, two values",
box_shorthand_two_values("border-style", border_styles, "-style"));
}
 
auto box_shorthand_three_values = [](std::string property,
std::array<std::string, 3> values,
std::string post_fix = "") {
return [=]() mutable {
return [=](etest::IActions &a) mutable {
auto rules =
css::parse(fmt::format("p {{ {}: {} {} {}; }}"sv, property, values[0], values[1], values[2])).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
if (property == "border-style") {
property = "border";
}
 
auto body = rules[0];
expect(body.declarations.size() == 4);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-top{}", property, post_fix)))
a.expect(body.declarations.size() == 4);
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-top{}", property, post_fix)))
== values[0]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-bottom{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-bottom{}", property, post_fix)))
== values[2]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-left{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-left{}", property, post_fix)))
== values[1]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-right{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-right{}", property, post_fix)))
== values[1]);
};
};
 
{
auto size_values = std::array{"12em"s, "36em"s, "52px"s};
etest::test("parser: shorthand padding, three values", box_shorthand_three_values("padding", size_values));
etest::test("parser: shorthand margin, three values", box_shorthand_three_values("margin", size_values));
s.add_test("parser: shorthand padding, three values", box_shorthand_three_values("padding", size_values));
s.add_test("parser: shorthand margin, three values", box_shorthand_three_values("margin", size_values));
 
auto border_styles = std::array{"groove"s, "dashed"s, "solid"s};
etest::test("parser: shorthand border-style, three values",
s.add_test("parser: shorthand border-style, three values",
box_shorthand_three_values("border-style", border_styles, "-style"));
}
 
auto box_shorthand_four_values = [](std::string property,
std::array<std::string, 4> values,
std::string post_fix = "") {
return [=]() mutable {
return [=](etest::IActions &a) mutable {
auto rules = css::parse(
fmt::format("p {{ {}: {} {} {} {}; }}"sv, property, values[0], values[1], values[2], values[3]))
.rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
if (property == "border-style" || property == "border-color" || property == "border-width") {
property = "border";
}
 
auto body = rules[0];
expect(body.declarations.size() == 4);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-top{}", property, post_fix)))
a.expect(body.declarations.size() == 4);
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-top{}", property, post_fix)))
== values[0]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-bottom{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-bottom{}", property, post_fix)))
== values[2]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-left{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-left{}", property, post_fix)))
== values[3]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-right{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-right{}", property, post_fix)))
== values[1]);
};
};
 
{
auto size_values = std::array{"12px"s, "36px"s, "52px"s, "2"s};
etest::test("parser: shorthand padding, four values", box_shorthand_four_values("padding", size_values));
etest::test("parser: shorthand margin, four values", box_shorthand_four_values("margin", size_values));
s.add_test("parser: shorthand padding, four values", box_shorthand_four_values("padding", size_values));
s.add_test("parser: shorthand margin, four values", box_shorthand_four_values("margin", size_values));
 
auto border_styles = std::array{"groove"s, "dashed"s, "solid"s, "dotted"s};
etest::test("parser: shorthand border-style, four values",
s.add_test("parser: shorthand border-style, four values",
box_shorthand_four_values("border-style", border_styles, "-style"));
 
etest::test("parser: shorthand border-color, four values",
s.add_test("parser: shorthand border-color, four values",
box_shorthand_four_values("border-color", std::array{"red"s, "green"s, "blue"s, "cyan"s}, "-color"));
 
etest::test("parser: shorthand border-width, four values",
s.add_test("parser: shorthand border-width, four values",
box_shorthand_four_values("border-width", size_values, "-width"));
}
 
auto box_shorthand_overridden = [](std::string property,
std::array<std::string, 3> values,
std::string post_fix = "") {
return [=]() mutable {
return [=](etest::IActions &a) mutable {
std::string workaround_for_border_style = property == "border-style" ? "border" : property;
auto rules = css::parse(fmt::format(R"(
p {{
@@ -611,39 +610,39 @@ int main() {
values[2],
workaround_for_border_style))
.rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
if (property == "border-style") {
property = "border";
}
 
auto body = rules[0];
expect(body.declarations.size() == 4);
expect_eq(body.declarations.at(css::property_id_from_string(fmt::format("{}-top{}", property, post_fix))),
a.expect(body.declarations.size() == 4);
a.expect_eq(body.declarations.at(css::property_id_from_string(fmt::format("{}-top{}", property, post_fix))),
values[1]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-bottom{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-bottom{}", property, post_fix)))
== values[0]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-left{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-left{}", property, post_fix)))
== values[2]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-right{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-right{}", property, post_fix)))
== values[0]);
};
};
 
{
auto size_values = std::array{"10px"s, "15px"s, "25px"s};
etest::test("parser: shorthand padding overridden", box_shorthand_overridden("padding", size_values));
etest::test("parser: shorthand margin overridden", box_shorthand_overridden("margin", size_values));
s.add_test("parser: shorthand padding overridden", box_shorthand_overridden("padding", size_values));
s.add_test("parser: shorthand margin overridden", box_shorthand_overridden("margin", size_values));
 
auto border_styles = std::array{"dashed"s, "solid"s, "dotted"s};
etest::test("parser: shorthand border-style overridden",
s.add_test("parser: shorthand border-style overridden",
box_shorthand_overridden("border-style", border_styles, "-style"));
}
 
auto box_override_with_shorthand = [](std::string property,
std::array<std::string, 4> values,
std::string post_fix = "") {
return [=]() mutable {
return [=](etest::IActions &a) mutable {
std::string workaround_for_border_style = property == "border-style" ? "border" : property;
auto rules = css::parse(fmt::format(R"(
p {{
@@ -659,263 +658,264 @@ int main() {
values[3],
workaround_for_border_style))
.rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
if (property == "border-style") {
property = "border";
}
 
auto body = rules[0];
expect(body.declarations.size() == 4);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-top{}", property, post_fix)))
a.expect(body.declarations.size() == 4);
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-top{}", property, post_fix)))
== values[2]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-bottom{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-bottom{}", property, post_fix)))
== values[2]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-left{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-left{}", property, post_fix)))
== values[3]);
expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-right{}", property, post_fix)))
a.expect(body.declarations.at(css::property_id_from_string(fmt::format("{}-right{}", property, post_fix)))
== values[3]);
};
};
 
{
auto size_values = std::array{"5px"s, "25px"s, "12px"s, "40px"s};
etest::test("parser: override padding with shorthand", box_override_with_shorthand("padding", size_values));
etest::test("parser: override margin with shorthand", box_override_with_shorthand("margin", size_values));
s.add_test("parser: override padding with shorthand", box_override_with_shorthand("padding", size_values));
s.add_test("parser: override margin with shorthand", box_override_with_shorthand("margin", size_values));
 
auto border_styles = std::array{"dashed"s, "solid"s, "hidden"s, "dotted"s};
etest::test("parser: override border-style with shorthand",
s.add_test("parser: override border-style with shorthand",
box_override_with_shorthand("border-style", border_styles, "-style"));
}
 
etest::test("parser: shorthand background color", [] {
s.add_test("parser: shorthand background color", [](etest::IActions &a) {
auto rules = css::parse("p { background: red }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto &p = rules[0];
expect_eq(get_and_erase(p.declarations, css::PropertyId::BackgroundColor), "red"sv);
expect(check_initial_background_values(p.declarations));
a.expect_eq(get_and_erase(a, p.declarations, css::PropertyId::BackgroundColor), "red"sv);
a.expect(check_initial_background_values(p.declarations));
});
 
etest::test("parser: shorthand font with only size and generic font family", [] {
s.add_test("parser: shorthand font with only size and generic font family", [](etest::IActions &a) {
auto rules = css::parse("p { font: 1.5em sans-serif; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == "sans-serif"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "1.5em"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == "sans-serif"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "1.5em"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: shorthand font with size, line height, and generic font family", [] {
s.add_test("parser: shorthand font with size, line height, and generic font family", [](etest::IActions &a) {
auto rules = css::parse("p { font: 10%/2.5 monospace; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == "monospace"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "10%"s);
expect(get_and_erase(body.declarations, css::PropertyId::LineHeight) == "2.5"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == "monospace"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "10%"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::LineHeight) == "2.5"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: shorthand font with absolute size, line height, and font family", [] {
s.add_test("parser: shorthand font with absolute size, line height, and font family", [](etest::IActions &a) {
auto rules = css::parse(R"(p { font: x-large/110% "New Century Schoolbook", serif; })"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == R"("New Century Schoolbook", serif)"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "x-large"s);
expect(get_and_erase(body.declarations, css::PropertyId::LineHeight) == "110%"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily)
== R"("New Century Schoolbook", serif)"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "x-large"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::LineHeight) == "110%"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: shorthand font with italic font style", [] {
s.add_test("parser: shorthand font with italic font style", [](etest::IActions &a) {
auto rules = css::parse(R"(p { font: italic 120% "Helvetica Neue", serif; })"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == R"("Helvetica Neue", serif)"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "120%"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontStyle) == "italic"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == R"("Helvetica Neue", serif)"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "120%"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontStyle) == "italic"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: shorthand font with oblique font style", [] {
s.add_test("parser: shorthand font with oblique font style", [](etest::IActions &a) {
auto rules = css::parse(R"(p { font: oblique 12pt "Helvetica Neue", serif; })"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == R"("Helvetica Neue", serif)"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "12pt"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontStyle) == "oblique"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == R"("Helvetica Neue", serif)"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "12pt"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontStyle) == "oblique"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: shorthand font with font style oblique with angle", [] {
s.add_test("parser: shorthand font with font style oblique with angle", [](etest::IActions &a) {
auto rules = css::parse("p { font: oblique 25deg 10px serif; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == "serif"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "10px"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontStyle) == "oblique 25deg"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == "serif"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "10px"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontStyle) == "oblique 25deg"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: shorthand font with bold font weight", [] {
s.add_test("parser: shorthand font with bold font weight", [](etest::IActions &a) {
auto rules = css::parse("p { font: italic bold 20em/50% serif; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == "serif"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "20em"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontStyle) == "italic"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontWeight) == "bold"s);
expect(get_and_erase(body.declarations, css::PropertyId::LineHeight) == "50%"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == "serif"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "20em"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontStyle) == "italic"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontWeight) == "bold"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::LineHeight) == "50%"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: shorthand font with bolder font weight", [] {
s.add_test("parser: shorthand font with bolder font weight", [](etest::IActions &a) {
auto rules = css::parse("p { font: normal bolder 100px serif; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == "serif"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "100px"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontWeight) == "bolder"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == "serif"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "100px"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontWeight) == "bolder"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: shorthand font with lighter font weight", [] {
s.add_test("parser: shorthand font with lighter font weight", [](etest::IActions &a) {
auto rules = css::parse("p { font: lighter 100px serif; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == "serif"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "100px"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontWeight) == "lighter"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == "serif"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "100px"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontWeight) == "lighter"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: shorthand font with 1000 font weight", [] {
s.add_test("parser: shorthand font with 1000 font weight", [](etest::IActions &a) {
auto rules = css::parse("p { font: 1000 oblique 100px serif; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == "serif"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "100px"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontStyle) == "oblique"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontWeight) == "1000"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == "serif"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "100px"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontStyle) == "oblique"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontWeight) == "1000"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: shorthand font with 550 font weight", [] {
s.add_test("parser: shorthand font with 550 font weight", [](etest::IActions &a) {
auto rules = css::parse("p { font: italic 550 100px serif; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == "serif"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "100px"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontStyle) == "italic"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontWeight) == "550"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == "serif"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "100px"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontStyle) == "italic"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontWeight) == "550"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: shorthand font with 1 font weight", [] {
s.add_test("parser: shorthand font with 1 font weight", [](etest::IActions &a) {
auto rules = css::parse("p { font: oblique 1 100px serif; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == "serif"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "100px"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontStyle) == "oblique"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontWeight) == "1"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == "serif"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "100px"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontStyle) == "oblique"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontWeight) == "1"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: shorthand font with smal1-caps font variant", [] {
s.add_test("parser: shorthand font with smal1-caps font variant", [](etest::IActions &a) {
auto rules = css::parse("p { font: small-caps 900 100px serif; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == "serif"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "100px"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontVariant) == "small-caps"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontWeight) == "900"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == "serif"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "100px"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontVariant) == "small-caps"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontWeight) == "900"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: shorthand font with condensed font stretch", [] {
s.add_test("parser: shorthand font with condensed font stretch", [](etest::IActions &a) {
auto rules = css::parse(R"(p { font: condensed oblique 25deg 753 12pt "Helvetica Neue", serif; })"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == R"("Helvetica Neue", serif)"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "12pt"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontStretch) == "condensed"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontStyle) == "oblique 25deg"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontWeight) == "753"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == R"("Helvetica Neue", serif)"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "12pt"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontStretch) == "condensed"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontStyle) == "oblique 25deg"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontWeight) == "753"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: shorthand font with exapnded font stretch", [] {
s.add_test("parser: shorthand font with exapnded font stretch", [](etest::IActions &a) {
auto rules = css::parse("p { font: italic expanded bold xx-smal/80% monospace; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == "monospace"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "xx-smal"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontStretch) == "expanded"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontStyle) == "italic"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontWeight) == "bold"s);
expect(get_and_erase(body.declarations, css::PropertyId::LineHeight) == "80%"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == "monospace"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "xx-smal"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontStretch) == "expanded"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontStyle) == "italic"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontWeight) == "bold"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::LineHeight) == "80%"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: font, single-argument", [] {
s.add_test("parser: font, single-argument", [](etest::IActions &a) {
auto rules = css::parse("p { font: status-bar; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto p = rules[0];
expect_eq(p.declarations.size(), std::size_t{1});
expect_eq(get_and_erase(p.declarations, css::PropertyId::FontFamily), "status-bar"s);
a.expect_eq(p.declarations.size(), std::size_t{1});
a.expect_eq(get_and_erase(a, p.declarations, css::PropertyId::FontFamily), "status-bar"s);
});
 
etest::test("parser: shorthand font with ultra-exapnded font stretch", [] {
s.add_test("parser: shorthand font with ultra-exapnded font stretch", [](etest::IActions &a) {
auto rules = css::parse("p { font: small-caps italic ultra-expanded bold medium Arial, monospace; }"sv).rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
 
auto body = rules[0];
expect(body.declarations.size() == 20);
expect(get_and_erase(body.declarations, css::PropertyId::FontFamily) == "Arial, monospace"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontSize) == "medium"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontStretch) == "ultra-expanded"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontStyle) == "italic"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontVariant) == "small-caps"s);
expect(get_and_erase(body.declarations, css::PropertyId::FontWeight) == "bold"s);
expect(check_initial_font_values(body.declarations));
a.expect(body.declarations.size() == 20);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontFamily) == "Arial, monospace"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontSize) == "medium"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontStretch) == "ultra-expanded"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontStyle) == "italic"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontVariant) == "small-caps"s);
a.expect(get_and_erase(a, body.declarations, css::PropertyId::FontWeight) == "bold"s);
a.expect(check_initial_font_values(body.declarations));
});
 
etest::test("parser: border-radius shorthand, 1 value", [] {
s.add_test("parser: border-radius shorthand, 1 value", [](etest::IActions &a) {
auto rules = css::parse("div { border-radius: 5px; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &div = rules[0];
expect_eq(div.declarations,
a.expect_eq(div.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::BorderTopLeftRadius, "5px"s},
{css::PropertyId::BorderTopRightRadius, "5px"s},
@@ -924,11 +924,11 @@ int main() {
});
});
 
etest::test("parser: border-radius shorthand, 2 values", [] {
s.add_test("parser: border-radius shorthand, 2 values", [](etest::IActions &a) {
auto rules = css::parse("div { border-radius: 1px 2px; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &div = rules[0];
expect_eq(div.declarations,
a.expect_eq(div.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::BorderTopLeftRadius, "1px"s},
{css::PropertyId::BorderTopRightRadius, "2px"s},
@@ -937,11 +937,11 @@ int main() {
});
});
 
etest::test("parser: border-radius shorthand, 3 values", [] {
s.add_test("parser: border-radius shorthand, 3 values", [](etest::IActions &a) {
auto rules = css::parse("div { border-radius: 1px 2px 3px; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &div = rules[0];
expect_eq(div.declarations,
a.expect_eq(div.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::BorderTopLeftRadius, "1px"s},
{css::PropertyId::BorderTopRightRadius, "2px"s},
@@ -950,11 +950,11 @@ int main() {
});
});
 
etest::test("parser: border-radius shorthand, 4 values", [] {
s.add_test("parser: border-radius shorthand, 4 values", [](etest::IActions &a) {
auto rules = css::parse("div { border-radius: 1px 2px 3px 4px; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &div = rules[0];
expect_eq(div.declarations,
a.expect_eq(div.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::BorderTopLeftRadius, "1px"s},
{css::PropertyId::BorderTopRightRadius, "2px"s},
@@ -963,11 +963,11 @@ int main() {
});
});
 
etest::test("parser: border-radius, 1 value, separate horizontal and vertical", [] {
s.add_test("parser: border-radius, 1 value, separate horizontal and vertical", [](etest::IActions &a) {
auto rules = css::parse("div { border-radius: 5px / 10px; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &div = rules[0];
expect_eq(div.declarations,
a.expect_eq(div.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::BorderTopLeftRadius, "5px / 10px"s},
{css::PropertyId::BorderTopRightRadius, "5px / 10px"s},
@@ -976,11 +976,11 @@ int main() {
});
});
 
etest::test("parser: border-radius, 2 values, separate horizontal and vertical", [] {
s.add_test("parser: border-radius, 2 values, separate horizontal and vertical", [](etest::IActions &a) {
auto rules = css::parse("div { border-radius: 5px / 10px 15px; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &div = rules[0];
expect_eq(div.declarations,
a.expect_eq(div.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::BorderTopLeftRadius, "5px / 10px"s},
{css::PropertyId::BorderTopRightRadius, "5px / 15px"s},
@@ -989,11 +989,11 @@ int main() {
});
});
 
etest::test("parser: border-radius, 3 values, separate horizontal and vertical", [] {
s.add_test("parser: border-radius, 3 values, separate horizontal and vertical", [](etest::IActions &a) {
auto rules = css::parse("div { border-radius: 5px / 10px 15px 20px; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &div = rules[0];
expect_eq(div.declarations,
a.expect_eq(div.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::BorderTopLeftRadius, "5px / 10px"s},
{css::PropertyId::BorderTopRightRadius, "5px / 15px"s},
@@ -1002,11 +1002,11 @@ int main() {
});
});
 
etest::test("parser: border-radius, 4 values, separate horizontal and vertical", [] {
s.add_test("parser: border-radius, 4 values, separate horizontal and vertical", [](etest::IActions &a) {
auto rules = css::parse("div { border-radius: 5px / 10px 15px 20px 25px; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &div = rules[0];
expect_eq(div.declarations,
a.expect_eq(div.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::BorderTopLeftRadius, "5px / 10px"s},
{css::PropertyId::BorderTopRightRadius, "5px / 15px"s},
@@ -1015,11 +1015,11 @@ int main() {
});
});
 
etest::test("parser: border-radius, invalid vertical, separate horizontal and vertical", [] {
s.add_test("parser: border-radius, invalid vertical, separate horizontal and vertical", [](etest::IActions &a) {
auto rules = css::parse("div { border-radius: 5px / 10px 15px 20px 25px 30px; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &div = rules[0];
expect_eq(div.declarations,
a.expect_eq(div.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::BorderTopLeftRadius, "5px"s},
{css::PropertyId::BorderTopRightRadius, "5px"s},
@@ -1028,7 +1028,7 @@ int main() {
});
});
 
etest::test("parser: @keyframes doesn't crash the parser", [] {
s.add_test("parser: @keyframes doesn't crash the parser", [](etest::IActions &a) {
auto css = R"(
@keyframes toast-spinner {
from {
@@ -1042,10 +1042,10 @@ int main() {
 
// No rules produced (yet!) since this isn't handled aside from not crashing.
auto rules = css::parse(css).rules;
expect(rules.empty());
a.expect(rules.empty());
});
 
etest::test("parser: several @keyframes in a row doesn't crash the parser", [] {
s.add_test("parser: several @keyframes in a row doesn't crash the parser", [](etest::IActions &a) {
auto css = R"(
@keyframes toast-spinner {
from { transform: rotate(0deg) }
@@ -1058,10 +1058,10 @@ int main() {
 
// No rules produced (yet!) since this isn't handled aside from not crashing.
auto rules = css::parse(css).rules;
expect(rules.empty());
a.expect(rules.empty());
});
 
etest::test("parser: @font-face", [] {
s.add_test("parser: @font-face", [](etest::IActions &a) {
// This isn't correct, but it doesn't crash.
auto css = R"(
@font-face {
@@ -1071,22 +1071,22 @@ int main() {
})"sv;
 
auto rules = css::parse(css).rules;
expect_eq(rules.size(), std::size_t{1});
expect_eq(rules[0].selectors, std::vector{"@font-face"s});
expect_eq(rules[0].declarations.size(), std::size_t{2});
expect_eq(rules[0].declarations.at(css::PropertyId::FontFamily), R"("Open Sans")");
a.expect_eq(rules.size(), std::size_t{1});
a.expect_eq(rules[0].selectors, std::vector{"@font-face"s});
a.expect_eq(rules[0].declarations.size(), std::size_t{2});
a.expect_eq(rules[0].declarations.at(css::PropertyId::FontFamily), R"("Open Sans")");
 
// Very incorrect.
auto const &src = rules[0].declarations.at(css::PropertyId::Unknown);
expect(src.contains(R"(url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2"))"));
expect(src.contains(R"(url("/fonts/OpenSans-Regular-webfont.woff") format("woff")"));
a.expect(src.contains(R"(url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2"))"));
a.expect(src.contains(R"(url("/fonts/OpenSans-Regular-webfont.woff") format("woff")"));
});
 
etest::test("parser: border shorthand, all values", [] {
s.add_test("parser: border shorthand, all values", [](etest::IActions &a) {
auto rules = css::parse("p { border: 5px black solid; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &p = rules[0];
expect_eq(p.declarations,
a.expect_eq(p.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::BorderBottomColor, "black"s},
{css::PropertyId::BorderBottomStyle, "solid"s},
@@ -1103,11 +1103,11 @@ int main() {
});
});
 
etest::test("parser: border shorthand, color+style", [] {
s.add_test("parser: border shorthand, color+style", [](etest::IActions &a) {
auto rules = css::parse("p { border-bottom: #123 dotted; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &p = rules[0];
expect_eq(p.declarations,
a.expect_eq(p.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::BorderBottomColor, "#123"s},
{css::PropertyId::BorderBottomStyle, "dotted"s},
@@ -1115,11 +1115,11 @@ int main() {
});
});
 
etest::test("parser: border shorthand, width+style", [] {
s.add_test("parser: border shorthand, width+style", [](etest::IActions &a) {
auto rules = css::parse("p { border-left: ridge 30em; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &p = rules[0];
expect_eq(p.declarations,
a.expect_eq(p.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::BorderLeftColor, "currentcolor"s},
{css::PropertyId::BorderLeftStyle, "ridge"s},
@@ -1127,11 +1127,11 @@ int main() {
});
});
 
etest::test("parser: border shorthand, width", [] {
s.add_test("parser: border shorthand, width", [](etest::IActions &a) {
auto rules = css::parse("p { border-right: thin; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &p = rules[0];
expect_eq(p.declarations,
a.expect_eq(p.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::BorderRightColor, "currentcolor"s},
{css::PropertyId::BorderRightStyle, "none"s},
@@ -1139,11 +1139,11 @@ int main() {
});
});
 
etest::test("parser: border shorthand, width, first character a dot", [] {
s.add_test("parser: border shorthand, width, first character a dot", [](etest::IActions &a) {
auto rules = css::parse("p { border-right: .3em; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &p = rules[0];
expect_eq(p.declarations,
a.expect_eq(p.declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::BorderRightColor, "currentcolor"s},
{css::PropertyId::BorderRightStyle, "none"s},
@@ -1151,83 +1151,83 @@ int main() {
});
});
 
etest::test("parser: border shorthand, too many values", [] {
s.add_test("parser: border shorthand, too many values", [](etest::IActions &a) {
auto rules = css::parse("p { border-top: outset #123 none solid; }").rules;
require(rules.size() == 1);
a.require(rules.size() == 1);
auto const &p = rules[0];
expect_eq(p.declarations, std::map<css::PropertyId, std::string>{});
a.expect_eq(p.declarations, std::map<css::PropertyId, std::string>{});
});
 
etest::test("parser: incomplete media-query crash", [] {
s.add_test("parser: incomplete media-query crash", [](etest::IActions &) {
std::ignore = css::parse("@media("); //
});
 
etest::test("parser: incomplete at-rule crash", [] {
s.add_test("parser: incomplete at-rule crash", [](etest::IActions &) {
std::ignore = css::parse("@lol"); //
});
 
etest::test("parser: incomplete rule in unknown at-rule crash", [] {
s.add_test("parser: incomplete rule in unknown at-rule crash", [](etest::IActions &) {
std::ignore = css::parse("@lol ");
std::ignore = css::parse("@lol { p {"); //
});
 
etest::test("parser: incomplete rule crash", [] {
s.add_test("parser: incomplete rule crash", [](etest::IActions &) {
std::ignore = css::parse("p");
std::ignore = css::parse("p {");
std::ignore = css::parse("p { font-size:");
});
 
etest::test("parser: flex-flow shorthand, global value", [] {
expect_eq(css::parse("p { flex-flow: revert; }").rules.at(0).declarations,
s.add_test("parser: flex-flow shorthand, global value", [](etest::IActions &a) {
a.expect_eq(css::parse("p { flex-flow: revert; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::FlexDirection, "revert"s},
{css::PropertyId::FlexWrap, "revert"s},
});
expect_eq(css::parse("p { flex-flow: revert row; }").rules.at(0).declarations,
a.expect_eq(css::parse("p { flex-flow: revert row; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{});
});
 
etest::test("parser: flex-flow shorthand, one value", [] {
expect_eq(css::parse("p { flex-flow: column; }").rules.at(0).declarations,
s.add_test("parser: flex-flow shorthand, one value", [](etest::IActions &a) {
a.expect_eq(css::parse("p { flex-flow: column; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::FlexDirection, "column"s},
{css::PropertyId::FlexWrap, "nowrap"s},
});
expect_eq(css::parse("p { flex-flow: wrap; }").rules.at(0).declarations,
a.expect_eq(css::parse("p { flex-flow: wrap; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::FlexDirection, "row"s},
{css::PropertyId::FlexWrap, "wrap"s},
});
expect_eq(css::parse("p { flex-flow: aaaaaaaaaa; }").rules.at(0).declarations,
a.expect_eq(css::parse("p { flex-flow: aaaaaaaaaa; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{});
});
 
etest::test("parser: flex-flow shorthand, two values", [] {
expect_eq(css::parse("p { flex-flow: column wrap; }").rules.at(0).declarations,
s.add_test("parser: flex-flow shorthand, two values", [](etest::IActions &a) {
a.expect_eq(css::parse("p { flex-flow: column wrap; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{
{css::PropertyId::FlexDirection, "column"s},
{css::PropertyId::FlexWrap, "wrap"s},
});
expect_eq(css::parse("p { flex-flow: wrap wrap; }").rules.at(0).declarations, //
a.expect_eq(css::parse("p { flex-flow: wrap wrap; }").rules.at(0).declarations, //
std::map<css::PropertyId, std::string>{});
expect_eq(css::parse("p { flex-flow: wrap asdf; }").rules.at(0).declarations, //
a.expect_eq(css::parse("p { flex-flow: wrap asdf; }").rules.at(0).declarations, //
std::map<css::PropertyId, std::string>{});
});
 
etest::test("parser: flex-flow shorthand, too many values :(", [] {
expect_eq(css::parse("p { flex-flow: column wrap nowrap; }").rules.at(0).declarations,
s.add_test("parser: flex-flow shorthand, too many values :(", [](etest::IActions &a) {
a.expect_eq(css::parse("p { flex-flow: column wrap nowrap; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{});
});
 
etest::test("parser: custom property", [] {
expect_eq(css::parse("p { --var: value; }").rules.at(0), //
s.add_test("parser: custom property", [](etest::IActions &a) {
a.expect_eq(css::parse("p { --var: value; }").rules.at(0), //
css::Rule{.selectors = {{"p"}}, .custom_properties = {{"--var", "value"}}});
});
 
// TODO(robinlinden): Nested rules are currently skipped, but at least
// they mostly don't break parsing of the rule they're nested in.
etest::test("parser: nested rule", [] {
expect_eq(css::parse("p { color: green; a { font-size: 3px; } font-size: 5px; }").rules, //
s.add_test("parser: nested rule", [](etest::IActions &a) {
a.expect_eq(css::parse("p { color: green; a { font-size: 3px; } font-size: 5px; }").rules, //
std::vector{
css::Rule{
.selectors = {{"p"}},
@@ -1239,23 +1239,23 @@ int main() {
});
});
 
etest::test("parser: eof in nested rule", [] {
expect(css::parse("p { color: green; a { font-size: 3px; ").rules.empty()); //
s.add_test("parser: eof in nested rule", [](etest::IActions &a) {
a.expect(css::parse("p { color: green; a { font-size: 3px; ").rules.empty()); //
});
 
etest::test("parser: -webkit-lol", [] {
expect_eq(css::parse("p { -webkit-font-size: 3px; }").rules.at(0).declarations,
s.add_test("parser: -webkit-lol", [](etest::IActions &a) {
a.expect_eq(css::parse("p { -webkit-font-size: 3px; }").rules.at(0).declarations,
std::map<css::PropertyId, std::string>{{css::PropertyId::Unknown, "3px"}});
});
 
etest::test("parser: @charset", [] {
expect_eq(css::parse("@charset 'shift-jis'; p { font-size: 3px; }").rules.at(0),
s.add_test("parser: @charset", [](etest::IActions &a) {
a.expect_eq(css::parse("@charset 'shift-jis'; p { font-size: 3px; }").rules.at(0),
css::Rule{.selectors = {{"p"}}, .declarations{{css::PropertyId::FontSize, "3px"}}});
});
 
etest::test("parser: @charset eof", [] {
expect(css::parse("@charset 'shi").rules.empty()); //
s.add_test("parser: @charset eof", [](etest::IActions &a) {
a.expect(css::parse("@charset 'shi").rules.empty()); //
});
 
return etest::run_all_tests();
return s.run();
}
 
css/rule_test.cpp added: 445, removed: 446, total 0
@@ -8,12 +8,11 @@
#include "css/media_query.h"
#include "css/property_id.h"
 
#include "etest/etest.h"
 
using etest::expect_eq;
#include "etest/etest2.h"
 
int main() {
etest::test("rule to string, one selector and declaration", [] {
etest::Suite s{};
s.add_test("rule to string, one selector and declaration", [](etest::IActions &a) {
css::Rule rule;
rule.selectors.emplace_back("div");
rule.declarations.emplace(css::PropertyId::BackgroundColor, "black");
@@ -22,10 +21,10 @@ int main() {
"Selectors: div\n"
"Declarations:\n"
" background-color: black\n";
expect_eq(css::to_string(rule), expected);
a.expect_eq(css::to_string(rule), expected);
});
 
etest::test("rule to string, two selectors and several declarations", [] {
s.add_test("rule to string, two selectors and several declarations", [](etest::IActions &a) {
css::Rule rule;
rule.selectors.emplace_back("h1");
rule.selectors.emplace_back("h2");
@@ -39,10 +38,10 @@ int main() {
" color: blue\n"
" font-family: Arial\n"
" text-align: center\n";
expect_eq(css::to_string(rule), expected);
a.expect_eq(css::to_string(rule), expected);
});
 
etest::test("rule to string, two selectors and several declarations", [] {
s.add_test("rule to string, two selectors and several declarations", [](etest::IActions &a) {
css::Rule rule;
rule.selectors.emplace_back("h1");
rule.declarations.emplace(css::PropertyId::Color, "blue");
@@ -56,10 +55,10 @@ int main() {
" text-align: center\n"
"Media query:\n"
" 0 <= width <= 900\n";
expect_eq(css::to_string(rule), expected);
a.expect_eq(css::to_string(rule), expected);
});
 
etest::test("rule to string, important declaration", [] {
s.add_test("rule to string, important declaration", [](etest::IActions &a) {
css::Rule rule;
rule.selectors.emplace_back("div");
rule.important_declarations.emplace(css::PropertyId::BackgroundColor, "black");
@@ -69,10 +68,10 @@ int main() {
"Declarations:\n"
"Important declarations:\n"
" background-color: black\n";
expect_eq(css::to_string(rule), expected);
a.expect_eq(css::to_string(rule), expected);
});
 
etest::test("rule to string, custom property", [] {
s.add_test("rule to string, custom property", [](etest::IActions &a) {
css::Rule rule;
rule.selectors.emplace_back("div");
rule.custom_properties.emplace("--ping", "pong");
@@ -82,8 +81,8 @@ int main() {
"Declarations:\n"
"Custom properties:\n"
" --ping: pong\n";
expect_eq(css::to_string(rule), expected);
a.expect_eq(css::to_string(rule), expected);
});
 
return etest::run_all_tests();
return s.run();
}