jspec 2.11.13 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/History.md +714 -0
  2. data/Manifest +51 -36
  3. data/README.md +968 -0
  4. data/Rakefile +4 -53
  5. data/bin/jspec +93 -224
  6. data/jspec.gemspec +5 -5
  7. data/lib/images/sprites.png +0 -0
  8. data/lib/jspec.css +2 -2
  9. data/lib/jspec.growl.js +115 -0
  10. data/lib/jspec.jquery.js +1 -1
  11. data/lib/jspec.js +98 -101
  12. data/lib/jspec.shell.js +5 -2
  13. data/lib/jspec.timers.js +1 -1
  14. data/lib/jspec.xhr.js +12 -2
  15. data/spec/commands/example_command.rb +19 -0
  16. data/spec/dom.html +33 -0
  17. data/spec/node.js +32 -0
  18. data/spec/rhino.js +24 -0
  19. data/spec/ruby/bin/init_spec.rb +101 -0
  20. data/spec/ruby/bin/install_spec.rb +141 -0
  21. data/spec/ruby/bin/run_spec.rb +0 -0
  22. data/spec/ruby/bin/shell_spec.rb +13 -0
  23. data/spec/ruby/bin/spec_helper.rb +25 -0
  24. data/spec/ruby/bin/update_spec.rb +72 -0
  25. data/spec/server.html +29 -0
  26. data/spec/server.rb +1 -1
  27. data/spec/{env.js → support/env.js} +554 -664
  28. data/spec/support/jquery.js +4376 -0
  29. data/spec/{helpers.js → unit/helpers.js} +2 -0
  30. data/spec/{spec.fixtures.js → unit/spec.fixtures.js} +0 -1
  31. data/spec/{spec.grammar-less.js → unit/spec.grammar-less.js} +0 -0
  32. data/spec/{spec.grammar.js → unit/spec.grammar.js} +1 -11
  33. data/spec/{spec.jquery.js → unit/spec.jquery.js} +0 -17
  34. data/spec/{spec.jquery.xhr.js → unit/spec.jquery.xhr.js} +13 -2
  35. data/spec/unit/spec.js +187 -0
  36. data/spec/{spec.matchers.js → unit/spec.matchers.js} +141 -66
  37. data/spec/{spec.modules.js → unit/spec.modules.js} +0 -0
  38. data/spec/{spec.shared-behaviors.js → unit/spec.shared-behaviors.js} +0 -0
  39. data/spec/{spec.utils.js → unit/spec.utils.js} +123 -22
  40. data/spec/{spec.xhr.js → unit/spec.xhr.js} +11 -10
  41. data/{server → src}/browsers.rb +23 -0
  42. data/{server → src}/helpers.rb +2 -17
  43. data/src/installables.rb +229 -0
  44. data/src/project.rb +340 -0
  45. data/{server → src}/routes.rb +1 -1
  46. data/{server → src}/server.rb +0 -0
  47. data/support/js.jar +0 -0
  48. data/templates/default/History.md +5 -0
  49. data/templates/default/{README.rdoc → Readme.md} +3 -3
  50. data/templates/default/lib/{yourlib.core.js → yourlib.js} +0 -0
  51. data/templates/default/spec/commands/example_command.rb +19 -0
  52. data/templates/default/spec/{spec.dom.html → dom.html} +5 -3
  53. data/templates/default/spec/rhino.js +10 -0
  54. data/templates/default/spec/server.html +18 -0
  55. data/templates/default/spec/unit/spec.helper.js +0 -0
  56. data/templates/default/spec/{spec.core.js → unit/spec.js} +0 -0
  57. data/templates/rails/commands/example_commands.rb +19 -0
  58. data/templates/rails/{spec.dom.html → dom.html} +4 -2
  59. data/templates/rails/rhino.js +10 -0
  60. data/templates/rails/server.html +18 -0
  61. data/templates/rails/unit/spec.helper.js +0 -0
  62. data/templates/rails/{spec.application.js → unit/spec.js} +0 -0
  63. metadata +56 -41
  64. data/History.rdoc +0 -590
  65. data/README.rdoc +0 -842
  66. data/spec/async +0 -1
  67. data/spec/jquery.js +0 -19
  68. data/spec/spec.dom.html +0 -34
  69. data/spec/spec.js +0 -166
  70. data/spec/spec.node.js +0 -46
  71. data/spec/spec.rhino.js +0 -23
  72. data/spec/spec.server.html +0 -29
  73. data/templates/default/History.rdoc +0 -4
  74. data/templates/default/spec/spec.rhino.js +0 -8
  75. data/templates/default/spec/spec.server.html +0 -16
  76. data/templates/rails/spec.rhino.js +0 -8
  77. data/templates/rails/spec.server.html +0 -16
