diff --git a/lib/checks/forms/autocomplete-valid.js b/lib/checks/forms/autocomplete-valid.js
index 3d6c5da16d..4b7617d7e7 100644
--- a/lib/checks/forms/autocomplete-valid.js
+++ b/lib/checks/forms/autocomplete-valid.js
@@ -1,102 +1,2 @@
-let {
- standaloneTerms = [],
- qualifiedTerms = [],
- qualifiers = [],
- locations = [],
- looseTyped = false
-} =
- options || {};
-
-qualifiers = qualifiers.concat(['home', 'work', 'mobile', 'fax', 'pager']);
-locations = locations.concat(['billing', 'shipping']);
-standaloneTerms = standaloneTerms.concat([
- 'name',
- 'honorific-prefix',
- 'given-name',
- 'additional-name',
- 'family-name',
- 'honorific-suffix',
- 'nickname',
- 'username',
- 'new-password',
- 'current-password',
- 'organization-title',
- 'organization',
- 'street-address',
- 'address-line1',
- 'address-line2',
- 'address-line3',
- 'address-level4',
- 'address-level3',
- 'address-level2',
- 'address-level1',
- 'country',
- 'country-name',
- 'postal-code',
- 'cc-name',
- 'cc-given-name',
- 'cc-additional-name',
- 'cc-family-name',
- 'cc-number',
- 'cc-exp',
- 'cc-exp-month',
- 'cc-exp-year',
- 'cc-csc',
- 'cc-type',
- 'transaction-currency',
- 'transaction-amount',
- 'language',
- 'bday',
- 'bday-day',
- 'bday-month',
- 'bday-year',
- 'sex',
- 'url',
- 'photo'
-]);
-
-qualifiedTerms = qualifiedTerms.concat([
- 'tel',
- 'tel-country-code',
- 'tel-national',
- 'tel-area-code',
- 'tel-local',
- 'tel-local-prefix',
- 'tel-local-suffix',
- 'tel-extension',
- 'email',
- 'impp'
-]);
-
-const autocomplete = node.getAttribute('autocomplete');
-const autocompleteTerms = autocomplete.split(/\s+/g).map(term => {
- return term.toLowerCase();
-});
-
-if (!looseTyped) {
- if (
- autocompleteTerms[0].length > 8 &&
- autocompleteTerms[0].substr(0, 8) === 'section-'
- ) {
- autocompleteTerms.shift();
- }
-
- if (locations.includes(autocompleteTerms[0])) {
- autocompleteTerms.shift();
- }
-
- if (qualifiers.includes(autocompleteTerms[0])) {
- autocompleteTerms.shift();
- // only quantifiers allowed at this point
- standaloneTerms = [];
- }
-
- if (autocompleteTerms.length !== 1) {
- return false;
- }
-}
-
-const purposeTerm = autocompleteTerms[autocompleteTerms.length - 1];
-return (
- standaloneTerms.includes(purposeTerm) || qualifiedTerms.includes(purposeTerm)
-);
+const autocomplete = node.getAttribute('autocomplete') || '';
+return axe.commons.text.isValidAutocomplete(autocomplete, options);
diff --git a/lib/commons/text/is-valid-autocomplete.js b/lib/commons/text/is-valid-autocomplete.js
new file mode 100644
index 0000000000..9811e095be
--- /dev/null
+++ b/lib/commons/text/is-valid-autocomplete.js
@@ -0,0 +1,118 @@
+/* global text */
+const autocomplete = {
+ stateTerms: ['on', 'off'],
+ standaloneTerms: [
+ 'name',
+ 'honorific-prefix',
+ 'given-name',
+ 'additional-name',
+ 'family-name',
+ 'honorific-suffix',
+ 'nickname',
+ 'username',
+ 'new-password',
+ 'current-password',
+ 'organization-title',
+ 'organization',
+ 'street-address',
+ 'address-line1',
+ 'address-line2',
+ 'address-line3',
+ 'address-level4',
+ 'address-level3',
+ 'address-level2',
+ 'address-level1',
+ 'country',
+ 'country-name',
+ 'postal-code',
+ 'cc-name',
+ 'cc-given-name',
+ 'cc-additional-name',
+ 'cc-family-name',
+ 'cc-number',
+ 'cc-exp',
+ 'cc-exp-month',
+ 'cc-exp-year',
+ 'cc-csc',
+ 'cc-type',
+ 'transaction-currency',
+ 'transaction-amount',
+ 'language',
+ 'bday',
+ 'bday-day',
+ 'bday-month',
+ 'bday-year',
+ 'sex',
+ 'url',
+ 'photo'
+ ],
+ qualifiers: ['home', 'work', 'mobile', 'fax', 'pager'],
+ qualifiedTerms: [
+ 'tel',
+ 'tel-country-code',
+ 'tel-national',
+ 'tel-area-code',
+ 'tel-local',
+ 'tel-local-prefix',
+ 'tel-local-suffix',
+ 'tel-extension',
+ 'email',
+ 'impp'
+ ],
+ locations: ['billing', 'shipping']
+};
+text.autocomplete = autocomplete;
+
+text.isValidAutocomplete = function isValidAutocomplete(
+ autocomplete,
+ {
+ looseTyped = false,
+ stateTerms = [],
+ locations = [],
+ qualifiers = [],
+ standaloneTerms = [],
+ qualifiedTerms = []
+ } = {}
+) {
+ /*eslint max-statements: ["error", 21] */
+ autocomplete = autocomplete.toLowerCase();
+ stateTerms = stateTerms.concat(text.autocomplete.stateTerms);
+ if (stateTerms.includes(autocomplete)) {
+ return true;
+ }
+
+ qualifiers = qualifiers.concat(text.autocomplete.qualifiers);
+ locations = locations.concat(text.autocomplete.locations);
+ standaloneTerms = standaloneTerms.concat(text.autocomplete.standaloneTerms);
+ qualifiedTerms = qualifiedTerms.concat(text.autocomplete.qualifiedTerms);
+
+ const autocompleteTerms = autocomplete.split(/\s+/g);
+ if (!looseTyped) {
+ if (
+ autocompleteTerms[0].length > 8 &&
+ autocompleteTerms[0].substr(0, 8) === 'section-'
+ ) {
+ autocompleteTerms.shift();
+ }
+
+ if (locations.includes(autocompleteTerms[0])) {
+ autocompleteTerms.shift();
+ }
+
+ if (qualifiers.includes(autocompleteTerms[0])) {
+ autocompleteTerms.shift();
+ // only quantifiers allowed at this point
+ standaloneTerms = [];
+ }
+
+ if (autocompleteTerms.length !== 1) {
+ return false;
+ }
+ }
+
+ const purposeTerm = autocompleteTerms[autocompleteTerms.length - 1];
+ return (
+ standaloneTerms.includes(purposeTerm) ||
+ qualifiedTerms.includes(purposeTerm)
+ );
+};
diff --git a/test/checks/forms/autocomplete-valid.js b/test/checks/forms/autocomplete-valid.js
index 1dbf0fa2fb..5f809f5e26 100644
--- a/test/checks/forms/autocomplete-valid.js
+++ b/test/checks/forms/autocomplete-valid.js
@@ -11,94 +11,57 @@ describe('autocomplete-valid', function() {
qualifiedTerms: ['qualified-term']
};
+ var _isValidAutocomplete;
beforeEach(function() {
axe._tree = undefined;
+ _isValidAutocomplete = axe.commons.text.isValidAutocomplete;
});
afterEach(function() {
+ axe.commons.text.isValidAutocomplete = _isValidAutocomplete;
fixture.innerHTML = '';
checkContext.reset();
});
- function autocompleteCheckParams(arg, opt) {
- return checkSetup(
- '',
- opt || options
- );
- }
-
- it('returns true the only term is a valid autocomplete term', function() {
- var params = autocompleteCheckParams('standalone-term');
- assert.isTrue(evaluate.apply(checkContext, params));
- });
-
- it('returns false the only term is an invalid autocomplete term', function() {
- var params = autocompleteCheckParams('bad-term');
- assert.isFalse(evaluate.apply(checkContext, params));
- });
-
- it('returns true if section-* is used as the first term', function() {
- var params = autocompleteCheckParams('section-foo standalone-term');
- assert.isTrue(evaluate.apply(checkContext, params));
- });
-
- it('returns true if `shipping` or `billing` is used as the first term', function() {
- var params1 = autocompleteCheckParams('shipping standalone-term');
- assert.isTrue(evaluate.apply(checkContext, params1));
-
- var params2 = autocompleteCheckParams('billing standalone-term');
- assert.isTrue(evaluate.apply(checkContext, params2));
+ it('passes autocomplete attribute to text.isValidAutocomplete', function() {
+ var params = checkSetup('');
+ var called = false;
+ axe.commons.text.isValidAutocomplete = function(arg1) {
+ assert.equal(arg1, 'foo');
+ called = true;
+ };
+ evaluate.apply(checkContext, params);
+ assert.isTrue(called);
});
- it('returns true if section-* is used before `shipping` or `billing`', function() {
- var params = autocompleteCheckParams(
- 'section-foo shipping standalone-term'
+ it('passes options to text.isValidAutocomplete', function() {
+ var options = { foo: 'bar' };
+ var params = checkSetup(
+ '',
+ options
);
- assert.isTrue(evaluate.apply(checkContext, params));
+ var called = false;
+ axe.commons.text.isValidAutocomplete = function(_, arg2) {
+ assert.equal(arg2, options);
+ called = true;
+ };
+ evaluate.apply(checkContext, params);
+ assert.isTrue(called);
});
- it('returns false if `shipping` or `billing` is used before section-*', function() {
- var params = autocompleteCheckParams(
- 'shipping section-foo standalone-term'
+ it('returns the outcome of text.isValidAutocomplete', function() {
+ var params1 = checkSetup(
+ '',
+ options
);
- assert.isFalse(evaluate.apply(checkContext, params));
- });
+ assert.isFalse(_isValidAutocomplete('badvalue'));
+ assert.isFalse(evaluate.apply(checkContext, params1));
- it('returns true if "home", "work", "mobile", "fax" or "pager" is used before aqualifier', function() {
- ['home', 'work', 'mobile', 'fax', 'pager'].forEach(function(qualifier) {
- var params = autocompleteCheckParams(qualifier + ' qualified-term');
- assert.isTrue(
- evaluate.apply(checkContext, params),
- 'failed for ' + qualifier
- );
- });
- });
-
- it('returns false if "home", "work", "mobile", "fax" or "pager" is used before an inappropriate term', function() {
- ['home', 'work', 'mobile', 'fax', 'pager'].forEach(function(qualifier) {
- var params = autocompleteCheckParams(qualifier + ' standalone-term');
- assert.isFalse(
- evaluate.apply(checkContext, params),
- 'failed for ' + qualifier
- );
- });
- });
-
- describe('options.strictMode:false', function() {
- it('returns true if the last term is a valid autocomplete term', function() {
- var params = autocompleteCheckParams('do not care! valid-term', {
- looseTyped: true,
- standaloneTerms: ['valid-term']
- });
- assert.isTrue(evaluate.apply(checkContext, params));
- });
-
- it('returns false if the last term is an invalid autocomplete term', function() {
- var params = autocompleteCheckParams('shipping invalid', {
- looseTyped: true,
- standaloneTerms: ['valid-term']
- });
- assert.isFalse(evaluate.apply(checkContext, params));
- });
+ var params2 = checkSetup(
+ '',
+ options
+ );
+ assert.isTrue(_isValidAutocomplete('email'));
+ assert.isTrue(evaluate.apply(checkContext, params2));
});
});
diff --git a/test/commons/text/is-valid-autocomplete.js b/test/commons/text/is-valid-autocomplete.js
new file mode 100644
index 0000000000..ca5d81d7bd
--- /dev/null
+++ b/test/commons/text/is-valid-autocomplete.js
@@ -0,0 +1,88 @@
+describe('text.isValidAutocomplete', function() {
+ 'use strict';
+
+ var isValidAutocomplete = axe.commons.text.isValidAutocomplete;
+ var options = {
+ standaloneTerms: ['standalone-term'],
+ qualifiedTerms: ['qualified-term']
+ };
+
+ it('returns true if autocomplete is `on` or `off', function() {
+ ['on', 'off'].forEach(function(state) {
+ assert.isTrue(isValidAutocomplete(state, options));
+ });
+ });
+
+ it('returns false if `on` or `off` is used with another term', function() {
+ ['on', 'off'].forEach(function(state) {
+ assert.isFalse(isValidAutocomplete('section-foo ' + state, options));
+ });
+ });
+
+ it('returns true the only term is a valid autocomplete term', function() {
+ assert.isTrue(isValidAutocomplete('standalone-term', options));
+ });
+
+ it('returns false the only term is an invalid autocomplete term', function() {
+ assert.isFalse(isValidAutocomplete('bad-term', options));
+ });
+
+ it('returns true if section-* is used as the first term', function() {
+ assert.isTrue(isValidAutocomplete('section-foo standalone-term', options));
+ });
+
+ it('returns true if `shipping` or `billing` is used as the first term', function() {
+ assert.isTrue(isValidAutocomplete('shipping standalone-term', options));
+ assert.isTrue(isValidAutocomplete('billing standalone-term', options));
+ });
+
+ it('returns true if section-* is used before `shipping` or `billing`', function() {
+ assert.isTrue(
+ isValidAutocomplete('section-foo shipping standalone-term', options)
+ );
+ });
+
+ it('returns false if `shipping` or `billing` is used before section-*', function() {
+ assert.isFalse(
+ isValidAutocomplete('shipping section-foo standalone-term', options)
+ );
+ });
+
+ it('returns true if "home", "work", "mobile", "fax" or "pager" is used before aqualifier', function() {
+ ['home', 'work', 'mobile', 'fax', 'pager'].forEach(function(qualifier) {
+ assert.isTrue(
+ isValidAutocomplete(qualifier + ' qualified-term', options),
+ 'failed for ' + qualifier
+ );
+ });
+ });
+
+ it('returns false if "home", "work", "mobile", "fax" or "pager" is used before an inappropriate term', function() {
+ ['home', 'work', 'mobile', 'fax', 'pager'].forEach(function(qualifier) {
+ assert.isFalse(
+ isValidAutocomplete(qualifier + ' standalone-term', options),
+ 'failed for ' + qualifier
+ );
+ });
+ });
+
+ describe('options.strictMode:false', function() {
+ it('returns true if the last term is a valid autocomplete term', function() {
+ assert.isTrue(
+ isValidAutocomplete('do not care! valid-term', {
+ looseTyped: true,
+ standaloneTerms: ['valid-term']
+ })
+ );
+ });
+
+ it('returns false if the last term is an invalid autocomplete term', function() {
+ assert.isFalse(
+ isValidAutocomplete('shipping invalid', {
+ looseTyped: true,
+ standaloneTerms: ['valid-term']
+ })
+ );
+ });
+ });
+});