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