Not trigger product specifications entry point for same products
This CL updates ClusterManager so that when returning similar products, it will not only return URLs but also product IDs of the products. This is needed by the tab strip entry point because when checking if the current window is eligible for showing the entry point, we need to count the number of unique products in the current window. Please note that in this CL, we only fetch ProductInfo of open tabs and expect no on-demand ProductInfo fetches. Bug: b/343109881 Change-Id: I947f33bc223c75c0efc3c78485e9a5440b370d60 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5582103 Commit-Queue: Yue Zhang <yuezhanggg@chromium.org> Reviewed-by: Matthew Jones <mdjones@chromium.org> Cr-Commit-Position: refs/heads/main@{#1310704}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
e314ced3ec
commit
f034625d24
chrome/browser/ui/commerce
product_specifications_entry_point_controller.ccproduct_specifications_entry_point_controller.hproduct_specifications_entry_point_controller_browsertest.cc
components/commerce/core
@ -28,22 +28,22 @@ bool CheckWindowContainsEntryPointURLs(
|
||||
TabStripModel* tab_strip_model,
|
||||
commerce::EntryPointInfo entry_point_info,
|
||||
size_t threshold) {
|
||||
std::set<GURL> similar_urls =
|
||||
entry_point_info.similar_candidate_products_urls;
|
||||
if (similar_urls.size() < threshold) {
|
||||
std::map<GURL, uint64_t> similar_products =
|
||||
entry_point_info.similar_candidate_products;
|
||||
if (similar_products.size() < threshold) {
|
||||
return false;
|
||||
}
|
||||
std::set<GURL> eligible_urls_in_current_window;
|
||||
std::set<uint64_t> similar_product_ids;
|
||||
for (int i = 0; i < tab_strip_model->count(); i++) {
|
||||
GURL tab_url = tab_strip_model->GetWebContentsAt(i)->GetLastCommittedURL();
|
||||
if (similar_urls.find(tab_url) != similar_urls.end()) {
|
||||
eligible_urls_in_current_window.insert(tab_url);
|
||||
if (eligible_urls_in_current_window.size() >= threshold) {
|
||||
if (similar_products.find(tab_url) != similar_products.end()) {
|
||||
similar_product_ids.insert(similar_products[tab_url]);
|
||||
if (similar_product_ids.size() >= threshold) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return eligible_urls_in_current_window.size() >= threshold;
|
||||
return similar_product_ids.size() >= threshold;
|
||||
}
|
||||
|
||||
bool IsWindowValidForEntryPoint(TabStripModel* tab_strip_model,
|
||||
@ -97,13 +97,14 @@ void ProductSpecificationsEntryPointController::OnTabStripModelChanged(
|
||||
!selection.new_contents || !cluster_manager_) {
|
||||
return;
|
||||
}
|
||||
const GURL old_url = selection.old_contents->GetLastCommittedURL();
|
||||
const GURL new_url = selection.new_contents->GetLastCommittedURL();
|
||||
|
||||
cluster_manager_->GetEntryPointInfoForSelection(
|
||||
selection.old_contents->GetLastCommittedURL(),
|
||||
selection.new_contents->GetLastCommittedURL(),
|
||||
old_url, new_url,
|
||||
base::BindOnce(&ProductSpecificationsEntryPointController::
|
||||
ShowEntryPointWithTitleForSelection,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
weak_ptr_factory_.GetWeakPtr(), old_url, new_url));
|
||||
}
|
||||
|
||||
void ProductSpecificationsEntryPointController::TabChangedAt(
|
||||
@ -134,7 +135,7 @@ void ProductSpecificationsEntryPointController::OnEntryPointExecuted() {
|
||||
DCHECK(product_specifications_service_);
|
||||
std::set<GURL> urls;
|
||||
auto candidate_products =
|
||||
current_entry_point_info_->similar_candidate_products_urls;
|
||||
current_entry_point_info_->similar_candidate_products;
|
||||
for (auto url_info : shopping_service_->GetUrlInfosForActiveWebWrappers()) {
|
||||
if (base::Contains(candidate_products, url_info.url)) {
|
||||
urls.insert(url_info.url);
|
||||
@ -179,11 +180,22 @@ void ProductSpecificationsEntryPointController::OnClusterFinishedForNavigation(
|
||||
|
||||
void ProductSpecificationsEntryPointController::
|
||||
ShowEntryPointWithTitleForSelection(
|
||||
const GURL old_url,
|
||||
const GURL new_url,
|
||||
std::optional<EntryPointInfo> entry_point_info) {
|
||||
if (!entry_point_info.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<GURL, uint64_t> similar_products =
|
||||
entry_point_info->similar_candidate_products;
|
||||
if (similar_products.find(old_url) == similar_products.end() ||
|
||||
similar_products.find(new_url) == similar_products.end()) {
|
||||
return;
|
||||
}
|
||||
if (similar_products[old_url] == similar_products[new_url]) {
|
||||
return;
|
||||
}
|
||||
// TODO(qinmin): we should check whether tabstrips have changed while
|
||||
// waiting for the callback.
|
||||
ShowEntryPointWithTitle(std::move(entry_point_info));
|
||||
|
@ -77,6 +77,8 @@ class ProductSpecificationsEntryPointController
|
||||
|
||||
// Show the tab strip entry point for tab selection.
|
||||
void ShowEntryPointWithTitleForSelection(
|
||||
const GURL old_url,
|
||||
const GURL new_url,
|
||||
std::optional<EntryPointInfo> entry_point_info);
|
||||
|
||||
// Show the tab strip entry point for navigation.
|
||||
|
@ -29,6 +29,10 @@ const char kTestUrl2[] = "chrome://version/";
|
||||
const char kTestUrl3[] = "chrome://flags/";
|
||||
const char kTestUrl4[] = "chrome://management/";
|
||||
|
||||
static const int64_t kProductId1 = 1;
|
||||
static const int64_t kProductId2 = 2;
|
||||
static const int64_t kProductId3 = 3;
|
||||
static const int64_t kProductId4 = 4;
|
||||
} // namespace
|
||||
|
||||
class MockObserver
|
||||
@ -108,9 +112,11 @@ class ProductSpecificationsEntryPointControllerBrowserTest
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(ProductSpecificationsEntryPointControllerBrowserTest,
|
||||
TriggerEntryPointWithSelection) {
|
||||
// Mock EntryPointInfo returned by ShoppingService.
|
||||
// Mock EntryPointInfo returned by ClusterManager.
|
||||
std::map<GURL, uint64_t> similar_products = {{GURL(kTestUrl1), kProductId1},
|
||||
{GURL(kTestUrl2), kProductId2}};
|
||||
auto info =
|
||||
std::make_optional<commerce::EntryPointInfo>(kTitle, std::set<GURL>());
|
||||
std::make_optional<commerce::EntryPointInfo>(kTitle, similar_products);
|
||||
mock_cluster_manager_->SetResponseForGetEntryPointInfoForSelection(info);
|
||||
|
||||
// Set up observer.
|
||||
@ -131,11 +137,43 @@ IN_PROC_BROWSER_TEST_F(ProductSpecificationsEntryPointControllerBrowserTest,
|
||||
ASSERT_TRUE(controller_->entry_point_info_for_testing().has_value());
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(ProductSpecificationsEntryPointControllerBrowserTest,
|
||||
TriggerEntryPointWithSelection_NotShowForSameProduct) {
|
||||
// Mock EntryPointInfo returned by ClusterManager which contains two products
|
||||
// with the same product ID.
|
||||
std::map<GURL, uint64_t> similar_products = {{GURL(kTestUrl1), kProductId1},
|
||||
{GURL(kTestUrl2), kProductId1}};
|
||||
auto info =
|
||||
std::make_optional<commerce::EntryPointInfo>(kTitle, similar_products);
|
||||
mock_cluster_manager_->SetResponseForGetEntryPointInfoForSelection(info);
|
||||
|
||||
// Set up observer.
|
||||
EXPECT_CALL(*observer_, ShowEntryPointWithTitle(kTitle)).Times(0);
|
||||
|
||||
// Create two tabs and simulate selection.
|
||||
ASSERT_TRUE(AddTabAtIndexToBrowser(browser(), 0, GURL(kTestUrl1),
|
||||
ui::PAGE_TRANSITION_LINK, true));
|
||||
ASSERT_TRUE(AddTabAtIndexToBrowser(browser(), 1, GURL(kTestUrl2),
|
||||
ui::PAGE_TRANSITION_LINK, true));
|
||||
base::RunLoop().RunUntilIdle();
|
||||
ASSERT_FALSE(controller_->entry_point_info_for_testing().has_value());
|
||||
|
||||
browser()->tab_strip_model()->ActivateTabAt(
|
||||
0, TabStripUserGestureDetails(
|
||||
TabStripUserGestureDetails::GestureType::kMouse));
|
||||
base::RunLoop().RunUntilIdle();
|
||||
// Not trigger entry point because the two products have the same product ID.
|
||||
ASSERT_FALSE(controller_->entry_point_info_for_testing().has_value());
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(ProductSpecificationsEntryPointControllerBrowserTest,
|
||||
TriggerEntryPointWithNavigation) {
|
||||
// Mock EntryPointInfo returned by ShoppingService.
|
||||
std::set<GURL> urls = {GURL(kTestUrl2), GURL(kTestUrl3), GURL(kTestUrl4)};
|
||||
auto info = std::make_optional<commerce::EntryPointInfo>(kTitle, urls);
|
||||
// Mock EntryPointInfo returned by ClusterManager.
|
||||
std::map<GURL, uint64_t> similar_products = {{GURL(kTestUrl2), kProductId2},
|
||||
{GURL(kTestUrl3), kProductId3},
|
||||
{GURL(kTestUrl4), kProductId4}};
|
||||
auto info =
|
||||
std::make_optional<commerce::EntryPointInfo>(kTitle, similar_products);
|
||||
mock_cluster_manager_->SetResponseForGetEntryPointInfoForNavigation(info);
|
||||
|
||||
// Set up observer.
|
||||
@ -162,11 +200,48 @@ IN_PROC_BROWSER_TEST_F(ProductSpecificationsEntryPointControllerBrowserTest,
|
||||
ASSERT_TRUE(controller_->entry_point_info_for_testing().has_value());
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(ProductSpecificationsEntryPointControllerBrowserTest,
|
||||
TriggerEntryPointWithNavigation_NotShowForSameProduct) {
|
||||
// Mock EntryPointInfo returned by ClusterManager which contains two products
|
||||
// with the same product ID.
|
||||
std::map<GURL, uint64_t> similar_products = {{GURL(kTestUrl2), kProductId2},
|
||||
{GURL(kTestUrl3), kProductId2},
|
||||
{GURL(kTestUrl4), kProductId4}};
|
||||
auto info =
|
||||
std::make_optional<commerce::EntryPointInfo>(kTitle, similar_products);
|
||||
mock_cluster_manager_->SetResponseForGetEntryPointInfoForNavigation(info);
|
||||
|
||||
// Set up observer.
|
||||
EXPECT_CALL(*observer_, ShowEntryPointWithTitle(kTitle)).Times(0);
|
||||
|
||||
// Current window has to have more than three unique and different products
|
||||
// that are similar in order to trigger the entry point for navigation.
|
||||
std::vector<std::string> urls_to_open = {kTestUrl2, kTestUrl3, kTestUrl3,
|
||||
kTestUrl1};
|
||||
for (auto& url : urls_to_open) {
|
||||
ASSERT_TRUE(AddTabAtIndexToBrowser(browser(), 0, GURL(url),
|
||||
ui::PAGE_TRANSITION_LINK, true));
|
||||
base::RunLoop().RunUntilIdle();
|
||||
controller_->OnClusterFinishedForNavigation(GURL(url));
|
||||
base::RunLoop().RunUntilIdle();
|
||||
ASSERT_FALSE(controller_->entry_point_info_for_testing().has_value());
|
||||
}
|
||||
|
||||
ASSERT_TRUE(AddTabAtIndexToBrowser(browser(), 0, GURL(kTestUrl4),
|
||||
ui::PAGE_TRANSITION_LINK, true));
|
||||
base::RunLoop().RunUntilIdle();
|
||||
controller_->OnClusterFinishedForNavigation(GURL(kTestUrl4));
|
||||
base::RunLoop().RunUntilIdle();
|
||||
ASSERT_FALSE(controller_->entry_point_info_for_testing().has_value());
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(ProductSpecificationsEntryPointControllerBrowserTest,
|
||||
HideEntryPoint) {
|
||||
// Trigger entry point with selection.
|
||||
std::map<GURL, uint64_t> similar_products = {{GURL(kTestUrl1), kProductId1},
|
||||
{GURL(kTestUrl2), kProductId2}};
|
||||
auto info =
|
||||
std::make_optional<commerce::EntryPointInfo>(kTitle, std::set<GURL>());
|
||||
std::make_optional<commerce::EntryPointInfo>(kTitle, similar_products);
|
||||
mock_cluster_manager_->SetResponseForGetEntryPointInfoForSelection(info);
|
||||
ASSERT_TRUE(AddTabAtIndexToBrowser(browser(), 0, GURL(kTestUrl1),
|
||||
ui::PAGE_TRANSITION_LINK, true));
|
||||
@ -197,8 +272,10 @@ IN_PROC_BROWSER_TEST_F(ProductSpecificationsEntryPointControllerBrowserTest,
|
||||
.WillByDefault(testing::Return(set));
|
||||
|
||||
// Trigger entry point with selection.
|
||||
std::set<GURL> urls = {GURL(kTestUrl1), GURL(kTestUrl2)};
|
||||
auto info = std::make_optional<commerce::EntryPointInfo>(kTitle, urls);
|
||||
std::map<GURL, uint64_t> similar_products = {{GURL(kTestUrl1), kProductId1},
|
||||
{GURL(kTestUrl2), kProductId2}};
|
||||
auto info =
|
||||
std::make_optional<commerce::EntryPointInfo>(kTitle, similar_products);
|
||||
mock_cluster_manager_->SetResponseForGetEntryPointInfoForSelection(info);
|
||||
ASSERT_TRUE(AddTabAtIndexToBrowser(browser(), 0, GURL(kTestUrl1),
|
||||
ui::PAGE_TRANSITION_LINK, true));
|
||||
@ -234,8 +311,11 @@ IN_PROC_BROWSER_TEST_F(ProductSpecificationsEntryPointControllerBrowserTest,
|
||||
.WillByDefault(testing::Return(set));
|
||||
|
||||
// Mock EntryPointInfo returned by ShoppingService.
|
||||
std::set<GURL> urls = {GURL(kTestUrl2), GURL(kTestUrl3), GURL(kTestUrl4)};
|
||||
auto info = std::make_optional<commerce::EntryPointInfo>(kTitle, urls);
|
||||
std::map<GURL, uint64_t> similar_products = {{GURL(kTestUrl2), kProductId2},
|
||||
{GURL(kTestUrl3), kProductId3},
|
||||
{GURL(kTestUrl4), kProductId4}};
|
||||
auto info =
|
||||
std::make_optional<commerce::EntryPointInfo>(kTitle, similar_products);
|
||||
mock_cluster_manager_->SetResponseForGetEntryPointInfoForNavigation(info);
|
||||
|
||||
// Mock that there is only two currently open unique URLs based on
|
||||
@ -275,9 +355,12 @@ IN_PROC_BROWSER_TEST_F(ProductSpecificationsEntryPointControllerBrowserTest,
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(ProductSpecificationsEntryPointControllerBrowserTest,
|
||||
InvalidEntryPointWithNavigation) {
|
||||
// Mock EntryPointInfo returned by ShoppingService.
|
||||
std::set<GURL> urls = {GURL(kTestUrl2), GURL(kTestUrl3), GURL(kTestUrl4)};
|
||||
auto info = std::make_optional<commerce::EntryPointInfo>(kTitle, urls);
|
||||
// Mock EntryPointInfo returned by ClusterManager.
|
||||
std::map<GURL, uint64_t> similar_products = {{GURL(kTestUrl2), kProductId2},
|
||||
{GURL(kTestUrl3), kProductId3},
|
||||
{GURL(kTestUrl4), kProductId4}};
|
||||
auto info =
|
||||
std::make_optional<commerce::EntryPointInfo>(kTitle, similar_products);
|
||||
mock_cluster_manager_->SetResponseForGetEntryPointInfoForNavigation(info);
|
||||
|
||||
// Set up observer.
|
||||
@ -313,8 +396,11 @@ IN_PROC_BROWSER_TEST_F(ProductSpecificationsEntryPointControllerBrowserTest,
|
||||
IN_PROC_BROWSER_TEST_F(ProductSpecificationsEntryPointControllerBrowserTest,
|
||||
InvalidEntryPointWithClosure) {
|
||||
// Mock EntryPointInfo returned by ShoppingService.
|
||||
std::set<GURL> urls = {GURL(kTestUrl2), GURL(kTestUrl3), GURL(kTestUrl4)};
|
||||
auto info = std::make_optional<commerce::EntryPointInfo>(kTitle, urls);
|
||||
std::map<GURL, uint64_t> similar_products = {{GURL(kTestUrl2), kProductId2},
|
||||
{GURL(kTestUrl3), kProductId3},
|
||||
{GURL(kTestUrl4), kProductId4}};
|
||||
auto info =
|
||||
std::make_optional<commerce::EntryPointInfo>(kTitle, similar_products);
|
||||
mock_cluster_manager_->SetResponseForGetEntryPointInfoForNavigation(info);
|
||||
|
||||
// Set up observer.
|
||||
|
@ -64,11 +64,11 @@ UrlInfo::UrlInfo(const UrlInfo&) = default;
|
||||
UrlInfo& UrlInfo::operator=(const UrlInfo& other) = default;
|
||||
UrlInfo::~UrlInfo() = default;
|
||||
|
||||
EntryPointInfo::EntryPointInfo(const std::string& title,
|
||||
std::set<GURL> similar_candidate_products_urls)
|
||||
EntryPointInfo::EntryPointInfo(
|
||||
const std::string& title,
|
||||
std::map<GURL, uint64_t> similar_candidate_products)
|
||||
: title(title),
|
||||
similar_candidate_products_urls(
|
||||
std::move(similar_candidate_products_urls)) {}
|
||||
similar_candidate_products(std::move(similar_candidate_products)) {}
|
||||
|
||||
EntryPointInfo::~EntryPointInfo() = default;
|
||||
EntryPointInfo::EntryPointInfo(const EntryPointInfo&) = default;
|
||||
|
@ -240,7 +240,7 @@ struct UrlInfo {
|
||||
// Class representing the tap strip entry point.
|
||||
struct EntryPointInfo {
|
||||
EntryPointInfo(const std::string& title,
|
||||
std::set<GURL> similar_candidate_products_urls);
|
||||
std::map<GURL, uint64_t> similar_candidate_products);
|
||||
~EntryPointInfo();
|
||||
EntryPointInfo(const EntryPointInfo&);
|
||||
EntryPointInfo& operator=(const EntryPointInfo&);
|
||||
@ -248,9 +248,10 @@ struct EntryPointInfo {
|
||||
// Title of the product group to be clustered.
|
||||
std::string title;
|
||||
|
||||
// Set of URLs of candidate products that are similar and can
|
||||
// be clustered into one product group.
|
||||
std::set<GURL> similar_candidate_products_urls;
|
||||
// Map of candidate products that are similar and can
|
||||
// be clustered into one product group. Key is the product URL and value is
|
||||
// the product cluster ID.
|
||||
std::map<GURL, uint64_t> similar_candidate_products;
|
||||
};
|
||||
|
||||
// Callbacks and typedefs for various accessors in the shopping service.
|
||||
|
@ -115,6 +115,23 @@ void GetCategoryData(
|
||||
url, base::BindOnce(&OnGetCategoryDataDone, std::move(callback)));
|
||||
}
|
||||
|
||||
void OnGetProductInfoDone(
|
||||
base::OnceCallback<void(std::pair<GURL, const ProductInfo>)> callback,
|
||||
const GURL& url,
|
||||
const std::optional<const ProductInfo>& product_info) {
|
||||
std::pair<GURL, const ProductInfo> pair(
|
||||
url, product_info.has_value() ? product_info.value() : ProductInfo());
|
||||
std::move(callback).Run(std::move(pair));
|
||||
}
|
||||
|
||||
void GetProductInfo(
|
||||
const GURL& url,
|
||||
const ClusterManager::GetProductInfoCallback& get_product_info_cb,
|
||||
base::OnceCallback<void(std::pair<GURL, const ProductInfo>)> callback) {
|
||||
get_product_info_cb.Run(
|
||||
url, base::BindOnce(&OnGetProductInfoDone, std::move(callback)));
|
||||
}
|
||||
|
||||
bool IsCandidateProductInProductGroup(
|
||||
const GURL& candidate_product_url,
|
||||
const std::map<base::Uuid, std::unique_ptr<ProductGroup>>&
|
||||
@ -369,8 +386,16 @@ void ClusterManager::GetEntryPointInfoForNavigation(
|
||||
|
||||
std::optional<std::string> title =
|
||||
GetShortestLabelAtBottom(candidate_product_map_[url]->category_data);
|
||||
std::move(callback).Run(std::make_optional<EntryPointInfo>(
|
||||
title ? title.value() : "", std::move(similar_urls)));
|
||||
|
||||
auto barrier_callback =
|
||||
base::BarrierCallback<std::pair<GURL, const ProductInfo>>(
|
||||
similar_urls.size(),
|
||||
base::BindOnce(&ClusterManager::OnProductInfoFetchedForSimilarUrls,
|
||||
weak_ptr_factory_.GetWeakPtr(), title,
|
||||
std::move(callback)));
|
||||
for (const auto& similar_url : similar_urls) {
|
||||
GetProductInfo(similar_url, get_product_info_cb_, barrier_callback);
|
||||
}
|
||||
}
|
||||
|
||||
void ClusterManager::GetEntryPointInfoForSelection(
|
||||
@ -402,8 +427,30 @@ void ClusterManager::GetEntryPointInfoForSelection(
|
||||
} else {
|
||||
title = std::move(title_old);
|
||||
}
|
||||
|
||||
auto barrier_callback =
|
||||
base::BarrierCallback<std::pair<GURL, const ProductInfo>>(
|
||||
similar_urls.size(),
|
||||
base::BindOnce(&ClusterManager::OnProductInfoFetchedForSimilarUrls,
|
||||
weak_ptr_factory_.GetWeakPtr(), title,
|
||||
std::move(callback)));
|
||||
for (const auto& similar_url : similar_urls) {
|
||||
GetProductInfo(similar_url, get_product_info_cb_, barrier_callback);
|
||||
}
|
||||
}
|
||||
|
||||
void ClusterManager::OnProductInfoFetchedForSimilarUrls(
|
||||
std::optional<std::string> title,
|
||||
GetEntryPointInfoCallback callback,
|
||||
const std::vector<std::pair<GURL, const ProductInfo>>& product_infos) {
|
||||
std::map<GURL, uint64_t> map;
|
||||
for (auto pair : product_infos) {
|
||||
if (pair.second.product_cluster_id.has_value()) {
|
||||
map[pair.first] = pair.second.product_cluster_id.value();
|
||||
}
|
||||
}
|
||||
std::move(callback).Run(std::make_optional<EntryPointInfo>(
|
||||
title ? title.value() : "", std::move(similar_urls)));
|
||||
title ? title.value() : "", std::move(map)));
|
||||
}
|
||||
|
||||
void ClusterManager::OnGetComparableUrls(
|
||||
|
@ -135,6 +135,11 @@ class ClusterManager : public ProductSpecificationsSet::Observer {
|
||||
bool success,
|
||||
const std::set<GURL>& comparable_urls);
|
||||
|
||||
void OnProductInfoFetchedForSimilarUrls(
|
||||
std::optional<std::string> title,
|
||||
GetEntryPointInfoCallback callback,
|
||||
const std::vector<std::pair<GURL, const ProductInfo>>& product_infos);
|
||||
|
||||
std::unique_ptr<ClusterServerProxy> cluster_server_proxy_;
|
||||
|
||||
// Callback to get product info.
|
||||
|
@ -28,6 +28,12 @@
|
||||
|
||||
namespace commerce {
|
||||
namespace {
|
||||
static const uint64_t kProductID1 = 1;
|
||||
static const uint64_t kProductID2 = 2;
|
||||
static const uint64_t kProductID3 = 3;
|
||||
static const uint64_t kProductID4 = 4;
|
||||
static const uint64_t kProductID5 = 5;
|
||||
|
||||
const std::string kTestUrl1 = "http://www.foo1.com";
|
||||
const std::string kTestUrl2 = "http://www.foo2.com";
|
||||
const std::string kTestUrl3 = "http://www.foo3.com";
|
||||
@ -125,8 +131,9 @@ class ClusterManagerTest : public testing::Test {
|
||||
return CreateProductSpecificationsSet(url, 0);
|
||||
}
|
||||
|
||||
ProductInfo CreateProductInfo(const std::string& label) {
|
||||
ProductInfo CreateProductInfo(const std::string& label, int64_t product_id) {
|
||||
ProductInfo product_info = ProductInfo();
|
||||
product_info.product_cluster_id = product_id;
|
||||
product_info.category_data.add_product_categories()
|
||||
->add_category_labels()
|
||||
->set_category_default_label(label);
|
||||
@ -134,11 +141,16 @@ class ClusterManagerTest : public testing::Test {
|
||||
}
|
||||
|
||||
void InitializeProductInfos() {
|
||||
product_infos_[GURL(kTestUrl1)] = CreateProductInfo(kCategoryLamp);
|
||||
product_infos_[GURL(kTestUrl2)] = CreateProductInfo(kCategoryChair);
|
||||
product_infos_[GURL(kTestUrl3)] = CreateProductInfo(kCategoryLamp);
|
||||
product_infos_[GURL(kProduct1Url)] = CreateProductInfo(kCategoryLamp);
|
||||
product_infos_[GURL(kProduct2Url)] = CreateProductInfo(kCategoryChair);
|
||||
product_infos_[GURL(kTestUrl1)] =
|
||||
CreateProductInfo(kCategoryLamp, kProductID1);
|
||||
product_infos_[GURL(kTestUrl2)] =
|
||||
CreateProductInfo(kCategoryChair, kProductID2);
|
||||
product_infos_[GURL(kTestUrl3)] =
|
||||
CreateProductInfo(kCategoryLamp, kProductID3);
|
||||
product_infos_[GURL(kProduct1Url)] =
|
||||
CreateProductInfo(kCategoryLamp, kProductID4);
|
||||
product_infos_[GURL(kProduct2Url)] =
|
||||
CreateProductInfo(kCategoryChair, kProductID5);
|
||||
}
|
||||
|
||||
void GetEntryPointInfoForNavigation(const GURL& url,
|
||||
@ -256,18 +268,22 @@ TEST_F(ClusterManagerTest, GetEntryPointInfoForNavigation) {
|
||||
|
||||
std::optional<EntryPointInfo> info;
|
||||
GetEntryPointInfoForNavigation(foo1, &info);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.size(), 2u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo3), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.size(), 2u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products[foo1], kProductID1);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo3), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products[foo3], kProductID3);
|
||||
ASSERT_EQ(info->title, "Lamp");
|
||||
|
||||
GetEntryPointInfoForNavigation(foo2, &info);
|
||||
ASSERT_FALSE(info);
|
||||
|
||||
GetEntryPointInfoForNavigation(foo3, &info);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.size(), 2u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo3), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.size(), 2u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products[foo1], kProductID1);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo3), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products[foo3], kProductID3);
|
||||
ASSERT_EQ(info->title, "Lamp");
|
||||
}
|
||||
|
||||
@ -309,22 +325,22 @@ TEST_F(ClusterManagerTest,
|
||||
|
||||
std::optional<EntryPointInfo> info;
|
||||
GetEntryPointInfoForNavigation(foo1, &info);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.size(), 3u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo2), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo3), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.size(), 3u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo2), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo3), 1u);
|
||||
ASSERT_EQ(info->title, "Lamp");
|
||||
|
||||
GetEntryPointInfoForNavigation(foo2, &info);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.size(), 2u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo2), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.size(), 2u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo2), 1u);
|
||||
ASSERT_EQ(info->title, "GamingChair");
|
||||
|
||||
GetEntryPointInfoForNavigation(foo3, &info);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.size(), 2u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo3), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.size(), 2u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo3), 1u);
|
||||
ASSERT_EQ(info->title, "Lamp");
|
||||
}
|
||||
|
||||
@ -343,9 +359,9 @@ TEST_F(ClusterManagerTest,
|
||||
ASSERT_EQ(3u, GetCandidateProductMap()->size());
|
||||
std::optional<EntryPointInfo> info;
|
||||
GetEntryPointInfoForNavigation(foo1, &info);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.size(), 2u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo3), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.size(), 2u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo3), 1u);
|
||||
ASSERT_EQ(info->title, "Lamp");
|
||||
GetEntryPointInfoForNavigation(foo2, &info);
|
||||
ASSERT_FALSE(info);
|
||||
@ -463,15 +479,15 @@ TEST_F(ClusterManagerTest,
|
||||
|
||||
std::optional<EntryPointInfo> info;
|
||||
GetEntryPointInfoForNavigation(foo2, &info);
|
||||
ASSERT_EQ(3u, info->similar_candidate_products_urls.size());
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo2), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo4), 1u);
|
||||
ASSERT_EQ(3u, info->similar_candidate_products.size());
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo2), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo4), 1u);
|
||||
GetEntryPointInfoForNavigation(foo1, &info);
|
||||
ASSERT_EQ(3u, info->similar_candidate_products_urls.size());
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo2), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo4), 1u);
|
||||
ASSERT_EQ(3u, info->similar_candidate_products.size());
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo2), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo4), 1u);
|
||||
|
||||
// Similar candidates will not include `foo1` if it is added to a product
|
||||
// group.
|
||||
@ -480,9 +496,9 @@ TEST_F(ClusterManagerTest,
|
||||
cluster_manager_->OnProductSpecificationsSetAdded(set1);
|
||||
|
||||
GetEntryPointInfoForNavigation(foo2, &info);
|
||||
ASSERT_EQ(2u, info->similar_candidate_products_urls.size());
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo2), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo4), 1u);
|
||||
ASSERT_EQ(2u, info->similar_candidate_products.size());
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo2), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo4), 1u);
|
||||
GetEntryPointInfoForNavigation(foo1, &info);
|
||||
ASSERT_FALSE(info);
|
||||
}
|
||||
@ -660,9 +676,11 @@ TEST_F(ClusterManagerTest, GetEntryPointInfoForSelection) {
|
||||
GetEntryPointInfoForSelection(foo1, foo3, &info);
|
||||
ASSERT_TRUE(info);
|
||||
ASSERT_EQ(info->title, "Lamp");
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.size(), 2u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo3), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.size(), 2u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products[foo1], kProductID1);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo3), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products[foo3], kProductID3);
|
||||
}
|
||||
|
||||
TEST_F(ClusterManagerTest,
|
||||
@ -692,17 +710,17 @@ TEST_F(ClusterManagerTest,
|
||||
GetEntryPointInfoForSelection(foo1, foo2, &info);
|
||||
ASSERT_TRUE(info);
|
||||
ASSERT_EQ(info->title, "Lamp");
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.size(), 3u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo2), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo3), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.size(), 3u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo2), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo3), 1u);
|
||||
|
||||
GetEntryPointInfoForSelection(foo1, foo3, &info);
|
||||
ASSERT_EQ(info->title, "Lamp");
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.size(), 3u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo2), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products_urls.count(foo3), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.size(), 3u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo1), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo2), 1u);
|
||||
ASSERT_EQ(info->similar_candidate_products.count(foo3), 1u);
|
||||
|
||||
GetEntryPointInfoForSelection(foo2, foo3, &info);
|
||||
ASSERT_FALSE(info);
|
||||
|
Reference in New Issue
Block a user