[gtk/ebassi/new-a11y: 59/63] a11y: Add testing API



commit 13af85aa8de52173923d410037b39bea5407e25d
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Fri Jul 17 14:39:56 2020 +0100

    a11y: Add testing API
    
    We want to test the accessibility API, as well as the implementation
    inside each widget. For that, we should expose an API that lets us
    verify that a GtkAccessible has a given role, as well as a given
    property.
    
    The API follows the pattern of other GTest API:
    
     - a macro to assert that a condition is respected
     - a function that prints out the error message in case of failure

 gtk/gtk.h                     |   1 +
 gtk/gtkaccessible.h           |   4 ++
 gtk/gtkatcontext.c            | 110 +++++++++++++++++++++++++++++++++++++++++-
 gtk/gtkatcontext.h            |   4 ++
 gtk/gtkatcontextprivate.h     |  10 ++++
 gtk/gtktestatcontext.c        |  84 ++++++++++++++++++++++++++++++++
 gtk/gtktestatcontext.h        |  73 ++++++++++++++++++++++++++++
 gtk/gtktestatcontextprivate.h |  13 +----
 gtk/meson.build               |   3 +-
 9 files changed, 288 insertions(+), 14 deletions(-)
---
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 6d897998aa..0bff9974e8 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -259,6 +259,7 @@
 #include <gtk/gtktextview.h>
 #include <gtk/gtktogglebutton.h>
 #include <gtk/gtktooltip.h>
+#include <gtk/gtktestatcontext.h>
 #include <gtk/gtktestutils.h>
 #include <gtk/gtktreednd.h>
 #include <gtk/gtktreeexpander.h>
diff --git a/gtk/gtkaccessible.h b/gtk/gtkaccessible.h
index d0a115d205..0f7776a1e4 100644
--- a/gtk/gtkaccessible.h
+++ b/gtk/gtkaccessible.h
@@ -20,6 +20,10 @@
 
 #pragma once
 
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
 #include <glib-object.h>
 #include <gtk/gtktypes.h>
 #include <gtk/gtkenums.h>
diff --git a/gtk/gtkatcontext.c b/gtk/gtkatcontext.c
index 7ea1f1a6bb..2fa6be8506 100644
--- a/gtk/gtkatcontext.c
+++ b/gtk/gtkatcontext.c
@@ -192,6 +192,24 @@ static const char *property_attrs[] = {
   [GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT]          = "valuetext",
 };
 
