blob: b78be7f572a000d8071abf627bb62c68b6012406 [file] [log] [blame]
// 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)));
}