gentooboontoo-jspec 4.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/History.md +840 -0
  2. data/Manifest +81 -0
  3. data/README.md +1039 -0
  4. data/Rakefile +28 -0
  5. data/bin/jspec +182 -0
  6. data/jspec.gemspec +44 -0
  7. data/lib/images/bg.png +0 -0
  8. data/lib/images/hr.png +0 -0
  9. data/lib/images/loading.gif +0 -0
  10. data/lib/images/sprites.bg.png +0 -0
  11. data/lib/images/sprites.png +0 -0
  12. data/lib/images/vr.png +0 -0
  13. data/lib/jspec.css +149 -0
  14. data/lib/jspec.growl.js +115 -0
  15. data/lib/jspec.jquery.js +88 -0
  16. data/lib/jspec.js +1908 -0
  17. data/lib/jspec.nodejs.js +18 -0
  18. data/lib/jspec.shell.js +39 -0
  19. data/lib/jspec.timers.js +154 -0
  20. data/lib/jspec.xhr.js +210 -0
  21. data/spec/commands/example_command.rb +19 -0
  22. data/spec/dom.html +33 -0
  23. data/spec/fixtures/test.html +1 -0
  24. data/spec/fixtures/test.json +1 -0
  25. data/spec/fixtures/test.xml +5 -0
  26. data/spec/node.js +19 -0
  27. data/spec/rhino.js +23 -0
  28. data/spec/ruby/bin/init_spec.rb +101 -0
  29. data/spec/ruby/bin/install_spec.rb +141 -0
  30. data/spec/ruby/bin/run_spec.rb +0 -0
  31. data/spec/ruby/bin/shell_spec.rb +13 -0
  32. data/spec/ruby/bin/spec_helper.rb +8 -0
  33. data/spec/ruby/bin/update_spec.rb +72 -0
  34. data/spec/server.html +29 -0
  35. data/spec/server.rb +2 -0
  36. data/spec/support/env.js +10118 -0
  37. data/spec/support/jquery.js +6240 -0
  38. data/spec/unit/helpers.js +64 -0
  39. data/spec/unit/spec.fixtures.js +24 -0
  40. data/spec/unit/spec.grammar-less.js +34 -0
  41. data/spec/unit/spec.grammar.js +275 -0
  42. data/spec/unit/spec.jquery.js +212 -0
  43. data/spec/unit/spec.jquery.xhr.js +103 -0
  44. data/spec/unit/spec.js +187 -0
  45. data/spec/unit/spec.matchers.js +577 -0
  46. data/spec/unit/spec.modules.js +51 -0
  47. data/spec/unit/spec.node.js +45 -0
  48. data/spec/unit/spec.shared-behaviors.js +279 -0
  49. data/spec/unit/spec.utils.js +355 -0
  50. data/spec/unit/spec.xhr.js +157 -0
  51. data/src/browsers.rb +305 -0
  52. data/src/helpers.rb +67 -0
  53. data/src/installables.rb +229 -0
  54. data/src/project.rb +340 -0
  55. data/src/routes.rb +61 -0
  56. data/src/server.rb +96 -0
  57. data/support/js.jar +0 -0
  58. data/templates/default/History.md +5 -0
  59. data/templates/default/Readme.md +29 -0
  60. data/templates/default/lib/yourlib.js +2 -0
  61. data/templates/default/spec/commands/example_command.rb +19 -0
  62. data/templates/default/spec/dom.html +22 -0
  63. data/templates/default/spec/node.js +10 -0
  64. data/templates/default/spec/rhino.js +10 -0
  65. data/templates/default/spec/server.html +18 -0
  66. data/templates/default/spec/server.rb +4 -0
  67. data/templates/default/spec/unit/spec.helper.js +0 -0
  68. data/templates/default/spec/unit/spec.js +8 -0
  69. data/templates/node/History.md +5 -0
  70. data/templates/node/Readme.md +29 -0
  71. data/templates/node/lib/yourlib.js +2 -0
  72. data/templates/node/spec/node.js +10 -0
  73. data/templates/node/spec/unit/spec.helper.js +0 -0
  74. data/templates/node/spec/unit/spec.js +8 -0
  75. data/templates/rails/commands/example_commands.rb +19 -0
  76. data/templates/rails/dom.html +22 -0
  77. data/templates/rails/rhino.js +10 -0
  78. data/templates/rails/server.html +18 -0
  79. data/templates/rails/server.rb +4 -0
  80. data/templates/rails/unit/spec.helper.js +0 -0
  81. data/templates/rails/unit/spec.js +8 -0
  82. metadata +227 -0
