Home | History | Annotate | Download | only in accessibility
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <string>
      6 #include <vector>
      7 
      8 #include "base/strings/utf_string_conversions.h"
      9 #include "content/browser/renderer_host/render_view_host_impl.h"
     10 #include "content/public/browser/notification_service.h"
     11 #include "content/public/browser/notification_types.h"
     12 #include "content/public/browser/render_widget_host_view.h"
     13 #include "content/shell/shell.h"
     14 #include "content/test/accessibility_browser_test_utils.h"
     15 #include "content/test/content_browser_test.h"
     16 #include "content/test/content_browser_test_utils.h"
     17 
     18 #if defined(OS_WIN)
     19 #include <atlbase.h>
     20 #include <atlcom.h>
     21 #include "base/win/scoped_com_initializer.h"
     22 #include "ui/base/win/atl_module.h"
     23 #endif
     24 
     25 // TODO(dmazzoni): Disabled accessibility tests on Win64. crbug.com/179717
     26 #if defined(OS_WIN) && defined(ARCH_CPU_X86_64)
     27 #define MAYBE_TableSpan DISABLED_TableSpan
     28 #else
     29 #define MAYBE_TableSpan TableSpan
     30 #endif
     31 
     32 namespace content {
     33 
     34 class CrossPlatformAccessibilityBrowserTest : public ContentBrowserTest {
     35  public:
     36   CrossPlatformAccessibilityBrowserTest() {}
     37 
     38   // Tell the renderer to send an accessibility tree, then wait for the
     39   // notification that it's been received.
     40   const AccessibilityNodeDataTreeNode& GetAccessibilityNodeDataTree(
     41       AccessibilityMode accessibility_mode = AccessibilityModeComplete) {
     42     AccessibilityNotificationWaiter waiter(
     43         shell(), accessibility_mode, AccessibilityNotificationLayoutComplete);
     44     waiter.WaitForNotification();
     45     return waiter.GetAccessibilityNodeDataTree();
     46   }
     47 
     48   // Make sure each node in the tree has an unique id.
     49   void RecursiveAssertUniqueIds(
     50       const AccessibilityNodeDataTreeNode& node, base::hash_set<int>* ids) {
     51     ASSERT_TRUE(ids->find(node.id) == ids->end());
     52     ids->insert(node.id);
     53     for (size_t i = 0; i < node.children.size(); i++)
     54       RecursiveAssertUniqueIds(node.children[i], ids);
     55   }
     56 
     57   // ContentBrowserTest
     58   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE;
     59   virtual void TearDownInProcessBrowserTestFixture() OVERRIDE;
     60 
     61  protected:
     62   std::string GetAttr(const AccessibilityNodeData& node,
     63                       const AccessibilityNodeData::StringAttribute attr);
     64   int GetIntAttr(const AccessibilityNodeData& node,
     65                  const AccessibilityNodeData::IntAttribute attr);
     66   bool GetBoolAttr(const AccessibilityNodeData& node,
     67                    const AccessibilityNodeData::BoolAttribute attr);
     68 
     69  private:
     70 #if defined(OS_WIN)
     71   scoped_ptr<base::win::ScopedCOMInitializer> com_initializer_;
     72 #endif
     73 
     74   DISALLOW_COPY_AND_ASSIGN(CrossPlatformAccessibilityBrowserTest);
     75 };
     76 
     77 void CrossPlatformAccessibilityBrowserTest::SetUpInProcessBrowserTestFixture() {
     78 #if defined(OS_WIN)
     79   ui::win::CreateATLModuleIfNeeded();
     80   com_initializer_.reset(new base::win::ScopedCOMInitializer());
     81 #endif
     82 }
     83 
     84 void
     85 CrossPlatformAccessibilityBrowserTest::TearDownInProcessBrowserTestFixture() {
     86 #if defined(OS_WIN)
     87   com_initializer_.reset();
     88 #endif
     89 }
     90 
     91 // Convenience method to get the value of a particular AccessibilityNodeData
     92 // node attribute as a UTF-8 const char*.
     93 std::string CrossPlatformAccessibilityBrowserTest::GetAttr(
     94     const AccessibilityNodeData& node,
     95     const AccessibilityNodeData::StringAttribute attr) {
     96   std::map<AccessibilityNodeData::StringAttribute, string16>::const_iterator
     97       iter = node.string_attributes.find(attr);
     98   if (iter != node.string_attributes.end())
     99     return UTF16ToUTF8(iter->second);
    100   else
    101     return std::string();
    102 }
    103 
    104 // Convenience method to get the value of a particular AccessibilityNodeData
    105 // node integer attribute.
    106 int CrossPlatformAccessibilityBrowserTest::GetIntAttr(
    107     const AccessibilityNodeData& node,
    108     const AccessibilityNodeData::IntAttribute attr) {
    109   std::map<AccessibilityNodeData::IntAttribute, int32>::const_iterator iter =
    110       node.int_attributes.find(attr);
    111   if (iter != node.int_attributes.end())
    112     return iter->second;
    113   else
    114     return -1;
    115 }
    116 
    117 // Convenience method to get the value of a particular AccessibilityNodeData
    118 // node boolean attribute.
    119 bool CrossPlatformAccessibilityBrowserTest::GetBoolAttr(
    120     const AccessibilityNodeData& node,
    121     const AccessibilityNodeData::BoolAttribute attr) {
    122   std::map<AccessibilityNodeData::BoolAttribute, bool>::const_iterator iter =
    123       node.bool_attributes.find(attr);
    124   if (iter != node.bool_attributes.end())
    125     return iter->second;
    126   else
    127     return false;
    128 }
    129 
    130 // Marked flaky per http://crbug.com/101984
    131 IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
    132                        DISABLED_WebpageAccessibility) {
    133   // Create a data url and load it.
    134   const char url_str[] =
    135       "data:text/html,"
    136       "<!doctype html>"
    137       "<html><head><title>Accessibility Test</title></head>"
    138       "<body><input type='button' value='push' /><input type='checkbox' />"
    139       "</body></html>";
    140   GURL url(url_str);
    141   NavigateToURL(shell(), url);
    142   const AccessibilityNodeDataTreeNode& tree = GetAccessibilityNodeDataTree();
    143 
    144   // Check properties of the root element of the tree.
    145   EXPECT_STREQ(url_str,
    146                GetAttr(tree, AccessibilityNodeData::ATTR_DOC_URL).c_str());
    147   EXPECT_STREQ(
    148       "Accessibility Test",
    149       GetAttr(tree, AccessibilityNodeData::ATTR_DOC_TITLE).c_str());
    150   EXPECT_STREQ(
    151       "html", GetAttr(tree, AccessibilityNodeData::ATTR_DOC_DOCTYPE).c_str());
    152   EXPECT_STREQ(
    153       "text/html",
    154       GetAttr(tree, AccessibilityNodeData::ATTR_DOC_MIMETYPE).c_str());
    155   EXPECT_STREQ("Accessibility Test", UTF16ToUTF8(tree.name).c_str());
    156   EXPECT_EQ(AccessibilityNodeData::ROLE_ROOT_WEB_AREA, tree.role);
    157 
    158   // Check properites of the BODY element.
    159   ASSERT_EQ(1U, tree.children.size());
    160   const AccessibilityNodeDataTreeNode& body = tree.children[0];
    161   EXPECT_EQ(AccessibilityNodeData::ROLE_GROUP, body.role);
    162   EXPECT_STREQ("body",
    163                GetAttr(body, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
    164   EXPECT_STREQ("block",
    165                GetAttr(body, AccessibilityNodeData::ATTR_DISPLAY).c_str());
    166 
    167   // Check properties of the two children of the BODY element.
    168   ASSERT_EQ(2U, body.children.size());
    169 
    170   const AccessibilityNodeDataTreeNode& button = body.children[0];
    171   EXPECT_EQ(AccessibilityNodeData::ROLE_BUTTON, button.role);
    172   EXPECT_STREQ(
    173       "input", GetAttr(button, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
    174   EXPECT_STREQ("push", UTF16ToUTF8(button.name).c_str());
    175   EXPECT_STREQ(
    176       "inline-block",
    177       GetAttr(button, AccessibilityNodeData::ATTR_DISPLAY).c_str());
    178   ASSERT_EQ(2U, button.html_attributes.size());
    179   EXPECT_STREQ("type", UTF16ToUTF8(button.html_attributes[0].first).c_str());
    180   EXPECT_STREQ("button", UTF16ToUTF8(button.html_attributes[0].second).c_str());
    181   EXPECT_STREQ("value", UTF16ToUTF8(button.html_attributes[1].first).c_str());
    182   EXPECT_STREQ("push", UTF16ToUTF8(button.html_attributes[1].second).c_str());
    183 
    184   const AccessibilityNodeDataTreeNode& checkbox = body.children[1];
    185   EXPECT_EQ(AccessibilityNodeData::ROLE_CHECKBOX, checkbox.role);
    186   EXPECT_STREQ(
    187       "input", GetAttr(checkbox, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
    188   EXPECT_STREQ(
    189       "inline-block",
    190       GetAttr(checkbox, AccessibilityNodeData::ATTR_DISPLAY).c_str());
    191   ASSERT_EQ(1U, checkbox.html_attributes.size());
    192   EXPECT_STREQ(
    193       "type", UTF16ToUTF8(checkbox.html_attributes[0].first).c_str());
    194   EXPECT_STREQ(
    195     "checkbox", UTF16ToUTF8(checkbox.html_attributes[0].second).c_str());
    196 }
    197 
    198 IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
    199                        UnselectedEditableTextAccessibility) {
    200   // Create a data url and load it.
    201   const char url_str[] =
    202       "data:text/html,"
    203       "<!doctype html>"
    204       "<body>"
    205       "<input value=\"Hello, world.\"/>"
    206       "</body></html>";
    207   GURL url(url_str);
    208   NavigateToURL(shell(), url);
    209 
    210   const AccessibilityNodeDataTreeNode& tree = GetAccessibilityNodeDataTree();
    211   ASSERT_EQ(1U, tree.children.size());
    212   const AccessibilityNodeDataTreeNode& body = tree.children[0];
    213   ASSERT_EQ(1U, body.children.size());
    214   const AccessibilityNodeDataTreeNode& text = body.children[0];
    215   EXPECT_EQ(AccessibilityNodeData::ROLE_TEXT_FIELD, text.role);
    216   EXPECT_STREQ(
    217       "input", GetAttr(text, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
    218   EXPECT_EQ(0, GetIntAttr(text, AccessibilityNodeData::ATTR_TEXT_SEL_START));
    219   EXPECT_EQ(0, GetIntAttr(text, AccessibilityNodeData::ATTR_TEXT_SEL_END));
    220   EXPECT_STREQ("Hello, world.", UTF16ToUTF8(text.value).c_str());
    221 
    222   // TODO(dmazzoni): as soon as more accessibility code is cross-platform,
    223   // this code should test that the accessible info is dynamically updated
    224   // if the selection or value changes.
    225 }
    226 
    227 IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
    228                        SelectedEditableTextAccessibility) {
    229   // Create a data url and load it.
    230   const char url_str[] =
    231       "data:text/html,"
    232       "<!doctype html>"
    233       "<body onload=\"document.body.children[0].select();\">"
    234       "<input value=\"Hello, world.\"/>"
    235       "</body></html>";
    236   GURL url(url_str);
    237   NavigateToURL(shell(), url);
    238 
    239   const AccessibilityNodeDataTreeNode& tree = GetAccessibilityNodeDataTree();
    240   ASSERT_EQ(1U, tree.children.size());
    241   const AccessibilityNodeDataTreeNode& body = tree.children[0];
    242   ASSERT_EQ(1U, body.children.size());
    243   const AccessibilityNodeDataTreeNode& text = body.children[0];
    244   EXPECT_EQ(AccessibilityNodeData::ROLE_TEXT_FIELD, text.role);
    245   EXPECT_STREQ(
    246       "input", GetAttr(text, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
    247   EXPECT_EQ(0, GetIntAttr(text, AccessibilityNodeData::ATTR_TEXT_SEL_START));
    248   EXPECT_EQ(13, GetIntAttr(text, AccessibilityNodeData::ATTR_TEXT_SEL_END));
    249   EXPECT_STREQ("Hello, world.", UTF16ToUTF8(text.value).c_str());
    250 }
    251 
    252 IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
    253                        MultipleInheritanceAccessibility) {
    254   // In a WebKit accessibility render tree for a table, each cell is a
    255   // child of both a row and a column, so it appears to use multiple
    256   // inheritance. Make sure that the AccessibilityNodeDataObject tree only
    257   // keeps one copy of each cell, and uses an indirect child id for the
    258   // additional reference to it.
    259   const char url_str[] =
    260       "data:text/html,"
    261       "<!doctype html>"
    262       "<table border=1><tr><td>1</td><td>2</td></tr></table>";
    263   GURL url(url_str);
    264   NavigateToURL(shell(), url);
    265 
    266   const AccessibilityNodeDataTreeNode& tree = GetAccessibilityNodeDataTree();
    267   ASSERT_EQ(1U, tree.children.size());
    268   const AccessibilityNodeDataTreeNode& table = tree.children[0];
    269   EXPECT_EQ(AccessibilityNodeData::ROLE_TABLE, table.role);
    270   const AccessibilityNodeDataTreeNode& row = table.children[0];
    271   EXPECT_EQ(AccessibilityNodeData::ROLE_ROW, row.role);
    272   const AccessibilityNodeDataTreeNode& cell1 = row.children[0];
    273   EXPECT_EQ(AccessibilityNodeData::ROLE_CELL, cell1.role);
    274   const AccessibilityNodeDataTreeNode& cell2 = row.children[1];
    275   EXPECT_EQ(AccessibilityNodeData::ROLE_CELL, cell2.role);
    276   const AccessibilityNodeDataTreeNode& column1 = table.children[1];
    277   EXPECT_EQ(AccessibilityNodeData::ROLE_COLUMN, column1.role);
    278   EXPECT_EQ(0U, column1.children.size());
    279   EXPECT_EQ(1U, column1.indirect_child_ids.size());
    280   EXPECT_EQ(cell1.id, column1.indirect_child_ids[0]);
    281   const AccessibilityNodeDataTreeNode& column2 = table.children[2];
    282   EXPECT_EQ(AccessibilityNodeData::ROLE_COLUMN, column2.role);
    283   EXPECT_EQ(0U, column2.children.size());
    284   EXPECT_EQ(1U, column2.indirect_child_ids.size());
    285   EXPECT_EQ(cell2.id, column2.indirect_child_ids[0]);
    286 }
    287 
    288 IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
    289                        MultipleInheritanceAccessibility2) {
    290   // Here's another html snippet where WebKit puts the same node as a child
    291   // of two different parents. Instead of checking the exact output, just
    292   // make sure that no id is reused in the resulting tree.
    293   const char url_str[] =
    294       "data:text/html,"
    295       "<!doctype html>"
    296       "<script>\n"
    297       "  document.writeln('<q><section></section></q><q><li>');\n"
    298       "  setTimeout(function() {\n"
    299       "    document.close();\n"
    300       "  }, 1);\n"
    301       "</script>";
    302   GURL url(url_str);
    303   NavigateToURL(shell(), url);
    304 
    305   const AccessibilityNodeDataTreeNode& tree = GetAccessibilityNodeDataTree();
    306   base::hash_set<int> ids;
    307   RecursiveAssertUniqueIds(tree, &ids);
    308 }
    309 
    310 IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
    311                        IframeAccessibility) {
    312   // Create a data url and load it.
    313   const char url_str[] =
    314       "data:text/html,"
    315       "<!doctype html><html><body>"
    316       "<button>Button 1</button>"
    317       "<iframe src='data:text/html,"
    318       "<!doctype html><html><body><button>Button 2</button></body></html>"
    319       "'></iframe>"
    320       "<button>Button 3</button>"
    321       "</body></html>";
    322   GURL url(url_str);
    323   NavigateToURL(shell(), url);
    324 
    325   const AccessibilityNodeDataTreeNode& tree = GetAccessibilityNodeDataTree();
    326   ASSERT_EQ(1U, tree.children.size());
    327   const AccessibilityNodeDataTreeNode& body = tree.children[0];
    328   ASSERT_EQ(3U, body.children.size());
    329 
    330   const AccessibilityNodeDataTreeNode& button1 = body.children[0];
    331   EXPECT_EQ(AccessibilityNodeData::ROLE_BUTTON, button1.role);
    332   EXPECT_STREQ("Button 1", UTF16ToUTF8(button1.name).c_str());
    333 
    334   const AccessibilityNodeDataTreeNode& iframe = body.children[1];
    335   EXPECT_STREQ("iframe",
    336                GetAttr(iframe, AccessibilityNodeData::ATTR_HTML_TAG).c_str());
    337   ASSERT_EQ(1U, iframe.children.size());
    338 
    339   const AccessibilityNodeDataTreeNode& scroll_area = iframe.children[0];
    340   EXPECT_EQ(AccessibilityNodeData::ROLE_SCROLLAREA, scroll_area.role);
    341   ASSERT_EQ(1U, scroll_area.children.size());
    342 
    343   const AccessibilityNodeDataTreeNode& sub_document = scroll_area.children[0];
    344   EXPECT_EQ(AccessibilityNodeData::ROLE_WEB_AREA, sub_document.role);
    345   ASSERT_EQ(1U, sub_document.children.size());
    346 
    347   const AccessibilityNodeDataTreeNode& sub_body = sub_document.children[0];
    348   ASSERT_EQ(1U, sub_body.children.size());
    349 
    350   const AccessibilityNodeDataTreeNode& button2 = sub_body.children[0];
    351   EXPECT_EQ(AccessibilityNodeData::ROLE_BUTTON, button2.role);
    352   EXPECT_STREQ("Button 2", UTF16ToUTF8(button2.name).c_str());
    353 
    354   const AccessibilityNodeDataTreeNode& button3 = body.children[2];
    355   EXPECT_EQ(AccessibilityNodeData::ROLE_BUTTON, button3.role);
    356   EXPECT_STREQ("Button 3", UTF16ToUTF8(button3.name).c_str());
    357 }
    358 
    359 IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
    360                        DuplicateChildrenAccessibility) {
    361   // Here's another html snippet where WebKit has a parent node containing
    362   // two duplicate child nodes. Instead of checking the exact output, just
    363   // make sure that no id is reused in the resulting tree.
    364   const char url_str[] =
    365       "data:text/html,"
    366       "<!doctype html>"
    367       "<em><code ><h4 ></em>";
    368   GURL url(url_str);
    369   NavigateToURL(shell(), url);
    370 
    371   const AccessibilityNodeDataTreeNode& tree = GetAccessibilityNodeDataTree();
    372   base::hash_set<int> ids;
    373   RecursiveAssertUniqueIds(tree, &ids);
    374 }
    375 
    376 IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
    377                        MAYBE_TableSpan) {
    378   // +---+---+---+
    379   // |   1   | 2 |
    380   // +---+---+---+
    381   // | 3 |   4   |
    382   // +---+---+---+
    383 
    384   const char url_str[] =
    385       "data:text/html,"
    386       "<!doctype html>"
    387       "<table border=1>"
    388       " <tr>"
    389       "  <td colspan=2>1</td><td>2</td>"
    390       " </tr>"
    391       " <tr>"
    392       "  <td>3</td><td colspan=2>4</td>"
    393       " </tr>"
    394       "</table>";
    395   GURL url(url_str);
    396   NavigateToURL(shell(), url);
    397 
    398   const AccessibilityNodeDataTreeNode& tree = GetAccessibilityNodeDataTree();
    399   const AccessibilityNodeDataTreeNode& table = tree.children[0];
    400   EXPECT_EQ(AccessibilityNodeData::ROLE_TABLE, table.role);
    401   ASSERT_GE(table.children.size(), 5U);
    402   EXPECT_EQ(AccessibilityNodeData::ROLE_ROW, table.children[0].role);
    403   EXPECT_EQ(AccessibilityNodeData::ROLE_ROW, table.children[1].role);
    404   EXPECT_EQ(AccessibilityNodeData::ROLE_COLUMN, table.children[2].role);
    405   EXPECT_EQ(AccessibilityNodeData::ROLE_COLUMN, table.children[3].role);
    406   EXPECT_EQ(AccessibilityNodeData::ROLE_COLUMN, table.children[4].role);
    407   EXPECT_EQ(3,
    408             GetIntAttr(table, AccessibilityNodeData::ATTR_TABLE_COLUMN_COUNT));
    409   EXPECT_EQ(2, GetIntAttr(table, AccessibilityNodeData::ATTR_TABLE_ROW_COUNT));
    410 
    411   const AccessibilityNodeDataTreeNode& cell1 = table.children[0].children[0];
    412   const AccessibilityNodeDataTreeNode& cell2 = table.children[0].children[1];
    413   const AccessibilityNodeDataTreeNode& cell3 = table.children[1].children[0];
    414   const AccessibilityNodeDataTreeNode& cell4 = table.children[1].children[1];
    415 
    416   ASSERT_EQ(6U, table.cell_ids.size());
    417   EXPECT_EQ(cell1.id, table.cell_ids[0]);
    418   EXPECT_EQ(cell1.id, table.cell_ids[1]);
    419   EXPECT_EQ(cell2.id, table.cell_ids[2]);
    420   EXPECT_EQ(cell3.id, table.cell_ids[3]);
    421   EXPECT_EQ(cell4.id, table.cell_ids[4]);
    422   EXPECT_EQ(cell4.id, table.cell_ids[5]);
    423 
    424   EXPECT_EQ(0, GetIntAttr(cell1,
    425                           AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_INDEX));
    426   EXPECT_EQ(0, GetIntAttr(cell1,
    427                           AccessibilityNodeData::ATTR_TABLE_CELL_ROW_INDEX));
    428   EXPECT_EQ(2, GetIntAttr(cell1,
    429                           AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_SPAN));
    430   EXPECT_EQ(1, GetIntAttr(cell1,
    431                           AccessibilityNodeData::ATTR_TABLE_CELL_ROW_SPAN));
    432   EXPECT_EQ(2, GetIntAttr(cell2,
    433                           AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_INDEX));
    434   EXPECT_EQ(1, GetIntAttr(cell2,
    435                           AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_SPAN));
    436   EXPECT_EQ(0, GetIntAttr(cell3,
    437                           AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_INDEX));
    438   EXPECT_EQ(1, GetIntAttr(cell3,
    439                           AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_SPAN));
    440   EXPECT_EQ(1, GetIntAttr(cell4,
    441                           AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_INDEX));
    442   EXPECT_EQ(2, GetIntAttr(cell4,
    443                           AccessibilityNodeData::ATTR_TABLE_CELL_COLUMN_SPAN));
    444 }
    445 
    446 IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
    447                        WritableElement) {
    448   const char url_str[] =
    449       "data:text/html,"
    450       "<!doctype html>"
    451       "<div role='textbox' tabindex=0>"
    452       " Some text"
    453       "</div>";
    454   GURL url(url_str);
    455   NavigateToURL(shell(), url);
    456   const AccessibilityNodeDataTreeNode& tree = GetAccessibilityNodeDataTree();
    457 
    458   ASSERT_EQ(1U, tree.children.size());
    459   const AccessibilityNodeDataTreeNode& textbox = tree.children[0];
    460 
    461   EXPECT_EQ(
    462       true, GetBoolAttr(textbox, AccessibilityNodeData::ATTR_CAN_SET_VALUE));
    463 }
    464 
    465 }  // namespace content
    466