├── .travis.yml
├── css
├── gh-fork-ribbon.css
├── locations.css
└── map.css
├── images
├── marker-icon-0.png
├── marker-icon-1.png
├── marker-icon-2.png
├── marker-icon-3.png
└── tolkien.jpg
├── index.html
├── js
├── locations.js
├── map.js
└── menu.js
├── locations.html
├── readme.md
└── test
├── index.html
├── test.js
└── vendors
├── chai-2.3.0
└── chai.js
└── mocha-2.2.5
├── mocha.css
└── mocha.js
/.travis.yml:
--------------------------------------------------------------------------------
1 | before_script:
2 | - wget http://stedolan.github.io/jq/download/linux64/jq && chmod u+x jq
3 | - npm install -g mocha
4 | - npm install mocha-phantomjs-core
5 |
6 | script:
7 | - error = 0; for file in `ls locations/*json`; do ./jq '.' $file; error=$((error + $?)); done; exit $error
8 | - phantomjs node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js test/index.html
9 |
--------------------------------------------------------------------------------
/css/gh-fork-ribbon.css:
--------------------------------------------------------------------------------
1 | /* Left will inherit from right (so we don't need to duplicate code) */
2 | .github-fork-ribbon {
3 | /* The right and left classes determine the side we attach our banner to */
4 | position: absolute;
5 |
6 | /* Add a bit of padding to give some substance outside the "stitching" */
7 | padding: 2px 0;
8 |
9 | /* Set the base colour */
10 | background-color: #a00;
11 |
12 | /* Set a gradient: transparent black at the top to almost-transparent black at the bottom */
13 | background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0)), to(rgba(0, 0, 0, 0.15)));
14 | background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
15 | background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
16 | background-image: -ms-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
17 | background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
18 | background-image: linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
19 |
20 | /* Add a drop shadow */
21 | -webkit-box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.5);
22 | -moz-box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.5);
23 | box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.5);
24 |
25 | z-index: 9999;
26 | pointer-events: auto;
27 | }
28 |
29 | .github-fork-ribbon a,
30 | .github-fork-ribbon a:hover {
31 | /* Set the font */
32 | font: 700 13px "Helvetica Neue", Helvetica, Arial, sans-serif;
33 | color: #fff;
34 |
35 | /* Set the text properties */
36 | text-decoration: none;
37 | text-shadow: 0 -1px rgba(0, 0, 0, 0.5);
38 | text-align: center;
39 |
40 | /* Set the geometry. If you fiddle with these you'll also need
41 | to tweak the top and right values in .github-fork-ribbon. */
42 | width: 200px;
43 | line-height: 20px;
44 |
45 | /* Set the layout properties */
46 | display: inline-block;
47 | padding: 2px 0;
48 |
49 | /* Add "stitching" effect */
50 | border-width: 1px 0;
51 | border-style: dotted;
52 | border-color: #fff;
53 | border-color: rgba(255, 255, 255, 0.7);
54 | }
55 |
56 | .github-fork-ribbon-wrapper {
57 | width: 150px;
58 | height: 150px;
59 | position: absolute;
60 | overflow: hidden;
61 | top: 0;
62 | z-index: 9999;
63 | pointer-events: none;
64 | }
65 |
66 | .github-fork-ribbon-wrapper.fixed {
67 | position: fixed;
68 | }
69 |
70 | .github-fork-ribbon-wrapper.left {
71 | left: 0;
72 | }
73 |
74 | .github-fork-ribbon-wrapper.right {
75 | right: 0;
76 | }
77 |
78 | .github-fork-ribbon-wrapper.left-bottom {
79 | position: fixed;
80 | top: inherit;
81 | bottom: 0;
82 | left: 0;
83 | }
84 |
85 | .github-fork-ribbon-wrapper.right-bottom {
86 | position: fixed;
87 | top: inherit;
88 | bottom: 0;
89 | right: 0;
90 | }
91 |
92 | .github-fork-ribbon-wrapper.right .github-fork-ribbon {
93 | top: 42px;
94 | right: -43px;
95 |
96 | -webkit-transform: rotate(45deg);
97 | -moz-transform: rotate(45deg);
98 | -ms-transform: rotate(45deg);
99 | -o-transform: rotate(45deg);
100 | transform: rotate(45deg);
101 | }
102 |
103 | .github-fork-ribbon-wrapper.left .github-fork-ribbon {
104 | top: 42px;
105 | left: -43px;
106 |
107 | -webkit-transform: rotate(-45deg);
108 | -moz-transform: rotate(-45deg);
109 | -ms-transform: rotate(-45deg);
110 | -o-transform: rotate(-45deg);
111 | transform: rotate(-45deg);
112 | }
113 |
114 |
115 | .github-fork-ribbon-wrapper.left-bottom .github-fork-ribbon {
116 | top: 80px;
117 | left: -43px;
118 |
119 | -webkit-transform: rotate(45deg);
120 | -moz-transform: rotate(45deg);
121 | -ms-transform: rotate(45deg);
122 | -o-transform: rotate(45deg);
123 | transform: rotate(45deg);
124 | }
125 |
126 | .github-fork-ribbon-wrapper.right-bottom .github-fork-ribbon {
127 | top: 80px;
128 | right: -43px;
129 |
130 | -webkit-transform: rotate(-45deg);
131 | -moz-transform: rotate(-45deg);
132 | -ms-transform: rotate(-45deg);
133 | -o-transform: rotate(-45deg);
134 | transform: rotate(-45deg);
135 | }
136 |
--------------------------------------------------------------------------------
/css/locations.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: #ADE199 url('../images/tolkien.jpg');
3 | background-size: 100%;
4 | height:100%;
5 | width: 100%;
6 | font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
7 | text-align: center;
8 | color: #35641E;
9 | }
10 |
11 | section.container {
12 | max-width: 300px;
13 | margin: auto;
14 | }
15 |
16 | h1 {
17 | font-size: 25px;
18 | }
19 |
20 | p {
21 | font-size: 17px;
22 | }
23 |
24 | ul {
25 | font-size: 14px;
26 | line-height: 1.42857143;
27 | padding-left: 0;
28 | }
29 |
30 | li {
31 | display: block;
32 | border-top-left-radius: 4px;
33 | border-top-right-radius: 4px;
34 | position: relative;
35 | padding: 5px 15px;
36 | margin-bottom: -1px;
37 | background-color: #fff;
38 | opacity: .5;
39 | border: 1px solid #ddd;
40 | }
41 |
42 | li:hover {
43 | background: #eee;
44 | }
45 |
46 | li a {
47 | display: block;
48 | text-decoration: none;
49 | color: #555;
50 | }
51 |
--------------------------------------------------------------------------------
/css/map.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 0;
3 | margin: 0;
4 | }
5 |
6 | html,
7 | body,
8 | #map {
9 | height: 100%;
10 | }
11 |
12 | #home {
13 | font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
14 | position: absolute;
15 | padding: 5px;
16 | bottom: 0;
17 | z-index: 9999;
18 | font-weight: 800;
19 | }
20 |
--------------------------------------------------------------------------------
/images/marker-icon-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/avernois/devfriendlyplaces/3187980a65d1ef3c5f1ee92d05ce6fe7dd017d08/images/marker-icon-0.png
--------------------------------------------------------------------------------
/images/marker-icon-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/avernois/devfriendlyplaces/3187980a65d1ef3c5f1ee92d05ce6fe7dd017d08/images/marker-icon-1.png
--------------------------------------------------------------------------------
/images/marker-icon-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/avernois/devfriendlyplaces/3187980a65d1ef3c5f1ee92d05ce6fe7dd017d08/images/marker-icon-2.png
--------------------------------------------------------------------------------
/images/marker-icon-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/avernois/devfriendlyplaces/3187980a65d1ef3c5f1ee92d05ce6fe7dd017d08/images/marker-icon-3.png
--------------------------------------------------------------------------------
/images/tolkien.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/avernois/devfriendlyplaces/3187980a65d1ef3c5f1ee92d05ce6fe7dd017d08/images/tolkien.jpg
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Dev Friendly Places
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/js/locations.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 |
4 | function extractLocationFromUrl(hostname) {
5 | var split = hostname.split(".");
6 | var location = split[0];
7 |
8 | if ((split.length < 3) || (location == "www")) {
9 | throw "No location in the url";;
10 | }
11 |
12 | return location;
13 | }
14 |
15 |
16 | function getJSON(url) {
17 | var request = new XMLHttpRequest();
18 | request.open("GET", url, false);
19 | request.send(null);
20 |
21 | return JSON.parse(request.responseText);
22 | }
23 |
24 |
25 | function slugifyLocation(location) {
26 | return location.toUpperCase()
27 | .replace("À", "A")
28 | .replace(/[È,É]/, "E")
29 | .replace(" ", "-")
30 | .toLowerCase();
31 | }
32 |
33 |
34 | function getLocations() {
35 | // Possible to get an absolute url : https://raw.githubusercontent.com/...
36 | return getJSON("https://raw.githubusercontent.com/devfriendlyplaces/data/data/locations/locations.json");
37 | }
38 |
39 |
40 | function getPlaces(location) {
41 | return getJSON("https://raw.githubusercontent.com/devfriendlyplaces/data/data/locations/" + location + ".json");
42 | }
43 |
44 |
45 | function sortKeys(locations) {
46 | return locations.map(l => l.name).sort()
47 | }
48 |
49 |
50 | function getLocationInfo(locations, location) {
51 | return locations.filter(
52 | l => slugifyLocation(l.name) === location
53 | )[0]
54 | }
55 |
--------------------------------------------------------------------------------
/js/map.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var marker_icons = [];
4 | for (var i = 0; i < 4; i++) {
5 | marker_icons.push(
6 | L.icon({
7 | iconUrl: 'images/marker-icon-' + i + '.png',
8 | iconSize: [25, 41],
9 | iconAnchor: [12, 41],
10 | popupAnchor: [0, -30]
11 | })
12 | );
13 | }
14 |
15 |
16 | function buildMapFor(location) {
17 | var defaultZoom = 14;
18 | var locations = getLocations();
19 | var locationInfo = getLocationInfo(locations, location);
20 | var map = L.map('map').setView([locationInfo.lat, locationInfo.lon], locationInfo.defaultZoom);
21 | map.on('moveend', onMoveEnd(map, locations));
22 | L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
23 | attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA'
24 | }).addTo(map);
25 |
26 | map.isDisplayedLocation = {};
27 |
28 | displayPlacesFromLocation(map, location);
29 | }
30 |
31 |
32 | function placeToHtml(place) {
33 | return "" + place.name + "
" +
34 | optionalFieldToHtml("address", place.address) +
35 | optionalFieldToHtml("open hours", place.openHours) +
36 | optionalFieldToHtml("type", place.type) +
37 | optionalUrlToLink("website", place.url) +
38 | optionToHtml("power", place.power) +
39 | optionToHtml("wifi", place.wifi) +
40 | optionalFieldToHtml("comment", place.comment);
41 | }
42 |
43 |
44 | function iconForPlace(place) {
45 | var weights = { wifi: 1, power: 2 };
46 | var iconIndex = 0;
47 |
48 | for (var idx in weights) {
49 | iconIndex += optionValue(place[idx]) * weights[idx];
50 | }
51 |
52 | return marker_icons[iconIndex];
53 | }
54 |
55 |
56 | function optionalFieldToHtml(label, value) {
57 | return value ? label + ": " + value + "
" : "";
58 | }
59 |
60 |
61 | function optionalUrlToLink(label, value) {
62 | return value ? label + ": " + "" + value + "" + "
" : "";
63 | }
64 |
65 |
66 | function optionToHtml(label, value) {
67 | return label + ": " + optionText(value) + "
";
68 | }
69 |
70 |
71 | function optionText(value) {
72 | if (value !== undefined) {
73 | return boolToStr(value.available) + optionalComment(value.comment);
74 | } else {
75 | return "undefined";
76 | }
77 | }
78 |
79 |
80 | function optionValue(value) {
81 | if (value !== undefined) {
82 | return boolToInt(value.available);
83 | }
84 | return 0;
85 | }
86 |
87 |
88 | function boolToStr(value) {
89 | if (value !== undefined) {
90 | return value ? "yes" : "no";
91 | } else {
92 | return 'undefined';
93 | }
94 | }
95 |
96 |
97 | function boolToInt(value) {
98 | if (value !== undefined) {
99 | return value ? 1 : 0;
100 | } else {
101 | return 0;
102 | }
103 | }
104 |
105 |
106 | function optionalComment(value) {
107 | return value ? "(" + value + ")" : "";
108 | }
109 |
110 |
111 | function displayPlacesFromLocation(map, location) {
112 | if (isLocationDisplayedOnMap(map, location)) { return; }
113 |
114 | var places = getPlaces(location);
115 |
116 | places.forEach(function(place) {
117 | L.marker([place.lat, place.lon], { icon: iconForPlace(place) })
118 | .bindPopup(placeToHtml(place))
119 | .addTo(map);
120 | });
121 |
122 | map.isDisplayedLocation[location] = true;
123 | }
124 |
125 |
126 | function onMoveEnd(map, locations) {
127 | return function() {
128 | locations.map(location => {
129 | if (map.getBounds().contains([location.lat, location.lon])) {
130 | displayPlacesFromLocation(map, slugifyLocation(location.name));
131 | }
132 | });
133 | }
134 | }
135 |
136 |
137 | function isLocationDisplayedOnMap(map, location) {
138 | return map.isDisplayedLocation[location];
139 | }
--------------------------------------------------------------------------------
/js/menu.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | function buildLocations() {
4 | var locations = getLocations();
5 | var listContainer = document.createElement("div");
6 | var listElement = document.createElement("ul");
7 | document.getElementById("locations").appendChild(listContainer);
8 | listContainer.appendChild(listElement);
9 | sortKeys(locations).map(location => {
10 | var listItem = document.createElement("li");
11 | listItem.innerHTML = "" + location + "";
12 | listElement.appendChild(listItem);
13 | });
14 | }
15 |
--------------------------------------------------------------------------------
/locations.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Dev Friendly Places
5 |
6 |
7 |
8 |
9 |
10 |
11 | DEV FRIENDLY PLACES
12 | Pick a city and find a place for coding
13 |
14 |
19 |
20 |
21 |
22 |
23 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | New reposistories for devfriendlyplaces
2 | =======================================
3 |
4 | Everything related to devfriendlyplaces has moved to a dedicated organisation [devfriendlyplaces](https://github.com/devfriendlyplaces):
5 | - code of website: https://github.com/devfriendlyplaces/elm-site
6 | - locations data: https://github.com/devfriendlyplaces/data
7 |
8 | This original repository is kept here for archive.
9 |
--------------------------------------------------------------------------------
/test/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Mocha Tests
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/test/test.js:
--------------------------------------------------------------------------------
1 | var should = chai.should();
2 |
3 | describe('Extract the location from the url', function() {
4 | it('should return the location from an Url', function () {
5 | var location = extractLocationFromUrl('cerclon.devfriendlyplaces.net');
6 | location.should.equal('cerclon');
7 | })
8 | })
9 |
--------------------------------------------------------------------------------
/test/vendors/chai-2.3.0/chai.js:
--------------------------------------------------------------------------------
1 |
2 | ;(function(){
3 |
4 | /**
5 | * Require the module at `name`.
6 | *
7 | * @param {String} name
8 | * @return {Object} exports
9 | * @api public
10 | */
11 |
12 | function require(name) {
13 | var module = require.modules[name];
14 | if (!module) throw new Error('failed to require "' + name + '"');
15 |
16 | if (!('exports' in module) && typeof module.definition === 'function') {
17 | module.client = module.component = true;
18 | module.definition.call(this, module.exports = {}, module);
19 | delete module.definition;
20 | }
21 |
22 | return module.exports;
23 | }
24 |
25 | /**
26 | * Meta info, accessible in the global scope unless you use AMD option.
27 | */
28 |
29 | require.loader = 'component';
30 |
31 | /**
32 | * Internal helper object, contains a sorting function for semantiv versioning
33 | */
34 | require.helper = {};
35 | require.helper.semVerSort = function(a, b) {
36 | var aArray = a.version.split('.');
37 | var bArray = b.version.split('.');
38 | for (var i=0; i bLex ? 1 : -1;
47 | continue;
48 | } else if (aInt > bInt) {
49 | return 1;
50 | } else {
51 | return -1;
52 | }
53 | }
54 | return 0;
55 | }
56 |
57 | /**
58 | * Find and require a module which name starts with the provided name.
59 | * If multiple modules exists, the highest semver is used.
60 | * This function can only be used for remote dependencies.
61 |
62 | * @param {String} name - module name: `user~repo`
63 | * @param {Boolean} returnPath - returns the canonical require path if true,
64 | * otherwise it returns the epxorted module
65 | */
66 | require.latest = function (name, returnPath) {
67 | function showError(name) {
68 | throw new Error('failed to find latest module of "' + name + '"');
69 | }
70 | // only remotes with semvers, ignore local files conataining a '/'
71 | var versionRegexp = /(.*)~(.*)@v?(\d+\.\d+\.\d+[^\/]*)$/;
72 | var remoteRegexp = /(.*)~(.*)/;
73 | if (!remoteRegexp.test(name)) showError(name);
74 | var moduleNames = Object.keys(require.modules);
75 | var semVerCandidates = [];
76 | var otherCandidates = []; // for instance: name of the git branch
77 | for (var i=0; i 0) {
93 | var module = semVerCandidates.sort(require.helper.semVerSort).pop().name;
94 | if (returnPath === true) {
95 | return module;
96 | }
97 | return require(module);
98 | }
99 | // if the build contains more than one branch of the same module
100 | // you should not use this funciton
101 | var module = otherCandidates.sort(function(a, b) {return a.name > b.name})[0].name;
102 | if (returnPath === true) {
103 | return module;
104 | }
105 | return require(module);
106 | }
107 |
108 | /**
109 | * Registered modules.
110 | */
111 |
112 | require.modules = {};
113 |
114 | /**
115 | * Register module at `name` with callback `definition`.
116 | *
117 | * @param {String} name
118 | * @param {Function} definition
119 | * @api private
120 | */
121 |
122 | require.register = function (name, definition) {
123 | require.modules[name] = {
124 | definition: definition
125 | };
126 | };
127 |
128 | /**
129 | * Define a module's exports immediately with `exports`.
130 | *
131 | * @param {String} name
132 | * @param {Generic} exports
133 | * @api private
134 | */
135 |
136 | require.define = function (name, exports) {
137 | require.modules[name] = {
138 | exports: exports
139 | };
140 | };
141 | require.register("chaijs~assertion-error@1.0.0", function (exports, module) {
142 | /*!
143 | * assertion-error
144 | * Copyright(c) 2013 Jake Luer
145 | * MIT Licensed
146 | */
147 |
148 | /*!
149 | * Return a function that will copy properties from
150 | * one object to another excluding any originally
151 | * listed. Returned function will create a new `{}`.
152 | *
153 | * @param {String} excluded properties ...
154 | * @return {Function}
155 | */
156 |
157 | function exclude () {
158 | var excludes = [].slice.call(arguments);
159 |
160 | function excludeProps (res, obj) {
161 | Object.keys(obj).forEach(function (key) {
162 | if (!~excludes.indexOf(key)) res[key] = obj[key];
163 | });
164 | }
165 |
166 | return function extendExclude () {
167 | var args = [].slice.call(arguments)
168 | , i = 0
169 | , res = {};
170 |
171 | for (; i < args.length; i++) {
172 | excludeProps(res, args[i]);
173 | }
174 |
175 | return res;
176 | };
177 | };
178 |
179 | /*!
180 | * Primary Exports
181 | */
182 |
183 | module.exports = AssertionError;
184 |
185 | /**
186 | * ### AssertionError
187 | *
188 | * An extension of the JavaScript `Error` constructor for
189 | * assertion and validation scenarios.
190 | *
191 | * @param {String} message
192 | * @param {Object} properties to include (optional)
193 | * @param {callee} start stack function (optional)
194 | */
195 |
196 | function AssertionError (message, _props, ssf) {
197 | var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON')
198 | , props = extend(_props || {});
199 |
200 | // default values
201 | this.message = message || 'Unspecified AssertionError';
202 | this.showDiff = false;
203 |
204 | // copy from properties
205 | for (var key in props) {
206 | this[key] = props[key];
207 | }
208 |
209 | // capture stack trace
210 | ssf = ssf || arguments.callee;
211 | if (ssf && Error.captureStackTrace) {
212 | Error.captureStackTrace(this, ssf);
213 | }
214 | }
215 |
216 | /*!
217 | * Inherit from Error.prototype
218 | */
219 |
220 | AssertionError.prototype = Object.create(Error.prototype);
221 |
222 | /*!
223 | * Statically set name
224 | */
225 |
226 | AssertionError.prototype.name = 'AssertionError';
227 |
228 | /*!
229 | * Ensure correct constructor
230 | */
231 |
232 | AssertionError.prototype.constructor = AssertionError;
233 |
234 | /**
235 | * Allow errors to be converted to JSON for static transfer.
236 | *
237 | * @param {Boolean} include stack (default: `true`)
238 | * @return {Object} object that can be `JSON.stringify`
239 | */
240 |
241 | AssertionError.prototype.toJSON = function (stack) {
242 | var extend = exclude('constructor', 'toJSON', 'stack')
243 | , props = extend({ name: this.name }, this);
244 |
245 | // include stack if exists and not turned off
246 | if (false !== stack && this.stack) {
247 | props.stack = this.stack;
248 | }
249 |
250 | return props;
251 | };
252 |
253 | });
254 |
255 | require.register("chaijs~type-detect@0.1.1", function (exports, module) {
256 | /*!
257 | * type-detect
258 | * Copyright(c) 2013 jake luer
259 | * MIT Licensed
260 | */
261 |
262 | /*!
263 | * Primary Exports
264 | */
265 |
266 | var exports = module.exports = getType;
267 |
268 | /*!
269 | * Detectable javascript natives
270 | */
271 |
272 | var natives = {
273 | '[object Array]': 'array'
274 | , '[object RegExp]': 'regexp'
275 | , '[object Function]': 'function'
276 | , '[object Arguments]': 'arguments'
277 | , '[object Date]': 'date'
278 | };
279 |
280 | /**
281 | * ### typeOf (obj)
282 | *
283 | * Use several different techniques to determine
284 | * the type of object being tested.
285 | *
286 | *
287 | * @param {Mixed} object
288 | * @return {String} object type
289 | * @api public
290 | */
291 |
292 | function getType (obj) {
293 | var str = Object.prototype.toString.call(obj);
294 | if (natives[str]) return natives[str];
295 | if (obj === null) return 'null';
296 | if (obj === undefined) return 'undefined';
297 | if (obj === Object(obj)) return 'object';
298 | return typeof obj;
299 | }
300 |
301 | exports.Library = Library;
302 |
303 | /**
304 | * ### Library
305 | *
306 | * Create a repository for custom type detection.
307 | *
308 | * ```js
309 | * var lib = new type.Library;
310 | * ```
311 | *
312 | */
313 |
314 | function Library () {
315 | this.tests = {};
316 | }
317 |
318 | /**
319 | * #### .of (obj)
320 | *
321 | * Expose replacement `typeof` detection to the library.
322 | *
323 | * ```js
324 | * if ('string' === lib.of('hello world')) {
325 | * // ...
326 | * }
327 | * ```
328 | *
329 | * @param {Mixed} object to test
330 | * @return {String} type
331 | */
332 |
333 | Library.prototype.of = getType;
334 |
335 | /**
336 | * #### .define (type, test)
337 | *
338 | * Add a test to for the `.test()` assertion.
339 | *
340 | * Can be defined as a regular expression:
341 | *
342 | * ```js
343 | * lib.define('int', /^[0-9]+$/);
344 | * ```
345 | *
346 | * ... or as a function:
347 | *
348 | * ```js
349 | * lib.define('bln', function (obj) {
350 | * if ('boolean' === lib.of(obj)) return true;
351 | * var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ];
352 | * if ('string' === lib.of(obj)) obj = obj.toLowerCase();
353 | * return !! ~blns.indexOf(obj);
354 | * });
355 | * ```
356 | *
357 | * @param {String} type
358 | * @param {RegExp|Function} test
359 | * @api public
360 | */
361 |
362 | Library.prototype.define = function (type, test) {
363 | if (arguments.length === 1) return this.tests[type];
364 | this.tests[type] = test;
365 | return this;
366 | };
367 |
368 | /**
369 | * #### .test (obj, test)
370 | *
371 | * Assert that an object is of type. Will first
372 | * check natives, and if that does not pass it will
373 | * use the user defined custom tests.
374 | *
375 | * ```js
376 | * assert(lib.test('1', 'int'));
377 | * assert(lib.test('yes', 'bln'));
378 | * ```
379 | *
380 | * @param {Mixed} object
381 | * @param {String} type
382 | * @return {Boolean} result
383 | * @api public
384 | */
385 |
386 | Library.prototype.test = function (obj, type) {
387 | if (type === getType(obj)) return true;
388 | var test = this.tests[type];
389 |
390 | if (test && 'regexp' === getType(test)) {
391 | return test.test(obj);
392 | } else if (test && 'function' === getType(test)) {
393 | return test(obj);
394 | } else {
395 | throw new ReferenceError('Type test "' + type + '" not defined or invalid.');
396 | }
397 | };
398 |
399 | });
400 |
401 | require.register("chaijs~deep-eql@0.1.3", function (exports, module) {
402 | /*!
403 | * deep-eql
404 | * Copyright(c) 2013 Jake Luer
405 | * MIT Licensed
406 | */
407 |
408 | /*!
409 | * Module dependencies
410 | */
411 |
412 | var type = require('chaijs~type-detect@0.1.1');
413 |
414 | /*!
415 | * Buffer.isBuffer browser shim
416 | */
417 |
418 | var Buffer;
419 | try { Buffer = require('buffer').Buffer; }
420 | catch(ex) {
421 | Buffer = {};
422 | Buffer.isBuffer = function() { return false; }
423 | }
424 |
425 | /*!
426 | * Primary Export
427 | */
428 |
429 | module.exports = deepEqual;
430 |
431 | /**
432 | * Assert super-strict (egal) equality between
433 | * two objects of any type.
434 | *
435 | * @param {Mixed} a
436 | * @param {Mixed} b
437 | * @param {Array} memoised (optional)
438 | * @return {Boolean} equal match
439 | */
440 |
441 | function deepEqual(a, b, m) {
442 | if (sameValue(a, b)) {
443 | return true;
444 | } else if ('date' === type(a)) {
445 | return dateEqual(a, b);
446 | } else if ('regexp' === type(a)) {
447 | return regexpEqual(a, b);
448 | } else if (Buffer.isBuffer(a)) {
449 | return bufferEqual(a, b);
450 | } else if ('arguments' === type(a)) {
451 | return argumentsEqual(a, b, m);
452 | } else if (!typeEqual(a, b)) {
453 | return false;
454 | } else if (('object' !== type(a) && 'object' !== type(b))
455 | && ('array' !== type(a) && 'array' !== type(b))) {
456 | return sameValue(a, b);
457 | } else {
458 | return objectEqual(a, b, m);
459 | }
460 | }
461 |
462 | /*!
463 | * Strict (egal) equality test. Ensures that NaN always
464 | * equals NaN and `-0` does not equal `+0`.
465 | *
466 | * @param {Mixed} a
467 | * @param {Mixed} b
468 | * @return {Boolean} equal match
469 | */
470 |
471 | function sameValue(a, b) {
472 | if (a === b) return a !== 0 || 1 / a === 1 / b;
473 | return a !== a && b !== b;
474 | }
475 |
476 | /*!
477 | * Compare the types of two given objects and
478 | * return if they are equal. Note that an Array
479 | * has a type of `array` (not `object`) and arguments
480 | * have a type of `arguments` (not `array`/`object`).
481 | *
482 | * @param {Mixed} a
483 | * @param {Mixed} b
484 | * @return {Boolean} result
485 | */
486 |
487 | function typeEqual(a, b) {
488 | return type(a) === type(b);
489 | }
490 |
491 | /*!
492 | * Compare two Date objects by asserting that
493 | * the time values are equal using `saveValue`.
494 | *
495 | * @param {Date} a
496 | * @param {Date} b
497 | * @return {Boolean} result
498 | */
499 |
500 | function dateEqual(a, b) {
501 | if ('date' !== type(b)) return false;
502 | return sameValue(a.getTime(), b.getTime());
503 | }
504 |
505 | /*!
506 | * Compare two regular expressions by converting them
507 | * to string and checking for `sameValue`.
508 | *
509 | * @param {RegExp} a
510 | * @param {RegExp} b
511 | * @return {Boolean} result
512 | */
513 |
514 | function regexpEqual(a, b) {
515 | if ('regexp' !== type(b)) return false;
516 | return sameValue(a.toString(), b.toString());
517 | }
518 |
519 | /*!
520 | * Assert deep equality of two `arguments` objects.
521 | * Unfortunately, these must be sliced to arrays
522 | * prior to test to ensure no bad behavior.
523 | *
524 | * @param {Arguments} a
525 | * @param {Arguments} b
526 | * @param {Array} memoize (optional)
527 | * @return {Boolean} result
528 | */
529 |
530 | function argumentsEqual(a, b, m) {
531 | if ('arguments' !== type(b)) return false;
532 | a = [].slice.call(a);
533 | b = [].slice.call(b);
534 | return deepEqual(a, b, m);
535 | }
536 |
537 | /*!
538 | * Get enumerable properties of a given object.
539 | *
540 | * @param {Object} a
541 | * @return {Array} property names
542 | */
543 |
544 | function enumerable(a) {
545 | var res = [];
546 | for (var key in a) res.push(key);
547 | return res;
548 | }
549 |
550 | /*!
551 | * Simple equality for flat iterable objects
552 | * such as Arrays or Node.js buffers.
553 | *
554 | * @param {Iterable} a
555 | * @param {Iterable} b
556 | * @return {Boolean} result
557 | */
558 |
559 | function iterableEqual(a, b) {
560 | if (a.length !== b.length) return false;
561 |
562 | var i = 0;
563 | var match = true;
564 |
565 | for (; i < a.length; i++) {
566 | if (a[i] !== b[i]) {
567 | match = false;
568 | break;
569 | }
570 | }
571 |
572 | return match;
573 | }
574 |
575 | /*!
576 | * Extension to `iterableEqual` specifically
577 | * for Node.js Buffers.
578 | *
579 | * @param {Buffer} a
580 | * @param {Mixed} b
581 | * @return {Boolean} result
582 | */
583 |
584 | function bufferEqual(a, b) {
585 | if (!Buffer.isBuffer(b)) return false;
586 | return iterableEqual(a, b);
587 | }
588 |
589 | /*!
590 | * Block for `objectEqual` ensuring non-existing
591 | * values don't get in.
592 | *
593 | * @param {Mixed} object
594 | * @return {Boolean} result
595 | */
596 |
597 | function isValue(a) {
598 | return a !== null && a !== undefined;
599 | }
600 |
601 | /*!
602 | * Recursively check the equality of two objects.
603 | * Once basic sameness has been established it will
604 | * defer to `deepEqual` for each enumerable key
605 | * in the object.
606 | *
607 | * @param {Mixed} a
608 | * @param {Mixed} b
609 | * @return {Boolean} result
610 | */
611 |
612 | function objectEqual(a, b, m) {
613 | if (!isValue(a) || !isValue(b)) {
614 | return false;
615 | }
616 |
617 | if (a.prototype !== b.prototype) {
618 | return false;
619 | }
620 |
621 | var i;
622 | if (m) {
623 | for (i = 0; i < m.length; i++) {
624 | if ((m[i][0] === a && m[i][1] === b)
625 | || (m[i][0] === b && m[i][1] === a)) {
626 | return true;
627 | }
628 | }
629 | } else {
630 | m = [];
631 | }
632 |
633 | try {
634 | var ka = enumerable(a);
635 | var kb = enumerable(b);
636 | } catch (ex) {
637 | return false;
638 | }
639 |
640 | ka.sort();
641 | kb.sort();
642 |
643 | if (!iterableEqual(ka, kb)) {
644 | return false;
645 | }
646 |
647 | m.push([ a, b ]);
648 |
649 | var key;
650 | for (i = ka.length - 1; i >= 0; i--) {
651 | key = ka[i];
652 | if (!deepEqual(a[key], b[key], m)) {
653 | return false;
654 | }
655 | }
656 |
657 | return true;
658 | }
659 |
660 | });
661 |
662 | require.register("chai", function (exports, module) {
663 | module.exports = require('chai/lib/chai.js');
664 |
665 | });
666 |
667 | require.register("chai/lib/chai.js", function (exports, module) {
668 | /*!
669 | * chai
670 | * Copyright(c) 2011-2014 Jake Luer
671 | * MIT Licensed
672 | */
673 |
674 | var used = []
675 | , exports = module.exports = {};
676 |
677 | /*!
678 | * Chai version
679 | */
680 |
681 | exports.version = '2.3.0';
682 |
683 | /*!
684 | * Assertion Error
685 | */
686 |
687 | exports.AssertionError = require('chaijs~assertion-error@1.0.0');
688 |
689 | /*!
690 | * Utils for plugins (not exported)
691 | */
692 |
693 | var util = require('chai/lib/chai/utils/index.js');
694 |
695 | /**
696 | * # .use(function)
697 | *
698 | * Provides a way to extend the internals of Chai
699 | *
700 | * @param {Function}
701 | * @returns {this} for chaining
702 | * @api public
703 | */
704 |
705 | exports.use = function (fn) {
706 | if (!~used.indexOf(fn)) {
707 | fn(this, util);
708 | used.push(fn);
709 | }
710 |
711 | return this;
712 | };
713 |
714 | /*!
715 | * Utility Functions
716 | */
717 |
718 | exports.util = util;
719 |
720 | /*!
721 | * Configuration
722 | */
723 |
724 | var config = require('chai/lib/chai/config.js');
725 | exports.config = config;
726 |
727 | /*!
728 | * Primary `Assertion` prototype
729 | */
730 |
731 | var assertion = require('chai/lib/chai/assertion.js');
732 | exports.use(assertion);
733 |
734 | /*!
735 | * Core Assertions
736 | */
737 |
738 | var core = require('chai/lib/chai/core/assertions.js');
739 | exports.use(core);
740 |
741 | /*!
742 | * Expect interface
743 | */
744 |
745 | var expect = require('chai/lib/chai/interface/expect.js');
746 | exports.use(expect);
747 |
748 | /*!
749 | * Should interface
750 | */
751 |
752 | var should = require('chai/lib/chai/interface/should.js');
753 | exports.use(should);
754 |
755 | /*!
756 | * Assert interface
757 | */
758 |
759 | var assert = require('chai/lib/chai/interface/assert.js');
760 | exports.use(assert);
761 |
762 | });
763 |
764 | require.register("chai/lib/chai/assertion.js", function (exports, module) {
765 | /*!
766 | * chai
767 | * http://chaijs.com
768 | * Copyright(c) 2011-2014 Jake Luer
769 | * MIT Licensed
770 | */
771 |
772 | var config = require('chai/lib/chai/config.js');
773 |
774 | module.exports = function (_chai, util) {
775 | /*!
776 | * Module dependencies.
777 | */
778 |
779 | var AssertionError = _chai.AssertionError
780 | , flag = util.flag;
781 |
782 | /*!
783 | * Module export.
784 | */
785 |
786 | _chai.Assertion = Assertion;
787 |
788 | /*!
789 | * Assertion Constructor
790 | *
791 | * Creates object for chaining.
792 | *
793 | * @api private
794 | */
795 |
796 | function Assertion (obj, msg, stack) {
797 | flag(this, 'ssfi', stack || arguments.callee);
798 | flag(this, 'object', obj);
799 | flag(this, 'message', msg);
800 | }
801 |
802 | Object.defineProperty(Assertion, 'includeStack', {
803 | get: function() {
804 | console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');
805 | return config.includeStack;
806 | },
807 | set: function(value) {
808 | console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');
809 | config.includeStack = value;
810 | }
811 | });
812 |
813 | Object.defineProperty(Assertion, 'showDiff', {
814 | get: function() {
815 | console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');
816 | return config.showDiff;
817 | },
818 | set: function(value) {
819 | console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');
820 | config.showDiff = value;
821 | }
822 | });
823 |
824 | Assertion.addProperty = function (name, fn) {
825 | util.addProperty(this.prototype, name, fn);
826 | };
827 |
828 | Assertion.addMethod = function (name, fn) {
829 | util.addMethod(this.prototype, name, fn);
830 | };
831 |
832 | Assertion.addChainableMethod = function (name, fn, chainingBehavior) {
833 | util.addChainableMethod(this.prototype, name, fn, chainingBehavior);
834 | };
835 |
836 | Assertion.overwriteProperty = function (name, fn) {
837 | util.overwriteProperty(this.prototype, name, fn);
838 | };
839 |
840 | Assertion.overwriteMethod = function (name, fn) {
841 | util.overwriteMethod(this.prototype, name, fn);
842 | };
843 |
844 | Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) {
845 | util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior);
846 | };
847 |
848 | /*!
849 | * ### .assert(expression, message, negateMessage, expected, actual)
850 | *
851 | * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass.
852 | *
853 | * @name assert
854 | * @param {Philosophical} expression to be tested
855 | * @param {String or Function} message or function that returns message to display if expression fails
856 | * @param {String or Function} negatedMessage or function that returns negatedMessage to display if negated expression fails
857 | * @param {Mixed} expected value (remember to check for negation)
858 | * @param {Mixed} actual (optional) will default to `this.obj`
859 | * @param {Boolean} showDiff (optional) when set to `true`, assert will display a diff in addition to the message if expression fails
860 | * @api private
861 | */
862 |
863 | Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) {
864 | var ok = util.test(this, arguments);
865 | if (true !== showDiff) showDiff = false;
866 | if (true !== config.showDiff) showDiff = false;
867 |
868 | if (!ok) {
869 | var msg = util.getMessage(this, arguments)
870 | , actual = util.getActual(this, arguments);
871 | throw new AssertionError(msg, {
872 | actual: actual
873 | , expected: expected
874 | , showDiff: showDiff
875 | }, (config.includeStack) ? this.assert : flag(this, 'ssfi'));
876 | }
877 | };
878 |
879 | /*!
880 | * ### ._obj
881 | *
882 | * Quick reference to stored `actual` value for plugin developers.
883 | *
884 | * @api private
885 | */
886 |
887 | Object.defineProperty(Assertion.prototype, '_obj',
888 | { get: function () {
889 | return flag(this, 'object');
890 | }
891 | , set: function (val) {
892 | flag(this, 'object', val);
893 | }
894 | });
895 | };
896 |
897 | });
898 |
899 | require.register("chai/lib/chai/config.js", function (exports, module) {
900 | module.exports = {
901 |
902 | /**
903 | * ### config.includeStack
904 | *
905 | * User configurable property, influences whether stack trace
906 | * is included in Assertion error message. Default of false
907 | * suppresses stack trace in the error message.
908 | *
909 | * chai.config.includeStack = true; // enable stack on error
910 | *
911 | * @param {Boolean}
912 | * @api public
913 | */
914 |
915 | includeStack: false,
916 |
917 | /**
918 | * ### config.showDiff
919 | *
920 | * User configurable property, influences whether or not
921 | * the `showDiff` flag should be included in the thrown
922 | * AssertionErrors. `false` will always be `false`; `true`
923 | * will be true when the assertion has requested a diff
924 | * be shown.
925 | *
926 | * @param {Boolean}
927 | * @api public
928 | */
929 |
930 | showDiff: true,
931 |
932 | /**
933 | * ### config.truncateThreshold
934 | *
935 | * User configurable property, sets length threshold for actual and
936 | * expected values in assertion errors. If this threshold is exceeded, for
937 | * example for large data structures, the value is replaced with something
938 | * like `[ Array(3) ]` or `{ Object (prop1, prop2) }`.
939 | *
940 | * Set it to zero if you want to disable truncating altogether.
941 | *
942 | * This is especially userful when doing assertions on arrays: having this
943 | * set to a reasonable large value makes the failure messages readily
944 | * inspectable.
945 | *
946 | * chai.config.truncateThreshold = 0; // disable truncating
947 | *
948 | * @param {Number}
949 | * @api public
950 | */
951 |
952 | truncateThreshold: 40
953 |
954 | };
955 |
956 | });
957 |
958 | require.register("chai/lib/chai/core/assertions.js", function (exports, module) {
959 | /*!
960 | * chai
961 | * http://chaijs.com
962 | * Copyright(c) 2011-2014 Jake Luer
963 | * MIT Licensed
964 | */
965 |
966 | module.exports = function (chai, _) {
967 | var Assertion = chai.Assertion
968 | , toString = Object.prototype.toString
969 | , flag = _.flag;
970 |
971 | /**
972 | * ### Language Chains
973 | *
974 | * The following are provided as chainable getters to
975 | * improve the readability of your assertions. They
976 | * do not provide testing capabilities unless they
977 | * have been overwritten by a plugin.
978 | *
979 | * **Chains**
980 | *
981 | * - to
982 | * - be
983 | * - been
984 | * - is
985 | * - that
986 | * - which
987 | * - and
988 | * - has
989 | * - have
990 | * - with
991 | * - at
992 | * - of
993 | * - same
994 | *
995 | * @name language chains
996 | * @api public
997 | */
998 |
999 | [ 'to', 'be', 'been'
1000 | , 'is', 'and', 'has', 'have'
1001 | , 'with', 'that', 'which', 'at'
1002 | , 'of', 'same' ].forEach(function (chain) {
1003 | Assertion.addProperty(chain, function () {
1004 | return this;
1005 | });
1006 | });
1007 |
1008 | /**
1009 | * ### .not
1010 | *
1011 | * Negates any of assertions following in the chain.
1012 | *
1013 | * expect(foo).to.not.equal('bar');
1014 | * expect(goodFn).to.not.throw(Error);
1015 | * expect({ foo: 'baz' }).to.have.property('foo')
1016 | * .and.not.equal('bar');
1017 | *
1018 | * @name not
1019 | * @api public
1020 | */
1021 |
1022 | Assertion.addProperty('not', function () {
1023 | flag(this, 'negate', true);
1024 | });
1025 |
1026 | /**
1027 | * ### .deep
1028 | *
1029 | * Sets the `deep` flag, later used by the `equal` and
1030 | * `property` assertions.
1031 | *
1032 | * expect(foo).to.deep.equal({ bar: 'baz' });
1033 | * expect({ foo: { bar: { baz: 'quux' } } })
1034 | * .to.have.deep.property('foo.bar.baz', 'quux');
1035 | *
1036 | * `.deep.property` special characters can be escaped
1037 | * by adding two slashes before the `.` or `[]`.
1038 | *
1039 | * var deepCss = { '.link': { '[target]': 42 }};
1040 | * expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);
1041 | *
1042 | * @name deep
1043 | * @api public
1044 | */
1045 |
1046 | Assertion.addProperty('deep', function () {
1047 | flag(this, 'deep', true);
1048 | });
1049 |
1050 | /**
1051 | * ### .any
1052 | *
1053 | * Sets the `any` flag, (opposite of the `all` flag)
1054 | * later used in the `keys` assertion.
1055 | *
1056 | * expect(foo).to.have.any.keys('bar', 'baz');
1057 | *
1058 | * @name any
1059 | * @api public
1060 | */
1061 |
1062 | Assertion.addProperty('any', function () {
1063 | flag(this, 'any', true);
1064 | flag(this, 'all', false)
1065 | });
1066 |
1067 |
1068 | /**
1069 | * ### .all
1070 | *
1071 | * Sets the `all` flag (opposite of the `any` flag)
1072 | * later used by the `keys` assertion.
1073 | *
1074 | * expect(foo).to.have.all.keys('bar', 'baz');
1075 | *
1076 | * @name all
1077 | * @api public
1078 | */
1079 |
1080 | Assertion.addProperty('all', function () {
1081 | flag(this, 'all', true);
1082 | flag(this, 'any', false);
1083 | });
1084 |
1085 | /**
1086 | * ### .a(type)
1087 | *
1088 | * The `a` and `an` assertions are aliases that can be
1089 | * used either as language chains or to assert a value's
1090 | * type.
1091 | *
1092 | * // typeof
1093 | * expect('test').to.be.a('string');
1094 | * expect({ foo: 'bar' }).to.be.an('object');
1095 | * expect(null).to.be.a('null');
1096 | * expect(undefined).to.be.an('undefined');
1097 | *
1098 | * // language chain
1099 | * expect(foo).to.be.an.instanceof(Foo);
1100 | *
1101 | * @name a
1102 | * @alias an
1103 | * @param {String} type
1104 | * @param {String} message _optional_
1105 | * @api public
1106 | */
1107 |
1108 | function an (type, msg) {
1109 | if (msg) flag(this, 'message', msg);
1110 | type = type.toLowerCase();
1111 | var obj = flag(this, 'object')
1112 | , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';
1113 |
1114 | this.assert(
1115 | type === _.type(obj)
1116 | , 'expected #{this} to be ' + article + type
1117 | , 'expected #{this} not to be ' + article + type
1118 | );
1119 | }
1120 |
1121 | Assertion.addChainableMethod('an', an);
1122 | Assertion.addChainableMethod('a', an);
1123 |
1124 | /**
1125 | * ### .include(value)
1126 | *
1127 | * The `include` and `contain` assertions can be used as either property
1128 | * based language chains or as methods to assert the inclusion of an object
1129 | * in an array or a substring in a string. When used as language chains,
1130 | * they toggle the `contains` flag for the `keys` assertion.
1131 | *
1132 | * expect([1,2,3]).to.include(2);
1133 | * expect('foobar').to.contain('foo');
1134 | * expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
1135 | *
1136 | * @name include
1137 | * @alias contain
1138 | * @alias includes
1139 | * @alias contains
1140 | * @param {Object|String|Number} obj
1141 | * @param {String} message _optional_
1142 | * @api public
1143 | */
1144 |
1145 | function includeChainingBehavior () {
1146 | flag(this, 'contains', true);
1147 | }
1148 |
1149 | function include (val, msg) {
1150 | if (msg) flag(this, 'message', msg);
1151 | var obj = flag(this, 'object');
1152 | var expected = false;
1153 | if (_.type(obj) === 'array' && _.type(val) === 'object') {
1154 | for (var i in obj) {
1155 | if (_.eql(obj[i], val)) {
1156 | expected = true;
1157 | break;
1158 | }
1159 | }
1160 | } else if (_.type(val) === 'object') {
1161 | if (!flag(this, 'negate')) {
1162 | for (var k in val) new Assertion(obj).property(k, val[k]);
1163 | return;
1164 | }
1165 | var subset = {};
1166 | for (var k in val) subset[k] = obj[k];
1167 | expected = _.eql(subset, val);
1168 | } else {
1169 | expected = obj && ~obj.indexOf(val);
1170 | }
1171 | this.assert(
1172 | expected
1173 | , 'expected #{this} to include ' + _.inspect(val)
1174 | , 'expected #{this} to not include ' + _.inspect(val));
1175 | }
1176 |
1177 | Assertion.addChainableMethod('include', include, includeChainingBehavior);
1178 | Assertion.addChainableMethod('contain', include, includeChainingBehavior);
1179 | Assertion.addChainableMethod('contains', include, includeChainingBehavior);
1180 | Assertion.addChainableMethod('includes', include, includeChainingBehavior);
1181 |
1182 | /**
1183 | * ### .ok
1184 | *
1185 | * Asserts that the target is truthy.
1186 | *
1187 | * expect('everthing').to.be.ok;
1188 | * expect(1).to.be.ok;
1189 | * expect(false).to.not.be.ok;
1190 | * expect(undefined).to.not.be.ok;
1191 | * expect(null).to.not.be.ok;
1192 | *
1193 | * @name ok
1194 | * @api public
1195 | */
1196 |
1197 | Assertion.addProperty('ok', function () {
1198 | this.assert(
1199 | flag(this, 'object')
1200 | , 'expected #{this} to be truthy'
1201 | , 'expected #{this} to be falsy');
1202 | });
1203 |
1204 | /**
1205 | * ### .true
1206 | *
1207 | * Asserts that the target is `true`.
1208 | *
1209 | * expect(true).to.be.true;
1210 | * expect(1).to.not.be.true;
1211 | *
1212 | * @name true
1213 | * @api public
1214 | */
1215 |
1216 | Assertion.addProperty('true', function () {
1217 | this.assert(
1218 | true === flag(this, 'object')
1219 | , 'expected #{this} to be true'
1220 | , 'expected #{this} to be false'
1221 | , this.negate ? false : true
1222 | );
1223 | });
1224 |
1225 | /**
1226 | * ### .false
1227 | *
1228 | * Asserts that the target is `false`.
1229 | *
1230 | * expect(false).to.be.false;
1231 | * expect(0).to.not.be.false;
1232 | *
1233 | * @name false
1234 | * @api public
1235 | */
1236 |
1237 | Assertion.addProperty('false', function () {
1238 | this.assert(
1239 | false === flag(this, 'object')
1240 | , 'expected #{this} to be false'
1241 | , 'expected #{this} to be true'
1242 | , this.negate ? true : false
1243 | );
1244 | });
1245 |
1246 | /**
1247 | * ### .null
1248 | *
1249 | * Asserts that the target is `null`.
1250 | *
1251 | * expect(null).to.be.null;
1252 | * expect(undefined).to.not.be.null;
1253 | *
1254 | * @name null
1255 | * @api public
1256 | */
1257 |
1258 | Assertion.addProperty('null', function () {
1259 | this.assert(
1260 | null === flag(this, 'object')
1261 | , 'expected #{this} to be null'
1262 | , 'expected #{this} not to be null'
1263 | );
1264 | });
1265 |
1266 | /**
1267 | * ### .undefined
1268 | *
1269 | * Asserts that the target is `undefined`.
1270 | *
1271 | * expect(undefined).to.be.undefined;
1272 | * expect(null).to.not.be.undefined;
1273 | *
1274 | * @name undefined
1275 | * @api public
1276 | */
1277 |
1278 | Assertion.addProperty('undefined', function () {
1279 | this.assert(
1280 | undefined === flag(this, 'object')
1281 | , 'expected #{this} to be undefined'
1282 | , 'expected #{this} not to be undefined'
1283 | );
1284 | });
1285 |
1286 | /**
1287 | * ### .exist
1288 | *
1289 | * Asserts that the target is neither `null` nor `undefined`.
1290 | *
1291 | * var foo = 'hi'
1292 | * , bar = null
1293 | * , baz;
1294 | *
1295 | * expect(foo).to.exist;
1296 | * expect(bar).to.not.exist;
1297 | * expect(baz).to.not.exist;
1298 | *
1299 | * @name exist
1300 | * @api public
1301 | */
1302 |
1303 | Assertion.addProperty('exist', function () {
1304 | this.assert(
1305 | null != flag(this, 'object')
1306 | , 'expected #{this} to exist'
1307 | , 'expected #{this} to not exist'
1308 | );
1309 | });
1310 |
1311 |
1312 | /**
1313 | * ### .empty
1314 | *
1315 | * Asserts that the target's length is `0`. For arrays and strings, it checks
1316 | * the `length` property. For objects, it gets the count of
1317 | * enumerable keys.
1318 | *
1319 | * expect([]).to.be.empty;
1320 | * expect('').to.be.empty;
1321 | * expect({}).to.be.empty;
1322 | *
1323 | * @name empty
1324 | * @api public
1325 | */
1326 |
1327 | Assertion.addProperty('empty', function () {
1328 | var obj = flag(this, 'object')
1329 | , expected = obj;
1330 |
1331 | if (Array.isArray(obj) || 'string' === typeof object) {
1332 | expected = obj.length;
1333 | } else if (typeof obj === 'object') {
1334 | expected = Object.keys(obj).length;
1335 | }
1336 |
1337 | this.assert(
1338 | !expected
1339 | , 'expected #{this} to be empty'
1340 | , 'expected #{this} not to be empty'
1341 | );
1342 | });
1343 |
1344 | /**
1345 | * ### .arguments
1346 | *
1347 | * Asserts that the target is an arguments object.
1348 | *
1349 | * function test () {
1350 | * expect(arguments).to.be.arguments;
1351 | * }
1352 | *
1353 | * @name arguments
1354 | * @alias Arguments
1355 | * @api public
1356 | */
1357 |
1358 | function checkArguments () {
1359 | var obj = flag(this, 'object')
1360 | , type = Object.prototype.toString.call(obj);
1361 | this.assert(
1362 | '[object Arguments]' === type
1363 | , 'expected #{this} to be arguments but got ' + type
1364 | , 'expected #{this} to not be arguments'
1365 | );
1366 | }
1367 |
1368 | Assertion.addProperty('arguments', checkArguments);
1369 | Assertion.addProperty('Arguments', checkArguments);
1370 |
1371 | /**
1372 | * ### .equal(value)
1373 | *
1374 | * Asserts that the target is strictly equal (`===`) to `value`.
1375 | * Alternately, if the `deep` flag is set, asserts that
1376 | * the target is deeply equal to `value`.
1377 | *
1378 | * expect('hello').to.equal('hello');
1379 | * expect(42).to.equal(42);
1380 | * expect(1).to.not.equal(true);
1381 | * expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });
1382 | * expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });
1383 | *
1384 | * @name equal
1385 | * @alias equals
1386 | * @alias eq
1387 | * @alias deep.equal
1388 | * @param {Mixed} value
1389 | * @param {String} message _optional_
1390 | * @api public
1391 | */
1392 |
1393 | function assertEqual (val, msg) {
1394 | if (msg) flag(this, 'message', msg);
1395 | var obj = flag(this, 'object');
1396 | if (flag(this, 'deep')) {
1397 | return this.eql(val);
1398 | } else {
1399 | this.assert(
1400 | val === obj
1401 | , 'expected #{this} to equal #{exp}'
1402 | , 'expected #{this} to not equal #{exp}'
1403 | , val
1404 | , this._obj
1405 | , true
1406 | );
1407 | }
1408 | }
1409 |
1410 | Assertion.addMethod('equal', assertEqual);
1411 | Assertion.addMethod('equals', assertEqual);
1412 | Assertion.addMethod('eq', assertEqual);
1413 |
1414 | /**
1415 | * ### .eql(value)
1416 | *
1417 | * Asserts that the target is deeply equal to `value`.
1418 | *
1419 | * expect({ foo: 'bar' }).to.eql({ foo: 'bar' });
1420 | * expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);
1421 | *
1422 | * @name eql
1423 | * @alias eqls
1424 | * @param {Mixed} value
1425 | * @param {String} message _optional_
1426 | * @api public
1427 | */
1428 |
1429 | function assertEql(obj, msg) {
1430 | if (msg) flag(this, 'message', msg);
1431 | this.assert(
1432 | _.eql(obj, flag(this, 'object'))
1433 | , 'expected #{this} to deeply equal #{exp}'
1434 | , 'expected #{this} to not deeply equal #{exp}'
1435 | , obj
1436 | , this._obj
1437 | , true
1438 | );
1439 | }
1440 |
1441 | Assertion.addMethod('eql', assertEql);
1442 | Assertion.addMethod('eqls', assertEql);
1443 |
1444 | /**
1445 | * ### .above(value)
1446 | *
1447 | * Asserts that the target is greater than `value`.
1448 | *
1449 | * expect(10).to.be.above(5);
1450 | *
1451 | * Can also be used in conjunction with `length` to
1452 | * assert a minimum length. The benefit being a
1453 | * more informative error message than if the length
1454 | * was supplied directly.
1455 | *
1456 | * expect('foo').to.have.length.above(2);
1457 | * expect([ 1, 2, 3 ]).to.have.length.above(2);
1458 | *
1459 | * @name above
1460 | * @alias gt
1461 | * @alias greaterThan
1462 | * @param {Number} value
1463 | * @param {String} message _optional_
1464 | * @api public
1465 | */
1466 |
1467 | function assertAbove (n, msg) {
1468 | if (msg) flag(this, 'message', msg);
1469 | var obj = flag(this, 'object');
1470 | if (flag(this, 'doLength')) {
1471 | new Assertion(obj, msg).to.have.property('length');
1472 | var len = obj.length;
1473 | this.assert(
1474 | len > n
1475 | , 'expected #{this} to have a length above #{exp} but got #{act}'
1476 | , 'expected #{this} to not have a length above #{exp}'
1477 | , n
1478 | , len
1479 | );
1480 | } else {
1481 | this.assert(
1482 | obj > n
1483 | , 'expected #{this} to be above ' + n
1484 | , 'expected #{this} to be at most ' + n
1485 | );
1486 | }
1487 | }
1488 |
1489 | Assertion.addMethod('above', assertAbove);
1490 | Assertion.addMethod('gt', assertAbove);
1491 | Assertion.addMethod('greaterThan', assertAbove);
1492 |
1493 | /**
1494 | * ### .least(value)
1495 | *
1496 | * Asserts that the target is greater than or equal to `value`.
1497 | *
1498 | * expect(10).to.be.at.least(10);
1499 | *
1500 | * Can also be used in conjunction with `length` to
1501 | * assert a minimum length. The benefit being a
1502 | * more informative error message than if the length
1503 | * was supplied directly.
1504 | *
1505 | * expect('foo').to.have.length.of.at.least(2);
1506 | * expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);
1507 | *
1508 | * @name least
1509 | * @alias gte
1510 | * @param {Number} value
1511 | * @param {String} message _optional_
1512 | * @api public
1513 | */
1514 |
1515 | function assertLeast (n, msg) {
1516 | if (msg) flag(this, 'message', msg);
1517 | var obj = flag(this, 'object');
1518 | if (flag(this, 'doLength')) {
1519 | new Assertion(obj, msg).to.have.property('length');
1520 | var len = obj.length;
1521 | this.assert(
1522 | len >= n
1523 | , 'expected #{this} to have a length at least #{exp} but got #{act}'
1524 | , 'expected #{this} to have a length below #{exp}'
1525 | , n
1526 | , len
1527 | );
1528 | } else {
1529 | this.assert(
1530 | obj >= n
1531 | , 'expected #{this} to be at least ' + n
1532 | , 'expected #{this} to be below ' + n
1533 | );
1534 | }
1535 | }
1536 |
1537 | Assertion.addMethod('least', assertLeast);
1538 | Assertion.addMethod('gte', assertLeast);
1539 |
1540 | /**
1541 | * ### .below(value)
1542 | *
1543 | * Asserts that the target is less than `value`.
1544 | *
1545 | * expect(5).to.be.below(10);
1546 | *
1547 | * Can also be used in conjunction with `length` to
1548 | * assert a maximum length. The benefit being a
1549 | * more informative error message than if the length
1550 | * was supplied directly.
1551 | *
1552 | * expect('foo').to.have.length.below(4);
1553 | * expect([ 1, 2, 3 ]).to.have.length.below(4);
1554 | *
1555 | * @name below
1556 | * @alias lt
1557 | * @alias lessThan
1558 | * @param {Number} value
1559 | * @param {String} message _optional_
1560 | * @api public
1561 | */
1562 |
1563 | function assertBelow (n, msg) {
1564 | if (msg) flag(this, 'message', msg);
1565 | var obj = flag(this, 'object');
1566 | if (flag(this, 'doLength')) {
1567 | new Assertion(obj, msg).to.have.property('length');
1568 | var len = obj.length;
1569 | this.assert(
1570 | len < n
1571 | , 'expected #{this} to have a length below #{exp} but got #{act}'
1572 | , 'expected #{this} to not have a length below #{exp}'
1573 | , n
1574 | , len
1575 | );
1576 | } else {
1577 | this.assert(
1578 | obj < n
1579 | , 'expected #{this} to be below ' + n
1580 | , 'expected #{this} to be at least ' + n
1581 | );
1582 | }
1583 | }
1584 |
1585 | Assertion.addMethod('below', assertBelow);
1586 | Assertion.addMethod('lt', assertBelow);
1587 | Assertion.addMethod('lessThan', assertBelow);
1588 |
1589 | /**
1590 | * ### .most(value)
1591 | *
1592 | * Asserts that the target is less than or equal to `value`.
1593 | *
1594 | * expect(5).to.be.at.most(5);
1595 | *
1596 | * Can also be used in conjunction with `length` to
1597 | * assert a maximum length. The benefit being a
1598 | * more informative error message than if the length
1599 | * was supplied directly.
1600 | *
1601 | * expect('foo').to.have.length.of.at.most(4);
1602 | * expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);
1603 | *
1604 | * @name most
1605 | * @alias lte
1606 | * @param {Number} value
1607 | * @param {String} message _optional_
1608 | * @api public
1609 | */
1610 |
1611 | function assertMost (n, msg) {
1612 | if (msg) flag(this, 'message', msg);
1613 | var obj = flag(this, 'object');
1614 | if (flag(this, 'doLength')) {
1615 | new Assertion(obj, msg).to.have.property('length');
1616 | var len = obj.length;
1617 | this.assert(
1618 | len <= n
1619 | , 'expected #{this} to have a length at most #{exp} but got #{act}'
1620 | , 'expected #{this} to have a length above #{exp}'
1621 | , n
1622 | , len
1623 | );
1624 | } else {
1625 | this.assert(
1626 | obj <= n
1627 | , 'expected #{this} to be at most ' + n
1628 | , 'expected #{this} to be above ' + n
1629 | );
1630 | }
1631 | }
1632 |
1633 | Assertion.addMethod('most', assertMost);
1634 | Assertion.addMethod('lte', assertMost);
1635 |
1636 | /**
1637 | * ### .within(start, finish)
1638 | *
1639 | * Asserts that the target is within a range.
1640 | *
1641 | * expect(7).to.be.within(5,10);
1642 | *
1643 | * Can also be used in conjunction with `length` to
1644 | * assert a length range. The benefit being a
1645 | * more informative error message than if the length
1646 | * was supplied directly.
1647 | *
1648 | * expect('foo').to.have.length.within(2,4);
1649 | * expect([ 1, 2, 3 ]).to.have.length.within(2,4);
1650 | *
1651 | * @name within
1652 | * @param {Number} start lowerbound inclusive
1653 | * @param {Number} finish upperbound inclusive
1654 | * @param {String} message _optional_
1655 | * @api public
1656 | */
1657 |
1658 | Assertion.addMethod('within', function (start, finish, msg) {
1659 | if (msg) flag(this, 'message', msg);
1660 | var obj = flag(this, 'object')
1661 | , range = start + '..' + finish;
1662 | if (flag(this, 'doLength')) {
1663 | new Assertion(obj, msg).to.have.property('length');
1664 | var len = obj.length;
1665 | this.assert(
1666 | len >= start && len <= finish
1667 | , 'expected #{this} to have a length within ' + range
1668 | , 'expected #{this} to not have a length within ' + range
1669 | );
1670 | } else {
1671 | this.assert(
1672 | obj >= start && obj <= finish
1673 | , 'expected #{this} to be within ' + range
1674 | , 'expected #{this} to not be within ' + range
1675 | );
1676 | }
1677 | });
1678 |
1679 | /**
1680 | * ### .instanceof(constructor)
1681 | *
1682 | * Asserts that the target is an instance of `constructor`.
1683 | *
1684 | * var Tea = function (name) { this.name = name; }
1685 | * , Chai = new Tea('chai');
1686 | *
1687 | * expect(Chai).to.be.an.instanceof(Tea);
1688 | * expect([ 1, 2, 3 ]).to.be.instanceof(Array);
1689 | *
1690 | * @name instanceof
1691 | * @param {Constructor} constructor
1692 | * @param {String} message _optional_
1693 | * @alias instanceOf
1694 | * @api public
1695 | */
1696 |
1697 | function assertInstanceOf (constructor, msg) {
1698 | if (msg) flag(this, 'message', msg);
1699 | var name = _.getName(constructor);
1700 | this.assert(
1701 | flag(this, 'object') instanceof constructor
1702 | , 'expected #{this} to be an instance of ' + name
1703 | , 'expected #{this} to not be an instance of ' + name
1704 | );
1705 | };
1706 |
1707 | Assertion.addMethod('instanceof', assertInstanceOf);
1708 | Assertion.addMethod('instanceOf', assertInstanceOf);
1709 |
1710 | /**
1711 | * ### .property(name, [value])
1712 | *
1713 | * Asserts that the target has a property `name`, optionally asserting that
1714 | * the value of that property is strictly equal to `value`.
1715 | * If the `deep` flag is set, you can use dot- and bracket-notation for deep
1716 | * references into objects and arrays.
1717 | *
1718 | * // simple referencing
1719 | * var obj = { foo: 'bar' };
1720 | * expect(obj).to.have.property('foo');
1721 | * expect(obj).to.have.property('foo', 'bar');
1722 | *
1723 | * // deep referencing
1724 | * var deepObj = {
1725 | * green: { tea: 'matcha' }
1726 | * , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]
1727 | * };
1728 | *
1729 | * expect(deepObj).to.have.deep.property('green.tea', 'matcha');
1730 | * expect(deepObj).to.have.deep.property('teas[1]', 'matcha');
1731 | * expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');
1732 | *
1733 | * You can also use an array as the starting point of a `deep.property`
1734 | * assertion, or traverse nested arrays.
1735 | *
1736 | * var arr = [
1737 | * [ 'chai', 'matcha', 'konacha' ]
1738 | * , [ { tea: 'chai' }
1739 | * , { tea: 'matcha' }
1740 | * , { tea: 'konacha' } ]
1741 | * ];
1742 | *
1743 | * expect(arr).to.have.deep.property('[0][1]', 'matcha');
1744 | * expect(arr).to.have.deep.property('[1][2].tea', 'konacha');
1745 | *
1746 | * Furthermore, `property` changes the subject of the assertion
1747 | * to be the value of that property from the original object. This
1748 | * permits for further chainable assertions on that property.
1749 | *
1750 | * expect(obj).to.have.property('foo')
1751 | * .that.is.a('string');
1752 | * expect(deepObj).to.have.property('green')
1753 | * .that.is.an('object')
1754 | * .that.deep.equals({ tea: 'matcha' });
1755 | * expect(deepObj).to.have.property('teas')
1756 | * .that.is.an('array')
1757 | * .with.deep.property('[2]')
1758 | * .that.deep.equals({ tea: 'konacha' });
1759 | *
1760 | * Note that dots and bracket in `name` must be backslash-escaped when
1761 | * the `deep` flag is set, while they must NOT be escaped when the `deep`
1762 | * flag is not set.
1763 | *
1764 | * // simple referencing
1765 | * var css = { '.link[target]': 42 };
1766 | * expect(css).to.have.property('.link[target]', 42);
1767 | *
1768 | * // deep referencing
1769 | * var deepCss = { '.link': { '[target]': 42 }};
1770 | * expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);
1771 | *
1772 | * @name property
1773 | * @alias deep.property
1774 | * @param {String} name
1775 | * @param {Mixed} value (optional)
1776 | * @param {String} message _optional_
1777 | * @returns value of property for chaining
1778 | * @api public
1779 | */
1780 |
1781 | Assertion.addMethod('property', function (name, val, msg) {
1782 | if (msg) flag(this, 'message', msg);
1783 |
1784 | var isDeep = !!flag(this, 'deep')
1785 | , descriptor = isDeep ? 'deep property ' : 'property '
1786 | , negate = flag(this, 'negate')
1787 | , obj = flag(this, 'object')
1788 | , pathInfo = isDeep ? _.getPathInfo(name, obj) : null
1789 | , hasProperty = isDeep
1790 | ? pathInfo.exists
1791 | : _.hasProperty(name, obj)
1792 | , value = isDeep
1793 | ? pathInfo.value
1794 | : obj[name];
1795 |
1796 | if (negate && undefined !== val) {
1797 | if (undefined === value) {
1798 | msg = (msg != null) ? msg + ': ' : '';
1799 | throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name));
1800 | }
1801 | } else {
1802 | this.assert(
1803 | hasProperty
1804 | , 'expected #{this} to have a ' + descriptor + _.inspect(name)
1805 | , 'expected #{this} to not have ' + descriptor + _.inspect(name));
1806 | }
1807 |
1808 | if (undefined !== val) {
1809 | this.assert(
1810 | val === value
1811 | , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'
1812 | , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}'
1813 | , val
1814 | , value
1815 | );
1816 | }
1817 |
1818 | flag(this, 'object', value);
1819 | });
1820 |
1821 |
1822 | /**
1823 | * ### .ownProperty(name)
1824 | *
1825 | * Asserts that the target has an own property `name`.
1826 | *
1827 | * expect('test').to.have.ownProperty('length');
1828 | *
1829 | * @name ownProperty
1830 | * @alias haveOwnProperty
1831 | * @param {String} name
1832 | * @param {String} message _optional_
1833 | * @api public
1834 | */
1835 |
1836 | function assertOwnProperty (name, msg) {
1837 | if (msg) flag(this, 'message', msg);
1838 | var obj = flag(this, 'object');
1839 | this.assert(
1840 | obj.hasOwnProperty(name)
1841 | , 'expected #{this} to have own property ' + _.inspect(name)
1842 | , 'expected #{this} to not have own property ' + _.inspect(name)
1843 | );
1844 | }
1845 |
1846 | Assertion.addMethod('ownProperty', assertOwnProperty);
1847 | Assertion.addMethod('haveOwnProperty', assertOwnProperty);
1848 |
1849 | /**
1850 | * ### .ownPropertyDescriptor(name[, descriptor[, message]])
1851 | *
1852 | * Asserts that the target has an own property descriptor `name`, that optionally matches `descriptor`.
1853 | *
1854 | * expect('test').to.have.ownPropertyDescriptor('length');
1855 | * expect('test').to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 4 });
1856 | * expect('test').not.to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 3 });
1857 | * expect('test').ownPropertyDescriptor('length').to.have.property('enumerable', false);
1858 | * expect('test').ownPropertyDescriptor('length').to.have.keys('value');
1859 | *
1860 | * @name ownPropertyDescriptor
1861 | * @alias haveOwnPropertyDescriptor
1862 | * @param {String} name
1863 | * @param {Object} descriptor _optional_
1864 | * @param {String} message _optional_
1865 | * @api public
1866 | */
1867 |
1868 | function assertOwnPropertyDescriptor (name, descriptor, msg) {
1869 | if (typeof descriptor === 'string') {
1870 | msg = descriptor;
1871 | descriptor = null;
1872 | }
1873 | if (msg) flag(this, 'message', msg);
1874 | var obj = flag(this, 'object');
1875 | var actualDescriptor = Object.getOwnPropertyDescriptor(Object(obj), name);
1876 | if (actualDescriptor && descriptor) {
1877 | this.assert(
1878 | _.eql(descriptor, actualDescriptor)
1879 | , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to match ' + _.inspect(descriptor) + ', got ' + _.inspect(actualDescriptor)
1880 | , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to not match ' + _.inspect(descriptor)
1881 | , descriptor
1882 | , actualDescriptor
1883 | , true
1884 | );
1885 | } else {
1886 | this.assert(
1887 | actualDescriptor
1888 | , 'expected #{this} to have an own property descriptor for ' + _.inspect(name)
1889 | , 'expected #{this} to not have an own property descriptor for ' + _.inspect(name)
1890 | );
1891 | }
1892 | flag(this, 'object', actualDescriptor);
1893 | }
1894 |
1895 | Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor);
1896 | Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor);
1897 |
1898 | /**
1899 | * ### .length(value)
1900 | *
1901 | * Asserts that the target's `length` property has
1902 | * the expected value.
1903 | *
1904 | * expect([ 1, 2, 3]).to.have.length(3);
1905 | * expect('foobar').to.have.length(6);
1906 | *
1907 | * Can also be used as a chain precursor to a value
1908 | * comparison for the length property.
1909 | *
1910 | * expect('foo').to.have.length.above(2);
1911 | * expect([ 1, 2, 3 ]).to.have.length.above(2);
1912 | * expect('foo').to.have.length.below(4);
1913 | * expect([ 1, 2, 3 ]).to.have.length.below(4);
1914 | * expect('foo').to.have.length.within(2,4);
1915 | * expect([ 1, 2, 3 ]).to.have.length.within(2,4);
1916 | *
1917 | * @name length
1918 | * @alias lengthOf
1919 | * @param {Number} length
1920 | * @param {String} message _optional_
1921 | * @api public
1922 | */
1923 |
1924 | function assertLengthChain () {
1925 | flag(this, 'doLength', true);
1926 | }
1927 |
1928 | function assertLength (n, msg) {
1929 | if (msg) flag(this, 'message', msg);
1930 | var obj = flag(this, 'object');
1931 | new Assertion(obj, msg).to.have.property('length');
1932 | var len = obj.length;
1933 |
1934 | this.assert(
1935 | len == n
1936 | , 'expected #{this} to have a length of #{exp} but got #{act}'
1937 | , 'expected #{this} to not have a length of #{act}'
1938 | , n
1939 | , len
1940 | );
1941 | }
1942 |
1943 | Assertion.addChainableMethod('length', assertLength, assertLengthChain);
1944 | Assertion.addMethod('lengthOf', assertLength);
1945 |
1946 | /**
1947 | * ### .match(regexp)
1948 | *
1949 | * Asserts that the target matches a regular expression.
1950 | *
1951 | * expect('foobar').to.match(/^foo/);
1952 | *
1953 | * @name match
1954 | * @param {RegExp} RegularExpression
1955 | * @param {String} message _optional_
1956 | * @api public
1957 | */
1958 |
1959 | Assertion.addMethod('match', function (re, msg) {
1960 | if (msg) flag(this, 'message', msg);
1961 | var obj = flag(this, 'object');
1962 | this.assert(
1963 | re.exec(obj)
1964 | , 'expected #{this} to match ' + re
1965 | , 'expected #{this} not to match ' + re
1966 | );
1967 | });
1968 |
1969 | /**
1970 | * ### .string(string)
1971 | *
1972 | * Asserts that the string target contains another string.
1973 | *
1974 | * expect('foobar').to.have.string('bar');
1975 | *
1976 | * @name string
1977 | * @param {String} string
1978 | * @param {String} message _optional_
1979 | * @api public
1980 | */
1981 |
1982 | Assertion.addMethod('string', function (str, msg) {
1983 | if (msg) flag(this, 'message', msg);
1984 | var obj = flag(this, 'object');
1985 | new Assertion(obj, msg).is.a('string');
1986 |
1987 | this.assert(
1988 | ~obj.indexOf(str)
1989 | , 'expected #{this} to contain ' + _.inspect(str)
1990 | , 'expected #{this} to not contain ' + _.inspect(str)
1991 | );
1992 | });
1993 |
1994 |
1995 | /**
1996 | * ### .keys(key1, [key2], [...])
1997 | *
1998 | * Asserts that the target contains any or all of the passed-in keys.
1999 | * Use in combination with `any`, `all`, `contains`, or `have` will affect
2000 | * what will pass.
2001 | *
2002 | * When used in conjunction with `any`, at least one key that is passed
2003 | * in must exist in the target object. This is regardless whether or not
2004 | * the `have` or `contain` qualifiers are used. Note, either `any` or `all`
2005 | * should be used in the assertion. If neither are used, the assertion is
2006 | * defaulted to `all`.
2007 | *
2008 | * When both `all` and `contain` are used, the target object must have at
2009 | * least all of the passed-in keys but may have more keys not listed.
2010 | *
2011 | * When both `all` and `have` are used, the target object must both contain
2012 | * all of the passed-in keys AND the number of keys in the target object must
2013 | * match the number of keys passed in (in other words, a target object must
2014 | * have all and only all of the passed-in keys).
2015 | *
2016 | * expect({ foo: 1, bar: 2 }).to.have.any.keys('foo', 'baz');
2017 | * expect({ foo: 1, bar: 2 }).to.have.any.keys('foo');
2018 | * expect({ foo: 1, bar: 2 }).to.contain.any.keys('bar', 'baz');
2019 | * expect({ foo: 1, bar: 2 }).to.contain.any.keys(['foo']);
2020 | * expect({ foo: 1, bar: 2 }).to.contain.any.keys({'foo': 6});
2021 | * expect({ foo: 1, bar: 2 }).to.have.all.keys(['bar', 'foo']);
2022 | * expect({ foo: 1, bar: 2 }).to.have.all.keys({'bar': 6, 'foo': 7});
2023 | * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys(['bar', 'foo']);
2024 | * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys([{'bar': 6}}]);
2025 | *
2026 | *
2027 | * @name keys
2028 | * @alias key
2029 | * @param {String...|Array|Object} keys
2030 | * @api public
2031 | */
2032 |
2033 | function assertKeys (keys) {
2034 | var obj = flag(this, 'object')
2035 | , str
2036 | , ok = true
2037 | , mixedArgsMsg = 'keys must be given single argument of Array|Object|String, or multiple String arguments';
2038 |
2039 | switch (_.type(keys)) {
2040 | case "array":
2041 | if (arguments.length > 1) throw (new Error(mixedArgsMsg));
2042 | break;
2043 | case "object":
2044 | if (arguments.length > 1) throw (new Error(mixedArgsMsg));
2045 | keys = Object.keys(keys);
2046 | break;
2047 | default:
2048 | keys = Array.prototype.slice.call(arguments);
2049 | }
2050 |
2051 | if (!keys.length) throw new Error('keys required');
2052 |
2053 | var actual = Object.keys(obj)
2054 | , expected = keys
2055 | , len = keys.length
2056 | , any = flag(this, 'any')
2057 | , all = flag(this, 'all');
2058 |
2059 | if (!any && !all) {
2060 | all = true;
2061 | }
2062 |
2063 | // Has any
2064 | if (any) {
2065 | var intersection = expected.filter(function(key) {
2066 | return ~actual.indexOf(key);
2067 | });
2068 | ok = intersection.length > 0;
2069 | }
2070 |
2071 | // Has all
2072 | if (all) {
2073 | ok = keys.every(function(key){
2074 | return ~actual.indexOf(key);
2075 | });
2076 | if (!flag(this, 'negate') && !flag(this, 'contains')) {
2077 | ok = ok && keys.length == actual.length;
2078 | }
2079 | }
2080 |
2081 | // Key string
2082 | if (len > 1) {
2083 | keys = keys.map(function(key){
2084 | return _.inspect(key);
2085 | });
2086 | var last = keys.pop();
2087 | if (all) {
2088 | str = keys.join(', ') + ', and ' + last;
2089 | }
2090 | if (any) {
2091 | str = keys.join(', ') + ', or ' + last;
2092 | }
2093 | } else {
2094 | str = _.inspect(keys[0]);
2095 | }
2096 |
2097 | // Form
2098 | str = (len > 1 ? 'keys ' : 'key ') + str;
2099 |
2100 | // Have / include
2101 | str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;
2102 |
2103 | // Assertion
2104 | this.assert(
2105 | ok
2106 | , 'expected #{this} to ' + str
2107 | , 'expected #{this} to not ' + str
2108 | , expected.slice(0).sort()
2109 | , actual.sort()
2110 | , true
2111 | );
2112 | }
2113 |
2114 | Assertion.addMethod('keys', assertKeys);
2115 | Assertion.addMethod('key', assertKeys);
2116 |
2117 | /**
2118 | * ### .throw(constructor)
2119 | *
2120 | * Asserts that the function target will throw a specific error, or specific type of error
2121 | * (as determined using `instanceof`), optionally with a RegExp or string inclusion test
2122 | * for the error's message.
2123 | *
2124 | * var err = new ReferenceError('This is a bad function.');
2125 | * var fn = function () { throw err; }
2126 | * expect(fn).to.throw(ReferenceError);
2127 | * expect(fn).to.throw(Error);
2128 | * expect(fn).to.throw(/bad function/);
2129 | * expect(fn).to.not.throw('good function');
2130 | * expect(fn).to.throw(ReferenceError, /bad function/);
2131 | * expect(fn).to.throw(err);
2132 | * expect(fn).to.not.throw(new RangeError('Out of range.'));
2133 | *
2134 | * Please note that when a throw expectation is negated, it will check each
2135 | * parameter independently, starting with error constructor type. The appropriate way
2136 | * to check for the existence of a type of error but for a message that does not match
2137 | * is to use `and`.
2138 | *
2139 | * expect(fn).to.throw(ReferenceError)
2140 | * .and.not.throw(/good function/);
2141 | *
2142 | * @name throw
2143 | * @alias throws
2144 | * @alias Throw
2145 | * @param {ErrorConstructor} constructor
2146 | * @param {String|RegExp} expected error message
2147 | * @param {String} message _optional_
2148 | * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
2149 | * @returns error for chaining (null if no error)
2150 | * @api public
2151 | */
2152 |
2153 | function assertThrows (constructor, errMsg, msg) {
2154 | if (msg) flag(this, 'message', msg);
2155 | var obj = flag(this, 'object');
2156 | new Assertion(obj, msg).is.a('function');
2157 |
2158 | var thrown = false
2159 | , desiredError = null
2160 | , name = null
2161 | , thrownError = null;
2162 |
2163 | if (arguments.length === 0) {
2164 | errMsg = null;
2165 | constructor = null;
2166 | } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {
2167 | errMsg = constructor;
2168 | constructor = null;
2169 | } else if (constructor && constructor instanceof Error) {
2170 | desiredError = constructor;
2171 | constructor = null;
2172 | errMsg = null;
2173 | } else if (typeof constructor === 'function') {
2174 | name = constructor.prototype.name || constructor.name;
2175 | if (name === 'Error' && constructor !== Error) {
2176 | name = (new constructor()).name;
2177 | }
2178 | } else {
2179 | constructor = null;
2180 | }
2181 |
2182 | try {
2183 | obj();
2184 | } catch (err) {
2185 | // first, check desired error
2186 | if (desiredError) {
2187 | this.assert(
2188 | err === desiredError
2189 | , 'expected #{this} to throw #{exp} but #{act} was thrown'
2190 | , 'expected #{this} to not throw #{exp}'
2191 | , (desiredError instanceof Error ? desiredError.toString() : desiredError)
2192 | , (err instanceof Error ? err.toString() : err)
2193 | );
2194 |
2195 | flag(this, 'object', err);
2196 | return this;
2197 | }
2198 |
2199 | // next, check constructor
2200 | if (constructor) {
2201 | this.assert(
2202 | err instanceof constructor
2203 | , 'expected #{this} to throw #{exp} but #{act} was thrown'
2204 | , 'expected #{this} to not throw #{exp} but #{act} was thrown'
2205 | , name
2206 | , (err instanceof Error ? err.toString() : err)
2207 | );
2208 |
2209 | if (!errMsg) {
2210 | flag(this, 'object', err);
2211 | return this;
2212 | }
2213 | }
2214 |
2215 | // next, check message
2216 | var message = 'object' === _.type(err) && "message" in err
2217 | ? err.message
2218 | : '' + err;
2219 |
2220 | if ((message != null) && errMsg && errMsg instanceof RegExp) {
2221 | this.assert(
2222 | errMsg.exec(message)
2223 | , 'expected #{this} to throw error matching #{exp} but got #{act}'
2224 | , 'expected #{this} to throw error not matching #{exp}'
2225 | , errMsg
2226 | , message
2227 | );
2228 |
2229 | flag(this, 'object', err);
2230 | return this;
2231 | } else if ((message != null) && errMsg && 'string' === typeof errMsg) {
2232 | this.assert(
2233 | ~message.indexOf(errMsg)
2234 | , 'expected #{this} to throw error including #{exp} but got #{act}'
2235 | , 'expected #{this} to throw error not including #{act}'
2236 | , errMsg
2237 | , message
2238 | );
2239 |
2240 | flag(this, 'object', err);
2241 | return this;
2242 | } else {
2243 | thrown = true;
2244 | thrownError = err;
2245 | }
2246 | }
2247 |
2248 | var actuallyGot = ''
2249 | , expectedThrown = name !== null
2250 | ? name
2251 | : desiredError
2252 | ? '#{exp}' //_.inspect(desiredError)
2253 | : 'an error';
2254 |
2255 | if (thrown) {
2256 | actuallyGot = ' but #{act} was thrown'
2257 | }
2258 |
2259 | this.assert(
2260 | thrown === true
2261 | , 'expected #{this} to throw ' + expectedThrown + actuallyGot
2262 | , 'expected #{this} to not throw ' + expectedThrown + actuallyGot
2263 | , (desiredError instanceof Error ? desiredError.toString() : desiredError)
2264 | , (thrownError instanceof Error ? thrownError.toString() : thrownError)
2265 | );
2266 |
2267 | flag(this, 'object', thrownError);
2268 | };
2269 |
2270 | Assertion.addMethod('throw', assertThrows);
2271 | Assertion.addMethod('throws', assertThrows);
2272 | Assertion.addMethod('Throw', assertThrows);
2273 |
2274 | /**
2275 | * ### .respondTo(method)
2276 | *
2277 | * Asserts that the object or class target will respond to a method.
2278 | *
2279 | * Klass.prototype.bar = function(){};
2280 | * expect(Klass).to.respondTo('bar');
2281 | * expect(obj).to.respondTo('bar');
2282 | *
2283 | * To check if a constructor will respond to a static function,
2284 | * set the `itself` flag.
2285 | *
2286 | * Klass.baz = function(){};
2287 | * expect(Klass).itself.to.respondTo('baz');
2288 | *
2289 | * @name respondTo
2290 | * @param {String} method
2291 | * @param {String} message _optional_
2292 | * @api public
2293 | */
2294 |
2295 | Assertion.addMethod('respondTo', function (method, msg) {
2296 | if (msg) flag(this, 'message', msg);
2297 | var obj = flag(this, 'object')
2298 | , itself = flag(this, 'itself')
2299 | , context = ('function' === _.type(obj) && !itself)
2300 | ? obj.prototype[method]
2301 | : obj[method];
2302 |
2303 | this.assert(
2304 | 'function' === typeof context
2305 | , 'expected #{this} to respond to ' + _.inspect(method)
2306 | , 'expected #{this} to not respond to ' + _.inspect(method)
2307 | );
2308 | });
2309 |
2310 | /**
2311 | * ### .itself
2312 | *
2313 | * Sets the `itself` flag, later used by the `respondTo` assertion.
2314 | *
2315 | * function Foo() {}
2316 | * Foo.bar = function() {}
2317 | * Foo.prototype.baz = function() {}
2318 | *
2319 | * expect(Foo).itself.to.respondTo('bar');
2320 | * expect(Foo).itself.not.to.respondTo('baz');
2321 | *
2322 | * @name itself
2323 | * @api public
2324 | */
2325 |
2326 | Assertion.addProperty('itself', function () {
2327 | flag(this, 'itself', true);
2328 | });
2329 |
2330 | /**
2331 | * ### .satisfy(method)
2332 | *
2333 | * Asserts that the target passes a given truth test.
2334 | *
2335 | * expect(1).to.satisfy(function(num) { return num > 0; });
2336 | *
2337 | * @name satisfy
2338 | * @param {Function} matcher
2339 | * @param {String} message _optional_
2340 | * @api public
2341 | */
2342 |
2343 | Assertion.addMethod('satisfy', function (matcher, msg) {
2344 | if (msg) flag(this, 'message', msg);
2345 | var obj = flag(this, 'object');
2346 | var result = matcher(obj);
2347 | this.assert(
2348 | result
2349 | , 'expected #{this} to satisfy ' + _.objDisplay(matcher)
2350 | , 'expected #{this} to not satisfy' + _.objDisplay(matcher)
2351 | , this.negate ? false : true
2352 | , result
2353 | );
2354 | });
2355 |
2356 | /**
2357 | * ### .closeTo(expected, delta)
2358 | *
2359 | * Asserts that the target is equal `expected`, to within a +/- `delta` range.
2360 | *
2361 | * expect(1.5).to.be.closeTo(1, 0.5);
2362 | *
2363 | * @name closeTo
2364 | * @param {Number} expected
2365 | * @param {Number} delta
2366 | * @param {String} message _optional_
2367 | * @api public
2368 | */
2369 |
2370 | Assertion.addMethod('closeTo', function (expected, delta, msg) {
2371 | if (msg) flag(this, 'message', msg);
2372 | var obj = flag(this, 'object');
2373 |
2374 | new Assertion(obj, msg).is.a('number');
2375 | if (_.type(expected) !== 'number' || _.type(delta) !== 'number') {
2376 | throw new Error('the arguments to closeTo must be numbers');
2377 | }
2378 |
2379 | this.assert(
2380 | Math.abs(obj - expected) <= delta
2381 | , 'expected #{this} to be close to ' + expected + ' +/- ' + delta
2382 | , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta
2383 | );
2384 | });
2385 |
2386 | function isSubsetOf(subset, superset, cmp) {
2387 | return subset.every(function(elem) {
2388 | if (!cmp) return superset.indexOf(elem) !== -1;
2389 |
2390 | return superset.some(function(elem2) {
2391 | return cmp(elem, elem2);
2392 | });
2393 | })
2394 | }
2395 |
2396 | /**
2397 | * ### .members(set)
2398 | *
2399 | * Asserts that the target is a superset of `set`,
2400 | * or that the target and `set` have the same strictly-equal (===) members.
2401 | * Alternately, if the `deep` flag is set, set members are compared for deep
2402 | * equality.
2403 | *
2404 | * expect([1, 2, 3]).to.include.members([3, 2]);
2405 | * expect([1, 2, 3]).to.not.include.members([3, 2, 8]);
2406 | *
2407 | * expect([4, 2]).to.have.members([2, 4]);
2408 | * expect([5, 2]).to.not.have.members([5, 2, 1]);
2409 | *
2410 | * expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]);
2411 | *
2412 | * @name members
2413 | * @param {Array} set
2414 | * @param {String} message _optional_
2415 | * @api public
2416 | */
2417 |
2418 | Assertion.addMethod('members', function (subset, msg) {
2419 | if (msg) flag(this, 'message', msg);
2420 | var obj = flag(this, 'object');
2421 |
2422 | new Assertion(obj).to.be.an('array');
2423 | new Assertion(subset).to.be.an('array');
2424 |
2425 | var cmp = flag(this, 'deep') ? _.eql : undefined;
2426 |
2427 | if (flag(this, 'contains')) {
2428 | return this.assert(
2429 | isSubsetOf(subset, obj, cmp)
2430 | , 'expected #{this} to be a superset of #{act}'
2431 | , 'expected #{this} to not be a superset of #{act}'
2432 | , obj
2433 | , subset
2434 | );
2435 | }
2436 |
2437 | this.assert(
2438 | isSubsetOf(obj, subset, cmp) && isSubsetOf(subset, obj, cmp)
2439 | , 'expected #{this} to have the same members as #{act}'
2440 | , 'expected #{this} to not have the same members as #{act}'
2441 | , obj
2442 | , subset
2443 | );
2444 | });
2445 |
2446 | /**
2447 | * ### .change(function)
2448 | *
2449 | * Asserts that a function changes an object property
2450 | *
2451 | * var obj = { val: 10 };
2452 | * var fn = function() { obj.val += 3 };
2453 | * var noChangeFn = function() { return 'foo' + 'bar'; }
2454 | * expect(fn).to.change(obj, 'val');
2455 | * expect(noChangFn).to.not.change(obj, 'val')
2456 | *
2457 | * @name change
2458 | * @alias changes
2459 | * @alias Change
2460 | * @param {String} object
2461 | * @param {String} property name
2462 | * @param {String} message _optional_
2463 | * @api public
2464 | */
2465 |
2466 | function assertChanges (object, prop, msg) {
2467 | if (msg) flag(this, 'message', msg);
2468 | var fn = flag(this, 'object');
2469 | new Assertion(object, msg).to.have.property(prop);
2470 | new Assertion(fn).is.a('function');
2471 |
2472 | var initial = object[prop];
2473 | fn();
2474 |
2475 | this.assert(
2476 | initial !== object[prop]
2477 | , 'expected .' + prop + ' to change'
2478 | , 'expected .' + prop + ' to not change'
2479 | );
2480 | }
2481 |
2482 | Assertion.addChainableMethod('change', assertChanges);
2483 | Assertion.addChainableMethod('changes', assertChanges);
2484 |
2485 | /**
2486 | * ### .increase(function)
2487 | *
2488 | * Asserts that a function increases an object property
2489 | *
2490 | * var obj = { val: 10 };
2491 | * var fn = function() { obj.val = 15 };
2492 | * expect(fn).to.increase(obj, 'val');
2493 | *
2494 | * @name increase
2495 | * @alias increases
2496 | * @alias Increase
2497 | * @param {String} object
2498 | * @param {String} property name
2499 | * @param {String} message _optional_
2500 | * @api public
2501 | */
2502 |
2503 | function assertIncreases (object, prop, msg) {
2504 | if (msg) flag(this, 'message', msg);
2505 | var fn = flag(this, 'object');
2506 | new Assertion(object, msg).to.have.property(prop);
2507 | new Assertion(fn).is.a('function');
2508 |
2509 | var initial = object[prop];
2510 | fn();
2511 |
2512 | this.assert(
2513 | object[prop] - initial > 0
2514 | , 'expected .' + prop + ' to increase'
2515 | , 'expected .' + prop + ' to not increase'
2516 | );
2517 | }
2518 |
2519 | Assertion.addChainableMethod('increase', assertIncreases);
2520 | Assertion.addChainableMethod('increases', assertIncreases);
2521 |
2522 | /**
2523 | * ### .decrease(function)
2524 | *
2525 | * Asserts that a function decreases an object property
2526 | *
2527 | * var obj = { val: 10 };
2528 | * var fn = function() { obj.val = 5 };
2529 | * expect(fn).to.decrease(obj, 'val');
2530 | *
2531 | * @name decrease
2532 | * @alias decreases
2533 | * @alias Decrease
2534 | * @param {String} object
2535 | * @param {String} property name
2536 | * @param {String} message _optional_
2537 | * @api public
2538 | */
2539 |
2540 | function assertDecreases (object, prop, msg) {
2541 | if (msg) flag(this, 'message', msg);
2542 | var fn = flag(this, 'object');
2543 | new Assertion(object, msg).to.have.property(prop);
2544 | new Assertion(fn).is.a('function');
2545 |
2546 | var initial = object[prop];
2547 | fn();
2548 |
2549 | this.assert(
2550 | object[prop] - initial < 0
2551 | , 'expected .' + prop + ' to decrease'
2552 | , 'expected .' + prop + ' to not decrease'
2553 | );
2554 | }
2555 |
2556 | Assertion.addChainableMethod('decrease', assertDecreases);
2557 | Assertion.addChainableMethod('decreases', assertDecreases);
2558 |
2559 | };
2560 |
2561 | });
2562 |
2563 | require.register("chai/lib/chai/interface/assert.js", function (exports, module) {
2564 | /*!
2565 | * chai
2566 | * Copyright(c) 2011-2014 Jake Luer
2567 | * MIT Licensed
2568 | */
2569 |
2570 |
2571 | module.exports = function (chai, util) {
2572 |
2573 | /*!
2574 | * Chai dependencies.
2575 | */
2576 |
2577 | var Assertion = chai.Assertion
2578 | , flag = util.flag;
2579 |
2580 | /*!
2581 | * Module export.
2582 | */
2583 |
2584 | /**
2585 | * ### assert(expression, message)
2586 | *
2587 | * Write your own test expressions.
2588 | *
2589 | * assert('foo' !== 'bar', 'foo is not bar');
2590 | * assert(Array.isArray([]), 'empty arrays are arrays');
2591 | *
2592 | * @param {Mixed} expression to test for truthiness
2593 | * @param {String} message to display on error
2594 | * @name assert
2595 | * @api public
2596 | */
2597 |
2598 | var assert = chai.assert = function (express, errmsg) {
2599 | var test = new Assertion(null, null, chai.assert);
2600 | test.assert(
2601 | express
2602 | , errmsg
2603 | , '[ negation message unavailable ]'
2604 | );
2605 | };
2606 |
2607 | /**
2608 | * ### .fail(actual, expected, [message], [operator])
2609 | *
2610 | * Throw a failure. Node.js `assert` module-compatible.
2611 | *
2612 | * @name fail
2613 | * @param {Mixed} actual
2614 | * @param {Mixed} expected
2615 | * @param {String} message
2616 | * @param {String} operator
2617 | * @api public
2618 | */
2619 |
2620 | assert.fail = function (actual, expected, message, operator) {
2621 | message = message || 'assert.fail()';
2622 | throw new chai.AssertionError(message, {
2623 | actual: actual
2624 | , expected: expected
2625 | , operator: operator
2626 | }, assert.fail);
2627 | };
2628 |
2629 | /**
2630 | * ### .ok(object, [message])
2631 | *
2632 | * Asserts that `object` is truthy.
2633 | *
2634 | * assert.ok('everything', 'everything is ok');
2635 | * assert.ok(false, 'this will fail');
2636 | *
2637 | * @name ok
2638 | * @param {Mixed} object to test
2639 | * @param {String} message
2640 | * @api public
2641 | */
2642 |
2643 | assert.ok = function (val, msg) {
2644 | new Assertion(val, msg).is.ok;
2645 | };
2646 |
2647 | /**
2648 | * ### .notOk(object, [message])
2649 | *
2650 | * Asserts that `object` is falsy.
2651 | *
2652 | * assert.notOk('everything', 'this will fail');
2653 | * assert.notOk(false, 'this will pass');
2654 | *
2655 | * @name notOk
2656 | * @param {Mixed} object to test
2657 | * @param {String} message
2658 | * @api public
2659 | */
2660 |
2661 | assert.notOk = function (val, msg) {
2662 | new Assertion(val, msg).is.not.ok;
2663 | };
2664 |
2665 | /**
2666 | * ### .equal(actual, expected, [message])
2667 | *
2668 | * Asserts non-strict equality (`==`) of `actual` and `expected`.
2669 | *
2670 | * assert.equal(3, '3', '== coerces values to strings');
2671 | *
2672 | * @name equal
2673 | * @param {Mixed} actual
2674 | * @param {Mixed} expected
2675 | * @param {String} message
2676 | * @api public
2677 | */
2678 |
2679 | assert.equal = function (act, exp, msg) {
2680 | var test = new Assertion(act, msg, assert.equal);
2681 |
2682 | test.assert(
2683 | exp == flag(test, 'object')
2684 | , 'expected #{this} to equal #{exp}'
2685 | , 'expected #{this} to not equal #{act}'
2686 | , exp
2687 | , act
2688 | );
2689 | };
2690 |
2691 | /**
2692 | * ### .notEqual(actual, expected, [message])
2693 | *
2694 | * Asserts non-strict inequality (`!=`) of `actual` and `expected`.
2695 | *
2696 | * assert.notEqual(3, 4, 'these numbers are not equal');
2697 | *
2698 | * @name notEqual
2699 | * @param {Mixed} actual
2700 | * @param {Mixed} expected
2701 | * @param {String} message
2702 | * @api public
2703 | */
2704 |
2705 | assert.notEqual = function (act, exp, msg) {
2706 | var test = new Assertion(act, msg, assert.notEqual);
2707 |
2708 | test.assert(
2709 | exp != flag(test, 'object')
2710 | , 'expected #{this} to not equal #{exp}'
2711 | , 'expected #{this} to equal #{act}'
2712 | , exp
2713 | , act
2714 | );
2715 | };
2716 |
2717 | /**
2718 | * ### .strictEqual(actual, expected, [message])
2719 | *
2720 | * Asserts strict equality (`===`) of `actual` and `expected`.
2721 | *
2722 | * assert.strictEqual(true, true, 'these booleans are strictly equal');
2723 | *
2724 | * @name strictEqual
2725 | * @param {Mixed} actual
2726 | * @param {Mixed} expected
2727 | * @param {String} message
2728 | * @api public
2729 | */
2730 |
2731 | assert.strictEqual = function (act, exp, msg) {
2732 | new Assertion(act, msg).to.equal(exp);
2733 | };
2734 |
2735 | /**
2736 | * ### .notStrictEqual(actual, expected, [message])
2737 | *
2738 | * Asserts strict inequality (`!==`) of `actual` and `expected`.
2739 | *
2740 | * assert.notStrictEqual(3, '3', 'no coercion for strict equality');
2741 | *
2742 | * @name notStrictEqual
2743 | * @param {Mixed} actual
2744 | * @param {Mixed} expected
2745 | * @param {String} message
2746 | * @api public
2747 | */
2748 |
2749 | assert.notStrictEqual = function (act, exp, msg) {
2750 | new Assertion(act, msg).to.not.equal(exp);
2751 | };
2752 |
2753 | /**
2754 | * ### .deepEqual(actual, expected, [message])
2755 | *
2756 | * Asserts that `actual` is deeply equal to `expected`.
2757 | *
2758 | * assert.deepEqual({ tea: 'green' }, { tea: 'green' });
2759 | *
2760 | * @name deepEqual
2761 | * @param {Mixed} actual
2762 | * @param {Mixed} expected
2763 | * @param {String} message
2764 | * @api public
2765 | */
2766 |
2767 | assert.deepEqual = function (act, exp, msg) {
2768 | new Assertion(act, msg).to.eql(exp);
2769 | };
2770 |
2771 | /**
2772 | * ### .notDeepEqual(actual, expected, [message])
2773 | *
2774 | * Assert that `actual` is not deeply equal to `expected`.
2775 | *
2776 | * assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' });
2777 | *
2778 | * @name notDeepEqual
2779 | * @param {Mixed} actual
2780 | * @param {Mixed} expected
2781 | * @param {String} message
2782 | * @api public
2783 | */
2784 |
2785 | assert.notDeepEqual = function (act, exp, msg) {
2786 | new Assertion(act, msg).to.not.eql(exp);
2787 | };
2788 |
2789 | /**
2790 | * ### .isTrue(value, [message])
2791 | *
2792 | * Asserts that `value` is true.
2793 | *
2794 | * var teaServed = true;
2795 | * assert.isTrue(teaServed, 'the tea has been served');
2796 | *
2797 | * @name isTrue
2798 | * @param {Mixed} value
2799 | * @param {String} message
2800 | * @api public
2801 | */
2802 |
2803 | assert.isAbove = function (val, abv, msg) {
2804 | new Assertion(val, msg).to.be.above(abv);
2805 | };
2806 |
2807 | /**
2808 | * ### .isAbove(valueToCheck, valueToBeAbove, [message])
2809 | *
2810 | * Asserts `valueToCheck` is strictly greater than (>) `valueToBeAbove`
2811 | *
2812 | * assert.isAbove(5, 2, '5 is strictly greater than 2');
2813 | *
2814 | * @name isAbove
2815 | * @param {Mixed} valueToCheck
2816 | * @param {Mixed} valueToBeAbove
2817 | * @param {String} message
2818 | * @api public
2819 | */
2820 |
2821 | assert.isBelow = function (val, blw, msg) {
2822 | new Assertion(val, msg).to.be.below(blw);
2823 | };
2824 |
2825 | /**
2826 | * ### .isBelow(valueToCheck, valueToBeBelow, [message])
2827 | *
2828 | * Asserts `valueToCheck` is strictly less than (<) `valueToBeBelow`
2829 | *
2830 | * assert.isBelow(3, 6, '3 is strictly less than 6');
2831 | *
2832 | * @name isBelow
2833 | * @param {Mixed} valueToCheck
2834 | * @param {Mixed} valueToBeBelow
2835 | * @param {String} message
2836 | * @api public
2837 | */
2838 |
2839 | assert.isTrue = function (val, msg) {
2840 | new Assertion(val, msg).is['true'];
2841 | };
2842 |
2843 | /**
2844 | * ### .isFalse(value, [message])
2845 | *
2846 | * Asserts that `value` is false.
2847 | *
2848 | * var teaServed = false;
2849 | * assert.isFalse(teaServed, 'no tea yet? hmm...');
2850 | *
2851 | * @name isFalse
2852 | * @param {Mixed} value
2853 | * @param {String} message
2854 | * @api public
2855 | */
2856 |
2857 | assert.isFalse = function (val, msg) {
2858 | new Assertion(val, msg).is['false'];
2859 | };
2860 |
2861 | /**
2862 | * ### .isNull(value, [message])
2863 | *
2864 | * Asserts that `value` is null.
2865 | *
2866 | * assert.isNull(err, 'there was no error');
2867 | *
2868 | * @name isNull
2869 | * @param {Mixed} value
2870 | * @param {String} message
2871 | * @api public
2872 | */
2873 |
2874 | assert.isNull = function (val, msg) {
2875 | new Assertion(val, msg).to.equal(null);
2876 | };
2877 |
2878 | /**
2879 | * ### .isNotNull(value, [message])
2880 | *
2881 | * Asserts that `value` is not null.
2882 | *
2883 | * var tea = 'tasty chai';
2884 | * assert.isNotNull(tea, 'great, time for tea!');
2885 | *
2886 | * @name isNotNull
2887 | * @param {Mixed} value
2888 | * @param {String} message
2889 | * @api public
2890 | */
2891 |
2892 | assert.isNotNull = function (val, msg) {
2893 | new Assertion(val, msg).to.not.equal(null);
2894 | };
2895 |
2896 | /**
2897 | * ### .isUndefined(value, [message])
2898 | *
2899 | * Asserts that `value` is `undefined`.
2900 | *
2901 | * var tea;
2902 | * assert.isUndefined(tea, 'no tea defined');
2903 | *
2904 | * @name isUndefined
2905 | * @param {Mixed} value
2906 | * @param {String} message
2907 | * @api public
2908 | */
2909 |
2910 | assert.isUndefined = function (val, msg) {
2911 | new Assertion(val, msg).to.equal(undefined);
2912 | };
2913 |
2914 | /**
2915 | * ### .isDefined(value, [message])
2916 | *
2917 | * Asserts that `value` is not `undefined`.
2918 | *
2919 | * var tea = 'cup of chai';
2920 | * assert.isDefined(tea, 'tea has been defined');
2921 | *
2922 | * @name isDefined
2923 | * @param {Mixed} value
2924 | * @param {String} message
2925 | * @api public
2926 | */
2927 |
2928 | assert.isDefined = function (val, msg) {
2929 | new Assertion(val, msg).to.not.equal(undefined);
2930 | };
2931 |
2932 | /**
2933 | * ### .isFunction(value, [message])
2934 | *
2935 | * Asserts that `value` is a function.
2936 | *
2937 | * function serveTea() { return 'cup of tea'; };
2938 | * assert.isFunction(serveTea, 'great, we can have tea now');
2939 | *
2940 | * @name isFunction
2941 | * @param {Mixed} value
2942 | * @param {String} message
2943 | * @api public
2944 | */
2945 |
2946 | assert.isFunction = function (val, msg) {
2947 | new Assertion(val, msg).to.be.a('function');
2948 | };
2949 |
2950 | /**
2951 | * ### .isNotFunction(value, [message])
2952 | *
2953 | * Asserts that `value` is _not_ a function.
2954 | *
2955 | * var serveTea = [ 'heat', 'pour', 'sip' ];
2956 | * assert.isNotFunction(serveTea, 'great, we have listed the steps');
2957 | *
2958 | * @name isNotFunction
2959 | * @param {Mixed} value
2960 | * @param {String} message
2961 | * @api public
2962 | */
2963 |
2964 | assert.isNotFunction = function (val, msg) {
2965 | new Assertion(val, msg).to.not.be.a('function');
2966 | };
2967 |
2968 | /**
2969 | * ### .isObject(value, [message])
2970 | *
2971 | * Asserts that `value` is an object (as revealed by
2972 | * `Object.prototype.toString`).
2973 | *
2974 | * var selection = { name: 'Chai', serve: 'with spices' };
2975 | * assert.isObject(selection, 'tea selection is an object');
2976 | *
2977 | * @name isObject
2978 | * @param {Mixed} value
2979 | * @param {String} message
2980 | * @api public
2981 | */
2982 |
2983 | assert.isObject = function (val, msg) {
2984 | new Assertion(val, msg).to.be.a('object');
2985 | };
2986 |
2987 | /**
2988 | * ### .isNotObject(value, [message])
2989 | *
2990 | * Asserts that `value` is _not_ an object.
2991 | *
2992 | * var selection = 'chai'
2993 | * assert.isNotObject(selection, 'tea selection is not an object');
2994 | * assert.isNotObject(null, 'null is not an object');
2995 | *
2996 | * @name isNotObject
2997 | * @param {Mixed} value
2998 | * @param {String} message
2999 | * @api public
3000 | */
3001 |
3002 | assert.isNotObject = function (val, msg) {
3003 | new Assertion(val, msg).to.not.be.a('object');
3004 | };
3005 |
3006 | /**
3007 | * ### .isArray(value, [message])
3008 | *
3009 | * Asserts that `value` is an array.
3010 | *
3011 | * var menu = [ 'green', 'chai', 'oolong' ];
3012 | * assert.isArray(menu, 'what kind of tea do we want?');
3013 | *
3014 | * @name isArray
3015 | * @param {Mixed} value
3016 | * @param {String} message
3017 | * @api public
3018 | */
3019 |
3020 | assert.isArray = function (val, msg) {
3021 | new Assertion(val, msg).to.be.an('array');
3022 | };
3023 |
3024 | /**
3025 | * ### .isNotArray(value, [message])
3026 | *
3027 | * Asserts that `value` is _not_ an array.
3028 | *
3029 | * var menu = 'green|chai|oolong';
3030 | * assert.isNotArray(menu, 'what kind of tea do we want?');
3031 | *
3032 | * @name isNotArray
3033 | * @param {Mixed} value
3034 | * @param {String} message
3035 | * @api public
3036 | */
3037 |
3038 | assert.isNotArray = function (val, msg) {
3039 | new Assertion(val, msg).to.not.be.an('array');
3040 | };
3041 |
3042 | /**
3043 | * ### .isString(value, [message])
3044 | *
3045 | * Asserts that `value` is a string.
3046 | *
3047 | * var teaOrder = 'chai';
3048 | * assert.isString(teaOrder, 'order placed');
3049 | *
3050 | * @name isString
3051 | * @param {Mixed} value
3052 | * @param {String} message
3053 | * @api public
3054 | */
3055 |
3056 | assert.isString = function (val, msg) {
3057 | new Assertion(val, msg).to.be.a('string');
3058 | };
3059 |
3060 | /**
3061 | * ### .isNotString(value, [message])
3062 | *
3063 | * Asserts that `value` is _not_ a string.
3064 | *
3065 | * var teaOrder = 4;
3066 | * assert.isNotString(teaOrder, 'order placed');
3067 | *
3068 | * @name isNotString
3069 | * @param {Mixed} value
3070 | * @param {String} message
3071 | * @api public
3072 | */
3073 |
3074 | assert.isNotString = function (val, msg) {
3075 | new Assertion(val, msg).to.not.be.a('string');
3076 | };
3077 |
3078 | /**
3079 | * ### .isNumber(value, [message])
3080 | *
3081 | * Asserts that `value` is a number.
3082 | *
3083 | * var cups = 2;
3084 | * assert.isNumber(cups, 'how many cups');
3085 | *
3086 | * @name isNumber
3087 | * @param {Number} value
3088 | * @param {String} message
3089 | * @api public
3090 | */
3091 |
3092 | assert.isNumber = function (val, msg) {
3093 | new Assertion(val, msg).to.be.a('number');
3094 | };
3095 |
3096 | /**
3097 | * ### .isNotNumber(value, [message])
3098 | *
3099 | * Asserts that `value` is _not_ a number.
3100 | *
3101 | * var cups = '2 cups please';
3102 | * assert.isNotNumber(cups, 'how many cups');
3103 | *
3104 | * @name isNotNumber
3105 | * @param {Mixed} value
3106 | * @param {String} message
3107 | * @api public
3108 | */
3109 |
3110 | assert.isNotNumber = function (val, msg) {
3111 | new Assertion(val, msg).to.not.be.a('number');
3112 | };
3113 |
3114 | /**
3115 | * ### .isBoolean(value, [message])
3116 | *
3117 | * Asserts that `value` is a boolean.
3118 | *
3119 | * var teaReady = true
3120 | * , teaServed = false;
3121 | *
3122 | * assert.isBoolean(teaReady, 'is the tea ready');
3123 | * assert.isBoolean(teaServed, 'has tea been served');
3124 | *
3125 | * @name isBoolean
3126 | * @param {Mixed} value
3127 | * @param {String} message
3128 | * @api public
3129 | */
3130 |
3131 | assert.isBoolean = function (val, msg) {
3132 | new Assertion(val, msg).to.be.a('boolean');
3133 | };
3134 |
3135 | /**
3136 | * ### .isNotBoolean(value, [message])
3137 | *
3138 | * Asserts that `value` is _not_ a boolean.
3139 | *
3140 | * var teaReady = 'yep'
3141 | * , teaServed = 'nope';
3142 | *
3143 | * assert.isNotBoolean(teaReady, 'is the tea ready');
3144 | * assert.isNotBoolean(teaServed, 'has tea been served');
3145 | *
3146 | * @name isNotBoolean
3147 | * @param {Mixed} value
3148 | * @param {String} message
3149 | * @api public
3150 | */
3151 |
3152 | assert.isNotBoolean = function (val, msg) {
3153 | new Assertion(val, msg).to.not.be.a('boolean');
3154 | };
3155 |
3156 | /**
3157 | * ### .typeOf(value, name, [message])
3158 | *
3159 | * Asserts that `value`'s type is `name`, as determined by
3160 | * `Object.prototype.toString`.
3161 | *
3162 | * assert.typeOf({ tea: 'chai' }, 'object', 'we have an object');
3163 | * assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array');
3164 | * assert.typeOf('tea', 'string', 'we have a string');
3165 | * assert.typeOf(/tea/, 'regexp', 'we have a regular expression');
3166 | * assert.typeOf(null, 'null', 'we have a null');
3167 | * assert.typeOf(undefined, 'undefined', 'we have an undefined');
3168 | *
3169 | * @name typeOf
3170 | * @param {Mixed} value
3171 | * @param {String} name
3172 | * @param {String} message
3173 | * @api public
3174 | */
3175 |
3176 | assert.typeOf = function (val, type, msg) {
3177 | new Assertion(val, msg).to.be.a(type);
3178 | };
3179 |
3180 | /**
3181 | * ### .notTypeOf(value, name, [message])
3182 | *
3183 | * Asserts that `value`'s type is _not_ `name`, as determined by
3184 | * `Object.prototype.toString`.
3185 | *
3186 | * assert.notTypeOf('tea', 'number', 'strings are not numbers');
3187 | *
3188 | * @name notTypeOf
3189 | * @param {Mixed} value
3190 | * @param {String} typeof name
3191 | * @param {String} message
3192 | * @api public
3193 | */
3194 |
3195 | assert.notTypeOf = function (val, type, msg) {
3196 | new Assertion(val, msg).to.not.be.a(type);
3197 | };
3198 |
3199 | /**
3200 | * ### .instanceOf(object, constructor, [message])
3201 | *
3202 | * Asserts that `value` is an instance of `constructor`.
3203 | *
3204 | * var Tea = function (name) { this.name = name; }
3205 | * , chai = new Tea('chai');
3206 | *
3207 | * assert.instanceOf(chai, Tea, 'chai is an instance of tea');
3208 | *
3209 | * @name instanceOf
3210 | * @param {Object} object
3211 | * @param {Constructor} constructor
3212 | * @param {String} message
3213 | * @api public
3214 | */
3215 |
3216 | assert.instanceOf = function (val, type, msg) {
3217 | new Assertion(val, msg).to.be.instanceOf(type);
3218 | };
3219 |
3220 | /**
3221 | * ### .notInstanceOf(object, constructor, [message])
3222 | *
3223 | * Asserts `value` is not an instance of `constructor`.
3224 | *
3225 | * var Tea = function (name) { this.name = name; }
3226 | * , chai = new String('chai');
3227 | *
3228 | * assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea');
3229 | *
3230 | * @name notInstanceOf
3231 | * @param {Object} object
3232 | * @param {Constructor} constructor
3233 | * @param {String} message
3234 | * @api public
3235 | */
3236 |
3237 | assert.notInstanceOf = function (val, type, msg) {
3238 | new Assertion(val, msg).to.not.be.instanceOf(type);
3239 | };
3240 |
3241 | /**
3242 | * ### .include(haystack, needle, [message])
3243 | *
3244 | * Asserts that `haystack` includes `needle`. Works
3245 | * for strings and arrays.
3246 | *
3247 | * assert.include('foobar', 'bar', 'foobar contains string "bar"');
3248 | * assert.include([ 1, 2, 3 ], 3, 'array contains value');
3249 | *
3250 | * @name include
3251 | * @param {Array|String} haystack
3252 | * @param {Mixed} needle
3253 | * @param {String} message
3254 | * @api public
3255 | */
3256 |
3257 | assert.include = function (exp, inc, msg) {
3258 | new Assertion(exp, msg, assert.include).include(inc);
3259 | };
3260 |
3261 | /**
3262 | * ### .notInclude(haystack, needle, [message])
3263 | *
3264 | * Asserts that `haystack` does not include `needle`. Works
3265 | * for strings and arrays.
3266 | *i
3267 | * assert.notInclude('foobar', 'baz', 'string not include substring');
3268 | * assert.notInclude([ 1, 2, 3 ], 4, 'array not include contain value');
3269 | *
3270 | * @name notInclude
3271 | * @param {Array|String} haystack
3272 | * @param {Mixed} needle
3273 | * @param {String} message
3274 | * @api public
3275 | */
3276 |
3277 | assert.notInclude = function (exp, inc, msg) {
3278 | new Assertion(exp, msg, assert.notInclude).not.include(inc);
3279 | };
3280 |
3281 | /**
3282 | * ### .match(value, regexp, [message])
3283 | *
3284 | * Asserts that `value` matches the regular expression `regexp`.
3285 | *
3286 | * assert.match('foobar', /^foo/, 'regexp matches');
3287 | *
3288 | * @name match
3289 | * @param {Mixed} value
3290 | * @param {RegExp} regexp
3291 | * @param {String} message
3292 | * @api public
3293 | */
3294 |
3295 | assert.match = function (exp, re, msg) {
3296 | new Assertion(exp, msg).to.match(re);
3297 | };
3298 |
3299 | /**
3300 | * ### .notMatch(value, regexp, [message])
3301 | *
3302 | * Asserts that `value` does not match the regular expression `regexp`.
3303 | *
3304 | * assert.notMatch('foobar', /^foo/, 'regexp does not match');
3305 | *
3306 | * @name notMatch
3307 | * @param {Mixed} value
3308 | * @param {RegExp} regexp
3309 | * @param {String} message
3310 | * @api public
3311 | */
3312 |
3313 | assert.notMatch = function (exp, re, msg) {
3314 | new Assertion(exp, msg).to.not.match(re);
3315 | };
3316 |
3317 | /**
3318 | * ### .property(object, property, [message])
3319 | *
3320 | * Asserts that `object` has a property named by `property`.
3321 | *
3322 | * assert.property({ tea: { green: 'matcha' }}, 'tea');
3323 | *
3324 | * @name property
3325 | * @param {Object} object
3326 | * @param {String} property
3327 | * @param {String} message
3328 | * @api public
3329 | */
3330 |
3331 | assert.property = function (obj, prop, msg) {
3332 | new Assertion(obj, msg).to.have.property(prop);
3333 | };
3334 |
3335 | /**
3336 | * ### .notProperty(object, property, [message])
3337 | *
3338 | * Asserts that `object` does _not_ have a property named by `property`.
3339 | *
3340 | * assert.notProperty({ tea: { green: 'matcha' }}, 'coffee');
3341 | *
3342 | * @name notProperty
3343 | * @param {Object} object
3344 | * @param {String} property
3345 | * @param {String} message
3346 | * @api public
3347 | */
3348 |
3349 | assert.notProperty = function (obj, prop, msg) {
3350 | new Assertion(obj, msg).to.not.have.property(prop);
3351 | };
3352 |
3353 | /**
3354 | * ### .deepProperty(object, property, [message])
3355 | *
3356 | * Asserts that `object` has a property named by `property`, which can be a
3357 | * string using dot- and bracket-notation for deep reference.
3358 | *
3359 | * assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green');
3360 | *
3361 | * @name deepProperty
3362 | * @param {Object} object
3363 | * @param {String} property
3364 | * @param {String} message
3365 | * @api public
3366 | */
3367 |
3368 | assert.deepProperty = function (obj, prop, msg) {
3369 | new Assertion(obj, msg).to.have.deep.property(prop);
3370 | };
3371 |
3372 | /**
3373 | * ### .notDeepProperty(object, property, [message])
3374 | *
3375 | * Asserts that `object` does _not_ have a property named by `property`, which
3376 | * can be a string using dot- and bracket-notation for deep reference.
3377 | *
3378 | * assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong');
3379 | *
3380 | * @name notDeepProperty
3381 | * @param {Object} object
3382 | * @param {String} property
3383 | * @param {String} message
3384 | * @api public
3385 | */
3386 |
3387 | assert.notDeepProperty = function (obj, prop, msg) {
3388 | new Assertion(obj, msg).to.not.have.deep.property(prop);
3389 | };
3390 |
3391 | /**
3392 | * ### .propertyVal(object, property, value, [message])
3393 | *
3394 | * Asserts that `object` has a property named by `property` with value given
3395 | * by `value`.
3396 | *
3397 | * assert.propertyVal({ tea: 'is good' }, 'tea', 'is good');
3398 | *
3399 | * @name propertyVal
3400 | * @param {Object} object
3401 | * @param {String} property
3402 | * @param {Mixed} value
3403 | * @param {String} message
3404 | * @api public
3405 | */
3406 |
3407 | assert.propertyVal = function (obj, prop, val, msg) {
3408 | new Assertion(obj, msg).to.have.property(prop, val);
3409 | };
3410 |
3411 | /**
3412 | * ### .propertyNotVal(object, property, value, [message])
3413 | *
3414 | * Asserts that `object` has a property named by `property`, but with a value
3415 | * different from that given by `value`.
3416 | *
3417 | * assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad');
3418 | *
3419 | * @name propertyNotVal
3420 | * @param {Object} object
3421 | * @param {String} property
3422 | * @param {Mixed} value
3423 | * @param {String} message
3424 | * @api public
3425 | */
3426 |
3427 | assert.propertyNotVal = function (obj, prop, val, msg) {
3428 | new Assertion(obj, msg).to.not.have.property(prop, val);
3429 | };
3430 |
3431 | /**
3432 | * ### .deepPropertyVal(object, property, value, [message])
3433 | *
3434 | * Asserts that `object` has a property named by `property` with value given
3435 | * by `value`. `property` can use dot- and bracket-notation for deep
3436 | * reference.
3437 | *
3438 | * assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha');
3439 | *
3440 | * @name deepPropertyVal
3441 | * @param {Object} object
3442 | * @param {String} property
3443 | * @param {Mixed} value
3444 | * @param {String} message
3445 | * @api public
3446 | */
3447 |
3448 | assert.deepPropertyVal = function (obj, prop, val, msg) {
3449 | new Assertion(obj, msg).to.have.deep.property(prop, val);
3450 | };
3451 |
3452 | /**
3453 | * ### .deepPropertyNotVal(object, property, value, [message])
3454 | *
3455 | * Asserts that `object` has a property named by `property`, but with a value
3456 | * different from that given by `value`. `property` can use dot- and
3457 | * bracket-notation for deep reference.
3458 | *
3459 | * assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha');
3460 | *
3461 | * @name deepPropertyNotVal
3462 | * @param {Object} object
3463 | * @param {String} property
3464 | * @param {Mixed} value
3465 | * @param {String} message
3466 | * @api public
3467 | */
3468 |
3469 | assert.deepPropertyNotVal = function (obj, prop, val, msg) {
3470 | new Assertion(obj, msg).to.not.have.deep.property(prop, val);
3471 | };
3472 |
3473 | /**
3474 | * ### .lengthOf(object, length, [message])
3475 | *
3476 | * Asserts that `object` has a `length` property with the expected value.
3477 | *
3478 | * assert.lengthOf([1,2,3], 3, 'array has length of 3');
3479 | * assert.lengthOf('foobar', 5, 'string has length of 6');
3480 | *
3481 | * @name lengthOf
3482 | * @param {Mixed} object
3483 | * @param {Number} length
3484 | * @param {String} message
3485 | * @api public
3486 | */
3487 |
3488 | assert.lengthOf = function (exp, len, msg) {
3489 | new Assertion(exp, msg).to.have.length(len);
3490 | };
3491 |
3492 | /**
3493 | * ### .throws(function, [constructor/string/regexp], [string/regexp], [message])
3494 | *
3495 | * Asserts that `function` will throw an error that is an instance of
3496 | * `constructor`, or alternately that it will throw an error with message
3497 | * matching `regexp`.
3498 | *
3499 | * assert.throw(fn, 'function throws a reference error');
3500 | * assert.throw(fn, /function throws a reference error/);
3501 | * assert.throw(fn, ReferenceError);
3502 | * assert.throw(fn, ReferenceError, 'function throws a reference error');
3503 | * assert.throw(fn, ReferenceError, /function throws a reference error/);
3504 | *
3505 | * @name throws
3506 | * @alias throw
3507 | * @alias Throw
3508 | * @param {Function} function
3509 | * @param {ErrorConstructor} constructor
3510 | * @param {RegExp} regexp
3511 | * @param {String} message
3512 | * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
3513 | * @api public
3514 | */
3515 |
3516 | assert.Throw = function (fn, errt, errs, msg) {
3517 | if ('string' === typeof errt || errt instanceof RegExp) {
3518 | errs = errt;
3519 | errt = null;
3520 | }
3521 |
3522 | var assertErr = new Assertion(fn, msg).to.Throw(errt, errs);
3523 | return flag(assertErr, 'object');
3524 | };
3525 |
3526 | /**
3527 | * ### .doesNotThrow(function, [constructor/regexp], [message])
3528 | *
3529 | * Asserts that `function` will _not_ throw an error that is an instance of
3530 | * `constructor`, or alternately that it will not throw an error with message
3531 | * matching `regexp`.
3532 | *
3533 | * assert.doesNotThrow(fn, Error, 'function does not throw');
3534 | *
3535 | * @name doesNotThrow
3536 | * @param {Function} function
3537 | * @param {ErrorConstructor} constructor
3538 | * @param {RegExp} regexp
3539 | * @param {String} message
3540 | * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
3541 | * @api public
3542 | */
3543 |
3544 | assert.doesNotThrow = function (fn, type, msg) {
3545 | if ('string' === typeof type) {
3546 | msg = type;
3547 | type = null;
3548 | }
3549 |
3550 | new Assertion(fn, msg).to.not.Throw(type);
3551 | };
3552 |
3553 | /**
3554 | * ### .operator(val1, operator, val2, [message])
3555 | *
3556 | * Compares two values using `operator`.
3557 | *
3558 | * assert.operator(1, '<', 2, 'everything is ok');
3559 | * assert.operator(1, '>', 2, 'this will fail');
3560 | *
3561 | * @name operator
3562 | * @param {Mixed} val1
3563 | * @param {String} operator
3564 | * @param {Mixed} val2
3565 | * @param {String} message
3566 | * @api public
3567 | */
3568 |
3569 | assert.operator = function (val, operator, val2, msg) {
3570 | var ok;
3571 | switch(operator) {
3572 | case '==':
3573 | ok = val == val2;
3574 | break;
3575 | case '===':
3576 | ok = val === val2;
3577 | break;
3578 | case '>':
3579 | ok = val > val2;
3580 | break;
3581 | case '>=':
3582 | ok = val >= val2;
3583 | break;
3584 | case '<':
3585 | ok = val < val2;
3586 | break;
3587 | case '<=':
3588 | ok = val <= val2;
3589 | break;
3590 | case '!=':
3591 | ok = val != val2;
3592 | break;
3593 | case '!==':
3594 | ok = val !== val2;
3595 | break;
3596 | default:
3597 | throw new Error('Invalid operator "' + operator + '"');
3598 | }
3599 | var test = new Assertion(ok, msg);
3600 | test.assert(
3601 | true === flag(test, 'object')
3602 | , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2)
3603 | , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) );
3604 | };
3605 |
3606 | /**
3607 | * ### .closeTo(actual, expected, delta, [message])
3608 | *
3609 | * Asserts that the target is equal `expected`, to within a +/- `delta` range.
3610 | *
3611 | * assert.closeTo(1.5, 1, 0.5, 'numbers are close');
3612 | *
3613 | * @name closeTo
3614 | * @param {Number} actual
3615 | * @param {Number} expected
3616 | * @param {Number} delta
3617 | * @param {String} message
3618 | * @api public
3619 | */
3620 |
3621 | assert.closeTo = function (act, exp, delta, msg) {
3622 | new Assertion(act, msg).to.be.closeTo(exp, delta);
3623 | };
3624 |
3625 | /**
3626 | * ### .sameMembers(set1, set2, [message])
3627 | *
3628 | * Asserts that `set1` and `set2` have the same members.
3629 | * Order is not taken into account.
3630 | *
3631 | * assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members');
3632 | *
3633 | * @name sameMembers
3634 | * @param {Array} set1
3635 | * @param {Array} set2
3636 | * @param {String} message
3637 | * @api public
3638 | */
3639 |
3640 | assert.sameMembers = function (set1, set2, msg) {
3641 | new Assertion(set1, msg).to.have.same.members(set2);
3642 | }
3643 |
3644 | /**
3645 | * ### .sameDeepMembers(set1, set2, [message])
3646 | *
3647 | * Asserts that `set1` and `set2` have the same members - using a deep equality checking.
3648 | * Order is not taken into account.
3649 | *
3650 | * assert.sameDeepMembers([ {b: 3}, {a: 2}, {c: 5} ], [ {c: 5}, {b: 3}, {a: 2} ], 'same deep members');
3651 | *
3652 | * @name sameDeepMembers
3653 | * @param {Array} set1
3654 | * @param {Array} set2
3655 | * @param {String} message
3656 | * @api public
3657 | */
3658 |
3659 | assert.sameDeepMembers = function (set1, set2, msg) {
3660 | new Assertion(set1, msg).to.have.same.deep.members(set2);
3661 | }
3662 |
3663 | /**
3664 | * ### .includeMembers(superset, subset, [message])
3665 | *
3666 | * Asserts that `subset` is included in `superset`.
3667 | * Order is not taken into account.
3668 | *
3669 | * assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members');
3670 | *
3671 | * @name includeMembers
3672 | * @param {Array} superset
3673 | * @param {Array} subset
3674 | * @param {String} message
3675 | * @api public
3676 | */
3677 |
3678 | assert.includeMembers = function (superset, subset, msg) {
3679 | new Assertion(superset, msg).to.include.members(subset);
3680 | }
3681 |
3682 | /**
3683 | * ### .changes(function, object, property)
3684 | *
3685 | * Asserts that a function changes the value of a property
3686 | *
3687 | * var obj = { val: 10 };
3688 | * var fn = function() { obj.val = 22 };
3689 | * assert.changes(fn, obj, 'val');
3690 | *
3691 | * @name changes
3692 | * @param {Function} modifier function
3693 | * @param {Object} object
3694 | * @param {String} property name
3695 | * @param {String} message _optional_
3696 | * @api public
3697 | */
3698 |
3699 | assert.changes = function (fn, obj, prop) {
3700 | new Assertion(fn).to.change(obj, prop);
3701 | }
3702 |
3703 | /**
3704 | * ### .doesNotChange(function, object, property)
3705 | *
3706 | * Asserts that a function does not changes the value of a property
3707 | *
3708 | * var obj = { val: 10 };
3709 | * var fn = function() { console.log('foo'); };
3710 | * assert.doesNotChange(fn, obj, 'val');
3711 | *
3712 | * @name doesNotChange
3713 | * @param {Function} modifier function
3714 | * @param {Object} object
3715 | * @param {String} property name
3716 | * @param {String} message _optional_
3717 | * @api public
3718 | */
3719 |
3720 | assert.doesNotChange = function (fn, obj, prop) {
3721 | new Assertion(fn).to.not.change(obj, prop);
3722 | }
3723 |
3724 | /**
3725 | * ### .increases(function, object, property)
3726 | *
3727 | * Asserts that a function increases an object property
3728 | *
3729 | * var obj = { val: 10 };
3730 | * var fn = function() { obj.val = 13 };
3731 | * assert.increases(fn, obj, 'val');
3732 | *
3733 | * @name increases
3734 | * @param {Function} modifier function
3735 | * @param {Object} object
3736 | * @param {String} property name
3737 | * @param {String} message _optional_
3738 | * @api public
3739 | */
3740 |
3741 | assert.increases = function (fn, obj, prop) {
3742 | new Assertion(fn).to.increase(obj, prop);
3743 | }
3744 |
3745 | /**
3746 | * ### .doesNotIncrease(function, object, property)
3747 | *
3748 | * Asserts that a function does not increase object property
3749 | *
3750 | * var obj = { val: 10 };
3751 | * var fn = function() { obj.val = 8 };
3752 | * assert.doesNotIncrease(fn, obj, 'val');
3753 | *
3754 | * @name doesNotIncrease
3755 | * @param {Function} modifier function
3756 | * @param {Object} object
3757 | * @param {String} property name
3758 | * @param {String} message _optional_
3759 | * @api public
3760 | */
3761 |
3762 | assert.doesNotIncrease = function (fn, obj, prop) {
3763 | new Assertion(fn).to.not.increase(obj, prop);
3764 | }
3765 |
3766 | /**
3767 | * ### .decreases(function, object, property)
3768 | *
3769 | * Asserts that a function decreases an object property
3770 | *
3771 | * var obj = { val: 10 };
3772 | * var fn = function() { obj.val = 5 };
3773 | * assert.decreases(fn, obj, 'val');
3774 | *
3775 | * @name decreases
3776 | * @param {Function} modifier function
3777 | * @param {Object} object
3778 | * @param {String} property name
3779 | * @param {String} message _optional_
3780 | * @api public
3781 | */
3782 |
3783 | assert.decreases = function (fn, obj, prop) {
3784 | new Assertion(fn).to.decrease(obj, prop);
3785 | }
3786 |
3787 | /**
3788 | * ### .doesNotDecrease(function, object, property)
3789 | *
3790 | * Asserts that a function does not decreases an object property
3791 | *
3792 | * var obj = { val: 10 };
3793 | * var fn = function() { obj.val = 15 };
3794 | * assert.doesNotDecrease(fn, obj, 'val');
3795 | *
3796 | * @name doesNotDecrease
3797 | * @param {Function} modifier function
3798 | * @param {Object} object
3799 | * @param {String} property name
3800 | * @param {String} message _optional_
3801 | * @api public
3802 | */
3803 |
3804 | assert.doesNotDecrease = function (fn, obj, prop) {
3805 | new Assertion(fn).to.not.decrease(obj, prop);
3806 | }
3807 |
3808 | /*!
3809 | * Undocumented / untested
3810 | */
3811 |
3812 | assert.ifError = function (val, msg) {
3813 | new Assertion(val, msg).to.not.be.ok;
3814 | };
3815 |
3816 | /*!
3817 | * Aliases.
3818 | */
3819 |
3820 | (function alias(name, as){
3821 | assert[as] = assert[name];
3822 | return alias;
3823 | })
3824 | ('Throw', 'throw')
3825 | ('Throw', 'throws');
3826 | };
3827 |
3828 | });
3829 |
3830 | require.register("chai/lib/chai/interface/expect.js", function (exports, module) {
3831 | /*!
3832 | * chai
3833 | * Copyright(c) 2011-2014 Jake Luer
3834 | * MIT Licensed
3835 | */
3836 |
3837 | module.exports = function (chai, util) {
3838 | chai.expect = function (val, message) {
3839 | return new chai.Assertion(val, message);
3840 | };
3841 |
3842 | /**
3843 | * ### .fail(actual, expected, [message], [operator])
3844 | *
3845 | * Throw a failure.
3846 | *
3847 | * @name fail
3848 | * @param {Mixed} actual
3849 | * @param {Mixed} expected
3850 | * @param {String} message
3851 | * @param {String} operator
3852 | * @api public
3853 | */
3854 |
3855 | chai.expect.fail = function (actual, expected, message, operator) {
3856 | message = message || 'expect.fail()';
3857 | throw new chai.AssertionError(message, {
3858 | actual: actual
3859 | , expected: expected
3860 | , operator: operator
3861 | }, chai.expect.fail);
3862 | };
3863 | };
3864 |
3865 | });
3866 |
3867 | require.register("chai/lib/chai/interface/should.js", function (exports, module) {
3868 | /*!
3869 | * chai
3870 | * Copyright(c) 2011-2014 Jake Luer
3871 | * MIT Licensed
3872 | */
3873 |
3874 | module.exports = function (chai, util) {
3875 | var Assertion = chai.Assertion;
3876 |
3877 | function loadShould () {
3878 | // explicitly define this method as function as to have it's name to include as `ssfi`
3879 | function shouldGetter() {
3880 | if (this instanceof String || this instanceof Number || this instanceof Boolean ) {
3881 | return new Assertion(this.valueOf(), null, shouldGetter);
3882 | }
3883 | return new Assertion(this, null, shouldGetter);
3884 | }
3885 | function shouldSetter(value) {
3886 | // See https://github.com/chaijs/chai/issues/86: this makes
3887 | // `whatever.should = someValue` actually set `someValue`, which is
3888 | // especially useful for `global.should = require('chai').should()`.
3889 | //
3890 | // Note that we have to use [[DefineProperty]] instead of [[Put]]
3891 | // since otherwise we would trigger this very setter!
3892 | Object.defineProperty(this, 'should', {
3893 | value: value,
3894 | enumerable: true,
3895 | configurable: true,
3896 | writable: true
3897 | });
3898 | }
3899 | // modify Object.prototype to have `should`
3900 | Object.defineProperty(Object.prototype, 'should', {
3901 | set: shouldSetter
3902 | , get: shouldGetter
3903 | , configurable: true
3904 | });
3905 |
3906 | var should = {};
3907 |
3908 | /**
3909 | * ### .fail(actual, expected, [message], [operator])
3910 | *
3911 | * Throw a failure.
3912 | *
3913 | * @name fail
3914 | * @param {Mixed} actual
3915 | * @param {Mixed} expected
3916 | * @param {String} message
3917 | * @param {String} operator
3918 | * @api public
3919 | */
3920 |
3921 | should.fail = function (actual, expected, message, operator) {
3922 | message = message || 'should.fail()';
3923 | throw new chai.AssertionError(message, {
3924 | actual: actual
3925 | , expected: expected
3926 | , operator: operator
3927 | }, should.fail);
3928 | };
3929 |
3930 | should.equal = function (val1, val2, msg) {
3931 | new Assertion(val1, msg).to.equal(val2);
3932 | };
3933 |
3934 | should.Throw = function (fn, errt, errs, msg) {
3935 | new Assertion(fn, msg).to.Throw(errt, errs);
3936 | };
3937 |
3938 | should.exist = function (val, msg) {
3939 | new Assertion(val, msg).to.exist;
3940 | }
3941 |
3942 | // negation
3943 | should.not = {}
3944 |
3945 | should.not.equal = function (val1, val2, msg) {
3946 | new Assertion(val1, msg).to.not.equal(val2);
3947 | };
3948 |
3949 | should.not.Throw = function (fn, errt, errs, msg) {
3950 | new Assertion(fn, msg).to.not.Throw(errt, errs);
3951 | };
3952 |
3953 | should.not.exist = function (val, msg) {
3954 | new Assertion(val, msg).to.not.exist;
3955 | }
3956 |
3957 | should['throw'] = should['Throw'];
3958 | should.not['throw'] = should.not['Throw'];
3959 |
3960 | return should;
3961 | };
3962 |
3963 | chai.should = loadShould;
3964 | chai.Should = loadShould;
3965 | };
3966 |
3967 | });
3968 |
3969 | require.register("chai/lib/chai/utils/addChainableMethod.js", function (exports, module) {
3970 | /*!
3971 | * Chai - addChainingMethod utility
3972 | * Copyright(c) 2012-2014 Jake Luer
3973 | * MIT Licensed
3974 | */
3975 |
3976 | /*!
3977 | * Module dependencies
3978 | */
3979 |
3980 | var transferFlags = require('chai/lib/chai/utils/transferFlags.js');
3981 | var flag = require('chai/lib/chai/utils/flag.js');
3982 | var config = require('chai/lib/chai/config.js');
3983 |
3984 | /*!
3985 | * Module variables
3986 | */
3987 |
3988 | // Check whether `__proto__` is supported
3989 | var hasProtoSupport = '__proto__' in Object;
3990 |
3991 | // Without `__proto__` support, this module will need to add properties to a function.
3992 | // However, some Function.prototype methods cannot be overwritten,
3993 | // and there seems no easy cross-platform way to detect them (@see chaijs/chai/issues/69).
3994 | var excludeNames = /^(?:length|name|arguments|caller)$/;
3995 |
3996 | // Cache `Function` properties
3997 | var call = Function.prototype.call,
3998 | apply = Function.prototype.apply;
3999 |
4000 | /**
4001 | * ### addChainableMethod (ctx, name, method, chainingBehavior)
4002 | *
4003 | * Adds a method to an object, such that the method can also be chained.
4004 | *
4005 | * utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) {
4006 | * var obj = utils.flag(this, 'object');
4007 | * new chai.Assertion(obj).to.be.equal(str);
4008 | * });
4009 | *
4010 | * Can also be accessed directly from `chai.Assertion`.
4011 | *
4012 | * chai.Assertion.addChainableMethod('foo', fn, chainingBehavior);
4013 | *
4014 | * The result can then be used as both a method assertion, executing both `method` and
4015 | * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`.
4016 | *
4017 | * expect(fooStr).to.be.foo('bar');
4018 | * expect(fooStr).to.be.foo.equal('foo');
4019 | *
4020 | * @param {Object} ctx object to which the method is added
4021 | * @param {String} name of method to add
4022 | * @param {Function} method function to be used for `name`, when called
4023 | * @param {Function} chainingBehavior function to be called every time the property is accessed
4024 | * @name addChainableMethod
4025 | * @api public
4026 | */
4027 |
4028 | module.exports = function (ctx, name, method, chainingBehavior) {
4029 | if (typeof chainingBehavior !== 'function') {
4030 | chainingBehavior = function () { };
4031 | }
4032 |
4033 | var chainableBehavior = {
4034 | method: method
4035 | , chainingBehavior: chainingBehavior
4036 | };
4037 |
4038 | // save the methods so we can overwrite them later, if we need to.
4039 | if (!ctx.__methods) {
4040 | ctx.__methods = {};
4041 | }
4042 | ctx.__methods[name] = chainableBehavior;
4043 |
4044 | Object.defineProperty(ctx, name,
4045 | { get: function () {
4046 | chainableBehavior.chainingBehavior.call(this);
4047 |
4048 | var assert = function assert() {
4049 | var old_ssfi = flag(this, 'ssfi');
4050 | if (old_ssfi && config.includeStack === false)
4051 | flag(this, 'ssfi', assert);
4052 | var result = chainableBehavior.method.apply(this, arguments);
4053 | return result === undefined ? this : result;
4054 | };
4055 |
4056 | // Use `__proto__` if available
4057 | if (hasProtoSupport) {
4058 | // Inherit all properties from the object by replacing the `Function` prototype
4059 | var prototype = assert.__proto__ = Object.create(this);
4060 | // Restore the `call` and `apply` methods from `Function`
4061 | prototype.call = call;
4062 | prototype.apply = apply;
4063 | }
4064 | // Otherwise, redefine all properties (slow!)
4065 | else {
4066 | var asserterNames = Object.getOwnPropertyNames(ctx);
4067 | asserterNames.forEach(function (asserterName) {
4068 | if (!excludeNames.test(asserterName)) {
4069 | var pd = Object.getOwnPropertyDescriptor(ctx, asserterName);
4070 | Object.defineProperty(assert, asserterName, pd);
4071 | }
4072 | });
4073 | }
4074 |
4075 | transferFlags(this, assert);
4076 | return assert;
4077 | }
4078 | , configurable: true
4079 | });
4080 | };
4081 |
4082 | });
4083 |
4084 | require.register("chai/lib/chai/utils/addMethod.js", function (exports, module) {
4085 | /*!
4086 | * Chai - addMethod utility
4087 | * Copyright(c) 2012-2014 Jake Luer
4088 | * MIT Licensed
4089 | */
4090 |
4091 | var config = require('chai/lib/chai/config.js');
4092 |
4093 | /**
4094 | * ### .addMethod (ctx, name, method)
4095 | *
4096 | * Adds a method to the prototype of an object.
4097 | *
4098 | * utils.addMethod(chai.Assertion.prototype, 'foo', function (str) {
4099 | * var obj = utils.flag(this, 'object');
4100 | * new chai.Assertion(obj).to.be.equal(str);
4101 | * });
4102 | *
4103 | * Can also be accessed directly from `chai.Assertion`.
4104 | *
4105 | * chai.Assertion.addMethod('foo', fn);
4106 | *
4107 | * Then can be used as any other assertion.
4108 | *
4109 | * expect(fooStr).to.be.foo('bar');
4110 | *
4111 | * @param {Object} ctx object to which the method is added
4112 | * @param {String} name of method to add
4113 | * @param {Function} method function to be used for name
4114 | * @name addMethod
4115 | * @api public
4116 | */
4117 | var flag = require('chai/lib/chai/utils/flag.js');
4118 |
4119 | module.exports = function (ctx, name, method) {
4120 | ctx[name] = function () {
4121 | var old_ssfi = flag(this, 'ssfi');
4122 | if (old_ssfi && config.includeStack === false)
4123 | flag(this, 'ssfi', ctx[name]);
4124 | var result = method.apply(this, arguments);
4125 | return result === undefined ? this : result;
4126 | };
4127 | };
4128 |
4129 | });
4130 |
4131 | require.register("chai/lib/chai/utils/addProperty.js", function (exports, module) {
4132 | /*!
4133 | * Chai - addProperty utility
4134 | * Copyright(c) 2012-2014 Jake Luer
4135 | * MIT Licensed
4136 | */
4137 |
4138 | /**
4139 | * ### addProperty (ctx, name, getter)
4140 | *
4141 | * Adds a property to the prototype of an object.
4142 | *
4143 | * utils.addProperty(chai.Assertion.prototype, 'foo', function () {
4144 | * var obj = utils.flag(this, 'object');
4145 | * new chai.Assertion(obj).to.be.instanceof(Foo);
4146 | * });
4147 | *
4148 | * Can also be accessed directly from `chai.Assertion`.
4149 | *
4150 | * chai.Assertion.addProperty('foo', fn);
4151 | *
4152 | * Then can be used as any other assertion.
4153 | *
4154 | * expect(myFoo).to.be.foo;
4155 | *
4156 | * @param {Object} ctx object to which the property is added
4157 | * @param {String} name of property to add
4158 | * @param {Function} getter function to be used for name
4159 | * @name addProperty
4160 | * @api public
4161 | */
4162 |
4163 | module.exports = function (ctx, name, getter) {
4164 | Object.defineProperty(ctx, name,
4165 | { get: function () {
4166 | var result = getter.call(this);
4167 | return result === undefined ? this : result;
4168 | }
4169 | , configurable: true
4170 | });
4171 | };
4172 |
4173 | });
4174 |
4175 | require.register("chai/lib/chai/utils/flag.js", function (exports, module) {
4176 | /*!
4177 | * Chai - flag utility
4178 | * Copyright(c) 2012-2014 Jake Luer
4179 | * MIT Licensed
4180 | */
4181 |
4182 | /**
4183 | * ### flag(object, key, [value])
4184 | *
4185 | * Get or set a flag value on an object. If a
4186 | * value is provided it will be set, else it will
4187 | * return the currently set value or `undefined` if
4188 | * the value is not set.
4189 | *
4190 | * utils.flag(this, 'foo', 'bar'); // setter
4191 | * utils.flag(this, 'foo'); // getter, returns `bar`
4192 | *
4193 | * @param {Object} object constructed Assertion
4194 | * @param {String} key
4195 | * @param {Mixed} value (optional)
4196 | * @name flag
4197 | * @api private
4198 | */
4199 |
4200 | module.exports = function (obj, key, value) {
4201 | var flags = obj.__flags || (obj.__flags = Object.create(null));
4202 | if (arguments.length === 3) {
4203 | flags[key] = value;
4204 | } else {
4205 | return flags[key];
4206 | }
4207 | };
4208 |
4209 | });
4210 |
4211 | require.register("chai/lib/chai/utils/getActual.js", function (exports, module) {
4212 | /*!
4213 | * Chai - getActual utility
4214 | * Copyright(c) 2012-2014 Jake Luer
4215 | * MIT Licensed
4216 | */
4217 |
4218 | /**
4219 | * # getActual(object, [actual])
4220 | *
4221 | * Returns the `actual` value for an Assertion
4222 | *
4223 | * @param {Object} object (constructed Assertion)
4224 | * @param {Arguments} chai.Assertion.prototype.assert arguments
4225 | */
4226 |
4227 | module.exports = function (obj, args) {
4228 | return args.length > 4 ? args[4] : obj._obj;
4229 | };
4230 |
4231 | });
4232 |
4233 | require.register("chai/lib/chai/utils/getEnumerableProperties.js", function (exports, module) {
4234 | /*!
4235 | * Chai - getEnumerableProperties utility
4236 | * Copyright(c) 2012-2014 Jake Luer
4237 | * MIT Licensed
4238 | */
4239 |
4240 | /**
4241 | * ### .getEnumerableProperties(object)
4242 | *
4243 | * This allows the retrieval of enumerable property names of an object,
4244 | * inherited or not.
4245 | *
4246 | * @param {Object} object
4247 | * @returns {Array}
4248 | * @name getEnumerableProperties
4249 | * @api public
4250 | */
4251 |
4252 | module.exports = function getEnumerableProperties(object) {
4253 | var result = [];
4254 | for (var name in object) {
4255 | result.push(name);
4256 | }
4257 | return result;
4258 | };
4259 |
4260 | });
4261 |
4262 | require.register("chai/lib/chai/utils/getMessage.js", function (exports, module) {
4263 | /*!
4264 | * Chai - message composition utility
4265 | * Copyright(c) 2012-2014 Jake Luer
4266 | * MIT Licensed
4267 | */
4268 |
4269 | /*!
4270 | * Module dependancies
4271 | */
4272 |
4273 | var flag = require('chai/lib/chai/utils/flag.js')
4274 | , getActual = require('chai/lib/chai/utils/getActual.js')
4275 | , inspect = require('chai/lib/chai/utils/inspect.js')
4276 | , objDisplay = require('chai/lib/chai/utils/objDisplay.js');
4277 |
4278 | /**
4279 | * ### .getMessage(object, message, negateMessage)
4280 | *
4281 | * Construct the error message based on flags
4282 | * and template tags. Template tags will return
4283 | * a stringified inspection of the object referenced.
4284 | *
4285 | * Message template tags:
4286 | * - `#{this}` current asserted object
4287 | * - `#{act}` actual value
4288 | * - `#{exp}` expected value
4289 | *
4290 | * @param {Object} object (constructed Assertion)
4291 | * @param {Arguments} chai.Assertion.prototype.assert arguments
4292 | * @name getMessage
4293 | * @api public
4294 | */
4295 |
4296 | module.exports = function (obj, args) {
4297 | var negate = flag(obj, 'negate')
4298 | , val = flag(obj, 'object')
4299 | , expected = args[3]
4300 | , actual = getActual(obj, args)
4301 | , msg = negate ? args[2] : args[1]
4302 | , flagMsg = flag(obj, 'message');
4303 |
4304 | if(typeof msg === "function") msg = msg();
4305 | msg = msg || '';
4306 | msg = msg
4307 | .replace(/#{this}/g, objDisplay(val))
4308 | .replace(/#{act}/g, objDisplay(actual))
4309 | .replace(/#{exp}/g, objDisplay(expected));
4310 |
4311 | return flagMsg ? flagMsg + ': ' + msg : msg;
4312 | };
4313 |
4314 | });
4315 |
4316 | require.register("chai/lib/chai/utils/getName.js", function (exports, module) {
4317 | /*!
4318 | * Chai - getName utility
4319 | * Copyright(c) 2012-2014 Jake Luer
4320 | * MIT Licensed
4321 | */
4322 |
4323 | /**
4324 | * # getName(func)
4325 | *
4326 | * Gets the name of a function, in a cross-browser way.
4327 | *
4328 | * @param {Function} a function (usually a constructor)
4329 | */
4330 |
4331 | module.exports = function (func) {
4332 | if (func.name) return func.name;
4333 |
4334 | var match = /^\s?function ([^(]*)\(/.exec(func);
4335 | return match && match[1] ? match[1] : "";
4336 | };
4337 |
4338 | });
4339 |
4340 | require.register("chai/lib/chai/utils/getPathValue.js", function (exports, module) {
4341 | /*!
4342 | * Chai - getPathValue utility
4343 | * Copyright(c) 2012-2014 Jake Luer
4344 | * @see https://github.com/logicalparadox/filtr
4345 | * MIT Licensed
4346 | */
4347 |
4348 | var getPathInfo = require('chai/lib/chai/utils/getPathInfo.js');
4349 |
4350 | /**
4351 | * ### .getPathValue(path, object)
4352 | *
4353 | * This allows the retrieval of values in an
4354 | * object given a string path.
4355 | *
4356 | * var obj = {
4357 | * prop1: {
4358 | * arr: ['a', 'b', 'c']
4359 | * , str: 'Hello'
4360 | * }
4361 | * , prop2: {
4362 | * arr: [ { nested: 'Universe' } ]
4363 | * , str: 'Hello again!'
4364 | * }
4365 | * }
4366 | *
4367 | * The following would be the results.
4368 | *
4369 | * getPathValue('prop1.str', obj); // Hello
4370 | * getPathValue('prop1.att[2]', obj); // b
4371 | * getPathValue('prop2.arr[0].nested', obj); // Universe
4372 | *
4373 | * @param {String} path
4374 | * @param {Object} object
4375 | * @returns {Object} value or `undefined`
4376 | * @name getPathValue
4377 | * @api public
4378 | */
4379 | module.exports = function(path, obj) {
4380 | var info = getPathInfo(path, obj);
4381 | return info.value;
4382 | };
4383 |
4384 | });
4385 |
4386 | require.register("chai/lib/chai/utils/getPathInfo.js", function (exports, module) {
4387 | /*!
4388 | * Chai - getPathInfo utility
4389 | * Copyright(c) 2012-2014 Jake Luer
4390 | * MIT Licensed
4391 | */
4392 |
4393 | var hasProperty = require('chai/lib/chai/utils/hasProperty.js');
4394 |
4395 | /**
4396 | * ### .getPathInfo(path, object)
4397 | *
4398 | * This allows the retrieval of property info in an
4399 | * object given a string path.
4400 | *
4401 | * The path info consists of an object with the
4402 | * following properties:
4403 | *
4404 | * * parent - The parent object of the property referenced by `path`
4405 | * * name - The name of the final property, a number if it was an array indexer
4406 | * * value - The value of the property, if it exists, otherwise `undefined`
4407 | * * exists - Whether the property exists or not
4408 | *
4409 | * @param {String} path
4410 | * @param {Object} object
4411 | * @returns {Object} info
4412 | * @name getPathInfo
4413 | * @api public
4414 | */
4415 |
4416 | module.exports = function getPathInfo(path, obj) {
4417 | var parsed = parsePath(path),
4418 | last = parsed[parsed.length - 1];
4419 |
4420 | var info = {
4421 | parent: parsed.length > 1 ? _getPathValue(parsed, obj, parsed.length - 1) : obj,
4422 | name: last.p || last.i,
4423 | value: _getPathValue(parsed, obj),
4424 | };
4425 | info.exists = hasProperty(info.name, info.parent);
4426 |
4427 | return info;
4428 | };
4429 |
4430 |
4431 | /*!
4432 | * ## parsePath(path)
4433 | *
4434 | * Helper function used to parse string object
4435 | * paths. Use in conjunction with `_getPathValue`.
4436 | *
4437 | * var parsed = parsePath('myobject.property.subprop');
4438 | *
4439 | * ### Paths:
4440 | *
4441 | * * Can be as near infinitely deep and nested
4442 | * * Arrays are also valid using the formal `myobject.document[3].property`.
4443 | * * Literal dots and brackets (not delimiter) must be backslash-escaped.
4444 | *
4445 | * @param {String} path
4446 | * @returns {Object} parsed
4447 | * @api private
4448 | */
4449 |
4450 | function parsePath (path) {
4451 | var str = path.replace(/([^\\])\[/g, '$1.[')
4452 | , parts = str.match(/(\\\.|[^.]+?)+/g);
4453 | return parts.map(function (value) {
4454 | var re = /^\[(\d+)\]$/
4455 | , mArr = re.exec(value);
4456 | if (mArr) return { i: parseFloat(mArr[1]) };
4457 | else return { p: value.replace(/\\([.\[\]])/g, '$1') };
4458 | });
4459 | }
4460 |
4461 |
4462 | /*!
4463 | * ## _getPathValue(parsed, obj)
4464 | *
4465 | * Helper companion function for `.parsePath` that returns
4466 | * the value located at the parsed address.
4467 | *
4468 | * var value = getPathValue(parsed, obj);
4469 | *
4470 | * @param {Object} parsed definition from `parsePath`.
4471 | * @param {Object} object to search against
4472 | * @param {Number} object to search against
4473 | * @returns {Object|Undefined} value
4474 | * @api private
4475 | */
4476 |
4477 | function _getPathValue (parsed, obj, index) {
4478 | var tmp = obj
4479 | , res;
4480 |
4481 | index = (index === undefined ? parsed.length : index);
4482 |
4483 | for (var i = 0, l = index; i < l; i++) {
4484 | var part = parsed[i];
4485 | if (tmp) {
4486 | if ('undefined' !== typeof part.p)
4487 | tmp = tmp[part.p];
4488 | else if ('undefined' !== typeof part.i)
4489 | tmp = tmp[part.i];
4490 | if (i == (l - 1)) res = tmp;
4491 | } else {
4492 | res = undefined;
4493 | }
4494 | }
4495 | return res;
4496 | }
4497 |
4498 | });
4499 |
4500 | require.register("chai/lib/chai/utils/hasProperty.js", function (exports, module) {
4501 | /*!
4502 | * Chai - hasProperty utility
4503 | * Copyright(c) 2012-2014 Jake Luer
4504 | * MIT Licensed
4505 | */
4506 |
4507 | var type = require('chai/lib/chai/utils/type.js');
4508 |
4509 | /**
4510 | * ### .hasProperty(object, name)
4511 | *
4512 | * This allows checking whether an object has
4513 | * named property or numeric array index.
4514 | *
4515 | * Basically does the same thing as the `in`
4516 | * operator but works properly with natives
4517 | * and null/undefined values.
4518 | *
4519 | * var obj = {
4520 | * arr: ['a', 'b', 'c']
4521 | * , str: 'Hello'
4522 | * }
4523 | *
4524 | * The following would be the results.
4525 | *
4526 | * hasProperty('str', obj); // true
4527 | * hasProperty('constructor', obj); // true
4528 | * hasProperty('bar', obj); // false
4529 | *
4530 | * hasProperty('length', obj.str); // true
4531 | * hasProperty(1, obj.str); // true
4532 | * hasProperty(5, obj.str); // false
4533 | *
4534 | * hasProperty('length', obj.arr); // true
4535 | * hasProperty(2, obj.arr); // true
4536 | * hasProperty(3, obj.arr); // false
4537 | *
4538 | * @param {Objuect} object
4539 | * @param {String|Number} name
4540 | * @returns {Boolean} whether it exists
4541 | * @name getPathInfo
4542 | * @api public
4543 | */
4544 |
4545 | var literals = {
4546 | 'number': Number
4547 | , 'string': String
4548 | };
4549 |
4550 | module.exports = function hasProperty(name, obj) {
4551 | var ot = type(obj);
4552 |
4553 | // Bad Object, obviously no props at all
4554 | if(ot === 'null' || ot === 'undefined')
4555 | return false;
4556 |
4557 | // The `in` operator does not work with certain literals
4558 | // box these before the check
4559 | if(literals[ot] && typeof obj !== 'object')
4560 | obj = new literals[ot](obj);
4561 |
4562 | return name in obj;
4563 | };
4564 |
4565 | });
4566 |
4567 | require.register("chai/lib/chai/utils/getProperties.js", function (exports, module) {
4568 | /*!
4569 | * Chai - getProperties utility
4570 | * Copyright(c) 2012-2014 Jake Luer
4571 | * MIT Licensed
4572 | */
4573 |
4574 | /**
4575 | * ### .getProperties(object)
4576 | *
4577 | * This allows the retrieval of property names of an object, enumerable or not,
4578 | * inherited or not.
4579 | *
4580 | * @param {Object} object
4581 | * @returns {Array}
4582 | * @name getProperties
4583 | * @api public
4584 | */
4585 |
4586 | module.exports = function getProperties(object) {
4587 | var result = Object.getOwnPropertyNames(subject);
4588 |
4589 | function addProperty(property) {
4590 | if (result.indexOf(property) === -1) {
4591 | result.push(property);
4592 | }
4593 | }
4594 |
4595 | var proto = Object.getPrototypeOf(subject);
4596 | while (proto !== null) {
4597 | Object.getOwnPropertyNames(proto).forEach(addProperty);
4598 | proto = Object.getPrototypeOf(proto);
4599 | }
4600 |
4601 | return result;
4602 | };
4603 |
4604 | });
4605 |
4606 | require.register("chai/lib/chai/utils/index.js", function (exports, module) {
4607 | /*!
4608 | * chai
4609 | * Copyright(c) 2011 Jake Luer
4610 | * MIT Licensed
4611 | */
4612 |
4613 | /*!
4614 | * Main exports
4615 | */
4616 |
4617 | var exports = module.exports = {};
4618 |
4619 | /*!
4620 | * test utility
4621 | */
4622 |
4623 | exports.test = require('chai/lib/chai/utils/test.js');
4624 |
4625 | /*!
4626 | * type utility
4627 | */
4628 |
4629 | exports.type = require('chai/lib/chai/utils/type.js');
4630 |
4631 | /*!
4632 | * message utility
4633 | */
4634 |
4635 | exports.getMessage = require('chai/lib/chai/utils/getMessage.js');
4636 |
4637 | /*!
4638 | * actual utility
4639 | */
4640 |
4641 | exports.getActual = require('chai/lib/chai/utils/getActual.js');
4642 |
4643 | /*!
4644 | * Inspect util
4645 | */
4646 |
4647 | exports.inspect = require('chai/lib/chai/utils/inspect.js');
4648 |
4649 | /*!
4650 | * Object Display util
4651 | */
4652 |
4653 | exports.objDisplay = require('chai/lib/chai/utils/objDisplay.js');
4654 |
4655 | /*!
4656 | * Flag utility
4657 | */
4658 |
4659 | exports.flag = require('chai/lib/chai/utils/flag.js');
4660 |
4661 | /*!
4662 | * Flag transferring utility
4663 | */
4664 |
4665 | exports.transferFlags = require('chai/lib/chai/utils/transferFlags.js');
4666 |
4667 | /*!
4668 | * Deep equal utility
4669 | */
4670 |
4671 | exports.eql = require('chaijs~deep-eql@0.1.3');
4672 |
4673 | /*!
4674 | * Deep path value
4675 | */
4676 |
4677 | exports.getPathValue = require('chai/lib/chai/utils/getPathValue.js');
4678 |
4679 | /*!
4680 | * Deep path info
4681 | */
4682 |
4683 | exports.getPathInfo = require('chai/lib/chai/utils/getPathInfo.js');
4684 |
4685 | /*!
4686 | * Check if a property exists
4687 | */
4688 |
4689 | exports.hasProperty = require('chai/lib/chai/utils/hasProperty.js');
4690 |
4691 | /*!
4692 | * Function name
4693 | */
4694 |
4695 | exports.getName = require('chai/lib/chai/utils/getName.js');
4696 |
4697 | /*!
4698 | * add Property
4699 | */
4700 |
4701 | exports.addProperty = require('chai/lib/chai/utils/addProperty.js');
4702 |
4703 | /*!
4704 | * add Method
4705 | */
4706 |
4707 | exports.addMethod = require('chai/lib/chai/utils/addMethod.js');
4708 |
4709 | /*!
4710 | * overwrite Property
4711 | */
4712 |
4713 | exports.overwriteProperty = require('chai/lib/chai/utils/overwriteProperty.js');
4714 |
4715 | /*!
4716 | * overwrite Method
4717 | */
4718 |
4719 | exports.overwriteMethod = require('chai/lib/chai/utils/overwriteMethod.js');
4720 |
4721 | /*!
4722 | * Add a chainable method
4723 | */
4724 |
4725 | exports.addChainableMethod = require('chai/lib/chai/utils/addChainableMethod.js');
4726 |
4727 | /*!
4728 | * Overwrite chainable method
4729 | */
4730 |
4731 | exports.overwriteChainableMethod = require('chai/lib/chai/utils/overwriteChainableMethod.js');
4732 |
4733 |
4734 | });
4735 |
4736 | require.register("chai/lib/chai/utils/inspect.js", function (exports, module) {
4737 | // This is (almost) directly from Node.js utils
4738 | // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js
4739 |
4740 | var getName = require('chai/lib/chai/utils/getName.js');
4741 | var getProperties = require('chai/lib/chai/utils/getProperties.js');
4742 | var getEnumerableProperties = require('chai/lib/chai/utils/getEnumerableProperties.js');
4743 |
4744 | module.exports = inspect;
4745 |
4746 | /**
4747 | * Echos the value of a value. Trys to print the value out
4748 | * in the best way possible given the different types.
4749 | *
4750 | * @param {Object} obj The object to print out.
4751 | * @param {Boolean} showHidden Flag that shows hidden (not enumerable)
4752 | * properties of objects.
4753 | * @param {Number} depth Depth in which to descend in object. Default is 2.
4754 | * @param {Boolean} colors Flag to turn on ANSI escape codes to color the
4755 | * output. Default is false (no coloring).
4756 | */
4757 | function inspect(obj, showHidden, depth, colors) {
4758 | var ctx = {
4759 | showHidden: showHidden,
4760 | seen: [],
4761 | stylize: function (str) { return str; }
4762 | };
4763 | return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth));
4764 | }
4765 |
4766 | // Returns true if object is a DOM element.
4767 | var isDOMElement = function (object) {
4768 | if (typeof HTMLElement === 'object') {
4769 | return object instanceof HTMLElement;
4770 | } else {
4771 | return object &&
4772 | typeof object === 'object' &&
4773 | object.nodeType === 1 &&
4774 | typeof object.nodeName === 'string';
4775 | }
4776 | };
4777 |
4778 | function formatValue(ctx, value, recurseTimes) {
4779 | // Provide a hook for user-specified inspect functions.
4780 | // Check that value is an object with an inspect function on it
4781 | if (value && typeof value.inspect === 'function' &&
4782 | // Filter out the util module, it's inspect function is special
4783 | value.inspect !== exports.inspect &&
4784 | // Also filter out any prototype objects using the circular check.
4785 | !(value.constructor && value.constructor.prototype === value)) {
4786 | var ret = value.inspect(recurseTimes);
4787 | if (typeof ret !== 'string') {
4788 | ret = formatValue(ctx, ret, recurseTimes);
4789 | }
4790 | return ret;
4791 | }
4792 |
4793 | // Primitive types cannot have properties
4794 | var primitive = formatPrimitive(ctx, value);
4795 | if (primitive) {
4796 | return primitive;
4797 | }
4798 |
4799 | // If this is a DOM element, try to get the outer HTML.
4800 | if (isDOMElement(value)) {
4801 | if ('outerHTML' in value) {
4802 | return value.outerHTML;
4803 | // This value does not have an outerHTML attribute,
4804 | // it could still be an XML element
4805 | } else {
4806 | // Attempt to serialize it
4807 | try {
4808 | if (document.xmlVersion) {
4809 | var xmlSerializer = new XMLSerializer();
4810 | return xmlSerializer.serializeToString(value);
4811 | } else {
4812 | // Firefox 11- do not support outerHTML
4813 | // It does, however, support innerHTML
4814 | // Use the following to render the element
4815 | var ns = "http://www.w3.org/1999/xhtml";
4816 | var container = document.createElementNS(ns, '_');
4817 |
4818 | container.appendChild(value.cloneNode(false));
4819 | html = container.innerHTML
4820 | .replace('><', '>' + value.innerHTML + '<');
4821 | container.innerHTML = '';
4822 | return html;
4823 | }
4824 | } catch (err) {
4825 | // This could be a non-native DOM implementation,
4826 | // continue with the normal flow:
4827 | // printing the element as if it is an object.
4828 | }
4829 | }
4830 | }
4831 |
4832 | // Look up the keys of the object.
4833 | var visibleKeys = getEnumerableProperties(value);
4834 | var keys = ctx.showHidden ? getProperties(value) : visibleKeys;
4835 |
4836 | // Some type of object without properties can be shortcutted.
4837 | // In IE, errors have a single `stack` property, or if they are vanilla `Error`,
4838 | // a `stack` plus `description` property; ignore those for consistency.
4839 | if (keys.length === 0 || (isError(value) && (
4840 | (keys.length === 1 && keys[0] === 'stack') ||
4841 | (keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack')
4842 | ))) {
4843 | if (typeof value === 'function') {
4844 | var name = getName(value);
4845 | var nameSuffix = name ? ': ' + name : '';
4846 | return ctx.stylize('[Function' + nameSuffix + ']', 'special');
4847 | }
4848 | if (isRegExp(value)) {
4849 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
4850 | }
4851 | if (isDate(value)) {
4852 | return ctx.stylize(Date.prototype.toUTCString.call(value), 'date');
4853 | }
4854 | if (isError(value)) {
4855 | return formatError(value);
4856 | }
4857 | }
4858 |
4859 | var base = '', array = false, braces = ['{', '}'];
4860 |
4861 | // Make Array say that they are Array
4862 | if (isArray(value)) {
4863 | array = true;
4864 | braces = ['[', ']'];
4865 | }
4866 |
4867 | // Make functions say that they are functions
4868 | if (typeof value === 'function') {
4869 | var name = getName(value);
4870 | var nameSuffix = name ? ': ' + name : '';
4871 | base = ' [Function' + nameSuffix + ']';
4872 | }
4873 |
4874 | // Make RegExps say that they are RegExps
4875 | if (isRegExp(value)) {
4876 | base = ' ' + RegExp.prototype.toString.call(value);
4877 | }
4878 |
4879 | // Make dates with properties first say the date
4880 | if (isDate(value)) {
4881 | base = ' ' + Date.prototype.toUTCString.call(value);
4882 | }
4883 |
4884 | // Make error with message first say the error
4885 | if (isError(value)) {
4886 | return formatError(value);
4887 | }
4888 |
4889 | if (keys.length === 0 && (!array || value.length == 0)) {
4890 | return braces[0] + base + braces[1];
4891 | }
4892 |
4893 | if (recurseTimes < 0) {
4894 | if (isRegExp(value)) {
4895 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
4896 | } else {
4897 | return ctx.stylize('[Object]', 'special');
4898 | }
4899 | }
4900 |
4901 | ctx.seen.push(value);
4902 |
4903 | var output;
4904 | if (array) {
4905 | output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
4906 | } else {
4907 | output = keys.map(function(key) {
4908 | return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
4909 | });
4910 | }
4911 |
4912 | ctx.seen.pop();
4913 |
4914 | return reduceToSingleString(output, base, braces);
4915 | }
4916 |
4917 |
4918 | function formatPrimitive(ctx, value) {
4919 | switch (typeof value) {
4920 | case 'undefined':
4921 | return ctx.stylize('undefined', 'undefined');
4922 |
4923 | case 'string':
4924 | var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
4925 | .replace(/'/g, "\\'")
4926 | .replace(/\\"/g, '"') + '\'';
4927 | return ctx.stylize(simple, 'string');
4928 |
4929 | case 'number':
4930 | if (value === 0 && (1/value) === -Infinity) {
4931 | return ctx.stylize('-0', 'number');
4932 | }
4933 | return ctx.stylize('' + value, 'number');
4934 |
4935 | case 'boolean':
4936 | return ctx.stylize('' + value, 'boolean');
4937 | }
4938 | // For some reason typeof null is "object", so special case here.
4939 | if (value === null) {
4940 | return ctx.stylize('null', 'null');
4941 | }
4942 | }
4943 |
4944 |
4945 | function formatError(value) {
4946 | return '[' + Error.prototype.toString.call(value) + ']';
4947 | }
4948 |
4949 |
4950 | function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
4951 | var output = [];
4952 | for (var i = 0, l = value.length; i < l; ++i) {
4953 | if (Object.prototype.hasOwnProperty.call(value, String(i))) {
4954 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
4955 | String(i), true));
4956 | } else {
4957 | output.push('');
4958 | }
4959 | }
4960 | keys.forEach(function(key) {
4961 | if (!key.match(/^\d+$/)) {
4962 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
4963 | key, true));
4964 | }
4965 | });
4966 | return output;
4967 | }
4968 |
4969 |
4970 | function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
4971 | var name, str;
4972 | if (value.__lookupGetter__) {
4973 | if (value.__lookupGetter__(key)) {
4974 | if (value.__lookupSetter__(key)) {
4975 | str = ctx.stylize('[Getter/Setter]', 'special');
4976 | } else {
4977 | str = ctx.stylize('[Getter]', 'special');
4978 | }
4979 | } else {
4980 | if (value.__lookupSetter__(key)) {
4981 | str = ctx.stylize('[Setter]', 'special');
4982 | }
4983 | }
4984 | }
4985 | if (visibleKeys.indexOf(key) < 0) {
4986 | name = '[' + key + ']';
4987 | }
4988 | if (!str) {
4989 | if (ctx.seen.indexOf(value[key]) < 0) {
4990 | if (recurseTimes === null) {
4991 | str = formatValue(ctx, value[key], null);
4992 | } else {
4993 | str = formatValue(ctx, value[key], recurseTimes - 1);
4994 | }
4995 | if (str.indexOf('\n') > -1) {
4996 | if (array) {
4997 | str = str.split('\n').map(function(line) {
4998 | return ' ' + line;
4999 | }).join('\n').substr(2);
5000 | } else {
5001 | str = '\n' + str.split('\n').map(function(line) {
5002 | return ' ' + line;
5003 | }).join('\n');
5004 | }
5005 | }
5006 | } else {
5007 | str = ctx.stylize('[Circular]', 'special');
5008 | }
5009 | }
5010 | if (typeof name === 'undefined') {
5011 | if (array && key.match(/^\d+$/)) {
5012 | return str;
5013 | }
5014 | name = JSON.stringify('' + key);
5015 | if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
5016 | name = name.substr(1, name.length - 2);
5017 | name = ctx.stylize(name, 'name');
5018 | } else {
5019 | name = name.replace(/'/g, "\\'")
5020 | .replace(/\\"/g, '"')
5021 | .replace(/(^"|"$)/g, "'");
5022 | name = ctx.stylize(name, 'string');
5023 | }
5024 | }
5025 |
5026 | return name + ': ' + str;
5027 | }
5028 |
5029 |
5030 | function reduceToSingleString(output, base, braces) {
5031 | var numLinesEst = 0;
5032 | var length = output.reduce(function(prev, cur) {
5033 | numLinesEst++;
5034 | if (cur.indexOf('\n') >= 0) numLinesEst++;
5035 | return prev + cur.length + 1;
5036 | }, 0);
5037 |
5038 | if (length > 60) {
5039 | return braces[0] +
5040 | (base === '' ? '' : base + '\n ') +
5041 | ' ' +
5042 | output.join(',\n ') +
5043 | ' ' +
5044 | braces[1];
5045 | }
5046 |
5047 | return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
5048 | }
5049 |
5050 | function isArray(ar) {
5051 | return Array.isArray(ar) ||
5052 | (typeof ar === 'object' && objectToString(ar) === '[object Array]');
5053 | }
5054 |
5055 | function isRegExp(re) {
5056 | return typeof re === 'object' && objectToString(re) === '[object RegExp]';
5057 | }
5058 |
5059 | function isDate(d) {
5060 | return typeof d === 'object' && objectToString(d) === '[object Date]';
5061 | }
5062 |
5063 | function isError(e) {
5064 | return typeof e === 'object' && objectToString(e) === '[object Error]';
5065 | }
5066 |
5067 | function objectToString(o) {
5068 | return Object.prototype.toString.call(o);
5069 | }
5070 |
5071 | });
5072 |
5073 | require.register("chai/lib/chai/utils/objDisplay.js", function (exports, module) {
5074 | /*!
5075 | * Chai - flag utility
5076 | * Copyright(c) 2012-2014 Jake Luer
5077 | * MIT Licensed
5078 | */
5079 |
5080 | /*!
5081 | * Module dependancies
5082 | */
5083 |
5084 | var inspect = require('chai/lib/chai/utils/inspect.js');
5085 | var config = require('chai/lib/chai/config.js');
5086 |
5087 | /**
5088 | * ### .objDisplay (object)
5089 | *
5090 | * Determines if an object or an array matches
5091 | * criteria to be inspected in-line for error
5092 | * messages or should be truncated.
5093 | *
5094 | * @param {Mixed} javascript object to inspect
5095 | * @name objDisplay
5096 | * @api public
5097 | */
5098 |
5099 | module.exports = function (obj) {
5100 | var str = inspect(obj)
5101 | , type = Object.prototype.toString.call(obj);
5102 |
5103 | if (config.truncateThreshold && str.length >= config.truncateThreshold) {
5104 | if (type === '[object Function]') {
5105 | return !obj.name || obj.name === ''
5106 | ? '[Function]'
5107 | : '[Function: ' + obj.name + ']';
5108 | } else if (type === '[object Array]') {
5109 | return '[ Array(' + obj.length + ') ]';
5110 | } else if (type === '[object Object]') {
5111 | var keys = Object.keys(obj)
5112 | , kstr = keys.length > 2
5113 | ? keys.splice(0, 2).join(', ') + ', ...'
5114 | : keys.join(', ');
5115 | return '{ Object (' + kstr + ') }';
5116 | } else {
5117 | return str;
5118 | }
5119 | } else {
5120 | return str;
5121 | }
5122 | };
5123 |
5124 | });
5125 |
5126 | require.register("chai/lib/chai/utils/overwriteMethod.js", function (exports, module) {
5127 | /*!
5128 | * Chai - overwriteMethod utility
5129 | * Copyright(c) 2012-2014 Jake Luer
5130 | * MIT Licensed
5131 | */
5132 |
5133 | /**
5134 | * ### overwriteMethod (ctx, name, fn)
5135 | *
5136 | * Overwites an already existing method and provides
5137 | * access to previous function. Must return function
5138 | * to be used for name.
5139 | *
5140 | * utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) {
5141 | * return function (str) {
5142 | * var obj = utils.flag(this, 'object');
5143 | * if (obj instanceof Foo) {
5144 | * new chai.Assertion(obj.value).to.equal(str);
5145 | * } else {
5146 | * _super.apply(this, arguments);
5147 | * }
5148 | * }
5149 | * });
5150 | *
5151 | * Can also be accessed directly from `chai.Assertion`.
5152 | *
5153 | * chai.Assertion.overwriteMethod('foo', fn);
5154 | *
5155 | * Then can be used as any other assertion.
5156 | *
5157 | * expect(myFoo).to.equal('bar');
5158 | *
5159 | * @param {Object} ctx object whose method is to be overwritten
5160 | * @param {String} name of method to overwrite
5161 | * @param {Function} method function that returns a function to be used for name
5162 | * @name overwriteMethod
5163 | * @api public
5164 | */
5165 |
5166 | module.exports = function (ctx, name, method) {
5167 | var _method = ctx[name]
5168 | , _super = function () { return this; };
5169 |
5170 | if (_method && 'function' === typeof _method)
5171 | _super = _method;
5172 |
5173 | ctx[name] = function () {
5174 | var result = method(_super).apply(this, arguments);
5175 | return result === undefined ? this : result;
5176 | }
5177 | };
5178 |
5179 | });
5180 |
5181 | require.register("chai/lib/chai/utils/overwriteProperty.js", function (exports, module) {
5182 | /*!
5183 | * Chai - overwriteProperty utility
5184 | * Copyright(c) 2012-2014 Jake Luer
5185 | * MIT Licensed
5186 | */
5187 |
5188 | /**
5189 | * ### overwriteProperty (ctx, name, fn)
5190 | *
5191 | * Overwites an already existing property getter and provides
5192 | * access to previous value. Must return function to use as getter.
5193 | *
5194 | * utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) {
5195 | * return function () {
5196 | * var obj = utils.flag(this, 'object');
5197 | * if (obj instanceof Foo) {
5198 | * new chai.Assertion(obj.name).to.equal('bar');
5199 | * } else {
5200 | * _super.call(this);
5201 | * }
5202 | * }
5203 | * });
5204 | *
5205 | *
5206 | * Can also be accessed directly from `chai.Assertion`.
5207 | *
5208 | * chai.Assertion.overwriteProperty('foo', fn);
5209 | *
5210 | * Then can be used as any other assertion.
5211 | *
5212 | * expect(myFoo).to.be.ok;
5213 | *
5214 | * @param {Object} ctx object whose property is to be overwritten
5215 | * @param {String} name of property to overwrite
5216 | * @param {Function} getter function that returns a getter function to be used for name
5217 | * @name overwriteProperty
5218 | * @api public
5219 | */
5220 |
5221 | module.exports = function (ctx, name, getter) {
5222 | var _get = Object.getOwnPropertyDescriptor(ctx, name)
5223 | , _super = function () {};
5224 |
5225 | if (_get && 'function' === typeof _get.get)
5226 | _super = _get.get
5227 |
5228 | Object.defineProperty(ctx, name,
5229 | { get: function () {
5230 | var result = getter(_super).call(this);
5231 | return result === undefined ? this : result;
5232 | }
5233 | , configurable: true
5234 | });
5235 | };
5236 |
5237 | });
5238 |
5239 | require.register("chai/lib/chai/utils/overwriteChainableMethod.js", function (exports, module) {
5240 | /*!
5241 | * Chai - overwriteChainableMethod utility
5242 | * Copyright(c) 2012-2014 Jake Luer
5243 | * MIT Licensed
5244 | */
5245 |
5246 | /**
5247 | * ### overwriteChainableMethod (ctx, name, method, chainingBehavior)
5248 | *
5249 | * Overwites an already existing chainable method
5250 | * and provides access to the previous function or
5251 | * property. Must return functions to be used for
5252 | * name.
5253 | *
5254 | * utils.overwriteChainableMethod(chai.Assertion.prototype, 'length',
5255 | * function (_super) {
5256 | * }
5257 | * , function (_super) {
5258 | * }
5259 | * );
5260 | *
5261 | * Can also be accessed directly from `chai.Assertion`.
5262 | *
5263 | * chai.Assertion.overwriteChainableMethod('foo', fn, fn);
5264 | *
5265 | * Then can be used as any other assertion.
5266 | *
5267 | * expect(myFoo).to.have.length(3);
5268 | * expect(myFoo).to.have.length.above(3);
5269 | *
5270 | * @param {Object} ctx object whose method / property is to be overwritten
5271 | * @param {String} name of method / property to overwrite
5272 | * @param {Function} method function that returns a function to be used for name
5273 | * @param {Function} chainingBehavior function that returns a function to be used for property
5274 | * @name overwriteChainableMethod
5275 | * @api public
5276 | */
5277 |
5278 | module.exports = function (ctx, name, method, chainingBehavior) {
5279 | var chainableBehavior = ctx.__methods[name];
5280 |
5281 | var _chainingBehavior = chainableBehavior.chainingBehavior;
5282 | chainableBehavior.chainingBehavior = function () {
5283 | var result = chainingBehavior(_chainingBehavior).call(this);
5284 | return result === undefined ? this : result;
5285 | };
5286 |
5287 | var _method = chainableBehavior.method;
5288 | chainableBehavior.method = function () {
5289 | var result = method(_method).apply(this, arguments);
5290 | return result === undefined ? this : result;
5291 | };
5292 | };
5293 |
5294 | });
5295 |
5296 | require.register("chai/lib/chai/utils/test.js", function (exports, module) {
5297 | /*!
5298 | * Chai - test utility
5299 | * Copyright(c) 2012-2014 Jake Luer
5300 | * MIT Licensed
5301 | */
5302 |
5303 | /*!
5304 | * Module dependancies
5305 | */
5306 |
5307 | var flag = require('chai/lib/chai/utils/flag.js');
5308 |
5309 | /**
5310 | * # test(object, expression)
5311 | *
5312 | * Test and object for expression.
5313 | *
5314 | * @param {Object} object (constructed Assertion)
5315 | * @param {Arguments} chai.Assertion.prototype.assert arguments
5316 | */
5317 |
5318 | module.exports = function (obj, args) {
5319 | var negate = flag(obj, 'negate')
5320 | , expr = args[0];
5321 | return negate ? !expr : expr;
5322 | };
5323 |
5324 | });
5325 |
5326 | require.register("chai/lib/chai/utils/transferFlags.js", function (exports, module) {
5327 | /*!
5328 | * Chai - transferFlags utility
5329 | * Copyright(c) 2012-2014 Jake Luer
5330 | * MIT Licensed
5331 | */
5332 |
5333 | /**
5334 | * ### transferFlags(assertion, object, includeAll = true)
5335 | *
5336 | * Transfer all the flags for `assertion` to `object`. If
5337 | * `includeAll` is set to `false`, then the base Chai
5338 | * assertion flags (namely `object`, `ssfi`, and `message`)
5339 | * will not be transferred.
5340 | *
5341 | *
5342 | * var newAssertion = new Assertion();
5343 | * utils.transferFlags(assertion, newAssertion);
5344 | *
5345 | * var anotherAsseriton = new Assertion(myObj);
5346 | * utils.transferFlags(assertion, anotherAssertion, false);
5347 | *
5348 | * @param {Assertion} assertion the assertion to transfer the flags from
5349 | * @param {Object} object the object to transfer the flags to; usually a new assertion
5350 | * @param {Boolean} includeAll
5351 | * @name transferFlags
5352 | * @api private
5353 | */
5354 |
5355 | module.exports = function (assertion, object, includeAll) {
5356 | var flags = assertion.__flags || (assertion.__flags = Object.create(null));
5357 |
5358 | if (!object.__flags) {
5359 | object.__flags = Object.create(null);
5360 | }
5361 |
5362 | includeAll = arguments.length === 3 ? includeAll : true;
5363 |
5364 | for (var flag in flags) {
5365 | if (includeAll ||
5366 | (flag !== 'object' && flag !== 'ssfi' && flag != 'message')) {
5367 | object.__flags[flag] = flags[flag];
5368 | }
5369 | }
5370 | };
5371 |
5372 | });
5373 |
5374 | require.register("chai/lib/chai/utils/type.js", function (exports, module) {
5375 | /*!
5376 | * Chai - type utility
5377 | * Copyright(c) 2012-2014 Jake Luer
5378 | * MIT Licensed
5379 | */
5380 |
5381 | /*!
5382 | * Detectable javascript natives
5383 | */
5384 |
5385 | var natives = {
5386 | '[object Arguments]': 'arguments'
5387 | , '[object Array]': 'array'
5388 | , '[object Date]': 'date'
5389 | , '[object Function]': 'function'
5390 | , '[object Number]': 'number'
5391 | , '[object RegExp]': 'regexp'
5392 | , '[object String]': 'string'
5393 | };
5394 |
5395 | /**
5396 | * ### type(object)
5397 | *
5398 | * Better implementation of `typeof` detection that can
5399 | * be used cross-browser. Handles the inconsistencies of
5400 | * Array, `null`, and `undefined` detection.
5401 | *
5402 | * utils.type({}) // 'object'
5403 | * utils.type(null) // `null'
5404 | * utils.type(undefined) // `undefined`
5405 | * utils.type([]) // `array`
5406 | *
5407 | * @param {Mixed} object to detect type of
5408 | * @name type
5409 | * @api private
5410 | */
5411 |
5412 | module.exports = function (obj) {
5413 | var str = Object.prototype.toString.call(obj);
5414 | if (natives[str]) return natives[str];
5415 | if (obj === null) return 'null';
5416 | if (obj === undefined) return 'undefined';
5417 | if (obj === Object(obj)) return 'object';
5418 | return typeof obj;
5419 | };
5420 |
5421 | });
5422 |
5423 | if (typeof exports == "object") {
5424 | module.exports = require("chai");
5425 | } else if (typeof define == "function" && define.amd) {
5426 | define("chai", [], function(){ return require("chai"); });
5427 | } else {
5428 | (this || window)["chai"] = require("chai");
5429 | }
5430 | })()
5431 |
--------------------------------------------------------------------------------
/test/vendors/mocha-2.2.5/mocha.css:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | body {
4 | margin:0;
5 | }
6 |
7 | #mocha {
8 | font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
9 | margin: 60px 50px;
10 | }
11 |
12 | #mocha ul,
13 | #mocha li {
14 | margin: 0;
15 | padding: 0;
16 | }
17 |
18 | #mocha ul {
19 | list-style: none;
20 | }
21 |
22 | #mocha h1,
23 | #mocha h2 {
24 | margin: 0;
25 | }
26 |
27 | #mocha h1 {
28 | margin-top: 15px;
29 | font-size: 1em;
30 | font-weight: 200;
31 | }
32 |
33 | #mocha h1 a {
34 | text-decoration: none;
35 | color: inherit;
36 | }
37 |
38 | #mocha h1 a:hover {
39 | text-decoration: underline;
40 | }
41 |
42 | #mocha .suite .suite h1 {
43 | margin-top: 0;
44 | font-size: .8em;
45 | }
46 |
47 | #mocha .hidden {
48 | display: none;
49 | }
50 |
51 | #mocha h2 {
52 | font-size: 12px;
53 | font-weight: normal;
54 | cursor: pointer;
55 | }
56 |
57 | #mocha .suite {
58 | margin-left: 15px;
59 | }
60 |
61 | #mocha .test {
62 | margin-left: 15px;
63 | overflow: hidden;
64 | }
65 |
66 | #mocha .test.pending:hover h2::after {
67 | content: '(pending)';
68 | font-family: arial, sans-serif;
69 | }
70 |
71 | #mocha .test.pass.medium .duration {
72 | background: #c09853;
73 | }
74 |
75 | #mocha .test.pass.slow .duration {
76 | background: #b94a48;
77 | }
78 |
79 | #mocha .test.pass::before {
80 | content: '✓';
81 | font-size: 12px;
82 | display: block;
83 | float: left;
84 | margin-right: 5px;
85 | color: #00d6b2;
86 | }
87 |
88 | #mocha .test.pass .duration {
89 | font-size: 9px;
90 | margin-left: 5px;
91 | padding: 2px 5px;
92 | color: #fff;
93 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
94 | -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
95 | box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
96 | -webkit-border-radius: 5px;
97 | -moz-border-radius: 5px;
98 | -ms-border-radius: 5px;
99 | -o-border-radius: 5px;
100 | border-radius: 5px;
101 | }
102 |
103 | #mocha .test.pass.fast .duration {
104 | display: none;
105 | }
106 |
107 | #mocha .test.pending {
108 | color: #0b97c4;
109 | }
110 |
111 | #mocha .test.pending::before {
112 | content: '◦';
113 | color: #0b97c4;
114 | }
115 |
116 | #mocha .test.fail {
117 | color: #c00;
118 | }
119 |
120 | #mocha .test.fail pre {
121 | color: black;
122 | }
123 |
124 | #mocha .test.fail::before {
125 | content: '✖';
126 | font-size: 12px;
127 | display: block;
128 | float: left;
129 | margin-right: 5px;
130 | color: #c00;
131 | }
132 |
133 | #mocha .test pre.error {
134 | color: #c00;
135 | max-height: 300px;
136 | overflow: auto;
137 | }
138 |
139 | /**
140 | * (1): approximate for browsers not supporting calc
141 | * (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border)
142 | * ^^ seriously
143 | */
144 | #mocha .test pre {
145 | display: block;
146 | float: left;
147 | clear: left;
148 | font: 12px/1.5 monaco, monospace;
149 | margin: 5px;
150 | padding: 15px;
151 | border: 1px solid #eee;
152 | max-width: 85%; /*(1)*/
153 | max-width: calc(100% - 42px); /*(2)*/
154 | word-wrap: break-word;
155 | border-bottom-color: #ddd;
156 | -webkit-border-radius: 3px;
157 | -webkit-box-shadow: 0 1px 3px #eee;
158 | -moz-border-radius: 3px;
159 | -moz-box-shadow: 0 1px 3px #eee;
160 | border-radius: 3px;
161 | }
162 |
163 | #mocha .test h2 {
164 | position: relative;
165 | }
166 |
167 | #mocha .test a.replay {
168 | position: absolute;
169 | top: 3px;
170 | right: 0;
171 | text-decoration: none;
172 | vertical-align: middle;
173 | display: block;
174 | width: 15px;
175 | height: 15px;
176 | line-height: 15px;
177 | text-align: center;
178 | background: #eee;
179 | font-size: 15px;
180 | -moz-border-radius: 15px;
181 | border-radius: 15px;
182 | -webkit-transition: opacity 200ms;
183 | -moz-transition: opacity 200ms;
184 | transition: opacity 200ms;
185 | opacity: 0.3;
186 | color: #888;
187 | }
188 |
189 | #mocha .test:hover a.replay {
190 | opacity: 1;
191 | }
192 |
193 | #mocha-report.pass .test.fail {
194 | display: none;
195 | }
196 |
197 | #mocha-report.fail .test.pass {
198 | display: none;
199 | }
200 |
201 | #mocha-report.pending .test.pass,
202 | #mocha-report.pending .test.fail {
203 | display: none;
204 | }
205 | #mocha-report.pending .test.pass.pending {
206 | display: block;
207 | }
208 |
209 | #mocha-error {
210 | color: #c00;
211 | font-size: 1.5em;
212 | font-weight: 100;
213 | letter-spacing: 1px;
214 | }
215 |
216 | #mocha-stats {
217 | position: fixed;
218 | top: 15px;
219 | right: 10px;
220 | font-size: 12px;
221 | margin: 0;
222 | color: #888;
223 | z-index: 1;
224 | }
225 |
226 | #mocha-stats .progress {
227 | float: right;
228 | padding-top: 0;
229 | }
230 |
231 | #mocha-stats em {
232 | color: black;
233 | }
234 |
235 | #mocha-stats a {
236 | text-decoration: none;
237 | color: inherit;
238 | }
239 |
240 | #mocha-stats a:hover {
241 | border-bottom: 1px solid #eee;
242 | }
243 |
244 | #mocha-stats li {
245 | display: inline-block;
246 | margin: 0 5px;
247 | list-style: none;
248 | padding-top: 11px;
249 | }
250 |
251 | #mocha-stats canvas {
252 | width: 40px;
253 | height: 40px;
254 | }
255 |
256 | #mocha code .comment { color: #ddd; }
257 | #mocha code .init { color: #2f6fad; }
258 | #mocha code .string { color: #5890ad; }
259 | #mocha code .keyword { color: #8a6343; }
260 | #mocha code .number { color: #2f6fad; }
261 |
262 | @media screen and (max-device-width: 480px) {
263 | #mocha {
264 | margin: 60px 0px;
265 | }
266 |
267 | #mocha #stats {
268 | position: absolute;
269 | }
270 | }
271 |
--------------------------------------------------------------------------------