matcha 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.gitignore +19 -0
  2. data/Gemfile +7 -0
  3. data/LICENSE +90 -0
  4. data/README.md +194 -0
  5. data/Rakefile +8 -0
  6. data/app/controllers/matcha/specs_controller.rb +22 -0
  7. data/app/models/matcha/spec.rb +25 -0
  8. data/app/views/layouts/matcha/specs.html.erb +31 -0
  9. data/app/views/matcha/specs/index.html.erb +1 -0
  10. data/app/views/matcha/specs/show.html.erb +1 -0
  11. data/config/routes.rb +4 -0
  12. data/lib/matcha.rb +41 -0
  13. data/lib/matcha/engine.rb +31 -0
  14. data/lib/matcha/runner.rb +151 -0
  15. data/lib/matcha/server.rb +7 -0
  16. data/lib/tasks/matcha.rake +11 -0
  17. data/matcha.gemspec +30 -0
  18. data/spec/controllers/specs_controller_spec.rb +46 -0
  19. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  20. data/spec/dummy/app/assets/javascripts/array_sum.js.coffee +4 -0
  21. data/spec/dummy/config.ru +4 -0
  22. data/spec/dummy/config/application.rb +17 -0
  23. data/spec/dummy/config/boot.rb +6 -0
  24. data/spec/dummy/config/environment.rb +5 -0
  25. data/spec/dummy/config/environments/test.rb +29 -0
  26. data/spec/dummy/config/initializers/matcha.rb +3 -0
  27. data/spec/dummy/spec/javascripts/array_sum_cs_spec.js.coffee +8 -0
  28. data/spec/dummy/spec/javascripts/array_sum_js_spec.js +11 -0
  29. data/spec/dummy/spec/javascripts/assert_spec.js.coffee +9 -0
  30. data/spec/dummy/spec/javascripts/failing_spec.js +5 -0
  31. data/spec/dummy/spec/javascripts/spec_helper.js +3 -0
  32. data/spec/dummy/spec/javascripts/spec_helper_spec.js +7 -0
  33. data/spec/dummy/spec/javascripts/subdirectory/subdirectory_spec.js +5 -0
  34. data/spec/dummy/spec/javascripts/templates/hello.jst.ejs +1 -0
  35. data/spec/dummy/spec/javascripts/templating_spec.js +8 -0
  36. data/spec/dummy/spec/javascripts/transactions_spec.js.coffee +7 -0
  37. data/spec/matcha_spec.rb +40 -0
  38. data/spec/models/spec_spec.rb +45 -0
  39. data/spec/runner_spec.rb +36 -0
  40. data/spec/server_spec.rb +41 -0
  41. data/spec/spec_helper.rb +18 -0
  42. data/spec/views/specs/index.html.erb_spec.rb +12 -0
  43. data/spec/views/specs/show.html.erb_spec.rb +10 -0
  44. data/spec/views/specs/specs.html.erb_spec.rb +15 -0
  45. data/vendor/assets/javascripts/chai.js +2007 -0
  46. data/vendor/assets/javascripts/matcha/runner.js +70 -0
  47. data/vendor/assets/javascripts/matcha/server.js +0 -0
  48. data/vendor/assets/javascripts/mocha.js +3290 -0
  49. data/vendor/assets/stylesheets/mocha.css +133 -0
  50. metadata +202 -0
