jspec 2.11.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/History.rdoc +522 -0
  2. data/Manifest +57 -0
  3. data/README.rdoc +825 -0
  4. data/Rakefile +75 -0
  5. data/bin/jspec +305 -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 +145 -0
  14. data/lib/jspec.jquery.js +71 -0
  15. data/lib/jspec.js +1771 -0
  16. data/lib/jspec.shell.js +36 -0
  17. data/lib/jspec.timers.js +90 -0
  18. data/lib/jspec.xhr.js +183 -0
  19. data/server/browsers.rb +228 -0
  20. data/server/helpers.rb +82 -0
  21. data/server/routes.rb +57 -0
  22. data/server/server.rb +88 -0
  23. data/spec/async +1 -0
  24. data/spec/env.js +695 -0
  25. data/spec/fixtures/test.html +1 -0
  26. data/spec/fixtures/test.json +1 -0
  27. data/spec/fixtures/test.xml +5 -0
  28. data/spec/helpers.js +66 -0
  29. data/spec/server.rb +2 -0
  30. data/spec/spec.dom.html +34 -0
  31. data/spec/spec.fixtures.js +18 -0
  32. data/spec/spec.grammar-less.js +34 -0
  33. data/spec/spec.grammar.js +226 -0
  34. data/spec/spec.jquery.js +176 -0
  35. data/spec/spec.jquery.xhr.js +65 -0
  36. data/spec/spec.js +166 -0
  37. data/spec/spec.matchers.js +493 -0
  38. data/spec/spec.modules.js +67 -0
  39. data/spec/spec.node.js +46 -0
  40. data/spec/spec.rhino.js +17 -0
  41. data/spec/spec.server.html +29 -0
  42. data/spec/spec.shared-behaviors.js +80 -0
  43. data/spec/spec.utils.js +279 -0
  44. data/spec/spec.xhr.js +156 -0
  45. data/templates/default/History.rdoc +4 -0
  46. data/templates/default/README.rdoc +29 -0
  47. data/templates/default/lib/yourlib.core.js +2 -0
  48. data/templates/default/spec/server.rb +4 -0
  49. data/templates/default/spec/spec.core.js +8 -0
  50. data/templates/default/spec/spec.dom.html +20 -0
  51. data/templates/default/spec/spec.rhino.js +8 -0
  52. data/templates/default/spec/spec.server.html +16 -0
  53. data/templates/rails/server.rb +4 -0
  54. data/templates/rails/spec.application.js +8 -0
  55. data/templates/rails/spec.dom.html +20 -0
  56. data/templates/rails/spec.rhino.js +8 -0
  57. data/templates/rails/spec.server.html +16 -0
  58. metadata +168 -0
