litehtml/test/cssTest.cpp
2022-03-19 09:30:22 +06:00

580 lines
29 KiB
C++

#include <gtest/gtest.h>
#include <assert.h>
#include "litehtml.h"
#include "test/container_test.h"
using namespace litehtml;
TEST(CSSTest, Parse) {
container_test container;
litehtml::document::ptr doc = std::make_shared<litehtml::document>(&container, nullptr);
media_query_list::ptr media = media_query_list::ptr();
css c;
c.parse_stylesheet(_t("/*Comment*/"), nullptr, doc, nullptr);
c.parse_stylesheet(_t("html { display: none }"), nullptr, doc, nullptr);
// https://www.w3schools.com/cssref/pr_import_rule.asp
c.parse_stylesheet(_t("@import \"navigation.css\"; /* Using a string */"), nullptr, doc, nullptr);
c.parse_stylesheet(_t("@import url(\"navigation.css\"); /* Using a url */"), nullptr, doc, nullptr);
c.parse_stylesheet(_t("@import \"navigation.css\""), nullptr, doc, nullptr);
c.parse_stylesheet(_t("@import \"printstyle.css\" print;"), nullptr, doc, nullptr);
c.parse_stylesheet(_t("@import \"mobstyle.css\" screen and (max-width: 768px);"), nullptr, doc, nullptr);
// https://www.w3schools.com/cssref/css3_pr_mediaquery.asp
c.parse_stylesheet(_t("@media only screen and (max-width: 600px) { body { background-color: lightblue; } }"), nullptr, doc, nullptr);
}
TEST(CSSTest, Url) {
tstring url;
css::parse_css_url(_t(""), url);
EXPECT_TRUE(url.empty());
css::parse_css_url(_t("value"), url);
EXPECT_TRUE(url.empty());
css::parse_css_url(_t("url()"), url);
EXPECT_TRUE(url.empty());
css::parse_css_url(_t("url(value)"), url);
EXPECT_TRUE(!t_strcmp(url.c_str(), _t("value")));
css::parse_css_url(_t("url('value')"), url);
EXPECT_TRUE(!t_strcmp(url.c_str(), _t("value")));
css::parse_css_url(_t("url(\"value\")"), url);
EXPECT_TRUE(!t_strcmp(url.c_str(), _t("value")));
}
TEST(CSSTest, LengthParse) {
css_length length;
length.fromString(_t("calc(todo)"));
assert(length.is_predefined() == true);
assert(length.predef() == 0);
assert(length.val() == 0);
assert(length.units() == css_units_none);
length.fromString(_t("top"), _t("top;bottom"), -1);
assert(length.is_predefined() == true);
assert(length.predef() == 0);
assert(length.val() == 0);
assert(length.units() == css_units_none);
length.fromString(_t("bottom"), _t("top;bottom"), -1);
assert(length.is_predefined() == true);
assert(length.predef() == 1);
assert(length.val() == 0);
assert(length.units() == css_units_none);
length.fromString(_t("bad"), _t("top;bottom"), -1);
assert(length.is_predefined() == true);
assert(length.predef() == -1);
assert(length.val() == 0);
assert(length.units() == css_units_none);
length.fromString(_t("123"), _t("top;bottom"), -1);
assert(length.is_predefined() == false);
assert(length.predef() == 0);
assert(length.val() == 123);
assert(length.units() == css_units_none);
length.fromString(_t("123px"), _t("top;bottom"), -1);
assert(length.is_predefined() == false);
assert(length.predef() == 0);
assert(length.val() == 123);
assert(length.units() == css_units_px);
}
TEST(CSSTest, ElementSelectorParse) {
css_element_selector selector;
// https://www.w3schools.com/cssref/css_selectors.asp
selector.parse(_t(".class"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("class")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("class")));
selector.parse(_t(".class1.class2"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 2);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("class1")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[1].val.c_str(), _t("class2")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("class")));
selector.parse(_t("#id"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("id")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("id")));
selector.parse(_t("*"));
EXPECT_TRUE(!t_strcmp(selector.m_tag.c_str(), _t("*")));
EXPECT_TRUE(selector.m_attrs.empty());
selector.parse(_t("element"));
EXPECT_TRUE(!t_strcmp(selector.m_tag.c_str(), _t("element")));
EXPECT_TRUE(selector.m_attrs.empty());
selector.parse(_t("[attribute]"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("attribute")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_exists);
selector.parse(_t("[attribute=value]"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("value")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("attribute")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_equal);
selector.parse(_t("[attribute~=value]"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("value")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("attribute")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_contain_str);
selector.parse(_t("[attribute|=value]"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("value")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("attribute")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_start_str);
selector.parse(_t("[attribute^=value]"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("value")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("attribute")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_start_str);
selector.parse(_t("[attribute$=value]"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("value")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("attribute")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_end_str);
selector.parse(_t("[attribute*=value]"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("value")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("attribute")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_contain_str);
selector.parse(_t(":active"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("active")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t("::after"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("after")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo-el")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_element);
selector.parse(_t("::before"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("before")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo-el")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_element);
selector.parse(_t(":checked"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("checked")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":default"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("default")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":disabled"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("disabled")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":empty"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("empty")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":enabled"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("enabled")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":first-child"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("first-child")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t("::first-letter"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("first-letter")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo-el")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_element);
selector.parse(_t("::first-line"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("first-line")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo-el")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_element);
selector.parse(_t(":first-of-type"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("first-of-type")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":focus"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("focus")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":hover"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("hover")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":in-range"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("in-range")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":indeterminate"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("indeterminate")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":invalid"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("invalid")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":lang(language)"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("lang(language)")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":last-child"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("last-child")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":last-of-type"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("last-of-type")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":link"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("link")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":not(selector)"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("not(selector)")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":nth-child(n)"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("nth-child(n)")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":nth-last-child(n)"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("nth-last-child(n)")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":nth-last-of-type(n)"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("nth-last-of-type(n)")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":nth-of-type(n)"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("nth-of-type(n)")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":only-of-type"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("only-of-type")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":only-child"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("only-child")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":optional"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("optional")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":out-of-range"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("out-of-range")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t("::placeholder"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("placeholder")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo-el")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_element);
selector.parse(_t(":read-only"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("read-only")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":read-write"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("read-write")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":required"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("required")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":root"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("root")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t("::selection"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("selection")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo-el")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_element);
selector.parse(_t(":target"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("target")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":valid"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("valid")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
selector.parse(_t(":visited"));
EXPECT_TRUE(selector.m_tag.empty());
EXPECT_TRUE(selector.m_attrs.size() == 1);
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].val.c_str(), _t("visited")));
EXPECT_TRUE(!t_strcmp(selector.m_attrs[0].attribute.c_str(), _t("pseudo")));
EXPECT_TRUE(selector.m_attrs[0].condition == select_pseudo_class);
// other
selector.parse(_t("tag:psudo#anchor"));
EXPECT_TRUE(!t_strcmp(selector.m_tag.c_str(), _t("tag")));
EXPECT_TRUE(selector.m_attrs.size() == 2);
}
TEST(CSSTest, DISABLED_SelectorParse) {
css_selector selector(nullptr, _t(""));
// https://www.w3schools.com/cssref/css_selectors.asp
assert(!selector.parse(_t("")));
EXPECT_TRUE(selector.parse(_t("element")));
EXPECT_TRUE(selector.m_combinator == combinator_descendant);
EXPECT_TRUE(!t_strcmp(selector.m_right.m_tag.c_str(), _t("element")));
EXPECT_TRUE(selector.m_right.m_attrs.empty());
EXPECT_TRUE(selector.m_left == nullptr);
// assert(selector.parse(_t("element,element")));
// EXPECT_TRUE(selector.m_combinator == combinator_descendant);
// EXPECT_TRUE(selector.m_right.m_tag.c_str(), _t("element"));
// EXPECT_TRUE(selector.m_right.m_attrs.empty());
EXPECT_TRUE(selector.parse(_t(".class1 .class2")));
EXPECT_TRUE(selector.m_combinator == combinator_descendant);
EXPECT_TRUE(selector.m_right.m_tag.empty());
EXPECT_TRUE(selector.m_right.m_attrs.size() == 1);
EXPECT_TRUE(selector.m_left->m_right.m_attrs.size() == 1);
assert(selector.parse(_t("element element")));
EXPECT_TRUE(selector.m_combinator == combinator_descendant);
EXPECT_TRUE(!t_strcmp(selector.m_right.m_tag.c_str(), _t("element")));
EXPECT_TRUE(selector.m_right.m_attrs.empty());
EXPECT_TRUE(!t_strcmp(selector.m_left->m_right.m_tag.c_str(), _t("element")));
assert(selector.parse(_t("element>element")));
EXPECT_TRUE(selector.m_combinator == combinator_child);
EXPECT_TRUE(!t_strcmp(selector.m_right.m_tag.c_str(), _t("element")));
EXPECT_TRUE(selector.m_right.m_attrs.empty());
EXPECT_TRUE(!t_strcmp(selector.m_left->m_right.m_tag.c_str(), _t("element")));
assert(selector.parse(_t("element+element")));
EXPECT_TRUE(selector.m_combinator == combinator_adjacent_sibling);
EXPECT_TRUE(!t_strcmp(selector.m_right.m_tag.c_str(), _t("element")));
EXPECT_TRUE(selector.m_right.m_attrs.empty());
EXPECT_TRUE(!t_strcmp(selector.m_left->m_right.m_tag.c_str(), _t("element")));
assert(selector.parse(_t("element1~element2")));
EXPECT_TRUE(selector.m_combinator == combinator_general_sibling);
EXPECT_TRUE(!t_strcmp(selector.m_right.m_tag.c_str(), _t("element2")));
EXPECT_TRUE(selector.m_right.m_attrs.empty());
EXPECT_TRUE(!t_strcmp(selector.m_left->m_right.m_tag.c_str(), _t("element1")));
}
TEST(CSSTest, StyleAdd) {
style style;
style.add(_t("border: 5px solid red; background-image: value"), _t("base"), nullptr);
style.add(_t("border: 5px solid red!important; background-image: value"), _t("base"), nullptr);
}
TEST(CSSTest, StyleAddProperty) {
style style;
style.add_property(_t("background-image"), _t("value"), _t("base"), false, nullptr);
style.add_property(_t("border-spacing"), _t("1"), nullptr, false, nullptr);
style.add_property(_t("border-spacing"), _t("1 2"), nullptr, false, nullptr);
style.add_property(_t("border"), _t("5px solid red"), nullptr, false, nullptr);
style.add_property(_t("border-left"), _t("5px solid red"), nullptr, false, nullptr);
style.add_property(_t("border-right"), _t("5px solid red"), nullptr, false, nullptr);
style.add_property(_t("border-top"), _t("5px solid red"), nullptr, false, nullptr);
style.add_property(_t("border-bottom"), _t("5px solid red"), nullptr, false, nullptr);
style.add_property(_t("border-bottom-left-radius"), _t("1"), nullptr, false, nullptr);
style.add_property(_t("border-bottom-left-radius"), _t("1 2"), nullptr, false, nullptr);
style.add_property(_t("border-bottom-right-radius"), _t("1"), nullptr, false, nullptr);
style.add_property(_t("border-bottom-right-radius"), _t("1 2"), nullptr, false, nullptr);
style.add_property(_t("border-top-right-radius"), _t("1"), nullptr, false, nullptr);
style.add_property(_t("border-top-right-radius"), _t("1 2"), nullptr, false, nullptr);
style.add_property(_t("border-top-left-radius"), _t("1"), nullptr, false, nullptr);
style.add_property(_t("border-top-left-radius"), _t("1 2"), nullptr, false, nullptr);
style.add_property(_t("border-radius"), _t("1"), nullptr, false, nullptr);
style.add_property(_t("border-radius"), _t("1 2"), nullptr, false, nullptr);
style.add_property(_t("border-radius-x"), _t("1"), nullptr, false, nullptr);
style.add_property(_t("border-radius-x"), _t("1 2"), nullptr, false, nullptr);
style.add_property(_t("border-radius-x"), _t("1 2 3"), nullptr, false, nullptr);
style.add_property(_t("border-radius-x"), _t("1 2 3 4"), nullptr, false, nullptr);
style.add_property(_t("border-radius-y"), _t("1"), nullptr, false, nullptr);
style.add_property(_t("border-radius-y"), _t("1 2"), nullptr, false, nullptr);
style.add_property(_t("border-radius-y"), _t("1 2 3"), nullptr, false, nullptr);
style.add_property(_t("border-radius-y"), _t("1 2 3 4"), nullptr, false, nullptr);
style.add_property(_t("list-style-image"), _t("value"), _t("base"), false, nullptr);
style.add_property(_t("background"), _t("url(value)"), _t("base"), false, nullptr);
style.add_property(_t("background"), _t("repeat"), nullptr, false, nullptr);
style.add_property(_t("background"), _t("fixed"), nullptr, false, nullptr);
style.add_property(_t("background"), _t("border-box"), nullptr, false, nullptr);
style.add_property(_t("background"), _t("border-box border-box"), nullptr, false, nullptr);
style.add_property(_t("background"), _t("left"), nullptr, false, nullptr);
style.add_property(_t("background"), _t("1"), nullptr, false, nullptr);
style.add_property(_t("background"), _t("-1"), nullptr, false, nullptr);
style.add_property(_t("background"), _t("-1"), nullptr, false, nullptr);
style.add_property(_t("background"), _t("+1"), nullptr, false, nullptr);
style.add_property(_t("background"), _t("left 1"), nullptr, false, nullptr);
style.add_property(_t("background"), _t("red"), nullptr, false, nullptr);
style.add_property(_t("margin"), _t("1"), nullptr, false, nullptr);
style.add_property(_t("margin"), _t("1 2"), nullptr, false, nullptr);
style.add_property(_t("margin"), _t("1 2 3"), nullptr, false, nullptr);
style.add_property(_t("margin"), _t("1 2 3 4"), nullptr, false, nullptr);
style.add_property(_t("padding"), _t("1"), nullptr, false, nullptr);
style.add_property(_t("padding"), _t("1 2"), nullptr, false, nullptr);
style.add_property(_t("padding"), _t("1 2 3"), nullptr, false, nullptr);
style.add_property(_t("padding"), _t("1 2 3 4"), nullptr, false, nullptr);
style.add_property(_t("border-left"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-left"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-left"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-left"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-right"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-right"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-right"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-right"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-top"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-top"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-top"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-top"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-bottom"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-bottom"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-bottom"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-bottom"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("border-width"), _t("1"), nullptr, false, nullptr);
style.add_property(_t("border-width"), _t("1 2"), nullptr, false, nullptr);
style.add_property(_t("border-width"), _t("1 2 3"), nullptr, false, nullptr);
style.add_property(_t("border-width"), _t("1 2 3 4"), nullptr, false, nullptr);
style.add_property(_t("border-style"), _t("1"), nullptr, false, nullptr);
style.add_property(_t("border-style"), _t("1 2"), nullptr, false, nullptr);
style.add_property(_t("border-style"), _t("1 2 3"), nullptr, false, nullptr);
style.add_property(_t("border-style"), _t("1 2 3 4"), nullptr, false, nullptr);
style.add_property(_t("border-color"), _t("1"), nullptr, false, nullptr);
style.add_property(_t("border-color"), _t("1 2"), nullptr, false, nullptr);
style.add_property(_t("border-color"), _t("1 2 3"), nullptr, false, nullptr);
style.add_property(_t("border-color"), _t("1 2 3 4"), nullptr, false, nullptr);
style.add_property(_t("font"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("font"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("font"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("font"), _t("TBD"), nullptr, false, nullptr);
style.add_property(_t("unknown"), _t("value"), nullptr, false, nullptr);
}