| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "components/doodle/doodle_types.h" |
| 6 |
| 7 #include <memory> |
| 8 #include <string> |
| 9 |
| 10 #include "base/json/json_reader.h" |
| 11 #include "base/optional.h" |
| 12 #include "base/values.h" |
| 13 #include "testing/gmock/include/gmock/gmock.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 #include "url/gurl.h" |
| 16 |
| 17 using testing::Eq; |
| 18 |
| 19 namespace doodle { |
| 20 |
| 21 namespace { |
| 22 |
| 23 // Parses the given |json| string into a base::DictionaryValue and creates a |
| 24 // DoodleImage out of that. |json| must be a valid json string. |
| 25 base::Optional<DoodleImage> DoodleImageFromJson( |
| 26 const std::string& json, |
| 27 const base::Optional<GURL>& base_url) { |
| 28 std::unique_ptr<base::DictionaryValue> value = |
| 29 base::DictionaryValue::From(base::JSONReader::Read(json)); |
| 30 DCHECK(value); |
| 31 return DoodleImage::FromDictionary(*value, base_url); |
| 32 } |
| 33 |
| 34 // Parses the given |json| string into a base::DictionaryValue and creates a |
| 35 // DoodleConfig out of that. |json| must be a valid json string. |
| 36 base::Optional<DoodleConfig> DoodleConfigFromJson( |
| 37 const std::string& json, |
| 38 const base::Optional<GURL>& base_url) { |
| 39 std::unique_ptr<base::DictionaryValue> value = |
| 40 base::DictionaryValue::From(base::JSONReader::Read(json)); |
| 41 DCHECK(value); |
| 42 return DoodleConfig::FromDictionary(*value, base_url); |
| 43 } |
| 44 |
| 45 } // namespace |
| 46 |
| 47 TEST(DoodleImageTest, ParsesMinimalImage) { |
| 48 std::string json = R"json({ |
| 49 "url":"https://www.doodle.com/doodle" |
| 50 })json"; |
| 51 base::Optional<DoodleImage> image = DoodleImageFromJson(json, base::nullopt); |
| 52 ASSERT_TRUE(image.has_value()); |
| 53 EXPECT_THAT(image->url, Eq(GURL("https://www.doodle.com/doodle"))); |
| 54 EXPECT_THAT(image->height, Eq(0)); |
| 55 EXPECT_THAT(image->width, Eq(0)); |
| 56 EXPECT_THAT(image->is_animated_gif, Eq(false)); |
| 57 EXPECT_THAT(image->is_cta, Eq(false)); |
| 58 } |
| 59 |
| 60 TEST(DoodleImageTest, ParsesFullImage) { |
| 61 std::string json = R"json({ |
| 62 "url":"https://www.doodle.com/doodle", |
| 63 "height":100, |
| 64 "width":50, |
| 65 "is_animated_gif":true, |
| 66 "is_cta":true |
| 67 })json"; |
| 68 base::Optional<DoodleImage> image = DoodleImageFromJson(json, base::nullopt); |
| 69 ASSERT_TRUE(image.has_value()); |
| 70 EXPECT_THAT(image->url, Eq(GURL("https://www.doodle.com/doodle"))); |
| 71 EXPECT_THAT(image->height, Eq(100)); |
| 72 EXPECT_THAT(image->width, Eq(50)); |
| 73 EXPECT_THAT(image->is_animated_gif, Eq(true)); |
| 74 EXPECT_THAT(image->is_cta, Eq(true)); |
| 75 } |
| 76 |
| 77 TEST(DoodleImageTest, ResolvesRelativeUrl) { |
| 78 std::string json = R"json({ |
| 79 "url":"/the_doodle_path" |
| 80 })json"; |
| 81 base::Optional<DoodleImage> image = |
| 82 DoodleImageFromJson(json, GURL("https://doodle.dood/")); |
| 83 ASSERT_TRUE(image.has_value()); |
| 84 EXPECT_THAT(image->url, Eq(GURL("https://doodle.dood/the_doodle_path"))); |
| 85 } |
| 86 |
| 87 TEST(DoodleImageTest, DoesNotResolveAbsoluteUrl) { |
| 88 std::string json = R"json({ |
| 89 "url":"https://www.doodle.com/the_doodle_path" |
| 90 })json"; |
| 91 base::Optional<DoodleImage> image = |
| 92 DoodleImageFromJson(json, GURL("https://other.com/")); |
| 93 ASSERT_TRUE(image.has_value()); |
| 94 EXPECT_THAT(image->url, Eq(GURL("https://www.doodle.com/the_doodle_path"))); |
| 95 } |
| 96 |
| 97 TEST(DoodleImageTest, RequiresUrl) { |
| 98 std::string json = R"json({ |
| 99 "height":100, |
| 100 "width":50, |
| 101 "is_animated_gif":true, |
| 102 "is_cta":true |
| 103 })json"; |
| 104 base::Optional<DoodleImage> image = DoodleImageFromJson(json, base::nullopt); |
| 105 EXPECT_FALSE(image.has_value()); |
| 106 } |
| 107 |
| 108 TEST(DoodleImageTest, HandlesInvalidUrl) { |
| 109 std::string json = R"json({ |
| 110 "url":"not_a_url" |
| 111 })json"; |
| 112 base::Optional<DoodleImage> image = DoodleImageFromJson(json, base::nullopt); |
| 113 // The URL is required, and invalid should be treated like missing. |
| 114 EXPECT_FALSE(image.has_value()); |
| 115 } |
| 116 |
| 117 TEST(DoodleImageTest, PreservesFieldsOverRoundtrip) { |
| 118 // Set all fields to non-default values. |
| 119 DoodleImage image(GURL("https://www.doodle.com/doodle")); |
| 120 image.height = 100; |
| 121 image.width = 50; |
| 122 image.is_animated_gif = true; |
| 123 image.is_cta = true; |
| 124 |
| 125 // Convert to a dictionary and back. |
| 126 base::Optional<DoodleImage> after_roundtrip = |
| 127 DoodleImage::FromDictionary(*image.ToDictionary(), base::nullopt); |
| 128 |
| 129 // Make sure everything survived. |
| 130 ASSERT_TRUE(after_roundtrip.has_value()); |
| 131 EXPECT_THAT(*after_roundtrip, Eq(image)); |
| 132 } |
| 133 |
| 134 TEST(DoodleConfigTest, ParsesMinimalConfig) { |
| 135 std::string json = R"json({ |
| 136 "large_image":{"url":"https://doodle.com/img.jpg"} |
| 137 })json"; |
| 138 base::Optional<DoodleConfig> config = |
| 139 DoodleConfigFromJson(json, base::nullopt); |
| 140 ASSERT_TRUE(config.has_value()); |
| 141 EXPECT_THAT(config->doodle_type, Eq(DoodleType::UNKNOWN)); |
| 142 EXPECT_THAT(config->alt_text, Eq(std::string())); |
| 143 EXPECT_THAT(config->interactive_html, Eq(std::string())); |
| 144 EXPECT_THAT(config->search_url, Eq(GURL())); |
| 145 EXPECT_THAT(config->target_url, Eq(GURL())); |
| 146 EXPECT_THAT(config->fullpage_interactive_url, Eq(GURL())); |
| 147 EXPECT_FALSE(config->large_cta_image.has_value()); |
| 148 EXPECT_FALSE(config->transparent_large_image.has_value()); |
| 149 } |
| 150 |
| 151 TEST(DoodleConfigTest, ParsesFullConfig) { |
| 152 std::string json = R"json({ |
| 153 "doodle_type":"SLIDESHOW", |
| 154 "alt_text":"some text", |
| 155 "interactive_html":"<div id='dood'></div>", |
| 156 "search_url":"https://doodle.com/search", |
| 157 "target_url":"https://doodle.com/target", |
| 158 "fullpage_interactive_url":"https://doodle.com/interactive", |
| 159 "large_image":{"url":"https://doodle.com/img.jpg"}, |
| 160 "large_cta_image":{"url":"https://doodle.com/cta.jpg"}, |
| 161 "transparent_large_image":{"url":"https://doodle.com/transparent.jpg"} |
| 162 })json"; |
| 163 base::Optional<DoodleConfig> config = |
| 164 DoodleConfigFromJson(json, base::nullopt); |
| 165 ASSERT_TRUE(config.has_value()); |
| 166 EXPECT_THAT(config->doodle_type, Eq(DoodleType::SLIDESHOW)); |
| 167 EXPECT_THAT(config->alt_text, Eq("some text")); |
| 168 EXPECT_THAT(config->interactive_html, Eq("<div id='dood'></div>")); |
| 169 EXPECT_THAT(config->search_url, Eq(GURL("https://doodle.com/search"))); |
| 170 EXPECT_THAT(config->target_url, Eq(GURL("https://doodle.com/target"))); |
| 171 EXPECT_THAT(config->fullpage_interactive_url, |
| 172 Eq(GURL("https://doodle.com/interactive"))); |
| 173 EXPECT_THAT(config->large_image.url, Eq(GURL("https://doodle.com/img.jpg"))); |
| 174 ASSERT_TRUE(config->large_cta_image.has_value()); |
| 175 EXPECT_THAT(config->large_cta_image->url, |
| 176 Eq(GURL("https://doodle.com/cta.jpg"))); |
| 177 ASSERT_TRUE(config->transparent_large_image.has_value()); |
| 178 EXPECT_THAT(config->transparent_large_image->url, |
| 179 Eq(GURL("https://doodle.com/transparent.jpg"))); |
| 180 } |
| 181 |
| 182 TEST(DoodleConfigTest, RequiresLargeImage) { |
| 183 std::string json = R"json({ |
| 184 "doodle_type":"SLIDESHOW", |
| 185 "alt_text":"some text", |
| 186 "interactive_html":"<div id='dood'></div>", |
| 187 "search_url":"https://doodle.com/search", |
| 188 "target_url":"https://doodle.com/target", |
| 189 "fullpage_interactive_url":"https://doodle.com/interactive", |
| 190 "large_cta_image":{"url":"https://doodle.com/cta.jpg"}, |
| 191 "transparent_large_image":{"url":"https://doodle.com/transparent.jpg"} |
| 192 })json"; |
| 193 base::Optional<DoodleConfig> config = |
| 194 DoodleConfigFromJson(json, base::nullopt); |
| 195 EXPECT_FALSE(config.has_value()); |
| 196 } |
| 197 |
| 198 TEST(DoodleConfigTest, RequiresValidLargeImage) { |
| 199 std::string json = R"json({ |
| 200 "doodle_type":"SLIDESHOW", |
| 201 "alt_text":"some text", |
| 202 "interactive_html":"<div id='dood'></div>", |
| 203 "search_url":"https://doodle.com/search", |
| 204 "target_url":"https://doodle.com/target", |
| 205 "fullpage_interactive_url":"https://doodle.com/interactive", |
| 206 "large_image":{"no_url":"asdf"}, |
| 207 "large_cta_image":{"url":"https://doodle.com/cta.jpg"}, |
| 208 "transparent_large_image":{"url":"https://doodle.com/transparent.jpg"} |
| 209 })json"; |
| 210 base::Optional<DoodleConfig> config = |
| 211 DoodleConfigFromJson(json, base::nullopt); |
| 212 EXPECT_FALSE(config.has_value()); |
| 213 } |
| 214 |
| 215 TEST(DoodleConfigTest, ResolvesRelativeUrls) { |
| 216 std::string json = R"json({ |
| 217 "search_url":"/search", |
| 218 "target_url":"/target", |
| 219 "fullpage_interactive_url":"/interactive", |
| 220 "large_image":{"url":"/large.jpg"}, |
| 221 "large_cta_image":{"url":"/cta.jpg"}, |
| 222 "transparent_large_image":{"url":"/transparent.jpg"} |
| 223 })json"; |
| 224 base::Optional<DoodleConfig> config = |
| 225 DoodleConfigFromJson(json, GURL("https://doodle.com/")); |
| 226 ASSERT_TRUE(config.has_value()); |
| 227 EXPECT_THAT(config->search_url, Eq(GURL("https://doodle.com/search"))); |
| 228 EXPECT_THAT(config->target_url, Eq(GURL("https://doodle.com/target"))); |
| 229 EXPECT_THAT(config->fullpage_interactive_url, |
| 230 Eq(GURL("https://doodle.com/interactive"))); |
| 231 EXPECT_THAT(config->large_image.url, |
| 232 Eq(GURL("https://doodle.com/large.jpg"))); |
| 233 ASSERT_TRUE(config->large_cta_image.has_value()); |
| 234 EXPECT_THAT(config->large_cta_image->url, |
| 235 Eq(GURL("https://doodle.com/cta.jpg"))); |
| 236 ASSERT_TRUE(config->transparent_large_image.has_value()); |
| 237 EXPECT_THAT(config->transparent_large_image->url, |
| 238 Eq(GURL("https://doodle.com/transparent.jpg"))); |
| 239 } |
| 240 |
| 241 TEST(DoodleConfigTest, HandlesInvalidUrls) { |
| 242 std::string json = R"json({ |
| 243 "search_url":"not_a_url", |
| 244 "target_url":"not_a_url", |
| 245 "fullpage_interactive_url":"not_a_url", |
| 246 "large_image":{"url":"https://doodle.com/img.jpg"} |
| 247 })json"; |
| 248 base::Optional<DoodleConfig> config = |
| 249 DoodleConfigFromJson(json, base::nullopt); |
| 250 // All the URLs are optional, so invalid ones shouldn't matter. |
| 251 ASSERT_TRUE(config.has_value()); |
| 252 EXPECT_TRUE(config->search_url.is_empty()); |
| 253 EXPECT_TRUE(config->target_url.is_empty()); |
| 254 EXPECT_TRUE(config->fullpage_interactive_url.is_empty()); |
| 255 } |
| 256 |
| 257 TEST(DoodleConfigTest, PreservesFieldsOverRoundtrip) { |
| 258 // Set all fields to non-default values. |
| 259 DoodleConfig config(DoodleType::SLIDESHOW, |
| 260 DoodleImage(GURL("https://www.doodle.com/img.jpg"))); |
| 261 config.alt_text = "some text"; |
| 262 config.interactive_html = "<div id='dood'></div>"; |
| 263 config.search_url = GURL("https://doodle.com/search"); |
| 264 config.target_url = GURL("https://doodle.com/target"); |
| 265 config.fullpage_interactive_url = GURL("https://doodle.com/interactive"); |
| 266 config.large_cta_image = DoodleImage(GURL("https://www.doodle.com/cta.jpg")); |
| 267 config.transparent_large_image = |
| 268 DoodleImage(GURL("https://www.doodle.com/transparent.jpg")); |
| 269 |
| 270 // Convert to a dictionary and back. |
| 271 // Note: The different |base_url| should make no difference, since all |
| 272 // persisted URLs are absolute already. |
| 273 base::Optional<DoodleConfig> after_roundtrip = DoodleConfig::FromDictionary( |
| 274 *config.ToDictionary(), GURL("https://other.com")); |
| 275 |
| 276 // Make sure everything survived. |
| 277 ASSERT_TRUE(after_roundtrip.has_value()); |
| 278 EXPECT_THAT(*after_roundtrip, Eq(config)); |
| 279 } |
| 280 |
| 281 } // namespace doodle |
| OLD | NEW |