[eye][tips] Additional requirements are supported

This commit is contained in:
Arsentiy Milchakov 2018-09-05 15:38:09 +03:00 committed by Roman Kuznetsov
parent 7af77c0e44
commit 2ac5023f78
11 changed files with 533 additions and 32 deletions

View file

@ -363,7 +363,6 @@ Framework::Framework(FrameworkParams const & params)
bind(&Framework::GetMwmIdByName, this, _1),
bind(&Framework::ReadFeatures, this, _1, _2),
bind(&Framework::GetFeatureByID, this, _1, _2))
, m_startForegroundTime(0.0)
, m_storage(platform::migrate::NeedMigrate() ? COUNTRIES_OBSOLETE_FILE : COUNTRIES_FILE)
, m_enabledDiffs(params.m_enableDiffs)
, m_isRenderingEnabled(true)
@ -392,8 +391,6 @@ Framework::Framework(FrameworkParams const & params)
, m_subscription(std::make_unique<Subscription>())
, m_tipsApi(static_cast<TipsApi::Delegate &>(*this))
{
m_startBackgroundTime = my::Timer::LocalTime();
// Editor should be initialized from the main thread to set its ThreadChecker.
// However, search calls editor upon initialization thus setting the lazy editor's ThreadChecker
// to a wrong thread. So editor should be initialiazed before serach.
@ -1353,7 +1350,7 @@ void Framework::EnterBackground()
void Framework::EnterForeground()
{
m_startForegroundTime = my::Timer::LocalTime();
if (m_drapeEngine != nullptr)
if (m_drapeEngine != nullptr && m_startBackgroundTime != 0.0)
{
auto const timeInBackground = m_startForegroundTime - m_startBackgroundTime;
m_drapeEngine->SetTimeInBackground(timeInBackground);
@ -3680,3 +3677,8 @@ bool Framework::HaveTransit(m2::PointD const & pt) const
return handle.GetValue<MwmValue>()->m_cont.IsExist(TRANSIT_FILE_TAG);
}
double Framework::GetLastBackgroundTime() const
{
return m_startBackgroundTime;
}

View file

@ -193,8 +193,8 @@ protected:
drape_ptr<df::DrapeEngine> m_drapeEngine;
double m_startForegroundTime;
double m_startBackgroundTime;
double m_startForegroundTime = 0.0;
double m_startBackgroundTime = 0.0;
StorageDownloadingPolicy m_storageDownloadingPolicy;
storage::Storage m_storage;
@ -890,4 +890,5 @@ public:
// TipsApi::Delegate override.
bool HaveTransit(m2::PointD const & pt) const override;
double GetLastBackgroundTime() const override;
};

View file

@ -5,6 +5,9 @@
#include "metrics/metrics_tests_support/eye_for_testing.hpp"
#include "metrics/eye.hpp"
#include "metrics/eye_info.hpp"
#include "base/timer.hpp"
#include <algorithm>
#include <vector>
@ -15,6 +18,30 @@ using namespace eye;
namespace
{
class TipsApiDelegate : public TipsApi::Delegate
{
public:
void SetLastBackgroundTime(double lastBackgroundTime)
{
m_lastBackgroundTime = lastBackgroundTime;
}
// TipsApi::Delegate overrides:
boost::optional<m2::PointD> GetCurrentPosition() const override
{
return boost::optional<m2::PointD>();
}
bool IsCountryLoaded(m2::PointD const & pt) const override { return false; }
bool HaveTransit(m2::PointD const & pt) const override { return false; }
double GetLastBackgroundTime() const override { return m_lastBackgroundTime; }
private:
double m_lastBackgroundTime = 0.0;
};
void MakeLastShownTipAvailableByTime()
{
auto const info = Eye::Instance().GetInfo();
@ -26,26 +53,27 @@ void MakeLastShownTipAvailableByTime()
}
boost::optional<eye::Tip::Type> GetTipForTesting(TipsApi::Duration showAnyTipPeriod,
TipsApi::Duration showSameTipPeriod)
TipsApi::Duration showSameTipPeriod,
TipsApiDelegate const & delegate)
{
// Do not use additional conditions for testing.
TipsApi::Conditions conditions =
{{
// Condition for Tips::Type::BookmarksCatalog type.
[] { return true; },
[] (eye::Info const & info) { return true; },
// Condition for Tips::Type::BookingHotels type.
[] { return true; },
[] (eye::Info const & info) { return true; },
// Condition for Tips::Type::DiscoverButton type.
[] { return true; },
[] (eye::Info const & info) { return true; },
// Condition for Tips::Type::MapsLayers type.
[] { return true; }
[] (eye::Info const & info) { return true; }
}};
return TipsApi::GetTipForTesting(showAnyTipPeriod, showSameTipPeriod, conditions);
return TipsApi::GetTipForTesting(showAnyTipPeriod, showSameTipPeriod, delegate, conditions);
}
boost::optional<eye::Tip::Type> GetTipForTesting()
{
return GetTipForTesting(TipsApi::GetShowAnyTipPeriod(), TipsApi::GetShowSameTipPeriod());
return GetTipForTesting(TipsApi::GetShowAnyTipPeriod(), TipsApi::GetShowSameTipPeriod(), {});
}
void ShowTipWithClickCountTest(Tip::Event eventType, size_t maxClickCount)
@ -114,7 +142,7 @@ UNIT_CLASS_TEST(ScopedEyeForTesting, ShowFirstTip_Test)
for (size_t i = 0; i < totalTipsCount; ++i)
{
auto tip = GetTipForTesting({}, TipsApi::GetShowSameTipPeriod());
auto tip = GetTipForTesting({}, TipsApi::GetShowSameTipPeriod(), {});
TEST(tip.is_initialized(), ());
TEST_NOT_EQUAL(tip.get(), Tip::Type::Count, ());
@ -145,4 +173,15 @@ UNIT_CLASS_TEST(ScopedEyeForTesting, ShowTipAndGotitClicked_Test)
{
ShowTipWithClickCountTest(Tip::Event::GotitClicked, TipsApi::GetGotitClicksCountToDisable());
}
UNIT_CLASS_TEST(ScopedEyeForTesting, ShowTipAfterWarmStart)
{
TipsApiDelegate d;
d.SetLastBackgroundTime(my::Timer::LocalTime());
auto tip = GetTipForTesting({}, TipsApi::GetShowSameTipPeriod(), d);
TEST(!tip.is_initialized(), ());
d.SetLastBackgroundTime(my::Timer::LocalTime() - TipsApi::ShowTipAfterCollapsingPeriod().count());
tip = GetTipForTesting({}, TipsApi::GetShowSameTipPeriod(), d);
TEST(tip.is_initialized(), ());
}
} // namespace

View file

@ -4,6 +4,9 @@
#include "platform/platform.hpp"
#include "base/timer.hpp"
#include <type_traits>
#include <utility>
using namespace eye;
@ -14,21 +17,35 @@ namespace
auto constexpr kShowAnyTipPeriod = std::chrono::hours(24) * 3;
// The app shouldn't show the same screen more frequently than 1 month.
auto constexpr kShowSameTipPeriod = std::chrono::hours(24) * 30;
// Every current trigger for a tips screen can be activated at the start of the application by
// default and if the app was inactive more then 12 hours.
auto constexpr kShowTipAfterCollapsingPeriod = std::chrono::seconds(12 * 60 * 60);
// If a user clicks on the action areas (highlighted or blue button)
// the appropriate screen will never be shown again.
size_t constexpr kActionClicksCountToDisable = 1;
// If a user clicks 3 times on the button GOT IT the appropriate screen will never be shown again.
size_t constexpr kGotitClicksCountToDisable = 3;
size_t ToIndex(Tip::Type type)
template <typename T, std::enable_if_t<std::is_enum<T>::value> * = nullptr>
size_t ToIndex(T type)
{
return static_cast<size_t>(type);
}
boost::optional<eye::Tip::Type> GetTipImpl(TipsApi::Duration showAnyTipPeriod,
TipsApi::Duration showSameTipPeriod,
TipsApi::Conditions const & triggers)
TipsApi::Delegate const & delegate,
TipsApi::Conditions const & conditions)
{
auto const lastBackgroundTime = delegate.GetLastBackgroundTime();
if (lastBackgroundTime != 0.0)
{
auto const timeInBackground =
static_cast<uint64_t>(my::Timer::LocalTime() - lastBackgroundTime);
if (timeInBackground < kShowTipAfterCollapsingPeriod.count())
return {};
}
auto const info = Eye::Instance().GetInfo();
auto const & tips = info->m_tips;
auto constexpr totalTipsCount = static_cast<size_t>(Tip::Type::Count);
@ -60,7 +77,7 @@ boost::optional<eye::Tip::Type> GetTipImpl(TipsApi::Duration showAnyTipPeriod,
for (auto const & c : candidates)
{
if (c.second && triggers[ToIndex(c.first)]())
if (c.second && conditions[ToIndex(c.first)](*info))
return c.first;
}
}
@ -70,7 +87,7 @@ boost::optional<eye::Tip::Type> GetTipImpl(TipsApi::Duration showAnyTipPeriod,
if (shownTip.m_eventCounters.Get(Tip::Event::ActionClicked) < kActionClicksCountToDisable &&
shownTip.m_eventCounters.Get(Tip::Event::GotitClicked) < kGotitClicksCountToDisable &&
Clock::now() - shownTip.m_lastShownTime > showSameTipPeriod &&
triggers[ToIndex(shownTip.m_type)]())
conditions[ToIndex(shownTip.m_type)](*info))
{
return shownTip.m_type;
}
@ -92,6 +109,12 @@ TipsApi::Duration TipsApi::GetShowSameTipPeriod()
return kShowSameTipPeriod;
}
// static
TipsApi::Duration TipsApi::ShowTipAfterCollapsingPeriod()
{
return kShowTipAfterCollapsingPeriod;
};
// static
size_t TipsApi::GetActionClicksCountToDisable()
{
@ -110,12 +133,26 @@ TipsApi::TipsApi(Delegate const & delegate)
m_conditions =
{{
// Condition for Tips::Type::BookmarksCatalog type.
[] { return GetPlatform().ConnectionStatus() != Platform::EConnectionType::CONNECTION_NONE; },
// Condition for Tips::Type::BookingHotels type.
[] { return true; },
// Condition for Tips::Type::DiscoverButton type.
[this]
[] (eye::Info const & info)
{
return info.m_bookmarks.m_lastOpenedTime.time_since_epoch().count() == 0 &&
GetPlatform().ConnectionStatus() != Platform::EConnectionType::CONNECTION_NONE;
},
// Condition for Tips::Type::BookingHotels type.
[] (eye::Info const & info)
{
return info.m_booking.m_lastFilterUsedTime.time_since_epoch().count() == 0;
},
// Condition for Tips::Type::DiscoverButton type.
[this] (eye::Info const & info)
{
auto const eventsCount = ToIndex(Discovery::Event::Count);
for (size_t i = 0; i < eventsCount; ++i)
{
if (info.m_discovery.m_eventCounters.Get(static_cast<Discovery::Event>(i)) != 0)
return false;
}
auto const pos = m_delegate.GetCurrentPosition();
if (!pos.is_initialized())
return false;
@ -123,8 +160,17 @@ TipsApi::TipsApi(Delegate const & delegate)
return m_delegate.IsCountryLoaded(pos.get());
},
// Condition for Tips::Type::MapsLayers type.
[this]
[this] (eye::Info const & info)
{
for (auto const & layer : info.m_layers)
{
if (layer.m_type == Layer::PublicTransport &&
layer.m_lastTimeUsed.time_since_epoch().count() != 0)
{
return false;
}
}
auto const pos = m_delegate.GetCurrentPosition();
if (!pos.is_initialized())
return false;
@ -136,13 +182,14 @@ TipsApi::TipsApi(Delegate const & delegate)
boost::optional<eye::Tip::Type> TipsApi::GetTip() const
{
return GetTipImpl(GetShowAnyTipPeriod(), GetShowSameTipPeriod(), m_conditions);
return GetTipImpl(GetShowAnyTipPeriod(), GetShowSameTipPeriod(), m_delegate, m_conditions);
}
// static
boost::optional<eye::Tip::Type> TipsApi::GetTipForTesting(Duration showAnyTipPeriod,
Duration showSameTipPeriod,
TipsApi::Delegate const & delegate,
Conditions const & triggers)
{
return GetTipImpl(showAnyTipPeriod, showSameTipPeriod, triggers);
return GetTipImpl(showAnyTipPeriod, showSameTipPeriod, delegate, triggers);
}

View file

@ -16,7 +16,7 @@ class TipsApi
{
public:
using Duration = std::chrono::duration<uint64_t>;
using Condition = std::function<bool()>;
using Condition = std::function<bool(eye::Info const & info)>;
using Conditions = std::array<Condition, static_cast<size_t>(eye::Tip::Type::Count)>;
class Delegate
@ -27,10 +27,12 @@ public:
virtual boost::optional<m2::PointD> GetCurrentPosition() const = 0;
virtual bool IsCountryLoaded(m2::PointD const & pt) const = 0;
virtual bool HaveTransit(m2::PointD const & pt) const = 0;
virtual double GetLastBackgroundTime() const = 0;
};
static Duration GetShowAnyTipPeriod();
static Duration GetShowSameTipPeriod();
static Duration ShowTipAfterCollapsingPeriod();
static size_t GetActionClicksCountToDisable();
static size_t GetGotitClicksCountToDisable();
@ -40,6 +42,7 @@ public:
static boost::optional<eye::Tip::Type> GetTipForTesting(Duration showAnyTipPeriod,
Duration showSameTipPeriod,
TipsApi::Delegate const & delegate,
Conditions const & triggers);
private:

View file

@ -100,6 +100,76 @@ void Eye::AppendTip(Tip::Type type, Tip::Event event)
Save(editableInfo);
}
void Eye::UpdateBookingFilterUsedTime()
{
auto const info = m_info.Get();
auto editableInfo = std::make_shared<Info>(*info);
editableInfo->m_booking.m_lastFilterUsedTime = Clock::now();
Save(editableInfo);
}
void Eye::UpdateBoomarksCatalogShownTime()
{
auto const info = m_info.Get();
auto editableInfo = std::make_shared<Info>(*info);
editableInfo->m_bookmarks.m_lastOpenedTime = Clock::now();
Save(editableInfo);
}
void Eye::UpdateDiscoveryShownTime()
{
auto const info = m_info.Get();
auto editableInfo = std::make_shared<Info>(*info);
editableInfo->m_discovery.m_lastOpenedTime = Clock::now();
Save(editableInfo);
}
void Eye::IncrementDiscoveryItem(Discovery::Event event)
{
auto const info = m_info.Get();
auto editableInfo = std::make_shared<Info>(*info);
editableInfo->m_discovery.m_lastClickedTime = Clock::now();
editableInfo->m_discovery.m_eventCounters.Increment(event);
Save(editableInfo);
}
void Eye::AppendLayer(Layer::Type type)
{
auto const info = m_info.Get();
auto editableInfo = std::make_shared<Info>(*info);
auto & editableLayers = editableInfo->m_layers;
auto it = std::find_if(editableLayers.begin(), editableLayers.end(), [type](Layer const & layer)
{
return layer.m_type == type;
});
if (it != editableLayers.end())
{
++it->m_useCount;
it->m_lastTimeUsed = Clock::now();
}
else
{
Layer layer;
layer.m_type = type;
++layer.m_useCount;
layer.m_lastTimeUsed = Clock::now();
editableLayers.emplace_back(std::move(layer));
}
Save(editableInfo);
}
// Eye::Event methods ------------------------------------------------------------------------------
// static
void Eye::Event::TipShown(Tip::Type type, Tip::Event event)
@ -109,4 +179,49 @@ void Eye::Event::TipShown(Tip::Type type, Tip::Event event)
Instance().AppendTip(type, event);
});
}
// static
void Eye::Event::BookingFilterUsed()
{
GetPlatform().RunTask(Platform::Thread::File, []
{
Instance().UpdateBookingFilterUsedTime();
});
}
// static
void Eye::Event::BoomarksCatalogShown()
{
GetPlatform().RunTask(Platform::Thread::File, []
{
Instance().UpdateBoomarksCatalogShownTime();
});
}
// static
void Eye::Event::DiscoveryShown()
{
GetPlatform().RunTask(Platform::Thread::File, []
{
Instance().UpdateDiscoveryShownTime();
});
}
// static
void Eye::Event::DiscoveryItemClicked(Discovery::Event event)
{
GetPlatform().RunTask(Platform::Thread::File, [event]
{
Instance().IncrementDiscoveryItem(event);
});
}
// static
void Eye::Event::LayerUsed(Layer::Type type)
{
GetPlatform().RunTask(Platform::Thread::File, [type]
{
Instance().AppendLayer(type);
});
}
} // namespace eye

