diff --git a/lib/index.js b/lib/index.js index 58348722..ed26a05b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -79,20 +79,14 @@ var enumeratedAttributeValues = { draggable: ['true', 'false'] // defaults to 'auto' }; -function isBooleanAttribute(attrName, attrValue) { - var isSimpleBoolean = /^(?:allowfullscreen|async|autofocus|autoplay|checked|compact|controls|declare|default|defaultchecked|defaultmuted|defaultselected|defer|disabled|enabled|formnovalidate|hidden|indeterminate|inert|ismap|itemscope|loop|multiple|muted|nohref|noresize|noshade|novalidate|nowrap|open|pauseonexit|readonly|required|reversed|scoped|seamless|selected|sortable|spellcheck|truespeed|typemustmatch|visible)$/i.test( - attrName - ); - if (isSimpleBoolean) { - return true; - } +var matchSimpleAttribute = /^(?:allowfullscreen|async|autofocus|autoplay|checked|compact|controls|declare|default|defaultchecked|defaultmuted|defaultselected|defer|disabled|enabled|formnovalidate|hidden|indeterminate|inert|ismap|itemscope|loop|multiple|muted|nohref|noresize|noshade|novalidate|nowrap|open|pauseonexit|readonly|required|reversed|scoped|seamless|selected|sortable|spellcheck|truespeed|typemustmatch|visible)$/i; - var attrValueEnumeration = enumeratedAttributeValues[attrName.toLowerCase()]; - if (!attrValueEnumeration) { - return false; - } else { - return attrValueEnumeration.indexOf(attrValue.toLowerCase()) === -1; - } +function isBooleanAttribute(attrName) { + return matchSimpleAttribute.test(attrName); +} + +function isEnumeratedAttribute(attrName) { + return attrName in enumeratedAttributeValues; } function styleStringToObject(str) { @@ -210,7 +204,7 @@ function writeAttributeToMagicPen(output, attributeName, value, isHtml) { } function stringifyAttribute(attributeName, value) { - if (isBooleanAttribute(attributeName)) { + if (isBooleanAttribute(attributeName) || isEnumeratedAttribute(attributeName)) { return attributeName; } else if (attributeName === 'class') { return 'class="' + value.join(' ') + '"'; // FIXME: entitify @@ -1042,13 +1036,34 @@ module.exports = { var expectedAttributeValue = expectedValueByAttributeName[attributeName]; promiseByKey.attributes[attributeName] = expect.promise(function() { - if (expectedAttributeValue === true) { + if (typeof expectedAttributeValue === 'undefined') { return bubbleError(function() { - expect(subject.hasAttribute(attributeName), 'to be true'); + expect(subject.hasAttribute(attributeName), 'to be false'); }); - } else if (typeof expectedAttributeValue === 'undefined') { + } else if (isEnumeratedAttribute(attributeName)) { return bubbleError(function() { - expect(subject.hasAttribute(attributeName), 'to be false'); + var indexOfEnumeratedAttributeValue = enumeratedAttributeValues[attributeName].indexOf(expectedAttributeValue); + if (indexOfEnumeratedAttributeValue === -1) { + expect.withError(function() { + expect(enumeratedAttributeValues[attributeName], 'to contain', expectedAttributeValue); + }, function(e) { + expect.fail({ + message: function(output) { + output + .text('Invalid expected value ') + .appendInspected(expectedAttributeValue) + .text('. Supported values include: ') + .appendInspected(enumeratedAttributeValues[attributeName]); + } + }); + }); + } + + expect(attributeValue, 'to satisfy', expectedAttributeValue); + }); + } else if (expectedAttributeValue === true) { + return bubbleError(function() { + expect(subject.hasAttribute(attributeName), 'to be true'); }); } else if ( attributeName === 'class' && diff --git a/test/index.spec.js b/test/index.spec.js index bd1a4929..6e4b45b1 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -1211,6 +1211,61 @@ describe('unexpected-dom', function() { ); }); + describe('with boolean attributes', function() { + describe('draggable', () => { + it('should allow "true"', function() { + body.innerHTML = '
'; + expect(body, 'to satisfy', { + children: [ + { + attributes: { + draggable: 'true' + } + } + ] + }); + }); + + it('should allow "false"', function() { + body.innerHTML = '
'; + expect(body, 'to satisfy', { + children: [ + { + attributes: { + draggable: 'false' + } + } + ] + }); + }); + + it('should error on mismatch', function() { + body.innerHTML = '
'; + expect( + function() { + expect(body, 'to satisfy', { + children: [ + { + attributes: { + draggable: false + } + } + ] + }) + }, + 'to throw', + 'expected
to satisfy { children: [ { attributes: ... } ] }\n' + + '\n' + + '\n' + + ' \n' + + '' + ); + }); + }); + }); + describe('with a textContent property', function() { it('should succeed', function() { body.innerHTML = '
foobarquux
';