| // Copyright 2019 The Fuchsia 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 <fuchsia/modular/testing/cpp/fidl.h> |
| |
| #include <gmock/gmock.h> |
| |
| #include "src/modular/lib/modular_test_harness/cpp/fake_session_shell.h" |
| #include "src/modular/lib/modular_test_harness/cpp/test_harness_fixture.h" |
| #include "src/modular/lib/testing/session_shell_impl.h" |
| |
| using testing::ElementsAre; |
| using testing::Gt; |
| |
| namespace { |
| |
| class LastFocusTimeTest : public modular_testing::TestHarnessFixture {}; |
| |
| // A simple story provider watcher implementation. It confirms that it sees an |
| // increase in the last_focus_time in the fuchsia::modular::StoryInfo it |
| // receives, and pushes the test through to the next step. |
| class TestStoryProviderWatcher : public fuchsia::modular::StoryProviderWatcher { |
| public: |
| TestStoryProviderWatcher() : binding_(this) {} |
| ~TestStoryProviderWatcher() override = default; |
| |
| void OnChange2(fit::function<void(fuchsia::modular::StoryInfo2)> on_change) { |
| on_change_2_ = std::move(on_change); |
| } |
| |
| void Watch(fuchsia::modular::StoryProvider* const story_provider) { |
| story_provider->Watch(binding_.NewBinding()); |
| } |
| |
| private: |
| // |fuchsia::modular::StoryProviderWatcher| |
| void OnDelete(::std::string story_id) override {} |
| |
| // |fuchsia::modular::StoryProviderWatcher| |
| void OnChange2(fuchsia::modular::StoryInfo2 story_info, fuchsia::modular::StoryState story_state, |
| fuchsia::modular::StoryVisibilityState story_visibility_state) override { |
| on_change_2_(std::move(story_info)); |
| return; |
| } |
| |
| fit::function<void(fuchsia::modular::StoryInfo2)> on_change_2_; |
| fidl::Binding<fuchsia::modular::StoryProviderWatcher> binding_; |
| }; |
| |
| class TestStoryWatcher : fuchsia::modular::StoryWatcher { |
| public: |
| TestStoryWatcher() : binding_(this) {} |
| ~TestStoryWatcher() override = default; |
| |
| // Registers itself as a watcher on the given story. Only one story at a time |
| // can be watched. |
| void Watch(fuchsia::modular::StoryController* const story_controller) { |
| story_controller->Watch(binding_.NewBinding()); |
| } |
| |
| // Sets the function where to continue when the story is observed to be |
| // running. |
| void OnStoryRunning(fit::function<void()> at) { continue_ = std::move(at); } |
| |
| private: |
| // |fuchsia::modular::StoryWatcher| |
| void OnStateChange(fuchsia::modular::StoryState state) override { |
| if (state != fuchsia::modular::StoryState::RUNNING) { |
| return; |
| } |
| |
| continue_(); |
| } |
| |
| // |fuchsia::modular::StoryWatcher| |
| void OnModuleAdded(fuchsia::modular::ModuleData /*module_data*/) override {} |
| |
| // |fuchsia::modular::StoryWatcher| |
| void OnModuleFocused(std::vector<std::string> /*module_path*/) override {} |
| |
| fit::function<void()> continue_; |
| fidl::Binding<fuchsia::modular::StoryWatcher> binding_; |
| }; |
| } // namespace |
| |
| const char kStoryName[] = "storyname"; |
| |
| TEST_F(LastFocusTimeTest, LastFocusTimeIncreases) { |
| modular_testing::TestHarnessBuilder builder; |
| |
| auto test_session_shell = modular_testing::FakeSessionShell::CreateWithDefaultOptions(); |
| builder.InterceptSessionShell(test_session_shell->BuildInterceptOptions()); |
| |
| // Listen for the module we're going to create. |
| modular_testing::FakeComponent test_module( |
| {.url = modular_testing::TestHarnessBuilder::GenerateFakeUrl()}); |
| builder.InterceptComponent(test_module.BuildInterceptOptions()); |
| builder.BuildAndRun(test_harness()); |
| |
| // Wait for our session shell to start. |
| RunLoopUntil([&] { return test_session_shell->is_running(); }); |
| |
| fuchsia::modular::FocusControllerPtr focus_controller; |
| fuchsia::modular::FocusProviderPtr focus_provider; |
| test_session_shell->session_shell_context()->GetFocusController(focus_controller.NewRequest()); |
| test_session_shell->session_shell_context()->GetFocusProvider(focus_provider.NewRequest()); |
| |
| // Watch for changes to the session. |
| TestStoryProviderWatcher story_provider_watcher; |
| story_provider_watcher.Watch(test_session_shell->story_provider()); |
| |
| // Keep track of the focus timestamps that we receive for the story created |
| // below so we can assert that they make sense at the end of the test. |
| std::vector<int64_t> last_focus_timestamps; |
| story_provider_watcher.OnChange2([&](fuchsia::modular::StoryInfo2 story_info) { |
| ASSERT_TRUE(story_info.has_id()); |
| ASSERT_TRUE(story_info.has_last_focus_time()); |
| ASSERT_EQ(kStoryName, story_info.id()); |
| last_focus_timestamps.push_back(story_info.last_focus_time()); |
| }); |
| |
| // Create a story so that we can signal the framework to focus it. |
| fuchsia::modular::Intent intent; |
| intent.handler = test_module.url(); |
| intent.action = "action"; |
| |
| modular_testing::AddModToStory(test_harness(), kStoryName, "modname", std::move(intent)); |
| |
| RunLoopUntil([&] { return test_module.is_running(); }); |
| |
| // Watch the story and then start it. |
| TestStoryWatcher story_watcher; |
| fuchsia::modular::StoryControllerPtr story_controller; |
| test_session_shell->story_provider()->GetController(kStoryName, story_controller.NewRequest()); |
| story_watcher.Watch(story_controller.get()); |
| story_controller->RequestStart(); |
| |
| story_watcher.OnStoryRunning([&] { |
| // Focus the story! |
| focus_controller->Set(kStoryName); |
| }); |
| |
| // Run until we have been notified of new last_focus_time values three times. |
| // We expect a call for each of: |
| // 1) The story is created. |
| // 2) The story transitions to running. |
| // 3) The story is focused. |
| RunLoopUntil([&] { return last_focus_timestamps.size() == 3; }); |
| EXPECT_THAT(last_focus_timestamps, ElementsAre(0, 0, Gt(0))); |
| } |