data/jspec.gemspec CHANGED
@@ -2,19 +2,19 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{jspec}
5
- s.version = "2.11.13"
5
+ s.version = "3.0.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["TJ Holowaychuk"]
9
- s.date = %q{2009-11-22}
9
+ s.date = %q{2010-01-04}
10
10
  s.default_executable = %q{jspec}
11
11
  s.description = %q{JavaScript BDD Testing Framework}
12
12
  s.email = %q{tj@vision-media.ca}
13
13
  s.executables = ["jspec"]
14
- s.extra_rdoc_files = ["README.rdoc", "bin/jspec", "lib/images/bg.png", "lib/images/hr.png", "lib/images/loading.gif", "lib/images/sprites.bg.png", "lib/images/sprites.png", "lib/images/vr.png", "lib/jspec.css", "lib/jspec.jquery.js", "lib/jspec.js", "lib/jspec.shell.js", "lib/jspec.timers.js", "lib/jspec.xhr.js"]
15
- s.files = ["History.rdoc", "Manifest", "README.rdoc", "Rakefile", "bin/jspec", "jspec.gemspec", "lib/images/bg.png", "lib/images/hr.png", "lib/images/loading.gif", "lib/images/sprites.bg.png", "lib/images/sprites.png", "lib/images/vr.png", "lib/jspec.css", "lib/jspec.jquery.js", "lib/jspec.js", "lib/jspec.shell.js", "lib/jspec.timers.js", "lib/jspec.xhr.js", "server/browsers.rb", "server/helpers.rb", "server/routes.rb", "server/server.rb", "spec/async", "spec/env.js", "spec/fixtures/test.html", "spec/fixtures/test.json", "spec/fixtures/test.xml", "spec/helpers.js", "spec/jquery.js", "spec/server.rb", "spec/spec.dom.html", "spec/spec.fixtures.js", "spec/spec.grammar-less.js", "spec/spec.grammar.js", "spec/spec.jquery.js", "spec/spec.jquery.xhr.js", "spec/spec.js", "spec/spec.matchers.js", "spec/spec.modules.js", "spec/spec.node.js", "spec/spec.rhino.js", "spec/spec.server.html", "spec/spec.shared-behaviors.js", "spec/spec.utils.js", "spec/spec.xhr.js", "templates/default/History.rdoc", "templates/default/README.rdoc", "templates/default/lib/yourlib.core.js", "templates/default/spec/server.rb", "templates/default/spec/spec.core.js", "templates/default/spec/spec.dom.html", "templates/default/spec/spec.rhino.js", "templates/default/spec/spec.server.html", "templates/rails/server.rb", "templates/rails/spec.application.js", "templates/rails/spec.dom.html", "templates/rails/spec.rhino.js", "templates/rails/spec.server.html"]
14
+ s.extra_rdoc_files = ["README.md", "bin/jspec", "lib/images/bg.png", "lib/images/hr.png", "lib/images/loading.gif", "lib/images/sprites.bg.png", "lib/images/sprites.png", "lib/images/vr.png", "lib/jspec.css", "lib/jspec.growl.js", "lib/jspec.jquery.js", "lib/jspec.js", "lib/jspec.shell.js", "lib/jspec.timers.js", "lib/jspec.xhr.js"]
15
+ s.files = ["History.md", "Manifest", "README.md", "Rakefile", "bin/jspec", "lib/images/bg.png", "lib/images/hr.png", "lib/images/loading.gif", "lib/images/sprites.bg.png", "lib/images/sprites.png", "lib/images/vr.png", "lib/jspec.css", "lib/jspec.growl.js", "lib/jspec.jquery.js", "lib/jspec.js", "lib/jspec.shell.js", "lib/jspec.timers.js", "lib/jspec.xhr.js", "spec/commands/example_command.rb", "spec/dom.html", "spec/fixtures/test.html", "spec/fixtures/test.json", "spec/fixtures/test.xml", "spec/node.js", "spec/rhino.js", "spec/ruby/bin/init_spec.rb", "spec/ruby/bin/install_spec.rb", "spec/ruby/bin/run_spec.rb", "spec/ruby/bin/shell_spec.rb", "spec/ruby/bin/spec_helper.rb", "spec/ruby/bin/update_spec.rb", "spec/server.html", "spec/server.rb", "spec/support/env.js", "spec/support/jquery.js", "spec/unit/helpers.js", "spec/unit/spec.fixtures.js", "spec/unit/spec.grammar-less.js", "spec/unit/spec.grammar.js", "spec/unit/spec.jquery.js", "spec/unit/spec.jquery.xhr.js", "spec/unit/spec.js", "spec/unit/spec.matchers.js", "spec/unit/spec.modules.js", "spec/unit/spec.shared-behaviors.js", "spec/unit/spec.utils.js", "spec/unit/spec.xhr.js", "src/browsers.rb", "src/helpers.rb", "src/installables.rb", "src/project.rb", "src/routes.rb", "src/server.rb", "support/js.jar", "templates/default/History.md", "templates/default/Readme.md", "templates/default/lib/yourlib.js", "templates/default/spec/commands/example_command.rb", "templates/default/spec/dom.html", "templates/default/spec/rhino.js", "templates/default/spec/server.html", "templates/default/spec/server.rb", "templates/default/spec/unit/spec.helper.js", "templates/default/spec/unit/spec.js", "templates/rails/commands/example_commands.rb", "templates/rails/dom.html", "templates/rails/rhino.js", "templates/rails/server.html", "templates/rails/server.rb", "templates/rails/unit/spec.helper.js", "templates/rails/unit/spec.js", "jspec.gemspec"]
16
16
  s.homepage = %q{http://visionmedia.github.com/jspec}
17
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Jspec", "--main", "README.rdoc"]
17
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Jspec", "--main", "README.md"]
18
18
  s.require_paths = ["lib"]
19
19
  s.rubyforge_project = %q{jspec}
20
20
  s.rubygems_version = %q{1.3.5}
Binary file
data/lib/jspec.css CHANGED
@@ -114,12 +114,12 @@ body.jspec {
114
114
  background: url(images/sprites.png) 3px -7px no-repeat;
115
115
  }
116
116
  #jspec-report td.fail {
117
- background: url(images/sprites.png) 3px -47px no-repeat;
117
+ background: url(images/sprites.png) 3px -158px no-repeat;
118
118
  font-weight: bold;
119
119
  color: #FC0D0D;
120
120
  }
