UNPKG

60.5 kBJavaScriptView Raw
1var QUnitDOM = (function (exports) {
2 'use strict';
3
4 function exists(options, message) {
5 var expectedCount = null;
6 if (typeof options === 'string') {
7 message = options;
8 }
9 else if (options) {
10 expectedCount = options.count;
11 }
12 var elements = this.findElements();
13 if (expectedCount === null) {
14 var result = elements.length > 0;
15 var expected = format$1(this.targetDescription);
16 var actual = result ? expected : format$1(this.targetDescription, 0);
17 if (!message) {
18 message = expected;
19 }
20 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
21 }
22 else if (typeof expectedCount === 'number') {
23 var result = elements.length === expectedCount;
24 var actual = format$1(this.targetDescription, elements.length);
25 var expected = format$1(this.targetDescription, expectedCount);
26 if (!message) {
27 message = expected;
28 }
29 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
30 }
31 else {
32 throw new TypeError("Unexpected Parameter: " + expectedCount);
33 }
34 }
35 function format$1(selector, num) {
36 if (num === undefined || num === null) {
37 return "Element " + selector + " exists";
38 }
39 else if (num === 0) {
40 return "Element " + selector + " does not exist";
41 }
42 else if (num === 1) {
43 return "Element " + selector + " exists once";
44 }
45 else if (num === 2) {
46 return "Element " + selector + " exists twice";
47 }
48 else {
49 return "Element " + selector + " exists " + num + " times";
50 }
51 }
52
53 // imported from https://github.com/nathanboktae/chai-dom
54 function elementToString(el) {
55 if (!el)
56 return '<not found>';
57 var desc;
58 if (el instanceof NodeList) {
59 if (el.length === 0) {
60 return 'empty NodeList';
61 }
62 desc = Array.prototype.slice.call(el, 0, 5).map(elementToString).join(', ');
63 return el.length > 5 ? desc + "... (+" + (el.length - 5) + " more)" : desc;
64 }
65 if (!(el instanceof HTMLElement || el instanceof SVGElement)) {
66 return String(el);
67 }
68 desc = el.tagName.toLowerCase();
69 if (el.id) {
70 desc += "#" + el.id;
71 }
72 if (el.className && !(el.className instanceof SVGAnimatedString)) {
73 desc += "." + String(el.className).replace(/\s+/g, '.');
74 }
75 Array.prototype.forEach.call(el.attributes, function (attr) {
76 if (attr.name !== 'class' && attr.name !== 'id') {
77 desc += "[" + attr.name + (attr.value ? "=\"" + attr.value + "\"]" : ']');
78 }
79 });
80 return desc;
81 }
82
83 function focused(message) {
84 var element = this.findTargetElement();
85 if (!element)
86 return;
87 var result = document.activeElement === element;
88 var actual = elementToString(document.activeElement);
89 var expected = elementToString(this.target);
90 if (!message) {
91 message = "Element " + expected + " is focused";
92 }
93 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
94 }
95
96 function notFocused(message) {
97 var element = this.findTargetElement();
98 if (!element)
99 return;
100 var result = document.activeElement !== element;
101 var expected = "Element " + this.targetDescription + " is not focused";
102 var actual = result ? expected : "Element " + this.targetDescription + " is focused";
103 if (!message) {
104 message = expected;
105 }
106 this.pushResult({ result: result, message: message, actual: actual, expected: expected });
107 }
108
109 function checked(message) {
110 var element = this.findTargetElement();
111 if (!element)
112 return;
113 var isChecked = element.checked === true;
114 var isNotChecked = element.checked === false;
115 var result = isChecked;
116 var hasCheckedProp = isChecked || isNotChecked;
117 if (!hasCheckedProp) {
118 var ariaChecked = element.getAttribute('aria-checked');
119 if (ariaChecked !== null) {
120 result = ariaChecked === 'true';
121 }
122 }
123 var actual = result ? 'checked' : 'not checked';
124 var expected = 'checked';
125 if (!message) {
126 message = "Element " + elementToString(this.target) + " is checked";
127 }
128 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
129 }
130
131 function notChecked(message) {
132 var element = this.findTargetElement();
133 if (!element)
134 return;
135 var isChecked = element.checked === true;
136 var isNotChecked = element.checked === false;
137 var result = !isChecked;
138 var hasCheckedProp = isChecked || isNotChecked;
139 if (!hasCheckedProp) {
140 var ariaChecked = element.getAttribute('aria-checked');
141 if (ariaChecked !== null) {
142 result = ariaChecked !== 'true';
143 }
144 }
145 var actual = result ? 'not checked' : 'checked';
146 var expected = 'not checked';
147 if (!message) {
148 message = "Element " + elementToString(this.target) + " is not checked";
149 }
150 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
151 }
152
153 function required(message) {
154 var element = this.findTargetElement();
155 if (!element)
156 return;
157 if (!(element instanceof HTMLInputElement ||
158 element instanceof HTMLTextAreaElement ||
159 element instanceof HTMLSelectElement)) {
160 throw new TypeError("Unexpected Element Type: " + element.toString());
161 }
162 var result = element.required === true;
163 var actual = result ? 'required' : 'not required';
164 var expected = 'required';
165 if (!message) {
166 message = "Element " + elementToString(this.target) + " is required";
167 }
168 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
169 }
170
171 function notRequired(message) {
172 var element = this.findTargetElement();
173 if (!element)
174 return;
175 if (!(element instanceof HTMLInputElement ||
176 element instanceof HTMLTextAreaElement ||
177 element instanceof HTMLSelectElement)) {
178 throw new TypeError("Unexpected Element Type: " + element.toString());
179 }
180 var result = element.required === false;
181 var actual = !result ? 'required' : 'not required';
182 var expected = 'not required';
183 if (!message) {
184 message = "Element " + elementToString(this.target) + " is not required";
185 }
186 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
187 }
188
189 function isValid(message, options) {
190 if (options === void 0) { options = {}; }
191 var element = this.findTargetElement();
192 if (!element)
193 return;
194 if (!(element instanceof HTMLFormElement ||
195 element instanceof HTMLInputElement ||
196 element instanceof HTMLTextAreaElement ||
197 element instanceof HTMLButtonElement ||
198 element instanceof HTMLOutputElement ||
199 element instanceof HTMLSelectElement)) {
200 throw new TypeError("Unexpected Element Type: " + element.toString());
201 }
202 var validity = element.reportValidity() === true;
203 var result = validity === !options.inverted;
204 var actual = validity ? 'valid' : 'not valid';
205 var expected = options.inverted ? 'not valid' : 'valid';
206 if (!message) {
207 message = "Element " + elementToString(this.target) + " is " + actual;
208 }
209 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
210 }
211
212 // Visible logic based on jQuery's
213 // https://github.com/jquery/jquery/blob/4a2bcc27f9c3ee24b3effac0fbe1285d1ee23cc5/src/css/hiddenVisibleSelectors.js#L11-L13
214 function visible(el) {
215 if (el === null)
216 return false;
217 if (el.offsetWidth === 0 || el.offsetHeight === 0)
218 return false;
219 var clientRects = el.getClientRects();
220 if (clientRects.length === 0)
221 return false;
222 for (var i = 0; i < clientRects.length; i++) {
223 var rect = clientRects[i];
224 if (rect.width !== 0 && rect.height !== 0)
225 return true;
226 }
227 return false;
228 }
229
230 function isVisible(options, message) {
231 var expectedCount = null;
232 if (typeof options === 'string') {
233 message = options;
234 }
235 else if (options) {
236 expectedCount = options.count;
237 }
238 var elements = this.findElements().filter(visible);
239 if (expectedCount === null) {
240 var result = elements.length > 0;
241 var expected = format(this.targetDescription);
242 var actual = result ? expected : format(this.targetDescription, 0);
243 if (!message) {
244 message = expected;
245 }
246 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
247 }
248 else if (typeof expectedCount === 'number') {
249 var result = elements.length === expectedCount;
250 var actual = format(this.targetDescription, elements.length);
251 var expected = format(this.targetDescription, expectedCount);
252 if (!message) {
253 message = expected;
254 }
255 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
256 }
257 else {
258 throw new TypeError("Unexpected Parameter: " + expectedCount);
259 }
260 }
261 function format(selector, num) {
262 if (num === undefined || num === null) {
263 return "Element " + selector + " is visible";
264 }
265 else if (num === 0) {
266 return "Element " + selector + " is not visible";
267 }
268 else if (num === 1) {
269 return "Element " + selector + " is visible once";
270 }
271 else if (num === 2) {
272 return "Element " + selector + " is visible twice";
273 }
274 else {
275 return "Element " + selector + " is visible " + num + " times";
276 }
277 }
278
279 function isDisabled(message, options) {
280 if (options === void 0) { options = {}; }
281 var inverted = options.inverted;
282 var element = this.findTargetElement();
283 if (!element)
284 return;
285 if (!(element instanceof HTMLInputElement ||
286 element instanceof HTMLTextAreaElement ||
287 element instanceof HTMLSelectElement ||
288 element instanceof HTMLButtonElement ||
289 element instanceof HTMLOptGroupElement ||
290 element instanceof HTMLOptionElement ||
291 element instanceof HTMLFieldSetElement)) {
292 throw new TypeError("Unexpected Element Type: " + element.toString());
293 }
294 var result = element.disabled === !inverted;
295 var actual = element.disabled === false
296 ? "Element " + this.targetDescription + " is not disabled"
297 : "Element " + this.targetDescription + " is disabled";
298 var expected = inverted
299 ? "Element " + this.targetDescription + " is not disabled"
300 : "Element " + this.targetDescription + " is disabled";
301 if (!message) {
302 message = expected;
303 }
304 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
305 }
306
307 function matchesSelector(elements, compareSelector) {
308 var failures = elements.filter(function (it) { return !it.matches(compareSelector); });
309 return failures.length;
310 }
311
312 function collapseWhitespace(string) {
313 return string
314 .replace(/[\t\r\n]/g, ' ')
315 .replace(/ +/g, ' ')
316 .replace(/^ /, '')
317 .replace(/ $/, '');
318 }
319
320 /**
321 * This function can be used to convert a NodeList to a regular array.
322 * We should be using `Array.from()` for this, but IE11 doesn't support that :(
323 *
324 * @private
325 */
326 function toArray(list) {
327 return Array.prototype.slice.call(list);
328 }
329
330 var DOMAssertions = /** @class */ (function () {
331 function DOMAssertions(target, rootElement, testContext) {
332 this.target = target;
333 this.rootElement = rootElement;
334 this.testContext = testContext;
335 }
336 /**
337 * Assert an {@link HTMLElement} (or multiple) matching the `selector` exists.
338 *
339 * @param {object?} options
340 * @param {number?} options.count
341 * @param {string?} message
342 *
343 * @example
344 * assert.dom('#title').exists();
345 * assert.dom('.choice').exists({ count: 4 });
346 *
347 * @see {@link #doesNotExist}
348 */
349 DOMAssertions.prototype.exists = function (options, message) {
350 exists.call(this, options, message);
351 return this;
352 };
353 /**
354 * Assert an {@link HTMLElement} matching the `selector` does not exists.
355 *
356 * @param {string?} message
357 *
358 * @example
359 * assert.dom('.should-not-exist').doesNotExist();
360 *
361 * @see {@link #exists}
362 */
363 DOMAssertions.prototype.doesNotExist = function (message) {
364 exists.call(this, { count: 0 }, message);
365 return this;
366 };
367 /**
368 * Assert that the {@link HTMLElement} or an {@link HTMLElement} matching the
369 * `selector` is currently checked.
370 *
371 * Note: This also supports `aria-checked="true/false"`.
372 *
373 * @param {string?} message
374 *
375 * @example
376 * assert.dom('input.active').isChecked();
377 *
378 * @see {@link #isNotChecked}
379 */
380 DOMAssertions.prototype.isChecked = function (message) {
381 checked.call(this, message);
382 return this;
383 };
384 /**
385 * Assert that the {@link HTMLElement} or an {@link HTMLElement} matching the
386 * `selector` is currently unchecked.
387 *
388 * Note: This also supports `aria-checked="true/false"`.
389 *
390 * @param {string?} message
391 *
392 * @example
393 * assert.dom('input.active').isNotChecked();
394 *
395 * @see {@link #isChecked}
396 */
397 DOMAssertions.prototype.isNotChecked = function (message) {
398 notChecked.call(this, message);
399 return this;
400 };
401 /**
402 * Assert that the {@link HTMLElement} or an {@link HTMLElement} matching the
403 * `selector` is currently focused.
404 *
405 * @param {string?} message
406 *
407 * @example
408 * assert.dom('input.email').isFocused();
409 *
410 * @see {@link #isNotFocused}
411 */
412 DOMAssertions.prototype.isFocused = function (message) {
413 focused.call(this, message);
414 return this;
415 };
416 /**
417 * Assert that the {@link HTMLElement} or an {@link HTMLElement} matching the
418 * `selector` is not currently focused.
419 *
420 * @param {string?} message
421 *
422 * @example
423 * assert.dom('input[type="password"]').isNotFocused();
424 *
425 * @see {@link #isFocused}
426 */
427 DOMAssertions.prototype.isNotFocused = function (message) {
428 notFocused.call(this, message);
429 return this;
430 };
431 /**
432 * Assert that the {@link HTMLElement} or an {@link HTMLElement} matching the
433 * `selector` is currently required.
434 *
435 * @param {string?} message
436 *
437 * @example
438 * assert.dom('input[type="text"]').isRequired();
439 *
440 * @see {@link #isNotRequired}
441 */
442 DOMAssertions.prototype.isRequired = function (message) {
443 required.call(this, message);
444 return this;
445 };
446 /**
447 * Assert that the {@link HTMLElement} or an {@link HTMLElement} matching the
448 * `selector` is currently not required.
449 *
450 * @param {string?} message
451 *
452 * @example
453 * assert.dom('input[type="text"]').isNotRequired();
454 *
455 * @see {@link #isRequired}
456 */
457 DOMAssertions.prototype.isNotRequired = function (message) {
458 notRequired.call(this, message);
459 return this;
460 };
461 /**
462 * Assert that the {@link HTMLElement} passes validation
463 *
464 * Validity is determined by asserting that:
465 *
466 * - `element.reportValidity() === true`
467 *
468 * @param {string?} message
469 *
470 * @example
471 * assert.dom('.input').isValid();
472 *
473 * @see {@link #isValid}
474 */
475 DOMAssertions.prototype.isValid = function (message) {
476 isValid.call(this, message);
477 return this;
478 };
479 /**
480 * Assert that the {@link HTMLElement} does not pass validation
481 *
482 * Validity is determined by asserting that:
483 *
484 * - `element.reportValidity() === true`
485 *
486 * @param {string?} message
487 *
488 * @example
489 * assert.dom('.input').isNotValid();
490 *
491 * @see {@link #isValid}
492 */
493 DOMAssertions.prototype.isNotValid = function (message) {
494 isValid.call(this, message, { inverted: true });
495 return this;
496 };
497 /**
498 * Assert that the {@link HTMLElement} or an {@link HTMLElement} matching the
499 * `selector` exists and is visible.
500 *
501 * Visibility is determined by asserting that:
502 *
503 * - the element's offsetWidth and offsetHeight are non-zero
504 * - any of the element's DOMRect objects have a non-zero size
505 *
506 * Additionally, visibility in this case means that the element is visible on the page,
507 * but not necessarily in the viewport.
508 *
509 * @param {object?} options
510 * @param {number?} options.count
511 * @param {string?} message
512 *
513 * @example
514 * assert.dom('#title').isVisible();
515 * assert.dom('.choice').isVisible({ count: 4 });
516 *
517 * @see {@link #isNotVisible}
518 */
519 DOMAssertions.prototype.isVisible = function (options, message) {
520 isVisible.call(this, options, message);
521 return this;
522 };
523 /**
524 * Assert that the {@link HTMLElement} or an {@link HTMLElement} matching the
525 * `selector` does not exist or is not visible on the page.
526 *
527 * Visibility is determined by asserting that:
528 *
529 * - the element's offsetWidth or offsetHeight are zero
530 * - all of the element's DOMRect objects have a size of zero
531 *
532 * Additionally, visibility in this case means that the element is visible on the page,
533 * but not necessarily in the viewport.
534 *
535 * @param {string?} message
536 *
537 * @example
538 * assert.dom('.foo').isNotVisible();
539 *
540 * @see {@link #isVisible}
541 */
542 DOMAssertions.prototype.isNotVisible = function (message) {
543 isVisible.call(this, { count: 0 }, message);
544 return this;
545 };
546 /**
547 * Assert that the {@link HTMLElement} has an attribute with the provided `name`
548 * and optionally checks if the attribute `value` matches the provided text
549 * or regular expression.
550 *
551 * @param {string} name
552 * @param {string|RegExp|object?} value
553 * @param {string?} message
554 *
555 * @example
556 * assert.dom('input.password-input').hasAttribute('type', 'password');
557 *
558 * @see {@link #doesNotHaveAttribute}
559 */
560 DOMAssertions.prototype.hasAttribute = function (name, value, message) {
561 var element = this.findTargetElement();
562 if (!element)
563 return this;
564 if (arguments.length === 1) {
565 value = { any: true };
566 }
567 var actualValue = element.getAttribute(name);
568 if (value instanceof RegExp) {
569 var result = value.test(actualValue);
570 var expected = "Element " + this.targetDescription + " has attribute \"" + name + "\" with value matching " + value;
571 var actual = actualValue === null
572 ? "Element " + this.targetDescription + " does not have attribute \"" + name + "\""
573 : "Element " + this.targetDescription + " has attribute \"" + name + "\" with value " + JSON.stringify(actualValue);
574 if (!message) {
575 message = expected;
576 }
577 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
578 }
579 else if (value.any === true) {
580 var result = actualValue !== null;
581 var expected = "Element " + this.targetDescription + " has attribute \"" + name + "\"";
582 var actual = result
583 ? expected
584 : "Element " + this.targetDescription + " does not have attribute \"" + name + "\"";
585 if (!message) {
586 message = expected;
587 }
588 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
589 }
590 else {
591 var result = value === actualValue;
592 var expected = "Element " + this.targetDescription + " has attribute \"" + name + "\" with value " + JSON.stringify(value);
593 var actual = actualValue === null
594 ? "Element " + this.targetDescription + " does not have attribute \"" + name + "\""
595 : "Element " + this.targetDescription + " has attribute \"" + name + "\" with value " + JSON.stringify(actualValue);
596 if (!message) {
597 message = expected;
598 }
599 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
600 }
601 return this;
602 };
603 /**
604 * Assert that the {@link HTMLElement} has no attribute with the provided `name`.
605 *
606 * **Aliases:** `hasNoAttribute`, `lacksAttribute`
607 *
608 * @param {string} name
609 * @param {string?} message
610 *
611 * @example
612 * assert.dom('input.username').hasNoAttribute('disabled');
613 *
614 * @see {@link #hasAttribute}
615 */
616 DOMAssertions.prototype.doesNotHaveAttribute = function (name, message) {
617 var element = this.findTargetElement();
618 if (!element)
619 return;
620 var result = !element.hasAttribute(name);
621 var expected = "Element " + this.targetDescription + " does not have attribute \"" + name + "\"";
622 var actual = expected;
623 if (!result) {
624 var value = element.getAttribute(name);
625 actual = "Element " + this.targetDescription + " has attribute \"" + name + "\" with value " + JSON.stringify(value);
626 }
627 if (!message) {
628 message = expected;
629 }
630 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
631 return this;
632 };
633 DOMAssertions.prototype.hasNoAttribute = function (name, message) {
634 return this.doesNotHaveAttribute(name, message);
635 };
636 DOMAssertions.prototype.lacksAttribute = function (name, message) {
637 return this.doesNotHaveAttribute(name, message);
638 };
639 /**
640 * Assert that the {@link HTMLElement} has an ARIA attribute with the provided
641 * `name` and optionally checks if the attribute `value` matches the provided
642 * text or regular expression.
643 *
644 * @param {string} name
645 * @param {string|RegExp|object?} value
646 * @param {string?} message
647 *
648 * @example
649 * assert.dom('button').hasAria('pressed', 'true');
650 *
651 * @see {@link #hasNoAria}
652 */
653 DOMAssertions.prototype.hasAria = function (name, value, message) {
654 return this.hasAttribute("aria-" + name, value, message);
655 };
656 /**
657 * Assert that the {@link HTMLElement} has no ARIA attribute with the
658 * provided `name`.
659 *
660 * @param {string} name
661 * @param {string?} message
662 *
663 * @example
664 * assert.dom('button').doesNotHaveAria('pressed');
665 *
666 * @see {@link #hasAria}
667 */
668 DOMAssertions.prototype.doesNotHaveAria = function (name, message) {
669 return this.doesNotHaveAttribute("aria-" + name, message);
670 };
671 /**
672 * Assert that the {@link HTMLElement} has a property with the provided `name`
673 * and checks if the property `value` matches the provided text or regular
674 * expression.
675 *
676 * @param {string} name
677 * @param {RegExp|any} value
678 * @param {string?} message
679 *
680 * @example
681 * assert.dom('input.password-input').hasProperty('type', 'password');
682 *
683 * @see {@link #doesNotHaveProperty}
684 */
685 DOMAssertions.prototype.hasProperty = function (name, value, message) {
686 var element = this.findTargetElement();
687 if (!element)
688 return this;
689 var description = this.targetDescription;
690 var actualValue = element[name];
691 if (value instanceof RegExp) {
692 var result = value.test(String(actualValue));
693 var expected = "Element " + description + " has property \"" + name + "\" with value matching " + value;
694 var actual = "Element " + description + " has property \"" + name + "\" with value " + JSON.stringify(actualValue);
695 if (!message) {
696 message = expected;
697 }
698 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
699 }
700 else {
701 var result = value === actualValue;
702 var expected = "Element " + description + " has property \"" + name + "\" with value " + JSON.stringify(value);
703 var actual = "Element " + description + " has property \"" + name + "\" with value " + JSON.stringify(actualValue);
704 if (!message) {
705 message = expected;
706 }
707 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
708 }
709 return this;
710 };
711 /**
712 * Assert that the {@link HTMLElement} or an {@link HTMLElement} matching the
713 * `selector` is disabled.
714 *
715 * @param {string?} message
716 *
717 * @example
718 * assert.dom('.foo').isDisabled();
719 *
720 * @see {@link #isNotDisabled}
721 */
722 DOMAssertions.prototype.isDisabled = function (message) {
723 isDisabled.call(this, message);
724 return this;
725 };
726 /**
727 * Assert that the {@link HTMLElement} or an {@link HTMLElement} matching the
728 * `selector` is not disabled.
729 *
730 * **Aliases:** `isEnabled`
731 *
732 * @param {string?} message
733 *
734 * @example
735 * assert.dom('.foo').isNotDisabled();
736 *
737 * @see {@link #isDisabled}
738 */
739 DOMAssertions.prototype.isNotDisabled = function (message) {
740 isDisabled.call(this, message, { inverted: true });
741 return this;
742 };
743 DOMAssertions.prototype.isEnabled = function (message) {
744 return this.isNotDisabled(message);
745 };
746 /**
747 * Assert that the {@link HTMLElement} has the `expected` CSS class using
748 * [`classList`](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList).
749 *
750 * `expected` can also be a regular expression, and the assertion will return
751 * true if any of the element's CSS classes match.
752 *
753 * @param {string|RegExp} expected
754 * @param {string?} message
755 *
756 * @example
757 * assert.dom('input[type="password"]').hasClass('secret-password-input');
758 *
759 * @example
760 * assert.dom('input[type="password"]').hasClass(/.*password-input/);
761 *
762 * @see {@link #doesNotHaveClass}
763 */
764 DOMAssertions.prototype.hasClass = function (expected, message) {
765 var element = this.findTargetElement();
766 if (!element)
767 return this;
768 var actual = element.classList.toString();
769 if (expected instanceof RegExp) {
770 var classNames = Array.prototype.slice.call(element.classList);
771 var result = classNames.some(function (className) {
772 return expected.test(className);
773 });
774 if (!message) {
775 message = "Element " + this.targetDescription + " has CSS class matching " + expected;
776 }
777 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
778 }
779 else {
780 var result = element.classList.contains(expected);
781 if (!message) {
782 message = "Element " + this.targetDescription + " has CSS class \"" + expected + "\"";
783 }
784 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
785 }
786 return this;
787 };
788 /**
789 * Assert that the {@link HTMLElement} does not have the `expected` CSS class using
790 * [`classList`](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList).
791 *
792 * `expected` can also be a regular expression, and the assertion will return
793 * true if none of the element's CSS classes match.
794 *
795 * **Aliases:** `hasNoClass`, `lacksClass`
796 *
797 * @param {string|RegExp} expected
798 * @param {string?} message
799 *
800 * @example
801 * assert.dom('input[type="password"]').doesNotHaveClass('username-input');
802 *
803 * @example
804 * assert.dom('input[type="password"]').doesNotHaveClass(/username-.*-input/);
805 *
806 * @see {@link #hasClass}
807 */
808 DOMAssertions.prototype.doesNotHaveClass = function (expected, message) {
809 var element = this.findTargetElement();
810 if (!element)
811 return this;
812 var actual = element.classList.toString();
813 if (expected instanceof RegExp) {
814 var classNames = Array.prototype.slice.call(element.classList);
815 var result = classNames.every(function (className) {
816 return !expected.test(className);
817 });
818 if (!message) {
819 message = "Element " + this.targetDescription + " does not have CSS class matching " + expected;
820 }
821 this.pushResult({ result: result, actual: actual, expected: "not: " + expected, message: message });
822 }
823 else {
824 var result = !element.classList.contains(expected);
825 if (!message) {
826 message = "Element " + this.targetDescription + " does not have CSS class \"" + expected + "\"";
827 }
828 this.pushResult({ result: result, actual: actual, expected: "not: " + expected, message: message });
829 }
830 return this;
831 };
832 DOMAssertions.prototype.hasNoClass = function (expected, message) {
833 return this.doesNotHaveClass(expected, message);
834 };
835 DOMAssertions.prototype.lacksClass = function (expected, message) {
836 return this.doesNotHaveClass(expected, message);
837 };
838 /**
839 * Assert that the [HTMLElement][] has the `expected` style declarations using
840 * [`window.getComputedStyle`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle).
841 *
842 * @param {object} expected
843 * @param {string?} message
844 *
845 * @example
846 * assert.dom('.progress-bar').hasStyle({
847 * opacity: 1,
848 * display: 'block'
849 * });
850 *
851 * @see {@link #hasClass}
852 */
853 DOMAssertions.prototype.hasStyle = function (expected, message) {
854 return this.hasPseudoElementStyle(null, expected, message);
855 };
856 /**
857 * Assert that the pseudo element for `selector` of the [HTMLElement][] has the `expected` style declarations using
858 * [`window.getComputedStyle`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle).
859 *
860 * @param {string} selector
861 * @param {object} expected
862 * @param {string?} message
863 *
864 * @example
865 * assert.dom('.progress-bar').hasPseudoElementStyle(':after', {
866 * content: '";"',
867 * });
868 *
869 * @see {@link #hasClass}
870 */
871 DOMAssertions.prototype.hasPseudoElementStyle = function (selector, expected, message) {
872 var element = this.findTargetElement();
873 if (!element)
874 return this;
875 var computedStyle = window.getComputedStyle(element, selector);
876 var expectedProperties = Object.keys(expected);
877 if (expectedProperties.length <= 0) {
878 throw new TypeError("Missing style expectations. There must be at least one style property in the passed in expectation object.");
879 }
880 var result = expectedProperties.every(function (property) { return computedStyle[property] === expected[property]; });
881 var actual = {};
882 expectedProperties.forEach(function (property) { return (actual[property] = computedStyle[property]); });
883 if (!message) {
884 var normalizedSelector = selector ? selector.replace(/^:{0,2}/, '::') : '';
885 message = "Element " + this.targetDescription + normalizedSelector + " has style \"" + JSON.stringify(expected) + "\"";
886 }
887 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
888 return this;
889 };
890 /**
891 * Assert that the [HTMLElement][] does not have the `expected` style declarations using
892 * [`window.getComputedStyle`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle).
893 *
894 * @param {object} expected
895 * @param {string?} message
896 *
897 * @example
898 * assert.dom('.progress-bar').doesNotHaveStyle({
899 * opacity: 1,
900 * display: 'block'
901 * });
902 *
903 * @see {@link #hasClass}
904 */
905 DOMAssertions.prototype.doesNotHaveStyle = function (expected, message) {
906 return this.doesNotHavePseudoElementStyle(null, expected, message);
907 };
908 /**
909 * Assert that the pseudo element for `selector` of the [HTMLElement][] does not have the `expected` style declarations using
910 * [`window.getComputedStyle`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle).
911 *
912 * @param {string} selector
913 * @param {object} expected
914 * @param {string?} message
915 *
916 * @example
917 * assert.dom('.progress-bar').doesNotHavePseudoElementStyle(':after', {
918 * content: '";"',
919 * });
920 *
921 * @see {@link #hasClass}
922 */
923 DOMAssertions.prototype.doesNotHavePseudoElementStyle = function (selector, expected, message) {
924 var element = this.findTargetElement();
925 if (!element)
926 return this;
927 var computedStyle = window.getComputedStyle(element, selector);
928 var expectedProperties = Object.keys(expected);
929 if (expectedProperties.length <= 0) {
930 throw new TypeError("Missing style expectations. There must be at least one style property in the passed in expectation object.");
931 }
932 var result = expectedProperties.some(function (property) { return computedStyle[property] !== expected[property]; });
933 var actual = {};
934 expectedProperties.forEach(function (property) { return (actual[property] = computedStyle[property]); });
935 if (!message) {
936 var normalizedSelector = selector ? selector.replace(/^:{0,2}/, '::') : '';
937 message = "Element " + this.targetDescription + normalizedSelector + " does not have style \"" + JSON.stringify(expected) + "\"";
938 }
939 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
940 return this;
941 };
942 /**
943 * Assert that the text of the {@link HTMLElement} or an {@link HTMLElement}
944 * matching the `selector` matches the `expected` text, using the
945 * [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
946 * attribute and stripping/collapsing whitespace.
947 *
948 * `expected` can also be a regular expression.
949 *
950 * > Note: This assertion will collapse whitespace if the type you pass in is a string.
951 * > If you are testing specifically for whitespace integrity, pass your expected text
952 * > in as a RegEx pattern.
953 *
954 * **Aliases:** `matchesText`
955 *
956 * @param {string|RegExp} expected
957 * @param {string?} message
958 *
959 * @example
960 * // <h2 id="title">
961 * // Welcome to <b>QUnit</b>
962 * // </h2>
963 *
964 * assert.dom('#title').hasText('Welcome to QUnit');
965 *
966 * @example
967 * assert.dom('.foo').hasText(/[12]\d{3}/);
968 *
969 * @see {@link #includesText}
970 */
971 DOMAssertions.prototype.hasText = function (expected, message) {
972 var element = this.findTargetElement();
973 if (!element)
974 return this;
975 if (expected instanceof RegExp) {
976 var result = expected.test(element.textContent);
977 var actual = element.textContent;
978 if (!message) {
979 message = "Element " + this.targetDescription + " has text matching " + expected;
980 }
981 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
982 }
983 else if (expected.any === true) {
984 var result = Boolean(element.textContent);
985 var expected_1 = "Element " + this.targetDescription + " has a text";
986 var actual = result ? expected_1 : "Element " + this.targetDescription + " has no text";
987 if (!message) {
988 message = expected_1;
989 }
990 this.pushResult({ result: result, actual: actual, expected: expected_1, message: message });
991 }
992 else if (typeof expected === 'string') {
993 expected = collapseWhitespace(expected);
994 var actual = collapseWhitespace(element.textContent);
995 var result = actual === expected;
996 if (!message) {
997 message = "Element " + this.targetDescription + " has text \"" + expected + "\"";
998 }
999 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
1000 }
1001 else {
1002 throw new TypeError("You must pass a string or Regular Expression to \"hasText\". You passed " + expected + ".");
1003 }
1004 return this;
1005 };
1006 DOMAssertions.prototype.matchesText = function (expected, message) {
1007 return this.hasText(expected, message);
1008 };
1009 /**
1010 * Assert that the `textContent` property of an {@link HTMLElement} is not empty.
1011 *
1012 * @param {string?} message
1013 *
1014 * @example
1015 * assert.dom('button.share').hasAnyText();
1016 *
1017 * @see {@link #hasText}
1018 */
1019 DOMAssertions.prototype.hasAnyText = function (message) {
1020 return this.hasText({ any: true }, message);
1021 };
1022 /**
1023 * Assert that the `textContent` property of an {@link HTMLElement} is empty.
1024 *
1025 * @param {string?} message
1026 *
1027 * @example
1028 * assert.dom('div').hasNoText();
1029 *
1030 * @see {@link #hasNoText}
1031 */
1032 DOMAssertions.prototype.hasNoText = function (message) {
1033 return this.hasText('', message);
1034 };
1035 /**
1036 * Assert that the text of the {@link HTMLElement} or an {@link HTMLElement}
1037 * matching the `selector` contains the given `text`, using the
1038 * [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
1039 * attribute.
1040 *
1041 * > Note: This assertion will collapse whitespace in `textContent` before searching.
1042 * > If you would like to assert on a string that *should* contain line breaks, tabs,
1043 * > more than one space in a row, or starting/ending whitespace, use the {@link #hasText}
1044 * > selector and pass your expected text in as a RegEx pattern.
1045 *
1046 * **Aliases:** `containsText`, `hasTextContaining`
1047 *
1048 * @param {string} text
1049 * @param {string?} message
1050 *
1051 * @example
1052 * assert.dom('#title').includesText('Welcome');
1053 *
1054 * @see {@link #hasText}
1055 */
1056 DOMAssertions.prototype.includesText = function (text, message) {
1057 var element = this.findTargetElement();
1058 if (!element)
1059 return this;
1060 var collapsedText = collapseWhitespace(element.textContent);
1061 var result = collapsedText.indexOf(text) !== -1;
1062 var actual = collapsedText;
1063 var expected = text;
1064 if (!message) {
1065 message = "Element " + this.targetDescription + " has text containing \"" + text + "\"";
1066 }
1067 if (!result && text !== collapseWhitespace(text)) {
1068 console.warn('The `.includesText()`, `.containsText()`, and `.hasTextContaining()` assertions collapse whitespace. The text you are checking for contains whitespace that may have made your test fail incorrectly. Try the `.hasText()` assertion passing in your expected text as a RegExp pattern. Your text:\n' +
1069 text);
1070 }
1071 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
1072 return this;
1073 };
1074 DOMAssertions.prototype.containsText = function (expected, message) {
1075 return this.includesText(expected, message);
1076 };
1077 DOMAssertions.prototype.hasTextContaining = function (expected, message) {
1078 return this.includesText(expected, message);
1079 };
1080 /**
1081 * Assert that the text of the {@link HTMLElement} or an {@link HTMLElement}
1082 * matching the `selector` does not include the given `text`, using the
1083 * [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
1084 * attribute.
1085 *
1086 * **Aliases:** `doesNotContainText`, `doesNotHaveTextContaining`
1087 *
1088 * @param {string} text
1089 * @param {string?} message
1090 *
1091 * @example
1092 * assert.dom('#title').doesNotIncludeText('Welcome');
1093 */
1094 DOMAssertions.prototype.doesNotIncludeText = function (text, message) {
1095 var element = this.findTargetElement();
1096 if (!element)
1097 return this;
1098 var collapsedText = collapseWhitespace(element.textContent);
1099 var result = collapsedText.indexOf(text) === -1;
1100 var expected = "Element " + this.targetDescription + " does not include text \"" + text + "\"";
1101 var actual = expected;
1102 if (!result) {
1103 actual = "Element " + this.targetDescription + " includes text \"" + text + "\"";
1104 }
1105 if (!message) {
1106 message = expected;
1107 }
1108 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
1109 return this;
1110 };
1111 DOMAssertions.prototype.doesNotContainText = function (unexpected, message) {
1112 return this.doesNotIncludeText(unexpected, message);
1113 };
1114 DOMAssertions.prototype.doesNotHaveTextContaining = function (unexpected, message) {
1115 return this.doesNotIncludeText(unexpected, message);
1116 };
1117 /**
1118 * Assert that the `value` property of an {@link HTMLInputElement} matches
1119 * the `expected` text or regular expression.
1120 *
1121 * If no `expected` value is provided, the assertion will fail if the
1122 * `value` is an empty string.
1123 *
1124 * @param {string|RegExp|object?} expected
1125 * @param {string?} message
1126 *
1127 * @example
1128 * assert.dom('input.username').hasValue('HSimpson');
1129
1130 * @see {@link #hasAnyValue}
1131 * @see {@link #hasNoValue}
1132 */
1133 DOMAssertions.prototype.hasValue = function (expected, message) {
1134 var element = this.findTargetElement();
1135 if (!element)
1136 return this;
1137 if (arguments.length === 0) {
1138 expected = { any: true };
1139 }
1140 var value = element.value;
1141 if (expected instanceof RegExp) {
1142 var result = expected.test(value);
1143 var actual = value;
1144 if (!message) {
1145 message = "Element " + this.targetDescription + " has value matching " + expected;
1146 }
1147 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
1148 }
1149 else if (expected.any === true) {
1150 var result = Boolean(value);
1151 var expected_2 = "Element " + this.targetDescription + " has a value";
1152 var actual = result ? expected_2 : "Element " + this.targetDescription + " has no value";
1153 if (!message) {
1154 message = expected_2;
1155 }
1156 this.pushResult({ result: result, actual: actual, expected: expected_2, message: message });
1157 }
1158 else {
1159 var actual = value;
1160 var result = actual === expected;
1161 if (!message) {
1162 message = "Element " + this.targetDescription + " has value \"" + expected + "\"";
1163 }
1164 this.pushResult({ result: result, actual: actual, expected: expected, message: message });
1165 }
1166 return this;
1167 };
1168 /**
1169 * Assert that the `value` property of an {@link HTMLInputElement} is not empty.
1170 *
1171 * @param {string?} message
1172 *
1173 * @example
1174 * assert.dom('input.username').hasAnyValue();
1175 *
1176 * @see {@link #hasValue}
1177 * @see {@link #hasNoValue}
1178 */
1179 DOMAssertions.prototype.hasAnyValue = function (message) {
1180 return this.hasValue({ any: true }, message);
1181 };
1182 /**
1183 * Assert that the `value` property of an {@link HTMLInputElement} is empty.
1184 *
1185 * **Aliases:** `lacksValue`
1186 *
1187 * @param {string?} message
1188 *
1189 * @example
1190 * assert.dom('input.username').hasNoValue();
1191 *
1192 * @see {@link #hasValue}
1193 * @see {@link #hasAnyValue}
1194 */
1195 DOMAssertions.prototype.hasNoValue = function (message) {
1196 return this.hasValue('', message);
1197 };
1198 DOMAssertions.prototype.lacksValue = function (message) {
1199 return this.hasNoValue(message);
1200 };
1201 /**
1202 * Assert that the target selector selects only Elements that are also selected by
1203 * compareSelector.
1204 *
1205 * @param {string} compareSelector
1206 * @param {string?} message
1207 *
1208 * @example
1209 * assert.dom('p.red').matchesSelector('div.wrapper p:last-child')
1210 */
1211 DOMAssertions.prototype.matchesSelector = function (compareSelector, message) {
1212 var targetElements = this.target instanceof Element ? [this.target] : this.findElements();
1213 var targets = targetElements.length;
1214 var matchFailures = matchesSelector(targetElements, compareSelector);
1215 var singleElement = targets === 1;
1216 var selectedByPart = this.target instanceof Element ? 'passed' : "selected by " + this.target;
1217 var actual;
1218 var expected;
1219 if (matchFailures === 0) {
1220 // no failures matching.
1221 if (!message) {
1222 message = singleElement
1223 ? "The element " + selectedByPart + " also matches the selector " + compareSelector + "."
1224 : targets + " elements, selected by " + this.target + ", also match the selector " + compareSelector + ".";
1225 }
1226 actual = expected = message;
1227 this.pushResult({ result: true, actual: actual, expected: expected, message: message });
1228 }
1229 else {
1230 var difference = targets - matchFailures;
1231 // there were failures when matching.
1232 if (!message) {
1233 message = singleElement
1234 ? "The element " + selectedByPart + " did not also match the selector " + compareSelector + "."
1235 : matchFailures + " out of " + targets + " elements selected by " + this.target + " did not also match the selector " + compareSelector + ".";
1236 }
1237 actual = singleElement ? message : difference + " elements matched " + compareSelector + ".";
1238 expected = singleElement
1239 ? "The element should have matched " + compareSelector + "."
1240 : targets + " elements should have matched " + compareSelector + ".";
1241 this.pushResult({ result: false, actual: actual, expected: expected, message: message });
1242 }
1243 return this;
1244 };
1245 /**
1246 * Assert that the target selector selects only Elements that are not also selected by
1247 * compareSelector.
1248 *
1249 * @param {string} compareSelector
1250 * @param {string?} message
1251 *
1252 * @example
1253 * assert.dom('input').doesNotMatchSelector('input[disabled]')
1254 */
1255 DOMAssertions.prototype.doesNotMatchSelector = function (compareSelector, message) {
1256 var targetElements = this.target instanceof Element ? [this.target] : this.findElements();
1257 var targets = targetElements.length;
1258 var matchFailures = matchesSelector(targetElements, compareSelector);
1259 var singleElement = targets === 1;
1260 var selectedByPart = this.target instanceof Element ? 'passed' : "selected by " + this.target;
1261 var actual;
1262 var expected;
1263 if (matchFailures === targets) {
1264 // the assertion is successful because no element matched the other selector.
1265 if (!message) {
1266 message = singleElement
1267 ? "The element " + selectedByPart + " did not also match the selector " + compareSelector + "."
1268 : targets + " elements, selected by " + this.target + ", did not also match the selector " + compareSelector + ".";
1269 }
1270 actual = expected = message;
1271 this.pushResult({ result: true, actual: actual, expected: expected, message: message });
1272 }
1273 else {
1274 var difference = targets - matchFailures;
1275 // the assertion fails because at least one element matched the other selector.
1276 if (!message) {
1277 message = singleElement
1278 ? "The element " + selectedByPart + " must not also match the selector " + compareSelector + "."
1279 : difference + " elements out of " + targets + ", selected by " + this.target + ", must not also match the selector " + compareSelector + ".";
1280 }
1281 actual = singleElement
1282 ? "The element " + selectedByPart + " matched " + compareSelector + "."
1283 : matchFailures + " elements did not match " + compareSelector + ".";
1284 expected = singleElement
1285 ? message
1286 : targets + " elements should not have matched " + compareSelector + ".";
1287 this.pushResult({ result: false, actual: actual, expected: expected, message: message });
1288 }
1289 return this;
1290 };
1291 /**
1292 * Assert that the tagName of the {@link HTMLElement} or an {@link HTMLElement}
1293 * matching the `selector` matches the `expected` tagName, using the
1294 * [`tagName`](https://developer.mozilla.org/en-US/docs/Web/API/Element/tagName)
1295 * property of the {@link HTMLElement}.
1296 *
1297 * @param {string} expected
1298 * @param {string?} message
1299 *
1300 * @example
1301 * // <h1 id="title">
1302 * // Title
1303 * // </h1>
1304 *
1305 * assert.dom('#title').hasTagName('h1');
1306 */
1307 DOMAssertions.prototype.hasTagName = function (tagName, message) {
1308 var element = this.findTargetElement();
1309 var actual;
1310 var expected;
1311 if (!element)
1312 return this;
1313 if (typeof tagName !== 'string') {
1314 throw new TypeError("You must pass a string to \"hasTagName\". You passed " + tagName + ".");
1315 }
1316 actual = element.tagName.toLowerCase();
1317 expected = tagName.toLowerCase();
1318 if (actual === expected) {
1319 if (!message) {
1320 message = "Element " + this.targetDescription + " has tagName " + expected;
1321 }
1322 this.pushResult({ result: true, actual: actual, expected: expected, message: message });
1323 }
1324 else {
1325 if (!message) {
1326 message = "Element " + this.targetDescription + " does not have tagName " + expected;
1327 }
1328 this.pushResult({ result: false, actual: actual, expected: expected, message: message });
1329 }
1330 return this;
1331 };
1332 /**
1333 * Assert that the tagName of the {@link HTMLElement} or an {@link HTMLElement}
1334 * matching the `selector` does not match the `expected` tagName, using the
1335 * [`tagName`](https://developer.mozilla.org/en-US/docs/Web/API/Element/tagName)
1336 * property of the {@link HTMLElement}.
1337 *
1338 * @param {string} expected
1339 * @param {string?} message
1340 *
1341 * @example
1342 * // <section id="block">
1343 * // Title
1344 * // </section>
1345 *
1346 * assert.dom('section#block').doesNotHaveTagName('div');
1347 */
1348 DOMAssertions.prototype.doesNotHaveTagName = function (tagName, message) {
1349 var element = this.findTargetElement();
1350 var actual;
1351 var expected;
1352 if (!element)
1353 return this;
1354 if (typeof tagName !== 'string') {
1355 throw new TypeError("You must pass a string to \"doesNotHaveTagName\". You passed " + tagName + ".");
1356 }
1357 actual = element.tagName.toLowerCase();
1358 expected = tagName.toLowerCase();
1359 if (actual !== expected) {
1360 if (!message) {
1361 message = "Element " + this.targetDescription + " does not have tagName " + expected;
1362 }
1363 this.pushResult({ result: true, actual: actual, expected: expected, message: message });
1364 }
1365 else {
1366 if (!message) {
1367 message = "Element " + this.targetDescription + " has tagName " + expected;
1368 }
1369 this.pushResult({ result: false, actual: actual, expected: expected, message: message });
1370 }
1371 return this;
1372 };
1373 /**
1374 * @private
1375 */
1376 DOMAssertions.prototype.pushResult = function (result) {
1377 this.testContext.pushResult(result);
1378 };
1379 /**
1380 * Finds a valid HTMLElement from target, or pushes a failing assertion if a valid
1381 * element is not found.
1382 * @private
1383 * @returns (HTMLElement|null) a valid HTMLElement, or null
1384 */
1385 DOMAssertions.prototype.findTargetElement = function () {
1386 var el = this.findElement();
1387 if (el === null) {
1388 var message = "Element " + (this.target || '<unknown>') + " should exist";
1389 this.pushResult({ message: message, result: false, actual: undefined, expected: undefined });
1390 return null;
1391 }
1392 return el;
1393 };
1394 /**
1395 * Finds a valid HTMLElement from target
1396 * @private
1397 * @returns (HTMLElement|null) a valid HTMLElement, or null
1398 * @throws TypeError will be thrown if target is an unrecognized type
1399 */
1400 DOMAssertions.prototype.findElement = function () {
1401 if (this.target === null) {
1402 return null;
1403 }
1404 else if (typeof this.target === 'string') {
1405 return this.rootElement.querySelector(this.target);
1406 }
1407 else if (this.target instanceof Element) {
1408 return this.target;
1409 }
1410 else {
1411 throw new TypeError("Unexpected Parameter: " + this.target);
1412 }
1413 };
1414 /**
1415 * Finds a collection of Element instances from target using querySelectorAll
1416 * @private
1417 * @returns (Element[]) an array of Element instances
1418 * @throws TypeError will be thrown if target is an unrecognized type
1419 */
1420 DOMAssertions.prototype.findElements = function () {
1421 if (this.target === null) {
1422 return [];
1423 }
1424 else if (typeof this.target === 'string') {
1425 return toArray(this.rootElement.querySelectorAll(this.target));
1426 }
1427 else if (this.target instanceof Element) {
1428 return [this.target];
1429 }
1430 else {
1431 throw new TypeError("Unexpected Parameter: " + this.target);
1432 }
1433 };
1434 Object.defineProperty(DOMAssertions.prototype, "targetDescription", {
1435 /**
1436 * @private
1437 */
1438 get: function () {
1439 return elementToString(this.target);
1440 },
1441 enumerable: false,
1442 configurable: true
1443 });
1444 return DOMAssertions;
1445 }());
1446
1447 var _getRootElement = function () { return null; };
1448 function overrideRootElement(fn) {
1449 _getRootElement = fn;
1450 }
1451 function getRootElement() {
1452 return _getRootElement();
1453 }
1454
1455 function install (assert) {
1456 assert.dom = function (target, rootElement) {
1457 if (!isValidRootElement(rootElement)) {
1458 throw new Error(rootElement + " is not a valid root element");
1459 }
1460 rootElement = rootElement || this.dom.rootElement || getRootElement();
1461 if (arguments.length === 0) {
1462 target = rootElement instanceof Element ? rootElement : null;
1463 }
1464 return new DOMAssertions(target, rootElement, this);
1465 };
1466 function isValidRootElement(element) {
1467 return (!element ||
1468 (typeof element === 'object' &&
1469 typeof element.querySelector === 'function' &&
1470 typeof element.querySelectorAll === 'function'));
1471 }
1472 }
1473
1474 function setup(assert, options) {
1475 if (options === void 0) { options = {}; }
1476 install(assert);
1477 var getRootElement = typeof options.getRootElement === 'function'
1478 ? options.getRootElement
1479 : function () { return document.querySelector('#ember-testing'); };
1480 overrideRootElement(getRootElement);
1481 }
1482
1483 /* global QUnit */
1484 install(QUnit.assert);
1485
1486 exports.setup = setup;
1487
1488 Object.defineProperty(exports, '__esModule', { value: true });
1489
1490 return exports;
1491
1492}({}));
1493//# sourceMappingURL=qunit-dom.js.map