data/Manifest ADDED
@@ -0,0 +1,81 @@
1
+ History.md
2
+ Manifest
3
+ README.md
4
+ Rakefile
5
+ bin/jspec
6
+ jspec.gemspec
7
+ lib/images/bg.png
8
+ lib/images/hr.png
9
+ lib/images/loading.gif
10
+ lib/images/sprites.bg.png
11
+ lib/images/sprites.png
12
+ lib/images/vr.png
13
+ lib/jspec.css
14
+ lib/jspec.growl.js
15
+ lib/jspec.jquery.js
16
+ lib/jspec.js
17
+ lib/jspec.nodejs.js
18
+ lib/jspec.shell.js
19
+ lib/jspec.timers.js
20
+ lib/jspec.xhr.js
21
+ spec/commands/example_command.rb
22
+ spec/dom.html
23
+ spec/fixtures/test.html
24
+ spec/fixtures/test.json
25
+ spec/fixtures/test.xml
26
+ spec/node.js
27
+ spec/rhino.js
28
+ spec/ruby/bin/init_spec.rb
29
+ spec/ruby/bin/install_spec.rb
30
+ spec/ruby/bin/run_spec.rb
31
+ spec/ruby/bin/shell_spec.rb
32
+ spec/ruby/bin/spec_helper.rb
33
+ spec/ruby/bin/update_spec.rb
34
+ spec/server.html
35
+ spec/server.rb
36
+ spec/support/env.js
37
+ spec/support/jquery.js
38
+ spec/unit/helpers.js
39
+ spec/unit/spec.fixtures.js
40
+ spec/unit/spec.grammar-less.js
41
+ spec/unit/spec.grammar.js
42
+ spec/unit/spec.jquery.js
43
+ spec/unit/spec.jquery.xhr.js
44
+ spec/unit/spec.js
45
+ spec/unit/spec.matchers.js
46
+ spec/unit/spec.modules.js
47
+ spec/unit/spec.node.js
48
+ spec/unit/spec.shared-behaviors.js
49
+ spec/unit/spec.utils.js
50
+ spec/unit/spec.xhr.js
51
+ src/browsers.rb
52
+ src/helpers.rb
53
+ src/installables.rb
54
+ src/project.rb
55
+ src/routes.rb
56
+ src/server.rb
57
+ support/js.jar
58
+ templates/default/History.md
59
+ templates/default/Readme.md
60
+ templates/default/lib/yourlib.js
61
+ templates/default/spec/commands/example_command.rb
62
+ templates/default/spec/dom.html
63
+ templates/default/spec/node.js
64
+ templates/default/spec/rhino.js
65
+ templates/default/spec/server.html
66
+ templates/default/spec/server.rb
67
+ templates/default/spec/unit/spec.helper.js
68
+ templates/default/spec/unit/spec.js
69
+ templates/node/History.md
70
+ templates/node/Readme.md
71
+ templates/node/lib/yourlib.js
72
+ templates/node/spec/node.js
73
+ templates/node/spec/unit/spec.helper.js
74
+ templates/node/spec/unit/spec.js
75
+ templates/rails/commands/example_commands.rb
76
+ templates/rails/dom.html
77
+ templates/rails/rhino.js
78
+ templates/rails/server.html
79
+ templates/rails/server.rb
80
+ templates/rails/unit/spec.helper.js
81
+ templates/rails/unit/spec.js
data/README.md ADDED
@@ -0,0 +1,1039 @@
1
+ # JSpec
2
+
3
+ ## No Longer Supported
4
+
5
+ The JSpec library is no longer being supported. We recommend taking a look at [Jasmine](http://github.com/pivotal/jasmine)
6
+
7
+ JSpec is a minimalistic JavaScript behavior driven development framework,
8
+ providing **simple installation**, extremely **low learning curve**, absolutely **no pollution**
9
+ to core prototypes, async request support, and incredibly sexy syntax, tons of matchers
10
+ and **much more**.
11
+
12
+ ## Features
13
+
14
+ * Highly readable
15
+ * Framework / DOM independent
16
+ * Modular via JSpec Module's and hooks
17
+ * Mock Ajax Requests
18
+ * Rhino support
19
+ * Node.js support
20
+ * Async support
21
+ * Growl (unobtrustive notifications) support
22
+ * Fixture support
23
+ * Ruby JavaScript testing server
24
+ * Nested describes
25
+ * Does not pollute core object prototypes
26
+ * Cascading before/after/before_each/after_each hooks
27
+ * Extremely simple and intuitive matcher declaration
28
+ * Over 45 core matchers
29
+ * Allows parens to be optional when using matchers to increase readability
30
+ * Several helpful reporters (DOM, Terminal, ...)
31
+ * Assertion graphs displaying how many, and which assertions pass or failed
32
+ * Default / customizable evaluation contexts
33
+ * DOM sandbox support
34
+ * Great looking default DOM theme
35
+ * `jspec` command-line utility for auto-running specs, and initializing project templates
36
+ * Proxy or 'Spy' assertions
37
+ * Method Stubbing
38
+ * Shared behaviors
39
+ * Extend the jspec executable with project / user specific sub-commands.
40
+ * Profiling
41
+ * Interactive Shell
42
+ * Ruby on Rails Integration
43
+ * Install support projects with a single command (jQuery, Rhino, Prototype, Dojo, etc)
44
+ * Tiny (2000-ish LOC)
45
+
46
+ ## Companies Using JSpec
47
+
48
+ To add or request removal from this list please email tj@vision-media.ca
49
+
50
+ * [Apple](http://apple.com)
51
+ * [Google - YouTube](http://youtube.com)
52
+ * [Palm](http://palm.com)
53
+ * [Carfax](http://carfax.com)
54
+ * [Apache CouchDB](http://couchdb.apache.org)
55
+ * [Vision Media](http://vision-media.ca)
56
+
57
+ ## Installation
58
+
59
+ Simply download JSpec and include _JSpec.css_ and _JSpec.js_ in your markup.
60
+ Head over to the downloads section on Github, clone this public repo, or
61
+ add JSpec as a git submodule with in your project. Alternatively JSpec is
62
+ also available as a Ruby Gem (though this is not required), which also
63
+ provides the `jspec` executable. First install [Gemcutter](http://gemcutter.org/) then execute:
64
+ $ sudo gem install jspec
65
+
66
+ At which point you may:
67
+
68
+ $ jspec init myproject
69
+
70
+ By default, the command above will use absolute path for all JSpec library files.
71
+ This behavior can be a problem when you're working across different computers or
72
+ operating systems. You can freeze the library or symlink it.
73
+
74
+ $ jspec init myproject --freeze
75
+ $ jspec init myproject --symlink
76
+
77
+ JSpec scripts should NOT be referenced via the `<script>` tag, they should be
78
+ loaded using the exec method (**unless you are using the grammar-less alternative**).
79
+ Below is an example:
80
+
81
+ ...
82
+ <script>
83
+ function runSuites() {
84
+ JSpec
85
+ .exec('spec.core.js')
86
+ .exec('spec.jquery.js')
87
+ .run({ failuresOnly : true })
88
+ .report()
89
+ }
90
+ </script>
91
+ <body onLoad="runSuites()">
92
+ ...
93
+
94
+ You may optionally want to use sources in the _/pkg_ directory
95
+ for your project, since it includes compressed alternatives generated
96
+ each release.
97
+
98
+ ## Example
99
+
100
+ describe 'ShoppingCart'
101
+ before_each
102
+ cart = new ShoppingCart
103
+ end
104
+
105
+ describe 'addProducts'
106
+ it 'should add several products'
107
+ cart.addProduct('cookie')
108
+ cart.addProduct('icecream')
109
+ cart.should.have 2, 'products'
110
+ end
111
+ end
112
+
113
+ describe 'checkout'
114
+ it 'should throw an error when checking out with no products'
115
+ -{ cart.clear().checkout() }.should.throw_error EmptyCart
116
+ end
117
+ end
118
+ end
119
+
120
+ ## Grammar-less Example
121
+
122
+ JSpec's grammar is optional, you may also use the equivalent grammar-less
123
+ alternative below using pure JavaScript (when using the JSpec grammar you
124
+ may also use grammar-less assertions):
125
+
126
+ JSpec.describe('ShoppingCart', function(){
127
+ before_each(function{
128
+ cart = new ShoppingCart
129
+ })
130
+
131
+ describe('addProducts', function(){
132
+ it ('should add several products', function(){
133
+ cart.addProducts('cookie')
134
+ cart.addProducts('icecream')
135
+ expect(cart).to(have, 2, 'products')
136
+ })
137
+ })
138
+
139
+ describe('checkout', function(){
140
+ it ('should throw an error when checking out with no products', function(){
141
+ expect(function(){ cart.clear().checkout() }).to(throw_error, EmptyCart)
142
+ })
143
+ })
144
+ })
145
+
146
+ ## Options
147
+
148
+ The following options may be passed to _JSpec.run()_.
149
+
150
+ - fixturePath
151
+ - {string} path to fixture directory (DOM, Terminal, Server)
152
+ - failuresOnly
153
+ - {bool} displays only failing specs, making them quick to discover and fix (DOM, Terminal, Server)
154
+ - reportToId
155
+ - {string} an element id to report to when using the DOM reporter (DOM)
156
+ - verbose
157
+ - {bool} verbose server output, defaults to false (Server)
158
+
159
+ ## Matchers
160
+
161
+ ### Core
162
+
163
+ - equal, be
164
+ - ===
165
+ - be_a, be_an
166
+ - have constructor of x
167
+ - be_an_instance_of
168
+ - instanceof x
169
+ - be_at_least
170
+ - &gt;=
171
+ - be_at_most
172
+ - &lt;=
173
+ - be_null
174
+ - == null
175
+ - be_empty
176
+ - length &lt; 0 or {}
177
+ - be_true
178
+ - == true
179
+ - be_false
180
+ - == false
181
+ - be_type
182
+ - be type of x
183
+ - be_greater_than
184
+ - &gt;
185
+ - be_less_than
186
+ - &lt;
187
+ - be_undefined
188
+ - check if variable passed is undefined
189
+ - throw_error
190
+ - should throw an error, optionally supply the error string or regexp for message comparison
191
+ - have
192
+ - object should have n of property (person.should.have(2, 'pets'))
193
+ - have_at_least
194
+ - object should have at least n of property
195
+ - have_at_most
196
+ - object should have a maximum n of property
197
+ - have_within
198
+ - object should have within n..n of property (person.should.have_within(1..3, 'pets')
199
+ - have_length
200
+ - length of n
201
+ - have_prop
202
+ - object should have property x, optionally supplying an expected value
203
+ - have_property
204
+ - strict version of have_prop
205
+ - be_within
206
+ - checks if n is within the range passed
207
+ - include
208
+ - include substring, array element, or hash key
209
+ - match
210
+ - string should match regexp x
211
+ - respond_to
212
+ - property x should be a function
213
+ - eql
214
+ - matches simple literals (strings, numbers) with ==
215
+ However composites like arrays or 'hashes' are recursively matched,
216
+ meaning that [1, 2, [3]].should_eql([1, 2, [3]]) will be true.
217
+
218
+ ### jQuery
219
+
220
+ - have_tag, have_one
221
+ - have exactly one tag
222
+ - have_tags, have_many
223
+ - have more than one tag
224
+ - have_child
225
+ - have exactly one child
226
+ - have_children
227
+ - have more than one child
228
+ - have_text
229
+ - have plain text
230
+ - have_attr
231
+ - have an attribute, with optional value
232
+ - have_type
233
+ - have_id
234
+ - have_title
235
+ - have_alt
236
+ - have_href
237
+ - have_rel
238
+ - have_rev
239
+ - have_name
240
+ - have_target
241
+ - have_value
242
+ - have_class
243
+ - have_classes
244
+ - have_event_handlers
245
+ - be_visible
246
+ - be_hidden
247
+ - be_enabled
248
+ - be_disabled
249
+ - be_selected
250
+ - be_checked
251
+ - be_animated
252
+
253
+ ## Growl Support
254
+
255
+ JSpec uses the [JavaScript Growl](http://github.com/visionmedia/js-growl) library to provide
256
+ growl support when using the **Rhino JavaScript engine**. To enable simply `load()` _jspec.growl.js_
257
+ within _spec/rhino.js_
258
+
259
+ ## Async Support With Mock Timers
260
+
261
+ The javascript mock timers library is available at [http://github.com/visionmedia/js-mock-timers](http://github.com/visionmedia/js-mock-timers)
262
+ although it is already bundled with JSpec at _lib/jspec.timers.js_
263
+
264
+ Timers return ids and may be passed to `clearInterval()`, however
265
+ they do not execute in threads, they must be manually scheduled and
266
+ controlled via the `tick()` function.
267
+
268
+ setTimeout(function(){
269
+ alert('Wahoo!')
270
+ }, 400)
271
+
272
+ tick(200) // Nothing happens
273
+ tick(400) // Wahoo!
274
+
275
+ `setInterval()` works as expected, although it persists, where as `setTimeout()`
276
+ is destroyed after a single call. As conveyed by the last `tick()` call below,
277
+ a large increment in milliseconds may cause the callbacks to be called several times
278
+ to 'catch up'.
279
+
280
+ progress = ''
281
+ var id = setInterval(function(){
282
+ progress += '.'
283
+ }, 100)
284
+
285
+ tick(50), print(progress) // ''
286
+ tick(50), print(progress) // '.'
287
+ tick(100), print(progress) // '..'
288
+ tick(100), print(progress) // '...'
289
+ tick(300), print(progress) // '......'
290
+
291
+ clearInterval(id)
292
+
293
+ tick(800) // Nothing happens
294
+
295
+ You may also reset at any time using resetTimers()
296
+
297
+ ## Proxy Assertions
298
+
299
+ Proxy or 'Spy' assertions allow you to assert that a method is called n number
300
+ of times, with x arguments, returning x value. For example:
301
+
302
+ person = { getPets : function(species){ return ['izzy'] }}
303
+ person.should.receive('getPets', 'twice').with_args(an_instance_of(String))and_return(['izzy'])
304
+ person.getPets('dog') // This will pass
305
+ person.getPets() // This will fail because we asked an instance of String
306
+
307
+ This is a useful mechanism for testing the behavior of your object, as well as
308
+ how other methods may interact with it. Below is another example:
309
+
310
+ array = ['foo', 'bar']
311
+ array.should.receive('toString').and_return('foo,bar')
312
+ 'array: ' + array // This line causes the spec to pass due to calling toString()
313
+
314
+ For more examples view _spec/spec.matchers.js_
315
+
316
+ ## Method Stubbing
317
+
318
+ JSpec currently provides very simple stubbing support shown below:
319
+
320
+ person = { toString : function(){ return '<Person>' } }
321
+ stub(person, 'toString').and_return('Ive been stubbed!')
322
+
323
+ After each spec all stubs are restored to their original methods so
324
+ there is no reason to explicitly call `destub()`. To persist stubs,
325
+ use a before_each hook:
326
+
327
+ before_each
328
+ stub(someObject, 'method').and_return({ some : thing })
329
+ end
330
+
331
+ To destub a method simply call `destub()` at any time:
332
+
333
+ destub(person, 'toString')
334
+
335
+ If you would like to wipe an object clear of stubs simply pass it
336
+ to `destub()` without an additional method argument:
337
+
338
+ destub(person)
339
+
340
+ Alternatively both these utility functions may be called as methods
341
+ on any object when using the JSpec grammar:
342
+
343
+ someObject.stub('method').and_return('whatever')
344
+ // Converted to stub(someObject, 'method').and_return('whatever')
345
+
346
+ ## Helpers
347
+
348
+ * core
349
+
350
+ - an_instance_of
351
+ - used in conjunction with the 'receive' matcher
352
+
353
+ * jspec.xhr.js
354
+ - mockRequest, mock_request
355
+ - mock a request
356
+ - unmockRequest, unmock_request
357
+ - unmock requests
358
+ - lastRequest, last_request
359
+ - access previous request data
360
+
361
+ * jspec.jquery.js
362
+
363
+ - sandbox
364
+ - used to generate new DOM sandbox, using jQuery object
365
+ - element
366
+ - same as invoking jQuery, just reads better and no need to worry about $ collisions
367
+ - elements
368
+ - alias of element
369
+
370
+ ## Shared Behaviors
371
+
372
+ JSpec's support for shared behaviors allows multiple suites or describe blocks to share
373
+ common functionality, including specs and hooks. Shared functionality is run in the order in
374
+ which it is included in the hosting suite. For example a canine would inherit all
375
+ behavior of an animal, and particular breeds of dog would inherit all behavior from the canine.
376
+ Note that as in the poodle example, shared behaviors can be nested inside suites or describe
377
+ blocks and will be visible only to other describe blocks _at or below_ the same nesting level.
378
+
379
+ shared_behaviors_for 'animal'
380
+ before
381
+ animal = { eats: function(){return true }}
382
+ end
383
+
384
+ it 'should eat'
385
+ animal.eats().should.eql true
386
+ end
387
+ end
388
+
389
+ shared_behaviors_for 'canine'
390
+ should_behave_like('animal')
391
+
392
+ before
393
+ animal.hasFourLegs = function(){ return true }
394
+ animal.barks = function(){ return true }
395
+ end
396
+
397
+ it 'should have 4 legs'
398
+ animal.hasFourLegs().should.eql true
399
+ end
400
+
401
+ it 'should bark'
402
+ animal.barks().should.eql true
403
+ end
404
+ end
405
+
406
+ describe 'mastif'
407
+ should_behave_like('canine')
408
+
409
+ before
410
+ animal.weight = 200
411
+ end
412
+
413
+ it 'should weigh > 100 lbs'
414
+ animal.weight.should.be_greater_than 100
415
+ end
416
+ end
417
+
418
+ describe 'poodle breeds'
419
+ should_behave_like('canine')
420
+
421
+ shared_behaviors_for 'poodle'
422
+ before
423
+ animal.isMean = true
424
+ end
425
+
426
+ it 'should be mean'
427
+ animal.isMean.should.eql true
428
+ end
429
+ end
430
+
431
+ describe 'fancy poodle'
432
+ should_behave_like('poodle')
433
+
434
+ before
435
+ animal.looksRidiculous = true
436
+ end
437
+
438
+ it 'should look ridiculous'
439
+ animal.looksRidiculous.should.eql true
440
+ end
441
+ end
442
+ end
443
+
444
+ NOTE: When the should_behave_like() call is searching for behaviors to include, it works inside out.
445
+ Therefore any nested shared behaviors by the same name as a shared behavior at a higher
446
+ nesting level will override the one at the higher level.
447
+
448
+
449
+ ## Mock Ajax Requests
450
+
451
+ JSpec supports generic Ajax mocking which is usable with any JavaScript framework via _jspec.xhr.js_. The
452
+ API is comprised of two functions, `mock_request()` and `unmock_request()`. `unmock_request()` is
453
+ automatically called after each specification to restore the default functionality of XMLHttpRequest,
454
+ so it is uncommon to call `unmock_request()` directly. Below is a jQuery example:
455
+
456
+ it 'should mock requests'
457
+ mock_request().and_return('{ foo : "bar" }', 'application/json')
458
+ $.getJSON('foo', function(response, statusText){
459
+ response.foo.should.eql 'bar'
460
+ })
461
+ end
462
+
463
+ The mock_request().and_return signature is as follows:
464
+
465
+ mock_request().and_return(<data>, [content-type], [response-status-code], [headers-hash])
466
+
467
+ At the moment `mock_request()` itself does not accept any arguments, however in the future
468
+ this will be used to target specific URIs for mocking.
469
+
470
+ Also, if the content-type of response is specified as XML, as specified in the XMLHttpRequest
471
+ draft specification at : http://www.w3.org/TR/XMLHttpRequest/, the responseXML attribute of the response
472
+ will be an XML document generated by parsing the response body.
473
+
474
+ **NOTE**: works with Rhino as well
475
+
476
+ ## Hooks
477
+
478
+ Currently the following hooks are supported, and may be utilized any number of times as they
479
+ are simply pushed to a stack. So for instance you may have two before_each blocks within the same
480
+ scope, they will both run, but this can help keep your specs readable.
481
+
482
+ - before
483
+ - run once before the suite is executed
484
+ - after
485
+ - run once after the suite is executed
486
+ - before_each
487
+ - run before each specification
488
+ - after_each
489
+ - run after each specification
490
+ - before_nested
491
+ - run once before the suite and once before any nested suites
492
+ - after_nested
493
+ - run once after the suite and once after any nested suites
494
+
495
+ ## Custom Contexts
496
+
497
+ Custom contexts can be applied to supply helper
498
+ methods or properties to all subsequent bodies (other hooks, or specs).
499
+
500
+ Keep in mind that when replacing the default context you will loose
501
+ functionality provided by it, unless you manually merge it with your
502
+ custom context.
503
+
504
+ To reset the context simply assign null to obtain the original context.
505
+
506
+ ...
507
+ before
508
+ JSpec.context = { foo : 'bar' }
509
+ end
510
+
511
+ after
512
+ JSpec.context = null
513
+ end
514
+
515
+ it 'will work ;)'
516
+ foo.should_equal 'bar'
517
+ end
518
+ ...
519
+
520
+ ## Async Support
521
+
522
+ Currently only _jspec.jquery.js_ supports async requests. JSpec uses `jQuery.ajaxSetup` and sets all
523
+ requests to sync, which preserves execution order, and reports correctly.
524
+
525
+ it 'should load mah cookies (textfile)'
526
+ $.post('async', function(text){
527
+ text.should_eql 'cookies!'
528
+ })
529
+ end
530
+
531
+ ## Grammar Pre-processor
532
+
533
+ The pre-processing capability of JSpec is extremely powerful. Your JavaScript
534
+ code is not necessarily what it seems. For example when you seemingly invoke a
535
+ object's prototype like below:
536
+
537
+ 'foobar'.should.include 'bar'
538
+
539
+ First parens are added:
540
+
541
+ 'foobar'.should.include('bar')
542
+
543
+ Secondly the matcher invocation is converted to a non-polluting match() call:
544
+
545
+ expect('foobar').to(include, 'bar')
546
+
547
+ This also means instead of:
548
+
549
+ var object = { foo : 'bar' }
550
+ object.should.include 'foo'
551
+
552
+ We can do:
553
+
554
+ { foo : 'bar' }.should.include 'foo'
555
+
556
+ ### Closure Literal
557
+
558
+ These are equivalent:
559
+
560
+ -{ throw 'test' }.should.throw_error
561
+ function() { throw 'test' }.should.throw_error
562
+
563
+ ### Inclusive Range Literal
564
+
565
+ The following expands to the array of [1,2,3,4,5]
566
+
567
+ n.should.be_within 1..5
568
+
569
+ ### __END__
570
+
571
+ Any text placed after **__END__** is considered irrelevant and
572
+ is striped out before evaluation. This is sometimes useful for
573
+ document or code reference while writing specs.
574
+
575
+ For example when writing regression specs it is sometimes useful
576
+ to paste the issue ticket's comment(s) below this area for reference.
577
+
578
+ ## Formatters
579
+
580
+ To change a reporter simply alter the options hash like below, assigning
581
+ a new constructor, or pass it within the hash to `run()`:
582
+
583
+ JSpec.options.reporter = JSpec.reporters.Terminal
584
+
585
+ OR
586
+
587
+ JSpec
588
+ .exec('...')
589
+ .run({ reporter: JSpec.reporters.Terminal })
590
+ .report()
591
+
592
+ ## Fixtures
593
+
594
+ The `fixture()` utility function may be used in order to load arbitrary file contents
595
+ for use with your specifications. JSpec will resolve `fixture('data')` in the following
596
+ manor:
597
+
598
+ - <fixturePath>/data
599
+ - <fixturePath>/data.html
600
+
601
+ In order for the `fixture()` utility to function you must pass the **fixturePath** option
602
+ to _JSpec.run()_ which provides JSpec with the fixture directory.
603
+
604
+ The `json_fixture()` utility works much the same as `fixture()` however `fixture('data')`
605
+ will be parsed as JSON, and resolved as shown below:
606
+
607
+ - <fixturePath>/data
608
+ - <fixturePath>/data.json
609
+
610
+ ## Testing DOM Elements
611
+
612
+ When using jQuery testing DOM elements is very easy. Many may think they require specific
613
+ sandbox divs in their html, however you do not. Using the fixture support mentioned above
614
+ you may simply load some HTML, and use the `elements()` utility which is an alias of jQuery:
615
+
616
+ describe 'JSpec DOM testing'
617
+ describe 'is so easy'
618
+ before_each
619
+ list = elements(fixture('users-list'))
620
+ // or list = jQuery(fixture('users-list'))
621
+ // or list = $(fixture('users-list'))
622
+ end
623
+
624
+ it 'should have users'
625
+ list.should.have_tag 'ul'
626
+ end
627
+ end
628
+ end
629
+
630
+ You may also use simple strings, since jQuery's constructor will convert them to DOM elements:
631
+
632
+ describe 'Something'
633
+ before_each
634
+ html = elements('<p>Foo</p>')
635
+ // or html = $('<p>Foo</p>') ...
636
+ end
637
+
638
+ it 'should do something'
639
+ html.should.have_text 'Foo'
640
+ end
641
+ end
642
+
643
+ ## Custom Matchers
644
+
645
+ First lets create a simple equality matcher. In the case below JSpec is smart enough to realize
646
+ this is simply a binary operator, and simply transforms this into `actual === expected`
647
+
648
+ JSpec.addMatchers({
649
+ equal : '==='
650
+ })
651
+
652
+ To alias a method to keep your specs readable you may alias them like below:
653
+
654
+ JSpec.addMatchers({
655
+ be : 'alias equal'
656
+ })
657
+
658
+ 'foo'.should.equal 'foo'
659
+ true.should.be true
660
+
661
+ Matchers with string bodies implicitly return the expression value.
662
+ The expanded version of the equal matcher would then be:
663
+
664
+ JSpec.addMatchers({
665
+ equal : 'actual === expected'
666
+ })
667
+
668
+ Large matchers or those which require several parameters may wish
669
+ to utilize the hash method:
670
+
671
+ JSpec.addMatchers({
672
+ equal : { match : function(actual, expected){
673
+ return actual === expected
674
+ }}
675
+ })
676
+
677
+ To keep JSpec tiny, JSpec will default to generating failure messages
678
+ for you, how ever this can be explicitly defined:
679
+
680
+ JSpec.addMatchers({
681
+ equal : {
682
+ match : function(actual, expected){
683
+ return actual === expected
684
+ },
685
+ message : function(actual, expected, negate) {
686
+ return 'a message here'
687
+ }
688
+ }
689
+ })
690
+
691
+ When defining matchers that are extremely similar in functionality, however
692
+ require different names, you may use a prefixed list of words like below which
693
+ defines be_disabled, be_selected, be_checked, and have_type, have_id, etc. Each
694
+ function must return the matcher body which will be used.
695
+
696
+ JSpec.addMatchers({
697
+ 'be disabled selected checked' : function(attr) {
698
+ return 'jQuery(actual).attr("' + attr + '")'
699
+ },
700
+
701
+ 'have type id title alt href src sel rev name target' : function(attr) {
702
+ return function(actual, value) {
703
+ return value ? jQuery(actual).attr(attr) ## value:
704
+ jQuery(actual).attr(attr)
705
+ }
706
+ }
707
+ })
708
+
709
+ ## Extending Or Hooking Into JSpec
710
+
711
+ JSpec provides a hook architecture for extending or analyzing various
712
+ points in its execution, through the use of modules. For a module
713
+ example view _lib/jspec.jquery.js_.
714
+
715
+ The following methods or properties are utilized by JSpec:
716
+
717
+ - name : module name string
718
+ - init : called to initialize a module
719
+ - reporters : hash of reporters merged with JSpec.reporters
720
+ - utilities : hash of utility functions merged with JSpec.defaultContext
721
+ - matchers : hash of matchers merged with JSpec's core matchers via JSpec.addMatchers()
722
+ - DSLs : hash of DSL methods; for example DSLs.snake contains before_each, after_each, etc.
723
+ Where as DSLs.camel may contain beforeEach, afterEach, etc.
724
+
725
+ Below is a list of hooks, descriptions, and valid return values which
726
+ may simply be implemented as module methods. beforeSuite, afterSuite, beforeSpec, and afterSpec have lower
727
+ precedence than before_each, after_each etc within the specs themselves, allowing them to override or undo
728
+ anything that has been done by a Module.
729
+
730
+ - running(options) : started running JSpec with the options passed : returning 'stop' will halt running
731
+ - loading(file) : loading a file : returning 'stop' will prevent loading
732
+ - executing(file) : executing a file : returning 'stop' will prevent execution
733
+ - posting(data, url) : posting data to a url : returning 'stop' will prevent request
734
+ - preprocessing(input) : before input string is preprocessed : return input string for next hook to preprocess
735
+ - stubbing(object, method, result) : called when stubbing an object's method, and return value (result). : (no return value)
736
+ - requiring(dependency, message) : requiring a dependency : (no return value)
737
+ - beforeAssertion(assertion) : before an assertion has been made : (no return value)
738
+ - afterAssertion(assertion) : after an assertion has been made : (no return value)
739
+ - addingMatcher(name, body) : unprocessed matcher name and body : (no return value)
740
+ - addingSuite(suite) : adding Suite instance to JSpec : (no return value)
741
+ - beforeSuite(suite) : before running of suite (describe block) : (no return value)
742
+ - afterSuite(suite) : after running of suite (describe block) : (no return value)
743
+ - beforeSpec(spec) : before running of spec (it block) : (no return value)
744
+ - afterSpec(spec) : after running of spec (it block) : (no return value)
745
+ - reporting(options) : called before reporting : (no return value)
746
+ - evaluatingBody(dsl, matchers, context, contents) : evaluating body contents, with the given context, matchers and dsl. : (no return value)
747
+
748
+ For example you may wish to proxy files which are being executed, simply implement the
749
+ executing method like below. This example will stop execution of any file matching /matchers/.
750
+
751
+ MyModule = {
752
+ executing : function(file) {
753
+ if (file.match(/matchers/))
754
+ return 'stop'
755
+ }
756
+ }
757
+ JSpec.include(MyModule)
758
+
759
+ Immutable values may also be passed to hooks using hookImmutable() internally. This allows
760
+ for simple numbers, strings, etc to be utilized or altered within a hook implementation. Below
761
+ is an example module which adds functionality to the JSpec grammar by converting `SomeObject.stub('method')`
762
+ to `stub(SomeObject, 'method')`:
763
+
764
+ JSpec.include({
765
+ preprocessing : function(input) {
766
+ return input.replace(/(\w+)\.(stub|destub)\((.*?)\)$/gm, '$2($1, $3)')
767
+ }
768
+ })
769
+
770
+ ## JSpec Command-line Utility
771
+
772
+ When installed as a Ruby Gem, the `jspec` executable will become available,
773
+ allowing you to initialize project templates quickly, as well as auto-testing
774
+ specifications when a file is altered.
775
+
776
+ Initialize JSpec-driven project template in directory _myproject_:
777
+ $ jspec init myproject
778
+
779
+ Once within 'myproject' start testing by executing:
780
+ $ jspec
781
+
782
+ For additional usage execute:
783
+ $ jspec help
784
+
785
+ Or for specific usage:
786
+ $ jspec help run
787
+
788
+ ## Extending JSpec's Executable
789
+
790
+ Both project specific, and user specific sub-commands may be used to
791
+ extend those already provided by `jspec`. For example create the following
792
+ in spec/commands/example_command.rb which are loaded when `jspec` is executed.
793
+
794
+ command :example do |c|
795
+ c.syntax = 'jspec example [options]'
796
+ c.description = 'Just an example command'
797
+ c.option '-f', '--foo string', 'Does some foo with <string>'
798
+ c.option '-b', '--bar [string]', 'Does some bar with [string]'
799
+ c.example 'Do some foo', 'jspec example --foo bar'
800
+ c.example 'Do some bar', 'jspec example --bar'
801
+ c.when_called do |args, options|
802
+ p args
803
+ p options.__hash__
804
+ # options.foo
805
+ # options.bar
806
+ # options.__hash__[:foo]
807
+ # options.__hash__[:bar]
808
+ end
809
+ end
810
+
811
+ And execute with:
812
+
813
+ `$ jspec example`
814
+
815
+ They may also be placed at ~/jspec/commands for global usage.
816
+
817
+ For more information on the command creation visit http://visionmedia.github.com/commander
818
+
819
+ ## Installing Support Projects
820
+
821
+ Lets say you need jQuery for your project, and wish to test against it. You could download
822
+ jQuery manually, use an absolute uri to Google's CDN, or use the following command, which will
823
+ install jQuery to _spec/support/jquery.js_.
824
+ $ jspec install jquery
825
+
826
+ Alternatively we may specify the destination path:
827
+ $ jspec install jquery spec/jquery.js
828
+
829
+ Or provide a specific version string:
830
+ $ jspec install jquery --release 1.3.1
831
+
832
+ The install command will also install Rhino for you (**MacOS only**) so you
833
+ can run specs, and js via the command-line.
834
+ $ jspec install rhino
835
+
836
+ To view the current projects supported view:
837
+ $ jspec help install
838
+
839
+ ## Rhino
840
+
841
+ JSpec provides transparent support for Rhino, while using the Terminal reporter.
842
+ Simply create a JavaScript file with contents similar to below, and then execute
843
+ the command following it:
844
+
845
+ load('lib/jspec.js')
846
+
847
+ JSpec
848
+ .exec('spec/spec.grammar.js')
849
+ .exec('spec/spec.core.js')
850
+ .run({ reporter: JSpec.reporters.Terminal, failuresOnly: true })
851
+ .report()
852
+
853
+ Initialize project with:
854
+ $ jspec init myproject
855
+
856
+ Run with:
857
+ $ jspec run --rhino
858
+
859
+ Or bind (automated testing):
860
+ $ jspec --rhino
861
+
862
+ ## Server
863
+
864
+ The Ruby JavaScript testing server included with JSpec simply runs
865
+ the spec suites within each browser you specify, while reporting result
866
+ back to the terminal. It is essentially the same as using the DOM reporter
867
+ and auto-testing each browser, however results are centralized to the terminal,
868
+ removing the need to manually view each browser's output.
869
+
870
+ When utilizing the server if a file named _spec/jspec.rb_ (or _jspec/jspec.rb_ for rails)
871
+ is present, then it will be loaded before the server is started. This allows you to
872
+ add Sinatra routes, support additional Browsers, etc.
873
+
874
+ Run with all supported browsers:
875
+ $ jspec run --server
876
+
877
+ Run with specific browsers:
878
+ $ jspec run --browsers Safari,Firefox,Chrome,Explorer
879
+
880
+ Run with alternative browser names:
881
+ $ jspec run --browsers safari,ff,chrome,ie
882
+
883
+ Browsers supported in core:
884
+
885
+ - Browser::Default (system default)
886
+ - Browser::Safari
887
+ - Browser::WebKit
888
+ - Browser::Chrome
889
+ - Browser::Firefox
890
+ - Browser::Opera
891
+ - Browser::IE
892
+
893
+ Supplied routes:
894
+
895
+ - /slow/NUMBER
896
+ - /status/NUMBER
897
+
898
+ For example `$.get('/slow/4', function(){})` will take 4 seconds
899
+ to reply, where as `$.get('/status/404', function(){})` will respond
900
+ with an 404 status code. Add additional Sinatra routes to the jspec.rb
901
+ file to add your own functionality.
902
+
903
+ ## Interactive Shell
904
+
905
+ JSpec provides an interactive shell through Rhino, utilize with:
906
+
907
+ $ jspec shell
908
+
909
+ Or to specify additional files to load:
910
+
911
+ $ jspec shell lib/*.js
912
+
913
+ Or view additional shell help
914
+
915
+ $ jspec help shell
916
+
917
+ When running the shell JSpec provides several commands:
918
+
919
+ - quit, exit
920
+ - Terminate the shell session
921
+ - p()
922
+ - Inspect the object passed
923
+
924
+ Or add your own. In the examples below, `foo` will become a getter, so it can
925
+ be invoked simply as `$ foo ` where as `bar` is a regular function which must be called
926
+ as `$ bar("something") `.
927
+
928
+ Shell.commands.foo = ['Does some foo', function(){ return 'something' }]
929
+ Shell.commands.bar = ['Does some bar', function(o){ return 'something' }]
930
+
931
+ ## Ruby on Rails
932
+
933
+ No additional gems are required for JSpec to work with rails, although
934
+ [jspec-rails](http://github.com/bhauman/jspec-rails) has been created by 'bhauman'. JSpec
935
+ supports Rails out of the box, simply execute:
936
+
937
+ $ jspec init --rails
938
+
939
+ Then while still in the root directory of your Rails project, run the following
940
+ command which will bind to, and refresh your browsers automatically when any changes
941
+ are made to _./public/javascripts/*.js_ or _./jspec/*.js_
942
+
943
+ $ jspec
944
+
945
+ Or just like regular JSpec applications, run once:
946
+
947
+ $ jspec run
948
+
949
+ Or run via the terminal using Rhino:
950
+
951
+ $ jspec run --rhino
952
+
953
+ ## Supported Browsers
954
+
955
+ Browsers below are supported and can be found in _server/browsers.rb_, however
956
+ your _spec/server.rb_ file may support additional browsers.
957
+
958
+ - Safari
959
+ - WebKit
960
+ - Chrome
961
+ - Firefox
962
+ - Opera
963
+ - Internet Explorer
964
+
965
+ ## Known Issues
966
+
967
+ - The preprocessor is not (yet) capable of multiline conversions. For example the following is invalid
968
+
969
+ object.stub('getContentsOfURL').and_return(function(url){
970
+ return 'html'
971
+ })
972
+
973
+ In cases such as this, you may always revert to utilizing JSpec in a grammar-less form as follows:
974
+
975
+ stub(object, 'getContentsOfURL').and_return(function(url){
976
+ return 'html'
977
+ })
978
+
979
+ ## Additional JSpec Modules
980
+
981
+ - JSocka stubbing http://github.com/gisikw/jsocka/tree/master
982
+
983
+ ## More Information
984
+
985
+ - [Google Group](http://groups.google.com/group/jspec)
986
+ - IRC Channel [irc://irc.freenode.net#jspec](irc://irc.freenode.net#jspec)
987
+ - Featured in Devmag ["Advanced JavaScript"](http://www.dev-mag.com/2010/02/18/advanced-javascript/) ebook for 4$
988
+ - Featured article in JSMag [http://www.jsmag.com/main.issues.description/id=21/](http://www.jsmag.com/main.issues.description/id=21/)
989
+ - Syntax comparison with other frameworks [http://gist.github.com/92283](http://gist.github.com/92283)
990
+ - Get the TextMate bundle at [https://github.com/visionmedia/jspec.tmbundle/tree](https://github.com/visionmedia/jspec.tmbundle/tree)
991
+ - For more information consult the JSpec source code documentation or visit [http://visionmedia.github.com/jspec](http://visionmedia.github.com/jspec)
992
+ - jQuery + HTML fixture example [http://gist.github.com/147831](http://gist.github.com/147831)
993
+ - [http://twitter.com/tjholowaychuk](Twitter)
994
+ - [JSpec Vim Snippits](http://github.com/tobiassvn/snipmate-jspec/)
995
+
996
+ ## Contributors
997
+
998
+ Many ideas and bug reports were contributed by
999
+ the following developers, thank you for making
1000
+ JSpec more enjoyable, and bug free. If I have
1001
+ missed you on this list please let me know
1002
+ (aka the fellow who donated [jspec.info](http://jspec.info))
1003
+
1004
+ - Lawrence Pit
1005
+ - [mpd@jesters-court.ne](mpd@jesters-court.ne)
1006
+ - [Sarah Brown](brown.sarah.v@gmail.com)
1007
+ - [kevin.gisi@gmail.com](kevin.gisi@gmail.com)
1008
+ - [tony_t_tubbs@yahoo.com](tony_t_tubbs@yahoo.com)
1009
+ - [enno84@gmx.net](enno84@gmx.net)
1010
+ - swalke16
1011
+ - fnando
1012
+ - Tobias Svensson
1013
+
1014
+ ## License
1015
+
1016
+ (The MIT License)
1017
+
1018
+ Copyright (c) 2008 - 2010 TJ Holowaychuk <tj@vision-media.ca>
1019
+
1020
+ Permission is hereby granted, free of charge, to any person obtaining
1021
+ a copy of this software and associated documentation files (the
1022
+ 'Software'), to deal in the Software without restriction, including
1023
+ without limitation the rights to use, copy, modify, merge, publish,
1024
+ distribute, sublicense, and/or sell copies of the Software, and to
1025
+ permit persons to whom the Software is furnished to do so, subject to
1026
+ the following conditions:
1027
+
1028
+ The above copyright notice and this permission notice shall be
1029
+ included in all copies or substantial portions of the Software.
1030
+
1031
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
1032
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1033
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1034
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1035
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
1036
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1037
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1038
+
1039
+