1 | Chai-jQ
|
2 | =======
|
3 |
|
4 | `chai-jq` is an alternate plugin for the [Chai](http://chaijs.com/) assertion
|
5 | library to provide jQuery-specific assertions.
|
6 |
|
7 | ## Usage
|
8 |
|
9 | You can install `chai-jq` with the following package managers:
|
10 |
|
11 | * [NPM](https://npmjs.org/package/chai-jq): `npm install chai-jq`
|
12 | * [Bower](http://bower.io/): `bower install chai-jq`
|
13 |
|
14 | The [integration notes](#integration) discuss how to properly patch Chai with
|
15 | the plugin in different environments (browser, AMD, Node.js). The
|
16 | [API documentation](#plugin-api) is a good starting point to learn how to use
|
17 | `chai-jq` assertions in your tests.
|
18 | The site's own test suites also provide a decent introduction to the API:
|
19 |
|
20 | * [Basic Tests](./test/test.html)
|
21 | * [AMD Tests](./test/test-amd.html)
|
22 |
|
23 | ## Assertions
|
24 |
|
25 | ### Integration
|
26 |
|
27 | `chai-jq` works in your browser, with AMD/RequireJS, and in Node.js with
|
28 | JsDom.
|
29 |
|
30 | **Standard Browser**: To use in a standard HTML page, include `chai-jq.js`
|
31 | after Chai.
|
32 |
|
33 | ```html
|
34 | <script src="chai.js"></script>
|
35 | <script src="chai-jq.js"></script>
|
36 | ```
|
37 |
|
38 | **AMD Browser**: To use in a RequireJS/AMD page, require in `chai-jq` and
|
39 | inject it into Chai before your test imports / runners begin:
|
40 |
|
41 | ```js
|
42 | require(["chai", "chai-jq"], function (chai, plugin) {
|
43 | // Inject plugin.
|
44 | chai.use(plugin);
|
45 |
|
46 | // Rest of your test code here...
|
47 | });
|
48 | ```
|
49 |
|
50 | **Node.js / JsDom**: To use in Node.js/JsDom, require in `chai-jq` and
|
51 | inject it into Chai before your test imports / runners begin:
|
52 |
|
53 | ```js
|
54 | var chai = require("chai");
|
55 | var plugin = require("chai-jq");
|
56 |
|
57 | // Inject plugin.
|
58 | chai.use(plugin);
|
59 |
|
60 | // Rest of test code here...
|
61 | ```
|
62 |
|
63 | ### Object Context Changes
|
64 |
|
65 | One slight difference from how assertions in `chai-jq` work from Chai and other
|
66 | plugins is the switching of object context for certain assertions, currently:
|
67 |
|
68 | * `$attr`
|
69 | * `$prop`
|
70 |
|
71 | In general usage, the object under test (e.g., the thing wrapped in an
|
72 | `expect()`) remains the current context, so you can do something like:
|
73 |
|
74 | ```js
|
75 | var $elem = $("<div id=\"hi\" foo=\"bar time\" />");
|
76 |
|
77 | expect($elem)
|
78 | // Assertion object is `$elem`
|
79 | .to.have.$attr("id", "hi").and
|
80 | // Assertion object is still `$elem`
|
81 | .to.contain.$attr("foo", "bar");
|
82 | ```
|
83 |
|
84 | In the above example, the jQuery object `$elem` remains the object under
|
85 | assertion for both `$attr` calls. However, in the special case for one of the
|
86 | enumerated assertions above where:
|
87 |
|
88 | * There is no **expected** assertion value given; **and**,
|
89 | * There are no negations (e.g., `not`) used in a chain.
|
90 |
|
91 | Then, the object under assertion switches to the **value** of the effective
|
92 | method called. So, taking our example again, and calling `$attr()` without
|
93 | an expected value, we would have:
|
94 |
|
95 | ```js
|
96 | var $elem = $("<div id=\"hi\" foo=\"bar time\" />");
|
97 |
|
98 | expect($elem)
|
99 | // Assertion object is `$elem`
|
100 | .to.have.$attr("foo").and
|
101 | // Assertion object now changed to `$attr()` value: `"bar time"`
|
102 | .to.equal("bar time").and
|
103 | .to.match(/^b/).and
|
104 | .to.not.have.length(2);
|
105 | ```
|
106 |
|
107 | In the above example here, the object under assertion becomes the string
|
108 | `"bar time"` immediately after the call to `$attr("foo")` with no expected
|
109 | value.
|
110 |
|
111 |
|
112 | ## Plugin API
|
113 |
|
114 | * [`$visible`](#-visible)
|
115 | * [`$hidden`](#-hidden)
|
116 | * [`$val(expected, [message])`](#-val-expected-message-)
|
117 | * [`$class(expected, [message])`](#-class-expected-message-)
|
118 | * [`$attr(name, [expected], [message])`](#-attr-name-expected-message-)
|
119 | * [`$data(name, [expected], [message])`](#-data-name-expected-message-)
|
120 | * [`$prop(name, [expected], [message])`](#-prop-name-expected-message-)
|
121 | * [`$html(expected, [message])`](#-html-expected-message-)
|
122 | * [`$text(expected, [message])`](#-text-expected-message-)
|
123 | * [`$css(expected, [message])`](#-css-expected-message-)
|
124 |
|
125 | ### `$visible`
|
126 |
|
127 | Asserts that the element is visible.
|
128 |
|
129 | *Node.js/JsDom Note*: JsDom does not currently infer zero-sized or
|
130 | hidden parent elements as hidden / visible appropriately.
|
131 |
|
132 | ```js
|
133 | expect($("<div> </div>"))
|
134 | .to.be.$visible;
|
135 | ```
|
136 |
|
137 | See: [http://api.jquery.com/visible-selector/](http://api.jquery.com/visible-selector/)
|
138 |
|
139 | ### `$hidden`
|
140 |
|
141 | Asserts that the element is hidden.
|
142 |
|
143 | *Node.js/JsDom Note*: JsDom does not currently infer zero-sized or
|
144 | hidden parent elements as hidden / visible appropriately.
|
145 |
|
146 | ```js
|
147 | expect($("<div style=\"display: none\" />"))
|
148 | .to.be.$hidden;
|
149 | ```
|
150 |
|
151 | See: [http://api.jquery.com/hidden-selector/](http://api.jquery.com/hidden-selector/)
|
152 |
|
153 | ### `$val(expected, [message])`
|
154 | * **expected** (`String|RegExp`) value
|
155 | * **message** (`String`) failure message (_optional_)
|
156 |
|
157 | Asserts that the element value matches a string or regular expression.
|
158 |
|
159 | ```js
|
160 | expect($("<input value='foo' />"))
|
161 | .to.have.$val("foo").and
|
162 | .to.have.$val(/^foo/);
|
163 | ```
|
164 |
|
165 | See: [http://api.jquery.com/val/](http://api.jquery.com/val/)
|
166 |
|
167 | ### `$class(expected, [message])`
|
168 | * **expected** (`String`) class name
|
169 | * **message** (`String`) failure message (_optional_)
|
170 |
|
171 | Asserts that the element has a class match.
|
172 |
|
173 | ```js
|
174 | expect($("<div class='foo bar' />"))
|
175 | .to.have.$class("foo").and
|
176 | .to.have.$class("bar");
|
177 | ```
|
178 |
|
179 | See: [http://api.jquery.com/hasClass/](http://api.jquery.com/hasClass/)
|
180 |
|
181 | ### `$attr(name, [expected], [message])`
|
182 | * **name** (`String`) attribute name
|
183 | * **expected** (`String`) attribute content (_optional_)
|
184 | * **message** (`String`) failure message (_optional_)
|
185 | * **_returns_** current object or attribute string value
|
186 |
|
187 | Asserts that the target has exactly the given named attribute, or
|
188 | asserts the target contains a subset of the attribute when using the
|
189 | `include` or `contain` modifiers.
|
190 |
|
191 | ```js
|
192 | expect($("<div id=\"hi\" foo=\"bar time\" />"))
|
193 | .to.have.$attr("id", "hi").and
|
194 | .to.contain.$attr("foo", "bar");
|
195 | ```
|
196 |
|
197 | Changes context to attribute string *value* when no expected value is
|
198 | provided:
|
199 |
|
200 | ```js
|
201 | expect($("<div id=\"hi\" foo=\"bar time\" />"))
|
202 | .to.have.$attr("foo").and
|
203 | .to.equal("bar time").and
|
204 | .to.match(/^b/);
|
205 | ```
|
206 |
|
207 | See: [http://api.jquery.com/attr/](http://api.jquery.com/attr/)
|
208 |
|
209 | ### `$data(name, [expected], [message])`
|
210 | * **name** (`String`) data-attribute name
|
211 | * **expected** (`String`) data-attribute content (_optional_)
|
212 | * **message** (`String`) failure message (_optional_)
|
213 | * **_returns_** current object or attribute string value
|
214 |
|
215 | Asserts that the target has exactly the given named
|
216 | data-attribute, or asserts the target contains a subset
|
217 | of the data-attribute when using the
|
218 | `include` or `contain` modifiers.
|
219 |
|
220 | ```js
|
221 | expect($("<div data-id=\"hi\" data-foo=\"bar time\" />"))
|
222 | .to.have.$data("id", "hi").and
|
223 | .to.contain.$data("foo", "bar");
|
224 | ```
|
225 |
|
226 | Changes context to data-attribute string *value* when no
|
227 | expected value is provided:
|
228 |
|
229 | ```js
|
230 | expect($("<div data-id=\"hi\" data-foo=\"bar time\" />"))
|
231 | .to.have.$data("foo").and
|
232 | .to.equal("bar time").and
|
233 | .to.match(/^b/);
|
234 | ```
|
235 |
|
236 | See: [http://api.jquery.com/data/](http://api.jquery.com/data/)
|
237 |
|
238 | ### `$prop(name, [expected], [message])`
|
239 | * **name** (`String`) property name
|
240 | * **expected** (`Object`) property value (_optional_)
|
241 | * **message** (`String`) failure message (_optional_)
|
242 | * **_returns_** current object or property string value
|
243 |
|
244 | Asserts that the target has exactly the given named property.
|
245 |
|
246 | ```js
|
247 | expect($("<input type=\"checkbox\" checked=\"checked\" />"))
|
248 | .to.have.$prop("checked", true).and
|
249 | .to.have.$prop("type", "checkbox");
|
250 | ```
|
251 |
|
252 | Changes context to property string *value* when no expected value is
|
253 | provided:
|
254 |
|
255 | ```js
|
256 | expect($("<input type=\"checkbox\" checked=\"checked\" />"))
|
257 | .to.have.$prop("type").and
|
258 | .to.equal("checkbox").and
|
259 | .to.match(/^c.*x$/);
|
260 | ```
|
261 |
|
262 | See: [http://api.jquery.com/prop/](http://api.jquery.com/prop/)
|
263 |
|
264 | ### `$html(expected, [message])`
|
265 | * **expected** (`String`) HTML content
|
266 | * **message** (`String`) failure message (_optional_)
|
267 |
|
268 | Asserts that the target has exactly the given HTML, or
|
269 | asserts the target contains a subset of the HTML when using the
|
270 | `include` or `contain` modifiers.
|
271 |
|
272 | ```js
|
273 | expect($("<div><span>foo</span></div>"))
|
274 | .to.have.$html("<span>foo</span>").and
|
275 | .to.contain.$html("foo");
|
276 | ```
|
277 |
|
278 | See: [http://api.jquery.com/html/](http://api.jquery.com/html/)
|
279 |
|
280 | ### `$text(expected, [message])`
|
281 | * **expected** (`String`) text content
|
282 | * **message** (`String`) failure message (_optional_)
|
283 |
|
284 | Asserts that the target has exactly the given text, or
|
285 | asserts the target contains a subset of the text when using the
|
286 | `include` or `contain` modifiers.
|
287 |
|
288 | ```js
|
289 | expect($("<div><span>foo</span> bar</div>"))
|
290 | .to.have.$text("foo bar").and
|
291 | .to.contain.$text("foo");
|
292 | ```
|
293 |
|
294 | See: [http://api.jquery.com/text/](http://api.jquery.com/text/)
|
295 |
|
296 | ### `$css(expected, [message])`
|
297 | * **expected** (`String`) CSS property content
|
298 | * **message** (`String`) failure message (_optional_)
|
299 |
|
300 | Asserts that the target has exactly the given CSS property, or
|
301 | asserts the target contains a subset of the CSS when using the
|
302 | `include` or `contain` modifiers.
|
303 |
|
304 | *Node.js/JsDom Note*: Computed CSS properties are not correctly
|
305 | inferred as of JsDom v0.8.8. Explicit ones should get matched exactly.
|
306 |
|
307 | *Browser Note*: Explicit CSS properties are sometimes not matched
|
308 | (in contrast to Node.js), so the plugin performs an extra check against
|
309 | explicit `style` properties for a match. May still have other wonky
|
310 | corner cases.
|
311 |
|
312 | *PhantomJS Note*: PhantomJS also is fairly wonky and unpredictable with
|
313 | respect to CSS / styles, especially those that come from CSS classes
|
314 | and not explicity `style` attributes.
|
315 |
|
316 | ```js
|
317 | expect($("<div style=\"width: 50px; border: 1px dotted black;\" />"))
|
318 | .to.have.$css("width", "50px").and
|
319 | .to.have.$css("border-top-style", "dotted");
|
320 | ```
|
321 |
|
322 | See: [http://api.jquery.com/css/](http://api.jquery.com/css/)
|
323 |
|
324 |
|
325 | ## Contributions
|
326 |
|
327 | Please see the [Contributions Guide](./CONTRIBUTING.md) for how to help out
|
328 | with the plugin.
|
329 |
|
330 | We test all changes with [Travis CI][trav], report internal test coverage
|
331 | with [Coveralls][cov] and check complexity / static analysis with
|
332 | [Code Climate][cc]. Here is the status for our
|
333 | [build][trav_site], [coverage][cov_site], and [complexity][cc_site]:
|
334 |
|
335 | [![Build Status][trav_img]][trav_site]
|
336 | [![Coverage Status][cov_img]][cov_site]
|
337 | [![Code Climate][cc_img]][cc_site]
|
338 |
|
339 | We also do multi-browser testing of the frontend code using [Sauce Labs][sauce].
|
340 | Here's our [build matrix][sauce_site]:
|
341 |
|
342 | [![Sauce Test Status][sauce_img]][sauce_site]
|
343 |
|
344 | [trav]: https://travis-ci.org/
|
345 | [trav_img]: https://api.travis-ci.org/FormidableLabs/chai-jq.svg
|
346 | [trav_site]: https://travis-ci.org/FormidableLabs/chai-jq
|
347 | [cov]: https://coveralls.io
|
348 | [cov_img]: https://img.shields.io/coveralls/FormidableLabs/chai-jq.svg
|
349 | [cov_site]: https://coveralls.io/r/FormidableLabs/chai-jq
|
350 | [cc]: https://codeclimate.com
|
351 | [cc_img]: https://codeclimate.com/github/FormidableLabs/chai-jq/badges/gpa.svg
|
352 | [cc_site]: https://codeclimate.com/github/FormidableLabs/chai-jq
|
353 | [sauce]: https://saucelabs.com
|
354 | [sauce_img]: https://saucelabs.com/browser-matrix/chai-jq.svg
|
355 | [sauce_site]: https://saucelabs.com/u/chai-jq
|
356 |
|
357 | ## Licenses
|
358 | All code not otherwise specified is Copyright 2013 Ryan Roemer.
|
359 | Released under the [MIT](./LICENSE.txt) License.
|
360 |
|
361 | This repository contains various libraries from other folks, and are licensed
|
362 | as follows:
|
363 |
|
364 | * [jQuery][jquery] is Copyright jQuery Foundation and licensed under the
|
365 | [MIT](https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt) license.
|
366 |
|
367 | * [Mocha][mocha] is Copyright TJ Holowaychuk and licensed under the
|
368 | [MIT](https://github.com/visionmedia/mocha/blob/master/LICENSE) license.
|
369 |
|
370 | * [Chai][chai] is Copyright Jake Luer and licensed under the
|
371 | [BSD](https://github.com/cjohansen/Sinon.JS/blob/master/LICENSE) license.
|
372 |
|
373 | * [Sinon.JS][sinon] is Copyright Christian Johansen and licensed under the
|
374 | [BSD](https://github.com/cjohansen/Sinon.JS/blob/master/LICENSE) license.
|
375 |
|
376 | * [Mocha-PhantomJS][mocha-phantom] is Copyright Ken Collins and licensed under the
|
377 | [MIT](https://github.com/metaskills/mocha-phantomjs/blob/master/MIT-LICENSE)
|
378 | license.
|
379 |
|
380 | * [Pure][pure] is Copyright Yahoo! and licensed under the
|
381 | [MIT](https://github.com/yui/pure/blob/master/LICENSE.md)
|
382 | license.
|
383 |
|
384 | [jquery]: https://github.com/jquery/jquery
|
385 | [mocha]: https://github.com/visionmedia/mocha
|
386 | [mocha-phantom]: https://github.com/metaskills/mocha-phantomjs
|
387 | [phantom]: http://phantomjs.org/
|
388 | [phantom-install]: http://phantomjs.org/download.html
|
389 | [chai]: https://github.com/chaijs/chai
|
390 | [sinon]: https://github.com/cjohansen/Sinon.JS
|
391 | [pure]: https://github.com/yui/pure/
|