[modular][storymodel] Don't notify observers when the StoryModel doesn't change.

TEST=fx run-test story_model_owner_unittest

Change-Id: I66d86e9675764d78d8b221ae63c6461663f7e23d
diff --git a/bin/sessionmgr/story/model/story_model_owner.cc b/bin/sessionmgr/story/model/story_model_owner.cc
index 7c65780..324c81e 100644
--- a/bin/sessionmgr/story/model/story_model_owner.cc
+++ b/bin/sessionmgr/story/model/story_model_owner.cc
@@ -148,7 +148,12 @@
   // HandleObservedMutations() will only be called on a single thread.
   StoryModel old_model;
   FXL_CHECK(fidl::Clone(model_, &old_model) == ZX_OK);
-  model_ = ApplyMutations(std::move(old_model), std::move(commands));
+  model_ = ApplyMutations(old_model, std::move(commands));
+
+  // Don't notify anyone if the model didn't change.
+  if (model_ == old_model) {
+    return;
+  }
 
   executor_->schedule_task(fit::make_promise([this] {
                              for (auto& listener : listeners_) {
diff --git a/bin/sessionmgr/story/model/story_model_owner_unittest.cc b/bin/sessionmgr/story/model/story_model_owner_unittest.cc
index 5da2a85..dfa2672 100644
--- a/bin/sessionmgr/story/model/story_model_owner_unittest.cc
+++ b/bin/sessionmgr/story/model/story_model_owner_unittest.cc
@@ -202,6 +202,25 @@
   EXPECT_TRUE(got_update3);
 }
 
+TEST_F(StoryModelOwnerTest, ObserversAreNotNotifiedOnNoChange) {
+  // Observers aren't told when an observed mutation doesn't change the model.
+  auto owner = Create("test");
+  auto mutator = owner->NewMutator();
+  auto observer = owner->NewObserver();
+
+  bool got_update{false};
+  observer->RegisterListener([&](const StoryModel& model) {
+    got_update = true;
+  });
+
+  std::vector<StoryModelMutation> commands;
+  commands.resize(1);
+  commands[0].set_set_visibility_state(StoryVisibilityState::DEFAULT);
+  model_storage()->Observe(std::move(commands));
+  RunLoopUntilIdle();
+  EXPECT_FALSE(got_update);
+}
+
 TEST_F(StoryModelOwnerTest, ObserversLifecycle_ClientDestroyed) {
   // When the client destroys its observer object, it no longer receives
   // updates.