@jarmee/jest-dom-custom-matchers v1.0.0
In This Documentation
Description
How does jasmine-dom-custom-matchers work?
A custom matchers syntax has changed with the release of jasmine 2.0. This library provides 19 custom matchers adapted to the new way of matchers constructing. It allows you to compare DOM Objects relations and states.
What can I use jasmine-dom-custom-matchers for?
- to check if the actual parameter is HTML Element [see below]
- to check if the actual parameter is HTML Text [see below]
- to check if the HTML Element or HTML Text is appended to the document [see below]
- to check if the expected HTML Element is a descendant of actual HTML Element [see below]
- to check if actual HTML Element or its HTML Element descendants contain expected text [see below]
- to check if expected Node is a child of actual Node [see below]
- to check if actual is n-th child of its parent [see below]
- to check if expected Node is a parent of actual Node [see below]
- to check i actual and expected nodes have got the same HTML Element parent [see below]
- to check if actual HTML Element has got any HTML Element children [see below]
- to check if actual HTML Element is the next sibling of expected HTML Element [see below]
- to check if actual HTML Element is the previous sibling of expected HTML Element [see below]
- to check if HTML Element is empty (has not got any HTML ELement and HTML Text nodes) [see below]
- to check if HTML Element has got any attributes defined [see below]
- to check if HTML Element has got expected attribute (or expected attribute of expected value) [see below]
- to check if HTML Element has got expected class [see below]
- to check if HTML Element (DOM node) has got expected style (computed style) [see below]
- to check if HTML Element (DOM node) has got expected color (computed style) [see below]
- to check if HTML Element has got expected event attached [see below]
DOM Custom Matchers list
expect(actual).toBeHTMLElement(name)[see below]expect(actual).toBeHTMLText(content)[see below]expect(actual).toBeDocumentNode()[see below]expect(actual).toContainHTMLElement(descendant)[see below]expect(actual).toContainText(content)[see below]expect(actual).toBeChildOf(parent)[see below]expect(actual).toBeNthChild(index)[see below]expect(actual).toBeParentOf(child)[see below]expect(actual).toHaveSameParent(node)[see below]expect(actual).toHaveChildren(numOfChildren)[see below]expect(actual).toBeNextSiblingOf(expected)[see below]expect(actual).toBePreviousSiblingOf(expected)[see below]expect(actual).toBeEmpty()[see below]expect(actual).toHaveAnyAttribute()[see below]expect(actual).toHaveAttribute(name,value)[see below]expect(actual).toHaveClass(class)[see below]expect(actual).toHaveComputedStyle(prop,value)[see below]expect(actual).toHaveComputedColor(prop,value)[see below]expect(actual).toHaveEvent(event)[see below]
Where can I check how jasmine-dom-custom-matchers work?
Examine the Samples described below to find out how you can use DOM custom matchers.
Browser Support
| Chrome | Firefox | IE | Edge | Safari | Opera | iOS Safari | Opera Mini |
|---|---|---|---|---|---|---|---|
| 4+ | 2+ | 9-11 | 12+ | 3.1+ | 9+ | 3.2+ | all |
Methods
expect(actual).toBeHTMLElement(name)
- check if
actualis HTML Element Object. nameparameter is optionalnameparameter if passed, must be of type Stringnameparameter if passed, the matcher checks ifactualis a HTML Element Object of expected tag namenamenameparameter if passed but not of type String, is ignored as if it was not passed (matcher checks ifactualis HTML Element Object regardless its tag name)- returns false if
actualis not the HTML Element Object - returns false if
actualis HTML Element Object but of not expected tag namename(if passed) - return true if
actualis HTML Element Object - return true if
actualis HTML Element Object of expectedname(if passed) - return true regardless
actualHTML Element Object is appended to the DOM or not
expect(actual).toBeHTMLText(content)
- check if
actualis HTML Text Object. contentparameter is optionalcontentparameter if passed, must be of type String or RegExp- if the
contentis of type String the matcher checks the equality of theactualtext content and expectedcontent - if the
contentis of type RegExp the matcher use String.prototype.match() to check if theactualtext content matches the expectedcontentregular expression contentparameter if passed but not of type String or RegExp, is ignored as if it was not passed (matcher checks ifactualis HTML Text Object regardless its content)- returns false if
actualis not the HTML Text Object - returns false if
actualis HTML Text Object but does not match expectedcontent(if passed) - return true if
actualis HTML Text Object - return true if both
actualis HTML Text Object and matches expectedcontent(if passed) - return true regardless
actualHTML Text Object is appended to the DOM or not
expect(actual).toBeDocumentNode()
- check if
actualis a HTML Element Object or HTML Text Object appended into DOM Tree - return false if
actualis not HTML Element Object or HTML Text Object or if it is not appended into DOM Tree - returns true if
actualis HTML Element Object or HTML Text Object appended into DOM Tree
expect(actual).toContainHTMLElement(descendant)
- check if
actualHTML Element contains expecteddescendant - both
actualanddescendantmust be HTML Element Object - return false if
actualordescendantis not the HTML Element Object - return false if
actualdoes not containdescendant - return false if
actualanddescendantis the same object - return true if
descendantis a child node ofactual - return true if
descendantis a farther descendant ofactual - return true regardless
actualHTML Element Object and its expected descendant are appended to the DOM or not
expect(actual).toContainText(content)
- check if
actualHTML Element Object and all its descendants contain or match expected textualcontent contentmust be of type String or RegEx- if
actualcontains multiple of HTML Text descendants, it is normalized (empty HTML Text nodes and multi spaces are removed from the text) before being compared with expectedcontenttext - return false if
actualis not HTML Element Object or ifcontentis not of type String or RegEx - return false if
actualdoes not contain or match the text or regular expression passed incontent - return true if
actualcontains or matches the text or regular expression passed incontent - return true regardless
actualHTML Element Object is appended to the DOM or not
to check whether the HTML Text Object equals text content, use
toBeHTMLText(content)with expected textcontent
expect(actual).toBeChildOf(parent)
- check if
actualHTML Element Object or HTML Text Object is a children ofparentHTML Element Object - return false if
actualis not HTML Element Object or HTML Text Object - return false if
parentis not HTML Element Object - return false if
actualis not a direct child node ofparent - return false if
actualandparentis the same object - return true if
actualis the direct child node ofparent - return true regardless
actualandparentare appended to the DOM or not
expect(actual).toBeNthChild(index)
- check if
actualHTML Element Object has expectedindexin the collection of child nodes ofactual's parent HTML Element Object indexmust be of type Number equal or greater than0or of the String value:lastexpect(actual).toBeNthChild(0)the matcher checks ifactualis the first child node of its parentexpect(actual).toBeNthChild(1)the matcher checks ifactualis the second child node of its parentexpect(actual).toBeNthChild('last')the matcher checks ifactualis the last child node of its parent- it ignores HTML Text and HTML Comment Objects when getting the collection od child nodes
- return false if
actualis not HTML Element Object - return false if
indexis not of type Number greater than 0 or if is not of'last'value - return false if
actualis not at expectedindexinside its HTML Element parent - return false if
actualhas not got HTML Element parent - return true if
actualis at expectedindexinside its HTML Element parent - return true regardless
actualand its HTML Element parent are appended to the DOM or not
expect(actual).toBeParentOf(child)
- check if
actualHTML Element Object is a parent ofchildHTML Element Object or HTML Text Object - return false if
actualis not HTML Element Object - return false if
childis not HTML Element Object or HTML Text Object - return false if
actualis not a direct parent node ofchild - return false if
actualandchildis the same object - return true if
actualis the direct parent node ofchild - return true regardless
actualandchildare appended to the DOM or not
expect(actual).toHaveSameParent(node)
- check if
actualandnodeare the children of the same HTML Element Object actualandnodemust be of type HTML Element or HTML Text- return false if
actualornodeis not HTML Element or HTML Text Object - return false if
actualandnodeare not the children of the same HTML Element Object - return true if
actualandnodeare the children of the same HTML Element Object - return true regardless
actualandnodeare appended to the DOM or not
expect(actual).toHaveChildren(numOfChildren,operator)
- check if
actualHTML Element Object contains any HTML Element child nodes - it ignores HTML Text and HTML Comment Objects
numOfChildrenis optional, if passed must be of type Number equal or greater than0numOfChildren, if passed the matcher checks if the number ofactualchild nodes equals to expectednumOfChildren- if
numOfChildrenis not of type Number or is less than0, it is ignored as if it was not passed operatoris optional, if passed must be the one of following String values:or more,or less,more than,less thanexpect(actual).toHaveChildren(3)the matcher checks ifactualhas got 3 element nodesexpect(actual).toHaveChildren(3,'or more')the matcher checks ifactualhas got 3 or more than 3 element nodesexpect(actual).toHaveChildren(3,'or less')the matcher checks ifactualhas got 3 or less than 3 element nodesexpect(actual).toHaveChildren(3,'more than')the matcher checks ifactualhas got more than 3 element nodesexpect(actual).toHaveChildren(3,'less than')the matcher checks ifactualhas got less than 3 element nodes- if
operatoris not the one of indicated four values, it is ignored as if it was not passed - return false if
actualis not HTML Element Object - return false if
actualdoes not contain any HTML Element child nodes (ifnumOfChildrennot passed) - return false if
actualdoes not contain expected number of HTML Element child nodes (ifnumOfChildren|operatorpassed) - return true if
actualcontains at least one HTML Element child node (ifnumOfChildrennot passed) - return true if
actualcontains expected number of HTML Element child nodes (ifnumOfChildren|operatorpassed) - return true regardless
actualHTML Element Object is appended to the DOM or not
expect(actual).toBeNextSiblingOf(expected)
- check if
actualHTML Element Object is the next element sibling ofexpectedHTML Element Object - both
actualandexpectedmust be of type HTML Element - it ignores HTML Text and HTML Comment sibling Objects
- return false if
actualorexpectedis not HTML Element Object - return false if
actualis not the next element sibling ofexpected - return false if
expectedhas not got any next element sibling - return true if
actualis the next element sibling ofexpected - return true regardless
actualandexpectedis appended to the DOM or not
expect(actual).toBePreviousSiblingOf(expected)
- check if
actualHTML Element Object is the previous element sibling ofexpectedHTML Element Object - both
actualandexpectedmust be of type HTML Element - it ignores HTML Text and HTML Comment sibling Objects
- return false if
actualorexpectedis not HTML Element Object - return false if
actualis not the previous element sibling ofexpected - return false if
expectedhas not got any previous element sibling - return true if
actualis the previous element sibling ofexpected - return true regardless
actualandexpectedis appended to the DOM or not
expect(actual).toBeEmpty()
- check if
actualHTML Element Object has not got any HTML Element or HTML Text child nodes - it ignores HTML Comment Objects, empty text nodes, <br/> and <wbr/> tags
- return false if
actualis not HTML Element Object - return false if
actualcontains at least one HTML Element Object or HTML Text Object - return true if
actualhas not got any HTML Element or HTML Text descendant - return true regardless
actualHTML Element Object is appended to the DOM or not
the difference between .toBeEmpty() matcher and .toHaveChildren() matcher is that .toBeEmpty() matcher checks if the actual HTML Element Object contains both HTML Element and HTML Text Objects when .toHaveChildren() matcher checks if the actual HTML Element Object contains only HTML Element Objects.
expect(actual).toHaveAnyAttribute()
- check if
actualHTML Element Object has got any attribute defined - return false if
actualis not HTML Element Object - return false if
actualis has not got any attribute defined - return true if
actualis has got at least one attribute defined
expect(actual).toHaveAttribute(name,value)
- check if
actualHTML Element Object has expected attributenameof expectedvalue namemust be of type Stringvalueparameter is optional, if not passed, matcher checks ifactualhas expected attributenameregardless its valuevalueparameter if passed, must be of type String or of type RegExp- if
valueis not of type String or of type RegExp, it is ignored as if it was not passed (matcher checks ifactualhas expected attributenameregardless its value) - if the
valueis of type String the matcher checks the equality of attribute's value and expectedvalue - if the
valueis of type RegExp the matcher useString.prototype.match()to check if the attribute's value matches the expected regular expressionvalue - return false if
actualis not HTML Element Object or ifnameis not of type String - return false if
actualdoes not have expected attributename(ifvaluenot passed) - return false if
actualdoes not have expected attributenameof expectedvalue(ifvaluepassed) - return true if
actualhas expected attributename(ifvaluenot passed) - return true if
actualhas expected attributenameof expected valuevalue(ifvaluepassed) - return true regardless
actualis appended to the DOM or not
with appropriate /regular expression/ passed as
valueparameter it is possible to check whether class attribute contains expected class, but it is easier to achieve with .toHaveClass() custom matcher
expect(actual).toHaveClass(class)
- check if
actualHTML Element Object has got class attribute with expected valueclassfrom among the list of classes classmust be of type String- return false if
actualis not HTML Element Object or ifclassis not of type String - return false if
actualhas not got expectedclassset - return true if
actualhas got expectedclassset - return true regardless
actualis appended to the DOM or not
to check whether HTML Element Object has got a class attribute defined regardless its values, use
.toHaveAttribute('class')matcher
expect(actual).toHaveComputedStyle(prop,value)
- check if
actualHTML Element Object's computedpropstyle is of expectedvalue actualmust be appended into the DOM tree, so that the CSSStyleDeclaration Object could be returnedpropmust be of type String (both camelCase and hyphen-case are accepted)valuemust be of type String or RegExp- if the
valueis of type String the matcher checks the equality of the computed style's value and expectedvalue - if the
valueis of type RegExp the matcher useString.prototype.match()to check if the computed style's value matches the expectedvalueregular expression - return false if
actualis not HTML Element Object orpropis not of type String orvalueis not of type String or RegExp - return false if returned CSSStyleDeclaration Object has not contain
propproperty - return false if
actualhas got the computedpropstyle of the different value than expectedvalue - return true if
actualhas got the computedpropstyle of the same value as expected Stringvalueor if computedpropstyle matches expected RegExpvalue
in order to deal with the differences between browsers of returning computed style values, use regular expression
.toHaveComputedStyle('propertyName',/(ms-value|moz-value|webkit-value)/)
expect(actual).toHaveComputedColor(prop,value)
- check if
actualHTML Element Object's computedpropstyle is of expectedvalue - the difference between
toHaveComputedStyle()andtoHaveComputedColor()is thattoHaveComputedColor()is convenient to compare each CSS*-colorproperty, which demand or return color value (background-color,border-bottom-color,color,box-shadow,text-shadow,outline-color, etc.) - the convenience is that you can expect the color
valuein the format of your choice (#HEXRGB()orHSL()), regardless which format the browser return as computed actualmust be appended into the DOM tree, so that the CSSStyleDeclaration Object could be returnedpropmust be of type String (both camelCase and hyphen-case are accepted)valuemust be of type String (in order to use RegExp value, use matchertoHaveComputedStyle('colorProp',/regEx/))- return false if
actualis not HTML Element Object orpropis not of type String orvalueis not of type String - return false if returned CSSStyleDeclaration Object has not contain
propproperty - return false if
actualcomputedpropstyle does not match expectedvaluecolor - return true if
actualcomputedpropstyle matches expectedvaluecolor
If the browser return
rgb(255, 255, 0) 2px 2px 2pxas computed 'box-shadow' style, the expectedvaluergb(255, 255, 0),rgba(255, 255, 0, 1),#ff0,#FFFF00,hsl(60, 100%, 50%)andhsla(60, 100%, 50%, 1)will return truthy result.If the browser return
rgba(255, 255, 0, .4)as computed 'color' style, the expectedvaluergba(255, 255, 0, .4)andhsla(60, 100%, 50%, .4)will return truthy result.If the browser return
rgba(255, 255, 0, .4)as computed 'color' style, the expectedvaluergb(255, 255, 0),#ff0,#FFFF00andhsl(60, 100%, 50%)will return faulty result because the alpha parameter does not match.Because of the differences between browsers, the
alphaparameter ofhsla()andrgba()formats is rounded to two digits after decimal point. The same result will be aimed withrgba(100, 100, 100, 0.23),rgba(100, 100, 100, 0.230445),rgba(100, 100, 100, 0.2349999999)
expect(actual).toHaveEvent(event)
- check if
actualHTML Element Object has got expectedeventattached - it does not detect events attached by
addEventListener()method - <div onclick='fireClick'></div> this event will be detected
actual.onclick = fireClickthis event will be detectedactual.addEventListener('click',fireClick)this event will not be detectedeventmust be of type String and must indicate expected event name, eg.click,mouseover,focuson,resize(bothclickand prefixedonclicksyntax accepted)- return false if
actualis not HTML Element Object oreventis not of type String - return false if
eventis not recognized event name - return false if
actualhas not got expectedeventattached - return false if
actualhas got expectedeventattached by theaddEventListener()method - return true if
actualhas got expectedeventattached - return true regardless
actualis appended to the DOM or not
Tips
Each matcher demands accurate type of parameter value. The matcher check the
actualandexpectedparameters' types before implementing the comparison and return false when value type is incorrect regardless the comparison result.Compared HTML Element and HTML Text Objects do not have to be appended to the DOM tree in order to use DOM custom matcher. The comparison can be implemented for dynamically created elements in
beforeEach(),beforeAll()orit()scope. Exception is.toBeDocumentNode()matcher which check ifactualObject is appended to the DOM and.toHaveComputedStyle().toHaveComputedColor()matchers which require the HTML Element Object to be appended to the DOM in order to return the expected computed styleIn order to check whether two HTML Objects are the same objects use the native matcher
expect(objectA).toBe(objectB)In order to check whether two HTML Objects are equal objects use the native matcher
expect(objectA).toEqual(objectB)
Implementation
with NodeJS
npm install jasmine-dom-custom-matchers --save-dev
var matchers = require('jasmine-dom-custom-matchers'); //get the module
describe("The new DIV element", function() {
beforeAll(function() {
jasmine.addMatchers(matchers); //set custom matchers for jasmine
this.newDiv = document.createElement('DIV');
});
it("should be empty.", function() {
expect(this.newDiv).toBeEmpty(); //do the magic with new DOM matchers
});
}You can use
karma-htmlmodule to test your.htmlfiles in thekarmabrowser runner [git] [npm]
with Karma
Use karma-jasmine-dom package [link] that adapts the jasmine-dom-custom-matchers package for karma.
with Browser
1. Load dom-matchers.js in html file
<head>
<link rel="shortcut icon" type="image/png" href="jasmine/lib/jasmine-core/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="jasmine/lib/jasmine-core/jasmine.css">
<script type="text/javascript" src="jasmine/lib/jasmine-core/jasmine.js"></script>
<script type="text/javascript" src="jasmine/lib/jasmine-core/jasmine-html.js"></script>
<script type="text/javascript" src="jasmine/lib/jasmine-core/boot.js"></script>
<script type="text/javascript" src="dom-matchers.js"></script>
</head>Any outer libraries needed. It is a fully JavaScript library.
2. Load custom matchers with jasmine.addMatchers in your tests files
describe("The new DIV element", function() {
beforeAll(function() {
//DOMCustomMatchers is the global window object got from dom-matchers.js
jasmine.addMatchers(DOMCustomMatchers);
this.newDiv = document.createElement('DIV');
});
it("should be empty.", function() {
expect(this.newDiv).toBeEmpty(); //do the magic with new DOM matchers
});
}How to use
- visit sample site and consider jasmine passed specs section (you can see how DOM custom matchers can be used)
- consider the HTML source with the login panel sample
- consider the <style> section with CSS styles for login panel
- consider the tests.js source to figure out how matchers were implemented
See also
karma-htmlto test your.htmlfiles in thekarmabrowser runner [git] [npm]karma-jasmine-dompackage to usejasmine-dom-custom-matcherswith karma [npm]jasminecustom matchers docs [link]jasmineinstallation [link]
License
Released under the MIT license.
Copyright (c) 2017 Paweł Rafałko dev.rafalko@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 years ago