oojspec 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +14 -0
- data/lib/assets/javascripts/oojspec.js.coffee +72 -43
- data/lib/oojspec/version.rb +1 -1
- data/vendor/assets/javascripts/buster/html.js +6 -2
- metadata +4 -4
data/README.md
CHANGED
@@ -23,10 +23,24 @@ I'd rather prefer to write:
|
|
23
23
|
assert(seats.length)
|
24
24
|
```
|
25
25
|
|
26
|
+
# Examples
|
27
|
+
|
26
28
|
[Here is how it looks like](http://oojspec.herokuapp.com/)
|
27
29
|
(yeah, I know it is failing - it is on purpose so that you can see
|
28
30
|
how the report looks like).
|
29
31
|
|
32
|
+
Feel free to explore it in jsfiddle:
|
33
|
+
|
34
|
+
- [JavaScript example with test runner](http://jsfiddle.net/rosenfeld/FWtaZ/)
|
35
|
+
- [JavaScript example without test runner](http://jsfiddle.net/rosenfeld/W3BCJ/)
|
36
|
+
- [CoffeeScript example with test runner](http://jsfiddle.net/rosenfeld/qJSyz/)
|
37
|
+
- [CoffeeScript example without test runner](http://jsfiddle.net/rosenfeld/37Qdn/)
|
38
|
+
|
39
|
+
And finally [a more complete suite](http://jsfiddle.net/rosenfeld/wgBJg/)
|
40
|
+
demonstrating lots of the features available. This was extracted from the test
|
41
|
+
application and is expected to fail. The result should be the same as the first
|
42
|
+
example of this section, hosted on Heroku.
|
43
|
+
|
30
44
|
# Is it production ready?
|
31
45
|
|
32
46
|
It should be, but its API is certainly going to change a lot before it becomes stable.
|
@@ -27,7 +27,7 @@ window.oojspec = new class OojspecRunner
|
|
27
27
|
autorun: -> @runSpecs() unless @disableAutorun
|
28
28
|
|
29
29
|
runSpecs: ->
|
30
|
-
@reporter = buster.reporters.html.create
|
30
|
+
@reporter = buster.reporters.html.create detectCssPath: false
|
31
31
|
@reporter.listen @runner
|
32
32
|
@runner.emit 'suite:start', name: "Specs"
|
33
33
|
@runNextDescription()
|
@@ -35,30 +35,46 @@ window.oojspec = new class OojspecRunner
|
|
35
35
|
runNextDescription: =>
|
36
36
|
(@runner.emit 'suite:end', @stats; return) unless @descriptions.length
|
37
37
|
# TODO: think about non null contexts usage
|
38
|
-
@descriptions.shift().run @runner, @assertions, null, @runNextDescription
|
38
|
+
@descriptions.shift().run @runner, @assertions, null, false, @runNextDescription
|
39
39
|
|
40
40
|
describe: (description, block)=>
|
41
41
|
@stats.contexts++ # only root descriptions will be count
|
42
42
|
@descriptions.push new Description(description, block)
|
43
43
|
|
44
|
+
RESERVED_FOR_DESCRIPTION_DSL = ['beforeAll', 'before', 'after', 'afterAll', 'describe', 'context',
|
45
|
+
'example', 'it', 'specify', 'pending', 'xit']
|
46
|
+
RESERVED_FOR_EXAMPLE_DSL = ['assert', 'expect', 'fail', 'refute', 'waitsFor', 'runs']
|
44
47
|
class Description
|
45
|
-
RESERVED =
|
46
|
-
|
48
|
+
RESERVED = RESERVED_FOR_DESCRIPTION_DSL.concat RESERVED_FOR_EXAMPLE_DSL
|
49
|
+
|
47
50
|
constructor: (@description, @block)->
|
51
|
+
if @description.runSpecs or @description.prototype?.runSpecs
|
52
|
+
@block = @description
|
53
|
+
@description = @block.description or @block.name
|
48
54
|
|
49
|
-
run: (@runner, @assertions, @
|
55
|
+
run: (@runner, @assertions, @binding, @bare, @onFinish, @beforeBlocks = [], @afterBlocks = [])->
|
50
56
|
@runner.emit 'context:start', name: @description
|
51
57
|
@dsl = new DescribeDsl
|
52
|
-
if
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
58
|
+
if @block.runSpecs or @block.prototype?.runSpecs
|
59
|
+
@runWithContext()
|
60
|
+
else
|
61
|
+
@doRun()
|
62
|
+
|
63
|
+
doRun: -> @runAround @beforeBlocks, @afterBlocks, @onDescriptionFinished, @processDescriptionBlock
|
64
|
+
|
65
|
+
runWithContext: ->
|
66
|
+
try
|
67
|
+
@binding = if @block.prototype then new @block else @block
|
68
|
+
if @binding and not (@bare = @block.bare)
|
69
|
+
for reserved in RESERVED
|
70
|
+
if @binding[reserved]
|
71
|
+
throw new Error("'#{reserved}' method is reserved for oojspec usage only")
|
72
|
+
@binding[reserved] = @dsl[reserved]
|
73
|
+
@doRun()
|
74
|
+
catch e
|
75
|
+
e.name = "syntax error"
|
76
|
+
@runner.emit 'test:error', name: @description, error: e
|
77
|
+
@onDescriptionFinished(e)
|
62
78
|
|
63
79
|
onDescriptionFinished: (error)=>
|
64
80
|
if error and not error.handled
|
@@ -68,11 +84,14 @@ class Description
|
|
68
84
|
@onFinish error
|
69
85
|
|
70
86
|
runAround: (befores, afters, onFinish, block)->
|
71
|
-
new AroundBlock(befores, afters, block).run @runner, @assertions, @
|
87
|
+
new AroundBlock(befores, afters, block).run @runner, @assertions, @binding, @bare, onFinish
|
72
88
|
|
73
89
|
processDescriptionBlock: (onFinish)=>
|
74
|
-
|
75
|
-
|
90
|
+
if @block.runSpecs or @block.prototype?.runSpecs
|
91
|
+
@binding.runSpecs @dsl
|
92
|
+
else
|
93
|
+
binding = @binding or @dsl
|
94
|
+
@block.call binding, @dsl
|
76
95
|
@runAround @dsl._beforeAllBlocks_, @dsl._afterAllBlocks_, onFinish, (@onExamplesFinished)=>
|
77
96
|
@runNextStep()
|
78
97
|
|
@@ -81,10 +100,11 @@ class Description
|
|
81
100
|
nextStep = @dsl._examples_.shift()
|
82
101
|
(@reportDeferred(nextStep.description); @runNextStep(); return) if nextStep.pending
|
83
102
|
nextTick =
|
84
|
-
if nextStep instanceof Description then =>
|
85
|
-
.run @runner, @assertions, @
|
103
|
+
if nextStep instanceof Description then =>
|
104
|
+
nextStep.run @runner, @assertions, @binding, @bare, @runNextStep, \
|
105
|
+
@dsl._beforeBlocks_, @dsl._afterBlocks_
|
86
106
|
else => # ExampleWithHooks
|
87
|
-
nextStep.run @runner, @assertions, @
|
107
|
+
nextStep.run @runner, @assertions, @binding, @bare, @onExampleFinished
|
88
108
|
setTimeout nextTick, 0
|
89
109
|
|
90
110
|
onExampleFinished: (error)=>
|
@@ -105,6 +125,7 @@ class DescribeDsl
|
|
105
125
|
block.description = description
|
106
126
|
else
|
107
127
|
block = description
|
128
|
+
throw new Error("block missing") unless block
|
108
129
|
container.push block
|
109
130
|
|
110
131
|
constructor: ->
|
@@ -125,17 +146,18 @@ class DescribeDsl
|
|
125
146
|
describe: (description, block)=>
|
126
147
|
@_examples_.push new Description(description, block, @_beforeBlocks_, @_afterBlocks_)
|
127
148
|
example: (description, block)=>
|
149
|
+
throw new Error("Examples must have a description and a block") unless description and block
|
128
150
|
@_examples_.push new ExampleWithHooks(description, @_beforeBlocks_, @_afterBlocks_, block)
|
129
151
|
pending: (description)=> @_examples_.push {description, pending: true}
|
130
152
|
|
131
153
|
class AroundBlock
|
132
154
|
constructor: (@beforeBlocks, @afterBlocks, @block)->
|
133
155
|
|
134
|
-
run: (@runner, @assertions, @
|
156
|
+
run: (@runner, @assertions, @binding, @bare, @onFinish)->
|
135
157
|
@runGroup @beforeBlocks, ((e)=> @onBeforeError e), (wasSuccessful)=>
|
136
158
|
if wasSuccessful
|
137
159
|
@runMainBlock @block, (error)=>
|
138
|
-
@registerError error
|
160
|
+
@registerError error if error
|
139
161
|
@runAfterGroup()
|
140
162
|
else @runAfterGroup()
|
141
163
|
|
@@ -152,7 +174,7 @@ class AroundBlock
|
|
152
174
|
onFinish error
|
153
175
|
|
154
176
|
runGroup: (group, onError, onFinish)->
|
155
|
-
new ExampleGroupWithoutHooks(@assertions, @
|
177
|
+
new ExampleGroupWithoutHooks(@assertions, @binding, @bare, group, onFinish, onError).run()
|
156
178
|
|
157
179
|
onBeforeError: (error)-> error.source = "before hook"; @registerError error
|
158
180
|
onAfterError: (error)-> error.source = "after hook"; @registerError error
|
@@ -161,7 +183,7 @@ class AroundBlock
|
|
161
183
|
|
162
184
|
class ExampleWithHooks extends AroundBlock
|
163
185
|
constructor: (@description, @beforeBlocks, @afterBlocks, @block)->
|
164
|
-
runMainBlock: (block, onFinish)-> new Example(block).run @assertions, @
|
186
|
+
runMainBlock: (block, onFinish)-> new Example(block).run @assertions, @binding, @bare, onFinish
|
165
187
|
onAfterHooks: ->
|
166
188
|
@handleResult()
|
167
189
|
super
|
@@ -182,7 +204,7 @@ class ExampleWithHooks extends AroundBlock
|
|
182
204
|
@runner.emit 'test:error', name: @description, error: @error
|
183
205
|
|
184
206
|
class ExampleGroupWithoutHooks
|
185
|
-
constructor: (@assertions, @
|
207
|
+
constructor: (@assertions, @binding, @bare, @blocks, @onFinish, @onError)-> @nextIndex = 0
|
186
208
|
|
187
209
|
run: ->
|
188
210
|
@wasSuccessful = true
|
@@ -191,39 +213,40 @@ class ExampleGroupWithoutHooks
|
|
191
213
|
nextTick: =>
|
192
214
|
(@onFinish(@wasSuccessful); return) unless @nextIndex < @blocks.length
|
193
215
|
block = @blocks[@nextIndex++]
|
194
|
-
new Example(block).run @assertions, @
|
216
|
+
new Example(block).run @assertions, @binding, @bare, (error)=>
|
195
217
|
(@wasSuccessful = false; @onError error) if error
|
196
218
|
setTimeout @nextTick, 0
|
197
219
|
|
198
220
|
class Example
|
199
221
|
TICK = 10 # ms
|
200
|
-
constructor: (@exampleBlock)->
|
222
|
+
constructor: (@exampleBlock)-> @describeDsl = {}
|
201
223
|
|
202
|
-
run: (@assertions, @
|
224
|
+
run: (@assertions, @binding, @bare, @onFinish)->
|
203
225
|
@dsl = new ExampleDsl(@assertions.assert, @assertions.expect, @assertions.fail, \
|
204
226
|
@assertions.refute)
|
205
|
-
if @
|
206
|
-
|
207
|
-
|
208
|
-
|
227
|
+
if @binding and not @bare
|
228
|
+
for m in RESERVED_FOR_DESCRIPTION_DSL
|
229
|
+
@describeDsl[m] = b if b = @binding[m]
|
230
|
+
delete @binding[m]
|
231
|
+
(@binding[m] = b if b = @dsl[m]) for m in RESERVED_FOR_EXAMPLE_DSL
|
209
232
|
@tryBlock @exampleBlock, ->
|
210
|
-
if @
|
211
|
-
delete @
|
212
|
-
delete @
|
213
|
-
(@
|
233
|
+
if @binding and not @bare
|
234
|
+
delete @binding.runs
|
235
|
+
delete @binding.waitsFor
|
236
|
+
(@finish(); return) unless (@steps = @dsl._asyncQueue_).length
|
214
237
|
@runNextAsyncStep()
|
215
238
|
|
216
239
|
tryBlock: (block, onSuccess)->
|
217
240
|
try
|
218
|
-
|
219
|
-
onSuccess.call this, block.call
|
241
|
+
binding = @binding or @dsl
|
242
|
+
onSuccess.call this, block.call(binding, @dsl)
|
220
243
|
catch error
|
221
244
|
error = new Error(error) if typeof error is 'string'
|
222
|
-
error.message = "'#{error.message}' in '#{block.description}'" if block
|
223
|
-
@
|
245
|
+
error.message = "'#{error.message}' in '#{block.description}'" if block?.description
|
246
|
+
@finish error
|
224
247
|
|
225
248
|
runNextAsyncStep: ->
|
226
|
-
(@
|
249
|
+
(@finish(); return) unless @steps.length
|
227
250
|
step = @steps.shift()
|
228
251
|
if step instanceof Function
|
229
252
|
@tryBlock step, @runNextAsyncStep
|
@@ -237,9 +260,15 @@ class Example
|
|
237
260
|
keepTryingCondition: =>
|
238
261
|
@tryBlock @condition, (result)->
|
239
262
|
(@runNextAsyncStep(); return) if result
|
240
|
-
(@
|
263
|
+
(@finish {timeout: true, @description}; return) if new Date().getTime() > @deadline
|
241
264
|
setTimeout @keepTryingCondition, TICK
|
242
265
|
|
266
|
+
finish: ->
|
267
|
+
if @binding and not @bare
|
268
|
+
(@binding[m] = b if b = @describeDsl[m]) for m in RESERVED_FOR_DESCRIPTION_DSL
|
269
|
+
delete @binding[m] for m in RESERVED_FOR_EXAMPLE_DSL
|
270
|
+
@onFinish.apply null, arguments
|
271
|
+
|
243
272
|
class ExampleDsl
|
244
273
|
constructor: (@assert, @expect, @fail, @refute)-> @_asyncQueue_ = []
|
245
274
|
|
data/lib/oojspec/version.rb
CHANGED
@@ -21,7 +21,9 @@
|
|
21
21
|
reporter.contexts = [];
|
22
22
|
reporter.doc = getDoc(opt);
|
23
23
|
var cssPath = opt.cssPath;
|
24
|
-
if (!cssPath && opt.detectCssPath
|
24
|
+
if (!cssPath && opt.detectCssPath !== false) {
|
25
|
+
cssPath = busterTestPath(reporter.doc) + "buster-test.css";
|
26
|
+
}
|
25
27
|
reporter.setRoot(opt.root || reporter.doc.body, cssPath);
|
26
28
|
reporter.io = opt.io || (isNodeJS && require("util"));
|
27
29
|
|
@@ -205,7 +207,9 @@
|
|
205
207
|
|
206
208
|
head.appendChild(el(head.ownerDocument, "style", {
|
207
209
|
type: "text/css",
|
208
|
-
innerHTML: fs.readFileSync(
|
210
|
+
innerHTML: fs.readFileSync(
|
211
|
+
path.join(__dirname, "../../../resources/buster-test.css")
|
212
|
+
)
|
209
213
|
}));
|
210
214
|
} else {
|
211
215
|
head.appendChild(el(document, "link", {
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oojspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: coffee-rails
|
@@ -85,7 +85,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
85
85
|
version: '0'
|
86
86
|
segments:
|
87
87
|
- 0
|
88
|
-
hash: -
|
88
|
+
hash: -1275332504698129146
|
89
89
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
90
|
none: false
|
91
91
|
requirements:
|
@@ -94,7 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
94
|
version: '0'
|
95
95
|
segments:
|
96
96
|
- 0
|
97
|
-
hash: -
|
97
|
+
hash: -1275332504698129146
|
98
98
|
requirements: []
|
99
99
|
rubyforge_project:
|
100
100
|
rubygems_version: 1.8.24
|