diff --git a/test/integration/virtual-rules/area-alt.js b/test/integration/virtual-rules/area-alt.js
new file mode 100644
index 0000000000..ad5841aa5a
--- /dev/null
+++ b/test/integration/virtual-rules/area-alt.js
@@ -0,0 +1,152 @@
+describe('area-alt', function() {
+ it('should pass for aria-label', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'map'
+ });
+ var child = new axe.SerialVirtualNode({
+ nodeName: 'area',
+ attributes: {
+ href: 'foobar',
+ 'aria-label': 'foobar'
+ }
+ });
+ child.parent = node;
+ node.children = [child];
+
+ var results = axe.runVirtualRule('area-alt', node);
+
+ assert.lengthOf(results.passes, 1);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should incomplete for aria-labelledby', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'map'
+ });
+ var child = new axe.SerialVirtualNode({
+ nodeName: 'area',
+ attributes: {
+ href: 'foobar',
+ 'aria-labelledby': 'foobar'
+ }
+ });
+ child.parent = node;
+ node.children = [child];
+
+ var results = axe.runVirtualRule('area-alt', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 1);
+ });
+
+ it('should pass for alt', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'map'
+ });
+ var child = new axe.SerialVirtualNode({
+ nodeName: 'area',
+ attributes: {
+ href: 'foobar',
+ alt: 'foobar'
+ }
+ });
+ child.parent = node;
+ node.children = [child];
+
+ var results = axe.runVirtualRule('area-alt', node);
+
+ assert.lengthOf(results.passes, 1);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should pass for title', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'map'
+ });
+ var child = new axe.SerialVirtualNode({
+ nodeName: 'area',
+ attributes: {
+ href: 'foobar',
+ title: 'foobar'
+ }
+ });
+ // children are required since titleText comes after subtree text
+ // in accessible name calculation
+ child.children = [];
+ child.parent = node;
+ node.children = [child];
+
+ var results = axe.runVirtualRule('area-alt', node);
+
+ assert.lengthOf(results.passes, 1);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should fail when alt contains only whitespace', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'map'
+ });
+ var child = new axe.SerialVirtualNode({
+ nodeName: 'area',
+ attributes: {
+ href: 'foobar',
+ alt: ' \t \n '
+ }
+ });
+ child.parent = node;
+ node.children = [child];
+
+ var results = axe.runVirtualRule('area-alt', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should fail when aria-label is empty', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'map'
+ });
+ var child = new axe.SerialVirtualNode({
+ nodeName: 'area',
+ attributes: {
+ href: 'foobar',
+ 'aria-label': ''
+ }
+ });
+ child.parent = node;
+ node.children = [child];
+
+ var results = axe.runVirtualRule('area-alt', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should fail when title is empty', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'map'
+ });
+ var child = new axe.SerialVirtualNode({
+ nodeName: 'area',
+ attributes: {
+ href: 'foobar',
+ title: ''
+ }
+ });
+ child.children = [];
+ child.parent = node;
+ node.children = [child];
+
+ var results = axe.runVirtualRule('area-alt', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+});
diff --git a/test/integration/virtual-rules/aria-input-field-name.js b/test/integration/virtual-rules/aria-input-field-name.js
new file mode 100644
index 0000000000..e5fd5f544f
--- /dev/null
+++ b/test/integration/virtual-rules/aria-input-field-name.js
@@ -0,0 +1,126 @@
+describe('aria-input-field-name', function() {
+ it('should pass for aria-label', function() {
+ var results = axe.runVirtualRule('aria-input-field-name', {
+ nodeName: 'div',
+ attributes: {
+ role: 'combobox',
+ 'aria-label': 'foobar'
+ }
+ });
+
+ assert.lengthOf(results.passes, 1);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should incomplete for aria-labelledby', function() {
+ var results = axe.runVirtualRule('aria-input-field-name', {
+ nodeName: 'div',
+ attributes: {
+ role: 'listbox',
+ 'aria-labelledby': 'foobar'
+ }
+ });
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 1);
+ });
+
+ it('should pass for title', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'div',
+ attributes: {
+ role: 'searchbox',
+ title: 'foobar'
+ }
+ });
+ // children are required since titleText comes after subtree text
+ // in accessible name calculation
+ node.children = [];
+
+ var results = axe.runVirtualRule('aria-input-field-name', node);
+
+ assert.lengthOf(results.passes, 1);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should fail when aria-label contains only whitespace', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'div',
+ attributes: {
+ role: 'spinbutton',
+ 'aria-label': ' \t \n '
+ }
+ });
+ node.children = [];
+
+ var results = axe.runVirtualRule('aria-input-field-name', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should fail when aria-label is empty', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'div',
+ attributes: {
+ role: 'textbox',
+ 'aria-label': ''
+ }
+ });
+ node.children = [];
+
+ var results = axe.runVirtualRule('aria-input-field-name', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should fail when title is empty', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'div',
+ attributes: {
+ role: 'combobox',
+ title: ''
+ }
+ });
+ node.children = [];
+
+ var results = axe.runVirtualRule('aria-input-field-name', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should incomplete if has explicit and implicit label', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'div',
+ attributes: {
+ role: 'listbox',
+ 'aria-label': 'name'
+ }
+ });
+ var parent = new axe.SerialVirtualNode({
+ nodeName: 'label'
+ });
+ var child = new axe.SerialVirtualNode({
+ nodeName: '#text',
+ nodeType: 3,
+ nodeValue: 'first name'
+ });
+ node.parent = parent;
+ node.children = [];
+ parent.children = [child, node];
+
+ var results = axe.runVirtualRule('aria-input-field-name', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 1);
+ });
+});
diff --git a/test/integration/virtual-rules/aria-toggle-field-name.js b/test/integration/virtual-rules/aria-toggle-field-name.js
new file mode 100644
index 0000000000..cd890a4fc7
--- /dev/null
+++ b/test/integration/virtual-rules/aria-toggle-field-name.js
@@ -0,0 +1,176 @@
+describe('aria-toggle-field-name', function() {
+ it('should pass for aria-label', function() {
+ var results = axe.runVirtualRule('aria-toggle-field-name', {
+ nodeName: 'div',
+ attributes: {
+ role: 'menuitemcheckbox',
+ 'aria-label': 'foobar'
+ }
+ });
+
+ assert.lengthOf(results.passes, 1);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should incomplete for aria-labelledby', function() {
+ var results = axe.runVirtualRule('aria-toggle-field-name', {
+ nodeName: 'div',
+ attributes: {
+ role: 'menuitemradio',
+ 'aria-labelledby': 'foobar'
+ }
+ });
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 1);
+ });
+
+ it('should pass for title', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'div',
+ attributes: {
+ role: 'checkbox',
+ title: 'foobar'
+ }
+ });
+ // children are required since titleText comes after subtree text
+ // in accessible name calculation
+ node.children = [];
+
+ var results = axe.runVirtualRule('aria-toggle-field-name', node);
+
+ assert.lengthOf(results.passes, 1);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should pass for visible text content', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'div',
+ attributes: {
+ role: 'radio'
+ }
+ });
+ var child = new axe.SerialVirtualNode({
+ nodeName: '#text',
+ nodeType: 3,
+ nodeValue: 'foobar'
+ });
+ node.children = [child];
+
+ var results = axe.runVirtualRule('aria-toggle-field-name', node);
+
+ assert.lengthOf(results.passes, 1);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should incomplete when children are missing', function() {
+ var results = axe.runVirtualRule('aria-toggle-field-name', {
+ nodeName: 'div',
+ attributes: {
+ role: 'switch'
+ }
+ });
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 1);
+ });
+
+ it('should fail children contain no visible text', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'div',
+ attributes: {
+ role: 'menuitemcheckbox'
+ }
+ });
+ node.children = [];
+
+ var results = axe.runVirtualRule('aria-toggle-field-name', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should fail when aria-label contains only whitespace', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'div',
+ attributes: {
+ role: 'menuitemcheckbox',
+ 'aria-label': ' \t \n '
+ }
+ });
+ node.children = [];
+
+ var results = axe.runVirtualRule('aria-toggle-field-name', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should fail when aria-label is empty', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'div',
+ attributes: {
+ role: 'menuitemcheckbox',
+ 'aria-label': ''
+ }
+ });
+ node.children = [];
+
+ var results = axe.runVirtualRule('aria-toggle-field-name', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should fail when title is empty', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'div',
+ attributes: {
+ role: 'menuitemcheckbox',
+ title: ''
+ }
+ });
+ node.children = [];
+
+ var results = axe.runVirtualRule('aria-toggle-field-name', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should incomplete if has explicit and implicit label', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'div',
+ attributes: {
+ role: 'menuitemcheckbox',
+ 'aria-label': 'name'
+ }
+ });
+ var parent = new axe.SerialVirtualNode({
+ nodeName: 'label'
+ });
+ var child = new axe.SerialVirtualNode({
+ nodeName: '#text',
+ nodeType: 3,
+ nodeValue: 'first name'
+ });
+ node.parent = parent;
+ node.children = [];
+ parent.children = [child, node];
+
+ var results = axe.runVirtualRule('aria-toggle-field-name', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 1);
+ });
+});
diff --git a/test/integration/virtual-rules/button-name.js b/test/integration/virtual-rules/button-name.js
new file mode 100644
index 0000000000..ede4f4b4d5
--- /dev/null
+++ b/test/integration/virtual-rules/button-name.js
@@ -0,0 +1,156 @@
+describe('button-name', function() {
+ it('should pass for aria-label', function() {
+ var results = axe.runVirtualRule('button-name', {
+ nodeName: 'button',
+ attributes: {
+ 'aria-label': 'foobar'
+ }
+ });
+
+ assert.lengthOf(results.passes, 1);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should incomplete for aria-labelledby', function() {
+ var results = axe.runVirtualRule('button-name', {
+ nodeName: 'button',
+ attributes: {
+ 'aria-labelledby': 'foobar'
+ }
+ });
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 1);
+ });
+
+ it('should pass for title', function() {
+ var results = axe.runVirtualRule('button-name', {
+ nodeName: 'button',
+ attributes: {
+ title: 'foobar'
+ }
+ });
+
+ assert.lengthOf(results.passes, 1);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should pass for role=presentation', function() {
+ var results = axe.runVirtualRule('button-name', {
+ nodeName: 'button',
+ attributes: {
+ role: 'presentation'
+ }
+ });
+
+ assert.lengthOf(results.passes, 1);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should pass for role=none', function() {
+ var results = axe.runVirtualRule('button-name', {
+ nodeName: 'button',
+ attributes: {
+ role: 'none'
+ }
+ });
+
+ assert.lengthOf(results.passes, 1);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should pass for visible text content', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'button'
+ });
+ var child = new axe.SerialVirtualNode({
+ nodeName: '#text',
+ nodeType: 3,
+ nodeValue: 'foobar'
+ });
+ node.children = [child];
+
+ var results = axe.runVirtualRule('button-name', node);
+
+ assert.lengthOf(results.passes, 1);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should incomplete when alt and children are missing', function() {
+ var results = axe.runVirtualRule('button-name', {
+ nodeName: 'button',
+ attributes: {}
+ });
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 0);
+ assert.lengthOf(results.incomplete, 1);
+ });
+
+ it('should fail children contain no visible text', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'button'
+ });
+ node.children = [];
+
+ var results = axe.runVirtualRule('button-name', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should fail when alt contains only whitespace', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'button',
+ attributes: {
+ alt: ' \t \n '
+ }
+ });
+ node.children = [];
+
+ var results = axe.runVirtualRule('button-name', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should fail when aria-label is empty', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'button',
+ attributes: {
+ alt: ''
+ }
+ });
+ node.children = [];
+
+ var results = axe.runVirtualRule('button-name', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+
+ it('should fail when title is empty', function() {
+ var node = new axe.SerialVirtualNode({
+ nodeName: 'button',
+ attributes: {
+ title: ''
+ }
+ });
+ node.children = [];
+
+ var results = axe.runVirtualRule('button-name', node);
+
+ assert.lengthOf(results.passes, 0);
+ assert.lengthOf(results.violations, 1);
+ assert.lengthOf(results.incomplete, 0);
+ });
+});
diff --git a/test/integration/virtual-rules/index.html b/test/integration/virtual-rules/index.html
index f4907ddc1b..b59f993a17 100644
--- a/test/integration/virtual-rules/index.html
+++ b/test/integration/virtual-rules/index.html
@@ -26,6 +26,11 @@
+
+
+
+
+