121
121
  #jspec-report td.requires-implementation {
122
- background: url(images/sprites.png) 3px -87px no-repeat;
122
+ background: url(images/sprites.png) 3px -333px no-repeat;
123
123
  }
124
124
  #jspec-report tr.description td {
125
125
  margin-top: 25px;
@@ -0,0 +1,115 @@
1
+
2
+ // JSpec - Growl - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
3
+
4
+ ;(function(){
5
+
6
+ Growl = {
7
+
8
+ // --- Version
9
+
10
+ version: '1.0.0',
11
+
12
+ /**
13
+ * Execute the given _cmd_, returning an array of lines from stdout.
14
+ *
15
+ * Examples:
16
+ *
17
+ * Growl.exec('growlnotify', '-m', msg)
18
+ *
19
+ * @param {string ...} cmd
20
+ * @return {array}
21
+ * @api public
22
+ */
23
+
24
+ exec: function(cmd) {
25
+ var lines = [], line
26
+ with (JavaImporter(java.lang, java.io)) {
27
+ var proccess = Runtime.getRuntime().exec(Array.prototype.slice.call(arguments))
28
+ var stream = new DataInputStream(proccess.getInputStream())
29
+ while (line = stream.readLine())
30
+ lines.push(line + '')
31
+ stream.close()
32
+ }
33
+ return lines
34
+ },
35
+
36
+ /**
37
+ * Return the extension of the given _path_ or null.
38
+ *
39
+ * @param {string} path
40
+ * @return {string}
41
+ * @api private
42
+ */
43
+
44
+ extname: function(path) {
45
+ return path.lastIndexOf('.') != -1 ?
46
+ path.slice(path.lastIndexOf('.') + 1, path.length) :
47
+ null
48
+ },
49
+
50
+ /**
51
+ * Version of the 'growlnotify' binary.
52
+ *
53
+ * @return {string}
54
+ * @api private
55
+ */
56
+
57
+ binVersion: function() {
58
+ try { return this.exec('growlnotify', '-v')[0].split(' ')[1] } catch (e) {}
59
+ },
60
+
61
+ /**
62
+ * Send growl notification _msg_ with _options_.
63
+ *
64
+ * Options:
65
+ *
66
+ * - title Notification title
67
+ * - sticky Make the notification stick (defaults to false)
68
+ * - name Application name (defaults to growlnotify)
69
+ * - image
70
+ * - path to an icon sets --iconpath
71
+ * - path to an image sets --image
72
+ * - capitalized word sets --appIcon
73
+ * - filename uses extname as --icon
74
+ * - otherwise treated as --icon
75
+ *
76
+ * Examples:
77
+ *
78
+ * Growl.notify('New email')
79
+ * Growl.notify('5 new emails', { title: 'Thunderbird' })
80
+ *
81
+ * @param {string} msg
82
+ * @param {options} hash
83
+ * @api public
84
+ */
85
+
86
+ notify: function(msg, options) {
87
+ options = options || {}
88
+ var args = ['growlnotify', '-m', msg]
89
+ if (!this.binVersion()) throw new Error('growlnotify executable is required')
90
+ if (image = options.image) {
91
+ var flag, ext = this.extname(image)
92
+ flag = flag || ext == 'icns' && 'iconpath'
93
+ flag = flag || /^[A-Z]/.test(image) && 'appIcon'
94
+ flag = flag || /^png|gif|jpe?g$/.test(ext) && 'image'
95
+ flag = flag || ext && (image = ext) && 'icon'
96
+ flag = flag || 'icon'
97
+ args.push('--' + flag, image)
98
+ }
99
+ if (options.sticky) args.push('--sticky')
100
+ if (options.name) args.push('--name', options.name)
101
+ if (options.title) args.push(options.title)
102
+ this.exec.apply(this, args)
103
+ }
104
+ }
105
+
106
+ JSpec.include({
107
+ name: 'Growl',
108
+ reporting: function(options){
109
+ var stats = JSpec.stats
110
+ if (stats.failures) Growl.notify('failed ' + stats.failures + ' assertions', { title: 'JSpec'})
111
+ else Growl.notify('passed ' + stats.passes + ' assertions', { title: 'JSpec' })
112
+ }
113
+ })
114
+
115
+ })()
data/lib/jspec.jquery.js CHANGED
@@ -47,7 +47,7 @@ JSpec
47
47
  },