+/*< private >
+ * gtk_accessible_property_get_attribute_name:
+ * @property: a #GtkAccessibleProperty
+ *
+ * Retrieves the name of a #GtkAccessibleProperty.
+ *
+ * Returns: (transfer none): the name of the accessible property
+ */
+const char *
+gtk_accessible_property_get_attribute_name (GtkAccessibleProperty property)
+{
+  g_return_val_if_fail (property >= GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE &&
+                        property <= GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT,
+                        "<none>");
+
+  return property_attrs[property];
+}
+
 static const char *relation_attrs[] = {
   [GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT]   = "activedescendant",
   [GTK_ACCESSIBLE_RELATION_COL_COUNT]           = "colcount",
@@ -213,6 +231,24 @@ static const char *relation_attrs[] = {
   [GTK_ACCESSIBLE_RELATION_SET_SIZE]            = "setsize",
 };
 
+/*< private >
+ * gtk_accessible_relation_get_attribute_name:
+ * @relation: a #GtkAccessibleRelation
+ *
+ * Retrieves the name of a #GtkAccessibleRelation.
+ *
+ * Returns: (transfer none): the name of the accessible relation
+ */
+const char *
+gtk_accessible_relation_get_attribute_name (GtkAccessibleRelation relation)
+{
+  g_return_val_if_fail (relation >= GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT &&
+                        relation <= GTK_ACCESSIBLE_RELATION_SET_SIZE,
+                        "<none>");
+
+  return relation_attrs[relation];
+}
+
 static const char *state_attrs[] = {
   [GTK_ACCESSIBLE_STATE_BUSY]           = "busy",
   [GTK_ACCESSIBLE_STATE_CHECKED]        = "checked",
@@ -224,6 +260,24 @@ static const char *state_attrs[] = {
   [GTK_ACCESSIBLE_STATE_SELECTED]       = "selected",
 };
 
+/*< private >
+ * gtk_accessible_state_get_attribute_name:
+ * @state: a #GtkAccessibleState
+ *
+ * Retrieves the name of a #GtkAccessibleState.
+ *
+ * Returns: (transfer none): the name of the accessible state
+ */
+const char *
+gtk_accessible_state_get_attribute_name (GtkAccessibleState state)
+{
+  g_return_val_if_fail (state >= GTK_ACCESSIBLE_STATE_BUSY &&
+                        state <= GTK_ACCESSIBLE_STATE_SELECTED,
+                        "<none>");
+
+  return state_attrs[state];
+}
+
 static void
 gtk_at_context_init (GtkATContext *self)
 {
@@ -355,7 +409,7 @@ gtk_at_context_update (GtkATContext *self)
 }
 
 /*< private >
- * gtk_at_context_set_state:
+ * gtk_at_context_set_accessible_state:
  * @self: a #GtkATContext
  * @state: a #GtkAccessibleState
  * @value: (nullable): #GtkAccessibleValue
@@ -380,6 +434,24 @@ gtk_at_context_set_accessible_state (GtkATContext       *self,
     gtk_accessible_attribute_set_remove (self->states, state);
 }
 
+/*< private >
+ * gtk_at_context_has_accessible_state:
+ * @self: a #GtkATContext
+ * @state: a #GtkAccessibleState
+ *
+ * Checks whether a #GtkATContext has the given @state set.
+ *
+ * Returns: %TRUE, if the accessible state is set
+ */
+gboolean
+gtk_at_context_has_accessible_state (GtkATContext       *self,
+                                     GtkAccessibleState  state)
+{
+  g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), FALSE);
+
+  return gtk_accessible_attribute_set_contains (self->states, state);
+}
+
 /*< private >
  * gtk_at_context_set_accessible_property:
  * @self: a #GtkATContext
@@ -406,6 +478,24 @@ gtk_at_context_set_accessible_property (GtkATContext          *self,
     gtk_accessible_attribute_set_remove (self->properties, property);
 }
 
+/*< private >
+ * gtk_at_context_has_accessible_property:
+ * @self: a #GtkATContext
+ * @property: a #GtkAccessibleProperty
+ *
+ * Checks whether a #GtkATContext has the given @property set.
+ *
+ * Returns: %TRUE, if the accessible property is set
+ */
+gboolean
+gtk_at_context_has_accessible_property (GtkATContext          *self,
+                                        GtkAccessibleProperty  property)
+{
+  g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), FALSE);
+
+  return gtk_accessible_attribute_set_contains (self->properties, property);
+}
+
 /*< private >
  * gtk_at_context_set_accessible_relation:
  * @self: a #GtkATContext
@@ -431,3 +521,21 @@ gtk_at_context_set_accessible_relation (GtkATContext          *self,
   else
     gtk_accessible_attribute_set_remove (self->relations, relation);
 }
+
+/*< private >
+ * gtk_at_context_has_accessible_relation:
+ * @self: a #GtkATContext
+ * @relation: a #GtkAccessibleRelation
+ *
+ * Checks whether a #GtkATContext has the given @relation set.
+ *
+ * Returns: %TRUE, if the accessible relation is set
+ */
+gboolean
+gtk_at_context_has_accessible_relation (GtkATContext          *self,
+                                        GtkAccessibleRelation  relation)
+{
+  g_return_val_if_fail (GTK_IS_AT_CONTEXT (self), FALSE);
+
+  return gtk_accessible_attribute_set_contains (self->relations, relation);
+}
diff --git a/gtk/gtkatcontext.h b/gtk/gtkatcontext.h
index e2fca0f564..6522e029d6 100644
--- a/gtk/gtkatcontext.h
+++ b/gtk/gtkatcontext.h
@@ -20,6 +20,10 @@
 
 #pragma once
 
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
 #include <gtk/gtktypes.h>
 #include <gtk/gtkenums.h>
 #include <gtk/gtkaccessible.h>
