chromium/chrome/browser/ash/hats/hats_dialog_unittest.cc

// Copyright 2021 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/hats/hats_dialog.h"

#include <string>

#include "ash/constants/ash_features.h"
#include "base/test/metrics/histogram_tester.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash {

namespace {
constexpr char kHistogramName[] = "Some.Kind.Of.Histogram";
}  // namespace

class HatsDialogTest : public testing::Test {
 public:
  void TriggerAction(std::string action) {
    EXPECT_FALSE(
        HatsDialog::HandleClientTriggeredAction(action, kHistogramName));
  }

  void TriggerActionAndClose(std::string action) {
    EXPECT_TRUE(
        HatsDialog::HandleClientTriggeredAction(action, kHistogramName));
  }

  std::vector<base::Bucket> GetHistogramSamples() {
    return histogram_tester_.GetAllSamples(kHistogramName);
  }

 private:
  base::HistogramTester histogram_tester_;
};

TEST_F(HatsDialogTest, HandleClientTriggeredAction_Unknown) {
  // Client sent an invalid action, ignore it
  TriggerAction("Invalid");

  EXPECT_THAT(GetHistogramSamples(), testing::IsEmpty());
}

TEST_F(HatsDialogTest, HandleClientTriggeredAction_Loaded) {
  // Client asks to close the window
  TriggerAction("load");

  std::vector<base::Bucket> expected = {
      {2, 1}};  // 2 is the enumeration for "Displayed".
  EXPECT_EQ(GetHistogramSamples(), expected);
}

TEST_F(HatsDialogTest, HandleClientTriggeredAction_Close) {
  // Client asks to close the window
  TriggerActionAndClose("close");

  EXPECT_THAT(GetHistogramSamples(), testing::IsEmpty());
}

TEST_F(HatsDialogTest, HandleClientTriggeredAction_Complete) {
  // Client asks to close the window
  TriggerActionAndClose("complete");

  std::vector<base::Bucket> expected = {
      {3, 1}};  // 3 is the enumeration for "Complete".
  EXPECT_EQ(GetHistogramSamples(), expected);
}

TEST_F(HatsDialogTest, HandleClientTriggeredAction_Error) {
  // There was an unhandled error, close the window
  TriggerActionAndClose("survey-loading-error-12345");

  EXPECT_THAT(GetHistogramSamples(), testing::IsEmpty());
}

TEST_F(HatsDialogTest, HandleClientTriggeredAction_OldQuestionResponse) {
  TriggerAction("smiley-selected-2");
  TriggerAction("smiley-selected-2");
  TriggerAction("smiley-selected-4");

  EXPECT_THAT(GetHistogramSamples(), testing::IsEmpty());
}

TEST_F(HatsDialogTest, HandleClientTriggeredAction_InvalidQuestion) {
  TriggerAction("answer-a-2");

  EXPECT_THAT(GetHistogramSamples(), testing::IsEmpty());
}

TEST_F(HatsDialogTest, HandleClientTriggeredAction_FirstQuestion) {
  TriggerAction("answer-1-2");

  std::vector<base::Bucket> expected = {{102, 1}};
  EXPECT_EQ(GetHistogramSamples(), expected);
}

TEST_F(HatsDialogTest, HandleClientTriggeredAction_SingleSelectQuestion) {
  TriggerAction("answer-2-4");

  std::vector<base::Bucket> expected = {{204, 1}};
  EXPECT_EQ(GetHistogramSamples(), expected);
}

TEST_F(HatsDialogTest, HandleClientTriggeredAction_MultipleSelectQuestion) {
  TriggerAction("answer-3-2,4,5");

  std::vector<base::Bucket> expected = {{302, 1}, {304, 1}, {305, 1}};
  EXPECT_EQ(GetHistogramSamples(), expected);
}

TEST_F(HatsDialogTest, HandleClientTriggeredAction_FullWorkflow) {
  TriggerAction("load");
  TriggerAction("answer-1-2");
  TriggerAction("answer-2-3");
  TriggerAction("answer-3-4,5");
  TriggerActionAndClose("complete");

  std::vector<base::Bucket> expected = {{2, 1},   {3, 1},   {102, 1},
                                        {203, 1}, {304, 1}, {305, 1}};
  EXPECT_EQ(GetHistogramSamples(), expected);
}

TEST_F(HatsDialogTest, ParseAnswer) {
  int question;
  std::vector<int> scores;

  // Incomplete answers
  EXPECT_FALSE(HatsDialog::ParseAnswer("answer-", &question, &scores));
  EXPECT_FALSE(HatsDialog::ParseAnswer("answer-1", &question, &scores));
  EXPECT_FALSE(HatsDialog::ParseAnswer("answer-1-", &question, &scores));

  // Invalid integers.
  EXPECT_FALSE(HatsDialog::ParseAnswer("answer-a-1,2,3", &question, &scores));
  EXPECT_FALSE(HatsDialog::ParseAnswer("answer-1-a", &question, &scores));

  // Out of range
  EXPECT_FALSE(HatsDialog::ParseAnswer("answer--1-1,2,3", &question, &scores));
  EXPECT_FALSE(HatsDialog::ParseAnswer("answer-1--1", &question, &scores));
  EXPECT_FALSE(HatsDialog::ParseAnswer("answer-0-1,2,3", &question, &scores));
  EXPECT_FALSE(HatsDialog::ParseAnswer("answer-11-1", &question, &scores));
  EXPECT_FALSE(HatsDialog::ParseAnswer("answer-1-101", &question, &scores));

  // Overflow int.
  EXPECT_FALSE(
      HatsDialog::ParseAnswer("answer-2147483648-a", &question, &scores));
  EXPECT_FALSE(
      HatsDialog::ParseAnswer("answer-1-2147483648", &question, &scores));

  EXPECT_TRUE(HatsDialog::ParseAnswer("answer-1-10", &question, &scores));
  EXPECT_EQ(question, 1);
  EXPECT_EQ(scores.size(), 1UL);
  EXPECT_EQ(scores[0], 10);

  scores.clear();
  EXPECT_TRUE(HatsDialog::ParseAnswer("answer-2-1,2", &question, &scores));
  EXPECT_EQ(question, 2);
  EXPECT_EQ(scores.size(), 2UL);
  EXPECT_EQ(scores[0], 1);
  EXPECT_EQ(scores[1], 2);
}

}  // namespace ash