48
48
 
49
49
  have_classes : function(actual) {
50
- return !JSpec.any(JSpec.argumentsToArray(arguments, 1), function(arg){
50
+ return !JSpec.any(JSpec.toArray(arguments, 1), function(arg){
51
51
  return !JSpec.does(actual, 'have_class', arg)
52
52
  })
53
53
  },
data/lib/jspec.js CHANGED
@@ -1,20 +1,20 @@
1
1
 
2
2
  // JSpec - Core - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
3
3
 
4
- (function(){
4
+ ;(function(){
5
5
 
6
6
  JSpec = {
7
-
8
- version : '2.11.13',
7
+ version : '3.1.0',
8
+ assert : true,
9
9
  cache : {},
10
10
  suites : [],
11
11
  modules : [],
12
12
  allSuites : [],
13
13
  matchers : {},
14
14
  stubbed : [],
15
+ options : {},
15
16
  request : 'XMLHttpRequest' in this ? XMLHttpRequest : null,
16
17
  stats : { specs: 0, assertions: 0, failures: 0, passes: 0, specsFinished: 0, suitesFinished: 0 },
17
- options : { profile: false },
18
18
 
19
19
  /**
20
20
  * Default context in which bodies are evaluated.
@@ -51,15 +51,12 @@
51
51
  },
52
52
 
53
53
  /**
54
- * Load fixture at _path_. This utility function
55
- * supplies the means to resolve, and cache fixture contents
56
- * via the DOM or Rhino.
54
+ * Load fixture at _path_.
57
55
  *
58
56
  * Fixtures are resolved as:
59
57
  *
60
58
  * - <path>
61
- * - fixtures/<path>
62
- * - fixtures/<path>.html
59
+ * - <path>.html
63
60
  *
64
61
  * @param {string} path
65
62
  * @return {string}
@@ -69,18 +66,14 @@
69
66
  fixture : function(path) {
70
67
  if (JSpec.cache[path]) return JSpec.cache[path]
71
68
  return JSpec.cache[path] =
72
- JSpec.tryLoading(path) ||
73
- JSpec.tryLoading('fixtures/' + path) ||
74
- JSpec.tryLoading('fixtures/' + path + '.html') ||
75
- JSpec.tryLoading('spec/' + path) ||
76
- JSpec.tryLoading('spec/fixtures/' + path) ||
77
- JSpec.tryLoading('spec/fixtures/' + path + '.html')
69
+ JSpec.tryLoading(JSpec.options.fixturePath + '/' + path) ||
70
+ JSpec.tryLoading(JSpec.options.fixturePath + '/' + path + '.html')
78
71
  }
79
72
  },
80
73
 
81
74
  // --- Objects
82
75
 
83
- formatters : {
76
+ reporters : {
84
77
 
85
78
  /**
86
79
  * Report to server.
@@ -123,7 +116,7 @@
123
116
  },
124
117
 
125
118
  /**
126
- * Default formatter, outputting to the DOM.
119
+ * Default reporter, outputting to the DOM.
127
120
  *
128
121
  * Options:
129
122
  * - reportToId id of element to output reports to, defaults to 'jspec'
@@ -149,6 +142,7 @@
149
142
  report.innerHTML = '<div id="jspec-report" class="' + classes + '"><div class="heading"> \
150
143
  <span class="passes">Passes: <em>' + results.stats.passes + '</em></span> \
151
144
  <span class="failures">Failures: <em>' + results.stats.failures + '</em></span> \
145
+ <span class="passes">Duration: <em>' + results.duration + '</em> ms</span> \
152
146
  </div><table class="suites">' + map(results.allSuites, function(suite) {
153
147
  var displaySuite = failuresOnly ? suite.ran && !suite.passed() : suite.ran
154
148
  if (displaySuite && suite.hasSpecs())
@@ -170,7 +164,7 @@
170
164
  },
171
165
 
172
166
  /**
173
- * Terminal formatter.
167
+ * Terminal reporter.
174
168
  *
175
169
  * @api public
176
170
  */
@@ -178,7 +172,8 @@
178
172
  Terminal : function(results, options) {
179
173
  failuresOnly = option('failuresOnly')
180
174
  print(color("\n Passes: ", 'bold') + color(results.stats.passes, 'green') +
181
- color(" Failures: ", 'bold') + color(results.stats.failures, 'red') + "\n")
175
+ color(" Failures: ", 'bold') + color(results.stats.failures, 'red') +
176
+ color(" Duration: ", 'bold') + color(results.duration, 'green') + " ms \n")
182
177
 
183
178
  function indent(string) {
184
179
  return string.replace(/^(.)/gm, ' $1')
@@ -208,7 +203,7 @@
208
203
  },
209
204
 
210
205
  /**
211
- * Console formatter.
206
+ * Console reporter.
212
207
  *
213
208
  * @api public
214
209
  */
@@ -246,7 +241,8 @@
246
241
  // Report assertion results
247
242
 
248
243
  report : function() {
249
- this.passed ? JSpec.stats.passes++ : JSpec.stats.failures++
244
+ if (JSpec.assert)
245
+ this.passed ? JSpec.stats.passes++ : JSpec.stats.failures++
250
246
  return this
251
247
  },
252
248
 
@@ -270,7 +266,7 @@
270
266
  // Proxy
271
267
 
272
268
  object[method] = function(){
273
- args = argumentsToArray(arguments)
269
+ args = toArray(arguments)
274
270
  result = old.apply(object, args)
275
271
  self.calls.push({ args : args, result : result })
276
272
  return result
@@ -302,7 +298,7 @@
302
298
  // Proxy arguments passed
303
299
 
304
300
  with_args : function() {
305
- this.expectedArgs = argumentsToArray(arguments)
301
+ this.expectedArgs = toArray(arguments)
306
302
  return this
307
303
  },
308
304
 
@@ -312,7 +308,7 @@
312
308
  return any(this.calls, function(call){
313
309
  return self.expectedResult.an_instance_of ?
314
310
  call.result.constructor != self.expectedResult.an_instance_of:
315
- hash(self.expectedResult) != hash(call.result)
311
+ !equal(self.expectedResult, call.result)
316
312
  })
317
313
  },
318
314
 
@@ -322,7 +318,7 @@
322
318
  return any(this.calls, function(call){
323
319
  return self.expectedResult.an_instance_of ?
324
320
  call.result.constructor == self.expectedResult.an_instance_of:
325
- hash(self.expectedResult) == hash(call.result)
321
+ equal(self.expectedResult, call.result)
326
322
  })
327
323
  },
328
324
 
@@ -346,7 +342,7 @@
346
342
  if (arg == null) return call.args[i] == null
347
343
  return arg.an_instance_of ?
348
344
  call.args[i].constructor != arg.an_instance_of:
349
- hash(arg) != hash(call.args[i])
345
+ !equal(arg, call.args[i])
350
346
 
351
347
  })
352
348
  })
@@ -359,7 +355,7 @@
359
355
  return any(self.expectedArgs, function(i, arg){
360
356
  return arg.an_instance_of ?
361
357
  call.args[i].constructor == arg.an_instance_of:
362
- hash(arg) == hash(call.args[i])
358
+ equal(arg, call.args[i])
363
359
 
364
360
  })
365
361
  })
