jspec 2.11.13 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  })()