Bug 1276972 - adding value and attributes caching tests. r=eeejay
authorYura Zenevich <yzenevich@mozilla.com>
Mon, 06 Jun 2016 10:29:24 -0400
changeset 300905 b107bbf2a067c19ff1b77dc29cc43929194e8240
parent 300904 dbadac2844a9b2df9e2ae1bfb64e442cb15c4e41
child 300906 643e79a2d47ac9ace4dfa78578832d1e76e3bda1
push id78130
push useryura.zenevich@gmail.com
push dateTue, 07 Jun 2016 18:29:08 +0000
treeherdermozilla-inbound@b107bbf2a067 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerseeejay
bugs1276972
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1276972 - adding value and attributes caching tests. r=eeejay MozReview-Commit-ID: BOXh17Ql1dW
accessible/tests/browser/.eslintrc
accessible/tests/browser/browser.ini
accessible/tests/browser/browser_caching_attributes.js
accessible/tests/browser/browser_caching_value.js
accessible/tests/browser/events.js
accessible/tests/mochitest/common.js
--- a/accessible/tests/browser/.eslintrc
+++ b/accessible/tests/browser/.eslintrc
@@ -6,20 +6,23 @@
   "globals": {
     // Content scripts have global 'content' object
     "content": true,
 
     // Defined in accessible/tests/mochitest/ common.js, name.js, states.js
     "prettyName": true,
     "statesToString": true,
     "eventTypeToString": true,
+    "testAttrs": true,
+    "testAbsentAttrs": true,
     "testName": true,
     "testDescr": true,
     "testStates": true,
     "testRelation": true,
+    "testValue": true,
     "testAccessibleTree": true,
     "isAccessible": true,
     "getAccessibleDOMNodeID": true,
 
     // Defined for all accessibility browser tests.
     "addAccessibleTask": true,
     "BrowserTestUtils": true,
     "ContentTask": true,
--- a/accessible/tests/browser/browser.ini
+++ b/accessible/tests/browser/browser.ini
@@ -9,21 +9,24 @@ support-files =
   doc_treeupdate_removal.xhtml
   doc_treeupdate_visibility.html
   doc_treeupdate_whitespace.html
   !/accessible/tests/mochitest/*.js
   !/accessible/tests/mochitest/letters.gif
   !/accessible/tests/mochitest/moz.png
 
 # Caching tests
+[browser_caching_attributes.js]
 [browser_caching_description.js]
 [browser_caching_name.js]
 skip-if = e10s
 [browser_caching_relations.js]
 [browser_caching_states.js]
+[browser_caching_value.js]
+skip-if = e10s # Bug 1276721: QueryInterface is not working with proxies.
 
 # Events tests
 [browser_events_caretmove.js]
 [browser_events_hide.js]
 [browser_events_show.js]
 [browser_events_statechange.js]
 [browser_events_textchange.js]
 
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/browser_caching_attributes.js
@@ -0,0 +1,117 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+'use strict';
+
+/* global EVENT_FOCUS */
+
+loadScripts({ name: 'attributes.js', dir: MOCHITESTS_DIR });
+
+/**
+ * Default textbox accessible attributes.
+ */
+const defaultAttributes = {
+  'margin-top': '0px',
+  'margin-right': '0px',
+  'margin-bottom': '0px',
+  'margin-left': '0px',
+  'text-align': 'start',
+  'text-indent': '0px',
+  'id': 'textbox',
+  'tag': 'input',
+  'display': 'inline'
+};
+
+/**
+ * Test data has the format of:
+ * {
+ *   desc        {String}       description for better logging
+ *   expected    {Object}       expected attributes for given accessibles
+ *   unexpected  {Object}       unexpected attributes for given accessibles
+ *
+ *   action      {?Function*}   an optional action that yields a change in
+ *                              attributes
+ *   attrs       {?Array}       an optional list of attributes to update
+ *   waitFor     {?Number}      an optional event to wait for
+ * }
+ */
+const attributesTests = [{
+  desc: 'Initiall accessible attributes',
+  expected: defaultAttributes,
+  unexpected: {
+    'line-number': '1',
+    'explicit-name': 'true',
+    'container-live': 'polite',
+    'live': 'polite'
+  }
+}, {
+  desc: '@line-number attribute is present when textbox is focused',
+  action: function*(browser) {
+    yield invokeFocus(browser, 'textbox');
+  },
+  waitFor: EVENT_FOCUS,
+  expected: Object.assign({}, defaultAttributes, { 'line-number': '1' }),
+  unexpected: {
+    'explicit-name': 'true',
+    'container-live': 'polite',
+    'live': 'polite'
+  }
+}, {
+  desc: '@aria-live sets container-live and live attributes',
+  attrs: [{
+    attr: 'aria-live',
+    value: 'polite'
+  }],
+  expected: Object.assign({}, defaultAttributes, {
+    'line-number': '1',
+    'container-live': 'polite',
+    'live': 'polite'
+  }),
+  unexpected: {
+    'explicit-name': 'true'
+  }
+}, {
+  desc: '@title attribute sets explicit-name attribute to true',
+  attrs: [{
+    attr: 'title',
+    value: 'textbox'
+  }],
+  expected: Object.assign({}, defaultAttributes, {
+    'line-number': '1',
+    'explicit-name': 'true',
+    'container-live': 'polite',
+    'live': 'polite'
+  }),
+  unexpected: {}
+}];
+
+/**
+ * Test caching of accessible object attributes
+ */
+addAccessibleTask(`
+  <input id="textbox" value="hello">`,
+  function* (browser, accDoc) {
+    let textbox = findAccessibleChildByID(accDoc, 'textbox');
+    for (let { desc, action, attrs, expected, waitFor, unexpected } of attributesTests) {
+      info(desc);
+      let onUpdate;
+
+      if (waitFor) {
+        onUpdate = waitForEvent(waitFor, 'textbox');
+      }
+
+      if (action) {
+        yield action(browser);
+      } else if (attrs) {
+        for (let { attr, value } of attrs) {
+          yield invokeSetAttribute(browser, 'textbox', attr, value);
+        }
+      }
+
+      yield onUpdate;
+      testAttrs(textbox, expected);
+      testAbsentAttrs(textbox, unexpected);
+    }
+  }
+);
new file mode 100644
--- /dev/null
+++ b/accessible/tests/browser/browser_caching_value.js
@@ -0,0 +1,155 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+'use strict';
+
+/* global nsIAccessibleValue, EVENT_VALUE_CHANGE, EVENT_TEXT_VALUE_CHANGE */
+
+loadScripts({ name: 'value.js', dir: MOCHITESTS_DIR });
+
+/**
+ * Test data has the format of:
+ * {
+ *   desc      {String}       description for better logging
+ *   id        {String}       given accessible DOMNode ID
+ *   expected  {String}       expected value for a given accessible
+ *   action    {?Function*}   an optional action that yields a value change
+ *   attrs     {?Array}       an optional list of attributes to update
+ *   waitFor   {?Number}      an optional value change event to wait for
+ * }
+ */
+const valueTests = [{
+  desc: 'Initially value is set to 1st element of select',
+  id: 'select',
+  expected: '1st'
+}, {
+  desc: 'Value should update to 3rd when 3 is pressed',
+  id: 'select',
+  action: function*(browser) {
+    yield invokeFocus(browser, 'select');
+    yield BrowserTestUtils.synthesizeKey('3', {}, browser);
+  },
+  waitFor: EVENT_TEXT_VALUE_CHANGE,
+  expected: '3rd'
+}, {
+  desc: 'Initially value is set to @aria-valuenow for slider',
+  id: 'slider',
+  expected: ['5', 5, 0, 7, 0]
+}, {
+  desc: 'Value should change when @aria-valuenow is updated',
+  id: 'slider',
+  attrs: [{
+    attr: 'aria-valuenow',
+    value: '6'
+  }],
+  waitFor: EVENT_VALUE_CHANGE,
+  expected: ['6', 6, 0, 7, 0]
+}, {
+  desc: 'Value should change when @aria-valuetext is set',
+  id: 'slider',
+  attrs: [{
+    attr: 'aria-valuetext',
+    value: 'plain'
+  }],
+  waitFor: EVENT_TEXT_VALUE_CHANGE,
+  expected: ['plain', 6, 0, 7, 0]
+}, {
+  desc: 'Value should change when @aria-valuetext is updated',
+  id: 'slider',
+  attrs: [{
+    attr: 'aria-valuetext',
+    value: 'hey!'
+  }],
+  waitFor: EVENT_TEXT_VALUE_CHANGE,
+  expected: ['hey!', 6, 0, 7, 0]
+}, {
+  desc: 'Value should change to @aria-valuetext when @aria-valuenow is removed',
+  id: 'slider',
+  attrs: [{
+    attr: 'aria-valuenow'
+  }],
+  expected: ['hey!', 0, 0, 7, 0]
+}, {
+  desc: 'Initially value is not set for combobox',
+  id: 'combobox',
+  expected: ''
+}, {
+  desc: 'Value should change when @value attribute is updated',
+  id: 'combobox',
+  attrs: [{
+    attr: 'value',
+    value: 'hello'
+  }],
+  waitFor: EVENT_TEXT_VALUE_CHANGE,
+  expected: 'hello'
+}, {
+  desc: 'Initially value corresponds to @value attribute for progress',
+  id: 'progress',
+  expected: '22%'
+}, {
+  desc: 'Value should change when @value attribute is updated',
+  id: 'progress',
+  attrs: [{
+    attr: 'value',
+    value: '50'
+  }],
+  waitFor: EVENT_VALUE_CHANGE,
+  expected: '50%'
+}, {
+  desc: 'Initially value corresponds to @value attribute for range',
+  id: 'range',
+  expected: '6'
+}, {
+  desc: 'Value should change when slider is moved',
+  id: 'range',
+  action: function*(browser) {
+    yield invokeFocus(browser, 'range');
+    yield BrowserTestUtils.synthesizeKey('VK_LEFT', {}, browser);
+  },
+  waitFor: EVENT_VALUE_CHANGE,
+  expected: '5'
+}];
+
+/**
+ * Test caching of accessible object values
+ */
+addAccessibleTask(`
+  <div id="slider" role="slider" aria-valuenow="5"
+       aria-valuemin="0" aria-valuemax="7">slider</div>
+  <select id="select">
+    <option>1st</option>
+    <option>2nd</option>
+    <option>3rd</option>
+  </select>
+  <input id="combobox" role="combobox" aria-autocomplete="inline">
+  <progress id="progress" value="22" max="100"></progress>
+  <input type="range" id="range" min="0" max="10" value="6">`,
+  function* (browser, accDoc) {
+    for (let { desc, id, action, attrs, expected, waitFor } of valueTests) {
+      info(desc);
+      let acc = findAccessibleChildByID(accDoc, id);
+      let onUpdate;
+
+      if (waitFor) {
+        onUpdate = waitForEvent(waitFor, id);
+      }
+
+      if (action) {
+        yield action(browser);
+      } else if (attrs) {
+        for (let { attr, value } of attrs) {
+          yield invokeSetAttribute(browser, id, attr, value);
+        }
+      }
+
+      yield onUpdate;
+      if (Array.isArray(expected)) {
+        acc.QueryInterface(nsIAccessibleValue);
+        testValue(acc, ...expected);
+      } else {
+        is(acc.value, expected, `Correct value for ${prettyName(acc)}`);
+      }
+    }
+  }
+);
--- a/accessible/tests/browser/events.js
+++ b/accessible/tests/browser/events.js
@@ -5,28 +5,32 @@
 'use strict';
 
 /* global nsIAccessibleEvent, nsIAccessibleDocument,
           nsIAccessibleStateChangeEvent, nsIAccessibleTextChangeEvent */
 
 /* exported EVENT_REORDER, EVENT_SHOW, EVENT_TEXT_INSERTED, EVENT_TEXT_REMOVED,
             EVENT_DOCUMENT_LOAD_COMPLETE, EVENT_HIDE, EVENT_TEXT_CARET_MOVED,
             EVENT_DESCRIPTION_CHANGE, EVENT_NAME_CHANGE, EVENT_STATE_CHANGE,
+            EVENT_VALUE_CHANGE, EVENT_TEXT_VALUE_CHANGE, EVENT_FOCUS,
             waitForEvent, waitForMultipleEvents */
 
 const EVENT_DOCUMENT_LOAD_COMPLETE = nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_COMPLETE;
 const EVENT_HIDE = nsIAccessibleEvent.EVENT_HIDE;
 const EVENT_REORDER = nsIAccessibleEvent.EVENT_REORDER;
 const EVENT_SHOW = nsIAccessibleEvent.EVENT_SHOW;
 const EVENT_STATE_CHANGE = nsIAccessibleEvent.EVENT_STATE_CHANGE;
 const EVENT_TEXT_CARET_MOVED = nsIAccessibleEvent.EVENT_TEXT_CARET_MOVED;
 const EVENT_TEXT_INSERTED = nsIAccessibleEvent.EVENT_TEXT_INSERTED;
 const EVENT_TEXT_REMOVED = nsIAccessibleEvent.EVENT_TEXT_REMOVED;
 const EVENT_DESCRIPTION_CHANGE = nsIAccessibleEvent.EVENT_DESCRIPTION_CHANGE;
 const EVENT_NAME_CHANGE = nsIAccessibleEvent.EVENT_NAME_CHANGE;
+const EVENT_VALUE_CHANGE = nsIAccessibleEvent.EVENT_VALUE_CHANGE;
+const EVENT_TEXT_VALUE_CHANGE = nsIAccessibleEvent.EVENT_TEXT_VALUE_CHANGE;
+const EVENT_FOCUS = nsIAccessibleEvent.EVENT_FOCUS;
 
 /**
  * Describe an event in string format.
  * @param  {nsIAccessibleEvent}  event  event to strigify
  */
 function eventToString(event) {
   let type = eventTypeToString(event.eventType);
   let info = `Event type: ${type}`;
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -286,16 +286,19 @@ function getAccessible(aAccOrElmOrID, aI
 
   if (!aInterfaces)
     return acc;
 
   if (!(aInterfaces instanceof Array))
     aInterfaces = [ aInterfaces ];
 
   for (var index = 0; index < aInterfaces.length; index++) {
+    if (acc instanceof aInterfaces[index]) {
+      continue;
+    }
     try {
       acc.QueryInterface(aInterfaces[index]);
     } catch (e) {
       if (!(aDoNotFailIf & DONOTFAIL_IF_NO_INTERFACE))
         ok(false, "Can't query " + aInterfaces[index] + " for " + aAccOrElmOrID);
 
       return null;
     }