@@ -380,7 +376,8 @@
380
376
  // Report assertion results
381
377
 
382
378
  report : function() {
383
- this.passed ? ++JSpec.stats.passes : ++JSpec.stats.failures
379
+ if (JSpec.assert)
380
+ this.passed ? ++JSpec.stats.passes : ++JSpec.stats.failures
384
381
  return this
385
382
  },
386
383
 
@@ -506,14 +503,14 @@
506
503
 
507
504
  pass : function(message) {
508
505
  this.assertions.push({ passed: true, message: message })
509
- ++JSpec.stats.passes
506
+ if (JSpec.assert) ++JSpec.stats.passes
510
507
  },
511
508
 
512
509
  // Add failing assertion
513
510
 
514
511
  fail : function(message) {
515
512
  this.assertions.push({ passed: false, message: message })
516
- ++JSpec.stats.failures
513
+ if (JSpec.assert) ++JSpec.stats.failures
517
514
  },
518
515
 
519
516
  // Run deferred assertions
@@ -679,7 +676,7 @@
679
676
  /**
680
677
  * Include _object_ which may be a hash or Module instance.
681
678
  *
682
- * @param {has, Module} object
679
+ * @param {hash, Module} object
683
680
  * @return {JSpec}
684
681
  * @api public
685
682
  */
