blob: 269acf84704fc8e53cd8b6ddbe976fbc3208c4f0 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/default_browser/utils.h"
#import "base/ios/ios_util.h"
#import "base/test/scoped_feature_list.h"
#import "base/time/time.h"
#import "ios/chrome/browser/default_browser/utils_test_support.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h"
#import "testing/platform_test.h"
#import "ui/base/l10n/l10n_util_mac.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Less than 7 days.
constexpr base::TimeDelta kLessThan7Days = base::Days(7) - base::Minutes(1);
// More than 7 days.
constexpr base::TimeDelta kMoreThan7Days = base::Days(7) + base::Minutes(1);
// More than 14 days.
constexpr base::TimeDelta kMoreThan14Days = base::Days(14) + base::Minutes(1);
// Less than 6 hours.
constexpr base::TimeDelta kLessThan6Hours = base::Hours(6) - base::Minutes(1);
// More than 6 hours.
constexpr base::TimeDelta kMoreThan6Hours = base::Hours(6) + base::Minutes(1);
// Test key for a generic timestamp in NSUserDefaults.
NSString* const kTestTimestampKey = @"testTimestampKeyDefaultBrowserUtils";
// Test key in storage for timestamp of last first party intent launch.
NSString* const kTimestampAppLastOpenedViaFirstPartyIntent =
@"TimestampAppLastOpenedViaFirstPartyIntent";
// Test key in storage for timestamp of last valid URL pasted.
NSString* const kTimestampLastValidURLPasted = @"TimestampLastValidURLPasted";
class DefaultBrowserUtilsTest : public PlatformTest {
protected:
void SetUp() override { ClearDefaultBrowserPromoData(); }
void TearDown() override { ClearDefaultBrowserPromoData(); }
base::test::ScopedFeatureList feature_list_;
};
// Tests interesting information for each type.
TEST_F(DefaultBrowserUtilsTest, LogInterestingActivityEach) {
// General promo.
EXPECT_FALSE(IsLikelyInterestedDefaultBrowserUser(DefaultPromoTypeGeneral));
LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeGeneral);
EXPECT_TRUE(IsLikelyInterestedDefaultBrowserUser(DefaultPromoTypeGeneral));
ClearDefaultBrowserPromoData();
// Stay safe promo.
EXPECT_FALSE(IsLikelyInterestedDefaultBrowserUser(DefaultPromoTypeStaySafe));
LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeStaySafe);
EXPECT_TRUE(IsLikelyInterestedDefaultBrowserUser(DefaultPromoTypeStaySafe));
ClearDefaultBrowserPromoData();
// Made for iOS promo.
EXPECT_FALSE(
IsLikelyInterestedDefaultBrowserUser(DefaultPromoTypeMadeForIOS));
LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeMadeForIOS);
EXPECT_TRUE(IsLikelyInterestedDefaultBrowserUser(DefaultPromoTypeMadeForIOS));
ClearDefaultBrowserPromoData();
// All tabs promo.
EXPECT_FALSE(IsLikelyInterestedDefaultBrowserUser(DefaultPromoTypeAllTabs));
LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeAllTabs);
EXPECT_TRUE(IsLikelyInterestedDefaultBrowserUser(DefaultPromoTypeAllTabs));
}
// Tests most recent interest type.
TEST_F(DefaultBrowserUtilsTest, MostRecentInterestDefaultPromoType) {
DefaultPromoType type = MostRecentInterestDefaultPromoType(NO);
EXPECT_EQ(type, DefaultPromoTypeGeneral);
LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeAllTabs);
type = MostRecentInterestDefaultPromoType(NO);
EXPECT_EQ(type, DefaultPromoTypeAllTabs);
type = MostRecentInterestDefaultPromoType(YES);
EXPECT_NE(type, DefaultPromoTypeAllTabs);
LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeStaySafe);
type = MostRecentInterestDefaultPromoType(NO);
EXPECT_EQ(type, DefaultPromoTypeStaySafe);
LogLikelyInterestedDefaultBrowserUserActivity(DefaultPromoTypeMadeForIOS);
type = MostRecentInterestDefaultPromoType(NO);
EXPECT_EQ(type, DefaultPromoTypeMadeForIOS);
}
// Tests cool down between promos.
TEST_F(DefaultBrowserUtilsTest, PromoCoolDown) {
LogUserInteractionWithFullscreenPromo();
EXPECT_TRUE(UserInPromoCooldown());
ClearDefaultBrowserPromoData();
LogUserInteractionWithTailoredFullscreenPromo();
EXPECT_TRUE(UserInPromoCooldown());
}
// Tests no 2 tailored promos are not shown.
TEST_F(DefaultBrowserUtilsTest, TailoredPromoDoesNotAppearTwoTimes) {
LogUserInteractionWithTailoredFullscreenPromo();
EXPECT_TRUE(HasUserInteractedWithTailoredFullscreenPromoBefore());
}
// Tests that two recent first party intent launches are less than 6 hours
// apart, both returning false.
TEST_F(DefaultBrowserUtilsTest,
HasRecentFirstPartyIntentLaunchesAndRecordsCurrentLaunchLessThan6Hours) {
// Calling this more than once tests different code paths, but should return
// false on both calls. This is due to there being less than 6 hours between
// each call.
EXPECT_FALSE(HasRecentFirstPartyIntentLaunchesAndRecordsCurrentLaunch());
EXPECT_FALSE(HasRecentFirstPartyIntentLaunchesAndRecordsCurrentLaunch());
}
// Manually tests that two recent first party intent launches are less than 6
// hours apart.
TEST_F(
DefaultBrowserUtilsTest,
ManualHasRecentFirstPartyIntentLaunchesAndRecordsCurrentLaunchLessThan6Hours) {
SetObjectInStorageForKey(
kTimestampAppLastOpenedViaFirstPartyIntent,
[[NSDate alloc]
initWithTimeIntervalSinceNow:-kLessThan6Hours.InSecondsF()]);
EXPECT_FALSE(HasRecentFirstPartyIntentLaunchesAndRecordsCurrentLaunch());
}
// Manually tests that two recent first party intent launches are more than 7
// days apart.
TEST_F(
DefaultBrowserUtilsTest,
ManualHasRecentFirstPartyIntentLaunchesAndRecordsCurrentLaunchMoreThan7Days) {
SetObjectInStorageForKey(
kTimestampAppLastOpenedViaFirstPartyIntent,
[[NSDate alloc]
initWithTimeIntervalSinceNow:-kMoreThan7Days.InSecondsF()]);
EXPECT_FALSE(HasRecentFirstPartyIntentLaunchesAndRecordsCurrentLaunch());
}
// Manually tests that two recent first party intent launches are more than 6
// hours apart, but less than 7 days apart. Returns true.
TEST_F(
DefaultBrowserUtilsTest,
ManualHasRecentFirstPartyIntentLaunchesAndRecordsCurrentLaunchLessThan7DaysMoreThan6Hours) {
SetObjectInStorageForKey(
kTimestampAppLastOpenedViaFirstPartyIntent,
[[NSDate alloc]
initWithTimeIntervalSinceNow:-kLessThan7Days.InSecondsF()]);
EXPECT_TRUE(HasRecentFirstPartyIntentLaunchesAndRecordsCurrentLaunch());
}
// Tests two consecutive pastes recorded within 7 days, second call returns
// true.
TEST_F(DefaultBrowserUtilsTest, TwoConsecutivePastesUnder7Days) {
// Should return false at first, then true since an event has already been
// recorded within 7 days when the second one is called.
EXPECT_FALSE(HasRecentValidURLPastesAndRecordsCurrentPaste());
EXPECT_TRUE(HasRecentValidURLPastesAndRecordsCurrentPaste());
}
// Manually tests two consecutive pastes recorded within 7 days, should return
// true.
TEST_F(DefaultBrowserUtilsTest, ManualTwoConsecutivePastesUnder7Days) {
SetObjectInStorageForKey(
kTimestampLastValidURLPasted,
[[NSDate alloc]
initWithTimeIntervalSinceNow:-kLessThan7Days.InSecondsF()]);
EXPECT_TRUE(HasRecentValidURLPastesAndRecordsCurrentPaste());
}
// Manually tests two consecutive pastes recorded with more than 7 days between,
// should return false.
TEST_F(DefaultBrowserUtilsTest, ManualTwoConsecutivePastesOver7Days) {
SetObjectInStorageForKey(
kTimestampLastValidURLPasted,
[[NSDate alloc]
initWithTimeIntervalSinceNow:-kMoreThan7Days.InSecondsF()]);
EXPECT_FALSE(HasRecentValidURLPastesAndRecordsCurrentPaste());
}
// Tests that a recent event timestamp (less than 6 hours) has already been
// recorded.
TEST_F(DefaultBrowserUtilsTest, HasRecentTimestampForKeyUnder6Hours) {
// Should return false at first, then true since an event has already been
// recorded when the second one is called.
EXPECT_FALSE(HasRecentTimestampForKey(kTestTimestampKey));
EXPECT_TRUE(HasRecentTimestampForKey(kTestTimestampKey));
}
// Manually tests that a recent event timestamp (less than 6 hours) has already
// been recorded.
TEST_F(DefaultBrowserUtilsTest, ManualHasRecentTimestampForKeyUnder6Hours) {
SetObjectInStorageForKey(
kTestTimestampKey,
[[NSDate alloc]
initWithTimeIntervalSinceNow:-kLessThan6Hours.InSecondsF()]);
EXPECT_TRUE(HasRecentTimestampForKey(kTestTimestampKey));
}
// Manually tests that no recent event timestamp (more than 6 hours) has already
// been recorded.
TEST_F(DefaultBrowserUtilsTest, ManualRecentTimestampForKeyOver6Hours) {
SetObjectInStorageForKey(
kTestTimestampKey,
[[NSDate alloc]
initWithTimeIntervalSinceNow:-kMoreThan6Hours.InSecondsF()]);
EXPECT_FALSE(HasRecentTimestampForKey(kTestTimestampKey));
}
// Test `CalculatePromoStatistics` when feature flag is disabled.
TEST_F(DefaultBrowserUtilsTest, CalculatePromoStatisticsTest_FlagDisabled) {
feature_list_.InitWithFeatures({},
{kDefaultBrowserTriggerCriteriaExperiment});
{
PromoStatistics* promo_stats = CalculatePromoStatistics();
EXPECT_EQ(0, promo_stats.promoDisplayCount);
EXPECT_EQ(0, promo_stats.numDaysSinceLastPromo);
EXPECT_EQ(0, promo_stats.chromeColdStartCount);
EXPECT_EQ(0, promo_stats.chromeWarmStartCount);
EXPECT_EQ(0, promo_stats.chromeIndirectStartCount);
}
LogDefaultBrowserPromoDisplayed();
LogUserInteractionWithFullscreenPromo();
LogBrowserLaunched(true);
LogBrowserLaunched(false);
LogBrowserIndirectlylaunched();
{
PromoStatistics* promo_stats = CalculatePromoStatistics();
EXPECT_EQ(0, promo_stats.promoDisplayCount);
EXPECT_EQ(0, promo_stats.numDaysSinceLastPromo);
EXPECT_EQ(0, promo_stats.chromeColdStartCount);
EXPECT_EQ(0, promo_stats.chromeWarmStartCount);
EXPECT_EQ(0, promo_stats.chromeIndirectStartCount);
}
}
// Test `CalculatePromoStatistics` when feature flag is enabled.
TEST_F(DefaultBrowserUtilsTest, CalculatePromoStatisticsTest_FlagEnabled) {
feature_list_.InitWithFeatures({kDefaultBrowserTriggerCriteriaExperiment},
{});
{
PromoStatistics* promo_stats = CalculatePromoStatistics();
EXPECT_EQ(0, promo_stats.promoDisplayCount);
EXPECT_EQ(0, promo_stats.numDaysSinceLastPromo);
}
NSTimeInterval secondsPerDay = 24 * 60 * 60;
NSDate* yesterday =
[[NSDate alloc] initWithTimeIntervalSinceNow:-secondsPerDay];
SetObjectInStorageForKey(kLastTimeUserInteractedWithPromo, yesterday);
LogDefaultBrowserPromoDisplayed();
{
PromoStatistics* promo_stats = CalculatePromoStatistics();
EXPECT_EQ(1, promo_stats.promoDisplayCount);
EXPECT_EQ(1, promo_stats.numDaysSinceLastPromo);
}
LogDefaultBrowserPromoDisplayed();
LogUserInteractionWithFullscreenPromo();
{
PromoStatistics* promo_stats = CalculatePromoStatistics();
EXPECT_EQ(2, promo_stats.promoDisplayCount);
EXPECT_EQ(0, promo_stats.numDaysSinceLastPromo);
}
}
// Test `CalculatePromoStatistics` for chrome open metrics.
TEST_F(DefaultBrowserUtilsTest, CalculatePromoStatisticsTest_ChromeOpen) {
feature_list_.InitWithFeatures({kDefaultBrowserTriggerCriteriaExperiment},
{});
{
PromoStatistics* promo_stats = CalculatePromoStatistics();
EXPECT_EQ(0, promo_stats.chromeColdStartCount);
EXPECT_EQ(0, promo_stats.chromeWarmStartCount);
EXPECT_EQ(0, promo_stats.chromeIndirectStartCount);
}
// Adding timestamps that are older than 14 days should not change the promo
// stats.
NSDate* moreThan14DaysAgo = [[NSDate alloc]
initWithTimeIntervalSinceNow:-kMoreThan14Days.InSecondsF()];
SetObjectIntoStorageForKey(kAllTimestampsAppLaunchColdStart,
@[ moreThan14DaysAgo ]);
SetObjectIntoStorageForKey(kAllTimestampsAppLaunchWarmStart,
@[ moreThan14DaysAgo ]);
SetObjectIntoStorageForKey(kAllTimestampsAppLaunchIndirectStart,
@[ moreThan14DaysAgo ]);
{
PromoStatistics* promo_stats = CalculatePromoStatistics();
EXPECT_EQ(0, promo_stats.chromeColdStartCount);
EXPECT_EQ(0, promo_stats.chromeWarmStartCount);
EXPECT_EQ(0, promo_stats.chromeIndirectStartCount);
}
// Adding timestamps that are between 7 - 14 days should be counted.
NSDate* moreThan7DaysAgo = [[NSDate alloc]
initWithTimeIntervalSinceNow:-kMoreThan7Days.InSecondsF()];
SetObjectIntoStorageForKey(kAllTimestampsAppLaunchColdStart,
@[ moreThan7DaysAgo, moreThan14DaysAgo ]);
SetObjectIntoStorageForKey(kAllTimestampsAppLaunchWarmStart,
@[ moreThan7DaysAgo, moreThan14DaysAgo ]);
SetObjectIntoStorageForKey(kAllTimestampsAppLaunchIndirectStart,
@[ moreThan7DaysAgo, moreThan14DaysAgo ]);
{
PromoStatistics* promo_stats = CalculatePromoStatistics();
EXPECT_EQ(1, promo_stats.chromeColdStartCount);
EXPECT_EQ(1, promo_stats.chromeWarmStartCount);
EXPECT_EQ(1, promo_stats.chromeIndirectStartCount);
}
LogBrowserLaunched(true);
{
PromoStatistics* promo_stats = CalculatePromoStatistics();
EXPECT_EQ(2, promo_stats.chromeColdStartCount);
EXPECT_EQ(1, promo_stats.chromeWarmStartCount);
EXPECT_EQ(1, promo_stats.chromeIndirectStartCount);
}
LogBrowserLaunched(true);
LogBrowserLaunched(false);
{
PromoStatistics* promo_stats = CalculatePromoStatistics();
EXPECT_EQ(3, promo_stats.chromeColdStartCount);
EXPECT_EQ(2, promo_stats.chromeWarmStartCount);
EXPECT_EQ(1, promo_stats.chromeIndirectStartCount);
}
LogBrowserLaunched(true);
LogBrowserLaunched(false);
LogBrowserIndirectlylaunched();
{
PromoStatistics* promo_stats = CalculatePromoStatistics();
EXPECT_EQ(4, promo_stats.chromeColdStartCount);
EXPECT_EQ(3, promo_stats.chromeWarmStartCount);
EXPECT_EQ(2, promo_stats.chromeIndirectStartCount);
}
}
} // namespace