From e07aaea86bc9460a2d9f568637b4a77d33094ed6 Mon Sep 17 00:00:00 2001 From: Jey Nandakumar Date: Fri, 28 Feb 2020 09:23:50 +0000 Subject: [PATCH] =?UTF-8?q?fix(has-lang):=20fail=20check=20when=20`xml:lan?= =?UTF-8?q?g`=20is=20used=20in=20HTML=20docum=E2=80=A6=20(#2053)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/checks/language/has-lang.js | 15 +++++--- test/checks/language/has-lang.js | 8 +++- .../html-has-lang-fail-xml-lang.html | 33 +++++++++++++++++ .../html-has-lang-fail-xml-lang.js | 37 +++++++++++++++++++ .../html-has-lang/html-has-lang-pass-xhtml.js | 36 ++++++++++++++++++ .../html-has-lang-pass-xhtml.xhtml | 33 +++++++++++++++++ 6 files changed, 156 insertions(+), 6 deletions(-) create mode 100644 test/integration/full/html-has-lang/html-has-lang-fail-xml-lang.html create mode 100644 test/integration/full/html-has-lang/html-has-lang-fail-xml-lang.js create mode 100644 test/integration/full/html-has-lang/html-has-lang-pass-xhtml.js create mode 100644 test/integration/full/html-has-lang/html-has-lang-pass-xhtml.xhtml diff --git a/lib/checks/language/has-lang.js b/lib/checks/language/has-lang.js index cc6da92678..aba70aaf4f 100644 --- a/lib/checks/language/has-lang.js +++ b/lib/checks/language/has-lang.js @@ -1,5 +1,10 @@ -return !!( - node.getAttribute('lang') || - node.getAttribute('xml:lang') || - '' -).trim(); +const { isXHTML } = axe.utils; + +const langValue = (node.getAttribute(`lang`) || '').trim(); +const xmlLangValue = (node.getAttribute(`xml:lang`) || '').trim(); + +if (!langValue && !isXHTML(document)) { + return false; +} + +return !!(langValue || xmlLangValue); diff --git a/test/checks/language/has-lang.js b/test/checks/language/has-lang.js index cfef076052..a4e06cf1db 100644 --- a/test/checks/language/has-lang.js +++ b/test/checks/language/has-lang.js @@ -15,9 +15,15 @@ describe('has-lang', function() { assert.isTrue(checks['has-lang'].evaluate(node)); }); - it('should return true if xml:lang attribute is present', function() { + it('should return false if only `xml:lang` attribute is present', function() { fixture.innerHTML = '
'; + assert.isFalse(checks['has-lang'].evaluate(fixture.firstChild)); + }); + + it('should return true if both `lang` and `xml:lang` attribute is present', function() { + fixture.innerHTML = '
'; + assert.isTrue(checks['has-lang'].evaluate(fixture.firstChild)); }); diff --git a/test/integration/full/html-has-lang/html-has-lang-fail-xml-lang.html b/test/integration/full/html-has-lang/html-has-lang-fail-xml-lang.html new file mode 100644 index 0000000000..5207908988 --- /dev/null +++ b/test/integration/full/html-has-lang/html-has-lang-fail-xml-lang.html @@ -0,0 +1,33 @@ + + + + html-has-lang test + + + + + + + + + + +
+ + + + + diff --git a/test/integration/full/html-has-lang/html-has-lang-fail-xml-lang.js b/test/integration/full/html-has-lang/html-has-lang-fail-xml-lang.js new file mode 100644 index 0000000000..fe3ead2ef3 --- /dev/null +++ b/test/integration/full/html-has-lang/html-has-lang-fail-xml-lang.js @@ -0,0 +1,37 @@ +/** + * Note: + * This rule does not include `iframe` uses matches "window-is-top.js" + */ +describe('html-has-lang fail test', function() { + 'use strict'; + + var results; + before(function(done) { + axe.testUtils.awaitNestedLoad(function() { + axe.run( + { runOnly: { type: 'rule', values: ['html-has-lang'] } }, + function(err, r) { + assert.isNull(err); + results = r; + done(); + } + ); + }); + }); + + describe('violations', function() { + it('should find 1 violations', function() { + assert.lengthOf(results.violations, 1); + }); + + it('should find #fail1', function() { + assert.deepEqual(results.violations[0].nodes[0].target, ['#fail1']); + }); + }); + + describe('passes', function() { + it('should find 0 passes', function() { + assert.lengthOf(results.passes, 0); + }); + }); +}); diff --git a/test/integration/full/html-has-lang/html-has-lang-pass-xhtml.js b/test/integration/full/html-has-lang/html-has-lang-pass-xhtml.js new file mode 100644 index 0000000000..fba87e4778 --- /dev/null +++ b/test/integration/full/html-has-lang/html-has-lang-pass-xhtml.js @@ -0,0 +1,36 @@ +/** + * Note: + * This rule does not include `iframe` uses matches "window-is-top.js" + */ +describe('html-has-lang pass test', function() { + 'use strict'; + var results; + before(function(done) { + axe.testUtils.awaitNestedLoad(function() { + axe.run( + { runOnly: { type: 'rule', values: ['html-has-lang'] } }, + function(err, r) { + assert.isNull(err); + results = r; + done(); + } + ); + }); + }); + + describe('violations', function() { + it('should find 0 violations', function() { + assert.lengthOf(results.violations, 0); + }); + }); + + describe('passes', function() { + it('should find 1', function() { + assert.lengthOf(results.passes[0].nodes, 1); + }); + + it('should find #pass1', function() { + assert.deepEqual(results.passes[0].nodes[0].target, ['#pass1']); + }); + }); +}); diff --git a/test/integration/full/html-has-lang/html-has-lang-pass-xhtml.xhtml b/test/integration/full/html-has-lang/html-has-lang-pass-xhtml.xhtml new file mode 100644 index 0000000000..69a9ab273d --- /dev/null +++ b/test/integration/full/html-has-lang/html-has-lang-pass-xhtml.xhtml @@ -0,0 +1,33 @@ + + + + html-has-lang test + + + + + + + + + + +
+ + + + +