Created
August 7, 2019 10:26
-
-
Save nweldev/56113345cb4fd5d45f636ac6c7c3637b to your computer and use it in GitHub Desktop.
chai-dom as an ES Module
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******** | |
Convert chai-dom 1.8.1 to es module, without any other modification. | |
From https://github.com/nathanboktae/chai-dom/blob/86c3423/chai-dom.js | |
See https://github.com/nathanboktae/chai-dom/issues/38 | |
Usage: | |
import { chaiDom } from '<path-to>/chai-dom'; | |
chai.use(chaiDom); | |
Copyright (c) 2015 Nathan Black and other contributors | |
This work is licensed under the terms of the MIT license. For a copy, see <https://opensource.org/licenses/MIT>. | |
**********/ | |
export function chaiDom(chai, utils) { | |
var flag = utils.flag, | |
elToString = function(el) { | |
var desc | |
if (isNodeList(el)) { | |
if (el.length === 0) return 'empty NodeList' | |
desc = Array.prototype.slice.call(el, 0, 5).map(elToString).join(', ') | |
return el.length > 5 ? desc + '... (+' + (el.length - 5) + ' more)' : desc | |
} | |
if (!isHTMLElement(el)) { | |
return String(el) | |
} | |
desc = el.tagName.toLowerCase() | |
if (el.id) { | |
desc += '#' + el.id | |
} | |
if (el.className) { | |
desc += '.' + String(el.className).replace(/\s+/g, '.') | |
} | |
Array.prototype.forEach.call(el.attributes, function(attr) { | |
if (attr.name !== 'class' && attr.name !== 'id') { | |
desc += '[' + attr.name + (attr.value ? '="' + attr.value + '"]' : ']') | |
} | |
}) | |
return desc | |
}, | |
attrAssert = function(name, val) { | |
var el = flag(this, 'object'), actual = el.getAttribute(name) | |
if (!flag(this, 'negate') || undefined === val) { | |
this.assert( | |
!!el.attributes[name] | |
, 'expected ' + elToString(el) + ' to have an attribute #{exp}' | |
, 'expected ' + elToString(el) + ' not to have an attribute #{exp}' | |
, name | |
) | |
} | |
if (undefined !== val) { | |
this.assert( | |
val === actual | |
, 'expected ' + elToString(el) + ' to have an attribute ' + utils.inspect(name) + ' with the value #{exp}, but the value was #{act}' | |
, 'expected ' + elToString(el) + ' not to have an attribute ' + utils.inspect(name) + ' with the value #{act}' | |
, val | |
, actual | |
) | |
} | |
flag(this, 'object', actual) | |
}, | |
isHTMLElement = function(el) { | |
return el.nodeType === 1 // window.Node.ELEMENT_NODE | |
}, | |
isNodeList = function(obj) { | |
return Object.prototype.toString.call(obj) === '[object NodeList]' | |
} | |
utils.elToString = elToString | |
chai.Assertion.addMethod('attr', attrAssert) | |
chai.Assertion.addMethod('attribute', attrAssert) | |
chai.Assertion.addMethod('class', function(className) { | |
var el = flag(this, 'object') | |
this.assert( | |
el.classList.contains(className) | |
, 'expected ' + elToString(el) + ' to have class #{exp}' | |
, 'expected ' + elToString(el) + ' not to have class #{exp}' | |
, className | |
) | |
}) | |
chai.Assertion.addMethod('id', function(id) { | |
var el = flag(this, 'object') | |
this.assert( | |
el.id == id | |
, 'expected ' + elToString(el) + ' to have id #{exp}' | |
, 'expected ' + elToString(el) + ' not to have id #{exp}' | |
, id | |
) | |
}) | |
chai.Assertion.addMethod('html', function(html) { | |
var el = flag(this, 'object'), actual = flag(this, 'object').innerHTML | |
if (flag(this, 'contains')) { | |
this.assert( | |
actual.indexOf(html) >= 0 | |
, 'expected #{act} to contain HTML #{exp}' | |
, 'expected #{act} not to contain HTML #{exp}' | |
, html | |
, actual | |
) | |
} else { | |
this.assert( | |
actual === html | |
, 'expected ' + elToString(el) + ' to have HTML #{exp}, but the HTML was #{act}' | |
, 'expected ' + elToString(el) + ' not to have HTML #{exp}' | |
, html | |
, actual | |
) | |
} | |
}) | |
chai.Assertion.addChainableMethod('trimmed', null, function() { | |
flag(this, 'trim-text', true) | |
}) | |
chai.Assertion.addMethod('text', function(text) { | |
var obj = flag(this, 'object'), contains = flag(this, 'contains'), | |
trim = flag(this, 'trim-text'), actual, result | |
if (isNodeList(obj)) { | |
actual = Array.prototype.map.call(obj, function(el) { return trim ? el.textContent.trim() : el.textContent }) | |
if (Array.isArray(text)) { | |
result = contains ? | |
text[flag(this, 'negate') ? 'some' : 'every'](function(t) { | |
return Array.prototype.some.call(obj, function(el) { | |
return (trim ? el.textContent.trim() : el.textContent) === t | |
}) | |
}) | |
: | |
utils.eql(actual, text) | |
actual = actual.join() | |
text = text.join() | |
} else { | |
actual = actual.join('') | |
result = contains ? actual.indexOf(text) >= 0 : actual === text | |
} | |
} else { | |
actual = trim ? obj.textContent.trim() : obj.textContent | |
result = contains ? actual.indexOf(text) >= 0 : actual === text | |
} | |
var objDesc = elToString(obj), textMsg = trim ? 'trimmed text' : 'text' | |
if (contains) { | |
this.assert( | |
result | |
, 'expected ' + objDesc + ' to contain #{exp}, but the ' + textMsg + ' was #{act}' | |
, 'expected ' + objDesc + ' not to contain #{exp}, but the ' + textMsg + ' was #{act}' | |
, text | |
, actual | |
) | |
} else { | |
this.assert( | |
result | |
, 'expected ' + objDesc + ' to have ' + textMsg + ' #{exp}, but the ' + textMsg + ' was #{act}' | |
, 'expected ' + objDesc + ' not to have ' + textMsg + ' #{exp}' | |
, text | |
, actual | |
) | |
} | |
}) | |
chai.Assertion.addMethod('value', function(value) { | |
var el = flag(this, 'object'), actual = flag(this, 'object').value | |
this.assert( | |
flag(this, 'object').value === value | |
, 'expected ' + elToString(el) + ' to have value #{exp}, but the value was #{act}' | |
, 'expected ' + elToString(el) + ' not to have value #{exp}' | |
, value | |
, actual | |
) | |
}) | |
chai.Assertion.overwriteProperty('exist', function(_super) { | |
return function() { | |
var obj = flag(this, 'object') | |
if (isNodeList(obj)) { | |
this.assert( | |
obj.length > 0 | |
, 'expected an empty NodeList to have nodes' | |
, 'expected ' + elToString(obj) + ' to not exist') | |
} else { | |
_super.apply(this, arguments) | |
} | |
} | |
}) | |
chai.Assertion.overwriteProperty('empty', function(_super) { | |
return function() { | |
var obj = flag(this, 'object') | |
if (isHTMLElement(obj)) { | |
this.assert( | |
obj.children.length === 0 | |
, 'expected ' + elToString(obj) + ' to be empty' | |
, 'expected ' + elToString(obj) + ' to not be empty') | |
} else if (isNodeList(obj)) { | |
this.assert( | |
obj.length === 0 | |
, 'expected ' + elToString(obj) + ' to be empty' | |
, 'expected ' + elToString(obj) + ' to not be empty') | |
} else { | |
_super.apply(this, arguments) | |
} | |
} | |
}) | |
chai.Assertion.overwriteChainableMethod('length', | |
function(_super) { | |
return function(length) { | |
var obj = flag(this, 'object') | |
if (isNodeList(obj) || isHTMLElement(obj)) { | |
var actualLength = obj.children ? obj.children.length : obj.length | |
this.assert( | |
actualLength === length | |
, 'expected ' + elToString(obj) + ' to have #{exp} children but it had #{act} children' | |
, 'expected ' + elToString(obj) + ' to not have #{exp} children' | |
, length | |
, actualLength | |
) | |
} else { | |
_super.apply(this, arguments) | |
} | |
} | |
}, | |
function(_super) { | |
return function() { | |
_super.call(this) | |
} | |
} | |
) | |
chai.Assertion.overwriteMethod('match', function(_super) { | |
return function(selector) { | |
var obj = flag(this, 'object') | |
if (isHTMLElement(obj)) { | |
this.assert( | |
obj.matches(selector) | |
, 'expected ' + elToString(obj) + ' to match #{exp}' | |
, 'expected ' + elToString(obj) + ' to not match #{exp}' | |
, selector | |
) | |
} else if (isNodeList(obj)) { | |
this.assert( | |
(!!obj.length && Array.prototype.every.call(obj, function(el) { return el.matches(selector) })) | |
, 'expected ' + elToString(obj) + ' to match #{exp}' | |
, 'expected ' + elToString(obj) + ' to not match #{exp}' | |
, selector | |
) | |
} else { | |
_super.apply(this, arguments) | |
} | |
} | |
}) | |
chai.Assertion.overwriteChainableMethod('contain', | |
function(_super) { | |
return function(subitem) { | |
var obj = flag(this, 'object') | |
if (isHTMLElement(obj)) { | |
if (typeof subitem === 'string') { | |
this.assert( | |
!!obj.querySelector(subitem) | |
, 'expected ' + elToString(obj) + ' to contain #{exp}' | |
, 'expected ' + elToString(obj) + ' to not contain #{exp}' | |
, subitem) | |
} else { | |
this.assert( | |
obj.contains(subitem) | |
, 'expected ' + elToString(obj) + ' to contain ' + elToString(subitem) | |
, 'expected ' + elToString(obj) + ' to not contain ' + elToString(subitem)) | |
} | |
} else { | |
_super.apply(this, arguments) | |
} | |
} | |
}, | |
function(_super) { | |
return function() { | |
_super.call(this) | |
} | |
} | |
) | |
chai.Assertion.addMethod('descendant', function(subitem) { | |
var obj = flag(this, 'object'), actual = subitem | |
if (typeof subitem === 'string') { | |
actual = obj.querySelector(subitem) | |
this.assert( | |
!!actual | |
, 'expected ' + elToString(obj) + ' to have descendant #{exp}' | |
, 'expected ' + elToString(obj) + ' to not have descendant #{exp}' | |
, subitem) | |
} else { | |
this.assert( | |
obj.contains(subitem) | |
, 'expected ' + elToString(obj) + ' to contain ' + elToString(subitem) | |
, 'expected ' + elToString(obj) + ' to not contain ' + elToString(subitem)) | |
} | |
flag(this, 'object', actual) | |
}) | |
chai.Assertion.addMethod('descendants', function(selector) { | |
var obj = flag(this, 'object'), | |
actual = obj.querySelectorAll(selector) | |
this.assert( | |
!!actual.length | |
, 'expected ' + elToString(obj) + ' to have descendants #{exp}' | |
, 'expected ' + elToString(obj) + ' to not have descendants #{exp}' | |
, selector) | |
flag(this, 'object', actual) | |
}) | |
chai.Assertion.addProperty('displayed', function() { | |
var el = flag(this, 'object'), | |
actual = document.body.contains(el) ? window.getComputedStyle(el).display : el.style.display | |
this.assert( | |
actual !== 'none' | |
, 'expected ' + elToString(el) + ' to be displayed, but it was not' | |
, 'expected ' + elToString(el) + ' to not be displayed, but it was as ' + actual | |
, actual | |
) | |
}) | |
chai.Assertion.addProperty('visible', function() { | |
var el = flag(this, 'object'), | |
actual = document.body.contains(el) ? window.getComputedStyle(el).visibility : el.style.visibility | |
this.assert( | |
actual !== 'hidden' && actual !== 'collapse' | |
, 'expected ' + elToString(el) + ' to be visible, but it was ' + (actual === 'hidden' ? 'hidden' : 'collapsed') | |
, 'expected ' + elToString(el) + ' to not be visible, but it was' | |
, actual | |
) | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment