// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Included first as it collides with the X11 headers.
#include "gtest/gtest.h"

#include "flutter/shell/platform/linux/fl_accessible_node.h"
#include "flutter/shell/platform/linux/testing/fl_test.h"

// Checks can build a tree of nodes.
TEST(FlAccessibleNodeTest, BuildTree) {
  g_autoptr(FlEngine) engine = make_mock_engine();

  g_autoptr(FlAccessibleNode) root = fl_accessible_node_new(engine, 0);
  g_autoptr(FlAccessibleNode) child1 = fl_accessible_node_new(engine, 1);
  fl_accessible_node_set_parent(child1, ATK_OBJECT(root), 0);
  g_autoptr(FlAccessibleNode) child2 = fl_accessible_node_new(engine, 1);
  fl_accessible_node_set_parent(child2, ATK_OBJECT(root), 1);
  g_autoptr(GPtrArray) children =
      g_ptr_array_new_with_free_func(g_object_unref);
  g_ptr_array_add(children, g_object_ref(child1));
  g_ptr_array_add(children, g_object_ref(child2));
  fl_accessible_node_set_children(root, children);

  EXPECT_EQ(atk_object_get_n_accessible_children(ATK_OBJECT(root)), 2);
  EXPECT_EQ(atk_object_get_index_in_parent(ATK_OBJECT(root)), 0);
  g_autoptr(AtkObject) c1 =
      atk_object_ref_accessible_child(ATK_OBJECT(root), 0);
  EXPECT_EQ(ATK_OBJECT(child1), c1);
  g_autoptr(AtkObject) c2 =
      atk_object_ref_accessible_child(ATK_OBJECT(root), 1);
  EXPECT_EQ(ATK_OBJECT(child2), c2);
  EXPECT_EQ(atk_object_get_parent(ATK_OBJECT(root)), nullptr);

  EXPECT_EQ(atk_object_get_parent(ATK_OBJECT(child1)), ATK_OBJECT(root));
  EXPECT_EQ(atk_object_get_index_in_parent(ATK_OBJECT(child1)), 0);
  EXPECT_EQ(atk_object_get_n_accessible_children(ATK_OBJECT(child1)), 0);

  EXPECT_EQ(atk_object_get_parent(ATK_OBJECT(child2)), ATK_OBJECT(root));
  EXPECT_EQ(atk_object_get_index_in_parent(ATK_OBJECT(child2)), 1);
  EXPECT_EQ(atk_object_get_n_accessible_children(ATK_OBJECT(child2)), 0);
}

// Checks node name is exposed to ATK.
TEST(FlAccessibleNodeTest, SetName) {
  g_autoptr(FlEngine) engine = make_mock_engine();

  g_autoptr(FlAccessibleNode) node = fl_accessible_node_new(engine, 0);
  fl_accessible_node_set_name(node, "test");
  EXPECT_STREQ(atk_object_get_name(ATK_OBJECT(node)), "test");
}

// Checks node extents are exposed to ATK.
TEST(FlAccessibleNodeTest, SetExtents) {
  g_autoptr(FlEngine) engine = make_mock_engine();

  g_autoptr(FlAccessibleNode) node = fl_accessible_node_new(engine, 0);
  fl_accessible_node_set_extents(node, 1, 2, 3, 4);
  gint x, y, width, height;
  atk_component_get_extents(ATK_COMPONENT(node), &x, &y, &width, &height,
                            ATK_XY_PARENT);
  EXPECT_EQ(x, 1);
  EXPECT_EQ(y, 2);
  EXPECT_EQ(width, 3);
  EXPECT_EQ(height, 4);
}

// Checks Flutter flags are mapped to appropriate ATK state.
TEST(FlAccessibleNodeTest, SetFlags) {
  g_autoptr(FlEngine) engine = make_mock_engine();

  g_autoptr(FlAccessibleNode) node = fl_accessible_node_new(engine, 0);
  fl_accessible_node_set_flags(
      node, static_cast<FlutterSemanticsFlag>(kFlutterSemanticsFlagIsEnabled |
                                              kFlutterSemanticsFlagIsFocusable |
                                              kFlutterSemanticsFlagIsFocused));

  AtkStateSet* state = atk_object_ref_state_set(ATK_OBJECT(node));
  EXPECT_TRUE(atk_state_set_contains_state(state, ATK_STATE_ENABLED));
  EXPECT_TRUE(atk_state_set_contains_state(state, ATK_STATE_SENSITIVE));
  EXPECT_TRUE(atk_state_set_contains_state(state, ATK_STATE_FOCUSABLE));
  EXPECT_TRUE(atk_state_set_contains_state(state, ATK_STATE_FOCUSED));
  EXPECT_TRUE(!atk_state_set_contains_state(state, ATK_STATE_CHECKED));
  g_object_unref(state);
}

// Checks Flutter flags are mapped to appropriate ATK roles.
TEST(FlAccessibleNodeTest, GetRole) {
  g_autoptr(FlEngine) engine = make_mock_engine();

  g_autoptr(FlAccessibleNode) node = fl_accessible_node_new(engine, 0);

  fl_accessible_node_set_flags(
      node, static_cast<FlutterSemanticsFlag>(kFlutterSemanticsFlagIsButton));
  EXPECT_EQ(atk_object_get_role(ATK_OBJECT(node)), ATK_ROLE_PUSH_BUTTON);

  fl_accessible_node_set_flags(node, static_cast<FlutterSemanticsFlag>(
                                         kFlutterSemanticsFlagHasCheckedState));
  EXPECT_EQ(atk_object_get_role(ATK_OBJECT(node)), ATK_ROLE_CHECK_BOX);

  fl_accessible_node_set_flags(
      node, static_cast<FlutterSemanticsFlag>(
                kFlutterSemanticsFlagHasCheckedState |
                kFlutterSemanticsFlagIsInMutuallyExclusiveGroup));
  EXPECT_EQ(atk_object_get_role(ATK_OBJECT(node)), ATK_ROLE_RADIO_BUTTON);

  fl_accessible_node_set_flags(node, static_cast<FlutterSemanticsFlag>(
                                         kFlutterSemanticsFlagHasToggledState));
  EXPECT_EQ(atk_object_get_role(ATK_OBJECT(node)), ATK_ROLE_TOGGLE_BUTTON);

  fl_accessible_node_set_flags(node, kFlutterSemanticsFlagIsTextField);
  EXPECT_EQ(atk_object_get_role(ATK_OBJECT(node)), ATK_ROLE_TEXT);

  fl_accessible_node_set_flags(
      node, static_cast<FlutterSemanticsFlag>(kFlutterSemanticsFlagIsTextField |
                                              kFlutterSemanticsFlagIsObscured));
  EXPECT_EQ(atk_object_get_role(ATK_OBJECT(node)), ATK_ROLE_PASSWORD_TEXT);
}

// Checks Flutter actions are mapped to the appropriate ATK actions.
TEST(FlAccessibleNodeTest, SetActions) {
  g_autoptr(FlEngine) engine = make_mock_engine();

  g_autoptr(FlAccessibleNode) node = fl_accessible_node_new(engine, 0);
  fl_accessible_node_set_actions(
      node, static_cast<FlutterSemanticsAction>(
                kFlutterSemanticsActionTap | kFlutterSemanticsActionLongPress));

  EXPECT_EQ(atk_action_get_n_actions(ATK_ACTION(node)), 2);
  EXPECT_STREQ(atk_action_get_name(ATK_ACTION(node), 0), "Tap");
  EXPECT_STREQ(atk_action_get_name(ATK_ACTION(node), 1), "LongPress");
}