@@ -0,0 +1,7 @@
1
+ describe "transactions", ->
2
+ it "should add stuff in one test...", ->
3
+ $('#test').append('<h1 id="added">New Stuff</h1>')
4
+ $('#test h1#added').length.should.equal(1)
5
+
6
+ it "... should have been removed before the next starts", ->
7
+ $('#test h1#added').length.should.equal(0)
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe Matcha do
4
+ describe ".config" do
5
+ subject { Matcha.config }
6
+
7
+ describe ".interface" do
8
+ it "defaults to :bdd interface" do
9
+ subject.interface.should == :bdd
10
+ end
11
+ end
12
+
13
+ describe ".spec_dir" do
14
+ it "defaults to 'spec/javascripts'" do
15
+ subject.spec_dir.should == "spec/javascripts"
16
+ end
17
+ end
18
+ end
19
+
20
+ describe ".spec_paths" do
21
+ subject { Matcha.spec_paths }
22
+
23
+ it "returns an array of paths relative to spec_dir" do
24
+ subject.should include("array_sum_js_spec.js")
25
+ subject.should include("array_sum_cs_spec.js.coffee")
26
+ end
27
+
28
+ it "includes subdirectories" do
29
+ subject.should include("subdirectory/subdirectory_spec.js")
30
+ end
31
+
32
+ it "does not include spec_helper" do
33
+ subject.should_not include("spec_helper.js")
34
+ end
35
+ end
36
+
37
+ it "can be configured in an initializer" do
38
+ Matcha.config.configured.should == true
39
+ end
40
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Matcha::Spec do
4
+ describe "#basename" do
5
+ it "is the basename of the path" do
6
+ described_class.new("array_spec.js").basename.should == "array_spec"
7
+ end
8
+
9
+ it "ignores multiple extensions" do
10
+ described_class.new("array_spec.js.coffee").basename.should == "array_spec"
11
+ end
12
+
13
+ it "includes relative path" do
14
+ described_class.new("subdirectory/array_spec.js").basename.should == "subdirectory/array_spec"
15
+ end
16
+ end
17
+
18
+ describe "#url" do
19
+ it "returns a URL path" do
20
+ described_class.new("array_spec.js").url.should == "/array_spec"
21
+ end
22
+ end
23
+
24
+ describe ".all" do
25
+ it "returns an array of specs" do
26
+ Matcha.should_receive(:spec_paths) { ["a_spec.js", "b_spec.js"] }
27
+ all = described_class.all
28
+ all.length.should == 2
29
+ end
30
+ end
31
+
32
+ describe ".find" do
33
+ it "returns the Spec with the given basename" do
34
+ all = [described_class.new("a_spec.js"),
35
+ described_class.new("b_spec.js")]
36
+ described_class.should_receive(:all) { all }
37
+ described_class.find("b_spec").should == all[1]
38
+ end
39
+
40
+ it "returns nil if no such spec exists" do
41
+ described_class.should_receive(:all) { [] }
42
+ described_class.find("b_spec").should be_nil
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Matcha::Runner do
4
+ before do
5
+ Matcha.mode = :runner
6
+ Matcha.config.driver = :selenium_with_firebug
7
+ end
8
+
9
+ let(:runner) { Matcha::Runner.new(:output => buffer) }
10
+ let(:buffer) { StringIO.new }
11
+
12
+ describe "#run" do
13
+ before { runner.run }
14
+
15
+ it "prints results to the output" do
16
+ buffer.rewind
17
+ results = buffer.read
18
+ results.should include(".......F.....")
19
+ results.should include("expected 4 to equal 5")
20
+ results.should include("13 examples, 1 failure")
21
+ end
22
+ end
23
+
24
+ describe "#run_spec" do
25
+ let(:spec) { Matcha::Spec.find("failing_spec") }
26
+ before { runner.spec_runner(spec).run }
27
+
28
+ it "prints results to the output" do
29
+ buffer.rewind
30
+ results = buffer.read
31
+ results.should include('F')
32
+ results.should include("expected 4 to equal 5")
33
+ results.should include("1 examples, 1 failures")
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Matcha::Server, :type => :request do
4
+ def app
5
+ Matcha.application
6
+ end
7
+
8
+ before do
9
+ Matcha.mode = :server
10
+ end
11
+
12
+ it "serves a root page" do
13
+ visit "/"
14
+ page.should have_content("Array#sum (js)")
15
+ page.should have_css(".test.pass")
16
+ end
17
+
18
+ it "serves an individual JavaScript spec" do
19
+ visit "/array_sum_js_spec"
20
+ page.should have_content("Array#sum (js)")
21
+ page.should have_css(".test.pass", :count => 2)
22
+ end
23
+
24
+ it "serves an individual CoffeeScript spec" do
25
+ visit "/array_sum_cs_spec"
26
+ page.should have_content("Array#sum (cs)")
27
+ page.should have_css(".test.pass", :count => 2)
28
+ end
29
+
30
+ it "serves a spec in a subdirectory" do
31
+ visit "/subdirectory/subdirectory_spec"
32
+ page.should have_content("spec in subdirectory")
33
+ page.should have_css(".test.pass")
34
+ end
35
+
36
+ it "supports spec helpers" do
37
+ visit "/spec_helper_spec"
38
+ page.should have_content("two_plus_two")
39
+ page.should have_css(".test.pass")
40
+ end
41
+ end
@@ -0,0 +1,18 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+
3
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
4
+ require "rspec/rails"
5
+ require "rspec/autorun"
6
+
7
+ # Requires supporting ruby files with custom matchers and macros, etc,
8
+ # in spec/support/ and its subdirectories.
9
+ Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
10
+
11
+ require "capybara/rails"
12
+ require "capybara/firebug"
13
+
14
+ Capybara.configure do |config|
15
+ config.default_selector = :css
16
+ config.default_driver = :selenium_with_firebug
17
+ config.app = Matcha.application
18
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe "matcha/specs/index" do
4
+ it "renders a script tag for each basename in @specs" do
5
+ a_spec = stub(:basename => "a_spec")
6
+ b_spec = stub(:basename => "b_spec")
7
+ assign(:specs, [a_spec, b_spec])
8
+ render
9
+ rendered.should have_selector("script[src='/assets/a_spec.js']")
10
+ rendered.should have_selector("script[src='/assets/b_spec.js']")
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe "matcha/specs/show" do
4
+ it "renders a script tag for @spec basename" do
5
+ spec = stub(:basename => "spec")
6
+ assign(:spec, spec)
7
+ render
8
+ rendered.should have_selector("script[src='/assets/spec.js']")
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe "layouts/matcha/specs" do
4
+ it "sets up the specified interface" do
5
+ assign(:interface, :tdd)
6
+ render
7
+ rendered.should include('mocha.setup("tdd")')
8
+ end
9
+
10
+ it "includes matcha JS for given mode" do
11
+ assign(:mode, :runner)
12
+ render
13
+ rendered.should have_css("script[src='/assets/matcha/runner.js']")
14
+ end
15
+ end
@@ -0,0 +1,2007 @@
1
+ !function (name, definition) {
2
+ if (typeof define == 'function' && typeof define.amd == 'object') define(definition);
3
+ else this[name] = definition();
4
+ }('chai', function () {
5
+
6
+ // CommonJS require()
7
+
8
+ function require(p){
9
+ var path = require.resolve(p)
10
+ , mod = require.modules[path];
11
+ if (!mod) throw new Error('failed to require "' + p + '"');
12
+ if (!mod.exports) {
13
+ mod.exports = {};
14
+ mod.call(mod.exports, mod, mod.exports, require.relative(path));
15
+ }
16
+ return mod.exports;
17
+ }
18
+
19
+ require.modules = {};
20
+
21
+ require.resolve = function (path){
22
+ var orig = path
23
+ , reg = path + '.js'
24
+ , index = path + '/index.js';
25
+ return require.modules[reg] && reg
26
+ || require.modules[index] && index
27
+ || orig;
28
+ };
29
+
30
+ require.register = function (path, fn){
31
+ require.modules[path] = fn;
32
+ };
33
+
34
+ require.relative = function (parent) {
35
+ return function(p){
36
+ if ('.' != p[0]) return require(p);
37
+
38
+ var path = parent.split('/')
39
+ , segs = p.split('/');
40
+ path.pop();
41
+
42
+ for (var i = 0; i < segs.length; i++) {
43
+ var seg = segs[i];
44
+ if ('..' == seg) path.pop();
45
+ else if ('.' != seg) path.push(seg);
46
+ }
47
+
48
+ return require(path.join('/'));
49
+ };
50
+ };
51
+
52
+
53
+ require.register("assertion.js", function(module, exports, require){
54
+ /*!
55
+ * chai
56
+ * Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>
57
+ * MIT Licensed
58
+ *
59
+ * Primarily a refactor of: should.js
60
+ * https://github.com/visionmedia/should.js
61
+ * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
62
+ * MIT Licensed
63
+ */
64
+
65
+ /**
66
+ * ### BDD Style Introduction
67
+ *
68
+ * The BDD style is exposed through `expect` or `should` interfaces. In both
69
+ * scenarios, you chain together natural language assertions.
70
+ *
71
+ * // expect
72
+ * var expect = require('chai').expect;
73
+ * expect(foo).to.equal('bar');
74
+ *
75
+ * // should
76
+ * var should = require('chai').should();
77
+ * foo.should.equal('bar');
78
+ *
79
+ * #### Differences
80
+ *
81
+ * The `expect` interface provides a function as a starting point for chaining
82
+ * your language assertions. It works on both node.js and in the browser.
83
+ *
84
+ * The `should` interface extends `Object.prototype` to provide a single getter as
85
+ * the starting point for your language assertions. Most browser don't like
86
+ * extensions to `Object.prototype` so it is not recommended for browser use.
87
+ */
88
+
89
+ /*!
90
+ * Module dependencies.
91
+ */
92
+
93
+ var AssertionError = require('./error')
94
+ , eql = require('./utils/eql')
95
+ , inspect = require('./utils/inspect');
96
+
97
+ /*!
98
+ * Module export.
99
+ */
100
+
101
+ module.exports = Assertion;
102
+
103
+ /*!
104
+ * # Assertion Constructor
105
+ *
106
+ * Creates object for chaining.
107
+ *
108
+ * @api private
109
+ */
110
+
111
+ function Assertion (obj, msg, stack) {
112
+ this.ssfi = stack || arguments.callee;
113
+ this.obj = obj;
114
+ this.msg = msg;
115
+ }
116
+
117
+ /*!
118
+ * # .assert(expression, message, negateMessage)
119
+ *
120
+ * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass.
121
+ *
122
+ * @name assert
123
+ * @param {Philosophical} expression to be tested
124
+ * @param {String} message to display if fails
125
+ * @param {String} negatedMessage to display if negated expression fails
126
+ * @api privage
127
+ */
128
+
129
+ Assertion.prototype.assert = function (expr, msg, negateMsg) {
130
+ var msg = (this.negate ? negateMsg : msg)
131
+ , ok = this.negate ? !expr : expr;
132
+
133
+ if (!ok) {
134
+ throw new AssertionError({
135
+ operator: this.msg,
136
+ message: msg,
137
+ stackStartFunction: this.ssfi
138
+ });
139
+ }
140
+ };
141
+
142
+ /*!
143
+ * # inspect
144
+ *
145
+ * Returns the current object stringified.
146
+ *
147
+ * @name inspect
148
+ * @api private
149
+ */
150
+
151
+ Object.defineProperty(Assertion.prototype, 'inspect',
152
+ { get: function () {
153
+ return inspect(this.obj);
154
+ },
155
+ configurable: true
156
+ });
157
+
158
+ /**
159
+ * # to
160
+ *
161
+ * Language chain.
162
+ *
163
+ * @name to
164
+ * @api public
165
+ */
166
+
167
+ Object.defineProperty(Assertion.prototype, 'to',
168
+ { get: function () {
169
+ return this;
170
+ },
171
+ configurable: true
172
+ });
173
+
174
+ /**
175
+ * # be
176
+ *
177
+ * Language chain.
178
+ *
179
+ * @name be
180
+ * @api public
181
+ */
182
+
183
+ Object.defineProperty(Assertion.prototype, 'be',
184
+ { get: function () {
185
+ return this;
186
+ },
187
+ configurable: true
188
+ });
189
+
190
+ /**
191
+ * # been
192
+ *
193
+ * Language chain. Also tests `tense` to past for addon
194
+ * modules that use the tense feature.
195
+ *
196
+ * @name been
197
+ * @api public
198
+ */
199
+
200
+ Object.defineProperty(Assertion.prototype, 'been',
201
+ { get: function () {
202
+ this.tense = 'past';
203
+ return this;
204
+ },
205
+ configurable: true
206
+ });
207
+
208
+ /**
209
+ * # an
210
+ *
211
+ * Language chain.
212
+ *
213
+ * @name an
214
+ * @api public
215
+ */
216
+
217
+ Object.defineProperty(Assertion.prototype, 'an',
218
+ { get: function () {
219
+ return this;
220
+ },
221
+ configurable: true
222
+ });
223
+ /**
224
+ * # is
225
+ *
226
+ * Language chain.
227
+ *
228
+ * @name is
229
+ * @api public
230
+ */
231
+
232
+ Object.defineProperty(Assertion.prototype, 'is',
233
+ { get: function () {
234
+ return this;
235
+ },
236
+ configurable: true
237
+ });
238
+
239
+ /**
240
+ * # and
241
+ *
242
+ * Language chain.
243
+ *
244
+ * @name and
245
+ * @api public
246
+ */
247
+
248
+ Object.defineProperty(Assertion.prototype, 'and',
249
+ { get: function () {
250
+ return this;
251
+ },
252
+ configurable: true
253
+ });
254
+
255
+ /**
256
+ * # have
257
+ *
258
+ * Language chain.
259
+ *
260
+ * @name have
261
+ * @api public
262
+ */
263
+
264
+ Object.defineProperty(Assertion.prototype, 'have',
265
+ { get: function () {
266
+ return this;
267
+ },
268
+ configurable: true
269
+ });
270
+
271
+ /**
272
+ * # with
273
+ *
274
+ * Language chain.
275
+ *
276
+ * @name with
277
+ * @api public
278
+ */
279
+
280
+ Object.defineProperty(Assertion.prototype, 'with',
281
+ { get: function () {
282
+ return this;
283
+ },
284
+ configurable: true
285
+ });
286
+
287
+ /**
288
+ * # .not
289
+ *
290
+ * Negates any of assertions following in the chain.
291
+ *
292
+ * @name not
293
+ * @api public
294
+ */
295
+
296
+ Object.defineProperty(Assertion.prototype, 'not',
297
+ { get: function () {
298
+ this.negate = true;
299
+ return this;
300
+ },
301
+ configurable: true
302
+ });
303
+
304
+ /**
305
+ * # .ok
306
+ *
307
+ * Assert object truthiness.
308
+ *
309
+ * expect('everthing').to.be.ok;
310
+ * expect(false).to.not.be.ok;
311
+ * expect(undefined).to.not.be.ok;
312
+ * expect(null).to.not.be.ok;
313
+ *
314
+ * @name ok
315
+ * @api public
316
+ */
317
+
318
+ Object.defineProperty(Assertion.prototype, 'ok',
319
+ { get: function () {
320
+ this.assert(
321
+ this.obj
322
+ , 'expected ' + this.inspect + ' to be truthy'
323
+ , 'expected ' + this.inspect + ' to be falsey');
324
+
325
+ return this;
326
+ },
327
+ configurable: true
328
+ });
329
+
330
+ /**
331
+ * # .true
332
+ *
333
+ * Assert object is true
334
+ *
335
+ * @name true
336
+ * @api public
337
+ */
338
+
339
+ Object.defineProperty(Assertion.prototype, 'true',
340
+ { get: function () {
341
+ this.assert(
342
+ true === this.obj
343
+ , 'expected ' + this.inspect + ' to be true'
344
+ , 'expected ' + this.inspect + ' to be false');
345
+
346
+ return this;
347
+ },
348
+ configurable: true
349
+ });
350
+
351
+ /**
352
+ * # .false
353
+ *
354
+ * Assert object is false
355
+ *
356
+ * @name false
357
+ * @api public
358
+ */
359
+
360
+ Object.defineProperty(Assertion.prototype, 'false',
361
+ { get: function () {
362
+ this.assert(
363
+ false === this.obj
364
+ , 'expected ' + this.inspect + ' to be false'
365
+ , 'expected ' + this.inspect + ' to be true');
366
+
367
+ return this;
368
+ },
369
+ configurable: true
370
+ });
371
+
372
+ /**
373
+ * # .exist
374
+ *
375
+ * Assert object exists (null).
376
+ *
377
+ * var foo = 'hi'
378
+ * , bar;
379
+ * expect(foo).to.exist;
380
+ * expect(bar).to.not.exist;
381
+ *
382
+ * @name exist
383
+ * @api public
384
+ */
385
+
386
+ Object.defineProperty(Assertion.prototype, 'exist',
387
+ { get: function () {
388
+ this.assert(
389
+ null != this.obj
390
+ , 'expected ' + this.inspect + ' to exist'
391
+ , 'expected ' + this.inspect + ' to not exist');
392
+
393
+ return this;
394
+ },
395
+ configurable: true
396
+ });
397
+
398
+ /**
399
+ * # .empty
400
+ *
401
+ * Assert object's length to be 0.
402
+ *
403
+ * expect([]).to.be.empty;
404
+ *
405
+ * @name empty
406
+ * @api public
407
+ */
408
+
409
+ Object.defineProperty(Assertion.prototype, 'empty',
410
+ { get: function () {
411
+ new Assertion(this.obj).to.have.property('length');
412
+
413
+ this.assert(
414
+ 0 === this.obj.length
415
+ , 'expected ' + this.inspect + ' to be empty'
416
+ , 'expected ' + this.inspect + ' not to be empty');
417
+
418
+ return this;
419
+ },
420
+ configurable: true
421
+ });
422
+
423
+ /**
424
+ * # .arguments
425
+ *
426
+ * Assert object is an instanceof arguments.
427
+ *
428
+ * function test () {
429
+ * expect(arguments).to.be.arguments;
430
+ * }
431
+ *
432
+ * @name arguments
433
+ * @api public
434
+ */
435
+
436
+ Object.defineProperty(Assertion.prototype, 'arguments',
437
+ { get: function () {
438
+ this.assert(
439
+ '[object Arguments]' == Object.prototype.toString.call(this.obj)
440
+ , 'expected ' + this.inspect + ' to be arguments'
441
+ , 'expected ' + this.inspect + ' to not be arguments');
442
+
443
+ return this;
444
+ },
445
+ configurable: true
446
+ });
447
+
448
+ /**
449
+ * # .equal(value)
450
+ *
451
+ * Assert strict equality.
452
+ *
453
+ * expect('hello').to.equal('hello');
454
+ *
455
+ * @name equal
456
+ * @param {*} value
457
+ * @api public
458
+ */
459
+
460
+ Assertion.prototype.equal = function (val) {
461
+ this.assert(
462
+ val === this.obj
463
+ , 'expected ' + this.inspect + ' to equal ' + inspect(val)
464
+ , 'expected ' + this.inspect + ' to not equal ' + inspect(val));
465
+
466
+ return this;
467
+ };
468
+
469
+ /**
470
+ * # .eql(value)
471
+ *
472
+ * Assert deep equality.
473
+ *
474
+ * expect({ foo: 'bar' }).to.eql({ foo: 'bar' });
475
+ *
476
+ * @name eql
477
+ * @param {*} value
478
+ * @api public
479
+ */
480
+
481
+ Assertion.prototype.eql = function (obj) {
482
+ this.assert(
483
+ eql(obj, this.obj)
484
+ , 'expected ' + this.inspect + ' to equal ' + inspect(obj)
485
+ , 'expected ' + this.inspect + ' to not equal ' + inspect(obj));
486
+ return this;
487
+ };
488
+
489
+ /**
490
+ * # .above(value)
491
+ *
492
+ * Assert greater than `value`.
493
+ *
494
+ * expect(10).to.be.above(5);
495
+ *
496
+ * @name above
497
+ * @param {Number} value
498
+ * @api public
499
+ */
500
+
501
+ Assertion.prototype.above = function (val) {
502
+ this.assert(
503
+ this.obj > val
504
+ , 'expected ' + this.inspect + ' to be above ' + val
505
+ , 'expected ' + this.inspect + ' to be below ' + val);
506
+
507
+ return this;
508
+ };
509
+
510
+ /**
511
+ * # .below(value)
512
+ *
513
+ * Assert less than `value`.
514
+ *
515
+ * expect(5).to.be.below(10);
516
+ *
517
+ * @name below
518
+ * @param {Number} value
519
+ * @api public
520
+ */
521
+
522
+ Assertion.prototype.below = function (val) {
523
+ this.assert(
524
+ this.obj < val
525
+ , 'expected ' + this.inspect + ' to be below ' + val
526
+ , 'expected ' + this.inspect + ' to be above ' + val);
527
+
528
+ return this;
529
+ };
530
+
531
+ /**
532
+ * # .within(start, finish)
533
+ *
534
+ * Assert that a number is within a range.
535
+ *
536
+ * expect(7).to.be.within(5,10);
537
+ *
538
+ * @name within
539
+ * @param {Number} start lowerbound inclusive
540
+ * @param {Number} finish upperbound inclusive
541
+ * @api public
542
+ */
543
+
544
+ Assertion.prototype.within = function (start, finish) {
545
+ var range = start + '..' + finish;
546
+
547
+ this.assert(
548
+ this.obj >= start && this.obj <= finish
549
+ , 'expected ' + this.inspect + ' to be within ' + range
550
+ , 'expected ' + this.inspect + ' to not be within ' + range);
551
+
552
+ return this;
553
+ };
554
+
555
+ /**
556
+ * # .a(type)
557
+ *
558
+ * Assert typeof.
559
+ *
560
+ * expect('test').to.be.a('string');
561
+ *
562
+ * @name a
563
+ * @param {String} type
564
+ * @api public
565
+ */
566
+
567
+ Assertion.prototype.a = function (type) {
568
+ this.assert(
569
+ type == typeof this.obj
570
+ , 'expected ' + this.inspect + ' to be a ' + type
571
+ , 'expected ' + this.inspect + ' not to be a ' + type);
572
+
573
+ return this;
574
+ };
575
+
576
+ /**
577
+ * # .instanceof(constructor)
578
+ *
579
+ * Assert instanceof.
580
+ *
581
+ * var Tea = function (name) { this.name = name; }
582
+ * , Chai = new Tea('chai');
583
+ *
584
+ * expect(Chai).to.be.an.instanceOf(Tea);
585
+ *
586
+ * @name instanceof
587
+ * @param {Constructor}
588
+ * @alias instanceOf
589
+ * @api public
590
+ */
591
+
592
+ Assertion.prototype.instanceof = function (constructor) {
593
+ var name = constructor.name;
594
+ this.assert(
595
+ this.obj instanceof constructor
596
+ , 'expected ' + this.inspect + ' to be an instance of ' + name
597
+ , 'expected ' + this.inspect + ' to not be an instance of ' + name);
598
+
599
+ return this;
600
+ };
601
+
602
+ /**
603
+ * # .property(name, [value])
604
+ *
605
+ * Assert that property of `name` exists, optionally with `value`.
606
+ *
607
+ * var obj = { foo: 'bar' }
608
+ * expect(obj).to.have.property('foo');
609
+ * expect(obj).to.have.property('foo', 'bar');
610
+ * expect(obj).to.have.property('foo').to.be.a('string');
611
+ *
612
+ * @name property
613
+ * @param {String} name
614
+ * @param {*} value (optional)
615
+ * @returns value of property for chaining
616
+ * @api public
617
+ */
618
+
619
+ Assertion.prototype.property = function (name, val) {
620
+ if (this.negate && undefined !== val) {
621
+ if (undefined === this.obj[name]) {
622
+ throw new Error(this.inspect + ' has no property ' + inspect(name));
623
+ }
624
+ } else {
625
+ this.assert(
626
+ undefined !== this.obj[name]
627
+ , 'expected ' + this.inspect + ' to have a property ' + inspect(name)
628
+ , 'expected ' + this.inspect + ' to not have property ' + inspect(name));
629
+ }
630
+
631
+ if (undefined !== val) {
632
+ this.assert(
633
+ val === this.obj[name]
634
+ , 'expected ' + this.inspect + ' to have a property ' + inspect(name) + ' of ' +
635
+ inspect(val) + ', but got ' + inspect(this.obj[name])
636
+ , 'expected ' + this.inspect + ' to not have a property ' + inspect(name) + ' of ' + inspect(val));
637
+ }
638
+
639
+ this.obj = this.obj[name];
640
+ return this;
641
+ };
642
+
643
+ /**
644
+ * # .ownProperty(name)
645
+ *
646
+ * Assert that has own property by `name`.
647
+ *
648
+ * expect('test').to.have.ownProperty('length');
649
+ *
650
+ * @name ownProperty
651
+ * @alias haveOwnProperty
652
+ * @param {String} name
653
+ * @api public
654
+ */
655
+
656
+ Assertion.prototype.ownProperty = function (name) {
657
+ this.assert(
658
+ this.obj.hasOwnProperty(name)
659
+ , 'expected ' + this.inspect + ' to have own property ' + inspect(name)
660
+ , 'expected ' + this.inspect + ' to not have own property ' + inspect(name));
661
+ return this;
662
+ };
663
+
664
+ /**
665
+ * # .length(val)
666
+ *
667
+ * Assert that object has expected length.
668
+ *
669
+ * expect([1,2,3]).to.have.length(3);
670
+ * expect('foobar').to.have.length(6);
671
+ *
672
+ * @name length
673
+ * @alias lengthOf
674
+ * @param {Number} length
675
+ * @api public
676
+ */
677
+
678
+ Assertion.prototype.length = function (n) {
679
+ new Assertion(this.obj).to.have.property('length');
680
+ var len = this.obj.length;
681
+
682
+ this.assert(
683
+ len == n
684
+ , 'expected ' + this.inspect + ' to have a length of ' + n + ' but got ' + len
685
+ , 'expected ' + this.inspect + ' to not have a length of ' + len);
686
+
687
+ return this;
688
+ };
689
+
690
+ /**
691
+ * # .match(regexp)
692
+ *
693
+ * Assert that matches regular expression.
694
+ *
695
+ * expect('foobar').to.match(/^foo/);
696
+ *
697
+ * @name match
698
+ * @param {RegExp} RegularExpression
699
+ * @api public
700
+ */
701
+
702
+ Assertion.prototype.match = function (re) {
703
+ this.assert(
704
+ re.exec(this.obj)
705
+ , 'expected ' + this.inspect + ' to match ' + re
706
+ , 'expected ' + this.inspect + ' not to match ' + re);
707
+
708
+ return this;
709
+ };
710
+
711
+ /**
712
+ * # .include(obj)
713
+ *
714
+ * Assert the inclusion of an object in an Array or substring in string.
715
+ *
716
+ * expect([1,2,3]).to.contain(2);
717
+ *
718
+ * @name include
719
+ * @param {Object|String|Number} obj
720
+ * @api public
721
+ */
722
+
723
+ Assertion.prototype.include = function (obj) {
724
+ this.assert(
725
+ ~this.obj.indexOf(obj)
726
+ , 'expected ' + this.inspect + ' to include ' + inspect(obj)
727
+ , 'expected ' + this.inspect + ' to not include ' + inspect(obj));
728
+
729
+ return this;
730
+ };
731
+
732
+ /**
733
+ * # .string(string)
734
+ *
735
+ * Assert inclusion of string in string.
736
+ *
737
+ * expect('foobar').to.include.string('bar');
738
+ *
739
+ * @name string
740
+ * @param {String} string
741
+ * @api public
742
+ */
743
+
744
+ Assertion.prototype.string = function (str) {
745
+ new Assertion(this.obj).is.a('string');
746
+
747
+ this.assert(
748
+ ~this.obj.indexOf(str)
749
+ , 'expected ' + this.inspect + ' to contain ' + inspect(str)
750
+ , 'expected ' + this.inspect + ' to not contain ' + inspect(str));
751
+
752
+ return this;
753
+ };
754
+
755
+
756
+
757
+ /**
758
+ * # contain
759
+ *
760
+ * Toggles the `contain` flag for the `keys` assertion.
761
+ *
762
+ * @name contain
763
+ * @api public
764
+ */
765
+
766
+ Object.defineProperty(Assertion.prototype, 'contain',
767
+ { get: function () {
768
+ this.contains = true;
769
+ return this;
770
+ },
771
+ configurable: true
772
+ });
773
+
774
+ /**
775
+ * # .keys(key1, [key2], [...])
776
+ *
777
+ * Assert exact keys or the inclusing of keys using the `contain` modifier.
778
+ *
779
+ * expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']);
780
+ * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar');
781
+ *
782
+ * @name keys
783
+ * @alias key
784
+ * @param {String|Array} Keys
785
+ * @api public
786
+ */
787
+
788
+ Assertion.prototype.keys = function(keys) {
789
+ var str
790
+ , ok = true;
791
+
792
+ keys = keys instanceof Array
793
+ ? keys
794
+ : Array.prototype.slice.call(arguments);
795
+
796
+ if (!keys.length) throw new Error('keys required');
797
+
798
+ var actual = Object.keys(this.obj)
799
+ , len = keys.length;
800
+
801
+ // Inclusion
802
+ ok = keys.every(function(key){
803
+ return ~actual.indexOf(key);
804
+ });
805
+
806
+ // Strict
807
+ if (!this.negate && !this.contains) {
808
+ ok = ok && keys.length == actual.length;
809
+ }
810
+
811
+ // Key string
812
+ if (len > 1) {
813
+ keys = keys.map(function(key){
814
+ return inspect(key);
815
+ });
816
+ var last = keys.pop();
817
+ str = keys.join(', ') + ', and ' + last;
818
+ } else {
819
+ str = inspect(keys[0]);
820
+ }
821
+
822
+ // Form
823
+ str = (len > 1 ? 'keys ' : 'key ') + str;
824
+
825
+ // Have / include
826
+ str = (this.contains ? 'contain ' : 'have ') + str;
827
+
828
+ // Assertion
829
+ this.assert(
830
+ ok
831
+ , 'expected ' + this.inspect + ' to ' + str
832
+ , 'expected ' + this.inspect + ' to not ' + str);
833
+
834
+ return this;
835
+ }
836
+
837
+ /**
838
+ * # .throw(constructor)
839
+ *
840
+ * Assert that a function will throw a specific type of error.
841
+ *
842
+ * var fn = function () { throw new ReferenceError(''); }
843
+ * expect(fn).to.throw(ReferenceError);
844
+ *
845
+ * @name throw
846
+ * @alias throws
847
+ * @alias Throw
848
+ * @param {ErrorConstructor} constructor
849
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
850
+ * @api public
851
+ */
852
+
853
+ Assertion.prototype.throw = function (constructor) {
854
+ new Assertion(this.obj).is.a('function');
855
+
856
+ var thrown = false;
857
+
858
+ try {
859
+ this.obj();
860
+ } catch (err) {
861
+ if (constructor && 'function' === typeof constructor && constructor.constructor != RegExp) {
862
+ this.assert(
863
+ err instanceof constructor && err.name == constructor.name
864
+ , 'expected ' + this.inspect + ' to throw ' + constructor.name + ' but a ' + err.name + ' was thrown'
865
+ , 'expected ' + this.inspect + ' to not throw ' + constructor.name );
866
+ return this;
867
+ } else if (constructor && constructor instanceof RegExp) {
868
+ this.assert(
869
+ constructor.exec(err.message)
870
+ , 'expected ' + this.inspect + ' to throw error matching ' + constructor + ' but got ' + inspect(err.message)
871
+ , 'expected ' + this.inspect + ' to throw error not matching ' + constructor);
872
+ return this;
873
+ } else {
874
+ thrown = true;
875
+ }
876
+ }
877
+
878
+ var name = (constructor ? constructor.name : 'an error');
879
+
880
+ this.assert(
881
+ thrown === true
882
+ , 'expected ' + this.inspect + ' to throw ' + name
883
+ , 'expected ' + this.inspect + ' to not throw ' + name);
884
+
885
+ return this;
886
+ };
887
+
888
+ /*!
889
+ * Aliases.
890
+ */
891
+
892
+ (function alias(name, as){
893
+ Assertion.prototype[as] = Assertion.prototype[name];
894
+ return alias;
895
+ })
896
+ ('length', 'lengthOf')
897
+ ('keys', 'key')
898
+ ('ownProperty', 'haveOwnProperty')
899
+ ('above', 'greaterThan')
900
+ ('below', 'lessThan')
901
+ ('throw', 'throws')
902
+ ('throw', 'Throw') // for troublesome browsers
903
+ ('instanceof', 'instanceOf');
904
+
905
+ }); // module: assertion.js
906
+
907
+ require.register("chai.js", function(module, exports, require){
908
+ /*!
909
+ * chai
910
+ * Copyright(c) 2011-2012 Jake Luer <jake@alogicalparadox.com>
911
+ * MIT Licensed
912
+ */
913
+
914
+ var used = [];
915
+ var exports = module.exports = {};
916
+
917
+ exports.version = '0.3.3';
918
+
919
+ exports.Assertion = require('./assertion');
920
+ exports.AssertionError = require('./error');
921
+
922
+ exports.inspect = require('./utils/inspect');
923
+
924
+ exports.use = function (fn) {
925
+ if (!~used.indexOf(fn)) {
926
+ fn(this);
927
+ used.push(fn);
928
+ }
929
+
930
+ return this;
931
+ };
932
+
933
+ exports.fail = function (actual, expected, message, operator, stackStartFunction) {
934
+ throw new exports.AssertionError({
935
+ message: message,
936
+ actual: actual,
937
+ expected: expected,
938
+ operator: operator,
939
+ stackStartFunction: stackStartFunction
940
+ });
941
+ };
942
+
943
+ var expect = require('./interface/expect');
944
+ exports.use(expect);
945
+
946
+ var should = require('./interface/should');
947
+ exports.use(should);
948
+
949
+ var assert = require('./interface/assert');
950
+ exports.use(assert);
951
+
952
+ }); // module: chai.js
953
+
954
+ require.register("error.js", function(module, exports, require){
955
+ /*!
956
+ * chai
957
+ * Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>
958
+ * MIT Licensed
959
+ */
960
+
961
+ var fail = require('./chai').fail;
962
+
963
+ module.exports = AssertionError;
964
+
965
+ /*!
966
+ * Inspired by node.js assert module
967
+ * https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/assert.js
968
+ */
969
+ function AssertionError (options) {
970
+ options = options || {};
971
+ this.name = 'AssertionError';
972
+ this.message = options.message;
973
+ this.actual = options.actual;
974
+ this.expected = options.expected;
975
+ this.operator = options.operator;
976
+ var stackStartFunction = options.stackStartFunction || fail;
977
+
978
+ if (Error.captureStackTrace) {
979
+ Error.captureStackTrace(this, stackStartFunction);
980
+ }
981
+ }
982
+
983
+ AssertionError.prototype.__proto__ = Error.prototype;
984
+
985
+ AssertionError.prototype.summary = function() {
986
+ var str = '';
987
+
988
+ if (this.operator) {
989
+ str += 'In: \'' + this.operator + '\'\n\t';
990
+ }
991
+
992
+ str += '' + this.name + (this.message ? ': ' + this.message : '');
993
+
994
+ return str;
995
+ };
996
+
997
+ AssertionError.prototype.details = function() {
998
+ return this.summary();
999
+ };
1000
+
1001
+ AssertionError.prototype.toString = function() {
1002
+ return this.summary();
1003
+ };
1004
+ }); // module: error.js
1005
+
1006
+ require.register("interface/assert.js", function(module, exports, require){
1007
+ /*!
1008
+ * chai
1009
+ * Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>
1010
+ * MIT Licensed
1011
+ */
1012
+
1013
+ /**
1014
+ * ### TDD Style Introduction
1015
+ *
1016
+ * The TDD style is exposed through `assert` interfaces. This provides
1017
+ * the classic assert.`test` notation, similiar to that packaged with
1018
+ * node.js. This assert module, however, provides several additional
1019
+ * tests and is browser compatible.
1020
+ *
1021
+ * // assert
1022
+ * var assert = require('chai').assert;
1023
+ * , foo = 'bar';
1024
+ *
1025
+ * assert.typeOf(foo, 'string');
1026
+ * assert.equal(foo, 'bar');
1027
+ */
1028
+
1029
+ module.exports = function (chai) {
1030
+ /*!
1031
+ * Chai dependencies.
1032
+ */
1033
+ var Assertion = chai.Assertion
1034
+ , inspect = chai.inspect;
1035
+
1036
+ /*!
1037
+ * Module export.
1038
+ */
1039
+
1040
+ var assert = chai.assert = {};
1041
+
1042
+ /**
1043
+ * # .ok(object, [message])
1044
+ *
1045
+ * Assert object is truthy.
1046
+ *
1047
+ * assert.ok('everthing', 'everything is ok');
1048
+ * assert.ok(false, 'this will fail');
1049
+ *
1050
+ * @name ok
1051
+ * @param {*} object to test
1052
+ * @param {String} message
1053
+ * @api public
1054
+ */
1055
+
1056
+ assert.ok = function (val, msg) {
1057
+ new Assertion(val, msg).is.ok;
1058
+ };
1059
+
1060
+ /**
1061
+ * # .equal(actual, expected, [message])
1062
+ *
1063
+ * Assert strict equality.
1064
+ *
1065
+ * assert.equal(3, 3, 'these numbers are equal');
1066
+ *
1067
+ * @name equal
1068
+ * @param {*} actual
1069
+ * @param {*} expected
1070
+ * @param {String} message
1071
+ * @api public
1072
+ */
1073
+
1074
+ assert.equal = function (act, exp, msg) {
1075
+ var test = new Assertion(act, msg);
1076
+
1077
+ test.assert(
1078
+ exp == test.obj
1079
+ , 'expected ' + test.inspect + ' to equal ' + inspect(exp)
1080
+ , 'expected ' + test.inspect + ' to not equal ' + inspect(exp));
1081
+ };
1082
+
1083
+ /**
1084
+ * # .notEqual(actual, expected, [message])
1085
+ *
1086
+ * Assert not equal.
1087
+ *
1088
+ * assert.notEqual(3, 4, 'these numbers are not equal');
1089
+ *
1090
+ * @name notEqual
1091
+ * @param {*} actual
1092
+ * @param {*} expected
1093
+ * @param {String} message
1094
+ * @api public
1095
+ */
1096
+
1097
+ assert.notEqual = function (act, exp, msg) {
1098
+ var test = new Assertion(act, msg);
1099
+
1100
+ test.assert(
1101
+ exp != test.obj
1102
+ , 'expected ' + test.inspect + ' to equal ' + inspect(exp)
1103
+ , 'expected ' + test.inspect + ' to not equal ' + inspect(exp));
1104
+ };
1105
+
1106
+ /**
1107
+ * # .strictEqual(actual, expected, [message])
1108
+ *
1109
+ * Assert strict equality.
1110
+ *
1111
+ * assert.strictEqual(true, true, 'these booleans are strictly equal');
1112
+ *
1113
+ * @name strictEqual
1114
+ * @param {*} actual
1115
+ * @param {*} expected
1116
+ * @param {String} message
1117
+ * @api public
1118
+ */
1119
+
1120
+ assert.strictEqual = function (act, exp, msg) {
1121
+ new Assertion(act, msg).to.equal(exp);
1122
+ };
1123
+
1124
+ /**
1125
+ * # .notStrictEqual(actual, expected, [message])
1126
+ *
1127
+ * Assert strict equality.
1128
+ *
1129
+ * assert.notStrictEqual(1, true, 'these booleans are not strictly equal');
1130
+ *
1131
+ * @name notStrictEqual
1132
+ * @param {*} actual
1133
+ * @param {*} expected
1134
+ * @param {String} message
1135
+ * @api public
1136
+ */
1137
+
1138
+ assert.notStrictEqual = function (act, exp, msg) {
1139
+ new Assertion(act, msg).to.not.equal(exp);
1140
+ };
1141
+
1142
+ /**
1143
+ * # .deepEqual(actual, expected, [message])
1144
+ *
1145
+ * Assert not deep equality.
1146
+ *
1147
+ * assert.deepEqual({ tea: 'green' }, { tea: 'green' });
1148
+ *
1149
+ * @name deepEqual
1150
+ * @param {*} actual
1151
+ * @param {*} expected
1152
+ * @param {String} message
1153
+ * @api public
1154
+ */
1155
+
1156
+ assert.deepEqual = function (act, exp, msg) {
1157
+ new Assertion(act, msg).to.eql(exp);
1158
+ };
1159
+
1160
+ /**
1161
+ * # .notDeepEqual(actual, expected, [message])
1162
+ *
1163
+ * Assert not deep equality.
1164
+ *
1165
+ * assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' });
1166
+ *
1167
+ * @name notDeepEqual
1168
+ * @param {*} actual
1169
+ * @param {*} expected
1170
+ * @param {String} message
1171
+ * @api public
1172
+ */
1173
+
1174
+ assert.notDeepEqual = function (act, exp, msg) {
1175
+ new Assertion(act, msg).to.not.eql(exp);
1176
+ };
1177
+
1178
+ /**
1179
+ * # .isTrue(value, [message])
1180
+ *
1181
+ * Assert `value` is true.
1182
+ *
1183
+ * var tea_served = true;
1184
+ * assert.isTrue(tea_served, 'the tea has been served');
1185
+ *
1186
+ * @name isTrue
1187
+ * @param {Boolean} value
1188
+ * @param {String} message
1189
+ * @api public
1190
+ */
1191
+
1192
+ assert.isTrue = function (val, msg) {
1193
+ new Assertion(val, msg).is.true;
1194
+ };
1195
+
1196
+ /**
1197
+ * # .isFalse(value, [message])
1198
+ *
1199
+ * Assert `value` is false.
1200
+ *
1201
+ * var tea_served = false;
1202
+ * assert.isFalse(tea_served, 'no tea yet? hmm...');
1203
+ *
1204
+ * @name isFalse
1205
+ * @param {Boolean} value
1206
+ * @param {String} message
1207
+ * @api public
1208
+ */
1209
+
1210
+ assert.isFalse = function (val, msg) {
1211
+ new Assertion(val, msg).is.false;
1212
+ };
1213
+
1214
+ /**
1215
+ * # .isNull(value, [message])
1216
+ *
1217
+ * Assert `value` is null.
1218
+ *
1219
+ * assert.isNull(err, 'no errors');
1220
+ *
1221
+ * @name isNull
1222
+ * @param {*} value
1223
+ * @param {String} message
1224
+ * @api public
1225
+ */
1226
+
1227
+ assert.isNull = function (val, msg) {
1228
+ new Assertion(val, msg).to.not.exist;
1229
+ };
1230
+
1231
+ /**
1232
+ * # .isNotNull(value, [message])
1233
+ *
1234
+ * Assert `value` is not null.
1235
+ *
1236
+ * var tea = 'tasty chai';
1237
+ * assert.isNotNull(tea, 'great, time for tea!');
1238
+ *
1239
+ * @name isNotNull
1240
+ * @param {*} value
1241
+ * @param {String} message
1242
+ * @api public
1243
+ */
1244
+
1245
+ assert.isNotNull = function (val, msg) {
1246
+ new Assertion(val, msg).to.exist;
1247
+ };
1248
+
1249
+ /**
1250
+ * # .isUndefined(value, [message])
1251
+ *
1252
+ * Assert `value` is undefined.
1253
+ *
1254
+ * assert.isUndefined(tea, 'no tea defined');
1255
+ *
1256
+ * @name isUndefined
1257
+ * @param {*} value
1258
+ * @param {String} message
1259
+ * @api public
1260
+ */
1261
+
1262
+ assert.isUndefined = function (val, msg) {
1263
+ new Assertion(val, msg).to.equal(undefined);
1264
+ };
1265
+
1266
+ /**
1267
+ * # .isFunction(value, [message])
1268
+ *
1269
+ * Assert `value` is a function.
1270
+ *
1271
+ * var serve_tea = function () { return 'cup of tea'; };
1272
+ * assert.isFunction(serve_tea, 'great, we can have tea now');
1273
+ *
1274
+ * @name isFunction
1275
+ * @param {Function} value
1276
+ * @param {String} message
1277
+ * @api public
1278
+ */
1279
+
1280
+ assert.isFunction = function (val, msg) {
1281
+ new Assertion(val, msg).to.be.a('function');
1282
+ };
1283
+
1284
+ /**
1285
+ * # .isObject(value, [message])
1286
+ *
1287
+ * Assert `value` is an object.
1288
+ *
1289
+ * var selection = { name: 'Chai', serve: 'with spices' };
1290
+ * assert.isObject(selection, 'tea selection is an object');
1291
+ *
1292
+ * @name isObject
1293
+ * @param {Object} value
1294
+ * @param {String} message
1295
+ * @api public
1296
+ */
1297
+
1298
+ assert.isObject = function (val, msg) {
1299
+ new Assertion(val, msg).to.be.a('object');
1300
+ };
1301
+
1302
+ /**
1303
+ * # .isArray(value, [message])
1304
+ *
1305
+ * Assert `value` is an instance of Array.
1306
+ *
1307
+ * var menu = [ 'green', 'chai', 'oolong' ];
1308
+ * assert.isArray(menu, 'what kind of tea do we want?');
1309
+ *
1310
+ * @name isArray
1311
+ * @param {*} value
1312
+ * @param {String} message
1313
+ * @api public
1314
+ */
1315
+
1316
+ assert.isArray = function (val, msg) {
1317
+ new Assertion(val, msg).to.be.instanceof(Array);
1318
+ };
1319
+
1320
+ /**
1321
+ * # .isString(value, [message])
1322
+ *
1323
+ * Assert `value` is a string.
1324
+ *
1325
+ * var teaorder = 'chai';
1326
+ * assert.isString(tea_order, 'order placed');
1327
+ *
1328
+ * @name isString
1329
+ * @param {String} value
1330
+ * @param {String} message
1331
+ * @api public
1332
+ */
1333
+
1334
+ assert.isString = function (val, msg) {
1335
+ new Assertion(val, msg).to.be.a('string');
1336
+ };
1337
+
1338
+ /**
1339
+ * # .isNumber(value, [message])
1340
+ *
1341
+ * Assert `value` is a number
1342
+ *
1343
+ * var cups = 2;
1344
+ * assert.isNumber(cups, 'how many cups');
1345
+ *
1346
+ * @name isNumber
1347
+ * @param {Number} value
1348
+ * @param {String} message
1349
+ * @api public
1350
+ */
1351
+
1352
+ assert.isNumber = function (val, msg) {
1353
+ new Assertion(val, msg).to.be.instanceof(Number);
1354
+ };
1355
+
1356
+ /**
1357
+ * # .isBoolean(value, [message])
1358
+ *
1359
+ * Assert `value` is a boolean
1360
+ *
1361
+ * var teaready = true
1362
+ * , teaserved = false;
1363
+ *
1364
+ * assert.isBoolean(tea_ready, 'is the tea ready');
1365
+ * assert.isBoolean(tea_served, 'has tea been served');
1366
+ *
1367
+ * @name isBoolean
1368
+ * @param {*} value
1369
+ * @param {String} message
1370
+ * @api public
1371
+ */
1372
+
1373
+ assert.isBoolean = function (val, msg) {
1374
+ new Assertion(val, msg).to.be.a('boolean');
1375
+ };
1376
+
1377
+ /**
1378
+ * # .typeOf(value, name, [message])
1379
+ *
1380
+ * Assert typeof `value` is `name`.
1381
+ *
1382
+ * assert.typeOf('tea', 'string', 'we have a string');
1383
+ *
1384
+ * @name typeOf
1385
+ * @param {*} value
1386
+ * @param {String} typeof name
1387
+ * @param {String} message
1388
+ * @api public
1389
+ */
1390
+
1391
+ assert.typeOf = function (val, type, msg) {
1392
+ new Assertion(val, msg).to.be.a(type);
1393
+ };
1394
+
1395
+ /**
1396
+ * # .instanceOf(object, constructor, [message])
1397
+ *
1398
+ * Assert `value` is instanceof `constructor`.
1399
+ *
1400
+ * var Tea = function (name) { this.name = name; }
1401
+ * , Chai = new Tea('chai');
1402
+ *
1403
+ * assert.instanceOf(Chai, Tea, 'chai is an instance of tea');
1404
+ *
1405
+ * @name instanceOf
1406
+ * @param {Object} object
1407
+ * @param {Constructor} constructor
1408
+ * @param {String} message
1409
+ * @api public
1410
+ */
1411
+
1412
+ assert.instanceOf = function (val, type, msg) {
1413
+ new Assertion(val, msg).to.be.instanceof(type);
1414
+ };
1415
+
1416
+ /**
1417
+ * # .include(value, includes, [message])
1418
+ *
1419
+ * Assert the inclusion of an object in another. Works
1420
+ * for strings and arrays.
1421
+ *
1422
+ * assert.include('foobar', 'bar', 'foobar contains string `var`);
1423
+ * assert.include([ 1, 2, 3], 3, 'array contains value);
1424
+ *
1425
+ * @name include
1426
+ * @param {Array|String} value
1427
+ * @param {*} includes
1428
+ * @param {String} message
1429
+ * @api public
1430
+ */
1431
+
1432
+ assert.include = function (exp, inc, msg) {
1433
+ var obj = new Assertion(exp, msg);
1434
+
1435
+ if (Array.isArray(exp)) {
1436
+ obj.to.include(inc);
1437
+ } else if ('string' === typeof exp) {
1438
+ obj.to.contain.string(inc);
1439
+ }
1440
+ };
1441
+
1442
+ /**
1443
+ * # .match(value, regex, [message])
1444
+ *
1445
+ * Assert that `value` matches regular expression.
1446
+ *
1447
+ * assert.match('foobar', /^foo/, 'Regexp matches');
1448
+ *
1449
+ * @name match
1450
+ * @param {*} value
1451
+ * @param {RegExp} RegularExpression
1452
+ * @param {String} message
1453
+ * @api public
1454
+ */
1455
+
1456
+ assert.match = function (exp, re, msg) {
1457
+ new Assertion(exp, msg).to.match(re);
1458
+ };
1459
+
1460
+ /**
1461
+ * # .length(value, constructor, [message])
1462
+ *
1463
+ * Assert that object has expected length.
1464
+ *
1465
+ * assert.length([1,2,3], 3, 'Array has length of 3');
1466
+ * assert.length('foobar', 5, 'String has length of 6');
1467
+ *
1468
+ * @name length
1469
+ * @param {*} value
1470
+ * @param {Number} length
1471
+ * @param {String} message
1472
+ * @api public
1473
+ */
1474
+
1475
+ assert.length = function (exp, len, msg) {
1476
+ new Assertion(exp, msg).to.have.length(len);
1477
+ };
1478
+
1479
+ /**
1480
+ * # .throws(function, [constructor/regexp], [message])
1481
+ *
1482
+ * Assert that a function will throw a specific
1483
+ * type of error.
1484
+ *
1485
+ * assert.throw(fn, ReferenceError, 'function throw reference error');
1486
+ *
1487
+ * @name throws
1488
+ * @alias throw
1489
+ * @param {Function} function to test
1490
+ * @param {ErrorConstructor} constructor
1491
+ * @param {String} message
1492
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
1493
+ * @api public
1494
+ */
1495
+
1496
+ assert.throws = function (fn, type, msg) {
1497
+ if ('string' === typeof type) {
1498
+ msg = type;
1499
+ type = null;
1500
+ }
1501
+
1502
+ new Assertion(fn, msg).to.throw(type);
1503
+ };
1504
+
1505
+ /**
1506
+ * # .doesNotThrow(function, [constructor/regexp], [message])
1507
+ *
1508
+ * Assert that a function will throw a specific
1509
+ * type of error.
1510
+ *
1511
+ * var fn = function (err) { if (err) throw Error(err) };
1512
+ * assert.doesNotThrow(fn, Error, 'function throw reference error');
1513
+ *
1514
+ * @name doesNotThrow
1515
+ * @param {Function} function to test
1516
+ * @param {ErrorConstructor} constructor
1517
+ * @param {String} message
1518
+ * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
1519
+ * @api public
1520
+ */
1521
+
1522
+ assert.doesNotThrow = function (fn, type, msg) {
1523
+ if ('string' === typeof type) {
1524
+ msg = type;
1525
+ type = null;
1526
+ }
1527
+
1528
+ new Assertion(fn, msg).to.not.throw(type);
1529
+ };
1530
+
1531
+ /*!
1532
+ * Undocumented / untested
1533
+ */
1534
+
1535
+ assert.ifError = function (val, msg) {
1536
+ new Assertion(val, msg).to.not.be.ok;
1537
+ };
1538
+
1539
+ /*!
1540
+ * Aliases.
1541
+ */
1542
+
1543
+ (function alias(name, as){
1544
+ assert[as] = assert[name];
1545
+ return alias;
1546
+ })
1547
+ ('length', 'lengthOf')
1548
+ ('throws', 'throw');
1549
+ };
1550
+
1551
+ }); // module: interface/assert.js
1552
+
1553
+ require.register("interface/expect.js", function(module, exports, require){
1554
+ /*!
1555
+ * chai
1556
+ * Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>
1557
+ * MIT Licensed
1558
+ */
1559
+
1560
+ module.exports = function (chai) {
1561
+ chai.expect = function (val, message) {
1562
+ return new chai.Assertion(val, message);
1563
+ };
1564
+ };
1565
+
1566
+
1567
+ }); // module: interface/expect.js
1568
+
1569
+ require.register("interface/should.js", function(module, exports, require){
1570
+ /*!
1571
+ * chai
1572
+ * Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>
1573
+ * MIT Licensed
1574
+ */
1575
+
1576
+ module.exports = function (chai) {
1577
+ var Assertion = chai.Assertion;
1578
+
1579
+ chai.should = function () {
1580
+ // modify Object.prototype to have `should`
1581
+ Object.defineProperty(Object.prototype, 'should', {
1582
+ set: function(){},
1583
+ get: function(){
1584
+ if (this instanceof String || this instanceof Number) {
1585
+ return new Assertion(this.constructor(this));
1586
+ } else if (this instanceof Boolean) {
1587
+ return new Assertion(this == true);
1588
+ }
1589
+ return new Assertion(this);
1590
+ },
1591
+ configurable: true
1592
+ });
1593
+
1594
+ var should = {};
1595
+
1596
+ should.equal = function (val1, val2) {
1597
+ new Assertion(val1).to.equal(val2);
1598
+ };
1599
+
1600
+ should.throw = function (fn, err) {
1601
+ new Assertion(fn).to.throw(err);
1602
+ };
1603
+
1604
+ should.exist = function (val) {
1605
+ new Assertion(val).to.exist;
1606
+ }
1607
+
1608
+ // negation
1609
+ should.not = {}
1610
+
1611
+ should.not.equal = function (val1, val2) {
1612
+ new Assertion(val1).to.not.equal(val2);
1613
+ };
1614
+
1615
+ should.not.throw = function (fn, err) {
1616
+ new Assertion(fn).to.not.throw(err);
1617
+ };
1618
+
1619
+ should.not.exist = function (val) {
1620
+ new Assertion(val).to.not.exist;
1621
+ }
1622
+
1623
+ return should;
1624
+ };
1625
+ };
1626
+
1627
+ }); // module: interface/should.js
1628
+
1629
+ require.register("utils/eql.js", function(module, exports, require){
1630
+ // This is directly from Node.js assert
1631
+ // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/assert.js
1632
+
1633
+
1634
+ module.exports = _deepEqual;
1635
+
1636
+ // For browser implementation
1637
+ if (!Buffer) {
1638
+ var Buffer = {
1639
+ isBuffer: function () {
1640
+ return false;
1641
+ }
1642
+ };
1643
+ }
1644
+
1645
+ function _deepEqual(actual, expected) {
1646
+ // 7.1. All identical values are equivalent, as determined by ===.
1647
+ if (actual === expected) {
1648
+ return true;
1649
+
1650
+ } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
1651
+ if (actual.length != expected.length) return false;
1652
+
1653
+ for (var i = 0; i < actual.length; i++) {
1654
+ if (actual[i] !== expected[i]) return false;
1655
+ }
1656
+
1657
+ return true;
1658
+
1659
+ // 7.2. If the expected value is a Date object, the actual value is
1660
+ // equivalent if it is also a Date object that refers to the same time.
1661
+ } else if (actual instanceof Date && expected instanceof Date) {
1662
+ return actual.getTime() === expected.getTime();
1663
+
1664
+ // 7.3. Other pairs that do not both pass typeof value == 'object',
1665
+ // equivalence is determined by ==.
1666
+ } else if (typeof actual != 'object' && typeof expected != 'object') {
1667
+ return actual === expected;
1668
+
1669
+ // 7.4. For all other Object pairs, including Array objects, equivalence is
1670
+ // determined by having the same number of owned properties (as verified
1671
+ // with Object.prototype.hasOwnProperty.call), the same set of keys
1672
+ // (although not necessarily the same order), equivalent values for every
1673
+ // corresponding key, and an identical 'prototype' property. Note: this
1674
+ // accounts for both named and indexed properties on Arrays.
1675
+ } else {
1676
+ return objEquiv(actual, expected);
1677
+ }
1678
+ }
1679
+
1680
+ function isUndefinedOrNull(value) {
1681
+ return value === null || value === undefined;
1682
+ }
1683
+
1684
+ function isArguments(object) {
1685
+ return Object.prototype.toString.call(object) == '[object Arguments]';
1686
+ }
1687
+
1688
+ function objEquiv(a, b) {
1689
+ if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
1690
+ return false;
1691
+ // an identical 'prototype' property.
1692
+ if (a.prototype !== b.prototype) return false;
1693
+ //~~~I've managed to break Object.keys through screwy arguments passing.
1694
+ // Converting to array solves the problem.
1695
+ if (isArguments(a)) {
1696
+ if (!isArguments(b)) {
1697
+ return false;
1698
+ }
1699
+ a = pSlice.call(a);
1700
+ b = pSlice.call(b);
1701
+ return _deepEqual(a, b);
1702
+ }
1703
+ try {
1704
+ var ka = Object.keys(a),
1705
+ kb = Object.keys(b),
1706
+ key, i;
1707
+ } catch (e) {//happens when one is a string literal and the other isn't
1708
+ return false;
1709
+ }
1710
+ // having the same number of owned properties (keys incorporates
1711
+ // hasOwnProperty)
1712
+ if (ka.length != kb.length)
1713
+ return false;
1714
+ //the same set of keys (although not necessarily the same order),
1715
+ ka.sort();
1716
+ kb.sort();
1717
+ //~~~cheap key test
1718
+ for (i = ka.length - 1; i >= 0; i--) {
1719
+ if (ka[i] != kb[i])
1720
+ return false;
1721
+ }
1722
+ //equivalent values for every corresponding key, and
1723
+ //~~~possibly expensive deep test
1724
+ for (i = ka.length - 1; i >= 0; i--) {
1725
+ key = ka[i];
1726
+ if (!_deepEqual(a[key], b[key])) return false;
1727
+ }
1728
+ return true;
1729
+ }
1730
+ }); // module: utils/eql.js
1731
+
1732
+ require.register("utils/inspect.js", function(module, exports, require){
1733
+ // This is (almost) directly from Node.js utils
1734
+ // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js
1735
+
1736
+ module.exports = inspect;
1737
+
1738
+ /**
1739
+ * Echos the value of a value. Trys to print the value out
1740
+ * in the best way possible given the different types.
1741
+ *
1742
+ * @param {Object} obj The object to print out.
1743
+ * @param {Boolean} showHidden Flag that shows hidden (not enumerable)
1744
+ * properties of objects.
1745
+ * @param {Number} depth Depth in which to descend in object. Default is 2.
1746
+ * @param {Boolean} colors Flag to turn on ANSI escape codes to color the
1747
+ * output. Default is false (no coloring).
1748
+ */
1749
+ function inspect(obj, showHidden, depth, colors) {
1750
+ var ctx = {
1751
+ showHidden: showHidden,
1752
+ seen: [],
1753
+ stylize: function (str) { return str; }
1754
+ };
1755
+ return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth));
1756
+ }
1757
+
1758
+ function formatValue(ctx, value, recurseTimes) {
1759
+ // Provide a hook for user-specified inspect functions.
1760
+ // Check that value is an object with an inspect function on it
1761
+ if (value && typeof value.inspect === 'function' &&
1762
+ // Filter out the util module, it's inspect function is special
1763
+ value.inspect !== exports.inspect &&
1764
+ // Also filter out any prototype objects using the circular check.
1765
+ !(value.constructor && value.constructor.prototype === value)) {
1766
+ return value.inspect(recurseTimes);
1767
+ }
1768
+
1769
+ // Primitive types cannot have properties
1770
+ var primitive = formatPrimitive(ctx, value);
1771
+ if (primitive) {
1772
+ return primitive;
1773
+ }
1774
+
1775
+ // Look up the keys of the object.
1776
+ var visibleKeys = Object.keys(value);
1777
+ var keys = ctx.showHidden ? Object.getOwnPropertyNames(value) : visibleKeys;
1778
+
1779
+ // Some type of object without properties can be shortcutted.
1780
+ if (keys.length === 0) {
1781
+ if (typeof value === 'function') {
1782
+ var name = value.name ? ': ' + value.name : '';
1783
+ return ctx.stylize('[Function' + name + ']', 'special');
1784
+ }
1785
+ if (isRegExp(value)) {
1786
+ return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
1787
+ }
1788
+ if (isDate(value)) {
1789
+ return ctx.stylize(Date.prototype.toUTCString.call(value), 'date');
1790
+ }
1791
+ if (isError(value)) {
1792
+ return formatError(value);
1793
+ }
1794
+ }
1795
+
1796
+ var base = '', array = false, braces = ['{', '}'];
1797
+
1798
+ // Make Array say that they are Array
1799
+ if (isArray(value)) {
1800
+ array = true;
1801
+ braces = ['[', ']'];
1802
+ }
1803
+
1804
+ // Make functions say that they are functions
1805
+ if (typeof value === 'function') {
1806
+ var n = value.name ? ': ' + value.name : '';
1807
+ base = ' [Function' + n + ']';
1808
+ }
1809
+
1810
+ // Make RegExps say that they are RegExps
1811
+ if (isRegExp(value)) {
1812
+ base = ' ' + RegExp.prototype.toString.call(value);
1813
+ }
1814
+
1815
+ // Make dates with properties first say the date
1816
+ if (isDate(value)) {
1817
+ base = ' ' + Date.prototype.toUTCString.call(value);
1818
+ }
1819
+
1820
+ // Make error with message first say the error
1821
+ if (isError(value)) {
1822
+ base = ' ' + formatError(value);
1823
+ }
1824
+
1825
+ if (keys.length === 0 && (!array || value.length == 0)) {
1826
+ return braces[0] + base + braces[1];
1827
+ }
1828
+
1829
+ if (recurseTimes < 0) {
1830
+ if (isRegExp(value)) {
1831
+ return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
1832
+ } else {
1833
+ return ctx.stylize('[Object]', 'special');
1834
+ }
1835
+ }
1836
+
1837
+ ctx.seen.push(value);
1838
+
1839
+ var output;
1840
+ if (array) {
1841
+ output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
1842
+ } else {
1843
+ output = keys.map(function(key) {
1844
+ return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
1845
+ });
1846
+ }
1847
+
1848
+ ctx.seen.pop();
1849
+
1850
+ return reduceToSingleString(output, base, braces);
1851
+ }
1852
+
1853
+
1854
+ function formatPrimitive(ctx, value) {
1855
+ switch (typeof value) {
1856
+ case 'undefined':
1857
+ return ctx.stylize('undefined', 'undefined');
1858
+
1859
+ case 'string':
1860
+ var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
1861
+ .replace(/'/g, "\\'")
1862
+ .replace(/\\"/g, '"') + '\'';
1863
+ return ctx.stylize(simple, 'string');
1864
+
1865
+ case 'number':
1866
+ return ctx.stylize('' + value, 'number');
1867
+
1868
+ case 'boolean':
1869
+ return ctx.stylize('' + value, 'boolean');
1870
+ }
1871
+ // For some reason typeof null is "object", so special case here.
1872
+ if (value === null) {
1873
+ return ctx.stylize('null', 'null');
1874
+ }
1875
+ }
1876
+
1877
+
1878
+ function formatError(value) {
1879
+ return '[' + Error.prototype.toString.call(value) + ']';
1880
+ }
1881
+
1882
+
1883
+ function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
1884
+ var output = [];
1885
+ for (var i = 0, l = value.length; i < l; ++i) {
1886
+ if (Object.prototype.hasOwnProperty.call(value, String(i))) {
1887
+ output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
1888
+ String(i), true));
1889
+ } else {
1890
+ output.push('');
1891
+ }
1892
+ }
1893
+ keys.forEach(function(key) {
1894
+ if (!key.match(/^\d+$/)) {
1895
+ output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
1896
+ key, true));
1897
+ }
1898
+ });
1899
+ return output;
1900
+ }
1901
+
1902
+
1903
+ function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
1904
+ var name, str;
1905
+ if (value.__lookupGetter__) {
1906
+ if (value.__lookupGetter__(key)) {
1907
+ if (value.__lookupSetter__(key)) {
1908
+ str = ctx.stylize('[Getter/Setter]', 'special');
1909
+ } else {
1910
+ str = ctx.stylize('[Getter]', 'special');
1911
+ }
1912
+ } else {
1913
+ if (value.__lookupSetter__(key)) {
1914
+ str = ctx.stylize('[Setter]', 'special');
1915
+ }
1916
+ }
1917
+ }
1918
+ if (visibleKeys.indexOf(key) < 0) {
1919
+ name = '[' + key + ']';
1920
+ }
1921
+ if (!str) {
1922
+ if (ctx.seen.indexOf(value[key]) < 0) {
1923
+ if (recurseTimes === null) {
1924
+ str = formatValue(ctx, value[key], null);
1925
+ } else {
1926
+ str = formatValue(ctx, value[key], recurseTimes - 1);
1927
+ }
1928
+ if (str.indexOf('\n') > -1) {
1929
+ if (array) {
1930
+ str = str.split('\n').map(function(line) {
1931
+ return ' ' + line;
1932
+ }).join('\n').substr(2);
1933
+ } else {
1934
+ str = '\n' + str.split('\n').map(function(line) {
1935
+ return ' ' + line;
1936
+ }).join('\n');
1937
+ }
1938
+ }
1939
+ } else {
1940
+ str = ctx.stylize('[Circular]', 'special');
1941
+ }
1942
+ }
1943
+ if (typeof name === 'undefined') {
1944
+ if (array && key.match(/^\d+$/)) {
1945
+ return str;
1946
+ }
1947
+ name = JSON.stringify('' + key);
1948
+ if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
1949
+ name = name.substr(1, name.length - 2);
1950
+ name = ctx.stylize(name, 'name');
1951
+ } else {
1952
+ name = name.replace(/'/g, "\\'")
1953
+ .replace(/\\"/g, '"')
1954
+ .replace(/(^"|"$)/g, "'");
1955
+ name = ctx.stylize(name, 'string');
1956
+ }
1957
+ }
1958
+
1959
+ return name + ': ' + str;
1960
+ }
1961
+
1962
+
1963
+ function reduceToSingleString(output, base, braces) {
1964
+ var numLinesEst = 0;
1965
+ var length = output.reduce(function(prev, cur) {
1966
+ numLinesEst++;
1967
+ if (cur.indexOf('\n') >= 0) numLinesEst++;
1968
+ return prev + cur.length + 1;
1969
+ }, 0);
1970
+
1971
+ if (length > 60) {
1972
+ return braces[0] +
1973
+ (base === '' ? '' : base + '\n ') +
1974
+ ' ' +
1975
+ output.join(',\n ') +
1976
+ ' ' +
1977
+ braces[1];
1978
+ }
1979
+
1980
+ return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
1981
+ }
1982
+
1983
+ function isArray(ar) {
1984
+ return Array.isArray(ar) ||
1985
+ (typeof ar === 'object' && objectToString(ar) === '[object Array]');
1986
+ }
1987
+
1988
+ function isRegExp(re) {
1989
+ return typeof re === 'object' && objectToString(re) === '[object RegExp]';
1990
+ }
1991
+
1992
+ function isDate(d) {
1993
+ return typeof d === 'object' && objectToString(d) === '[object Date]';
1994
+ }
1995
+
1996
+ function isError(e) {
1997
+ return typeof e === 'object' && objectToString(e) === '[object Error]';
1998
+ }
1999
+
2000
+ function objectToString(o) {
2001
+ return Object.prototype.toString.call(o);
2002
+ }
2003
+ }); // module: utils/inspect.js
2004
+
2005
+
2006
+ return require('chai');
2007
+ });