View file

@ -21,6 +21,11 @@ public:
{
public:
static void TipShown(Tip::Type type, Tip::Event event);
static void BookingFilterUsed();
static void BoomarksCatalogShown();
static void DiscoveryShown();
static void DiscoveryItemClicked(Discovery::Event event);
static void LayerUsed(Layer::Type type);
};
static Eye & Instance();
@ -34,6 +39,11 @@ private:
// Event processing:
void AppendTip(Tip::Type type, Tip::Event event);
void UpdateBookingFilterUsedTime();
void UpdateBoomarksCatalogShownTime();
void UpdateDiscoveryShownTime();
void IncrementDiscoveryItem(Discovery::Event event);
void AppendLayer(Layer::Type type);
base::AtomicSharedPtr<Info> m_info;

View file

@ -7,9 +7,10 @@
#include "base/visitor.hpp"
#include <array>
#include <cstdint>
#include <chrono>
#include <string>
#include <tuple>
#include <type_traits>
#include <vector>
namespace eye
@ -67,6 +68,64 @@ enum class Version : int8_t
using Clock = std::chrono::system_clock;
using Time = Clock::time_point;
struct Booking
{
DECLARE_VISITOR(visitor(m_lastFilterUsedTime, "last_filter_used_time"))
Time m_lastFilterUsedTime;
};
struct Bookmarks
{
DECLARE_VISITOR(visitor(m_lastOpenedTime, "last_use_time"))
Time m_lastOpenedTime;
};
struct Discovery
{
enum class Event
{
HotelsClicked,
AttractionsClicked,
CafesClicked,
LocalsClicked,
MoreHotelsClicked,
MoreAttractionsClicked,
MoreCafesClicked,
MoreLocalsClicked,
Count
};
DECLARE_VISITOR(visitor(m_eventCounters, "event_counters"),
visitor(m_lastOpenedTime, "last_opened_time"),
visitor(m_lastClickedTime, "last_clicked_time"))
Counters<Event, uint32_t> m_eventCounters;
Time m_lastOpenedTime;
Time m_lastClickedTime;
};
struct Layer
{
enum Type
{
TrafficJams,
PublicTransport
};
DECLARE_VISITOR(visitor(m_type, "type"), visitor(m_useCount, "use_count"),
visitor(m_lastTimeUsed, "last_time_used"))
Type m_type;
uint64_t m_useCount = 0;
Time m_lastTimeUsed;
};
using Layers = std::vector<Layer>;
struct Tip
{
// The order is important.
@ -102,8 +161,14 @@ using Tips = std::vector<Tip>;
struct InfoV0
{
static Version GetVersion() { return Version::V0; }
DECLARE_VISITOR(visitor(m_tips, "tips"))
DECLARE_VISITOR(visitor(m_booking, "booking"), visitor(m_bookmarks, "bookmarks"),
visitor(m_discovery, "discovery"), visitor(m_layers, "layers"),
visitor(m_tips, "tips"))
Booking m_booking;
Bookmarks m_bookmarks;
Discovery m_discovery;
Layers m_layers;
Tips m_tips;
};

View file

@ -50,6 +50,18 @@ Time GetLastShownTipTime(Tips const & tips)
return lastShownTime;
}
Time GetLastShownLayerTime(Layers const & layers)
{
Time lastUsedTime;
for (auto const & layer : layers)
{
if (lastUsedTime < layer.m_lastTimeUsed)
lastUsedTime = layer.m_lastTimeUsed;
}
return lastUsedTime;
}
} // namespace
UNIT_TEST(Eye_SerdesTest)
@ -139,3 +151,175 @@ UNIT_CLASS_TEST(ScopedEyeForTesting, AppendTipTest)
TEST_NOT_EQUAL(prevShowTime, lastShownTipTime, ());
}
}
UNIT_CLASS_TEST(ScopedEyeForTesting, UpdateBookingFilterUsedTimeTest)
{
auto const initialInfo = Eye::Instance().GetInfo();
auto const & initialBooking = initialInfo->m_booking;
TEST_EQUAL(initialBooking.m_lastFilterUsedTime, Time(), ());
EyeForTesting::UpdateBookingFilterUsedTime();
auto const info = Eye::Instance().GetInfo();
auto const & booking = info->m_booking;
TEST_NOT_EQUAL(initialBooking.m_lastFilterUsedTime, booking.m_lastFilterUsedTime, ());
}
UNIT_CLASS_TEST(ScopedEyeForTesting, UpdateBoomarksCatalogShownTimeTest)
{
auto const initialInfo = Eye::Instance().GetInfo();
auto const & initialBookmarks = initialInfo->m_bookmarks;
TEST_EQUAL(initialBookmarks.m_lastOpenedTime, Time(), ());
EyeForTesting::UpdateBoomarksCatalogShownTime();
auto const info = Eye::Instance().GetInfo();
auto const & bookmarks = info->m_bookmarks;
TEST_NOT_EQUAL(initialBookmarks.m_lastOpenedTime, bookmarks.m_lastOpenedTime, ());
}
UNIT_CLASS_TEST(ScopedEyeForTesting, UpdateDiscoveryShownTimeTest)
{
auto const initialInfo = Eye::Instance().GetInfo();
auto const & initialDiscovery = initialInfo->m_discovery;
TEST_EQUAL(initialDiscovery.m_lastOpenedTime, Time(), ());
EyeForTesting::UpdateDiscoveryShownTime();
auto const info = Eye::Instance().GetInfo();
auto const & discovery = info->m_discovery;
TEST_NOT_EQUAL(initialDiscovery.m_lastOpenedTime, discovery.m_lastOpenedTime, ());
}
UNIT_CLASS_TEST(ScopedEyeForTesting, IncrementDiscoveryItemTest)
{
auto const initialInfo = Eye::Instance().GetInfo();
auto const & initialDiscovery = initialInfo->m_discovery;
TEST_EQUAL(initialDiscovery.m_lastClickedTime, Time(), ());
TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::AttractionsClicked), 0, ());
TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::CafesClicked), 0, ());
TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::HotelsClicked), 0, ());
TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::LocalsClicked), 0, ());
TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::MoreAttractionsClicked), 0, ());
TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::MoreCafesClicked), 0, ());
TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::MoreHotelsClicked), 0, ());
TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::MoreLocalsClicked), 0, ());
{
EyeForTesting::IncrementDiscoveryItem(Discovery::Event::CafesClicked);
auto const info = Eye::Instance().GetInfo();
auto const & discovery = info->m_discovery;
TEST_NOT_EQUAL(initialDiscovery.m_lastClickedTime, discovery.m_lastClickedTime, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::AttractionsClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::CafesClicked), 1, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::HotelsClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::LocalsClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreAttractionsClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreCafesClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreHotelsClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreLocalsClicked), 0, ());
}
{
EyeForTesting::IncrementDiscoveryItem(Discovery::Event::CafesClicked);
auto const info = Eye::Instance().GetInfo();
auto const & discovery = info->m_discovery;
TEST_NOT_EQUAL(initialDiscovery.m_lastClickedTime, discovery.m_lastClickedTime, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::AttractionsClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::CafesClicked), 2, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::HotelsClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::LocalsClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreAttractionsClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreCafesClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreHotelsClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreLocalsClicked), 0, ());
}
{
EyeForTesting::IncrementDiscoveryItem(Discovery::Event::CafesClicked);
EyeForTesting::IncrementDiscoveryItem(Discovery::Event::HotelsClicked);
EyeForTesting::IncrementDiscoveryItem(Discovery::Event::MoreLocalsClicked);
EyeForTesting::IncrementDiscoveryItem(Discovery::Event::MoreHotelsClicked);
auto const info = Eye::Instance().GetInfo();
auto const & discovery = info->m_discovery;
TEST_NOT_EQUAL(initialDiscovery.m_lastClickedTime, discovery.m_lastClickedTime, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::AttractionsClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::CafesClicked), 3, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::HotelsClicked), 1, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::LocalsClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreAttractionsClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreCafesClicked), 0, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreHotelsClicked), 1, ());
TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreLocalsClicked), 1, ());
}
}
UNIT_CLASS_TEST(ScopedEyeForTesting, AppendLayerTest)
{
{
auto const initialInfo = Eye::Instance().GetInfo();
auto const & initialLayers = initialInfo->m_layers;
TEST(initialLayers.empty(), ());
TEST_EQUAL(GetLastShownLayerTime(initialLayers), Time(), ());
}
Time prevShowTime;
{
EyeForTesting::AppendLayer(Layer::Type::PublicTransport);
auto const info = Eye::Instance().GetInfo();
auto const & layers = info->m_layers;
auto const prevShowTime = GetLastShownLayerTime(layers);
TEST_EQUAL(layers.size(), 1, ());
TEST_NOT_EQUAL(layers[0].m_lastTimeUsed, Time(), ());
TEST_EQUAL(layers[0].m_type, Layer::Type::PublicTransport, ());
TEST_EQUAL(layers[0].m_useCount, 1, ());
TEST_NOT_EQUAL(prevShowTime, Time(), ());
}
{
EyeForTesting::AppendLayer(Layer::Type::TrafficJams);
auto const info = Eye::Instance().GetInfo();
auto const & layers = info->m_layers;
auto const lastShownLayerTime = GetLastShownLayerTime(layers);
TEST_EQUAL(layers.size(), 2, ());
TEST_NOT_EQUAL(layers[1].m_lastTimeUsed, Time(), ());
TEST_EQUAL(layers[1].m_type, Layer::Type::TrafficJams, ());
TEST_EQUAL(layers[1].m_useCount, 1, ());
TEST_EQUAL(layers[1].m_lastTimeUsed, lastShownLayerTime, ());
TEST_NOT_EQUAL(prevShowTime, lastShownLayerTime, ());
prevShowTime = lastShownLayerTime;
}
{
EyeForTesting::AppendLayer(Layer::Type::TrafficJams);
auto const info = Eye::Instance().GetInfo();
auto const & layers = info->m_layers;
auto const lastShownLayerTime = GetLastShownLayerTime(layers);
TEST_EQUAL(layers.size(), 2, ());
TEST_NOT_EQUAL(layers[1].m_lastTimeUsed, Time(), ());
TEST_EQUAL(layers[1].m_type, Layer::Type::TrafficJams, ());
TEST_EQUAL(layers[1].m_useCount, 2, ());
TEST_EQUAL(layers[1].m_lastTimeUsed, lastShownLayerTime, ());
TEST_NOT_EQUAL(prevShowTime, lastShownLayerTime, ());
}
}

