chromium/chrome/browser/ash/crosapi/desk_profiles_ash_unittest.cc

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/crosapi/desk_profiles_ash.h"

#include "testing/gmock/include/gmock/gmock.h"

namespace crosapi {

using testing::ElementsAre;

MATCHER_P2(EqualsProfile, profile_id, name, "") {
  return profile_id == arg.profile_id && name == arg.name;
}

class DeskProfileObserver : public ash::DeskProfilesDelegate::Observer {
 public:
  void OnProfileUpsert(const ash::LacrosProfileSummary& summary) override {
    updates_.push_back(summary);
  }

  void OnProfileRemoved(uint64_t profile_id) override {
    removes_.push_back(profile_id);
  }

  std::vector<ash::LacrosProfileSummary> ConsumeUpdates() {
    return std::exchange(updates_, {});
  }

  std::vector<uint64_t> ConsumeRemoves() { return std::exchange(removes_, {}); }

 private:
  // Tracks received updates. Cleared by `ConsumeUpdates`.
  std::vector<ash::LacrosProfileSummary> updates_;

  // Tracks received removals. Cleared by `ConsumeRemoves`.
  std::vector<uint64_t> removes_;
};

class DeskProfilesAshTest : public testing::Test {
 public:
  ash::DeskProfilesDelegate& delegate() { return desk_profiles_ash_; }

  void SendProfileUpdate(
      const std::vector<std::pair<uint64_t, std::string>>& profiles) {
    // Convert to mojom format.
    std::vector<mojom::LacrosProfileSummaryPtr> mojom_profiles;
    for (const auto& [profile_id, name] : profiles) {
      auto summary = mojom::LacrosProfileSummary::New();
      summary->profile_id = profile_id;
      summary->name = name;

      mojom_profiles.push_back(std::move(summary));
    }

    desk_profiles_observer().OnProfileUpsert(std::move(mojom_profiles));
  }

  void SendProfileRemoved(uint64_t profile_id) {
    desk_profiles_observer().OnProfileRemoved(profile_id);
  }

 private:
  mojom::DeskProfileObserver& desk_profiles_observer() {
    return desk_profiles_ash_;
  }

  DeskProfilesAsh desk_profiles_ash_;
};

TEST_F(DeskProfilesAshTest, GetSnapshot) {
  // Initial empty state.
  EXPECT_THAT(delegate().GetProfilesSnapshot(), ElementsAre());

  // Snapshot order should match update order.
  SendProfileUpdate({{124u, "profile 1"}, {102u, "profile 2"}});
  EXPECT_THAT(delegate().GetProfilesSnapshot(),
              ElementsAre(EqualsProfile(124u, u"profile 1"),
                          EqualsProfile(102u, u"profile 2")));

  // Updated profile remains in place, new profile goes at the end.
  SendProfileUpdate({{124u, "profile 1 renamed"}, {100u, "profile 3"}});
  EXPECT_THAT(delegate().GetProfilesSnapshot(),
              ElementsAre(EqualsProfile(124u, u"profile 1 renamed"),
                          EqualsProfile(102u, u"profile 2"),
                          EqualsProfile(100u, u"profile 3")));

  // Removing a profile does not change the order among other profiles.
  SendProfileRemoved(102);
  EXPECT_THAT(delegate().GetProfilesSnapshot(),
              ElementsAre(EqualsProfile(124u, u"profile 1 renamed"),
                          EqualsProfile(100u, u"profile 3")));
}

TEST_F(DeskProfilesAshTest, ObserverTest) {
  DeskProfileObserver observer;
  delegate().AddObserver(&observer);

  SendProfileUpdate({{106u, "profile 2"}, {104u, "profile 3"}});
  EXPECT_THAT(observer.ConsumeUpdates(),
              ElementsAre(EqualsProfile(106u, u"profile 2"),
                          EqualsProfile(104u, u"profile 3")));
  EXPECT_THAT(observer.ConsumeRemoves(), ElementsAre());

  SendProfileUpdate({{106u, "profile 2 renamed"}});
  EXPECT_THAT(observer.ConsumeUpdates(),
              ElementsAre(EqualsProfile(106u, u"profile 2 renamed")));

  // Removal of unknown profile is not propagated to observers.
  SendProfileRemoved(102u);
  EXPECT_THAT(observer.ConsumeUpdates(), ElementsAre());
  EXPECT_THAT(observer.ConsumeRemoves(), ElementsAre());

  SendProfileRemoved(106u);
  EXPECT_THAT(observer.ConsumeUpdates(), ElementsAre());
  EXPECT_THAT(observer.ConsumeRemoves(), ElementsAre(106u));
}

}  // namespace crosapi