visionmedia-jspec 1.1.3 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.rdoc +33 -0
- data/Manifest +14 -0
- data/README.rdoc +95 -51
- data/bin/jspec +68 -14
- data/jspec.gemspec +3 -3
- data/lib/jspec.jquery.js +30 -24
- data/lib/jspec.js +428 -251
- data/server/browsers.rb +24 -0
- data/server/server.rb +114 -0
- data/spec/server.html +20 -0
- data/spec/spec.core.js +48 -1
- data/spec/spec.grammar.js +5 -0
- data/spec/spec.jquery.js +13 -7
- data/spec/spec.rhino.js +8 -0
- data/templates/default/lib/yourlib.core.js +1 -34
- data/templates/rhino/History.rdoc +4 -0
- data/templates/rhino/README.rdoc +29 -0
- data/templates/rhino/lib/yourlib.core.js +2 -0
- data/templates/rhino/spec/spec.core.js +8 -0
- data/templates/rhino/spec/spec.js +7 -0
- data/templates/server/History.rdoc +4 -0
- data/templates/server/README.rdoc +29 -0
- data/templates/server/lib/yourlib.core.js +2 -0
- data/templates/server/spec/spec.core.js +8 -0
- data/templates/server/spec/spec.html +15 -0
- metadata +16 -2
data/server/browsers.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
module JSpec
|
3
|
+
class Browser
|
4
|
+
def open url
|
5
|
+
`open -g -a #{name} #{url}`
|
6
|
+
end
|
7
|
+
|
8
|
+
def name
|
9
|
+
self.class.to_s.split('::').last
|
10
|
+
end
|
11
|
+
|
12
|
+
class Firefox < self
|
13
|
+
end
|
14
|
+
|
15
|
+
class Safari < self
|
16
|
+
end
|
17
|
+
|
18
|
+
class Opera < self
|
19
|
+
end
|
20
|
+
|
21
|
+
class MSIE < self
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/server/server.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rack'
|
4
|
+
require 'server/browsers'
|
5
|
+
|
6
|
+
module JSpec
|
7
|
+
class Server
|
8
|
+
attr_reader :responses, :browsers, :root
|
9
|
+
|
10
|
+
def initialize options = {}
|
11
|
+
@responses = []
|
12
|
+
@browsers = options.delete :browsers
|
13
|
+
@root = options.delete :root
|
14
|
+
end
|
15
|
+
|
16
|
+
def call env
|
17
|
+
request = Rack::Request.new env
|
18
|
+
path = request.path_info
|
19
|
+
body = case path
|
20
|
+
when '/'
|
21
|
+
agent = env['HTTP_USER_AGENT']
|
22
|
+
responses << browser(agent)
|
23
|
+
display_results browser(agent), request['failures'], request['passes']
|
24
|
+
type = 'text/plain'
|
25
|
+
'close'
|
26
|
+
when /jspec/
|
27
|
+
type = 'application/javascript'
|
28
|
+
File.read File.join(JSPEC_ROOT, 'lib', request.path_info)
|
29
|
+
when /\.js/
|
30
|
+
type = 'application/javascript'
|
31
|
+
File.read File.join(root, request.path_info)
|
32
|
+
else
|
33
|
+
type = 'text/html'
|
34
|
+
File.read File.join(root, request.path_info) rescue ''
|
35
|
+
end
|
36
|
+
[200, { 'Content-Type' => type, 'Content-Length' => body.length.to_s }, body]
|
37
|
+
end
|
38
|
+
|
39
|
+
def display_results browser, failures, passes
|
40
|
+
puts '%s - failures %s passes %s' % [bold(browser), red(failures), green(passes)]
|
41
|
+
require 'rubygems'
|
42
|
+
require 'growl'
|
43
|
+
if failures.to_i > 0
|
44
|
+
notify_error "failed #{failures} assertion(s)", :title => browser
|
45
|
+
else
|
46
|
+
notify_ok "passed #{passes} assertion(s)", :title => browser
|
47
|
+
end
|
48
|
+
rescue
|
49
|
+
# Do nothing
|
50
|
+
end
|
51
|
+
|
52
|
+
def browser string
|
53
|
+
case string
|
54
|
+
when /Safari/ ; :Safari
|
55
|
+
when /Firefox/ ; :Firefox
|
56
|
+
when /MSIE/ ; :MSIE
|
57
|
+
when /Opera/ ; :Opera
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def bold string
|
62
|
+
color string, 1
|
63
|
+
end
|
64
|
+
|
65
|
+
def red string
|
66
|
+
color string, 31
|
67
|
+
end
|
68
|
+
|
69
|
+
def green string
|
70
|
+
color string, 32
|
71
|
+
end
|
72
|
+
|
73
|
+
def color string, code
|
74
|
+
"\e[#{code}m#{string}\e[m"
|
75
|
+
end
|
76
|
+
|
77
|
+
def when_finished &block
|
78
|
+
Thread.new {
|
79
|
+
while responses.length < browsers.length
|
80
|
+
sleep 0.1
|
81
|
+
end
|
82
|
+
yield
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.start options, spec
|
87
|
+
app = Rack::Builder.new do
|
88
|
+
server = JSpec::Server.new :browsers => options.browsers, :root => File.dirname(spec)
|
89
|
+
server.when_finished { exit }
|
90
|
+
run server
|
91
|
+
end
|
92
|
+
unless options.server_only
|
93
|
+
Thread.new {
|
94
|
+
sleep 2
|
95
|
+
puts "Running browsers: #{options.browsers.join(', ')}\n\n"
|
96
|
+
run_browsers options.browsers, spec
|
97
|
+
}
|
98
|
+
end
|
99
|
+
puts "JSpec server started\n"
|
100
|
+
Rack::Handler::Mongrel.run app, :Port => 4444
|
101
|
+
self
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.run_browsers browsers, spec
|
105
|
+
browsers.each do |name|
|
106
|
+
browser(name).open "http://localhost:4444/#{File.basename(spec)}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.browser name
|
111
|
+
eval("JSpec::Browser::#{name}").new
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
data/spec/server.html
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<script src="jquery-1.3.1.js"></script>
|
4
|
+
<script src="jspec.js"></script>
|
5
|
+
<script src="jspec.jquery.js"></script>
|
6
|
+
<script>
|
7
|
+
function runSuites() {
|
8
|
+
JSpec
|
9
|
+
.exec('spec.grammar.js')
|
10
|
+
.exec('spec.core.js')
|
11
|
+
.exec('spec.core.dom.js')
|
12
|
+
.exec('spec.jquery.js')
|
13
|
+
.run()
|
14
|
+
.reportToServer()
|
15
|
+
}
|
16
|
+
</script>
|
17
|
+
</head>
|
18
|
+
<body class="jspec" onLoad="runSuites();">
|
19
|
+
</body>
|
20
|
+
</html>
|
data/spec/spec.core.js
CHANGED
@@ -26,12 +26,22 @@ describe 'Matchers'
|
|
26
26
|
it 'should hash compare objects'
|
27
27
|
{ foo : 'bar' }.should.eql { foo : 'bar' }
|
28
28
|
end
|
29
|
+
|
30
|
+
it 'should hash compare arbitrary objects'
|
31
|
+
Foo = function(){}, Bar = function(){}
|
32
|
+
Bar.prototype = { doSomething : function(){ }}
|
33
|
+
foo = new Foo, foo2 = new Foo, bar = new Bar
|
34
|
+
foo.should.eql foo2
|
35
|
+
foo.should.not.eql bar
|
36
|
+
end
|
29
37
|
end
|
30
38
|
|
31
39
|
describe 'equal'
|
32
40
|
it 'should perform strict comparisons'
|
33
41
|
'test'.should.equal 'test'
|
34
42
|
'1'.should.not.equal 1
|
43
|
+
true.should.be true
|
44
|
+
'1'.should.not.be true
|
35
45
|
end
|
36
46
|
end
|
37
47
|
|
@@ -130,7 +140,7 @@ describe 'Matchers'
|
|
130
140
|
end
|
131
141
|
|
132
142
|
it 'should check if a regular expression includes a string'
|
133
|
-
/(foo)?bar
|
143
|
+
(/(foo)?bar/).should.include '(foo)'
|
134
144
|
end
|
135
145
|
|
136
146
|
it 'should check if a function body includes a string'
|
@@ -173,6 +183,24 @@ describe 'Matchers'
|
|
173
183
|
-{ throw 'some foo bar' }.should.not.throw_error(/rawr/)
|
174
184
|
-{ throw 'some foo bar' }.should.not.throw_error('rawr')
|
175
185
|
end
|
186
|
+
|
187
|
+
it 'should check if an error of a specific constructor is thrown'
|
188
|
+
-{ throw new Error('foo') }.should.throw_error(Error)
|
189
|
+
-{ throw new TypeError('foo') }.should.throw_error(TypeError)
|
190
|
+
-{ throw 'foo' }.should.not.throw_error(Error)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe 'be_an_instance_of'
|
195
|
+
it 'should check that an object is an instance of another'
|
196
|
+
MyObject = function(){}
|
197
|
+
myInstance = new MyObject()
|
198
|
+
{}.should.be_an_instance_of Object
|
199
|
+
[].should.be_an_instance_of Array
|
200
|
+
MyObject.should.be_an_instance_of Function
|
201
|
+
myInstance.should.be_an_instance_of MyObject
|
202
|
+
myInstance.should.be_an_instance_of Object
|
203
|
+
end
|
176
204
|
end
|
177
205
|
|
178
206
|
describe 'be_type'
|
@@ -224,6 +252,13 @@ describe 'Matchers'
|
|
224
252
|
end
|
225
253
|
end
|
226
254
|
|
255
|
+
describe 'should_receive'
|
256
|
+
it 'should fail when a method is not available'
|
257
|
+
person = {}
|
258
|
+
person.should.receive('getPets')
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
227
262
|
end
|
228
263
|
|
229
264
|
describe 'Negative specs'
|
@@ -278,6 +313,18 @@ describe 'Negative specs'
|
|
278
313
|
['foo', 'bar'].should.include 'foo', 'car'
|
279
314
|
end
|
280
315
|
|
316
|
+
it 'should catch exceptions throw within specs'
|
317
|
+
throw new Error('Oh noes!')
|
318
|
+
end
|
319
|
+
|
320
|
+
it 'should catch improper exceptions'
|
321
|
+
throw 'oh noes'
|
322
|
+
end
|
323
|
+
|
324
|
+
it 'should catch proper exceptions'
|
325
|
+
iDoNotExist
|
326
|
+
end
|
327
|
+
|
281
328
|
end
|
282
329
|
|
283
330
|
describe 'Utility'
|
data/spec/spec.grammar.js
CHANGED
@@ -28,6 +28,11 @@ describe 'Grammar'
|
|
28
28
|
-{ throw 'test' }.should.throw_error
|
29
29
|
end
|
30
30
|
|
31
|
+
it 'should allow commenting out of conversions'
|
32
|
+
// -{ throw 'foo' }.should.throw_error
|
33
|
+
// foo.should.not.eql 'bar'
|
34
|
+
end
|
35
|
+
|
31
36
|
it 'should allow . this. literal'
|
32
37
|
this.foo = 'bar'
|
33
38
|
.foo.should.eql 'bar'
|
data/spec/spec.jquery.js
CHANGED
@@ -34,13 +34,13 @@ describe 'jQuery'
|
|
34
34
|
|
35
35
|
describe 'matchers'
|
36
36
|
before_each
|
37
|
-
html = '<p><label><em>Save?</em></label>
|
38
|
-
<select class="save" style="display: none;">
|
39
|
-
<option value="0">No</option>
|
40
|
-
<option value="1">Yes</option>
|
41
|
-
</select>
|
42
|
-
<strong>test</strong>
|
43
|
-
<strong>test</strong>
|
37
|
+
html = '<p><label><em>Save?</em></label> \
|
38
|
+
<select class="save form-select" style="display: none;"> \
|
39
|
+
<option value="0">No</option> \
|
40
|
+
<option value="1">Yes</option> \
|
41
|
+
</select> \
|
42
|
+
<strong>test</strong> \
|
43
|
+
<strong>test</strong> \
|
44
44
|
</p>'
|
45
45
|
.elem = $(html)
|
46
46
|
end
|
@@ -97,6 +97,12 @@ describe 'jQuery'
|
|
97
97
|
.elem.children('select').should.have_class 'save'
|
98
98
|
end
|
99
99
|
end
|
100
|
+
|
101
|
+
describe 'have_classes'
|
102
|
+
it 'should check if an element has the classes given'
|
103
|
+
.elem.children('select').should.have_classes 'save', 'form-select'
|
104
|
+
end
|
105
|
+
end
|
100
106
|
|
101
107
|
describe 'be_visible'
|
102
108
|
it 'should check that an element is not hidden or set to display of none'
|
data/spec/spec.rhino.js
ADDED
@@ -1,35 +1,2 @@
|
|
1
1
|
|
2
|
-
//
|
3
|
-
|
4
|
-
(function(){
|
5
|
-
|
6
|
-
this.Evo = { version : '0.0.1' }
|
7
|
-
|
8
|
-
/**
|
9
|
-
* Merge methods and properties of _other_.
|
10
|
-
*
|
11
|
-
* @param {hash} other
|
12
|
-
* @return {mixed} this
|
13
|
-
* @api public
|
14
|
-
*/
|
15
|
-
|
16
|
-
Object.prototype.extend = function(other) {
|
17
|
-
for (key in other)
|
18
|
-
if (other.hasOwnProperty(key))
|
19
|
-
this[key] = other[key]
|
20
|
-
return this
|
21
|
-
}
|
22
|
-
|
23
|
-
/**
|
24
|
-
* Merge prototype with methods and properties with _mixin_.
|
25
|
-
*
|
26
|
-
* @param {hash} mixin
|
27
|
-
* @return {mixed} this
|
28
|
-
* @api public
|
29
|
-
*/
|
30
|
-
|
31
|
-
Object.prototype.include = function(mixin) {
|
32
|
-
return this.prototype.extend(mixin)
|
33
|
-
}
|
34
|
-
|
35
|
-
})()
|
2
|
+
// Your library here
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
= YourLib
|
3
|
+
|
4
|
+
Description
|
5
|
+
|
6
|
+
== License
|
7
|
+
|
8
|
+
(The MIT License)
|
9
|
+
|
10
|
+
Copyright (c) 2009 Your Name <Your Email>
|
11
|
+
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
13
|
+
a copy of this software and associated documentation files (the
|
14
|
+
'Software'), to deal in the Software without restriction, including
|
15
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
16
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
17
|
+
permit persons to whom the Software is furnished to do so, subject to
|
18
|
+
the following conditions:
|
19
|
+
|
20
|
+
The above copyright notice and this permission notice shall be
|
21
|
+
included in all copies or substantial portions of the Software.
|
22
|
+
|
23
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
24
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
25
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
26
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
27
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
28
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
29
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
= YourLib
|
3
|
+
|
4
|
+
Description
|
5
|
+
|
6
|
+
== License
|
7
|
+
|
8
|
+
(The MIT License)
|
9
|
+
|
10
|
+
Copyright (c) 2009 Your Name <Your Email>
|
11
|
+
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
13
|
+
a copy of this software and associated documentation files (the
|
14
|
+
'Software'), to deal in the Software without restriction, including
|
15
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
16
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
17
|
+
permit persons to whom the Software is furnished to do so, subject to
|
18
|
+
the following conditions:
|
19
|
+
|
20
|
+
The above copyright notice and this permission notice shall be
|
21
|
+
included in all copies or substantial portions of the Software.
|
22
|
+
|
23
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
24
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
25
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
26
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
27
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
28
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
29
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|