| // Copyright 2014 The Cobalt Authors. 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 <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/strings/stringprintf.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/cobalt_ui_nav_focus_transform_function.h" |
| #include "cobalt/cssom/cobalt_ui_nav_spotlight_transform_function.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 "cobalt/cssom/viewport_size.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using cobalt::cssom::ViewportSize; |
| using testing::_; |
| using testing::AtLeast; |
| |
| namespace cobalt { |
| namespace css_parser { |
| |
| constexpr cssom::TransformFunction::Trait kTraitIsDynamic = |
| cssom::TransformFunction::Trait::kTraitIsDynamic; |
| constexpr cssom::TransformFunction::Trait kTraitUsesRelativeUnits = |
| cssom::TransformFunction::Trait::kTraitUsesRelativeUnits; |
| constexpr cssom::TransformFunction::Trait kTraitUsesUiNavFocus = |
| cssom::TransformFunction::Trait::kTraitUsesUiNavFocus; |
| |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| ASSERT_TRUE(class_selector); |
| EXPECT_EQ("my-class", class_selector->class_name()); |
| } |
| |
| TEST_F(ParserTest, ParsesPropertyKeyAsClassSelector) { |
| for (int i = 0; i < 1 + cssom::kMaxEveryPropertyKey; i++) { |
| cssom::PropertyKey property_key = static_cast<cssom::PropertyKey>(i); |
| std::string property_name = cssom::GetPropertyName(property_key); |
| std::string declaration = |
| base::StringPrintf(".%s {}", property_name.c_str()); |
| |
| scoped_refptr<cssom::CSSStyleSheet> style_sheet = |
| parser_.ParseStyleSheet(declaration, 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].get())); |
| 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].get())); |
| ASSERT_TRUE(class_selector); |
| EXPECT_EQ(property_name, class_selector->class_name()); |
| } |
| } |
| |
| TEST_F(ParserTest, ParsesKeywordAsClassSelector) { |
| for (int i = 0; i < 1 + cssom::KeywordValue::kMaxKeywordValue; i++) { |
| cssom::KeywordValue::Value keyword_value = |
| static_cast<cssom::KeywordValue::Value>(i); |
| std::string keyword_name = cssom::KeywordValue::GetName(keyword_value); |
| std::string declaration = |
| base::StringPrintf(".%s {}", keyword_name.c_str()); |
| |
| scoped_refptr<cssom::CSSStyleSheet> style_sheet = |
| parser_.ParseStyleSheet(declaration, 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].get())); |
| 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].get())); |
| ASSERT_TRUE(class_selector); |
| EXPECT_EQ(keyword_name, 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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].get())); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kColorProperty)); |
| EXPECT_TRUE(style->GetPropertyValue(cssom::kColorProperty)); |
| ASSERT_TRUE(style->IsDeclared(cssom::kFontSizeProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kColorProperty)); |
| EXPECT_TRUE(style->GetPropertyValue(cssom::kColorProperty)); |
| ASSERT_TRUE(style->IsDeclared(cssom::kFontSizeProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kColorProperty)); |
| EXPECT_TRUE(style->GetPropertyValue(cssom::kColorProperty)); |
| ASSERT_TRUE(style->IsDeclared(cssom::kFontSizeProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kColorProperty)); |
| EXPECT_TRUE(style->GetPropertyValue(cssom::kColorProperty)); |
| ASSERT_TRUE(style->IsDeclared(cssom::kFontSizeProperty)); |
| 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); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kWidthProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kTransformProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kColorProperty)); |
| 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_); |
| |
| ASSERT_FALSE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| EXPECT_FALSE(style->GetPropertyValue(cssom::kBackgroundColorProperty)); |
| ASSERT_TRUE(style->IsDeclared(cssom::kColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kTransformProperty)); |
| scoped_refptr<cssom::TransformFunctionListValue> transform_list = |
| dynamic_cast<cssom::TransformFunctionListValue*>( |
| style->GetPropertyValue(cssom::kTransformProperty).get()); |
| ASSERT_TRUE(transform_list); |
| EXPECT_FALSE(transform_list->value().HasTrait(kTraitIsDynamic)); |
| EXPECT_FALSE(transform_list->value().HasTrait(kTraitUsesRelativeUnits)); |
| EXPECT_FALSE(transform_list->value().HasTrait(kTraitUsesUiNavFocus)); |
| ASSERT_EQ(1, transform_list->value().size()); |
| |
| const cssom::TranslateFunction* translate_function = |
| dynamic_cast<const cssom::TranslateFunction*>( |
| transform_list->value()[0].get()); |
| 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 that the keywords supported for a property are parsed into a |
| // corresponding KeywordValue, FontStyleValue, or FontWeightValue. |
| TEST_F(ParserTest, ParsesLonghandPropertyKeywords) { |
| // List of longhand properties and keywords that are parsed to a KeywordValue, |
| // FontStyleValue, or FontWeightValue that is not computed further during |
| // parsing. Each longhand property in the enum cssom::PropertyKey has to |
| // appear here once, in the same order as the enum. |
| // clang-format off |
| const char* longhand_property_keywords[] = { |
| "align-content", |
| "inherit", "initial", "flex-start", "flex-end", "center", "space-between", |
| "space-around", "stretch", nullptr, |
| "align-items", |
| "inherit", "initial", "flex-start", "flex-end", "center", "baseline", |
| "stretch", nullptr, |
| "align-self", |
| "inherit", "initial", "auto", "flex-start", "flex-end", "center", |
| "baseline", "stretch", nullptr, |
| "animation-delay", |
| "inherit", "initial", nullptr, |
| "animation-direction", |
| "inherit", "initial", nullptr, |
| "animation-duration", |
| "inherit", "initial", nullptr, |
| "animation-fill-mode", |
| "inherit", "initial", nullptr, |
| "animation-iteration-count", |
| "inherit", "initial", nullptr, |
| "animation-name", |
| "inherit", "initial", nullptr, |
| "animation-timing-function", |
| "inherit", "initial", nullptr, |
| "background-color", |
| "inherit", "initial", nullptr, |
| "background-image", |
| "inherit", "initial", nullptr, |
| "background-position", |
| "inherit", "initial", nullptr, |
| "background-repeat", |
| "inherit", "initial", nullptr, |
| "background-size", |
| "inherit", "initial", "cover", "contain", nullptr, |
| "border-bottom-color", |
| "inherit", "initial", nullptr, |
| "border-bottom-left-radius", |
| "inherit", "initial", nullptr, |
| "border-bottom-right-radius", |
| "inherit", "initial", nullptr, |
| "border-bottom-style", |
| "inherit", "initial", "none", "hidden", "solid", nullptr, |
| "border-bottom-width", |
| "inherit", "initial", nullptr, |
| "border-left-color", |
| "inherit", "initial", nullptr, |
| "border-left-style", |
| "inherit", "initial", "none", "hidden", "solid", nullptr, |
| "border-left-width", |
| "inherit", "initial", nullptr, |
| "border-right-color", |
| "inherit", "initial", nullptr, |
| "border-right-style", |
| "inherit", "initial", "none", "hidden", "solid", nullptr, |
| "border-right-width", |
| "inherit", "initial", nullptr, |
| "border-top-color", |
| "inherit", "initial", nullptr, |
| "border-top-left-radius", |
| "inherit", "initial", nullptr, |
| "border-top-right-radius", |
| "inherit", "initial", nullptr, |
| "border-top-style", |
| "inherit", "initial", "none", "hidden", "solid", nullptr, |
| "border-top-width", |
| "inherit", "initial", nullptr, |
| "bottom", |
| "inherit", "initial", "auto", nullptr, |
| "box-shadow", |
| "inherit", "initial", "none", nullptr, |
| "color", |
| "inherit", "initial", nullptr, |
| "content", |
| "inherit", "initial", "none", "normal", nullptr, |
| "display", |
| "inherit", "initial", "block", "flex", "inline", "inline-block", |
| "inline-flex", "none", nullptr, |
| "filter", |
| "inherit", "initial", "none", nullptr, |
| "flex-basis", |
| "inherit", "initial", "auto", "content", nullptr, |
| "flex-direction", |
| "inherit", "initial", "row", "row-reverse", "column", "column-reverse", |
| nullptr, |
| "flex-grow", |
| "inherit", "initial", nullptr, |
| "flex-shrink", |
| "inherit", "initial", nullptr, |
| "flex-wrap", |
| "inherit", "initial", "nowrap", "wrap", "wrap-reverse", nullptr, |
| "font-family", |
| "inherit", "initial", nullptr, |
| "font-size", |
| "inherit", "initial", nullptr, |
| "font-style", |
| "inherit", "initial", "normal", "italic", "oblique", nullptr, |
| "font-weight", |
| "inherit", "initial", "bold", nullptr, |
| "height", |
| "inherit", "initial", "auto", nullptr, |
| "intersection-observer-root-margin", |
| nullptr, |
| "justify-content", |
| "inherit", "initial", "flex-start", "flex-end", "center", "space-between", |
| "space-around", nullptr, |
| "left", |
| "inherit", "initial", "auto", nullptr, |
| "line-height", |
| "inherit", "initial", "normal", nullptr, |
| "margin-bottom", |
| "inherit", "initial", "auto", nullptr, |
| "margin-left", |
| "inherit", "initial", "auto", nullptr, |
| "margin-right", |
| "inherit", "initial", "auto", nullptr, |
| "margin-top", |
| "inherit", "initial", "auto", nullptr, |
| "max-height", |
| "inherit", "initial", "none", nullptr, |
| "max-width", |
| "inherit", "initial", "none", nullptr, |
| "min-height", |
| "inherit", "initial", nullptr, |
| "min-width", |
| "inherit", "initial", nullptr, |
| "opacity", |
| "inherit", "initial", nullptr, |
| "order", |
| "inherit", "initial", nullptr, |
| "outline-color", |
| "inherit", "initial", nullptr, |
| "outline-style", |
| "inherit", "initial", "solid", "hidden", nullptr, |
| "outline-width", |
| "inherit", "initial", nullptr, |
| "overflow", |
| "inherit", "initial", "auto", "hidden", "scroll", "visible", nullptr, |
| "overflow-wrap", |
| "inherit", "initial", "break-word", "normal", nullptr, |
| "padding-bottom", |
| "inherit", "initial", nullptr, |
| "padding-left", |
| "inherit", "initial", nullptr, |
| "padding-right", |
| "inherit", "initial", nullptr, |
| "padding-top", |
| "inherit", "initial", nullptr, |
| "pointer-events", |
| "inherit", "initial", "auto", "none", nullptr, |
| "position", |
| "inherit", "initial", "static", "relative", "absolute", nullptr, |
| "right", |
| "inherit", "initial", "auto", nullptr, |
| "text-align", |
| "inherit", "initial", "start", "end", "left", "center", "right", nullptr, |
| "text-decoration-color", |
| "inherit", "initial", nullptr, |
| "text-decoration-line", |
| "inherit", "initial", "none", "line-through", nullptr, |
| "text-indent", |
| "inherit", "initial", nullptr, |
| "text-overflow", |
| "inherit", "initial", "clip", "ellipsis", nullptr, |
| "text-shadow", |
| "inherit", "initial", "none", nullptr, |
| "text-transform", |
| "inherit", "initial", "none", "uppercase", nullptr, |
| "top", |
| "inherit", "initial", "auto", nullptr, |
| "transform-origin", |
| "inherit", "initial", nullptr, |
| "transform", |
| "inherit", "initial", "none", nullptr, |
| "transition-delay", |
| "inherit", "initial", nullptr, |
| "transition-duration", |
| "inherit", "initial", nullptr, |
| "transition-property", |
| "inherit", "initial", nullptr, |
| "transition-timing-function", |
| "inherit", "initial", nullptr, |
| "vertical-align", |
| "inherit", "initial", "baseline", "bottom", "middle", "top", nullptr, |
| "visibility", |
| "inherit", "initial", "collapse", "hidden", "visible", nullptr, |
| "white-space", |
| "inherit", "initial", "normal", "nowrap", "pre", "pre-line", "pre-wrap", |
| nullptr, |
| "width", |
| "inherit", "initial", "auto", nullptr, |
| "z-index", |
| "inherit", "initial", "auto", nullptr, |
| nullptr, |
| }; |
| // clang-format on |
| |
| // Helper class to check if a PropertyValue is a KeywordValue, FontStyleValue, |
| // or FontWeightValue. |
| class KeywordProvider : public cssom::NotReachedPropertyValueVisitor { |
| public: |
| KeywordProvider() : is_keyword_(false) {} |
| bool is_keyword() { return is_keyword_; } |
| void VisitKeyword(cssom::KeywordValue* keyword) override { |
| is_keyword_ = true; |
| } |
| void VisitFontStyle(cssom::FontStyleValue* font_style) override { |
| is_keyword_ = true; |
| } |
| void VisitFontWeight(cssom::FontWeightValue* font_weight_value) override { |
| is_keyword_ = true; |
| } |
| |
| private: |
| bool is_keyword_; |
| DISALLOW_COPY_AND_ASSIGN(KeywordProvider); |
| }; |
| |
| const char** property_keyword = longhand_property_keywords; |
| for (int i = 0; i <= cssom::kMaxLonghandPropertyKey; |
| ++i, ++property_keyword) { |
| const char* property(*property_keyword); |
| cssom::PropertyKey property_key(static_cast<cssom::PropertyKey>(i)); |
| ASSERT_NE(property, nullptr); |
| for (++property_keyword; *property_keyword; ++property_keyword) { |
| const char* keyword = *property_keyword; |
| std::string declaration = |
| base::StringPrintf("%s: %s;", property, keyword); |
| scoped_refptr<cssom::CSSDeclaredStyleData> style = |
| parser_.ParseStyleDeclarationList(declaration, source_location_); |
| ASSERT_TRUE(style->IsDeclared(property_key)); |
| scoped_refptr<cssom::PropertyValue> property_value = |
| style->GetPropertyValue(property_key); |
| EXPECT_EQ(keyword, property_value->ToString()); |
| KeywordProvider keyword_provider; |
| property_value->Accept(&keyword_provider); |
| EXPECT_EQ(true, keyword_provider.is_keyword()); |
| } |
| } |
| } |
| |
| // Test that shorthand properties are parsed into corresponding KeywordValues |
| // for the expanded properties for values 'inherit' and 'initial'. |
| TEST_F(ParserTest, ParsesShorthandPropertyInitialAndInherit) { |
| const char* shorthand_property_keywords[] = { |
| "inherit", "initial", nullptr, |
| }; |
| |
| // Helper class to check if a PropertyValue is a KeywordValue. |
| class KeywordProvider : public cssom::NotReachedPropertyValueVisitor { |
| public: |
| KeywordProvider() : is_keyword_(false) {} |
| bool is_keyword() { return is_keyword_; } |
| void VisitKeyword(cssom::KeywordValue* keyword) override { |
| is_keyword_ = true; |
| } |
| |
| // Returns true if the property key is a longhand property with a keyword |
| // value, or is a shorthand property for which all longhand properties have |
| // keyword values, where all keywords serialize to the given keyword; |
| static void VerifyIsLongHandKeywordValue( |
| const scoped_refptr<cssom::CSSDeclaredStyleData>& style, |
| cssom::PropertyKey property_key, const char* keyword) { |
| if (!IsShorthandProperty(property_key)) { |
| // Test that the shorthand property is set and has a keyword value that |
| // serializes to the keyword name. |
| ASSERT_TRUE(style->IsDeclared(property_key)); |
| scoped_refptr<cssom::PropertyValue> property_value = |
| style->GetPropertyValue(property_key); |
| EXPECT_EQ(keyword, property_value->ToString()); |
| |
| KeywordProvider keyword_provider; |
| property_value->Accept(&keyword_provider); |
| EXPECT_EQ(true, keyword_provider.is_keyword()); |
| return; |
| } |
| |
| for (auto expanded_property : |
| cssom::ExpandShorthandProperty(property_key)) { |
| // Recurse for the longhand properties that this shorthand expands to. |
| VerifyIsLongHandKeywordValue(style, expanded_property, keyword); |
| } |
| } |
| |
| private: |
| bool is_keyword_; |
| DISALLOW_COPY_AND_ASSIGN(KeywordProvider); |
| }; |
| |
| for (int i = cssom::kFirstShorthandPropertyKey; |
| i <= cssom::kMaxShorthandPropertyKey; ++i) { |
| cssom::PropertyKey property_key(static_cast<cssom::PropertyKey>(i)); |
| const char* property = cssom::GetPropertyName(property_key); |
| ASSERT_NE(property, nullptr); |
| for (const char** property_keyword = shorthand_property_keywords; |
| *property_keyword; ++property_keyword) { |
| const char* keyword = *property_keyword; |
| std::string declaration = |
| base::StringPrintf("%s: %s;", property, keyword); |
| scoped_refptr<cssom::CSSDeclaredStyleData> style = |
| parser_.ParseStyleDeclarationList(declaration, source_location_); |
| KeywordProvider::VerifyIsLongHandKeywordValue(style, property_key, |
| keyword); |
| } |
| } |
| } |
| |
| TEST_F(ParserTest, ParsesBackgroundWithOnlyColor) { |
| scoped_refptr<cssom::CSSDeclaredStyleData> style = |
| parser_.ParseStyleDeclarationList("background: rgba(0, 0, 0, .8);", |
| source_location_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundRepeatProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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()); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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()); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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()); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundPositionProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundPositionProperty)); |
| 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()); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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()); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundPositionProperty)); |
| 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]); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundSizeProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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()); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundPositionProperty)); |
| 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]); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundSizeProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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()); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundRepeatProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundRepeatProperty)); |
| 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]); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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()); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundRepeatProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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()); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundPositionProperty)); |
| 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]); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundRepeatProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundPositionProperty)); |
| 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]); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundRepeatProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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].get(); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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].get(); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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].get(); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundColorProperty)); |
| 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, ParsesBackgroundImageNone) { |
| scoped_refptr<cssom::CSSDeclaredStyleData> style = |
| parser_.ParseStyleDeclarationList("background-image: none;", |
| source_location_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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, ParsesSingleBackgroundImageURL) { |
| scoped_refptr<cssom::CSSDeclaredStyleData> style = |
| parser_.ParseStyleDeclarationList("background-image: url(foo.png);", |
| source_location_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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].get(); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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].get(); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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].get(); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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].get(); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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].get(); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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].get(); |
| 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_); |
| |
| ASSERT_TRUE(style->IsDeclared(cssom::kBackgroundImageProperty)); |
| 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()[
|