qunit-dom
Version:
DOM element assertions for QUnit
338 lines (278 loc) • 9.65 kB
JavaScript
(function (QUnit) {
'use strict';
function exists(options, message) {
if (typeof this.target !== 'string') {
throw new TypeError('Unexpected Parameter: ' + this.target);
}
if (typeof options === 'string') {
message = options;
options = undefined;
}
var elements = this.rootElement.querySelectorAll(this.target);
var expectedCount = options ? options.count : null;
if (expectedCount === null) {
var result = elements.length > 0;
var expected = format(this.target);
var actual = result ? expected : format(this.target, 0);
if (!message) {
message = expected;
}
this.pushResult({ result: result, actual: actual, expected: expected, message: message });
} else if (typeof expectedCount === 'number') {
var _result = elements.length === expectedCount;
var _actual = format(this.target, elements.length);
var _expected = format(this.target, expectedCount);
if (!message) {
message = _expected;
}
this.pushResult({ result: _result, actual: _actual, expected: _expected, message: message });
} else {
throw new TypeError('Unexpected Parameter: ' + expectedCount);
}
}
function format(selector, num) {
if (num === undefined || num === null) {
return 'Element ' + selector + ' exists';
} else if (num === 0) {
return 'Element ' + selector + ' does not exist';
} else if (num === 1) {
return 'Element ' + selector + ' exists once';
} else if (num === 2) {
return 'Element ' + selector + ' exists twice';
} else {
return 'Element ' + selector + ' exists ' + num + ' times';
}
}
// imported from https://github.com/nathanboktae/chai-dom
function elementToString(el) {
var desc = void 0;
if (el instanceof window.NodeList) {
if (el.length === 0) {
return 'empty NodeList';
}
desc = Array.prototype.slice.call(el, 0, 5).map(elementToString).join(', ');
return el.length > 5 ? desc + '... (+' + (el.length - 5) + ' more)' : desc;
}
if (!(el instanceof window.HTMLElement)) {
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;
}
function focused(message) {
var element = this.findTargetElement();
if (!element) return;
var result = document.activeElement === element;
var actual = elementToString(document.activeElement);
var expected = elementToString(this.target);
if (!message) {
message = 'Element ' + expected + ' is focused';
}
this.pushResult({ result: result, actual: actual, expected: expected, message: message });
}
function notFocused(message) {
var element = this.findTargetElement();
if (!element) return;
var result = document.activeElement !== element;
if (!message) {
message = "Element " + this.targetDescription + " is not focused";
}
this.pushResult({ result: result, message: message });
}
function collapseWhitespace(string) {
return string.replace(/[\t\r\n]/g, ' ').replace(/ +/g, ' ').replace(/^ /, '').replace(/ $/, '');
}
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var DOMAssertions = function () {
function DOMAssertions(target, rootElement, testContext) {
_classCallCheck(this, DOMAssertions);
this.target = target;
this.rootElement = rootElement;
this.testContext = testContext;
}
/**
* Assert an [HTMLElement][] (or multiple) matching the `selector` exists.
*
* @param {object?} options
* @param {string?} message
*
* @example
* assert.dom('#title').exists();
* assert.dom('.choice').exists({ count: 4 });
*/
_createClass(DOMAssertions, [{
key: 'exists',
value: function exists$$1(options, message) {
exists.call(this, options, message);
}
/**
* Assert an [HTMLElement][] matching the `selector` does not exists.
*
* @param {string?} message
*
* @example
* assert.dom('.should-not-exist').doesNotExist();
*/
}, {
key: 'doesNotExist',
value: function doesNotExist(message) {
exists.call(this, { count: 0 }, message);
}
/**
* Assert that the [HTMLElement][] or an [HTMLElement][] matching the
* `selector` is currently focused.
*
* @param {string?} message
*
* @example
* assert.dom('input.email').isFocused();
*/
}, {
key: 'isFocused',
value: function isFocused(message) {
focused.call(this, message);
}
/**
* Assert that the [HTMLElement][] or an [HTMLElement][] matching the
* `selector` is not currently focused.
*
* @param {string?} message
*
* @example
* assert.dom('input[type="password"]').isNotFocused();
*/
}, {
key: 'isNotFocused',
value: function isNotFocused(message) {
notFocused.call(this, message);
}
/**
* Assert that the text of the [HTMLElement][] or an [HTMLElement][]
* matching the `selector` matches the `expected` text, using the
* [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
* attribute and stripping/collapsing whitespace.
*
* `expected` can also be a regular expression.
*
* @param {string|RegExp} expected
* @param {string?} message
*
* @example
* // <h2 id="title">
* // Welcome to <b>QUnit</b>
* // </h2>
*
* assert.dom('#title').hasText('Welcome to QUnit');
*
* @example
* assert.dom('.foo').hasText(/[12]\d{3}/);
*/
}, {
key: 'hasText',
value: function hasText(expected, message) {
var element = this.findTargetElement();
if (!element) return;
if (expected instanceof RegExp) {
var result = expected.test(element.textContent);
var actual = element.textContent;
if (!message) {
message = 'Element ' + this.targetDescription + ' has text matching ' + expected;
}
this.pushResult({ result: result, actual: actual, expected: expected, message: message });
} else {
expected = collapseWhitespace(expected);
var _actual = collapseWhitespace(element.textContent);
var _result = _actual === expected;
if (!message) {
message = 'Element ' + this.targetDescription + ' has text "' + expected + '"';
}
this.pushResult({ result: _result, actual: _actual, expected: expected, message: message });
}
}
/**
* Assert that the text of the [HTMLElement][] or an [HTMLElement][]
* matching the `selector` contains the given `text`, using the
* [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
* attribute.
*
* @param {string} text
* @param {string?} message
*
* @example
* assert.dom('#title').hasTextContaining('Welcome');
*/
}, {
key: 'hasTextContaining',
value: function hasTextContaining(text, message) {
var element = this.findTargetElement();
if (!element) return;
var result = element.textContent.indexOf(text) !== -1;
var actual = element.textContent;
var expected = text;
if (!message) {
message = 'Element ' + this.targetDescription + ' has text containing "' + text + '"';
}
this.pushResult({ result: result, actual: actual, expected: expected, message: message });
}
/**
* @private
*/
}, {
key: 'pushResult',
value: function pushResult(result) {
this.testContext.pushResult(result);
}
/**
* @private
*/
}, {
key: 'findTargetElement',
value: function findTargetElement() {
if (this.target === null) {
var message = 'Element <unknown> exists';
this.pushResult({ message: message, result: false });
return null;
}
if (typeof this.target === 'string') {
var el = this.rootElement.querySelector(this.target);
if (el === null) {
var _message = 'Element ' + (this.target || '<unknown>') + ' exists';
this.pushResult({ message: _message, result: false });
}
return el;
} else if (this.target instanceof HTMLElement) {
return this.target;
} else {
throw new TypeError('Unexpected Parameter: ' + this.target);
}
}
/**
* @private
*/
}, {
key: 'targetDescription',
get: function get() {
return elementToString(this.target);
}
}]);
return DOMAssertions;
}();
QUnit.extend(QUnit.assert, {
dom: function dom(target, rootElement) {
return new DOMAssertions(target, rootElement || this.dom.rootElement || document, this);
}
});
}(QUnit));
//# sourceMappingURL=qunit-dom.js.map