View file

@ -20,6 +20,12 @@ void EyeForTesting::ResetEye()
my::DeleteFileX(path);
}
// static
void EyeForTesting::SetInfo(Info const & info)
{
Eye::Instance().m_info.Set(std::make_shared<Info>(info));
}
// static
void EyeForTesting::AppendTip(Tip::Type type, Tip::Event event)
{
@ -27,8 +33,32 @@ void EyeForTesting::AppendTip(Tip::Type type, Tip::Event event)
}
// static
void EyeForTesting::SetInfo(Info const & info)
void EyeForTesting::UpdateBookingFilterUsedTime()
{
Eye::Instance().m_info.Set(std::make_shared<Info>(info));
Eye::Instance().UpdateBookingFilterUsedTime();
}
// static
void EyeForTesting::UpdateBoomarksCatalogShownTime()
{
Eye::Instance().UpdateBoomarksCatalogShownTime();
}
// static
void EyeForTesting::UpdateDiscoveryShownTime()
{
Eye::Instance().UpdateDiscoveryShownTime();
}
// static
void EyeForTesting::IncrementDiscoveryItem(Discovery::Event event)
{
Eye::Instance().IncrementDiscoveryItem(event);
}
// static
void EyeForTesting::AppendLayer(Layer::Type type)
{
Eye::Instance().AppendLayer(type);
}
} // namespace eye

View file

@ -8,8 +8,13 @@ class EyeForTesting
{
public:
static void ResetEye();
static void AppendTip(Tip::Type type, Tip::Event event);
static void SetInfo(Info const & info);
static void AppendTip(Tip::Type type, Tip::Event event);
static void UpdateBookingFilterUsedTime();
static void UpdateBoomarksCatalogShownTime();
static void UpdateDiscoveryShownTime();
static void IncrementDiscoveryItem(Discovery::Event event);
static void AppendLayer(Layer::Type type);
};
class ScopedEyeForTesting