data/README.rdoc ADDED
@@ -0,0 +1,825 @@
1
+
2
+ = JSpec
3
+
4
+ JSpec is a minimalistic JavaScript behavior driven development framework,
5
+ providing simple installation, extremely low learning curve, absolutely no pollution
6
+ to core prototypes, async request support, and incredibly sexy syntax, tons of matchers
7
+ and much more.
8
+
9
+ == Features
10
+
11
+ * Highly readable
12
+ * Framework / DOM independent
13
+ * Modular via JSpec Module's and hooks
14
+ * Mock Ajax Requests
15
+ * Rhino support
16
+ * Node.js support
17
+ * Async support
18
+ * Fixture support
19
+ * Ruby JavaScript testing server
20
+ * Nested describes
21
+ * Does not pollute core object prototypes
22
+ * Cascading before/after/before_each/after_each hooks
23
+ * Extremely simple and intuitive matcher declaration
24
+ * Over 45 core matchers
25
+ * Allows parens to be optional when using matchers to increase readability
26
+ * Several helpful formatters (DOM, Console, Terminal, ...)
27
+ * Assertion graphs displaying how many, and which assertions pass or failed
28
+ * Default / customizable evaluation contexts
29
+ * DOM sandbox support
30
+ * Great looking default DOM theme
31
+ * `jspec` command-line utility for auto-running specs, and initializing project templates
32
+ * Proxy or 'Spy' assertions
33
+ * Method Stubbing
34
+ * Shared behaviors
35
+ * Profiling
36
+ * Interactive Shell
37
+ * Ruby on Rails Integration
38
+ * Tiny (15 kb compressed, 1300-ish LOC)
39
+
40
+ == Installation
41
+
42
+ Simply download JSpec and include JSpec.css and JSpec.js in your markup.
43
+ Head over to the downloads section on Github, clone this public repo, or
44
+ add JSpec as a git submodule with in your project. Alternatively JSpec is
45
+ also available as a Ruby Gem (though this is not required), which also
46
+ provides the `jspec` executable. To install execute:
47
+ $ gem sources -a http://gems.github.com (if you have not previously done so)
48
+ $ sudo gem install visionmedia-jspec
49
+
50
+ At which point you may:
51
+ $ jspec init myproject
52
+
53
+ By default, the command above will use absolute path for all JSpec library files.
54
+ This behavior can be a problem when you're working across different computers or
55
+ operating systems. You can freeze the library or symlink it.
56
+
57
+ $ jspec init myproject --freeze
58
+ $ jspec init myproject --symlink
59
+
60
+ JSpec scripts should NOT be referenced via the <script> tag, they should be
61
+ loaded using the exec method (unless you are using the grammar-less alternative).
62
+ Below is an example:
63
+
64
+ ...
65
+ <script>
66
+ function runSuites() {
67
+ JSpec
68
+ .exec('spec.core.js')
69
+ .exec('spec.jquery.js')
70
+ .run({ failuresOnly : true })
71
+ .report()
72
+ }
73
+ </script>
74
+ <body onLoad="runSuites()">
75
+ ...
76
+
77
+ You may optionally want to use sources in the /pkg directory
78
+ for your project, since it includes compressed alternatives generated
79
+ each release.
80
+
81
+ == Example
82
+
83
+ describe 'ShoppingCart'
84
+ before_each
85
+ cart = new ShoppingCart
86
+ end
87
+
88
+ describe 'addProducts'
89
+ it 'should add several products'
90
+ cart.addProduct('cookie')
91
+ cart.addProduct('icecream')
92
+ cart.should.have 2, 'products'
93
+ end
94
+ end
95
+
96
+ describe 'checkout'
97
+ it 'should throw an error when checking out with no products'
98
+ -{ cart.clear().checkout() }.should.throw_error EmptyCart
99
+ end
100
+ end
101
+ end
102
+
103
+ == Grammar-less Example
104
+
105
+ JSpec's grammar is optional, you may also use the equivalent grammar-less
106
+ alternative below using pure JavaScript (when using the JSpec grammar you
107
+ may also use grammar-less assertions):
108
+
109
+ JSpec.describe('ShoppingCart', function(){
110
+ before_each(function{
111
+ cart = new ShoppingCart
112
+ })
113
+
114
+ describe('addProducts', function(){
115
+ it ('should add several products', function(){
116
+ cart.addProducts('cookie')
117
+ cart.addProducts('icecream')
118
+ expect(cart).to(have, 2, 'products')
119
+ })
120
+ })
121
+
122
+ describe('checkout', function(){
123
+ it ('should throw an error when checking out with no products', function(){
124
+ expect(function(){ cart.clear().checkout() }).to(throw_error, EmptyCart)
125
+ })
126
+ })
127
+ })
128
+
129
+ == Options
130
+
131
+ You may alter the way JSpec operates by assigning options via the
132
+ JSpec.options hash, by passing string-based option values via the
133
+ query string, or passing a hash to run(). For example
134
+ JSpec.options.failuresOnly = true, and ?failuresOnly=1 will both work.
135
+
136
+ * profile {bool} when enabled, uses console.time() in order to display performance information in your console log as specs are completed. (DOM, Console)
137
+ * failuresOnly {bool} displays only failing specs, making them quick to discover and fix (DOM, Terminal, Server)
138
+ * reportToId {string} an element id to report to when using the DOM formatter (DOM)
139
+ * verbose {bool} verbose server output, defaults to false (Server)
140
+
141
+ == Matchers
142
+
143
+ * Core
144
+
145
+ - equal, be ===
146
+ - be_a, be_an have constructor of x
147
+ - be_an_instance_of instanceof x
148
+ - be_at_least >=
149
+ - be_at_most <=
150
+ - be_null == null
151
+ - be_empty length < 0 or {}
152
+ - be_true == true
153
+ - be_false == false
154
+ - be_type be type of x
155
+ - be_greater_than >
156
+ - be_less_than <
157
+ - be_undefined check if variable passed is undefined
158
+ - throw_error should throw an error, optionally supply the error string or regexp for message comparison
159
+ - have object should have n of property (person.should.have(2, 'pets'))
160
+ - have_at_least object should have at least n of property
161
+ - have_at_most object should have a maximum n of property
162
+ - have_within object should have within n..n of property (person.should.have_within(1..3, 'pets')
163
+ - have_length length of n
164
+ - have_prop object should have property x, optionally supplying an expected value
165
+ - have_property strict version of have_prop
166
+ - be_within checks if n is within the range passed
167
+ - include include substring, array element, or hash key
168
+ - match string should match regexp x
169
+ - respond_to property x should be a function
170
+ - eql matches simple literals (strings, numbers) with ==
171
+ However composites like arrays or 'hashes' are recursively matched,
172
+ meaning that [1, 2, [3]].should_eql([1, 2, [3]]) will be true.
173
+
174
+ * jQuery
175
+
176
+ - have_tag, have_one have exactly one tag
177
+ - have_tags, have_many have more than one tag
178
+ - have_child have exactly one child
179
+ - have_children have more than one child
180
+ - have_text have plain text
181
+ - have_attr have an attribute, with optional value
182
+ - have_type
183
+ - have_id
184
+ - have_title
185
+ - have_alt
186
+ - have_href
187
+ - have_rel
188
+ - have_rev
189
+ - have_name
190
+ - have_target
191
+ - have_value
192
+ - have_class
193
+ - have_classes
194
+ - be_visible
195
+ - be_hidden
196
+ - be_enabled
197
+ - be_disabled
198
+ - be_selected
199
+ - be_checked
200
+
201
+ == Async Support With Mock Timers
202
+
203
+ The javascript mock timers library is available at http://github.com/visionmedia/js-mock-timers
204
+ although it is already bundled with JSpec at lib/jspec.timers.js
205
+
206
+ Timers return ids and may be passed to clearInterval(), however
207
+ they do not execute in threads, they must be manually scheduled and
208
+ controlled via the tick() function.
209
+
210
+ setTimeout(function(){
211
+ alert('Wahoo!')
212
+ }, 400)
213
+
214
+ tick(200) // Nothing happens
215
+ tick(400) // Wahoo!
216
+
217
+ setInterval() works as expected, although it persists, where as setTimeout()
218
+ is destroyed after a single call. As conveyed by the last tick() call below,
219
+ a large increment in milliseconds may cause the callbacks to be called several times
220
+ to 'catch up'.
221
+
222
+ progress = ''
223
+ var id = setInterval(function(){
224
+ progress += '.'
225
+ }, 100)
226
+
227
+ tick(50), print(progress) // ''
228
+ tick(50), print(progress) // '.'
229
+ tick(100), print(progress) // '..'
230
+ tick(100), print(progress) // '...'
231
+ tick(300), print(progress) // '......'
232
+
233
+ clearInterval(id)
234
+
235
+ tick(800) // Nothing happens
236
+
237
+ You may also reset at any time using resetTimers()
238
+
239
+ == Proxy Assertions
240
+
241
+ Proxy or 'Spy' assertions allow you to assert that a method is called n number
242
+ of times, with x arguments, returning x value. For example:
243
+
244
+ person = { getPets : function(species){ return ['izzy'] }}
245
+ person.should.receive('getPets', 'twice').with_args(an_instance_of(String))and_return(['izzy'])
246
+ person.getPets('dog') // This will pass
247
+ person.getPets() // This will fail because we asked an instance of String
248
+
249
+ This is a useful mechanism for testing the behavior of your object, as well as
250
+ how other methods may interact with it. Below is another example:
251
+
252
+ array = ['foo', 'bar']
253
+ array.should.receive('toString').and_return('foo,bar')
254
+ 'array: ' + array // This line causes the spec to pass due to calling toString()
255
+
256
+ For more examples view spec/spec.matchers.js
257
+
258
+ == Method Stubbing
259
+
260
+ JSpec currently provides very simple stubbing support shown below:
261
+
262
+ person = { toString : function(){ return '<Person>' } }
263
+ stub(person, 'toString').and_return('Ive been stubbed!')
264
+
265
+ After each spec all stubs are restored to their original methods so
266
+ there is no reason to explicitly call destub(). To persist stubs,
267
+ use a before_each hook:
268
+
269
+ before_each
270
+ stub(someObject, 'method').and_return({ some : thing })
271
+ end
272
+
273
+ To destub a method simply call destub() at any time:
274
+
275
+ destub(person, 'toString')
276
+
277
+ If you would like to whipe an object clear of stubs simply pass it
278
+ to destub() without an additional method argument:
279
+
280
+ destub(person)
281
+
282
+ Alternatively both these utility functions may be called as methods
283
+ on any object when using the JSpec grammar:
284
+
285
+ someObject.stub('method').and_return('whatever')
286
+ // Converted to stub(someObject, 'method').and_return('whatever')
287
+
288
+ == Helpers
289
+
290
+ * Core
291
+
292
+ - an_instance_of used in conjunction with the 'receive' matcher
293
+ - mockRequest, mock_request mock a request (requires jspec.xhr.js)
294
+ - unmockRequest, unmock_request unmock requests (requests jspec.xhr.js)
295
+
296
+ * jQuery
297
+
298
+ - sandbox used to generate new DOM sandbox, using jQuery object
299
+ - element same as invoking jQuery, just reads better and no need to worry about $ collisions
300
+ - elements alias of element
301
+
302
+ == Shared Behaviors
303
+
304
+ JSpec's support for shared behaviors allows multiple suites or describe blocks to share
305
+ common functionality. For example an Admin, would inherit all specs of User:
306
+
307
+ describe 'User'
308
+ before
309
+ User = function(name) { this.name = name }
310
+ user = new User('joe')
311
+ end
312
+
313
+ it 'should have a name'
314
+ user.should.have_property 'name'
315
+ end
316
+
317
+ describe 'Administrator'
318
+ should_behave_like('User')
319
+
320
+ before
321
+ Admin = function(name) { this.name = name }
322
+ Admin.prototype.may = function(perm){ return true }
323
+ user = new Admin('tj')
324
+ end
325
+
326
+ it 'should have access to all permissions'
327
+ user.may('edit pages').should.be_true
328
+ end
329
+ end
330
+ end
331
+
332
+ NOTE: both User and Administrator's before hooks implement the 'user' variable
333
+
334
+ == Mock Ajax Requests
335
+
336
+ JSpec supports generic Ajax mocking which is usable with any JavaScript framework via 'jspec.xhr.js'. The
337
+ API is comprised of two functions, mockRequest() and unmockRequest(). unmockRequest() is
338
+ automatically called after each specification to restore the default functionality of XMLHttpRequest,
339
+ so it is uncommon to call unmockRequest() directly. Below is a jQuery example:
340
+
341
+ it 'should mock requests'
342
+ mockRequest().and_return('{ foo : "bar" }', 'application/json')
343
+ $.getJSON('foo', function(response, statusText){
344
+ response.foo.should.eql 'bar'
345
+ })
346
+ end
347
+
348
+ The mockRequest().and_return signature is as follows:
349
+
350
+ mockRequest().and_return(<data>, [content-type], [response-status-code], [headers-hash])
351
+
352
+ At the moment mockRequest() itself does not accept any arguments, however in the future
353
+ this will be used to target specific uris for mocking.
354
+
355
+ NOTE: works with Rhino as well
356
+
357
+ == Hooks
358
+
359
+ Currently the following hooks are supported, and may be utilized any number of times as they
360
+ are simply pushed to a stack. So for instance you may have two before_each blocks within the same
361
+ scope, they will both run, but this can help keep your specs readable.
362
+
363
+ * before run once before the suite is executed
364
+ * after run once after the suite is executed
365
+ * before_each run before each specification
366
+ * after_each run after each specification
367
+
368
+ == Custom Contexts
369
+
370
+ Custom contexts can be applied to supply helper
371
+ methods or properties to all subsequent bodies (other hooks, or specs).
372
+
373
+ Keep in mind that when replacing the default context you will loose
374
+ functionality provided by it, unless you manually merge it with your
375
+ custom context.
376
+
377
+ To reset the context simply assign null to obtain the original context.
378
+
379
+ ...
380
+ before
381
+ JSpec.context = { foo : 'bar' }
382
+ end
383
+
384
+ after
385
+ JSpec.context = null
386
+ end
387
+
388
+ it 'will work ;)'
389
+ foo.should_equal 'bar'
390
+ end
391
+ ...
392
+
393
+ == Async Support
394
+
395
+ Currently only jspec.jquery.js supports async requests. JSpec uses jQuery.ajaxSetup and sets all
396
+ requests to sync, which preserves execution order, and reports correctly.
397
+
398
+ it 'should load mah cookies (textfile)'
399
+ $.post('async', function(text){
400
+ text.should_eql 'cookies!'
401
+ })
402
+ end
403
+
404
+ == Pre-processor
405
+
406
+ The pre-processing capability of JSpec is extremely powerful. Your JavaScript
407
+ code is not necessarily what it seems. For example when you seemingly invoke a
408
+ object's prototype like below:
409
+
410
+ 'foobar'.should.include 'bar'
411
+
412
+ First parens are added:
413
+
414
+ 'foobar'.should.include('bar')
415
+
416
+ Secondly the matcher invocation is converted to a non-polluting match() call:
417
+
418
+ JSpec.match('foobar', 'should', 'include', 'bar')
419
+
420
+ This also means instead of:
421
+
422
+ var object = { foo : 'bar' }
423
+ object.should.include 'foo'
424
+
425
+ We can do:
426
+
427
+ { foo : 'bar' }.should.include 'foo'
428
+
429
+ === Closure Literal
430
+
431
+ These are equivalent:
432
+
433
+ -{ throw 'test' }.should.throw_error
434
+ function() { throw 'test' }.should.throw_error
435
+
436
+ === Inclusive Range Literal
437
+
438
+ The following expands to the array of [1,2,3,4,5]
439
+
440
+ n.should.be_within 1..5
441
+
442
+ == Formatters
443
+
444
+ To change a formatter simply alter the options hash like below, assigning
445
+ a new constructor, or pass it within the hash to run():
446
+
447
+ JSpec.options.formatter = JSpec.formatters.Console
448
+
449
+ OR
450
+
451
+ JSpec
452
+ .exec('...')
453
+ .run({ formatter : JSpec.formatters.Terminal })
454
+ .report()
455
+
456
+ == Fixtures
457
+
458
+ The fixture() utility function may be used in order to load arbitrary file contents
459
+ for use with your specifications. JSpec will resolve fixture('data') in the following
460
+ manor:
461
+
462
+ - 'data'
463
+ - 'spec/data'
464
+ - 'spec/fixtures/data'
465
+ - 'spec/fixtures/data.html'
466
+
467
+ So if the file 'spec/fixtures/data.html' exists, we can simply use fixture('data'),
468
+ where as 'spec/fixtures/xml/data.xml' must be specified with fixture('xml/data.xml').
469
+
470
+ If you prefer not to store fixtures in the 'fixtures' directory you must be more specific
471
+ with the path supplied.
472
+
473
+ == Testing DOM Elements
474
+
475
+ When using jQuery testing DOM elements is very easy. Many may think they require specific
476
+ sandbox divs in their html, however you do not. Using the fixture support mentioned above
477
+ you may simply load some HTML, and use the 'elements()' utility which is an alias of jQuery:
478
+
479
+ describe 'JSpec DOM testing'
480
+ describe 'is so easy'
481
+ before_each
482
+ list = elements(fixture('users-list'))
483
+ // or list = jQuery(fixture('users-list'))
484
+ // or list = $(fixture('users-list'))
485
+ end
486
+
487
+ it 'should have users'
488
+ list.should.have_tag 'ul'
489
+ end
490
+ end
491
+ end
492
+
493
+ You may also use simple strings, since jQuery's constructor will convert them to DOM elements:
494
+
495
+ describe 'Something'
496
+ before_each
497
+ html = elements('<p>Foo</p>')
498
+ // or html = $('<p>Foo</p>') ...
499
+ end
500
+
501
+ it 'should do something'
502
+ html.should.have_text 'Foo'
503
+ end
504
+ end
505
+
506
+ == Custom Matchers
507
+
508
+ First lets create a simple equality matcher. In the case below JSpec is smart enough to realize
509
+ this is simply a binary operator, and simply transforms this into 'actual === expected'
510
+
511
+ JSpec.addMatchers({
512
+ equal : '==='
513
+ })
514
+
515
+ To alias a method to keep your specs readable you may alias them like below:
516
+
517
+ JSpec.addMatchers({
518
+ be : 'alias equal'
519
+ })
520
+
521
+ 'foo'.should.equal 'foo'
522
+ true.should.be true
523
+
524
+ Matchers with string bodies implicitly return the expression value.
525
+ The expanded version of the equal matcher would then be:
526
+
527
+ JSpec.addMatchers({
528
+ equal : 'actual === expected'
529
+ })
530
+
531
+ Large matchers or those which require several parameters may wish
532
+ to utilize the hash method:
533
+
534
+ JSpec.addMatchers({
535
+ equal : { match : function(actual, expected){
536
+ return actual === expected
537
+ }}
538
+ })
539
+
540
+ To keep JSpec tiny, JSpec will default to generating failure messages
541
+ for you, how ever this can be explicitly defined:
542
+
543
+ JSpec.addMatchers({
544
+ equal : {
545
+ match : function(actual, expected){
546
+ return actual === expected
547
+ },
548
+ message : function(actual, expected, negate) {
549
+ return 'a message here'
550
+ }
551
+ }
552
+ })
553
+
554
+ When defining matchers that are extremely similar in functionality, however
555
+ require different names, you may use a prefixed list of words like below which
556
+ defines be_disabled, be_selected, be_checked, and have_type, have_id, etc. Each
557
+ function must return the matcher body which will be used.
558
+
559
+ JSpec.addMatchers({
560
+ 'be disabled selected checked' : function(attr) {
561
+ return 'jQuery(actual).attr("' + attr + '")'
562
+ },
563
+
564
+ 'have type id title alt href src sel rev name target' : function(attr) {
565
+ return function(actual, value) {
566
+ return value ? jQuery(actual).attr(attr) == value:
567
+ jQuery(actual).attr(attr)
568
+ }
569
+ }
570
+ })
571
+
572
+ == Extending Or Hooking Into JSpec
573
+
574
+ JSpec provides a hook architecture for extending or analyzing various
575
+ points in its execution, through the use of 'Modules'. For a Module
576
+ example view lib/jspec.jquery.js.
577
+
578
+ The following methods or properties are utilized by JSpec:
579
+
580
+ - name : module name string
581
+ - init : called to initialize a module
582
+ - formatters : hash of formatters merged with JSpec.formatters
583
+ - utilities : hash of utility functions merged with JSpec.defaultContext
584
+ - matchers : hash of matchers merged with JSpec's core matchers via JSpec.addMatchers()
585
+ - DSLs : hash of DSL methods; for example DSLs.snake contains before_each, after_each, etc.
586
+ Where as DSLs.camel may contain beforeEach, afterEach, etc.
587
+
588
+ Below is a list of hooks, descriptions, and valid return values which
589
+ may simply be implemented as module methods. beforeSuite, afterSuite, beforeSpec, and afterSpec have lower
590
+ precedence than before_each, after_each etc within the specs themselves, allowing them to override or undo
591
+ anything that has been done by a Module.
592
+
593
+ - running(options) : started running JSpec with the options passed : returning 'stop' will halt running
594
+ - loading(file) : loading a file : returning 'stop' will prevent loading
595
+ - executing(file) : executing a file : returning 'stop' will prevent execution
596
+ - posting(data, url) : posting data to a url : returning 'stop' will prevent request
597
+ - preprocessing(input) : before input string is preprocessed : return input string for next hook to preprocess
598
+ - stubbing(object, method, result) : called when stubbing an object's method, and return value (result). : (no return value)
599
+ - requiring(dependency, message) : requiring a dependency : (no return value)
600
+ - beforeAssertion(assertion) : before an assertion has been made : (no return value)
601
+ - afterAssertion(assertion) : after an assertion has been made : (no return value)
602
+ - addingMatcher(name, body) : unprocessed matcher name and body : (no return value)
603
+ - addingSuite(suite) : adding Suite instance to JSpec : (no return value)
604
+ - beforeSuite(suite) : before running of suite (describe block) : (no return value)
605
+ - afterSuite(suite) : after running of suite (describe block) : (no return value)
606
+ - beforeSpec(spec) : before running of spec (it block) : (no return value)
607
+ - afterSpec(spec) : after running of spec (it block) : (no return value)
608
+ - reporting(options) : called before reporting : (no return value)
609
+ - evaluatingBody(dsl, matchers, context, contents) : evaluating body contents, with the given context, matchers and dsl. : (no return value)
610
+
611
+ For example you may wish to proxy files which are being executed, simply implement the
612
+ executing method like below. This example will stop execution of any file matching /matchers/.
613
+
614
+ MyModule = {
615
+ executing : function(file) {
616
+ if (file.match(/matchers/))
617
+ return 'stop'
618
+ }
619
+ }
620
+ JSpec.include(MyModule)
621
+
622
+ Immutable values may also be passed to hooks using hookImmutable() internally. This allows
623
+ for simple numbers, strings, etc to be utilized or altered within a hook implementation. Below
624
+ is an example module which adds functionality to the JSpec grammar by converting SomeObject.stub('method')
625
+ to stub(SomeObject, 'method'):
626
+
627
+ JSpec.include({
628
+ preprocessing : function(input) {
629
+ return input.replace(/(\w+)\.(stub|destub)\((.*?)\)$/gm, '$2($1, $3)')
630
+ }
631
+ })
632
+
633
+ == JSpec Command-line Utility
634
+
635
+ When installed as a Ruby Gem, the `jspec` executable will become available,
636
+ allowing you to initialize project templates quickly, as well as auto-testing
637
+ specifications when a file is altered.
638
+
639
+ Initialize JSpec-driven project template in directory 'myproject':
640
+ $ jspec init myproject
641
+
642
+ Once within 'myproject' start testing by executing:
643
+ $ jspec
644
+
645
+ For additional usage execute:
646
+ $ jspec help
647
+
648
+ Or for specific usage:
649
+ $ jspec help run
650
+
651
+ == Rhino
652
+
653
+ JSpec provides transparent support for Rhino, while using the Terminal formatter.
654
+ Simply create a JavaScript file with contents similar to below, and then execute
655
+ the command following it:
656
+
657
+ load('lib/jspec.js')
658
+
659
+ JSpec
660
+ .exec('spec/spec.grammar.js')
661
+ .exec('spec/spec.core.js')
662
+ .run({ formatter : JSpec.formatters.Terminal, failuresOnly : true })
663
+ .report()
664
+
665
+ Initialize project with:
666
+ $ jspec init myproject
667
+
668
+ Run with:
669
+ $ jspec run --rhino
670
+
671
+ Or bind (automated testing):
672
+ $ jspec --rhino
673
+
674
+ == Server
675
+
676
+ The Ruby JavaScript testing server included with JSpec simply runs
677
+ the spec suites within each browser you specify, while reporting result
678
+ back to the terminal. It is essentially the same as using the DOM formatter
679
+ and auto-testing each browser, however results are centralized to the terminal,
680
+ removing the need to manually view each browser's output.
681
+
682
+ When utilizing the server if a file named spec/jspec.rb (or jspec/jspec.rb for rails)
683
+ is present, then it will be loaded before the server is started. This allows you to
684
+ add Sinatra routes, support additional Browsers, etc.
685
+
686
+ Run with all supported browsers:
687
+ $ jspec run --server
688
+
689
+ Run with specific browsers:
690
+ $ jspec run --browsers Safari,Firefox,Chrome,Explorer
691
+
692
+ Run with alternative browser names:
693
+ $ jspec run --browsers safari,ff,chrome,ie
694
+
695
+ Browsers supported in core:
696
+ Browser::Safari
697
+ Browser::Chrome
698
+ Browser::Opera
699
+ Browser::Firefox
700
+ Browser::IE
701
+
702
+ Supplied routes:
703
+ /slow/NUMBER
704
+ /status/NUMBER
705
+
706
+ For example $.get('/slow/4', function(){}) will take 4 seconds
707
+ to reply, where as $.get('/status/404', function(){}) will respond
708
+ with an 404 status code. Add additional Sinatra routes to the jspec.rb
709
+ file to add your own functionality.
710
+
711
+ == Interactive Shell
712
+
713
+ JSpec provides an interactive shell through Rhino, utilize with:
714
+
715
+ $ jspec shell
716
+
717
+ Or to specify additional files to load:
718
+
719
+ $ jspec shell lib/*.js
720
+
721
+ Or view additional shell help
722
+
723
+ $ jspec help shell
724
+
725
+ == Ruby on Rails
726
+
727
+ No additional gems are required for JSpec to work with rails, although
728
+ http://github.com/bhauman/jspec-rails has been created by 'bhauman'. JSpec
729
+ supports Rails out of the box, simply execute:
730
+
731
+ $ jspec init --rails
732
+
733
+ Then while still in the root directory of your Rails project, run the following
734
+ command which will bind to, and refresh your browsers automatically when any changes
735
+ are made to ./public/javascripts/*.js or ./jspec/*.js
736
+
737
+ $ jspec
738
+
739
+ Or just like regular JSpec applications, run once:
740
+
741
+ $ jspec run
742
+
743
+ Or run via the terminal using Rhino:
744
+
745
+ $ jspec run --rhino
746
+
747
+ == Support Browsers
748
+
749
+ Browsers below are supported and can be found in server/browsers.rb, however
750
+ your spec/server.rb file may support additional browsers.
751
+
752
+ * Safari
753
+ * Chrome
754
+ * Firefox
755
+ * Opera
756
+ * Internet Explorer
757
+
758
+ == Known Issues
759
+
760
+ * Tabs may cause a parse error. To prevent this use 'soft tabs' (setting in your IDE/Editor)
761
+ or use JSpec's grammar-less alternative (mentioned above).
762
+
763
+ * The preprocessor is not (yet) capable of multiline conversions. For example the following is invalid
764
+
765
+ object.stub('getContentsOfURL').and_return(function(url){
766
+ return 'html'
767
+ })
768
+
769
+ In cases such as this, you may always revert to utilizing JSpec in a grammar-less form as follows:
770
+
771
+ stub(object, 'getContentsOfURL').and_return(function(url){
772
+ return 'html'
773
+ })
774
+
775
+ == Additional JSpec Modules
776
+
777
+ * JSocka stubbing http://github.com/gisikw/jsocka/tree/master
778
+
779
+ == More Information
780
+
781
+ * IRC Channel irc://irc.freenode.net#jspec
782
+ * Featured article in JSMag: http://www.jsmag.com/main.issues.description/id=21/
783
+ * Syntax comparison with other frameworks http://gist.github.com/92283
784
+ * Get the TextMate bundle at https://github.com/visionmedia/jspec.tmbundle/tree
785
+ * For more information consult the JSpec source code documentation or visit http://visionmedia.github.com/jspec
786
+ * jQuery + HTML fixture example http://gist.github.com/147831
787
+
788
+ == Contributors
789
+
790
+ Many ideas and bug reports were contributed by
791
+ the following developers, thankyou for making
792
+ JSpec more enjoyable, and bug free ;)
793
+
794
+ * Lawrence Pit
795
+ * mpd@jesters-court.ne
796
+ * kevin.gisi@gmail.com
797
+ * enno84@gmx.net
798
+ * fnando
799
+
800
+ == License
801
+
802
+ (The MIT License)
803
+
804
+ Copyright (c) 2008 - 2009 TJ Holowaychuk <tj@vision-media.ca>
805
+
806
+ Permission is hereby granted, free of charge, to any person obtaining
807
+ a copy of this software and associated documentation files (the
808
+ 'Software'), to deal in the Software without restriction, including
809
+ without limitation the rights to use, copy, modify, merge, publish,
810
+ distribute, sublicense, and/or sell copies of the Software, and to
811
+ permit persons to whom the Software is furnished to do so, subject to
812
+ the following conditions:
813
+
814
+ The above copyright notice and this permission notice shall be
815
+ included in all copies or substantial portions of the Software.
816
+
817
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
818
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
819
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
820
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
821
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
822
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
823
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
824
+
825
+