diff --git a/gtk/gtkatcontextprivate.h b/gtk/gtkatcontextprivate.h
index c7f59f8fae..8c10db276c 100644
--- a/gtk/gtkatcontextprivate.h
+++ b/gtk/gtkatcontextprivate.h
@@ -113,11 +113,21 @@ void            gtk_at_context_update                   (GtkATContext          *
 void            gtk_at_context_set_accessible_state     (GtkATContext          *self,
                                                          GtkAccessibleState     state,
                                                          GtkAccessibleValue    *value);
+gboolean        gtk_at_context_has_accessible_state     (GtkATContext          *self,
+                                                         GtkAccessibleState     state);
 void            gtk_at_context_set_accessible_property  (GtkATContext          *self,
                                                          GtkAccessibleProperty  property,
                                                          GtkAccessibleValue    *value);
+gboolean        gtk_at_context_has_accessible_property  (GtkATContext          *self,
+                                                         GtkAccessibleProperty  property);
 void            gtk_at_context_set_accessible_relation  (GtkATContext          *self,
                                                          GtkAccessibleRelation  property,
                                                          GtkAccessibleValue    *value);
+gboolean        gtk_at_context_has_accessible_relation  (GtkATContext          *self,
+                                                         GtkAccessibleRelation  relation);
+
+const char *    gtk_accessible_property_get_attribute_name      (GtkAccessibleProperty property);
+const char *    gtk_accessible_relation_get_attribute_name      (GtkAccessibleRelation relation);
+const char *    gtk_accessible_state_get_attribute_name         (GtkAccessibleState    state);
 
 G_END_DECLS
diff --git a/gtk/gtktestatcontext.c b/gtk/gtktestatcontext.c
index 8eade3566c..b7eb29b642 100644
--- a/gtk/gtktestatcontext.c
+++ b/gtk/gtktestatcontext.c
@@ -24,12 +24,18 @@
 
 #include "gtkatcontextprivate.h"
 #include "gtkenums.h"
+#include "gtktypebuiltins.h"
 
 struct _GtkTestATContext
 {
   GtkATContext parent_instance;
 };
 
+struct _GtkTestATContextClass
+{
+  GtkATContextClass parent_class;
+};
+
 G_DEFINE_TYPE (GtkTestATContext, gtk_test_at_context, GTK_TYPE_AT_CONTEXT)
 
 static void
@@ -75,6 +81,16 @@ gtk_test_at_context_init (GtkTestATContext *self)
 {
 }
 
+/*< private >
+ * gtk_test_at_context_new:
+ * @accessible_role: the #GtkAccessibleRole for the AT context
+ * @accessible: the #GtkAccessible instance which owns the AT context
+ *
+ * Creates a new #GtkTestATContext instance for @accessible, using the
+ * given @accessible_role.
+ *
+ * Returns: (transfer full): the newly created #GtkTestATContext instance
+ */
 GtkATContext *
 gtk_test_at_context_new (GtkAccessibleRole  accessible_role,
                          GtkAccessible     *accessible)
@@ -84,3 +100,71 @@ gtk_test_at_context_new (GtkAccessibleRole  accessible_role,
                        "accessible", accessible,
                        NULL);
 }
