| // Copyright 2020 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/cart/cart_service.h" |
| |
| #include "base/optional.h" |
| #include "chrome/browser/cart/cart_db_content.pb.h" |
| #include "chrome/browser/cart/cart_service_factory.h" |
| #include "chrome/browser/history/history_service_factory.h" |
| #include "chrome/browser/persisted_state_db/profile_proto_db.h" |
| #include "chrome/browser/persisted_state_db/profile_proto_db_factory.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/search/ntp_features.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| cart_db::ChromeCartContentProto BuildProto(const char* domain, |
| const char* merchant_url) { |
| cart_db::ChromeCartContentProto proto; |
| proto.set_key(domain); |
| proto.set_merchant_cart_url(merchant_url); |
| proto.set_timestamp(base::Time::Now().ToDoubleT()); |
| return proto; |
| } |
| |
| constexpr char kFakeDataPrefix[] = "Fake:"; |
| const char kMockMerchantA[] = "foo.com"; |
| const char kMockMerchantURLA[] = "https://www.foo.com"; |
| const char kMockMerchantB[] = "bar.com"; |
| const char kMockMerchantURLB[] = "https://www.bar.com"; |
| const char kMockMerchantC[] = "baz.com"; |
| const char kMockMerchantURLC[] = "https://www.baz.com"; |
| const cart_db::ChromeCartContentProto kMockProtoA = |
| BuildProto(kMockMerchantA, kMockMerchantURLA); |
| const cart_db::ChromeCartContentProto kMockProtoB = |
| BuildProto(kMockMerchantB, kMockMerchantURLB); |
| using ShoppingCarts = |
| std::vector<ProfileProtoDB<cart_db::ChromeCartContentProto>::KeyAndValue>; |
| const ShoppingCarts kExpectedA = {{kMockMerchantA, kMockProtoA}}; |
| const ShoppingCarts kExpectedB = {{kMockMerchantB, kMockProtoB}}; |
| const ShoppingCarts kExpectedAB = { |
| {kMockMerchantB, kMockProtoB}, |
| {kMockMerchantA, kMockProtoA}, |
| }; |
| const ShoppingCarts kEmptyExpected = {}; |
| } // namespace |
| |
| class CartServiceTest : public testing::Test { |
| public: |
| CartServiceTest() |
| : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP) {} |
| |
| void SetUp() override { |
| testing::Test::SetUp(); |
| |
| service_ = CartServiceFactory::GetForProfile(&profile_); |
| DCHECK(profile_.CreateHistoryService()); |
| } |
| |
| void OperationEvaluation(base::OnceClosure closure, |
| bool expected_success, |
| bool actual_success) { |
| EXPECT_EQ(expected_success, actual_success); |
| std::move(closure).Run(); |
| } |
| |
| void GetEvaluationURL(base::OnceClosure closure, |
| ShoppingCarts expected, |
| bool result, |
| ShoppingCarts found) { |
| EXPECT_EQ(found.size(), expected.size()); |
| for (size_t i = 0; i < expected.size(); i++) { |
| EXPECT_EQ(found[i].first, expected[i].first); |
| EXPECT_EQ(found[i].second.merchant_cart_url(), |
| expected[i].second.merchant_cart_url()); |
| for (int j = 0; j < expected[i].second.product_image_urls().size(); j++) { |
| EXPECT_EQ(expected[i].second.product_image_urls()[j], |
| found[i].second.product_image_urls()[j]); |
| } |
| } |
| std::move(closure).Run(); |
| } |
| |
| std::string GetCartURL(const std::string& domain) { |
| base::RunLoop run_loop; |
| std::string cart_url; |
| |
| service_->LoadCart( |
| domain, base::BindOnce( |
| [](base::OnceClosure closure, std::string* out, bool result, |
| ShoppingCarts found) { |
| EXPECT_TRUE(result); |
| EXPECT_EQ(found.size(), 1U); |
| *out = found[0].second.merchant_cart_url(); |
| std::move(closure).Run(); |
| }, |
| run_loop.QuitClosure(), &cart_url)); |
| run_loop.Run(); |
| return cart_url; |
| } |
| |
| void GetEvaluationFakeDataDB(base::OnceClosure closure, |
| bool result, |
| ShoppingCarts found) { |
| EXPECT_EQ(found.size(), 6U); |
| for (CartDB::KeyAndValue proto_pair : found) { |
| EXPECT_EQ(proto_pair.second.key().rfind(kFakeDataPrefix, 0), 0U); |
| } |
| std::move(closure).Run(); |
| } |
| |
| void GetEvaluationCartHiddenStatus(base::OnceClosure closure, |
| bool isHidden, |
| bool result, |
| ShoppingCarts found) { |
| EXPECT_EQ(1U, found.size()); |
| EXPECT_EQ(isHidden, found[0].second.is_hidden()); |
| std::move(closure).Run(); |
| } |
| |
| void GetEvaluationCartRemovedStatus(base::OnceClosure closure, |
| bool isRemoved, |
| bool result, |
| ShoppingCarts found) { |
| EXPECT_EQ(1U, found.size()); |
| EXPECT_EQ(isRemoved, found[0].second.is_removed()); |
| std::move(closure).Run(); |
| } |
| |
| void GetEvaluationCartTimeStamp(base::OnceClosure closure, |
| double expect_timestamp, |
| bool result, |
| ShoppingCarts found) { |
| EXPECT_EQ(1U, found.size()); |
| EXPECT_EQ(expect_timestamp, found[0].second.timestamp()); |
| std::move(closure).Run(); |
| } |
| |
| std::string getDomainName(base::StringPiece domain) { |
| std::string* res = service_->domain_name_mapping_->FindStringKey(domain); |
| if (!res) |
| return ""; |
| return *res; |
| } |
| |
| std::string getDomainCartURL(base::StringPiece domain) { |
| std::string* res = |
| service_->domain_cart_url_mapping_->FindStringKey(domain); |
| if (!res) |
| return ""; |
| return *res; |
| } |
| |
| void TearDown() override {} |
| |
| protected: |
| // This needs to be destroyed after task_environment, so that any tasks on |
| // other threads that might check if features are enabled complete first. |
| base::test::ScopedFeatureList features_; |
| |
| // Required to run tests from UI thread. |
| content::BrowserTaskEnvironment task_environment_; |
| TestingProfile profile_; |
| CartService* service_; |
| }; |
| |
| // Verifies the hide status is flipped by hiding and restoring. |
| TEST_F(CartServiceTest, TestHideStatusChange) { |
| ASSERT_FALSE(service_->IsHidden()); |
| |
| service_->Hide(); |
| ASSERT_TRUE(service_->IsHidden()); |
| |
| service_->RestoreHidden(); |
| ASSERT_FALSE(service_->IsHidden()); |
| } |
| |
| // Tests adding one cart to the service. |
| TEST_F(CartServiceTest, TestAddCart) { |
| CartDB* cart_db_ = service_->GetDB(); |
| base::RunLoop run_loop[2]; |
| cart_db_->LoadAllCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[0].QuitClosure(), kEmptyExpected)); |
| run_loop[0].Run(); |
| |
| service_->AddCart(kMockMerchantA, base::nullopt, kMockProtoA); |
| task_environment_.RunUntilIdle(); |
| |
| cart_db_->LoadAllCarts(base::BindOnce(&CartServiceTest::GetEvaluationURL, |
| base::Unretained(this), |
| run_loop[1].QuitClosure(), kExpectedA)); |
| run_loop[1].Run(); |
| } |
| |
| // Test adding a cart with the same key and no product image won't overwrite |
| // existing proto. |
| TEST_F(CartServiceTest, TestAddCartWithNoProductImages) { |
| CartDB* cart_db_ = service_->GetDB(); |
| base::RunLoop run_loop[3]; |
| cart_db::ChromeCartContentProto merchant_A_proto = |
| BuildProto(kMockMerchantA, kMockMerchantURLA); |
| merchant_A_proto.set_timestamp(0); |
| merchant_A_proto.add_product_image_urls("https://image1.com"); |
| merchant_A_proto.set_is_hidden(true); |
| service_->AddCart(kMockMerchantA, base::nullopt, merchant_A_proto); |
| task_environment_.RunUntilIdle(); |
| |
| // Add a new proto with the same key and no product images. |
| cart_db::ChromeCartContentProto new_proto = |
| BuildProto(kMockMerchantA, kMockMerchantURLA); |
| new_proto.set_timestamp(1); |
| service_->AddCart(kMockMerchantA, base::nullopt, new_proto); |
| task_environment_.RunUntilIdle(); |
| |
| cart_db_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationCartHiddenStatus, |
| base::Unretained(this), run_loop[0].QuitClosure(), false)); |
| run_loop[0].Run(); |
| cart_db_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationCartTimeStamp, |
| base::Unretained(this), run_loop[1].QuitClosure(), 1)); |
| run_loop[1].Run(); |
| const ShoppingCarts result = {{kMockMerchantA, merchant_A_proto}}; |
| cart_db_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[2].QuitClosure(), result)); |
| run_loop[2].Run(); |
| } |
| |
| // Test adding a cart with the same key and some product images would overwrite |
| // existing proto. |
| TEST_F(CartServiceTest, TestAddCartWithProductImages) { |
| CartDB* cart_db_ = service_->GetDB(); |
| base::RunLoop run_loop[3]; |
| cart_db::ChromeCartContentProto merchant_A_proto = |
| BuildProto(kMockMerchantA, kMockMerchantURLA); |
| merchant_A_proto.set_timestamp(0); |
| merchant_A_proto.add_product_image_urls("https://image1.com"); |
| merchant_A_proto.set_is_hidden(true); |
| service_->AddCart(kMockMerchantA, base::nullopt, merchant_A_proto); |
| task_environment_.RunUntilIdle(); |
| |
| // Add a new proto with the same key and some product images. |
| cart_db::ChromeCartContentProto new_proto = |
| BuildProto(kMockMerchantA, kMockMerchantURLA); |
| new_proto.set_timestamp(1); |
| new_proto.add_product_image_urls("https://image2.com"); |
| service_->AddCart(kMockMerchantA, base::nullopt, new_proto); |
| task_environment_.RunUntilIdle(); |
| |
| cart_db_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationCartHiddenStatus, |
| base::Unretained(this), run_loop[0].QuitClosure(), false)); |
| run_loop[0].Run(); |
| cart_db_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationCartTimeStamp, |
| base::Unretained(this), run_loop[1].QuitClosure(), 1)); |
| run_loop[1].Run(); |
| const ShoppingCarts result = {{kMockMerchantA, new_proto}}; |
| cart_db_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[2].QuitClosure(), result)); |
| run_loop[2].Run(); |
| } |
| |
| // Test adding a cart that has been removed would not take effect. |
| TEST_F(CartServiceTest, TestAddRemovedCart) { |
| CartDB* cart_db_ = service_->GetDB(); |
| base::RunLoop run_loop[3]; |
| cart_db::ChromeCartContentProto merchant_A_proto = |
| BuildProto(kMockMerchantA, kMockMerchantURLA); |
| merchant_A_proto.set_timestamp(0); |
| merchant_A_proto.add_product_image_urls("https://image1.com"); |
| merchant_A_proto.set_is_removed(true); |
| service_->AddCart(kMockMerchantA, base::nullopt, merchant_A_proto); |
| task_environment_.RunUntilIdle(); |
| |
| // Add a new proto with the same key and some product images. |
| cart_db::ChromeCartContentProto new_proto = |
| BuildProto(kMockMerchantA, kMockMerchantURLA); |
| new_proto.set_timestamp(2); |
| new_proto.add_product_image_urls("https://image2.com"); |
| service_->AddCart(kMockMerchantA, base::nullopt, new_proto); |
| task_environment_.RunUntilIdle(); |
| |
| cart_db_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationCartRemovedStatus, |
| base::Unretained(this), run_loop[0].QuitClosure(), true)); |
| run_loop[0].Run(); |
| cart_db_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationCartTimeStamp, |
| base::Unretained(this), run_loop[1].QuitClosure(), 0)); |
| run_loop[1].Run(); |
| const ShoppingCarts result = {{kMockMerchantA, merchant_A_proto}}; |
| cart_db_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[2].QuitClosure(), result)); |
| run_loop[2].Run(); |
| } |
| |
| // Tests deleting one cart from the service. |
| TEST_F(CartServiceTest, TestDeleteCart) { |
| CartDB* cart_db_ = service_->GetDB(); |
| base::RunLoop run_loop[3]; |
| cart_db_->AddCart( |
| kMockMerchantA, kMockProtoA, |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[0].QuitClosure(), true)); |
| run_loop[0].Run(); |
| |
| cart_db_->LoadAllCarts(base::BindOnce(&CartServiceTest::GetEvaluationURL, |
| base::Unretained(this), |
| run_loop[1].QuitClosure(), kExpectedA)); |
| run_loop[1].Run(); |
| |
| service_->DeleteCart(kMockMerchantA); |
| |
| cart_db_->LoadAllCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[2].QuitClosure(), kEmptyExpected)); |
| run_loop[2].Run(); |
| } |
| |
| // Tests loading one cart from the service. |
| TEST_F(CartServiceTest, TestLoadCart) { |
| CartDB* cart_db_ = service_->GetDB(); |
| base::RunLoop run_loop[3]; |
| cart_db_->AddCart( |
| kMockMerchantA, kMockProtoA, |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[0].QuitClosure(), true)); |
| run_loop[0].Run(); |
| |
| service_->LoadCart( |
| kMockMerchantB, |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[1].QuitClosure(), kEmptyExpected)); |
| run_loop[1].Run(); |
| |
| service_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[2].QuitClosure(), kExpectedA)); |
| run_loop[2].Run(); |
| } |
| |
| // Tests loading all active carts from the service. |
| TEST_F(CartServiceTest, TestLoadAllActiveCarts) { |
| CartDB* cart_db_ = service_->GetDB(); |
| base::RunLoop run_loop[8]; |
| cart_db_->AddCart( |
| kMockMerchantA, kMockProtoA, |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[0].QuitClosure(), true)); |
| run_loop[0].Run(); |
| |
| service_->LoadAllActiveCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[1].QuitClosure(), kExpectedA)); |
| run_loop[1].Run(); |
| |
| cart_db_->AddCart( |
| kMockMerchantB, kMockProtoB, |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[2].QuitClosure(), true)); |
| run_loop[2].Run(); |
| |
| service_->LoadAllActiveCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[3].QuitClosure(), kExpectedAB)); |
| run_loop[3].Run(); |
| |
| service_->HideCart( |
| GURL(kMockMerchantURLB), |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[4].QuitClosure(), true)); |
| run_loop[4].Run(); |
| |
| service_->LoadAllActiveCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[5].QuitClosure(), kExpectedA)); |
| run_loop[5].Run(); |
| |
| service_->RemoveCart( |
| GURL(kMockMerchantURLA), |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[6].QuitClosure(), true)); |
| run_loop[6].Run(); |
| |
| service_->LoadAllActiveCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[7].QuitClosure(), kEmptyExpected)); |
| run_loop[7].Run(); |
| } |
| |
| // Verifies the database is cleared when detected history deletion. |
| TEST_F(CartServiceTest, TestOnHistoryDeletion) { |
| CartDB* cart_db_ = service_->GetDB(); |
| base::RunLoop run_loop[3]; |
| cart_db_->AddCart( |
| kMockMerchantA, kMockProtoA, |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[0].QuitClosure(), true)); |
| task_environment_.RunUntilIdle(); |
| run_loop[0].Run(); |
| |
| cart_db_->LoadAllCarts(base::BindOnce(&CartServiceTest::GetEvaluationURL, |
| base::Unretained(this), |
| run_loop[1].QuitClosure(), kExpectedA)); |
| task_environment_.RunUntilIdle(); |
| run_loop[1].Run(); |
| |
| service_->OnURLsDeleted( |
| HistoryServiceFactory::GetForProfile(&profile_, |
| ServiceAccessType::EXPLICIT_ACCESS), |
| history::DeletionInfo(history::DeletionTimeRange::Invalid(), false, |
| history::URLRows(), std::set<GURL>(), |
| base::nullopt)); |
| |
| cart_db_->LoadAllCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[2].QuitClosure(), kEmptyExpected)); |
| task_environment_.RunUntilIdle(); |
| run_loop[2].Run(); |
| } |
| |
| // Tests hiding a single cart and undoing the hide. |
| TEST_F(CartServiceTest, TestHideCart) { |
| CartDB* cart_db_ = service_->GetDB(); |
| base::RunLoop run_loop[6]; |
| cart_db_->AddCart( |
| kMockMerchantA, kMockProtoA, |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[0].QuitClosure(), true)); |
| run_loop[0].Run(); |
| |
| service_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationCartHiddenStatus, |
| base::Unretained(this), run_loop[1].QuitClosure(), false)); |
| run_loop[1].Run(); |
| |
| service_->HideCart( |
| GURL(kMockMerchantURLA), |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[2].QuitClosure(), true)); |
| run_loop[2].Run(); |
| |
| service_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationCartHiddenStatus, |
| base::Unretained(this), run_loop[3].QuitClosure(), true)); |
| run_loop[3].Run(); |
| |
| service_->RestoreHiddenCart( |
| GURL(kMockMerchantURLA), |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[4].QuitClosure(), true)); |
| run_loop[4].Run(); |
| |
| service_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationCartHiddenStatus, |
| base::Unretained(this), run_loop[5].QuitClosure(), false)); |
| run_loop[5].Run(); |
| } |
| |
| // Tests removing a single cart and undoing the remove. |
| TEST_F(CartServiceTest, TestRemoveCart) { |
| CartDB* cart_db_ = service_->GetDB(); |
| base::RunLoop run_loop[6]; |
| cart_db_->AddCart( |
| kMockMerchantA, kMockProtoA, |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[0].QuitClosure(), true)); |
| run_loop[0].Run(); |
| |
| service_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationCartRemovedStatus, |
| base::Unretained(this), run_loop[1].QuitClosure(), false)); |
| run_loop[1].Run(); |
| |
| service_->RemoveCart( |
| GURL(kMockMerchantURLA), |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[2].QuitClosure(), true)); |
| run_loop[2].Run(); |
| |
| service_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationCartRemovedStatus, |
| base::Unretained(this), run_loop[3].QuitClosure(), true)); |
| run_loop[3].Run(); |
| |
| service_->RestoreRemovedCart( |
| GURL(kMockMerchantURLA), |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[4].QuitClosure(), true)); |
| run_loop[4].Run(); |
| |
| service_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationCartRemovedStatus, |
| base::Unretained(this), run_loop[5].QuitClosure(), false)); |
| run_loop[5].Run(); |
| } |
| |
| // Tests after service shutdown, content of removed cart entries are deleted |
| // from database except for the removed status data. |
| TEST_F(CartServiceTest, TestRemovedCartsDeleted) { |
| CartDB* cart_db_ = service_->GetDB(); |
| base::RunLoop run_loop[6]; |
| cart_db::ChromeCartContentProto merchant_A_proto = |
| BuildProto(kMockMerchantA, kMockMerchantURLA); |
| merchant_A_proto.add_product_image_urls("https://image1.com"); |
| cart_db_->AddCart( |
| kMockMerchantA, merchant_A_proto, |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[0].QuitClosure(), true)); |
| run_loop[0].Run(); |
| |
| service_->RemoveCart( |
| GURL(kMockMerchantURLA), |
| base::BindOnce(&CartServiceTest::OperationEvaluation, |
| base::Unretained(this), run_loop[1].QuitClosure(), true)); |
| run_loop[1].Run(); |
| |
| cart_db_->LoadAllCarts(base::BindOnce(&CartServiceTest::GetEvaluationURL, |
| base::Unretained(this), |
| run_loop[2].QuitClosure(), kExpectedA)); |
| run_loop[2].Run(); |
| |
| service_->LoadAllActiveCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[3].QuitClosure(), kEmptyExpected)); |
| run_loop[3].Run(); |
| |
| service_->Shutdown(); |
| task_environment_.RunUntilIdle(); |
| |
| // After shut down, cart content is removed and only the removed status is |
| // kept. |
| cart_db::ChromeCartContentProto empty_proto; |
| empty_proto.set_key(kMockMerchantA); |
| empty_proto.set_is_removed(true); |
| const ShoppingCarts result = {{kMockMerchantA, empty_proto}}; |
| cart_db_->LoadAllCarts(base::BindOnce(&CartServiceTest::GetEvaluationURL, |
| base::Unretained(this), |
| run_loop[4].QuitClosure(), result)); |
| run_loop[4].Run(); |
| cart_db_->LoadAllCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationCartRemovedStatus, |
| base::Unretained(this), run_loop[5].QuitClosure(), true)); |
| run_loop[5].Run(); |
| } |
| |
| // Tests whether to show the welcome surface is correctly controlled. |
| TEST_F(CartServiceTest, TestControlShowWelcomeSurface) { |
| const int limit = CartService::kWelcomSurfaceShowLimit; |
| for (int i = 0; i < limit; i++) { |
| EXPECT_EQ(i, profile_.GetPrefs()->GetInteger( |
| prefs::kCartModuleWelcomeSurfaceShownTimes)); |
| EXPECT_TRUE(service_->ShouldShowWelcomSurface()); |
| service_->IncreaseWelcomeSurfaceCounter(); |
| } |
| EXPECT_FALSE(service_->ShouldShowWelcomSurface()); |
| EXPECT_EQ(limit, profile_.GetPrefs()->GetInteger( |
| prefs::kCartModuleWelcomeSurfaceShownTimes)); |
| } |
| |
| // Tests cart data is loaded in the order of timestamp. |
| TEST_F(CartServiceTest, TestOrderInTimestamp) { |
| base::RunLoop run_loop[3]; |
| double time_now = base::Time::Now().ToDoubleT(); |
| cart_db::ChromeCartContentProto merchant_A_proto = |
| BuildProto(kMockMerchantA, kMockMerchantURLA); |
| merchant_A_proto.set_timestamp(time_now); |
| cart_db::ChromeCartContentProto merchant_B_proto = |
| BuildProto(kMockMerchantB, kMockMerchantURLB); |
| merchant_B_proto.set_timestamp(time_now + 1); |
| cart_db::ChromeCartContentProto merchant_C_proto = |
| BuildProto(kMockMerchantC, kMockMerchantURLC); |
| merchant_C_proto.set_timestamp(time_now + 2); |
| service_->AddCart(kMockMerchantA, base::nullopt, merchant_A_proto); |
| service_->AddCart(kMockMerchantB, base::nullopt, merchant_B_proto); |
| service_->AddCart(kMockMerchantC, base::nullopt, merchant_C_proto); |
| task_environment_.RunUntilIdle(); |
| |
| const ShoppingCarts result1 = {{kMockMerchantC, merchant_C_proto}, |
| {kMockMerchantB, merchant_B_proto}, |
| {kMockMerchantA, merchant_A_proto}}; |
| service_->LoadAllActiveCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[0].QuitClosure(), result1)); |
| run_loop[0].Run(); |
| |
| merchant_A_proto.set_timestamp(time_now + 3); |
| service_->AddCart(kMockMerchantA, base::nullopt, merchant_A_proto); |
| task_environment_.RunUntilIdle(); |
| const ShoppingCarts result2 = {{kMockMerchantA, merchant_A_proto}, |
| {kMockMerchantC, merchant_C_proto}, |
| {kMockMerchantB, merchant_B_proto}}; |
| service_->LoadAllActiveCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[1].QuitClosure(), result2)); |
| run_loop[1].Run(); |
| |
| merchant_C_proto.set_timestamp(time_now + 4); |
| service_->AddCart(kMockMerchantC, base::nullopt, merchant_C_proto); |
| task_environment_.RunUntilIdle(); |
| const ShoppingCarts result3 = {{kMockMerchantC, merchant_C_proto}, |
| {kMockMerchantA, merchant_A_proto}, |
| {kMockMerchantB, merchant_B_proto}}; |
| service_->LoadAllActiveCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[2].QuitClosure(), result3)); |
| run_loop[2].Run(); |
| } |
| |
| // Tests domain to merchant name mapping. |
| TEST_F(CartServiceTest, TestDomainToNameMapping) { |
| EXPECT_EQ("Amazon", getDomainName("amazon.com")); |
| |
| EXPECT_EQ("eBay", getDomainName("ebay.com")); |
| |
| EXPECT_EQ("", getDomainName("example.com")); |
| } |
| |
| // Tests domain to cart URL mapping. |
| TEST_F(CartServiceTest, TestDomainToCartURLMapping) { |
| EXPECT_EQ("https://www.amazon.com/gp/cart/view.html", |
| getDomainCartURL("amazon.com")); |
| |
| EXPECT_EQ("https://cart.ebay.com/", getDomainCartURL("ebay.com")); |
| |
| EXPECT_EQ("", getDomainCartURL("example.com")); |
| } |
| |
| // Tests looking up cart URL and merchant name when adding cart. |
| TEST_F(CartServiceTest, TestLookupCartInfo) { |
| CartDB* cart_db_ = service_->GetDB(); |
| const char* amazon_domain = "amazon.com"; |
| base::RunLoop run_loop[3]; |
| cart_db::ChromeCartContentProto merchant_A_proto = |
| BuildProto(amazon_domain, kMockMerchantURLA); |
| service_->AddCart(amazon_domain, base::nullopt, merchant_A_proto); |
| task_environment_.RunUntilIdle(); |
| |
| merchant_A_proto.set_merchant_cart_url(getDomainCartURL(amazon_domain)); |
| merchant_A_proto.set_merchant(getDomainName(amazon_domain)); |
| const ShoppingCarts result1 = {{amazon_domain, merchant_A_proto}}; |
| cart_db_->LoadCart( |
| amazon_domain, |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[1].QuitClosure(), result1)); |
| run_loop[1].Run(); |
| |
| // Use default value when no info can be found in the lookup table. |
| service_->DeleteCart(amazon_domain); |
| const char* fake_domain = "fake.com"; |
| const char* fake_cart_url = "fake.com/cart"; |
| cart_db::ChromeCartContentProto fake_proto = |
| BuildProto(fake_domain, fake_cart_url); |
| service_->AddCart(fake_domain, base::nullopt, fake_proto); |
| task_environment_.RunUntilIdle(); |
| |
| const ShoppingCarts result2 = {{fake_domain, fake_proto}}; |
| cart_db_->LoadCart( |
| fake_domain, |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[2].QuitClosure(), result2)); |
| run_loop[2].Run(); |
| } |
| |
| // Tests the priority of cart URL sources. |
| TEST_F(CartServiceTest, CartURLPriority) { |
| const char amazon_domain[] = "amazon.com"; |
| const char example_domain[] = "example.com"; |
| GURL amazon_cart = GURL("http://amazon.com/mycart"); |
| GURL amazon_cart2 = GURL("http://amazon.com/shopping-cart"); |
| cart_db::ChromeCartContentProto merchant_A_proto = |
| BuildProto(amazon_domain, kMockMerchantURLA); |
| |
| // The priority of shopping cart URL from highest: |
| // - The navigation URL when visiting carts |
| // - The existing URL in the cart entry if exist |
| // - The look-up table by eTLD+1 domain |
| // - The navigation URL |
| |
| // * Lowest priority: no overriding. |
| service_->AddCart(example_domain, base::nullopt, merchant_A_proto); |
| task_environment_.RunUntilIdle(); |
| EXPECT_EQ(GetCartURL(example_domain), kMockMerchantURLA); |
| |
| // * Higher priority: from look up table. |
| service_->AddCart(amazon_domain, base::nullopt, merchant_A_proto); |
| task_environment_.RunUntilIdle(); |
| EXPECT_EQ(GetCartURL(amazon_domain), |
| "https://www.amazon.com/gp/cart/view.html"); |
| service_->DeleteCart(amazon_domain); |
| |
| // * Higher priority: from existing entry. |
| service_->AddCart(amazon_domain, amazon_cart, merchant_A_proto); |
| task_environment_.RunUntilIdle(); |
| EXPECT_EQ(GetCartURL(amazon_domain), amazon_cart.spec()); |
| service_->AddCart(amazon_domain, base::nullopt, merchant_A_proto); |
| task_environment_.RunUntilIdle(); |
| // Lookup table cannot override existing entry. |
| EXPECT_EQ(GetCartURL(amazon_domain), amazon_cart.spec()); |
| service_->DeleteCart(amazon_domain); |
| |
| // * Highest priority: overriding existing entry. |
| service_->AddCart(amazon_domain, base::nullopt, merchant_A_proto); |
| task_environment_.RunUntilIdle(); |
| EXPECT_EQ(GetCartURL(amazon_domain), |
| "https://www.amazon.com/gp/cart/view.html"); |
| service_->AddCart(amazon_domain, amazon_cart, merchant_A_proto); |
| task_environment_.RunUntilIdle(); |
| // Visiting carts can override existing entry. |
| EXPECT_EQ(GetCartURL(amazon_domain), amazon_cart.spec()); |
| service_->DeleteCart(amazon_domain); |
| // New visiting carts can override existing entry from earlier visiting carts. |
| service_->AddCart(amazon_domain, amazon_cart, merchant_A_proto); |
| task_environment_.RunUntilIdle(); |
| EXPECT_EQ(GetCartURL(amazon_domain), amazon_cart.spec()); |
| service_->AddCart(amazon_domain, amazon_cart2, merchant_A_proto); |
| task_environment_.RunUntilIdle(); |
| EXPECT_EQ(GetCartURL(amazon_domain), amazon_cart2.spec()); |
| service_->AddCart(amazon_domain, amazon_cart, merchant_A_proto); |
| task_environment_.RunUntilIdle(); |
| EXPECT_EQ(GetCartURL(amazon_domain), amazon_cart.spec()); |
| } |
| |
| class CartServiceTestWithFeature : public CartServiceTest { |
| public: |
| // Features need to be initialized before CartServiceTest::SetUp runs, in |
| // order to avoid tsan data race error on FeatureList. |
| CartServiceTestWithFeature() { |
| features_.InitAndEnableFeatureWithParameters( |
| ntp_features::kNtpChromeCartModule, |
| {{"NtpChromeCartModuleDataParam", "fake"}}); |
| } |
| }; |
| |
| TEST_F(CartServiceTestWithFeature, TestFakeData) { |
| base::RunLoop run_loop[2]; |
| TestingProfile fake_profile; |
| CartService* fake_service = CartServiceFactory::GetForProfile(&fake_profile); |
| CartDB* fake_db = fake_service->GetDB(); |
| |
| fake_service->LoadCartsWithFakeData( |
| base::BindOnce(&CartServiceTest::GetEvaluationFakeDataDB, |
| base::Unretained(this), run_loop[0].QuitClosure())); |
| run_loop[0].Run(); |
| |
| fake_service->Shutdown(); |
| |
| fake_db->LoadAllCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[1].QuitClosure(), kEmptyExpected)); |
| run_loop[1].Run(); |
| } |
| |
| // Tests expired entries are deleted when data is loaded. |
| TEST_F(CartServiceTest, TestExpiredDataDeleted) { |
| base::RunLoop run_loop[3]; |
| cart_db::ChromeCartContentProto merchant_proto = |
| BuildProto(kMockMerchantA, kMockMerchantURLA); |
| |
| merchant_proto.set_timestamp( |
| (base::Time::Now() - base::TimeDelta::FromDays(16)).ToDoubleT()); |
| service_->AddCart(kMockMerchantA, base::nullopt, merchant_proto); |
| task_environment_.RunUntilIdle(); |
| |
| // The expired entry is deleted in load results. |
| service_->LoadAllActiveCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[0].QuitClosure(), kEmptyExpected)); |
| run_loop[0].Run(); |
| |
| // The expired entry is deleted in database. |
| service_->LoadCart( |
| kMockMerchantA, |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[1].QuitClosure(), kEmptyExpected)); |
| run_loop[1].Run(); |
| |
| merchant_proto.set_timestamp( |
| (base::Time::Now() - base::TimeDelta::FromDays(13)).ToDoubleT()); |
| service_->AddCart(kMockMerchantA, base::nullopt, merchant_proto); |
| task_environment_.RunUntilIdle(); |
| |
| const ShoppingCarts result = {{kMockMerchantA, merchant_proto}}; |
| service_->LoadAllActiveCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[2].QuitClosure(), result)); |
| run_loop[2].Run(); |
| } |
| |
| // Tests cart-related actions would reshow hidden module. |
| TEST_F(CartServiceTest, TestHiddenFlipedByCartAction) { |
| base::RunLoop run_loop[3]; |
| cart_db::ChromeCartContentProto merchant_proto = |
| BuildProto(kMockMerchantA, kMockMerchantURLA); |
| const ShoppingCarts result = {{kMockMerchantA, merchant_proto}}; |
| service_->AddCart(kMockMerchantA, base::nullopt, merchant_proto); |
| task_environment_.RunUntilIdle(); |
| service_->LoadAllActiveCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[0].QuitClosure(), result)); |
| run_loop[0].Run(); |
| |
| service_->Hide(); |
| ASSERT_TRUE(service_->IsHidden()); |
| service_->LoadAllActiveCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[1].QuitClosure(), kEmptyExpected)); |
| run_loop[1].Run(); |
| |
| service_->AddCart(kMockMerchantA, base::nullopt, merchant_proto); |
| task_environment_.RunUntilIdle(); |
| ASSERT_FALSE(service_->IsHidden()); |
| service_->LoadAllActiveCarts( |
| base::BindOnce(&CartServiceTest::GetEvaluationURL, base::Unretained(this), |
| run_loop[2].QuitClosure(), result)); |
| run_loop[2].Run(); |
| } |