chromium/ash/ambient/ui/ambient_animation_attribution_transformer_unittest.cc

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

#include "ash/ambient/ui/ambient_animation_attribution_transformer.h"

#include <memory>
#include <string>
#include <string_view>

#include "ash/ambient/test/ambient_test_util.h"
#include "base/check.h"

#include "cc/paint/skottie_resource_metadata.h"
#include "cc/paint/skottie_text_property_value.h"
#include "cc/paint/skottie_transform_property_value.h"
#include "cc/paint/skottie_wrapper.h"
#include "cc/test/lottie_test_data.h"
#include "cc/test/skia_common.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/test/geometry_util.h"
#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/lottie/animation.h"
#include "ui/views/controls/animated_image_view.h"

namespace ash {
namespace {

using ::testing::Eq;

constexpr float kTextBoxCoordinatesTolerance = 0.5f;

class AmbientAnimationAttributionTransformerTest : public ::testing::Test {
 protected:
  AmbientAnimationAttributionTransformerTest()
      : AmbientAnimationAttributionTransformerTest(
            GenerateLottieCustomizableIdForTesting(/*unique_id=*/1),
            GenerateLottieCustomizableIdForTesting(/*unique_id=*/2)) {}

  AmbientAnimationAttributionTransformerTest(std::string_view text_node_1_name,
                                             std::string_view text_node_2_name)
      : text_node_1_name_(text_node_1_name),
        text_node_2_name_(text_node_2_name) {
    view_.SetAnimatedImage(std::make_unique<lottie::Animation>(
        cc::CreateSkottieFromString(cc::CreateCustomLottieDataWith2TextNodes(
            text_node_1_name_, text_node_2_name_))));
    view_.SetHorizontalAlignment(views::ImageViewBase::Alignment::kCenter);
    view_.SetVerticalAlignment(views::ImageViewBase::Alignment::kCenter);
    animation_original_size_ = view_.animated_image()->GetOriginalSize();
  }

  gfx::RectF GetAbsoluteTextBoxCoordinates(std::string_view text_node_name) {
    cc::SkottieResourceIdHash text_node_id =
        cc::HashSkottieResourceId(text_node_name);
    cc::SkottieTransformPropertyValueMap transform_properties =
        view_.animated_image()->skottie()->GetCurrentTransformPropertyValues();
    CHECK(transform_properties.contains(text_node_id))
        << "Transform property not found for " << text_node_name;
    const cc::SkottieTextPropertyValueMap& text_map =
        view_.animated_image()->text_map();
    CHECK(text_map.contains(text_node_id))
        << "Text property not found for " << text_node_name;
    return text_map.at(text_node_id).box() +
           transform_properties.at(text_node_id).position.OffsetFromOrigin();
  }

  const std::string text_node_1_name_;
  const std::string text_node_2_name_;
  views::AnimatedImageView view_;
  gfx::Size animation_original_size_;
};

class AmbientAnimationAttributionTransformerTestWithStaticText
    : public AmbientAnimationAttributionTransformerTest {
 protected:
  AmbientAnimationAttributionTransformerTestWithStaticText()
      : AmbientAnimationAttributionTransformerTest(
            cc::kLottieDataWith2TextNode1,
            cc::kLottieDataWith2TextNode2) {}
};

TEST_F(AmbientAnimationAttributionTransformerTest, ViewSmallerThanAnimation) {
  const gfx::Rect view_bounds(animation_original_size_.width() / 2,
                              animation_original_size_.height() / 2);
  view_.SetBoundsRect(view_bounds);
  AmbientAnimationAttributionTransformer::TransformTextBox(view_);

  gfx::RectF expected_box;
  expected_box.set_width((animation_original_size_.width() / 4) +
                         (view_bounds.width() - 24));
  expected_box.set_height(cc::kLottieDataWith2TextNode1Box.height());
  expected_box.set_x(0);
  expected_box.set_y((animation_original_size_.height() / 4) +
                     (view_bounds.height() - 24 - expected_box.height()));
  EXPECT_RECTF_NEAR(GetAbsoluteTextBoxCoordinates(text_node_1_name_),
                    expected_box, kTextBoxCoordinatesTolerance);

  expected_box.set_height(cc::kLottieDataWith2TextNode2Box.height());
  expected_box.set_y((animation_original_size_.height() / 4) +
                     (view_bounds.height() - 24 - expected_box.height()));
  EXPECT_RECTF_NEAR(GetAbsoluteTextBoxCoordinates(text_node_2_name_),
                    expected_box, kTextBoxCoordinatesTolerance);
}

TEST_F(AmbientAnimationAttributionTransformerTest, ViewLargerThanAnimation) {
  const gfx::Rect view_bounds(animation_original_size_.width() * 2,
                              animation_original_size_.height() * 2);
  view_.SetBoundsRect(view_bounds);
  AmbientAnimationAttributionTransformer::TransformTextBox(view_);
  gfx::RectF expected_box;
  expected_box.set_width(animation_original_size_.width());
  expected_box.set_height(cc::kLottieDataWith2TextNode1Box.height());
  expected_box.set_x(0);
  expected_box.set_y(animation_original_size_.height() - expected_box.height());
  EXPECT_RECTF_NEAR(GetAbsoluteTextBoxCoordinates(text_node_1_name_),
                    expected_box, kTextBoxCoordinatesTolerance);
}

TEST_F(AmbientAnimationAttributionTransformerTestWithStaticText,
       ViewLargerThanAnimation) {
  view_.SetBoundsRect(gfx::Rect(animation_original_size_));
  AmbientAnimationAttributionTransformer::TransformTextBox(view_);
  // Static text nodes shouldn't change.
  EXPECT_RECTF_EQ(view_.animated_image()
                      ->text_map()
                      .at(cc::HashSkottieResourceId(text_node_1_name_))
                      .box(),
                  cc::kLottieDataWith2TextNode1Box);
  EXPECT_RECTF_EQ(view_.animated_image()
                      ->text_map()
                      .at(cc::HashSkottieResourceId(text_node_2_name_))
                      .box(),
                  cc::kLottieDataWith2TextNode2Box);
}

}  // namespace
}  // namespace ash