+
+gboolean
+gtk_test_accessible_has_role (GtkAccessible     *accessible,
+                              GtkAccessibleRole  role)
+{
+  GtkATContext *context;
+
+  g_return_val_if_fail (GTK_IS_ACCESSIBLE (accessible), FALSE);
+
+  context = gtk_accessible_get_at_context (accessible);
+  if (context == NULL)
+    return FALSE;
+
+  return gtk_at_context_get_accessible_role (context) == role;
+}
+
+gboolean
+gtk_test_accessible_has_property (GtkAccessible         *accessible,
+                                  GtkAccessibleProperty  property)
+{
+  GtkATContext *context;
+
+  g_return_val_if_fail (GTK_IS_ACCESSIBLE (accessible), FALSE);
+
+  context = gtk_accessible_get_at_context (accessible);
+  if (context == NULL)
+    return FALSE;
+
+  return gtk_at_context_has_accessible_property (context, property);
+}
+
+void
+gtk_test_accessible_assertion_message_cmprole (const char        *domain,
+                                               const char        *file,
+                                               int                line,
+                                               const char        *func,
+                                               const char        *expr,
+                                               GtkAccessible     *accessible,
+                                               GtkAccessibleRole  role)
+{
+  char *role_name = g_enum_to_string (GTK_TYPE_ACCESSIBLE_ROLE, role);
+  char *s = g_strdup_printf ("%s:accessible-role == %s",
+                             G_OBJECT_TYPE_NAME (accessible),
+                             role_name);
+
+  g_assertion_message_expr (domain, file, line, func, s);
+
+  g_free (role_name);
+  g_free (s);
+}
+
+void
+gtk_test_accessible_assertion_message_cmpproperty (const char            *domain,
+                                                   const char            *file,
+                                                   int                    line,
+                                                   const char            *func,
+                                                   const char            *expr,
+                                                   GtkAccessible         *accessible,
+                                                   GtkAccessibleProperty  property)
+{
+  char *s = g_strdup_printf ("%s:accessible-property == %s",
+                             G_OBJECT_TYPE_NAME (accessible),
+                             gtk_accessible_property_get_attribute_name (property));
+
+  g_assertion_message_expr (domain, file, line, func, s);
+
+  g_free (s);
+}
diff --git a/gtk/gtktestatcontext.h b/gtk/gtktestatcontext.h
new file mode 100644
index 0000000000..50ab7302d5
--- /dev/null
+++ b/gtk/gtktestatcontext.h
@@ -0,0 +1,73 @@
+/* gtktestatcontext.h: Test AT context
+ *
+ * Copyright 2020  GNOME Foundation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gtk/gtkatcontext.h>
+
+G_BEGIN_DECLS
+
+#define gtk_test_accessible_assert_cmprole(accessible,role)             G_STMT_START { \
+                                                                          GtkAccessible *__a = 
GTK_ACCESSIBLE (accessible); \
+                                                                          GtkAccessibleRole __r = (role); \
+                                                                          if (gtk_test_accessible_has_role 
(__a, __r)) ; else \
+                                                                            
gtk_test_accessible_assertion_message_cmprole (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
+                                                                                                             
              #accessible " == " #role, \
+                                                                                                             
              __a, __r); \
+                                                                        } G_STMT_END
+#define gtk_test_accessible_assert_cmpproperty(accessible,property)     G_STMT_START { \
+                                                                          GtkAccessible *__a = 
GTK_ACCESSIBLE (accessible); \
+                                                                          GtkAccessibleProperty __p = 
(property); \
+                                                                          if 
(gtk_test_accessible_has_property (__a, __p)) ; else \
+                                                                            
gtk_test_accessible_assertion_message_cmpproperty (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
+                                                                                                             
                  #accessible " == " #property, \
+                                                                                                             
                  __a, __p); \
+                                                                        } G_STMT_END
+
+GDK_AVAILABLE_IN_ALL
+gboolean        gtk_test_accessible_has_role            (GtkAccessible         *accessible,
+                                                         GtkAccessibleRole      role);
+GDK_AVAILABLE_IN_ALL
+gboolean        gtk_test_accessible_has_property        (GtkAccessible         *accessible,
+                                                         GtkAccessibleProperty  property);
+
+GDK_AVAILABLE_IN_ALL
+void    gtk_test_accessible_assertion_message_cmprole           (const char        *domain,
+                                                                 const char        *file,
+                                                                 int                line,
+                                                                 const char        *func,
+                                                                 const char        *expr,
+                                                                 GtkAccessible     *accessible,
+                                                                 GtkAccessibleRole  role) G_GNUC_NORETURN;
+GDK_AVAILABLE_IN_ALL
+void    gtk_test_accessible_assertion_message_cmpproperty       (const char            *domain,
+                                                                 const char            *file,
+                                                                 int                    line,
+                                                                 const char            *func,
+                                                                 const char            *expr,
+                                                                 GtkAccessible         *accessible,
+                                                                 GtkAccessibleProperty  property) 
G_GNUC_NORETURN;
+
+
+G_END_DECLS
diff --git a/gtk/gtktestatcontextprivate.h b/gtk/gtktestatcontextprivate.h
index 2b5cc108e3..edafb76c4c 100644
--- a/gtk/gtktestatcontextprivate.h
+++ b/gtk/gtktestatcontextprivate.h
@@ -20,6 +20,7 @@
 
 #pragma once
 
+#include "gtktestatcontext.h"
 #include "gtkatcontextprivate.h"
 
 G_BEGIN_DECLS
@@ -32,16 +33,4 @@ GtkATContext *
 gtk_test_at_context_new (GtkAccessibleRole  accessible_role,
                          GtkAccessible     *accessible);
 
-void
-gtk_test_at_context_assert_role (GtkTestATContext  *self,
-                                 GtkAccessibleRole  role);
-
-void
-gtk_test_at_context_assert_state_added (GtkTestATContext   *self,
-                                        GtkAccessibleState  state);
-
-void
-gtk_test_at_context_assert_state_removed (GtkTestATContext   *self,
-                                          GtkAccessibleState  state);
-
 G_END_DECLS
diff --git a/gtk/meson.build b/gtk/meson.build
index 3dabe6c7a3..1f471bf09c 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -138,7 +138,6 @@ gtk_private_sources = files([
   'gtkstyleanimation.c',
   'gtkstylecascade.c',
   'gtkstyleproperty.c',
-  'gtktestatcontext.c',
   'gtktextbtree.c',
   'gtktexthistory.c',
   'gtktextviewchild.c',
@@ -386,6 +385,7 @@ gtk_public_sources = files([
   'gtkstylecontext.c',
   'gtkstyleprovider.c',
   'gtkswitch.c',
+  'gtktestatcontext.c',
   'gtktestutils.c',
   'gtktext.c',
   'gtktextattributes.c',
@@ -656,6 +656,7 @@ gtk_public_headers = files([
   'gtkstylecontext.h',
   'gtkstyleprovider.h',
   'gtkswitch.h',
+  'gtktestatcontext.h',
   'gtktestutils.h',
   'gtktext.h',
   'gtktextbuffer.h',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]