Commit e3d9e082 authored by Dan Harrington's avatar Dan Harrington Committed by Commit Bot

Create feed/core/common, feed/core/v2

This CL begins organizing code for Feed v2 by pulling some enums
into a new common directory.

Putting shared code in a different place makes it easier to understand
implications of modifying code, and will make it easier to understand
what pieces of code effect the 'v2' effort.

I'm starting with a few enums because they are very likely to remain
identical. More code will be moved here soon.

Bug: 1044139
Change-Id: I51f83f2fdc212aba9f72a1e9afd2ef8e79437e0a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2012903
Commit-Queue: Dan H <harringtond@chromium.org>
Reviewed-by: default avatarCarlos Knippschild <carlosk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#734195}
parent 63f525d3
...@@ -34,15 +34,15 @@ feed_internals::mojom::TimePtr ToMojoTime(base::Time time) { ...@@ -34,15 +34,15 @@ feed_internals::mojom::TimePtr ToMojoTime(base::Time time) {
: feed_internals::mojom::Time::New(time.ToJsTime()); : feed_internals::mojom::Time::New(time.ToJsTime());
} }
std::string TriggerTypeToString(feed::FeedSchedulerHost::TriggerType* trigger) { std::string TriggerTypeToString(feed::TriggerType* trigger) {
if (trigger == nullptr) if (trigger == nullptr)
return "Not set"; return "Not set";
switch (*trigger) { switch (*trigger) {
case feed::FeedSchedulerHost::TriggerType::kNtpShown: case feed::TriggerType::kNtpShown:
return "NTP Shown"; return "NTP Shown";
case feed::FeedSchedulerHost::TriggerType::kForegrounded: case feed::TriggerType::kForegrounded:
return "Foregrounded"; return "Foregrounded";
case feed::FeedSchedulerHost::TriggerType::kFixedTimer: case feed::TriggerType::kFixedTimer:
return "Fixed Timer"; return "Fixed Timer";
} }
} }
......
...@@ -48,6 +48,7 @@ source_set("feed_core") { ...@@ -48,6 +48,7 @@ source_set("feed_core") {
] ]
deps = [ deps = [
"//components/feed/core/common:feed_core_common",
"//components/prefs", "//components/prefs",
"//components/signin/public/identity_manager", "//components/signin/public/identity_manager",
"//components/variations", "//components/variations",
......
# 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.
if (is_android) {
import("//build/config/android/rules.gni")
}
source_set("feed_core_common") {
sources = [ "enums.h" ]
}
This directory contains code common to feed v2 and v1.
// 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.
#ifndef COMPONENTS_FEED_CORE_COMMON_ENUMS_H_
#define COMPONENTS_FEED_CORE_COMMON_ENUMS_H_
// This file contains enumerations common to Feed v1 and v2.
namespace feed {
// The TriggerType enum specifies values for the events that can trigger
// refreshing articles. When adding values, be certain to also update the
// corresponding definition in enums.xml.
enum class TriggerType {
kNtpShown = 0,
kForegrounded = 1,
kFixedTimer = 2,
kMaxValue = kFixedTimer
};
// Different groupings of usage. A user will belong to exactly one of these at
// any given point in time. Can change at runtime.
enum class UserClass {
kRareSuggestionsViewer, // Almost never opens surfaces that show
// suggestions, like the NTP.
kActiveSuggestionsViewer, // Frequently shown suggestions, but does not
// usually open them.
kActiveSuggestionsConsumer, // Frequently opens news articles.
};
// Enum for the status of the refresh, reported through UMA.
// If any new values are added, update FeedSchedulerRefreshStatus in
// enums.xml.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class ShouldRefreshResult {
kShouldRefresh = 0,
kDontRefreshOutstandingRequest = 1,
kDontRefreshTriggerDisabled = 2,
kDontRefreshNetworkOffline = 3,
kDontRefreshEulaNotAccepted = 4,
kDontRefreshArticlesHidden = 5,
kDontRefreshRefreshSuppressed = 6,
kDontRefreshNotStale = 7,
kDontRefreshRefreshThrottled = 8,
kMaxValue = kDontRefreshRefreshThrottled,
};
} // namespace feed
#endif // COMPONENTS_FEED_CORE_COMMON_ENUMS_H_
This diff is collapsed.
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "components/feed/core/common/enums.h"
#include "components/feed/core/refresh_throttler.h" #include "components/feed/core/refresh_throttler.h"
#include "components/feed/core/user_classifier.h" #include "components/feed/core/user_classifier.h"
#include "components/web_resource/eula_accepted_notifier.h" #include "components/web_resource/eula_accepted_notifier.h"
...@@ -49,33 +50,6 @@ enum NativeRequestBehavior { ...@@ -49,33 +50,6 @@ enum NativeRequestBehavior {
// content. // content.
class FeedSchedulerHost : web_resource::EulaAcceptedNotifier::Observer { class FeedSchedulerHost : web_resource::EulaAcceptedNotifier::Observer {
public: public:
// The TriggerType enum specifies values for the events that can trigger
// refreshing articles. When adding values, be certain to also update the
// corresponding definition in enums.xml.
enum class TriggerType {
kNtpShown = 0,
kForegrounded = 1,
kFixedTimer = 2,
kMaxValue = kFixedTimer
};
// Enum for the status of the refresh, reported through UMA.
// If any new values are added, update the corresponding definition in
// enums.xml.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum ShouldRefreshResult {
kShouldRefresh = 0,
kDontRefreshOutstandingRequest = 1,
kDontRefreshTriggerDisabled = 2,
kDontRefreshNetworkOffline = 3,
kDontRefreshEulaNotAccepted = 4,
kDontRefreshArticlesHidden = 5,
kDontRefreshRefreshSuppressed = 6,
kDontRefreshNotStale = 7,
kDontRefreshRefreshThrottled = 8,
kMaxValue = kDontRefreshRefreshThrottled,
};
FeedSchedulerHost(PrefService* profile_prefs, FeedSchedulerHost(PrefService* profile_prefs,
PrefService* local_state, PrefService* local_state,
...@@ -224,8 +198,7 @@ class FeedSchedulerHost : web_resource::EulaAcceptedNotifier::Observer { ...@@ -224,8 +198,7 @@ class FeedSchedulerHost : web_resource::EulaAcceptedNotifier::Observer {
// In the case the user transitions between user classes, hold onto a // In the case the user transitions between user classes, hold onto a
// throttler for any situation. // throttler for any situation.
base::flat_map<UserClassifier::UserClass, std::unique_ptr<RefreshThrottler>> base::flat_map<UserClass, std::unique_ptr<RefreshThrottler>> throttlers_;
throttlers_;
// Status of the last fetch for debugging. // Status of the last fetch for debugging.
int last_fetch_status_ = 0; int last_fetch_status_ = 0;
......
...@@ -92,7 +92,7 @@ class FeedSchedulerHostTest : public ::testing::Test { ...@@ -92,7 +92,7 @@ class FeedSchedulerHostTest : public ::testing::Test {
// into kRareNtpUser classification. // into kRareNtpUser classification.
test_clock()->Advance(TimeDelta::FromDays(7)); test_clock()->Advance(TimeDelta::FromDays(7));
ASSERT_EQ(UserClassifier::UserClass::kRareSuggestionsViewer, ASSERT_EQ(UserClass::kRareSuggestionsViewer,
scheduler()->GetUserClassifierForDebugging()->GetUserClass()); scheduler()->GetUserClassifierForDebugging()->GetUserClass());
} }
...@@ -107,7 +107,7 @@ class FeedSchedulerHostTest : public ::testing::Test { ...@@ -107,7 +107,7 @@ class FeedSchedulerHostTest : public ::testing::Test {
// Depending on which events occurred over which period of time in the test // Depending on which events occurred over which period of time in the test
// before this function was called, it may not necessarily be sufficient to // before this function was called, it may not necessarily be sufficient to
// push the user into the active consumer class. // push the user into the active consumer class.
ASSERT_EQ(UserClassifier::UserClass::kActiveSuggestionsConsumer, ASSERT_EQ(UserClass::kActiveSuggestionsConsumer,
scheduler()->GetUserClassifierForDebugging()->GetUserClass()); scheduler()->GetUserClassifierForDebugging()->GetUserClass());
} }
...@@ -177,23 +177,22 @@ class FeedSchedulerHostTest : public ::testing::Test { ...@@ -177,23 +177,22 @@ class FeedSchedulerHostTest : public ::testing::Test {
TEST_F(FeedSchedulerHostTest, GetTriggerThreshold) { TEST_F(FeedSchedulerHostTest, GetTriggerThreshold) {
// Make sure that there is no missing configuration in the Cartesian product // Make sure that there is no missing configuration in the Cartesian product
// of states between TriggerType and UserClass. // of states between TriggerType and UserClass.
std::vector<FeedSchedulerHost::TriggerType> triggers = { std::vector<TriggerType> triggers = {TriggerType::kNtpShown,
FeedSchedulerHost::TriggerType::kNtpShown, TriggerType::kForegrounded,
FeedSchedulerHost::TriggerType::kForegrounded, TriggerType::kFixedTimer};
FeedSchedulerHost::TriggerType::kFixedTimer};
// Classification starts out as an active NTP user. // Classification starts out as an active NTP user.
for (FeedSchedulerHost::TriggerType trigger : triggers) { for (TriggerType trigger : triggers) {
EXPECT_FALSE(scheduler()->GetTriggerThreshold(trigger).is_zero()); EXPECT_FALSE(scheduler()->GetTriggerThreshold(trigger).is_zero());
} }
ClassifyAsActiveSuggestionsConsumer(); ClassifyAsActiveSuggestionsConsumer();
for (FeedSchedulerHost::TriggerType trigger : triggers) { for (TriggerType trigger : triggers) {
EXPECT_FALSE(scheduler()->GetTriggerThreshold(trigger).is_zero()); EXPECT_FALSE(scheduler()->GetTriggerThreshold(trigger).is_zero());
} }
ClassifyAsRareNtpUser(); ClassifyAsRareNtpUser();
for (FeedSchedulerHost::TriggerType trigger : triggers) { for (TriggerType trigger : triggers) {
EXPECT_FALSE(scheduler()->GetTriggerThreshold(trigger).is_zero()); EXPECT_FALSE(scheduler()->GetTriggerThreshold(trigger).is_zero());
} }
} }
...@@ -1034,14 +1033,14 @@ TEST_F(FeedSchedulerHostTest, RefreshThrottler) { ...@@ -1034,14 +1033,14 @@ TEST_F(FeedSchedulerHostTest, RefreshThrottler) {
TEST_F(FeedSchedulerHostTest, GetUserClassifierForDebuggingRareUser) { TEST_F(FeedSchedulerHostTest, GetUserClassifierForDebuggingRareUser) {
ClassifyAsRareNtpUser(); ClassifyAsRareNtpUser();
EXPECT_EQ(UserClassifier::UserClass::kRareSuggestionsViewer, EXPECT_EQ(UserClass::kRareSuggestionsViewer,
scheduler()->GetUserClassifierForDebugging()->GetUserClass()); scheduler()->GetUserClassifierForDebugging()->GetUserClass());
} }
TEST_F(FeedSchedulerHostTest, GetUserClassifierForDebuggingActiveConsumer) { TEST_F(FeedSchedulerHostTest, GetUserClassifierForDebuggingActiveConsumer) {
ClassifyAsActiveSuggestionsConsumer(); ClassifyAsActiveSuggestionsConsumer();
EXPECT_EQ(UserClassifier::UserClass::kActiveSuggestionsConsumer, EXPECT_EQ(UserClass::kActiveSuggestionsConsumer,
scheduler()->GetUserClassifierForDebugging()->GetUserClass()); scheduler()->GetUserClassifierForDebugging()->GetUserClass());
} }
...@@ -1069,19 +1068,19 @@ TEST_F(FeedSchedulerHostTest, GetLastFetchStatusForDebugging) { ...@@ -1069,19 +1068,19 @@ TEST_F(FeedSchedulerHostTest, GetLastFetchStatusForDebugging) {
TEST_F(FeedSchedulerHostTest, GetLastFetchTriggerTypeForDebugging) { TEST_F(FeedSchedulerHostTest, GetLastFetchTriggerTypeForDebugging) {
scheduler()->OnForegrounded(); scheduler()->OnForegrounded();
EXPECT_EQ(FeedSchedulerHost::TriggerType::kForegrounded, EXPECT_EQ(TriggerType::kForegrounded,
*scheduler()->GetLastFetchTriggerTypeForDebugging()); *scheduler()->GetLastFetchTriggerTypeForDebugging());
scheduler()->OnArticlesCleared(/*suppress_refreshes*/ false); scheduler()->OnArticlesCleared(/*suppress_refreshes*/ false);
EXPECT_EQ(FeedSchedulerHost::TriggerType::kNtpShown, EXPECT_EQ(TriggerType::kNtpShown,
*scheduler()->GetLastFetchTriggerTypeForDebugging()); *scheduler()->GetLastFetchTriggerTypeForDebugging());
ClassifyAsActiveSuggestionsConsumer(); // Fixed timer at 48 hours. ClassifyAsActiveSuggestionsConsumer(); // Fixed timer at 48 hours.
test_clock()->Advance(TimeDelta::FromHours(49)); test_clock()->Advance(TimeDelta::FromHours(49));
scheduler()->OnFixedTimer(base::OnceClosure()); scheduler()->OnFixedTimer(base::OnceClosure());
EXPECT_EQ(FeedSchedulerHost::TriggerType::kFixedTimer, EXPECT_EQ(TriggerType::kFixedTimer,
*scheduler()->GetLastFetchTriggerTypeForDebugging()); *scheduler()->GetLastFetchTriggerTypeForDebugging());
} }
......
...@@ -34,21 +34,20 @@ enum class RequestStatus { ...@@ -34,21 +34,20 @@ enum class RequestStatus {
// When adding a new type here, extend also the "RequestThrottlerTypes" // When adding a new type here, extend also the "RequestThrottlerTypes"
// <histogram_suffixes> in histograms.xml with the |name| string. First value in // <histogram_suffixes> in histograms.xml with the |name| string. First value in
// the pair is the name, second is the default requests per day. // the pair is the name, second is the default requests per day.
std::pair<std::string, int> GetThrottlerParams( std::pair<std::string, int> GetThrottlerParams(UserClass user_class) {
UserClassifier::UserClass user_class) {
switch (user_class) { switch (user_class) {
case UserClassifier::UserClass::kRareSuggestionsViewer: case UserClass::kRareSuggestionsViewer:
return {"SuggestionFetcherRareNTPUser", 5}; return {"SuggestionFetcherRareNTPUser", 5};
case UserClassifier::UserClass::kActiveSuggestionsViewer: case UserClass::kActiveSuggestionsViewer:
return {"SuggestionFetcherActiveNTPUser", 20}; return {"SuggestionFetcherActiveNTPUser", 20};
case UserClassifier::UserClass::kActiveSuggestionsConsumer: case UserClass::kActiveSuggestionsConsumer:
return {"SuggestionFetcherActiveSuggestionsConsumer", 20}; return {"SuggestionFetcherActiveSuggestionsConsumer", 20};
} }
} }
} // namespace } // namespace
RefreshThrottler::RefreshThrottler(UserClassifier::UserClass user_class, RefreshThrottler::RefreshThrottler(UserClass user_class,
PrefService* pref_service, PrefService* pref_service,
base::Clock* clock) base::Clock* clock)
: pref_service_(pref_service), clock_(clock) { : pref_service_(pref_service), clock_(clock) {
......
...@@ -28,7 +28,7 @@ namespace feed { ...@@ -28,7 +28,7 @@ namespace feed {
// - "NewTabPage.RequestThrottler.PerDay_|name|" - the daily count of requests. // - "NewTabPage.RequestThrottler.PerDay_|name|" - the daily count of requests.
class RefreshThrottler { class RefreshThrottler {
public: public:
RefreshThrottler(UserClassifier::UserClass user_class, RefreshThrottler(UserClass user_class,
PrefService* pref_service, PrefService* pref_service,
base::Clock* clock); base::Clock* clock);
......
...@@ -38,8 +38,7 @@ class RefreshThrottlerTest : public testing::Test { ...@@ -38,8 +38,7 @@ class RefreshThrottlerTest : public testing::Test {
{{"quota_SuggestionFetcherActiveNTPUser", "2"}}); {{"quota_SuggestionFetcherActiveNTPUser", "2"}});
throttler_ = std::make_unique<RefreshThrottler>( throttler_ = std::make_unique<RefreshThrottler>(
UserClassifier::UserClass::kActiveSuggestionsViewer, &test_prefs_, UserClass::kActiveSuggestionsViewer, &test_prefs_, &test_clock_);
&test_clock_);
} }
protected: protected:
......
...@@ -253,7 +253,7 @@ double UserClassifier::GetEstimatedAvgTime(Event event) const { ...@@ -253,7 +253,7 @@ double UserClassifier::GetEstimatedAvgTime(Event event) const {
min_hours_, max_hours_); min_hours_, max_hours_);
} }
UserClassifier::UserClass UserClassifier::GetUserClass() const { UserClass UserClassifier::GetUserClass() const {
// The pref_service_ can be null in tests. // The pref_service_ can be null in tests.
if (!pref_service_) { if (!pref_service_) {
return UserClass::kActiveSuggestionsViewer; return UserClass::kActiveSuggestionsViewer;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <string> #include <string>
#include "base/macros.h" #include "base/macros.h"
#include "components/feed/core/common/enums.h"
class PrefRegistrySimple; class PrefRegistrySimple;
class PrefService; class PrefService;
...@@ -24,16 +25,6 @@ namespace feed { ...@@ -24,16 +25,6 @@ namespace feed {
// Based on these long-term user rates, it classifies the user in a UserClass. // Based on these long-term user rates, it classifies the user in a UserClass.
class UserClassifier { class UserClassifier {
public: public:
// Different groupings of usage. A user will belong to exactly one of these at
// any given point in time. Can change at runtime.
enum class UserClass {
kRareSuggestionsViewer, // Almost never opens surfaces that show
// suggestions, like the NTP.
kActiveSuggestionsViewer, // Frequently shown suggestions, but does not
// usually open them.
kActiveSuggestionsConsumer, // Frequently opens news articles.
};
// For estimating the average length of the intervals between two successive // For estimating the average length of the intervals between two successive
// events, we keep a simple frequency model, a single value that we call // events, we keep a simple frequency model, a single value that we call
// "rate" below. // "rate" below.
......
...@@ -59,7 +59,7 @@ class FeedUserClassifierTest : public testing::Test { ...@@ -59,7 +59,7 @@ class FeedUserClassifierTest : public testing::Test {
TEST_F(FeedUserClassifierTest, ShouldBeActiveSuggestionsViewerInitially) { TEST_F(FeedUserClassifierTest, ShouldBeActiveSuggestionsViewerInitially) {
UserClassifier* user_classifier = CreateUserClassifier(); UserClassifier* user_classifier = CreateUserClassifier();
EXPECT_THAT(user_classifier->GetUserClass(), EXPECT_THAT(user_classifier->GetUserClass(),
Eq(UserClassifier::UserClass::kActiveSuggestionsViewer)); Eq(UserClass::kActiveSuggestionsViewer));
} }
TEST_F(FeedUserClassifierTest, TEST_F(FeedUserClassifierTest,
...@@ -69,7 +69,7 @@ TEST_F(FeedUserClassifierTest, ...@@ -69,7 +69,7 @@ TEST_F(FeedUserClassifierTest,
// After one click still only an active user. // After one click still only an active user.
user_classifier->OnEvent(UserClassifier::Event::kSuggestionsUsed); user_classifier->OnEvent(UserClassifier::Event::kSuggestionsUsed);
EXPECT_THAT(user_classifier->GetUserClass(), EXPECT_THAT(user_classifier->GetUserClass(),
Eq(UserClassifier::UserClass::kActiveSuggestionsViewer)); Eq(UserClass::kActiveSuggestionsViewer));
// After a few more clicks, become an active consumer. // After a few more clicks, become an active consumer.
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
...@@ -77,7 +77,7 @@ TEST_F(FeedUserClassifierTest, ...@@ -77,7 +77,7 @@ TEST_F(FeedUserClassifierTest,
user_classifier->OnEvent(UserClassifier::Event::kSuggestionsUsed); user_classifier->OnEvent(UserClassifier::Event::kSuggestionsUsed);
} }
EXPECT_THAT(user_classifier->GetUserClass(), EXPECT_THAT(user_classifier->GetUserClass(),
Eq(UserClassifier::UserClass::kActiveSuggestionsConsumer)); Eq(UserClass::kActiveSuggestionsConsumer));
} }
TEST_F(FeedUserClassifierTest, TEST_F(FeedUserClassifierTest,
...@@ -95,13 +95,13 @@ TEST_F(FeedUserClassifierTest, ...@@ -95,13 +95,13 @@ TEST_F(FeedUserClassifierTest,
test_clock()->Advance(base::TimeDelta::FromHours(1)); test_clock()->Advance(base::TimeDelta::FromHours(1));
user_classifier->OnEvent(UserClassifier::Event::kSuggestionsUsed); user_classifier->OnEvent(UserClassifier::Event::kSuggestionsUsed);
EXPECT_THAT(user_classifier->GetUserClass(), EXPECT_THAT(user_classifier->GetUserClass(),
Eq(UserClassifier::UserClass::kActiveSuggestionsViewer)); Eq(UserClass::kActiveSuggestionsViewer));
// One more click to become an active consumer. // One more click to become an active consumer.
test_clock()->Advance(base::TimeDelta::FromHours(1)); test_clock()->Advance(base::TimeDelta::FromHours(1));
user_classifier->OnEvent(UserClassifier::Event::kSuggestionsUsed); user_classifier->OnEvent(UserClassifier::Event::kSuggestionsUsed);
EXPECT_THAT(user_classifier->GetUserClass(), EXPECT_THAT(user_classifier->GetUserClass(),
Eq(UserClassifier::UserClass::kActiveSuggestionsConsumer)); Eq(UserClass::kActiveSuggestionsConsumer));
} }
TEST_F(FeedUserClassifierTest, TEST_F(FeedUserClassifierTest,
...@@ -111,12 +111,12 @@ TEST_F(FeedUserClassifierTest, ...@@ -111,12 +111,12 @@ TEST_F(FeedUserClassifierTest,
// After two days of waiting still an active user. // After two days of waiting still an active user.
test_clock()->Advance(base::TimeDelta::FromDays(2)); test_clock()->Advance(base::TimeDelta::FromDays(2));
EXPECT_THAT(user_classifier->GetUserClass(), EXPECT_THAT(user_classifier->GetUserClass(),
Eq(UserClassifier::UserClass::kActiveSuggestionsViewer)); Eq(UserClass::kActiveSuggestionsViewer));
// Two more days to become a rare user. // Two more days to become a rare user.
test_clock()->Advance(base::TimeDelta::FromDays(2)); test_clock()->Advance(base::TimeDelta::FromDays(2));
EXPECT_THAT(user_classifier->GetUserClass(), EXPECT_THAT(user_classifier->GetUserClass(),
Eq(UserClassifier::UserClass::kRareSuggestionsViewer)); Eq(UserClass::kRareSuggestionsViewer));
} }
TEST_F(FeedUserClassifierTest, TEST_F(FeedUserClassifierTest,
...@@ -131,12 +131,12 @@ TEST_F(FeedUserClassifierTest, ...@@ -131,12 +131,12 @@ TEST_F(FeedUserClassifierTest,
// After one days of waiting still an active user. // After one days of waiting still an active user.
test_clock()->Advance(base::TimeDelta::FromDays(1)); test_clock()->Advance(base::TimeDelta::FromDays(1));
EXPECT_THAT(user_classifier->GetUserClass(), EXPECT_THAT(user_classifier->GetUserClass(),
Eq(UserClassifier::UserClass::kActiveSuggestionsViewer)); Eq(UserClass::kActiveSuggestionsViewer));
// One more day to become a rare user. // One more day to become a rare user.
test_clock()->Advance(base::TimeDelta::FromDays(1)); test_clock()->Advance(base::TimeDelta::FromDays(1));
EXPECT_THAT(user_classifier->GetUserClass(), EXPECT_THAT(user_classifier->GetUserClass(),
Eq(UserClassifier::UserClass::kRareSuggestionsViewer)); Eq(UserClass::kRareSuggestionsViewer));
} }
class FeedUserClassifierEventTest class FeedUserClassifierEventTest
......
The next iteration of the feed component, in development.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment