From 9f7f13256e30bebccbb1c5bd61d713953fb18aa1 Mon Sep 17 00:00:00 2001 From: Steven Lambert Date: Mon, 18 May 2020 15:07:03 -0600 Subject: [PATCH] feat(valid-lang): add option for which attributes to look at --- lib/checks/language/valid-lang-evaluate.js | 20 ++- lib/checks/language/valid-lang.json | 3 + test/checks/language/valid-lang.js | 166 +++++---------------- 3 files changed, 50 insertions(+), 139 deletions(-) diff --git a/lib/checks/language/valid-lang-evaluate.js b/lib/checks/language/valid-lang-evaluate.js index fd2c7a1fd6..3305d837a5 100644 --- a/lib/checks/language/valid-lang-evaluate.js +++ b/lib/checks/language/valid-lang-evaluate.js @@ -1,25 +1,23 @@ import { validLangs, getBaseLang } from '../../core/utils'; -function validLangEvaluate(node, options) { - var langs, invalid; +function validLangEvaluate(node, options, virtualNode) { + const langs = (options.value ? options.value : validLangs()).map(getBaseLang); - langs = (options.value ? options.value : validLangs()).map(getBaseLang); - - invalid = ['lang', 'xml:lang'].reduce(function(invalid, langAttr) { - var langVal = node.getAttribute(langAttr); + const invalid = []; + options.attributes.forEach(langAttr => { + const langVal = virtualNode.attr(langAttr); if (typeof langVal !== 'string') { - return invalid; + return; } - var baselangVal = getBaseLang(langVal); + const baselangVal = getBaseLang(langVal); // Edge sets lang to an empty string when xml:lang is set // so we need to ignore empty strings here if (baselangVal !== '' && langs.indexOf(baselangVal) === -1) { - invalid.push(langAttr + '="' + node.getAttribute(langAttr) + '"'); + invalid.push(langAttr + '="' + virtualNode.attr(langAttr) + '"'); } - return invalid; - }, []); + }); if (invalid.length) { this.data(invalid); diff --git a/lib/checks/language/valid-lang.json b/lib/checks/language/valid-lang.json index 9cf3cb24b6..5947e002fe 100644 --- a/lib/checks/language/valid-lang.json +++ b/lib/checks/language/valid-lang.json @@ -1,6 +1,9 @@ { "id": "valid-lang", "evaluate": "valid-lang-evaluate", + "options": { + "attributes": ["lang", "xml:lang"] + }, "metadata": { "impact": "serious", "messages": { diff --git a/test/checks/language/valid-lang.js b/test/checks/language/valid-lang.js index 705376920f..632b587212 100644 --- a/test/checks/language/valid-lang.js +++ b/test/checks/language/valid-lang.js @@ -2,159 +2,69 @@ describe('valid-lang', function() { 'use strict'; var fixture = document.getElementById('fixture'); - + var checkSetup = axe.testUtils.checkSetup; var checkContext = axe.testUtils.MockCheckContext(); + var validLangEvaluate = axe.testUtils.getCheckEvaluate('valid-lang'); afterEach(function() { fixture.innerHTML = ''; checkContext.reset(); }); - describe('lang', function() { - it('should return false if a lang attribute is present in options', function() { - var node = document.createElement('div'); - node.setAttribute('lang', 'woohoo'); - fixture.appendChild(node); - - assert.isFalse( - axe.testUtils - .getCheckEvaluate('valid-lang') - .call(checkContext, node, ['blah', 'blah', 'woohoo']) - ); + it('should return false if a lang attribute is present in options', function() { + var params = checkSetup('
', { + value: ['blah', 'blah', 'woohoo'] }); - it('should lowercase options and attribute first', function() { - var node = document.createElement('div'); - node.setAttribute('lang', 'wooHOo'); - fixture.appendChild(node); + assert.isFalse(validLangEvaluate.apply(checkContext, params)); + }); - assert.isFalse( - axe.testUtils - .getCheckEvaluate('valid-lang') - .call(checkContext, node, ['blah', 'blah', 'wOohoo']) - ); + it('should lowercase options and attribute first', function() { + var params = checkSetup('
', { + value: ['blah', 'blah', 'wOohoo'] }); - it('should return true if a lang attribute is not present in options', function() { - var node = document.createElement('div'); - node.setAttribute('lang', 'en-FOO'); - fixture.appendChild(node); - - assert.isTrue( - axe.testUtils - .getCheckEvaluate('valid-lang') - .call(checkContext, node, []) - ); - assert.deepEqual(checkContext._data, ['lang="en-FOO"']); - }); + assert.isFalse(validLangEvaluate.apply(checkContext, params)); + }); - it('should return false (and not throw) when given no options', function() { - var node = document.createElement('div'); - node.setAttribute('lang', 'en-US'); - fixture.appendChild(node); + it('should return true if a lang attribute is not present in options', function() { + var params = checkSetup('
'); - assert.isFalse( - axe.testUtils.getCheckEvaluate('valid-lang').call(checkContext, node) - ); - }); - - it('should return true if the language is badly formatted', function() { - var node = document.createElement('div'); - node.setAttribute('lang', 'en_US'); - fixture.appendChild(node); - - assert.isTrue( - axe.testUtils - .getCheckEvaluate('valid-lang') - .call(checkContext, node, ['en']) - ); - assert.deepEqual(checkContext._data, ['lang="en_US"']); - }); + assert.isTrue(validLangEvaluate.apply(checkContext, params)); + assert.deepEqual(checkContext._data, ['lang="FOO"']); + }); - it('should return false if it matches a substring proceeded by -', function() { - var node = document.createElement('div'); - node.setAttribute('lang', 'en-LOL'); - fixture.appendChild(node); + it('should return false (and not throw) when given no present in options', function() { + var params = checkSetup('
'); - assert.isFalse( - axe.testUtils - .getCheckEvaluate('valid-lang') - .call(checkContext, node, ['en']) - ); - }); + assert.isFalse(validLangEvaluate.apply(checkContext, params)); }); - describe('xml:lang', function() { - it('should return false if a lang attribute is present in options', function() { - var node = document.createElement('div'); - node.setAttribute('xml:lang', 'woohoo'); - fixture.appendChild(node); - - assert.isFalse( - axe.testUtils - .getCheckEvaluate('valid-lang') - .call(checkContext, node, ['blah', 'blah', 'woohoo']) - ); - }); + it('should return true if the language is badly formatted', function() { + var params = checkSetup('
'); - it('should lowercase options and attribute first', function() { - var node = document.createElement('div'); - node.setAttribute('xml:lang', 'wooHOo'); - fixture.appendChild(node); + assert.isTrue(validLangEvaluate.apply(checkContext, params)); + assert.deepEqual(checkContext._data, ['lang="en_US"']); + }); - assert.isFalse( - axe.testUtils - .getCheckEvaluate('valid-lang') - .call(checkContext, node, ['blah', 'blah', 'wOohoo']) - ); - }); + it('should return false if it matches a substring proceeded by -', function() { + var params = checkSetup('
'); - it('should return true if a lang attribute is not present in options', function() { - var node = document.createElement('div'); - node.setAttribute('xml:lang', 'en-FOO'); - fixture.appendChild(node); - - assert.isTrue( - axe.testUtils - .getCheckEvaluate('valid-lang') - .call(checkContext, node, []) - ); - assert.deepEqual(checkContext._data, ['xml:lang="en-FOO"']); - }); + assert.isFalse(validLangEvaluate.apply(checkContext, params)); + }); - it('should return false (and not throw) when given no options', function() { - var node = document.createElement('div'); - node.setAttribute('xml:lang', 'en-US'); - fixture.appendChild(node); + it('should work with xml:lang', function() { + var params = checkSetup('
'); - assert.isFalse( - axe.testUtils.getCheckEvaluate('valid-lang').call(checkContext, node) - ); - }); + assert.isFalse(validLangEvaluate.apply(checkContext, params)); + }); - it('should return true if the language is badly formatted', function() { - var node = document.createElement('div'); - node.setAttribute('xml:lang', 'en_US'); - fixture.appendChild(node); - - assert.isTrue( - axe.testUtils - .getCheckEvaluate('valid-lang') - .call(checkContext, node, ['en']) - ); - assert.deepEqual(checkContext._data, ['xml:lang="en_US"']); + it('should accept options.attributes', function() { + var params = checkSetup('
', { + attributes: ['custom-lang'] }); - it('should return false if it matches a substring proceeded by -', function() { - var node = document.createElement('div'); - node.setAttribute('xml:lang', 'en-LOL'); - fixture.appendChild(node); - - assert.isFalse( - axe.testUtils - .getCheckEvaluate('valid-lang') - .call(checkContext, node, ['en']) - ); - }); + assert.isTrue(validLangEvaluate.apply(checkContext, params)); + assert.deepEqual(checkContext._data, ['custom-lang="en_US"']); }); });