blob: ef8c2a51b91515754527071daa13bc68c0e8fad8 [file] [log] [blame]
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/css_parser/parser.h"
#include "cobalt/cssom/css_style_rule.h"
#include "cobalt/cssom/selector_tree.h"
#include "cobalt/cssom/specificity.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cobalt {
namespace cssom {
TEST(SelectorTreeTest, RootShouldHaveNoChildrenAfterInitialization) {
SelectorTree selector_tree;
EXPECT_TRUE(
selector_tree.children(selector_tree.root(), kChildCombinator).empty());
EXPECT_TRUE(
selector_tree.children(selector_tree.root(), kDescendantCombinator)
.empty());
EXPECT_TRUE(
selector_tree.children(selector_tree.root(), kNextSiblingCombinator)
.empty());
EXPECT_TRUE(
selector_tree.children(selector_tree.root(), kFollowingSiblingCombinator)
.empty());
}
TEST(SelectorTreeTest, AppendRuleShouldTakeOneRule) {
SelectorTree selector_tree;
// Selector Tree:
// root
// kDescendantCombinator -> node_1("div")
scoped_ptr<css_parser::Parser> css_parser = css_parser::Parser::Create();
scoped_refptr<CSSStyleRule> css_style_rule_1 =
css_parser->ParseRule("div {}", base::SourceLocation(
"[object SelectorTreeTest]", 1, 1))
->AsCSSStyleRule();
selector_tree.AppendRule(css_style_rule_1);
ASSERT_EQ(
0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
ASSERT_EQ(1,
selector_tree.children(selector_tree.root(), kDescendantCombinator)
.size());
ASSERT_EQ(0,
selector_tree.children(selector_tree.root(), kNextSiblingCombinator)
.size());
ASSERT_EQ(0, selector_tree.children(selector_tree.root(),
kFollowingSiblingCombinator)
.size());
const SelectorTree::Node* node_1 =
selector_tree.children(selector_tree.root(), kDescendantCombinator)
.begin()
->second;
ASSERT_EQ(1, node_1->rules().size());
EXPECT_EQ(css_style_rule_1, node_1->rules()[0]);
EXPECT_EQ(Specificity(0, 0, 1), node_1->cumulative_specificity());
}
TEST(SelectorTreeTest, AppendRuleShouldNormalizeCompoundSelector) {
SelectorTree selector_tree;
// Selector Tree:
// root
// kDescendantCombinator -> node_1(".class#id")
scoped_ptr<css_parser::Parser> css_parser = css_parser::Parser::Create();
scoped_refptr<CSSStyleRule> css_style_rule_1 =
css_parser->ParseRule(
".class#id {}",
base::SourceLocation("[object SelectorTreeTest]", 1, 1))
->AsCSSStyleRule();
scoped_refptr<CSSStyleRule> css_style_rule_2 =
css_parser->ParseRule(
"#id.class {}",
base::SourceLocation("[object SelectorTreeTest]", 1, 1))
->AsCSSStyleRule();
selector_tree.AppendRule(css_style_rule_1);
selector_tree.AppendRule(css_style_rule_2);
ASSERT_EQ(
0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
ASSERT_EQ(1,
selector_tree.children(selector_tree.root(), kDescendantCombinator)
.size());
ASSERT_EQ(0,
selector_tree.children(selector_tree.root(), kNextSiblingCombinator)
.size());
ASSERT_EQ(0, selector_tree.children(selector_tree.root(),
kFollowingSiblingCombinator)
.size());
}
TEST(SelectorTreeTest, AppendRuleSimpleShouldTakeTwoIdenticalRules) {
SelectorTree selector_tree;
// Selector Tree:
// root
// kDescendantCombinator -> node_1("div")
scoped_ptr<css_parser::Parser> css_parser = css_parser::Parser::Create();
scoped_refptr<CSSStyleRule> css_style_rule_1 =
css_parser->ParseRule("div {}", base::SourceLocation(
"[object SelectorTreeTest]", 1, 1))
->AsCSSStyleRule();
scoped_refptr<CSSStyleRule> css_style_rule_2 =
css_parser->ParseRule("div {}", base::SourceLocation(
"[object SelectorTreeTest]", 1, 1))
->AsCSSStyleRule();
selector_tree.AppendRule(css_style_rule_1);
selector_tree.AppendRule(css_style_rule_2);
ASSERT_EQ(
0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
ASSERT_EQ(1,
selector_tree.children(selector_tree.root(), kDescendantCombinator)
.size());
ASSERT_EQ(0,
selector_tree.children(selector_tree.root(), kNextSiblingCombinator)
.size());
ASSERT_EQ(0, selector_tree.children(selector_tree.root(),
kFollowingSiblingCombinator)
.size());
const SelectorTree::Node* node_1 =
selector_tree.children(selector_tree.root(), kDescendantCombinator)
.begin()
->second;
ASSERT_EQ(2, node_1->rules().size());
EXPECT_EQ(css_style_rule_1, node_1->rules()[0]);
EXPECT_EQ(css_style_rule_2, node_1->rules()[1]);
EXPECT_EQ(Specificity(0, 0, 1), node_1->cumulative_specificity());
}
TEST(SelectorTreeTest, AppendRuleSimpleShouldTakeTwoDesendantSelectors) {
SelectorTree selector_tree;
// Selector Tree:
// root
// kNone -> node_1("div")
// kChildCombinator -> node_2("span")
scoped_ptr<css_parser::Parser> css_parser = css_parser::Parser::Create();
scoped_refptr<CSSStyleRule> css_style_rule_1 =
css_parser->ParseRule("div {}", base::SourceLocation(
"[object SelectorTreeTest]", 1, 1))
->AsCSSStyleRule();
scoped_refptr<CSSStyleRule> css_style_rule_2 =
css_parser->ParseRule(
"div span {}",
base::SourceLocation("[object SelectorTreeTest]", 1, 1))
->AsCSSStyleRule();
selector_tree.AppendRule(css_style_rule_1);
selector_tree.AppendRule(css_style_rule_2);
ASSERT_EQ(
0, selector_tree.children(selector_tree.root(), kChildCombinator).size());
ASSERT_EQ(1,
selector_tree.children(selector_tree.root(), kDescendantCombinator)
.size());
ASSERT_EQ(0,
selector_tree.children(selector_tree.root(), kNextSiblingCombinator)
.size());
ASSERT_EQ(0, selector_tree.children(selector_tree.root(),
kFollowingSiblingCombinator)
.size());
const SelectorTree::Node* node_1 =
selector_tree.children(selector_tree.root(), kDescendantCombinator)
.begin()
->second;
ASSERT_EQ(1, node_1->rules().size());
EXPECT_EQ(css_style_rule_1, node_1->rules()[0]);
EXPECT_EQ(Specificity(0, 0, 1), node_1->cumulative_specificity());
ASSERT_EQ(0, selector_tree.children(node_1, kChildCombinator).size());
ASSERT_EQ(1, selector_tree.children(node_1, kDescendantCombinator).size());
ASSERT_EQ(0, selector_tree.children(node_1, kNextSiblingCombinator).size());
ASSERT_EQ(0,
selector_tree.children(node_1, kFollowingSiblingCombinator).size());
const SelectorTree::Node* node_2 =
selector_tree.children(node_1, kDescendantCombinator).begin()->second;
ASSERT_EQ(1, node_2->rules().size());
EXPECT_EQ(css_style_rule_2, node_2->rules()[0]);
EXPECT_EQ(Specificity(0, 0, 2), node_2->cumulative_specificity());
}
} // namespace cssom
} // namespace cobalt