blob: 4854f5ee1fc594bfd5df244e2b9afafe5e59358c [file] [log] [blame]
// Copyright 2014 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 <cmath>
#include <string>
#include <vector>
#include "base/bind.h"
#include "cobalt/cssom/active_pseudo_class.h"
#include "cobalt/cssom/after_pseudo_element.h"
#include "cobalt/cssom/attribute_selector.h"
#include "cobalt/cssom/before_pseudo_element.h"
#include "cobalt/cssom/child_combinator.h"
#include "cobalt/cssom/class_selector.h"
#include "cobalt/cssom/complex_selector.h"
#include "cobalt/cssom/compound_selector.h"
#include "cobalt/cssom/css_declared_style_data.h"
#include "cobalt/cssom/css_font_face_declaration_data.h"
#include "cobalt/cssom/css_font_face_rule.h"
#include "cobalt/cssom/css_keyframe_rule.h"
#include "cobalt/cssom/css_keyframes_rule.h"
#include "cobalt/cssom/css_rule_list.h"
#include "cobalt/cssom/css_style_rule.h"
#include "cobalt/cssom/css_style_sheet.h"
#include "cobalt/cssom/descendant_combinator.h"
#include "cobalt/cssom/empty_pseudo_class.h"
#include "cobalt/cssom/filter_function_list_value.h"
#include "cobalt/cssom/focus_pseudo_class.h"
#include "cobalt/cssom/following_sibling_combinator.h"
#include "cobalt/cssom/font_style_value.h"
#include "cobalt/cssom/font_weight_value.h"
#include "cobalt/cssom/hover_pseudo_class.h"
#include "cobalt/cssom/id_selector.h"
#include "cobalt/cssom/integer_value.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/cssom/length_value.h"
#include "cobalt/cssom/linear_gradient_value.h"
#include "cobalt/cssom/local_src_value.h"
#include "cobalt/cssom/map_to_mesh_function.h"
#include "cobalt/cssom/matrix_function.h"
#include "cobalt/cssom/media_list.h"
#include "cobalt/cssom/media_query.h"
#include "cobalt/cssom/next_sibling_combinator.h"
#include "cobalt/cssom/not_pseudo_class.h"
#include "cobalt/cssom/number_value.h"
#include "cobalt/cssom/percentage_value.h"
#include "cobalt/cssom/property_definitions.h"
#include "cobalt/cssom/property_key_list_value.h"
#include "cobalt/cssom/property_list_value.h"
#include "cobalt/cssom/property_value_visitor.h"
#include "cobalt/cssom/radial_gradient_value.h"
#include "cobalt/cssom/rgba_color_value.h"
#include "cobalt/cssom/rotate_function.h"
#include "cobalt/cssom/scale_function.h"
#include "cobalt/cssom/shadow_value.h"
#include "cobalt/cssom/simple_selector.h"
#include "cobalt/cssom/string_value.h"
#include "cobalt/cssom/time_list_value.h"
#include "cobalt/cssom/timing_function.h"
#include "cobalt/cssom/timing_function_list_value.h"
#include "cobalt/cssom/transform_function_list_value.h"
#include "cobalt/cssom/translate_function.h"
#include "cobalt/cssom/type_selector.h"
#include "cobalt/cssom/unicode_range_value.h"
#include "cobalt/cssom/universal_selector.h"
#include "cobalt/cssom/url_src_value.h"
#include "cobalt/cssom/url_value.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cobalt {
namespace css_parser {
using ::testing::_;
using ::testing::AtLeast;
class MockParserObserver {
public:
MOCK_METHOD1(OnWarning, void(const std::string& message));
MOCK_METHOD1(OnError, void(const std::string& message));
};
class ParserTestBase : public ::testing::Test {
public:
explicit ParserTestBase(Parser::SupportsMapToMeshFlag supports_map_to_mesh);
~ParserTestBase() override {}
protected:
::testing::StrictMock<MockParserObserver> parser_observer_;
Parser parser_;
const base::SourceLocation source_location_;
};
ParserTestBase::ParserTestBase(
Parser::SupportsMapToMeshFlag supports_map_to_mesh)
: parser_(base::Bind(&MockParserObserver::OnWarning,
base::Unretained(&parser_observer_)),
base::Bind(&MockParserObserver::OnError,
base::Unretained(&parser_observer_)),
Parser::kShort, supports_map_to_mesh),
source_location_("[object ParserTest]", 1, 1) {}
class ParserTest : public ParserTestBase {
public:
ParserTest() : ParserTestBase(Parser::kSupportsMapToMesh) {}
};
class ParserNoMapToMeshTest : public ParserTestBase {
public:
ParserNoMapToMeshTest() : ParserTestBase(Parser::kDoesNotSupportMapToMesh) {}
};
// TODO: Test every reduction that has semantic action.
TEST_F(ParserTest, ParsesEmptyInput) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("", source_location_);
ASSERT_TRUE(style_sheet);
EXPECT_EQ(0, style_sheet->css_rules_same_origin()->length());
}
TEST_F(ParserTest, HandlesInvalidAtRuleEndsWithSemicolons) {
EXPECT_CALL(
parser_observer_,
OnWarning(
"[object ParserTest]:1:1: warning: invalid rule @casino-royale"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("@casino-royale;", source_location_);
ASSERT_TRUE(style_sheet);
EXPECT_EQ(0, style_sheet->css_rules_same_origin()->length());
}
TEST_F(ParserTest, HandlesInvalidAtRuleWithoutSemicolonsAtTheEndOfFile) {
EXPECT_CALL(
parser_observer_,
OnWarning(
"[object ParserTest]:1:1: warning: invalid rule @casino-royale"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("@casino-royale", source_location_);
ASSERT_TRUE(style_sheet);
EXPECT_EQ(0, style_sheet->css_rules_same_origin()->length());
}
TEST_F(ParserTest, HandlesInvalidAtRuleWithNoMatchingEndBrace) {
EXPECT_CALL(
parser_observer_,
OnWarning(
"[object ParserTest]:1:1: warning: invalid rule @casino-royale"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("@casino-royale }", source_location_);
ASSERT_TRUE(style_sheet);
EXPECT_EQ(0, style_sheet->css_rules_same_origin()->length());
}
TEST_F(ParserTest, ComputesErrorLocationOnFirstLine) {
EXPECT_CALL(
parser_observer_,
OnError("[object ParserTest]:10:18: error: unrecoverable syntax error"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet = parser_.ParseStyleSheet(
"cucumber", base::SourceLocation("[object ParserTest]", 10, 10));
ASSERT_TRUE(style_sheet);
EXPECT_EQ(0, style_sheet->css_rules_same_origin()->length());
}
TEST_F(ParserTest, ComputesErrorLocationOnSecondLine) {
EXPECT_CALL(
parser_observer_,
OnError("[object ParserTest]:11:9: error: unrecoverable syntax error"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet = parser_.ParseStyleSheet(
"\n"
"cucumber",
base::SourceLocation("[object ParserTest]", 10, 10));
ASSERT_TRUE(style_sheet);
EXPECT_EQ(0, style_sheet->css_rules_same_origin()->length());
}
TEST_F(ParserTest, IgnoresSgmlCommentDelimiters) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("<!-- body {} -->", source_location_);
ASSERT_TRUE(style_sheet);
EXPECT_EQ(1, style_sheet->css_rules_same_origin()->length());
}
TEST_F(ParserTest, RecoversFromInvalidAtToken) {
EXPECT_CALL(
parser_observer_,
OnWarning(
"[object ParserTest]:1:9: warning: invalid rule @cobalt-magic"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet = parser_.ParseStyleSheet(
"body {} @cobalt-magic; div {}", source_location_);
ASSERT_TRUE(style_sheet);
EXPECT_EQ(2, style_sheet->css_rules_same_origin()->length());
}
TEST_F(ParserTest, RecoversFromInvalidRuleWhichEndsWithSemicolon) {
EXPECT_CALL(
parser_observer_,
OnWarning("[object ParserTest]:1:9: warning: invalid rule @charset"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet = parser_.ParseStyleSheet(
"body {} @charset 'utf-8'; div {}", source_location_);
ASSERT_TRUE(style_sheet);
EXPECT_EQ(2, style_sheet->css_rules_same_origin()->length());
}
TEST_F(ParserTest, RecoversFromInvalidRuleWhichEndsWithBlock) {
EXPECT_CALL(
parser_observer_,
OnWarning("[object ParserTest]:1:9: warning: invalid qualified rule"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("body {} !important {} div {}", source_location_);
ASSERT_TRUE(style_sheet);
EXPECT_EQ(2, style_sheet->css_rules_same_origin()->length());
}
TEST_F(ParserTest, SemicolonsDonotEndQualifiedRules) {
EXPECT_CALL(
parser_observer_,
OnWarning("[object ParserTest]:1:1: warning: invalid qualified rule"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("foo; bar {} div {}", source_location_);
ASSERT_TRUE(style_sheet);
EXPECT_EQ(1, style_sheet->css_rules_same_origin()->length());
}
TEST_F(ParserTest, ParsesAttributeSelectorNoValue) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("[attr] {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::AttributeSelector* attribute_selector =
dynamic_cast<cssom::AttributeSelector*>(
const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(attribute_selector);
EXPECT_EQ("attr", attribute_selector->attribute_name());
}
TEST_F(ParserTest, ParsesAttributeSelectorValueWithQuotes) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("[attr=\"value\"] {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::AttributeSelector* attribute_selector =
dynamic_cast<cssom::AttributeSelector*>(
const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(attribute_selector);
EXPECT_EQ("attr", attribute_selector->attribute_name());
EXPECT_EQ("value", attribute_selector->attribute_value());
}
TEST_F(ParserTest, ParsesAttributeSelectorValueWithoutQuotes) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("[attr=value] {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::AttributeSelector* attribute_selector =
dynamic_cast<cssom::AttributeSelector*>(
const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(attribute_selector);
EXPECT_EQ("attr", attribute_selector->attribute_name());
EXPECT_EQ("value", attribute_selector->attribute_value());
}
TEST_F(ParserTest, ParsesClassSelector) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet(".my-class {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::ClassSelector* class_selector =
dynamic_cast<cssom::ClassSelector*>(const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(class_selector);
EXPECT_EQ("my-class", class_selector->class_name());
}
TEST_F(ParserTest, ParsesAfterPseudoElementCSS2) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet(":after {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::AfterPseudoElement* after_pseudo_element =
dynamic_cast<cssom::AfterPseudoElement*>(
const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(after_pseudo_element);
}
TEST_F(ParserTest, ParsesAfterPseudoElementCSS3) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("::after {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::AfterPseudoElement* after_pseudo_element =
dynamic_cast<cssom::AfterPseudoElement*>(
const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(after_pseudo_element);
}
TEST_F(ParserTest, ParsesBeforePseudoElementCSS2) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet(":before {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::BeforePseudoElement* before_pseudo_element =
dynamic_cast<cssom::BeforePseudoElement*>(
const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(before_pseudo_element);
}
TEST_F(ParserTest, ParsesBeforePseudoElementCSS3) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("::before {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::BeforePseudoElement* before_pseudo_element =
dynamic_cast<cssom::BeforePseudoElement*>(
const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(before_pseudo_element);
}
TEST_F(ParserTest, ParsesActivePseudoClass) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet(":active {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::ActivePseudoClass* active_pseudo_class =
dynamic_cast<cssom::ActivePseudoClass*>(
const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(active_pseudo_class);
}
TEST_F(ParserTest, ParsesEmptyPseudoClass) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet(":empty {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::EmptyPseudoClass* empty_pseudo_class =
dynamic_cast<cssom::EmptyPseudoClass*>(const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(empty_pseudo_class);
}
TEST_F(ParserTest, ParsesFocusPseudoClass) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet(":focus {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::FocusPseudoClass* focus_pseudo_class =
dynamic_cast<cssom::FocusPseudoClass*>(const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(focus_pseudo_class);
}
TEST_F(ParserTest, ParsesHoverPseudoClass) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet(":hover {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::HoverPseudoClass* hover_pseudo_class =
dynamic_cast<cssom::HoverPseudoClass*>(const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(hover_pseudo_class);
}
TEST_F(ParserTest, ParsesNotPseudoClass) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet(":not(div.my-class) {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::NotPseudoClass* not_pseudo_class =
dynamic_cast<cssom::NotPseudoClass*>(const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(not_pseudo_class);
// Check the selector within :not pseudo class.
cssom::CompoundSelector* not_compound_selector = not_pseudo_class->selector();
ASSERT_TRUE(not_compound_selector);
ASSERT_EQ(2, not_compound_selector->simple_selectors().size());
cssom::TypeSelector* type_selector =
dynamic_cast<cssom::TypeSelector*>(const_cast<cssom::SimpleSelector*>(
not_compound_selector->simple_selectors()[0]));
ASSERT_TRUE(type_selector);
EXPECT_EQ("div", type_selector->element_name());
cssom::ClassSelector* class_selector =
dynamic_cast<cssom::ClassSelector*>(const_cast<cssom::SimpleSelector*>(
not_compound_selector->simple_selectors()[1]));
ASSERT_TRUE(class_selector);
EXPECT_EQ("my-class", class_selector->class_name());
}
TEST_F(ParserTest, ParsesNotPseudoClassShouldNotTakeEmptyParameter) {
EXPECT_CALL(parser_observer_,
OnWarning("[object ParserTest]:1:1: warning: unsupported "
"selector within :not()"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet(":not() {}", source_location_);
EXPECT_EQ(0, style_sheet->css_rules_same_origin()->length());
}
TEST_F(ParserTest, ParsesNotPseudoClassShouldNotTakeComplexSelector) {
EXPECT_CALL(parser_observer_,
OnWarning("[object ParserTest]:1:1: warning: unsupported "
"selector within :not()"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet(":not(div span) {}", source_location_);
EXPECT_EQ(0, style_sheet->css_rules_same_origin()->length());
}
TEST_F(ParserTest, ParsesIdSelector) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("#my-id {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::IdSelector* id_selector =
dynamic_cast<cssom::IdSelector*>(const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(id_selector);
EXPECT_EQ("my-id", id_selector->id());
}
TEST_F(ParserTest, ParsesTypeSelector) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("div {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::TypeSelector* type_selector =
dynamic_cast<cssom::TypeSelector*>(const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(type_selector);
EXPECT_EQ("div", type_selector->element_name());
}
TEST_F(ParserTest, ParsesUniversalSelector) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("* {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(1, compound_selector->simple_selectors().size());
cssom::UniversalSelector* universal_selector =
dynamic_cast<cssom::UniversalSelector*>(
const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(universal_selector);
}
TEST_F(ParserTest, ParsesCompoundSelector) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("div.my-class {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
cssom::CompoundSelector* compound_selector =
complex_selector->first_selector();
ASSERT_TRUE(compound_selector);
ASSERT_EQ(2, compound_selector->simple_selectors().size());
cssom::TypeSelector* type_selector =
dynamic_cast<cssom::TypeSelector*>(const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[0]));
ASSERT_TRUE(type_selector);
EXPECT_EQ("div", type_selector->element_name());
cssom::ClassSelector* class_selector =
dynamic_cast<cssom::ClassSelector*>(const_cast<cssom::SimpleSelector*>(
compound_selector->simple_selectors()[1]));
ASSERT_TRUE(class_selector);
EXPECT_EQ("my-class", class_selector->class_name());
}
TEST_F(ParserTest, ParsesComplexSelectorDescendantCombinator) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("div div {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
ASSERT_TRUE(complex_selector->first_selector());
cssom::CompoundSelector* selector = complex_selector->first_selector();
ASSERT_TRUE(selector->right_combinator());
EXPECT_EQ(cssom::kDescendantCombinator,
selector->right_combinator()->GetCombinatorType());
}
TEST_F(ParserTest, ParsesComplexSelectorFollowingSiblingCombinator) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("div ~ div {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
ASSERT_TRUE(complex_selector->first_selector());
cssom::CompoundSelector* selector = complex_selector->first_selector();
ASSERT_TRUE(selector->right_combinator());
EXPECT_EQ(cssom::kFollowingSiblingCombinator,
selector->right_combinator()->GetCombinatorType());
}
TEST_F(ParserTest, ParsesComplexSelectorChildCombinator) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("div > div {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
ASSERT_TRUE(complex_selector->first_selector());
cssom::CompoundSelector* selector = complex_selector->first_selector();
ASSERT_TRUE(selector->right_combinator());
EXPECT_EQ(cssom::kChildCombinator,
selector->right_combinator()->GetCombinatorType());
}
TEST_F(ParserTest, ParsesComplexSelectorNextSiblingCombinator) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("div + div {}", source_location_);
ASSERT_EQ(1, style_sheet->css_rules_same_origin()->length());
ASSERT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
cssom::CSSStyleRule* style_rule = static_cast<cssom::CSSStyleRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_EQ(1, style_rule->selectors().size());
cssom::ComplexSelector* complex_selector =
dynamic_cast<cssom::ComplexSelector*>(
const_cast<cssom::Selector*>(style_rule->selectors()[0]));
ASSERT_TRUE(complex_selector);
ASSERT_TRUE(complex_selector->first_selector());
cssom::CompoundSelector* selector = complex_selector->first_selector();
ASSERT_TRUE(selector->right_combinator());
EXPECT_EQ(cssom::kNextSiblingCombinator,
selector->right_combinator()->GetCombinatorType());
}
TEST_F(ParserTest, ParsesDeclarationListWithTrailingSemicolon) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"color: #0047ab; /* Cobalt blue */\n"
"font-size: 100px;\n",
source_location_);
EXPECT_TRUE(style->GetPropertyValue(cssom::kColorProperty));
EXPECT_TRUE(style->GetPropertyValue(cssom::kFontSizeProperty));
}
TEST_F(ParserTest, ParsesDeclarationListWithoutTrailingSemicolon) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"color: #0047ab;\n"
"font-size: 100px\n",
source_location_);
EXPECT_TRUE(style->GetPropertyValue(cssom::kColorProperty));
EXPECT_TRUE(style->GetPropertyValue(cssom::kFontSizeProperty));
}
TEST_F(ParserTest, ParsesDeclarationListWithEmptyDeclaration) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"color: #0047ab;\n"
";\n"
"font-size: 100px;\n",
source_location_);
EXPECT_TRUE(style->GetPropertyValue(cssom::kColorProperty));
EXPECT_TRUE(style->GetPropertyValue(cssom::kFontSizeProperty));
}
TEST_F(ParserTest, RecoversFromInvalidPropertyDeclaration) {
EXPECT_CALL(
parser_observer_,
OnWarning("[object ParserTest]:2:1: warning: invalid declaration"));
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"color: #0047ab;\n"
"1px;\n"
"font-size: 100px;\n",
source_location_);
EXPECT_TRUE(style->GetPropertyValue(cssom::kColorProperty));
EXPECT_TRUE(style->GetPropertyValue(cssom::kFontSizeProperty));
}
TEST_F(ParserTest, HandlesUnsupportedPropertyInStyleDeclarationList) {
EXPECT_CALL(
parser_observer_,
OnWarning(
"[object ParserTest]:1:1: warning: unsupported style property: src"));
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("src: initial;", source_location_);
EXPECT_EQ(style->length(), 0);
}
TEST_F(ParserTest,
HandlesUnsupportedPropertyInStyleDeclarationListWithSupportedProperty) {
EXPECT_CALL(parser_observer_,
OnWarning("[object ParserTest]:1:1: warning: unsupported style "
"property: unicode-range"));
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("width: 100px; unicode-range: U+100;",
source_location_);
EXPECT_EQ(style->length(), 1);
scoped_refptr<cssom::LengthValue> width = dynamic_cast<cssom::LengthValue*>(
style->GetPropertyValue(cssom::kWidthProperty).get());
ASSERT_TRUE(width);
EXPECT_EQ(100, width->value());
EXPECT_EQ(cssom::kPixelsUnit, width->unit());
}
TEST_F(ParserTest, SilentlyIgnoresNonWebKitProperties) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"-moz-transform: scale(2);\n"
"-ms-transform: scale(2);\n"
"-o-transform: scale(2);\n"
"transform: scale(2);\n",
source_location_);
EXPECT_TRUE(style->GetPropertyValue(cssom::kTransformProperty));
}
TEST_F(ParserTest, WarnsAboutInvalidDeclaration) {
EXPECT_CALL(
parser_observer_,
OnWarning("[object ParserTest]:1:1: warning: unsupported property pony"));
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"pony: rainbowdash;\n"
"color: #9edbf9;\n",
source_location_);
scoped_refptr<cssom::RGBAColorValue> color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kColorProperty).get());
ASSERT_TRUE(color);
EXPECT_EQ(0x9edbf9ff, color->value());
}
TEST_F(ParserTest, WarnsAboutInvalidDeclarationAtTheEndOfBlock) {
EXPECT_CALL(parser_observer_, OnWarning("[object ParserTest]:1:10: warning: "
"unsupported property hallelujah"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet = parser_.ParseStyleSheet(
":empty { hallelujah: rainbowdash }", source_location_);
}
TEST_F(ParserTest, WarnsAboutInvalidPropertyValues) {
EXPECT_CALL(
parser_observer_,
OnWarning("[object ParserTest]:1:19: warning: unsupported value"));
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background-color: morning haze over Paris;\n"
"color: #fff;\n",
source_location_);
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundColorProperty));
EXPECT_TRUE(style->GetPropertyValue(cssom::kColorProperty));
}
TEST_F(ParserTest, WarnsAboutInvalidAtRule) {
EXPECT_CALL(
parser_observer_,
OnWarning("[object ParserTest]:1:1: warning: invalid rule @wuli-style"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet = parser_.ParseStyleSheet(
"@wuli-style winners-list {"
" from ["
" opacity: 0.6;"
" ]"
" to ["
" opacity: 0.8;"
" ]"
"}\n"
"#my-id {} \n",
source_location_);
EXPECT_EQ(1, style_sheet->css_rules_same_origin()->length());
EXPECT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
}
TEST_F(ParserTest, WarnsAboutInvalidAtRuleCurlyBraceInsideOfAnotherBlock) {
EXPECT_CALL(
parser_observer_,
OnWarning("[object ParserTest]:1:1: warning: invalid rule @foo-style"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet = parser_.ParseStyleSheet(
"@foo-style winners-list {"
" from ["
" opacity: 0.6; }"
" ]"
" to ["
" opacity: 0.8;"
" ]"
"}\n"
"#my-id {} \n",
source_location_);
EXPECT_EQ(1, style_sheet->css_rules_same_origin()->length());
EXPECT_EQ(cssom::CSSRule::kStyleRule,
style_sheet->css_rules_same_origin()->Item(0)->type());
}
TEST_F(ParserTest, StyleSheetEndsWhileRuleIsStillOpen) {
scoped_refptr<cssom::CSSStyleSheet> style_sheet = parser_.ParseStyleSheet(
"@keyframes foo3 {"
" from {"
" opacity: 0.6;"
" }"
" to {"
" opacity: 0.8;",
source_location_);
ASSERT_TRUE(style_sheet);
EXPECT_EQ(1, style_sheet->css_rules_same_origin()->length());
cssom::CSSKeyframesRule* keyframes_rule =
dynamic_cast<cssom::CSSKeyframesRule*>(
style_sheet->css_rules_same_origin()->Item(0).get());
ASSERT_TRUE(keyframes_rule);
EXPECT_EQ("foo3", keyframes_rule->name());
ASSERT_EQ(2, keyframes_rule->css_rules()->length());
}
TEST_F(ParserTest, StyleSheetEndsWhileUnrecognizedAtRuleIsStillOpen) {
EXPECT_CALL(
parser_observer_,
OnWarning(
"[object ParserTest]:1:1: warning: invalid rule @user-defined"));
scoped_refptr<cssom::CSSStyleSheet> style_sheet =
parser_.ParseStyleSheet("@user-defined { abc[", source_location_);
}
TEST_F(ParserTest, StyleSheetEndsWhileDeclarationIsStillOpen) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: inherit",
source_location_);
EXPECT_EQ(cssom::KeywordValue::GetInherit(),
style->GetPropertyValue(cssom::kBackgroundColorProperty));
}
TEST_F(ParserTest, StyleSheetEndsWhileUrlIsStillOpen) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-image: url(foo.png",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::URLValue> url_value =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[0].get());
EXPECT_EQ("foo.png", url_value->value());
}
TEST_F(ParserTest, StyleSheetEndsWhileFunctionIsStillOpen) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("transform: translateX(20%",
source_location_);
scoped_refptr<cssom::TransformFunctionListValue> transform_list =
dynamic_cast<cssom::TransformFunctionListValue*>(
style->GetPropertyValue(cssom::kTransformProperty).get());
ASSERT_TRUE(transform_list);
ASSERT_EQ(1, transform_list->value().size());
const cssom::TranslateFunction* translate_function =
dynamic_cast<const cssom::TranslateFunction*>(transform_list->value()[0]);
ASSERT_TRUE(translate_function);
ASSERT_EQ(cssom::TranslateFunction::kPercentage,
translate_function->offset_type());
scoped_refptr<cssom::PercentageValue> offset =
translate_function->offset_as_percentage();
EXPECT_FLOAT_EQ(0.2f, offset->value());
EXPECT_EQ(cssom::TranslateFunction::kXAxis, translate_function->axis());
}
TEST_F(ParserTest, ParsesInherit) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: inherit;",
source_location_);
EXPECT_EQ(cssom::KeywordValue::GetInherit(),
style->GetPropertyValue(cssom::kBackgroundColorProperty));
}
TEST_F(ParserTest, ParsesInitial) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: initial;",
source_location_);
EXPECT_EQ(cssom::KeywordValue::GetInitial(),
style->GetPropertyValue(cssom::kBackgroundColorProperty));
}
TEST_F(ParserTest, ParsesBackgroundWithOnlyColor) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background: rgba(0, 0, 0, .8);",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x000000cc, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundWithOnlyRepeat) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background: no-repeat;",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_repeat_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundRepeatProperty).get());
ASSERT_TRUE(background_repeat_list);
EXPECT_EQ(2, background_repeat_list->value().size());
EXPECT_EQ(cssom::KeywordValue::GetNoRepeat(),
background_repeat_list->value()[0]);
EXPECT_EQ(cssom::KeywordValue::GetNoRepeat(),
background_repeat_list->value()[1]);
}
TEST_F(ParserTest, ParsesBackgroundWithColorAndURL) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: url(foo.png) rgba(0, 0, 0, .8);", source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x000000cc, background_color->value());
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::URLValue> url_value =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[0].get());
EXPECT_EQ("foo.png", url_value->value());
}
TEST_F(ParserTest, ParsesBackgroundWithColorAndURLInDifferentOrder) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: rgba(0, 0, 0, .8) url(foo.png);", source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x000000cc, background_color->value());
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::URLValue> url_value =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[0].get());
EXPECT_EQ("foo.png", url_value->value());
}
TEST_F(ParserTest, ParsesBackgroundWithColorAndPosition) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: rgba(0, 0, 0, .8) 70px 45%;", source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x000000cc, background_color->value());
scoped_refptr<cssom::PropertyListValue> background_position_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundPositionProperty).get());
ASSERT_TRUE(background_position_list);
scoped_refptr<cssom::LengthValue> length_value_left =
dynamic_cast<cssom::LengthValue*>(
background_position_list->value()[0].get());
EXPECT_FLOAT_EQ(70, length_value_left->value());
EXPECT_EQ(cssom::kPixelsUnit, length_value_left->unit());
scoped_refptr<cssom::PercentageValue> percentage_value_right =
dynamic_cast<cssom::PercentageValue*>(
background_position_list->value()[1].get());
EXPECT_FLOAT_EQ(0.45f, percentage_value_right->value());
}
TEST_F(ParserTest, ParsesBackgroundWithColorAndPositionInDifferentOrder) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: 70px 45% rgba(0, 0, 0, .8);", source_location_);
scoped_refptr<cssom::PropertyListValue> background_position_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundPositionProperty).get());
ASSERT_TRUE(background_position_list);
scoped_refptr<cssom::LengthValue> length_value_left =
dynamic_cast<cssom::LengthValue*>(
background_position_list->value()[0].get());
EXPECT_FLOAT_EQ(70, length_value_left->value());
EXPECT_EQ(cssom::kPixelsUnit, length_value_left->unit());
scoped_refptr<cssom::PercentageValue> percentage_value_right =
dynamic_cast<cssom::PercentageValue*>(
background_position_list->value()[1].get());
EXPECT_FLOAT_EQ(0.45f, percentage_value_right->value());
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x000000cc, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundWithURLPositionAndSize) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: url(foo.png) center / 50px 80px;", source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::URLValue> url_value =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[0].get());
EXPECT_EQ("foo.png", url_value->value());
scoped_refptr<cssom::PropertyListValue> background_position_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundPositionProperty).get());
ASSERT_TRUE(background_position_list);
EXPECT_EQ(1, background_position_list->value().size());
EXPECT_EQ(cssom::KeywordValue::GetCenter(),
background_position_list->value()[0]);
scoped_refptr<cssom::PropertyListValue> background_size_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundSizeProperty).get());
ASSERT_TRUE(background_size_list);
scoped_refptr<cssom::LengthValue> size_value_left =
dynamic_cast<cssom::LengthValue*>(background_size_list->value()[0].get());
EXPECT_FLOAT_EQ(50, size_value_left->value());
EXPECT_EQ(cssom::kPixelsUnit, size_value_left->unit());
scoped_refptr<cssom::LengthValue> size_value_right =
dynamic_cast<cssom::LengthValue*>(background_size_list->value()[1].get());
EXPECT_FLOAT_EQ(80, size_value_right->value());
EXPECT_EQ(cssom::kPixelsUnit, size_value_right->unit());
}
TEST_F(ParserTest, ParsesBackgroundWithURLPositionAndSizeInDifferentOrder) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: center/50px 80px url(foo.png);", source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::URLValue> url_value =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[0].get());
EXPECT_EQ("foo.png", url_value->value());
scoped_refptr<cssom::PropertyListValue> background_position_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundPositionProperty).get());
ASSERT_TRUE(background_position_list);
EXPECT_EQ(1, background_position_list->value().size());
EXPECT_EQ(cssom::KeywordValue::GetCenter(),
background_position_list->value()[0]);
scoped_refptr<cssom::PropertyListValue> background_size_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundSizeProperty).get());
ASSERT_TRUE(background_size_list);
scoped_refptr<cssom::LengthValue> size_value_left =
dynamic_cast<cssom::LengthValue*>(background_size_list->value()[0].get());
EXPECT_FLOAT_EQ(50, size_value_left->value());
EXPECT_EQ(cssom::kPixelsUnit, size_value_left->unit());
scoped_refptr<cssom::LengthValue> size_value_right =
dynamic_cast<cssom::LengthValue*>(background_size_list->value()[1].get());
EXPECT_FLOAT_EQ(80, size_value_right->value());
EXPECT_EQ(cssom::kPixelsUnit, size_value_right->unit());
}
TEST_F(ParserTest, ParsesBackgroundWithURLNoRepeat) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background: url(foo.png) no-repeat",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::URLValue> url_value =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[0].get());
EXPECT_EQ("foo.png", url_value->value());
scoped_refptr<cssom::PropertyListValue> background_repeat =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundRepeatProperty).get());
ASSERT_TRUE(background_repeat);
EXPECT_EQ(cssom::KeywordValue::GetNoRepeat(), background_repeat->value()[0]);
EXPECT_EQ(cssom::KeywordValue::GetNoRepeat(), background_repeat->value()[1]);
}
TEST_F(ParserTest, ParsesBackgroundWithNoRepeatAndColor) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: no-repeat rgba(0, 0, 0, .8);", source_location_);
scoped_refptr<cssom::PropertyListValue> background_repeat =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundRepeatProperty).get());
ASSERT_TRUE(background_repeat);
EXPECT_EQ(cssom::KeywordValue::GetNoRepeat(), background_repeat->value()[0]);
EXPECT_EQ(cssom::KeywordValue::GetNoRepeat(), background_repeat->value()[1]);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x000000cc, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundWithBackgroundRepeatProperty) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: url(foo.png); background-repeat: no-repeat;",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::URLValue> url_value =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[0].get());
EXPECT_EQ("foo.png", url_value->value());
scoped_refptr<cssom::PropertyListValue> background_repeat =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundRepeatProperty).get());
ASSERT_TRUE(background_repeat);
}
TEST_F(ParserTest, ParsesBackgroundWithURLNoRepeatAndPosition) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: url(foo.png) center no-repeat", source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::URLValue> url_value =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[0].get());
EXPECT_EQ("foo.png", url_value->value());
scoped_refptr<cssom::PropertyListValue> background_position_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundPositionProperty).get());
ASSERT_TRUE(background_position_list);
EXPECT_EQ(1, background_position_list->value().size());
EXPECT_EQ(cssom::KeywordValue::GetCenter(),
background_position_list->value()[0]);
scoped_refptr<cssom::PropertyListValue> background_repeat =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundRepeatProperty).get());
ASSERT_TRUE(background_repeat);
EXPECT_EQ(cssom::KeywordValue::GetNoRepeat(), background_repeat->value()[0]);
EXPECT_EQ(cssom::KeywordValue::GetNoRepeat(), background_repeat->value()[1]);
}
TEST_F(ParserTest, ParsesBackgroundWithNoRepeatAndCenter) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background: no-repeat center",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_position_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundPositionProperty).get());
ASSERT_TRUE(background_position_list);
EXPECT_EQ(1, background_position_list->value().size());
EXPECT_EQ(cssom::KeywordValue::GetCenter(),
background_position_list->value()[0]);
scoped_refptr<cssom::PropertyListValue> background_repeat =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundRepeatProperty).get());
ASSERT_TRUE(background_repeat);
EXPECT_EQ(cssom::KeywordValue::GetNoRepeat(), background_repeat->value()[0]);
EXPECT_EQ(cssom::KeywordValue::GetNoRepeat(), background_repeat->value()[1]);
}
TEST_F(ParserTest, ParsesBackgroundWithNone) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background: none;", source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
EXPECT_EQ(cssom::KeywordValue::GetNone(), background_image_list->value()[0]);
}
TEST_F(ParserTest, ParsesBackgroundWithTransparent) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background: transparent;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x00000000, background_color->value());
}
TEST_F(ParserTest, InvalidBackgroundWithTwoPositions) {
EXPECT_CALL(parser_observer_,
OnError("[object ParserTest]:1:11: error: background-position or "
"background-repeat declared twice in background."));
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: 0 0 rgba(255,255,255,.1) 100%", source_location_);
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundColorProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundImageProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundPositionProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundRepeatProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundSizeProperty));
}
TEST_F(ParserTest, InvalidBackgroundWithTwoColors) {
EXPECT_CALL(parser_observer_,
OnError("[object ParserTest]:1:38: error: background-color value "
"declared twice in background."));
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: 0 0 rgba(255,255,255,.1) rgba(255,255,255,.1)",
source_location_);
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundColorProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundImageProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundPositionProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundRepeatProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundSizeProperty));
}
TEST_F(ParserTest, InvalidBackgroundWithTwoImages) {
EXPECT_CALL(parser_observer_,
OnError("[object ParserTest]:1:26: error: background-image value "
"declared twice in background."));
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background: url(foo.png) url(bar.png)",
source_location_);
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundColorProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundImageProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundPositionProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundRepeatProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundSizeProperty));
}
TEST_F(ParserTest, InvalidBackgroundWithTwoPositionsAndTwoColors) {
EXPECT_CALL(parser_observer_,
OnError("[object ParserTest]:1:11: error: background-position or "
"background-repeat declared twice in background."));
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: 0 0 rgba(255,255,255,.1) 100% rgba(255,255,255,.1) 100%",
source_location_);
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundColorProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundImageProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundPositionProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundRepeatProperty));
EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundSizeProperty));
}
TEST_F(ParserTest, LinearGradientWithOneColorStopIsError) {
EXPECT_CALL(
parser_observer_,
OnWarning("[object ParserTest]:1:11: warning: unsupported value"));
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: linear-gradient(to right, rgba(0,0,0,0.9));",
source_location_);
EXPECT_EQ(GetPropertyInitialValue(cssom::kBackgroundImageProperty),
style->GetPropertyValue(cssom::kBackgroundImageProperty));
}
TEST_F(ParserTest, LinearGradientWithInvalidColorStopIsError) {
EXPECT_CALL(
parser_observer_,
OnWarning("[object ParserTest]:1:11: warning: unsupported value"));
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: linear-gradient(#0123456789abcde 0%));",
source_location_);
EXPECT_EQ(GetPropertyInitialValue(cssom::kBackgroundImageProperty),
style->GetPropertyValue(cssom::kBackgroundImageProperty));
}
TEST_F(ParserTest, RadialGradientWithOneColorStopIsError) {
EXPECT_CALL(
parser_observer_,
OnWarning("[object ParserTest]:1:11: warning: unsupported value"));
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: radial-gradient(closest-corner, rgba(0,0,0,0.9));",
source_location_);
EXPECT_EQ(GetPropertyInitialValue(cssom::kBackgroundImageProperty),
style->GetPropertyValue(cssom::kBackgroundImageProperty));
}
TEST_F(ParserTest, ParsesBackgroundWithLinearGradient) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: linear-gradient(rgba(0,0,0,0.56), rgba(0,0,0,0.9));",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::LinearGradientValue> linear_gradient_value =
dynamic_cast<cssom::LinearGradientValue*>(
background_image_list->value()[0].get());
EXPECT_FALSE(linear_gradient_value->angle_in_radians());
EXPECT_EQ(cssom::LinearGradientValue::kBottom,
*linear_gradient_value->side_or_corner());
const cssom::ColorStopList& color_stop_list_value =
linear_gradient_value->color_stop_list();
EXPECT_EQ(2, color_stop_list_value.size());
float color_list[2] = {0x0000008E, 0x000000E5};
for (size_t i = 0; i < color_stop_list_value.size(); ++i) {
const cssom::ColorStop* color_stop_value = color_stop_list_value[i];
scoped_refptr<cssom::RGBAColorValue> color = color_stop_value->rgba();
ASSERT_TRUE(color);
EXPECT_EQ(color_list[i], color->value());
EXPECT_FALSE(color_stop_value->position());
}
}
TEST_F(ParserTest, ParsesBackgroundWithLinearGradientContainsTransparent) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: linear-gradient(to bottom, rgba(0,0,0,0.56), "
"rgba(0,0,0,0.9), transparent);",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::LinearGradientValue> linear_gradient_value =
dynamic_cast<cssom::LinearGradientValue*>(
background_image_list->value()[0].get());
EXPECT_FALSE(linear_gradient_value->angle_in_radians());
EXPECT_EQ(cssom::LinearGradientValue::kBottom,
*linear_gradient_value->side_or_corner());
const cssom::ColorStopList& color_stop_list_value =
linear_gradient_value->color_stop_list();
EXPECT_EQ(3, color_stop_list_value.size());
float color_list[3] = {0x0000008E, 0x000000E5, 0x00000000};
for (size_t i = 0; i < color_stop_list_value.size(); ++i) {
const cssom::ColorStop* color_stop_value = color_stop_list_value[i];
scoped_refptr<cssom::RGBAColorValue> color = color_stop_value->rgba();
ASSERT_TRUE(color);
EXPECT_EQ(color_list[i], color->value());
EXPECT_FALSE(color_stop_value->position());
}
}
TEST_F(ParserTest, ParsesBackgroundWithRadialGradient) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background: radial-gradient(closest-corner, "
"rgba(0,0,0,0.56), rgba(0,0,0,0.9));",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::RadialGradientValue> radial_gradient_value =
dynamic_cast<cssom::RadialGradientValue*>(
background_image_list->value()[0].get());
EXPECT_EQ(cssom::RadialGradientValue::kEllipse,
radial_gradient_value->shape());
EXPECT_EQ(cssom::RadialGradientValue::kClosestCorner,
radial_gradient_value->size_keyword());
EXPECT_FALSE(radial_gradient_value->size_value());
scoped_refptr<cssom::PropertyListValue> position =
radial_gradient_value->position();
EXPECT_FALSE(position);
const cssom::ColorStopList& color_stop_list_value =
radial_gradient_value->color_stop_list();
EXPECT_EQ(2, color_stop_list_value.size());
float color_list[2] = {0x0000008E, 0x000000E5};
for (size_t i = 0; i < color_stop_list_value.size(); ++i) {
const cssom::ColorStop* color_stop_value = color_stop_list_value[i];
scoped_refptr<cssom::RGBAColorValue> color = color_stop_value->rgba();
ASSERT_TRUE(color);
EXPECT_EQ(color_list[i], color->value());
EXPECT_FALSE(color_stop_value->position());
}
}
TEST_F(ParserTest, ParsesBackgroundColor) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: #fff;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0xffffffff, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordAqua) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: aqua;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x00FFFFFF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordBlack) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: black;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x000000FF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordBlue) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: blue;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x0000FFFF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordFuchsia) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: fuchsia;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0xFF00FFFF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordGray) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: gray;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x808080FF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordGreen) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: green;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x008000FF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordLime) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: lime;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x00FF00FF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordMaroon) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: maroon;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x800000FF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordNavy) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: navy;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x000080FF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordOlive) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: olive;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x808000FF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordPurple) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: purple;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x800080FF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordRed) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: red;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0xFF0000FF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordSilver) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: silver;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0xC0C0C0FF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordTeal) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: teal;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x008080FF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordTransparent) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: transparent;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0x00000000, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordWhite) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: white;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0xFFFFFFFF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordYellow) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: yellow;",
source_location_);
scoped_refptr<cssom::RGBAColorValue> background_color =
dynamic_cast<cssom::RGBAColorValue*>(
style->GetPropertyValue(cssom::kBackgroundColorProperty).get());
ASSERT_TRUE(background_color);
EXPECT_EQ(0xFFFF00FF, background_color->value());
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordInitial) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: initial;",
source_location_);
EXPECT_EQ(cssom::KeywordValue::GetInitial(),
style->GetPropertyValue(cssom::kBackgroundColorProperty));
}
TEST_F(ParserTest, ParsesBackgroundColorWithKeywordInherit) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-color: inherit;",
source_location_);
EXPECT_EQ(cssom::KeywordValue::GetInherit(),
style->GetPropertyValue(cssom::kBackgroundColorProperty));
}
TEST_F(ParserTest, ParsesBackgroundImageNone) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-image: none;",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
EXPECT_EQ(cssom::KeywordValue::GetNone(), background_image_list->value()[0]);
}
TEST_F(ParserTest, ParsesBackgroundImageInitial) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-image: initial;",
source_location_);
EXPECT_EQ(cssom::KeywordValue::GetInitial(),
style->GetPropertyValue(cssom::kBackgroundImageProperty));
}
TEST_F(ParserTest, ParsesBackgroundImageInherit) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-image: inherit;",
source_location_);
EXPECT_EQ(cssom::KeywordValue::GetInherit(),
style->GetPropertyValue(cssom::kBackgroundImageProperty));
}
TEST_F(ParserTest, ParsesSingleBackgroundImageURL) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-image: url(foo.png);",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::URLValue> url_value =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[0].get());
EXPECT_EQ("foo.png", url_value->value());
}
TEST_F(ParserTest, ParsesMultipleBackgroundImageURLs) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background-image: url(foo.png), url(bar.jpg), url(baz.png);",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(3, background_image_list->value().size());
scoped_refptr<cssom::URLValue> url_value_1 =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[0].get());
EXPECT_EQ("foo.png", url_value_1->value());
scoped_refptr<cssom::URLValue> url_value_2 =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[1].get());
EXPECT_EQ("bar.jpg", url_value_2->value());
scoped_refptr<cssom::URLValue> url_value_3 =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[2].get());
EXPECT_EQ("baz.png", url_value_3->value());
}
TEST_F(ParserTest, ParsesMultipleBackgroundImagesWithNone) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background-image: url(foo.png), none, url(baz.png);",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(3, background_image_list->value().size());
scoped_refptr<cssom::URLValue> url_value_1 =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[0].get());
EXPECT_EQ("foo.png", url_value_1->value());
EXPECT_EQ(cssom::KeywordValue::GetNone(), background_image_list->value()[1]);
scoped_refptr<cssom::URLValue> url_value_3 =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[2].get());
EXPECT_EQ("baz.png", url_value_3->value());
}
TEST_F(ParserTest, ParsesBackgroundImageLinearGradientWithDirection) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background-image: linear-gradient(180deg, rgba(34, 34, 34, 0) 50px,"
"rgba(34, 34, 34, 0) 100px);",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::LinearGradientValue> linear_gradient_value =
dynamic_cast<cssom::LinearGradientValue*>(
background_image_list->value()[0].get());
EXPECT_FLOAT_EQ(static_cast<float>(M_PI),
*linear_gradient_value->angle_in_radians());
EXPECT_FALSE(linear_gradient_value->side_or_corner());
const cssom::ColorStopList& color_stop_list_value =
linear_gradient_value->color_stop_list();
EXPECT_EQ(2, color_stop_list_value.size());
float percentage_list[2] = {50.0f, 100.0f};
for (size_t i = 0; i < color_stop_list_value.size(); ++i) {
const cssom::ColorStop* color_stop_value = color_stop_list_value[i];
scoped_refptr<cssom::RGBAColorValue> color = color_stop_value->rgba();
ASSERT_TRUE(color);
EXPECT_EQ(0x22222200, color->value());
scoped_refptr<cssom::LengthValue> position =
dynamic_cast<cssom::LengthValue*>(color_stop_value->position().get());
EXPECT_FLOAT_EQ(percentage_list[i], position->value());
EXPECT_EQ(cssom::kPixelsUnit, position->unit());
}
}
TEST_F(ParserTest, ParsesBackgroundImageLinearGradientWithoutDirection) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background-image: linear-gradient(rgba(34, 34, 34, 0),"
"rgba(34, 34, 34, 0) 60%);",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::LinearGradientValue> linear_gradient_value =
dynamic_cast<cssom::LinearGradientValue*>(
background_image_list->value()[0].get());
EXPECT_FALSE(linear_gradient_value->angle_in_radians());
EXPECT_EQ(cssom::LinearGradientValue::kBottom,
*linear_gradient_value->side_or_corner());
const cssom::ColorStopList& color_stop_list_value =
linear_gradient_value->color_stop_list();
EXPECT_EQ(2, color_stop_list_value.size());
for (size_t i = 0; i < color_stop_list_value.size(); ++i) {
const cssom::ColorStop* color_stop_value = color_stop_list_value[i];
scoped_refptr<cssom::RGBAColorValue> color = color_stop_value->rgba();
ASSERT_TRUE(color);
EXPECT_EQ(0x22222200, color->value());
if (i == 0) {
EXPECT_FALSE(color_stop_value->position());
} else {
scoped_refptr<cssom::PercentageValue> position =
dynamic_cast<cssom::PercentageValue*>(
color_stop_value->position().get());
EXPECT_FLOAT_EQ(0.6f, position->value());
}
}
}
TEST_F(ParserTest, ParsesBackgroundImageLinearGradientAndURL) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background-image: linear-gradient(to right top, "
"rgba(34, 34, 34, 0) 0%, rgba(34, 34, 34, 0) 80px), url(foo.png), "
"url(bar.jpg);",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(3, background_image_list->value().size());
scoped_refptr<cssom::LinearGradientValue> linear_gradient_value =
dynamic_cast<cssom::LinearGradientValue*>(
background_image_list->value()[0].get());
EXPECT_FALSE(linear_gradient_value->angle_in_radians());
EXPECT_EQ(cssom::LinearGradientValue::kTopRight,
*linear_gradient_value->side_or_corner());
const cssom::ColorStopList& color_stop_list_value =
linear_gradient_value->color_stop_list();
EXPECT_EQ(2, color_stop_list_value.size());
for (size_t i = 0; i < color_stop_list_value.size(); ++i) {
const cssom::ColorStop* color_stop_value = color_stop_list_value[i];
scoped_refptr<cssom::RGBAColorValue> color = color_stop_value->rgba();
ASSERT_TRUE(color);
EXPECT_EQ(0x22222200, color->value());
if (i == 0) {
scoped_refptr<cssom::PercentageValue> position =
dynamic_cast<cssom::PercentageValue*>(
color_stop_value->position().get());
EXPECT_FLOAT_EQ(0.0f, position->value());
} else {
scoped_refptr<cssom::LengthValue> position =
dynamic_cast<cssom::LengthValue*>(color_stop_value->position().get());
EXPECT_FLOAT_EQ(80.0f, position->value());
EXPECT_EQ(cssom::kPixelsUnit, position->unit());
}
}
scoped_refptr<cssom::URLValue> background_image_1 =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[1].get());
ASSERT_TRUE(background_image_1);
EXPECT_EQ("foo.png", background_image_1->value());
scoped_refptr<cssom::URLValue> background_image_2 =
dynamic_cast<cssom::URLValue*>(background_image_list->value()[2].get());
ASSERT_TRUE(background_image_2);
EXPECT_EQ("bar.jpg", background_image_2->value());
}
TEST_F(ParserTest, ParsesBackgroundImageRadialGradientWithShapeAndSizeKeyword) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background-image: radial-gradient(ellipse closest-side, "
"rgba(0,0,0,0.2) 25%, rgba(0,0,0,0.1) 60%, rgba(0,0,0,0));",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::RadialGradientValue> radial_gradient_value =
dynamic_cast<cssom::RadialGradientValue*>(
background_image_list->value()[0].get());
EXPECT_EQ(cssom::RadialGradientValue::kEllipse,
radial_gradient_value->shape());
EXPECT_EQ(cssom::RadialGradientValue::kClosestSide,
radial_gradient_value->size_keyword());
EXPECT_FALSE(radial_gradient_value->size_value());
scoped_refptr<cssom::PropertyListValue> position =
radial_gradient_value->position();
EXPECT_FALSE(position);
const cssom::ColorStopList& color_stop_list_value =
radial_gradient_value->color_stop_list();
EXPECT_EQ(3, color_stop_list_value.size());
uint32 color_list[3] = {0x00000033, 0x00000019, 0x00000000};
float color_stop_position_list[2] = {0.25f, 0.6f};
for (size_t i = 0; i < color_stop_list_value.size(); ++i) {
const cssom::ColorStop* color_stop_value = color_stop_list_value[i];
scoped_refptr<cssom::RGBAColorValue> color = color_stop_value->rgba();
ASSERT_TRUE(color);
EXPECT_EQ(color_list[i], color->value());
if (i < 2) {
scoped_refptr<cssom::PercentageValue> position_value =
dynamic_cast<cssom::PercentageValue*>(
color_stop_value->position().get());
EXPECT_FLOAT_EQ(color_stop_position_list[i], position_value->value());
} else {
EXPECT_FALSE(color_stop_value->position());
}
}
}
TEST_F(ParserTest,
ParsesBackgroundImageRadialGradientWithShapeSizeLengthAndPosition) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background-image: radial-gradient(circle 20px at top center, "
"rgba(0,0,0,0.2) 25%, rgba(0,0,0,0.1) 60%);",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::RadialGradientValue> radial_gradient_value =
dynamic_cast<cssom::RadialGradientValue*>(
background_image_list->value()[0].get());
EXPECT_EQ(cssom::RadialGradientValue::kCircle,
radial_gradient_value->shape());
EXPECT_FALSE(radial_gradient_value->size_keyword());
scoped_refptr<cssom::PropertyListValue> size =
radial_gradient_value->size_value();
ASSERT_TRUE(size);
EXPECT_EQ(1, size->value().size());
scoped_refptr<cssom::LengthValue> size_value =
dynamic_cast<cssom::LengthValue*>(size->value()[0].get());
EXPECT_FLOAT_EQ(20.0f, size_value->value());
EXPECT_EQ(cssom::kPixelsUnit, size_value->unit());
scoped_refptr<cssom::PropertyListValue> position =
radial_gradient_value->position();
ASSERT_TRUE(position);
EXPECT_EQ(2, position->value().size());
EXPECT_EQ(cssom::KeywordValue::GetTop(), position->value()[0]);
EXPECT_EQ(cssom::KeywordValue::GetCenter(), position->value()[1]);
const cssom::ColorStopList& color_stop_list_value =
radial_gradient_value->color_stop_list();
EXPECT_EQ(2, color_stop_list_value.size());
uint32 color_list[2] = {0x00000033, 0x00000019};
float color_stop_position_list[2] = {0.25f, 0.6f};
for (size_t i = 0; i < color_stop_list_value.size(); ++i) {
const cssom::ColorStop* color_stop_value = color_stop_list_value[i];
scoped_refptr<cssom::RGBAColorValue> color = color_stop_value->rgba();
ASSERT_TRUE(color);
EXPECT_EQ(color_list[i], color->value());
scoped_refptr<cssom::PercentageValue> color_stop_position_value =
dynamic_cast<cssom::PercentageValue*>(
color_stop_value->position().get());
EXPECT_FLOAT_EQ(color_stop_position_list[i],
color_stop_position_value->value());
}
}
TEST_F(ParserTest,
ParsesBackgroundImageRadialGradientWithSizeShapeAndPosition) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background-image: radial-gradient(2em circle at top center, "
"rgba(0,0,0,0.2) 25%, rgba(0,0,0,0.1) 60%);",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::RadialGradientValue> radial_gradient_value =
dynamic_cast<cssom::RadialGradientValue*>(
background_image_list->value()[0].get());
EXPECT_EQ(cssom::RadialGradientValue::kCircle,
radial_gradient_value->shape());
EXPECT_FALSE(radial_gradient_value->size_keyword());
scoped_refptr<cssom::PropertyListValue> size =
radial_gradient_value->size_value();
ASSERT_TRUE(size);
EXPECT_EQ(1, size->value().size());
scoped_refptr<cssom::LengthValue> size_value =
dynamic_cast<cssom::LengthValue*>(size->value()[0].get());
EXPECT_FLOAT_EQ(2.0f, size_value->value());
EXPECT_EQ(cssom::kFontSizesAkaEmUnit, size_value->unit());
scoped_refptr<cssom::PropertyListValue> position =
radial_gradient_value->position();
ASSERT_TRUE(position);
EXPECT_EQ(2, position->value().size());
EXPECT_EQ(cssom::KeywordValue::GetTop(), position->value()[0]);
EXPECT_EQ(cssom::KeywordValue::GetCenter(), position->value()[1]);
const cssom::ColorStopList& color_stop_list_value =
radial_gradient_value->color_stop_list();
EXPECT_EQ(2, color_stop_list_value.size());
uint32 color_list[2] = {0x00000033, 0x00000019};
float color_stop_position_list[2] = {0.25f, 0.6f};
for (size_t i = 0; i < color_stop_list_value.size(); ++i) {
const cssom::ColorStop* color_stop_value = color_stop_list_value[i];
scoped_refptr<cssom::RGBAColorValue> color = color_stop_value->rgba();
ASSERT_TRUE(color);
EXPECT_EQ(color_list[i], color->value());
scoped_refptr<cssom::PercentageValue> color_stop_position_value =
dynamic_cast<cssom::PercentageValue*>(
color_stop_value->position().get());
EXPECT_FLOAT_EQ(color_stop_position_list[i],
color_stop_position_value->value());
}
}
TEST_F(ParserTest, ParsesBackgroundImageRadialGradientWithSizeLength) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background-image: radial-gradient(20px 60%, "
"rgba(0,0,0,0.2) 25%, rgba(0,0,0,0.1) 60%);",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::RadialGradientValue> radial_gradient_value =
dynamic_cast<cssom::RadialGradientValue*>(
background_image_list->value()[0].get());
EXPECT_EQ(cssom::RadialGradientValue::kEllipse,
radial_gradient_value->shape());
EXPECT_FALSE(radial_gradient_value->size_keyword());
scoped_refptr<cssom::PropertyListValue> size =
radial_gradient_value->size_value();
ASSERT_TRUE(size);
EXPECT_EQ(2, size->value().size());
scoped_refptr<cssom::LengthValue> side_value_horizontal =
dynamic_cast<cssom::LengthValue*>(size->value()[0].get());
EXPECT_FLOAT_EQ(20.0f, side_value_horizontal->value());
EXPECT_EQ(cssom::kPixelsUnit, side_value_horizontal->unit());
scoped_refptr<cssom::PercentageValue> side_value_vertical =
dynamic_cast<cssom::PercentageValue*>(size->value()[1].get());
EXPECT_FLOAT_EQ(0.6f, side_value_vertical->value());
scoped_refptr<cssom::PropertyListValue> position =
radial_gradient_value->position();
EXPECT_FALSE(position);
const cssom::ColorStopList& color_stop_list_value =
radial_gradient_value->color_stop_list();
EXPECT_EQ(2, color_stop_list_value.size());
uint32 color_list[2] = {0x00000033, 0x00000019};
float color_stop_position_list[2] = {0.25f, 0.6f};
for (size_t i = 0; i < color_stop_list_value.size(); ++i) {
const cssom::ColorStop* color_stop_value = color_stop_list_value[i];
scoped_refptr<cssom::RGBAColorValue> color = color_stop_value->rgba();
ASSERT_TRUE(color);
EXPECT_EQ(color_list[i], color->value());
scoped_refptr<cssom::PercentageValue> color_stop_position_value =
dynamic_cast<cssom::PercentageValue*>(
color_stop_value->position().get());
EXPECT_FLOAT_EQ(color_stop_position_list[i],
color_stop_position_value->value());
}
}
TEST_F(ParserTest, ParsesBackgroundImageRadialGradientWithoutShapeAndSize) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background-image: radial-gradient(at left, "
"rgba(0,0,0,0.2) 25%, rgba(0,0,0,0.1) 60%);",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::RadialGradientValue> radial_gradient_value =
dynamic_cast<cssom::RadialGradientValue*>(
background_image_list->value()[0].get());
EXPECT_EQ(cssom::RadialGradientValue::kEllipse,
radial_gradient_value->shape());
EXPECT_EQ(cssom::RadialGradientValue::kFarthestCorner,
radial_gradient_value->size_keyword());
EXPECT_FALSE(radial_gradient_value->size_value());
scoped_refptr<cssom::PropertyListValue> position =
radial_gradient_value->position();
ASSERT_TRUE(position);
EXPECT_EQ(1, position->value().size());
EXPECT_EQ(cssom::KeywordValue::GetLeft(), position->value()[0]);
const cssom::ColorStopList& color_stop_list_value =
radial_gradient_value->color_stop_list();
EXPECT_EQ(2, color_stop_list_value.size());
uint32 color_list[2] = {0x00000033, 0x00000019};
float color_stop_position_list[2] = {0.25f, 0.6f};
for (size_t i = 0; i < color_stop_list_value.size(); ++i) {
const cssom::ColorStop* color_stop_value = color_stop_list_value[i];
scoped_refptr<cssom::RGBAColorValue> color = color_stop_value->rgba();
ASSERT_TRUE(color);
EXPECT_EQ(color_list[i], color->value());
scoped_refptr<cssom::PercentageValue> color_stop_position_value =
dynamic_cast<cssom::PercentageValue*>(
color_stop_value->position().get());
EXPECT_FLOAT_EQ(color_stop_position_list[i],
color_stop_position_value->value());
}
}
TEST_F(ParserTest, ParsesBackgroundImageRadialGradientOnlyHasColorStop) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList(
"background-image: radial-gradient("
"rgba(0,0,0,0.2) 25%, rgba(0,0,0,0.1) 60%);",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_image_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundImageProperty).get());
ASSERT_TRUE(background_image_list);
EXPECT_EQ(1, background_image_list->value().size());
scoped_refptr<cssom::RadialGradientValue> radial_gradient_value =
dynamic_cast<cssom::RadialGradientValue*>(
background_image_list->value()[0].get());
EXPECT_EQ(cssom::RadialGradientValue::kEllipse,
radial_gradient_value->shape());
EXPECT_EQ(cssom::RadialGradientValue::kFarthestCorner,
radial_gradient_value->size_keyword());
EXPECT_FALSE(radial_gradient_value->size_value());
scoped_refptr<cssom::PropertyListValue> position =
radial_gradient_value->position();
EXPECT_FALSE(position);
const cssom::ColorStopList& color_stop_list_value =
radial_gradient_value->color_stop_list();
EXPECT_EQ(2, color_stop_list_value.size());
uint32 color_list[2] = {0x00000033, 0x00000019};
float color_stop_position_list[2] = {0.25f, 0.6f};
for (size_t i = 0; i < color_stop_list_value.size(); ++i) {
const cssom::ColorStop* color_stop_value = color_stop_list_value[i];
scoped_refptr<cssom::RGBAColorValue> color = color_stop_value->rgba();
ASSERT_TRUE(color);
EXPECT_EQ(color_list[i], color->value());
scoped_refptr<cssom::PercentageValue> color_stop_position_value =
dynamic_cast<cssom::PercentageValue*>(
color_stop_value->position().get());
EXPECT_FLOAT_EQ(color_stop_position_list[i],
color_stop_position_value->value());
}
}
TEST_F(ParserTest, ParsesBackgroundPositionCenter) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-position: center;",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_position_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundPositionProperty).get());
ASSERT_TRUE(background_position_list);
EXPECT_EQ(1, background_position_list->value().size());
EXPECT_EQ(cssom::KeywordValue::GetCenter(),
background_position_list->value()[0]);
}
TEST_F(ParserTest, ParsesBackgroundPositionOneValue) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-position: 20%;",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_position_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundPositionProperty).get());
ASSERT_TRUE(background_position_list);
EXPECT_EQ(1, background_position_list->value().size());
scoped_refptr<cssom::PercentageValue> percentage =
dynamic_cast<cssom::PercentageValue*>(
background_position_list->value()[0].get());
ASSERT_TRUE(percentage);
EXPECT_FLOAT_EQ(0.2f, percentage->value());
}
TEST_F(ParserTest, ParsesBackgroundPositionCenterLeft) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-position: center left;",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_position_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundPositionProperty).get());
ASSERT_TRUE(background_position_list);
EXPECT_EQ(2, background_position_list->value().size());
EXPECT_EQ(cssom::KeywordValue::GetCenter(),
background_position_list->value()[0]);
EXPECT_EQ(cssom::KeywordValue::GetLeft(),
background_position_list->value()[1]);
}
TEST_F(ParserTest, ParsesBackgroundPositionRightCenter) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-position: right center;",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_position_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundPositionProperty).get());
ASSERT_TRUE(background_position_list);
EXPECT_EQ(2, background_position_list->value().size());
EXPECT_EQ(cssom::KeywordValue::GetRight(),
background_position_list->value()[0]);
EXPECT_EQ(cssom::KeywordValue::GetCenter(),
background_position_list->value()[1]);
}
TEST_F(ParserTest, ParsesBackgroundPositionCenterCenter) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-position: center center;",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_position_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundPositionProperty).get());
ASSERT_TRUE(background_position_list);
EXPECT_EQ(2, background_position_list->value().size());
EXPECT_EQ(cssom::KeywordValue::GetCenter(),
background_position_list->value()[0]);
EXPECT_EQ(cssom::KeywordValue::GetCenter(),
background_position_list->value()[1]);
}
TEST_F(ParserTest, ParsesBackgroundPositionValueCenter) {
scoped_refptr<cssom::CSSDeclaredStyleData> style =
parser_.ParseStyleDeclarationList("background-position: 20px center;",
source_location_);
scoped_refptr<cssom::PropertyListValue> background_position_list =
dynamic_cast<cssom::PropertyListValue*>(
style->GetPropertyValue(cssom::kBackgroundPositionProperty).get());