@@ -690,7 +687,7 @@
690
687
  if ('init' in module) module.init()
691
688
  if ('utilities' in module) extend(this.defaultContext, module.utilities)
692
689
  if ('matchers' in module) this.addMatchers(module.matchers)
693
- if ('formatters' in module) extend(this.formatters, module.formatters)
690
+ if ('reporters' in module) extend(this.reporters, module.reporters)
694
691
  if ('DSLs' in module)
695
692
  each(module.DSLs, function(name, methods){
696
693
  JSpec.DSLs[name] = JSpec.DSLs[name] || {}
@@ -711,7 +708,7 @@
711
708
  */
712
709
 
713
710
  hook : function(name, args) {
714
- args = argumentsToArray(arguments, 1)
711
+ args = toArray(arguments, 1)
715
712
  return inject(JSpec.modules, [], function(results, module){
716
713
  if (typeof module[name] == 'function')
717
714
  results.push(JSpec.evalHook(module, name, args))
@@ -805,7 +802,7 @@
805
802
  * @api public
806
803
  */
807
804
 
808
- argumentsToArray : function(arguments, offset) {
805
+ toArray : function(arguments, offset) {
809
806
  return Array.prototype.slice.call(arguments, offset || 0)
810
807
  },
811
808
 
@@ -842,7 +839,9 @@
842
839
  return 'expected ' + puts(actual) + ' to ' +
843
840
  (negate ? 'not ' : '') +
844
841
  name.replace(/_/g, ' ') +
845
- ' ' + puts.apply(this, expected.slice(1))
842
+ ' ' + (expected.length > 1 ?
843
+ puts.apply(this, expected.slice(1)) :
844
+ '')
846
845
  },
847
846
 
848
847
  /**
@@ -907,34 +906,35 @@
907
906
  return (value = query(key)) !== null ? value :
908
907
  JSpec.options[key] || null
909
908
  },
910
-
911
- /**
912
- * Generates a hash of the object passed.
913
- *
914
- * @param {object} object
915
- * @return {string}
916
- * @api private
917
- */
918
-
919
- hash : function(object) {
920
- if (object == null) return 'null'
921
- if (object == undefined) return 'undefined'
922
- function serialize(prefix) {
923
- return inject(object, prefix + ':', function(buffer, key, value){
924
- return buffer += hash(value)
925
- })
926
- }
927
- switch (object.constructor) {
928
- case Array : return serialize('a')
929
- case RegExp: return 'r:' + object.toString()
930
- case Number: return 'n:' + object.toString()
931
- case String: return 's:' + object.toString()
932
- case Object: return 'o:' + inject(object, [], function(array, key, value){
933
- array.push([key, hash(value)])
934
- }).sort()
935
- default: return object.toString()
936
- }
937
- },
909
+
910
+ /**
911
+ * Check if object _a_, is equal to object _b_.
912
+ *
913
+ * @param {object} a
914
+ * @param {object} b
915
+ * @return {bool}
916
+ * @api private
917
+ */
918
+
919
+ equal: function(a, b) {
920
+ if (typeof a != typeof b) return
921
+ if (a === b) return true
922
+ if (a instanceof RegExp)
923
+ return a.toString() === b.toString()
924
+ if (a instanceof Date)
925
+ return Number(a) === Number(b)
926
+ if (typeof a != 'object') return
927
+ if (a.length !== undefined)
928
+ if (a.length !== b.length) return
929
+ else
930
+ for (var i = 0, len = a.length; i < len; ++i)
931
+ if (!equal(a[i], b[i]))
932
+ return
933
+ for (var key in a)
934
+ if (!equal(a[key], b[key]))
935
+ return
936
+ return true
937
+ },
938
938
 
939
939
  /**
940
940
  * Return last element of an array.
@@ -957,30 +957,35 @@
957
957
  */
958
958
 
959
959
  puts : function(object) {
960
- if (arguments.length > 1) {
961
- return map(argumentsToArray(arguments), function(arg){
960
+ if (arguments.length > 1)
961
+ return map(toArray(arguments), function(arg){
962
962
  return puts(arg)
963
963
  }).join(', ')
964
- }
965
- if (object === undefined) return ''
964
+ if (object === undefined) return 'undefined'
966
965
  if (object === null) return 'null'
967
966
  if (object === true) return 'true'
968
967
  if (object === false) return 'false'
969
968
  if (object.an_instance_of) return 'an instance of ' + object.an_instance_of.name
970
- if (object.jquery && object.selector.length > 0) return 'selector ' + puts(object.selector) + ''
969
+ if (object.jquery && object.selector.length > 0) return 'selector ' + puts(object.selector)
971
970
  if (object.jquery) return object.get(0).outerHTML
972
971
  if (object.nodeName) return object.outerHTML
973
972
  switch (object.constructor) {
974
- case String: return "'" + object + "'"
975
- case Number: return object
976
973
  case Function: return object.name || object
974
+ case String:
975
+ return '"' + object
976
+ .replace(/"/g, '\\"')
977
+ .replace(/\n/g, '\\n')
978
+ .replace(/\t/g, '\\t')
979
+ + '"'
977
980
  case Array:
978
981
  return inject(object, '[', function(b, v){
979
982
  return b + ', ' + puts(v)
980
983
  }).replace('[,', '[') + ' ]'
981
984
  case Object:
985
+ object.__hit__ = true
982
986
  return inject(object, '{', function(b, k, v) {
983
- return b + ', ' + puts(k) + ' : ' + puts(v)
987
+ if (k == '__hit__') return b
988
+ return b + ', ' + k + ': ' + (v && v.__hit__ ? '<circular reference>' : puts(v))
984
989
  }).replace('{,', '{') + ' }'
985
990
  default:
986
991
  return object.toString()
@@ -1024,7 +1029,7 @@
1024
1029
  */
1025
1030
 
1026
1031
  does : function(actual, matcher, expected) {
1027
- var assertion = new JSpec.Assertion(JSpec.matchers[matcher], actual, argumentsToArray(arguments, 2))
1032
+ var assertion = new JSpec.Assertion(JSpec.matchers[matcher], actual, toArray(arguments, 2))
1028
1033
  return assertion.run().result
1029
1034
  },
1030
1035
 
@@ -1042,7 +1047,7 @@
1042
1047
 
1043
1048
  expect : function(actual) {
1044
1049
  assert = function(matcher, args, negate) {
1045
- var expected = argumentsToArray(args, 1)
1050
+ var expected = toArray(args, 1)
1046
1051
  matcher.negate = negate
1047
1052
  assertion = new JSpec.Assertion(matcher, actual, expected, negate)
1048
1053
  hook('beforeAssertion', assertion)
@@ -1114,17 +1119,20 @@
1114
1119
  /**
1115
1120
  * Iterate an object, invoking the given callback.
1116
1121
  *
1117
- * @param {hash, array, string} object
1122
+ * @param {hash, array} object
1118
1123
  * @param {function} callback
1119
1124
  * @return {JSpec}
1120
1125
  * @api public
1121
1126
  */
1122
1127
 
1123
1128
  each : function(object, callback) {
1124
- if (typeof object == 'string') object = object.split(' ')
1125
- for (key in object)
1126
- if (object.hasOwnProperty(key))
1127
- callIterator(callback, key, object[key])
1129
+ if (object.constructor == Array)
1130
+ for (var i = 0, len = object.length; i < len; ++i)
1131
+ callIterator(callback, i, object[i])
1132
+ else
1133
+ for (var key in object)
1134
+ if (object.hasOwnProperty(key))
1135
+ callIterator(callback, key, object[key])
1128
1136
  },
1129
1137
 
1130
1138
  /**
@@ -1326,7 +1334,7 @@
1326
1334
  var context = this.context || this.defaultContext
1327
1335
  var contents = this.contentsOf(body)
1328
1336
  hook('evaluatingBody', dsl, matchers, context, contents)
1329
- try { eval('with (dsl){ with (context) { with (matchers) { ' + contents + ' }}}') }
1337
+ try { with (dsl){ with (context) { with (matchers) { eval(contents) }}} }
1330
1338
  catch(e) { error(errorMessage, e) }
1331
1339
  },
1332
1340
 
@@ -1344,7 +1352,7 @@
1344
1352
  return input.
1345
1353
  replace(/\t/g, ' ').
1346
1354
  replace(/\r\n|\n|\r/g, '\n').
1347
- replace(/__END__[^]*/, '').
1355
+ split('__END__')[0].
1348
1356
  replace(/([\w\.]+)\.(stub|destub)\((.*?)\)$/gm, '$2($1, $3)').
1349
1357
  replace(/describe\s+(.*?)$/gm, 'describe($1, function(){').
1350
1358
  replace(/^\s+it\s+(.*?)$/gm, ' it($1, function(){').
@@ -1381,8 +1389,9 @@
1381
1389
  */
1382
1390
 
1383
1391
  report : function() {
1392
+ this.duration = Number(new Date) - this.start
1384
1393
  hook('reporting', JSpec.options)
1385
- new (JSpec.options.formatter || JSpec.formatters.DOM)(JSpec, JSpec.options)
1394
+ new (JSpec.options.reporter || JSpec.reporters.DOM)(JSpec, JSpec.options)
1386
1395
  },
1387
1396
 
1388
1397
  /**
@@ -1397,9 +1406,8 @@
1397
1406
  run : function(options) {
1398
1407
  if (any(hook('running'), haveStopped)) return this
1399
1408
  if (options) extend(this.options, options)
1400
- if (option('profile')) console.group('Profile')
1409
+ this.start = Number(new Date)
1401
1410
  each(this.suites, function(suite) { JSpec.runSuite(suite) })
1402
- if (option('profile')) console.groupEnd()
1403
1411
  return this
1404
1412
  },
1405
1413
 
@@ -1462,10 +1470,8 @@
1462
1470
 
1463
1471
  runSpec : function(spec) {
1464
1472
  this.currentSpec = spec
1465
- if (option('profile')) console.time(spec.description)
1466
1473
  try { this.evalBody(spec.body) }
1467
1474
  catch (e) { fail(e) }
1468
- if (option('profile')) console.timeEnd(spec.description)
1469
1475
  spec.runDeferredAssertions()
1470
1476
  destub()
1471
1477
  this.stats.specsFinished++
@@ -1588,8 +1594,7 @@
1588
1594
  */
1589
1595
 
1590
1596
  tryLoading : function(file) {
1591
- try { return JSpec.load(file) }
1592
- catch (e) {}
1597
+ try { return JSpec.load(file) } catch (e) {}
1593
1598
  },
1594
1599
 
1595
1600
  /**
@@ -1638,14 +1643,15 @@
1638
1643
  var main = this
1639
1644
  var find = JSpec.any
1640
1645
  var utils = 'haveStopped stub hookImmutable hook destub map any last pass fail range each option inject select \
1641
- error escape extend puts hash query strip color does addMatchers callIterator argumentsToArray'.split(/\s+/)
1642
- while (utils.length) util = utils.shift(), eval('var ' + util + ' = JSpec.' + util)
1646
+ error escape extend puts query strip color does addMatchers callIterator toArray equal'.split(/\s+/)
1647
+ while (utils.length) eval('var ' + utils[0] + ' = JSpec.' + utils.shift())
1643
1648
  if (!main.setTimeout) main.setTimeout = function(callback){ callback() }
1644
1649
 
1645
1650
  // --- Matchers
1646
1651
 
1647
1652
  addMatchers({
1648
1653
  equal : "===",
1654
+ eql : "equal(actual, expected)",
1649
1655
  be : "alias equal",
1650
1656
  be_greater_than : ">",
1651
1657
  be_less_than : "<",
@@ -1664,13 +1670,6 @@
1664
1670
  have_length : "actual.length == expected",
1665
1671
  be_within : "actual >= expected[0] && actual <= last(expected)",
1666
1672
  have_length_within : "actual.length >= expected[0] && actual.length <= last(expected)",
1667
-
1668
- eql : function(actual, expected) {
1669
- return actual.constructor == Array ||
1670
- actual instanceof Object ?
1671
- hash(actual) == hash(expected):
1672
- actual == expected
1673
- },
1674
1673
 
1675
1674
  receive : { defer : true, match : function(actual, method, times) {
1676
1675
  proxy = new JSpec.ProxyAssertion(actual, method, times, this.negate)
@@ -1701,7 +1700,7 @@
1701
1700
  break
1702
1701
 
1703
1702
  case Array:
1704
- state = any(actual, function(value){ return hash(value) == hash(arg) })
1703
+ state = any(actual, function(value){ return equal(value, arg) })
1705
1704
  break
1706
1705
  }
1707
1706
  if (!state) return false
@@ -1715,9 +1714,9 @@
1715
1714
  this.e = e
1716
1715
  var assert = function(arg) {
1717
1716
  switch (arg.constructor) {
1718
- case RegExp : return arg.test(e)
1717
+ case RegExp : return arg.test(e.message || e.toString())
1719
1718
  case String : return arg == (e.message || e.toString())
1720
- case Function : return (e.name || 'Error') == arg.name
1719
+ case Function : return e instanceof arg || e.name == arg.name
1721
1720
  }
1722
1721
  }
1723
1722
  return message ? assert(expected) && assert(message) :
@@ -1771,6 +1770,4 @@
1771
1770
  }
1772
1771
  })
1773
1772
 
1774
- if ('exports' in main) exports.JSpec = JSpec
1775
-
1776
1773
  })()