Add unit test covering ax_enum_util and fix issues found.

TBR=tsepez@chromium.org

Change-Id: I9ae1d2d051ab5a045c3987b781907f684050a3bf
Reviewed-on: https://chromium-review.googlesource.com/c/1460490
Commit-Queue: Dominic Mazzoni <dmazzoni@chromium.org>
Reviewed-by: Akihiro Ota <akihiroota@chromium.org>
Cr-Commit-Position: refs/heads/master@{#631484}
diff --git a/content/test/data/accessibility/aria/dpub-roles-expected-blink.txt b/content/test/data/accessibility/aria/dpub-roles-expected-blink.txt
index fe29d8c..0791432 100644
--- a/content/test/data/accessibility/aria/dpub-roles-expected-blink.txt
+++ b/content/test/data/accessibility/aria/dpub-roles-expected-blink.txt
@@ -1,40 +1,40 @@
 rootWebArea
-++docAbstractRole name='doc-abstract'
-++docAcknowledgmentsRole name='doc-acknowledgments'
-++docAfterwordRole name='doc-afterword'
-++docAppendixRole name='doc-appendix'
-++docBackLinkRole name='doc-backlink'
-++docBiblioEntryRole name='doc-biblioentry'
-++docBibliographyRole name='doc-bibliography'
-++docBiblioRefRole name='doc-biblioref'
-++docChapterRole name='doc-chapter'
-++docColophonRole name='doc-colophon'
-++docConclusionRole name='doc-conclusion'
-++docCoverRole name='doc-cover'
-++docCreditRole name='doc-credit'
-++docCreditsRole name='doc-credits'
-++docDedicationRole name='doc-dedication'
-++docEndnoteRole name='doc-endnote'
-++docEndnotesRole name='doc-endnotes'
-++docEpigraphRole name='doc-epigraph'
-++docEpilogueRole name='doc-epilogue'
-++docErrataRole name='doc-errata'
-++docExampleRole name='doc-example'
-++docFootnoteRole name='doc-footnote'
-++docForewordRole name='doc-foreword'
-++docGlossaryRole name='doc-glossary'
-++docGlossrefRole name='doc-glossref'
-++docIndexRole name='doc-index'
-++docIntroductionRole name='doc-introduction'
-++docNoteRefRole name='doc-noteref'
-++docNoticeRole name='doc-notice'
-++docPageBreakRole name='doc-pagebreak'
-++docPageListRole name='doc-pagelist'
-++docPartRole name='doc-part'
-++docPrefaceRole name='doc-preface'
-++docPrologueRole name='doc-prologue'
-++docPullquoteRole name='doc-pullquote'
-++docQnaRole name='doc-qna'
-++docSubtitleRole name='doc-subtitle'
-++docTipRole name='doc-tip'
-++docTocRole name='doc-toc'
+++docAbstract name='doc-abstract'
+++docAcknowledgments name='doc-acknowledgments'
+++docAfterword name='doc-afterword'
+++docAppendix name='doc-appendix'
+++docBackLink name='doc-backlink'
+++docBiblioEntry name='doc-biblioentry'
+++docBibliography name='doc-bibliography'
+++docBiblioRef name='doc-biblioref'
+++docChapter name='doc-chapter'
+++docColophon name='doc-colophon'
+++docConclusion name='doc-conclusion'
+++docCover name='doc-cover'
+++docCredit name='doc-credit'
+++docCredits name='doc-credits'
+++docDedication name='doc-dedication'
+++docEndnote name='doc-endnote'
+++docEndnotes name='doc-endnotes'
+++docEpigraph name='doc-epigraph'
+++docEpilogue name='doc-epilogue'
+++docErrata name='doc-errata'
+++docExample name='doc-example'
+++docFootnote name='doc-footnote'
+++docForeword name='doc-foreword'
+++docGlossary name='doc-glossary'
+++docGlossref name='doc-glossref'
+++docIndex name='doc-index'
+++docIntroduction name='doc-introduction'
+++docNoteRef name='doc-noteref'
+++docNotice name='doc-notice'
+++docPageBreak name='doc-pagebreak'
+++docPageList name='doc-pagelist'
+++docPart name='doc-part'
+++docPreface name='doc-preface'
+++docPrologue name='doc-prologue'
+++docPullquote name='doc-pullquote'
+++docQna name='doc-qna'
+++docSubtitle name='doc-subtitle'
+++docTip name='doc-tip'
+++docToc name='doc-toc'
\ No newline at end of file
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn
index f09dce57..42d30b4 100644
--- a/ui/accessibility/BUILD.gn
+++ b/ui/accessibility/BUILD.gn
@@ -204,6 +204,7 @@
 test("accessibility_unittests") {
   testonly = true
   sources = [
+    "ax_enum_util_unittest.cc",
     "ax_event_generator_unittest.cc",
     "ax_generated_tree_unittest.cc",
     "ax_language_info_unittest.cc",
diff --git a/ui/accessibility/ax_enum_util.cc b/ui/accessibility/ax_enum_util.cc
index 8852fe1..c9f6a89 100644
--- a/ui/accessibility/ax_enum_util.cc
+++ b/ui/accessibility/ax_enum_util.cc
@@ -152,6 +152,8 @@
     return ax::mojom::Event::kExpandedChanged;
   if (0 == strcmp(event, "focus"))
     return ax::mojom::Event::kFocus;
+  if (0 == strcmp(event, "focusContext"))
+    return ax::mojom::Event::kFocusContext;
   if (0 == strcmp(event, "hide"))
     return ax::mojom::Event::kHide;
   if (0 == strcmp(event, "hitTestResult"))
@@ -222,6 +224,8 @@
     return ax::mojom::Event::kSelectionRemove;
   if (0 == strcmp(event, "show"))
     return ax::mojom::Event::kShow;
+  if (0 == strcmp(event, "stateChanged"))
+    return ax::mojom::Event::kStateChanged;
   if (0 == strcmp(event, "textChanged"))
     return ax::mojom::Event::kTextChanged;
   if (0 == strcmp(event, "textSelectionChanged"))
@@ -316,83 +320,83 @@
     case ax::mojom::Role::kDisclosureTriangle:
       return "disclosureTriangle";
     case ax::mojom::Role::kDocAbstract:
-      return "docAbstractRole";
+      return "docAbstract";
     case ax::mojom::Role::kDocAcknowledgments:
-      return "docAcknowledgmentsRole";
+      return "docAcknowledgments";
     case ax::mojom::Role::kDocAfterword:
-      return "docAfterwordRole";
+      return "docAfterword";
     case ax::mojom::Role::kDocAppendix:
-      return "docAppendixRole";
+      return "docAppendix";
     case ax::mojom::Role::kDocBackLink:
-      return "docBackLinkRole";
+      return "docBackLink";
     case ax::mojom::Role::kDocBiblioEntry:
-      return "docBiblioEntryRole";
+      return "docBiblioEntry";
     case ax::mojom::Role::kDocBibliography:
-      return "docBibliographyRole";
+      return "docBibliography";
     case ax::mojom::Role::kDocBiblioRef:
-      return "docBiblioRefRole";
+      return "docBiblioRef";
     case ax::mojom::Role::kDocChapter:
-      return "docChapterRole";
+      return "docChapter";
     case ax::mojom::Role::kDocColophon:
-      return "docColophonRole";
+      return "docColophon";
     case ax::mojom::Role::kDocConclusion:
-      return "docConclusionRole";
+      return "docConclusion";
     case ax::mojom::Role::kDocCover:
-      return "docCoverRole";
+      return "docCover";
     case ax::mojom::Role::kDocCredit:
-      return "docCreditRole";
+      return "docCredit";
     case ax::mojom::Role::kDocCredits:
-      return "docCreditsRole";
+      return "docCredits";
     case ax::mojom::Role::kDocDedication:
-      return "docDedicationRole";
+      return "docDedication";
     case ax::mojom::Role::kDocEndnote:
-      return "docEndnoteRole";
+      return "docEndnote";
     case ax::mojom::Role::kDocEndnotes:
-      return "docEndnotesRole";
+      return "docEndnotes";
     case ax::mojom::Role::kDocEpigraph:
-      return "docEpigraphRole";
+      return "docEpigraph";
     case ax::mojom::Role::kDocEpilogue:
-      return "docEpilogueRole";
+      return "docEpilogue";
     case ax::mojom::Role::kDocErrata:
-      return "docErrataRole";
+      return "docErrata";
     case ax::mojom::Role::kDocExample:
-      return "docExampleRole";
+      return "docExample";
     case ax::mojom::Role::kDocFootnote:
-      return "docFootnoteRole";
+      return "docFootnote";
     case ax::mojom::Role::kDocForeword:
-      return "docForewordRole";
+      return "docForeword";
     case ax::mojom::Role::kDocGlossary:
-      return "docGlossaryRole";
+      return "docGlossary";
     case ax::mojom::Role::kDocGlossRef:
-      return "docGlossrefRole";
+      return "docGlossref";
     case ax::mojom::Role::kDocIndex:
-      return "docIndexRole";
+      return "docIndex";
     case ax::mojom::Role::kDocIntroduction:
-      return "docIntroductionRole";
+      return "docIntroduction";
     case ax::mojom::Role::kDocNoteRef:
-      return "docNoteRefRole";
+      return "docNoteRef";
     case ax::mojom::Role::kDocNotice:
-      return "docNoticeRole";
+      return "docNotice";
     case ax::mojom::Role::kDocPageBreak:
-      return "docPageBreakRole";
+      return "docPageBreak";
     case ax::mojom::Role::kDocPageList:
-      return "docPageListRole";
+      return "docPageList";
     case ax::mojom::Role::kDocPart:
-      return "docPartRole";
+      return "docPart";
     case ax::mojom::Role::kDocPreface:
-      return "docPrefaceRole";
+      return "docPreface";
     case ax::mojom::Role::kDocPrologue:
-      return "docPrologueRole";
+      return "docPrologue";
     case ax::mojom::Role::kDocPullquote:
-      return "docPullquoteRole";
+      return "docPullquote";
     case ax::mojom::Role::kDocQna:
-      return "docQnaRole";
+      return "docQna";
     case ax::mojom::Role::kDocSubtitle:
-      return "docSubtitleRole";
+      return "docSubtitle";
     case ax::mojom::Role::kDocTip:
-      return "docTipRole";
+      return "docTip";
     case ax::mojom::Role::kDocToc:
-      return "docTocRole";
+      return "docToc";
     case ax::mojom::Role::kDocument:
       return "document";
     case ax::mojom::Role::kEmbeddedObject:
@@ -673,6 +677,84 @@
     return ax::mojom::Role::kDirectory;
   if (0 == strcmp(role, "disclosureTriangle"))
     return ax::mojom::Role::kDisclosureTriangle;
+  if (0 == strcmp(role, "docAbstract"))
+    return ax::mojom::Role::kDocAbstract;
+  if (0 == strcmp(role, "docAcknowledgments"))
+    return ax::mojom::Role::kDocAcknowledgments;
+  if (0 == strcmp(role, "docAfterword"))
+    return ax::mojom::Role::kDocAfterword;
+  if (0 == strcmp(role, "docAppendix"))
+    return ax::mojom::Role::kDocAppendix;
+  if (0 == strcmp(role, "docBackLink"))
+    return ax::mojom::Role::kDocBackLink;
+  if (0 == strcmp(role, "docBiblioEntry"))
+    return ax::mojom::Role::kDocBiblioEntry;
+  if (0 == strcmp(role, "docBibliography"))
+    return ax::mojom::Role::kDocBibliography;
+  if (0 == strcmp(role, "docBiblioRef"))
+    return ax::mojom::Role::kDocBiblioRef;
+  if (0 == strcmp(role, "docChapter"))
+    return ax::mojom::Role::kDocChapter;
+  if (0 == strcmp(role, "docColophon"))
+    return ax::mojom::Role::kDocColophon;
+  if (0 == strcmp(role, "docConclusion"))
+    return ax::mojom::Role::kDocConclusion;
+  if (0 == strcmp(role, "docCover"))
+    return ax::mojom::Role::kDocCover;
+  if (0 == strcmp(role, "docCredit"))
+    return ax::mojom::Role::kDocCredit;
+  if (0 == strcmp(role, "docCredits"))
+    return ax::mojom::Role::kDocCredits;
+  if (0 == strcmp(role, "docDedication"))
+    return ax::mojom::Role::kDocDedication;
+  if (0 == strcmp(role, "docEndnote"))
+    return ax::mojom::Role::kDocEndnote;
+  if (0 == strcmp(role, "docEndnotes"))
+    return ax::mojom::Role::kDocEndnotes;
+  if (0 == strcmp(role, "docEpigraph"))
+    return ax::mojom::Role::kDocEpigraph;
+  if (0 == strcmp(role, "docEpilogue"))
+    return ax::mojom::Role::kDocEpilogue;
+  if (0 == strcmp(role, "docErrata"))
+    return ax::mojom::Role::kDocErrata;
+  if (0 == strcmp(role, "docExample"))
+    return ax::mojom::Role::kDocExample;
+  if (0 == strcmp(role, "docFootnote"))
+    return ax::mojom::Role::kDocFootnote;
+  if (0 == strcmp(role, "docForeword"))
+    return ax::mojom::Role::kDocForeword;
+  if (0 == strcmp(role, "docGlossary"))
+    return ax::mojom::Role::kDocGlossary;
+  if (0 == strcmp(role, "docGlossref"))
+    return ax::mojom::Role::kDocGlossRef;
+  if (0 == strcmp(role, "docIndex"))
+    return ax::mojom::Role::kDocIndex;
+  if (0 == strcmp(role, "docIntroduction"))
+    return ax::mojom::Role::kDocIntroduction;
+  if (0 == strcmp(role, "docNoteRef"))
+    return ax::mojom::Role::kDocNoteRef;
+  if (0 == strcmp(role, "docNotice"))
+    return ax::mojom::Role::kDocNotice;
+  if (0 == strcmp(role, "docPageBreak"))
+    return ax::mojom::Role::kDocPageBreak;
+  if (0 == strcmp(role, "docPageList"))
+    return ax::mojom::Role::kDocPageList;
+  if (0 == strcmp(role, "docPart"))
+    return ax::mojom::Role::kDocPart;
+  if (0 == strcmp(role, "docPreface"))
+    return ax::mojom::Role::kDocPreface;
+  if (0 == strcmp(role, "docPrologue"))
+    return ax::mojom::Role::kDocPrologue;
+  if (0 == strcmp(role, "docPullquote"))
+    return ax::mojom::Role::kDocPullquote;
+  if (0 == strcmp(role, "docQna"))
+    return ax::mojom::Role::kDocQna;
+  if (0 == strcmp(role, "docSubtitle"))
+    return ax::mojom::Role::kDocSubtitle;
+  if (0 == strcmp(role, "docTip"))
+    return ax::mojom::Role::kDocTip;
+  if (0 == strcmp(role, "docToc"))
+    return ax::mojom::Role::kDocToc;
   if (0 == strcmp(role, "document"))
     return ax::mojom::Role::kDocument;
   if (0 == strcmp(role, "embeddedObject"))
@@ -689,6 +771,12 @@
     return ax::mojom::Role::kForm;
   if (0 == strcmp(role, "genericContainer"))
     return ax::mojom::Role::kGenericContainer;
+  if (0 == strcmp(role, "graphicsDocument"))
+    return ax::mojom::Role::kGraphicsDocument;
+  if (0 == strcmp(role, "graphicsObject"))
+    return ax::mojom::Role::kGraphicsObject;
+  if (0 == strcmp(role, "graphicsSymbol"))
+    return ax::mojom::Role::kGraphicsSymbol;
   if (0 == strcmp(role, "grid"))
     return ax::mojom::Role::kGrid;
   if (0 == strcmp(role, "group"))
@@ -709,6 +797,8 @@
     return ax::mojom::Role::kInlineTextBox;
   if (0 == strcmp(role, "inputTime"))
     return ax::mojom::Role::kInputTime;
+  if (0 == strcmp(role, "keyboard"))
+    return ax::mojom::Role::kKeyboard;
   if (0 == strcmp(role, "labelText"))
     return ax::mojom::Role::kLabelText;
   if (0 == strcmp(role, "layoutTable"))
@@ -729,6 +819,8 @@
     return ax::mojom::Role::kListBoxOption;
   if (0 == strcmp(role, "listBox"))
     return ax::mojom::Role::kListBox;
+  if (0 == strcmp(role, "listGrid"))
+    return ax::mojom::Role::kListGrid;
   if (0 == strcmp(role, "listItem"))
     return ax::mojom::Role::kListItem;
   if (0 == strcmp(role, "listMarker"))
@@ -797,6 +889,8 @@
     return ax::mojom::Role::kSvgRoot;
   if (0 == strcmp(role, "scrollBar"))
     return ax::mojom::Role::kScrollBar;
+  if (0 == strcmp(role, "scrollView"))
+    return ax::mojom::Role::kScrollView;
   if (0 == strcmp(role, "search"))
     return ax::mojom::Role::kSearch;
   if (0 == strcmp(role, "searchBox"))
@@ -1027,6 +1121,8 @@
     return ax::mojom::Action::kFocus;
   if (0 == strcmp(action, "getImageData"))
     return ax::mojom::Action::kGetImageData;
+  if (0 == strcmp(action, "getTextLocation"))
+    return ax::mojom::Action::kGetTextLocation;
   if (0 == strcmp(action, "hitTest"))
     return ax::mojom::Action::kHitTest;
   if (0 == strcmp(action, "increment"))
@@ -1898,11 +1994,25 @@
       return "underline";
     case ax::mojom::TextStyle::kLineThrough:
       return "lineThrough";
+    case ax::mojom::TextStyle::kNone:
+      return "none";
   }
 
   return "";
 }
 
+ax::mojom::TextStyle ParseTextStyle(const char* text_style) {
+  if (0 == strcmp(text_style, "bold"))
+    return ax::mojom::TextStyle::kBold;
+  if (0 == strcmp(text_style, "italic"))
+    return ax::mojom::TextStyle::kItalic;
+  if (0 == strcmp(text_style, "underline"))
+    return ax::mojom::TextStyle::kUnderline;
+  if (0 == strcmp(text_style, "lineThrough"))
+    return ax::mojom::TextStyle::kLineThrough;
+  return ax::mojom::TextStyle::kNone;
+}
+
 const char* ToString(ax::mojom::AriaCurrentState aria_current_state) {
   switch (aria_current_state) {
     case ax::mojom::AriaCurrentState::kNone:
diff --git a/ui/accessibility/ax_enum_util_unittest.cc b/ui/accessibility/ax_enum_util_unittest.cc
new file mode 100644
index 0000000..754886e
--- /dev/null
+++ b/ui/accessibility/ax_enum_util_unittest.cc
@@ -0,0 +1,198 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/ax_enum_util.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/ax_node_data.h"
+
+namespace ui {
+
+// Templatized function that tests that for a mojom enum
+// such as ax::mojom::Role, ax::mojom::Event, etc. we can
+// call ToString() on the enum to get a string, and then
+// ParseEnumName() on the string to get back the original
+// value. Also tests what happens when we call ToString
+// or ParseEnumName on a bogus value.
+template <typename T>
+void TestEnumStringConversion(T(ParseFunction)(const char*)) {
+  // Check every valid enum value.
+  for (int i = static_cast<int>(T::kMinValue);
+       i <= static_cast<int>(T::kMaxValue); ++i) {
+    T src = static_cast<T>(i);
+    std::string str = ToString(src);
+    auto dst = ParseFunction(str.c_str());
+    EXPECT_EQ(src, dst);
+  }
+
+  // Parse a bogus string.
+  EXPECT_EQ(T::kNone, ParseFunction("bogus"));
+
+  // Convert a bogus value to a string.
+  EXPECT_STREQ("", ToString(static_cast<T>(999999)));
+}
+
+// Templatized function that tries calling a setter on AXNodeData
+// such as AddIntAttribute, AddFloatAttribute - with each possible
+// enum value.
+//
+// This variant is for cases where the value type is an object.
+template <typename T, typename U>
+void TestAXNodeDataSetter(void (AXNodeData::*Setter)(T, const U&),
+                          const U& value) {
+  AXNodeData node_data;
+  for (int i = static_cast<int>(T::kMinValue) + 1;
+       i <= static_cast<int>(T::kMaxValue); ++i) {
+    T attr = static_cast<T>(i);
+    ((node_data).*(Setter))(attr, value);
+  }
+  EXPECT_TRUE(!node_data.ToString().empty());
+}
+
+// Same as TextAXNodeData, above, but This variant is for
+// cases where the value type is POD.
+template <typename T, typename U>
+void TestAXNodeDataSetter(void (AXNodeData::*Setter)(T, U), U value) {
+  AXNodeData node_data;
+  for (int i = static_cast<int>(T::kMinValue) + 1;
+       i <= static_cast<int>(T::kMaxValue); ++i) {
+    T attr = static_cast<T>(i);
+    ((node_data).*(Setter))(attr, value);
+  }
+  EXPECT_TRUE(!node_data.ToString().empty());
+}
+
+TEST(AXEnumUtilTest, Event) {
+  TestEnumStringConversion<ax::mojom::Event>(ParseEvent);
+}
+
+TEST(AXEnumUtilTest, Role) {
+  TestEnumStringConversion<ax::mojom::Role>(ParseRole);
+}
+
+TEST(AXEnumUtilTest, State) {
+  TestEnumStringConversion<ax::mojom::State>(ParseState);
+}
+
+TEST(AXEnumUtilTest, Action) {
+  TestEnumStringConversion<ax::mojom::Action>(ParseAction);
+}
+
+TEST(AXEnumUtilTest, ActionFlags) {
+  TestEnumStringConversion<ax::mojom::ActionFlags>(ParseActionFlags);
+}
+
+TEST(AXEnumUtilTest, DefaultActionVerb) {
+  TestEnumStringConversion<ax::mojom::DefaultActionVerb>(
+      ParseDefaultActionVerb);
+}
+
+TEST(AXEnumUtilTest, Mutation) {
+  TestEnumStringConversion<ax::mojom::Mutation>(ParseMutation);
+}
+
+TEST(AXEnumUtilTest, StringAttribute) {
+  TestEnumStringConversion<ax::mojom::StringAttribute>(ParseStringAttribute);
+  TestAXNodeDataSetter<ax::mojom::StringAttribute>(
+      &AXNodeData::AddStringAttribute, std::string());
+}
+
+TEST(AXEnumUtilTest, IntAttribute) {
+  TestEnumStringConversion<ax::mojom::IntAttribute>(ParseIntAttribute);
+  TestAXNodeDataSetter<ax::mojom::IntAttribute>(&AXNodeData::AddIntAttribute,
+                                                0);
+}
+
+TEST(AXEnumUtilTest, FloatAttribute) {
+  TestEnumStringConversion<ax::mojom::FloatAttribute>(ParseFloatAttribute);
+  TestAXNodeDataSetter<ax::mojom::FloatAttribute>(
+      &AXNodeData::AddFloatAttribute, 0.0f);
+}
+
+TEST(AXEnumUtilTest, BoolAttribute) {
+  TestEnumStringConversion<ax::mojom::BoolAttribute>(ParseBoolAttribute);
+  TestAXNodeDataSetter<ax::mojom::BoolAttribute>(&AXNodeData::AddBoolAttribute,
+                                                 false);
+}
+
+TEST(AXEnumUtilTest, IntListAttribute) {
+  TestEnumStringConversion<ax::mojom::IntListAttribute>(ParseIntListAttribute);
+  TestAXNodeDataSetter<ax::mojom::IntListAttribute>(
+      &AXNodeData::AddIntListAttribute, std::vector<int32_t>());
+}
+
+TEST(AXEnumUtilTest, StringListAttribute) {
+  TestEnumStringConversion<ax::mojom::StringListAttribute>(
+      ParseStringListAttribute);
+  TestAXNodeDataSetter<ax::mojom::StringListAttribute>(
+      &AXNodeData::AddStringListAttribute, std::vector<std::string>());
+}
+
+// TODO(dmazzoni) this should be an enum of flags, not an
+// enum of every possible bitfield value.
+TEST(AXEnumUtilTest, DISABLED_MarkerType) {
+  TestEnumStringConversion<ax::mojom::MarkerType>(ParseMarkerType);
+}
+
+TEST(AXEnumUtilTest, TextDirection) {
+  TestEnumStringConversion<ax::mojom::TextDirection>(ParseTextDirection);
+}
+
+TEST(AXEnumUtilTest, TextPosition) {
+  TestEnumStringConversion<ax::mojom::TextPosition>(ParseTextPosition);
+}
+
+TEST(AXEnumUtilTest, TextStyle) {
+  TestEnumStringConversion<ax::mojom::TextStyle>(ParseTextStyle);
+}
+
+TEST(AXEnumUtilTest, AriaCurrentState) {
+  TestEnumStringConversion<ax::mojom::AriaCurrentState>(ParseAriaCurrentState);
+}
+
+TEST(AXEnumUtilTest, HasPopup) {
+  TestEnumStringConversion<ax::mojom::HasPopup>(ParseHasPopup);
+}
+
+TEST(AXEnumUtilTest, InvalidState) {
+  TestEnumStringConversion<ax::mojom::InvalidState>(ParseInvalidState);
+}
+
+TEST(AXEnumUtilTest, Restriction) {
+  TestEnumStringConversion<ax::mojom::Restriction>(ParseRestriction);
+}
+
+TEST(AXEnumUtilTest, CheckedState) {
+  TestEnumStringConversion<ax::mojom::CheckedState>(ParseCheckedState);
+}
+
+TEST(AXEnumUtilTest, SortDirection) {
+  TestEnumStringConversion<ax::mojom::SortDirection>(ParseSortDirection);
+}
+
+TEST(AXEnumUtilTest, NameFrom) {
+  TestEnumStringConversion<ax::mojom::NameFrom>(ParseNameFrom);
+}
+
+TEST(AXEnumUtilTest, DescriptionFrom) {
+  TestEnumStringConversion<ax::mojom::DescriptionFrom>(ParseDescriptionFrom);
+}
+
+TEST(AXEnumUtilTest, EventFrom) {
+  TestEnumStringConversion<ax::mojom::EventFrom>(ParseEventFrom);
+}
+
+TEST(AXEnumUtilTest, Gesture) {
+  TestEnumStringConversion<ax::mojom::Gesture>(ParseGesture);
+}
+
+TEST(AXEnumUtilTest, TextAffinity) {
+  TestEnumStringConversion<ax::mojom::TextAffinity>(ParseTextAffinity);
+}
+
+TEST(AXEnumUtilTest, TreeOrder) {
+  TestEnumStringConversion<ax::mojom::TreeOrder>(ParseTreeOrder);
+}
+
+}  // namespace ui
diff --git a/ui/accessibility/ax_enums.mojom b/ui/accessibility/ax_enums.mojom
index 8f492b1..f8515bb 100644
--- a/ui/accessibility/ax_enums.mojom
+++ b/ui/accessibility/ax_enums.mojom
@@ -752,6 +752,7 @@
   kItalic,
   kUnderline,
   kLineThrough,
+  kNone,
 };
 
 enum AriaCurrentState {
@@ -774,7 +775,7 @@
   kTree,
   kGrid,
   kDialog,
-  kLast = kDialog,
+  kNone = kFalse
 };
 
 enum InvalidState {
@@ -892,4 +893,3 @@
   kUnknown,  // The Tree ID is unknown.
   kToken,    // Every other tree ID must have a valid unguessable token.
 };
-