oojspec 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +4 -0
- data/lib/assets/javascripts/oojspec.js.coffee +7 -300
- data/lib/assets/javascripts/{progress.js.coffee → oojspec/progress.js.coffee} +3 -1
- data/lib/assets/javascripts/oojspec/runner.js.coffee +316 -0
- data/lib/assets/javascripts/oojspec/utils.js.coffee +7 -0
- data/lib/oojspec/version.rb +1 -1
- metadata +17 -26
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8744b2c6b9c6be58bbd8eb3b566c54bae6dda38e
|
4
|
+
data.tar.gz: 9e6d34de2357feeb77a41663e8024dc16bf389fe
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b93bcf5981587f22cf10e3fbd2a901c869c965804e34d6f05c69c620a48b0e28b904c760c5b1b134f275eb4dfc6052ae24f602995e2c6a428cc68b05edf5e4ae
|
7
|
+
data.tar.gz: e02c4ded0fce6d1b47b649bded82d9190ab38b553beb5ddcecec975e8b737f8c0863e2c5be66686fa827869b3197b37513fe7dc0778641227a181f438b2a4d9c
|
data/README.md
CHANGED
@@ -194,3 +194,7 @@ I'd love to hear your opinions on the API and design of `oojspec` and of course
|
|
194
194
|
will be very welcome if they're aligned with this project goals.
|
195
195
|
|
196
196
|
Enjoy! :)
|
197
|
+
|
198
|
+
|
199
|
+
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rosenfeld/oojspec/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
|
200
|
+
|
@@ -1,303 +1,10 @@
|
|
1
|
-
# =require buster/all
|
2
1
|
# =require_self
|
3
|
-
# =
|
2
|
+
# =require_tree ./oojspec
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
@descriptions = []
|
10
|
-
@assertions = buster.assertions
|
11
|
-
(logFormatter = buster.create buster.format).quoteStrings = false
|
12
|
-
@assertions.format = buster.bind logFormatter, "ascii"
|
13
|
-
@assertions.on 'pass', => @stats.assertions++
|
14
|
-
@assertions.on 'failure', => @stats.failures++
|
15
|
-
#@runner.on 'context:start', => @stats.contexts++
|
16
|
-
@runner.on 'test:timeout', => @stats.timeouts++; @assertions.emit 'failure'
|
17
|
-
@runner.on 'test:error', => @stats.errors++
|
18
|
-
@runner.on 'test:deferred', => @stats.deferred++
|
19
|
-
@runner.on 'oojspec:examples:add', (count)=> @stats.tests += count
|
4
|
+
# avoid polluting the global namespace
|
5
|
+
# namespace for allowing us to split code in multiple files
|
6
|
+
# internal classes and functions declared in separate units should be exported to _
|
7
|
+
@oojspec = _: {}
|
20
8
|
|
21
|
-
|
22
|
-
|
23
|
-
tests: 0
|
24
|
-
assertions: 0
|
25
|
-
errors: 0
|
26
|
-
failures: 0
|
27
|
-
timeouts: 0
|
28
|
-
deferred: 0
|
29
|
-
|
30
|
-
exposeAll: -> window.describe = @describe
|
31
|
-
autorun: -> @runSpecs() unless @disableAutorun
|
32
|
-
|
33
|
-
runSpecs: ->
|
34
|
-
@reporter = buster.reporters.html.create detectCssPath: false
|
35
|
-
@reporter.listen @runner
|
36
|
-
d.processDsl @runner for d in @descriptions
|
37
|
-
@runner.emit 'suite:start', name: "Specs"
|
38
|
-
@runNextDescription()
|
39
|
-
|
40
|
-
runNextDescription: =>
|
41
|
-
(@runner.emit 'suite:end', @stats; return) unless @descriptions.length
|
42
|
-
@descriptions.shift().run @assertions, @runNextDescription
|
43
|
-
|
44
|
-
describe: (description, block)=>
|
45
|
-
@stats.contexts++ # only root descriptions will be count
|
46
|
-
@descriptions.push new Description(description, block)
|
47
|
-
|
48
|
-
RESERVED_FOR_DESCRIPTION_DSL = ['beforeAll', 'before', 'after', 'afterAll', 'describe', 'context',
|
49
|
-
'example', 'it', 'specify', 'pending', 'xit']
|
50
|
-
RESERVED_FOR_EXAMPLE_DSL = ['assert', 'expect', 'fail', 'refute', 'waitsFor', 'runs']
|
51
|
-
class Description
|
52
|
-
RESERVED = RESERVED_FOR_DESCRIPTION_DSL.concat RESERVED_FOR_EXAMPLE_DSL
|
53
|
-
|
54
|
-
constructor: (@description, @block)->
|
55
|
-
if @description.runSpecs or @description.prototype?.runSpecs
|
56
|
-
@block = @description
|
57
|
-
@description = @block.description or @block.name
|
58
|
-
|
59
|
-
processDsl: (@runner, @binding, @bare)->
|
60
|
-
@dsl = new DescribeDsl
|
61
|
-
(@block.runSpecs or @block.prototype?.runSpecs) and @detectBindingError()
|
62
|
-
|
63
|
-
@binding or= {}
|
64
|
-
@injectDsl() unless @bare
|
65
|
-
if @block.runSpecs or @block.prototype?.runSpecs
|
66
|
-
@binding.runSpecs @dsl
|
67
|
-
else
|
68
|
-
@block.call @binding, @dsl
|
69
|
-
@runner.emit 'oojspec:examples:add', @dsl._examplesCount_
|
70
|
-
@removeDsl() unless @bare
|
71
|
-
@bare or= @binding.bare
|
72
|
-
|
73
|
-
d.processDsl @runner, @binding, @bare for d in @dsl._examples_ when d instanceof Description
|
74
|
-
|
75
|
-
detectBindingError: ->
|
76
|
-
try
|
77
|
-
@binding = if @block.prototype then new @block else @block
|
78
|
-
if @binding and not (@bare = @block.bare)
|
79
|
-
for reserved in RESERVED when @binding[reserved]
|
80
|
-
throw new Error("'#{reserved}' method is reserved for oojspec usage only")
|
81
|
-
catch e
|
82
|
-
e.name = "syntax error"
|
83
|
-
@bindingError = e
|
84
|
-
|
85
|
-
injectDsl: -> @binding[p] = v for p, v of @dsl; return
|
86
|
-
|
87
|
-
removeDsl: -> delete @binding[p] for p in RESERVED_FOR_DESCRIPTION_DSL; return
|
88
|
-
|
89
|
-
run: (@assertions, @onFinish, @beforeBlocks = [], @afterBlocks = [])->
|
90
|
-
@runner.emit 'context:start', name: @description
|
91
|
-
if @bindingError
|
92
|
-
@runner.emit 'test:error', name: @description, error: @bindingError
|
93
|
-
@onDescriptionFinished @bindingError
|
94
|
-
else
|
95
|
-
@doRun()
|
96
|
-
|
97
|
-
doRun: -> @runAround @beforeBlocks, @afterBlocks, @onDescriptionFinished, @processDescriptionBlock
|
98
|
-
|
99
|
-
onDescriptionFinished: (error)=>
|
100
|
-
if error and not error.handled
|
101
|
-
error.handled = true
|
102
|
-
@runner.emit 'test:error', { name: 'Error running describe statements', error }
|
103
|
-
@runner.emit 'context:end'
|
104
|
-
@onFinish error
|
105
|
-
|
106
|
-
runAround: (befores, afters, onFinish, block)->
|
107
|
-
new AroundBlock(befores, afters, block).run @runner, @assertions, @binding, @bare, onFinish
|
108
|
-
|
109
|
-
processDescriptionBlock: (onFinish)=>
|
110
|
-
@runAround @dsl._beforeAllBlocks_, @dsl._afterAllBlocks_, onFinish, (@onExamplesFinished)=>
|
111
|
-
@runNextStep()
|
112
|
-
|
113
|
-
runNextStep: =>
|
114
|
-
(@onExamplesFinished(); return) unless @dsl._examples_.length
|
115
|
-
nextStep = @dsl._examples_.shift()
|
116
|
-
(@reportDeferred(nextStep.description); @runNextStep(); return) if nextStep.pending
|
117
|
-
nextTick =
|
118
|
-
if nextStep instanceof Description then =>
|
119
|
-
nextStep.run @assertions, @runNextStep, @dsl._beforeBlocks_, @dsl._afterBlocks_
|
120
|
-
else => # ExampleWithHooks
|
121
|
-
nextStep.run @runner, @assertions, @binding, @bare, @onExampleFinished
|
122
|
-
setTimeout nextTick, 0
|
123
|
-
|
124
|
-
onExampleFinished: (error)=>
|
125
|
-
(@runNextStep(); return) unless error and not error.handled
|
126
|
-
error.handled = true
|
127
|
-
console.log error
|
128
|
-
name = @description
|
129
|
-
name += " in #{error.source}" if error.source
|
130
|
-
@runner.emit 'test:error', { name, error }
|
131
|
-
@onFinish(error)
|
132
|
-
|
133
|
-
reportDeferred: (description)-> @runner.emit 'test:deferred', name: description
|
134
|
-
|
135
|
-
class DescribeDsl
|
136
|
-
addHook = (description, block, container)->
|
137
|
-
if typeof description is 'string'
|
138
|
-
return unless block # pending hook
|
139
|
-
block.description = description
|
140
|
-
else
|
141
|
-
block = description
|
142
|
-
throw new Error("block missing") unless block
|
143
|
-
container.push block
|
144
|
-
|
145
|
-
constructor: ->
|
146
|
-
@_beforeAllBlocks_ = []
|
147
|
-
@_beforeBlocks_ = []
|
148
|
-
@_afterBlocks_ = []
|
149
|
-
@_afterAllBlocks_ = []
|
150
|
-
@_examples_ = []
|
151
|
-
@_examplesCount_ = 0 # only examples, not describes
|
152
|
-
# aliases:
|
153
|
-
@it = @specify = @example
|
154
|
-
@context = @describe
|
155
|
-
@xit = @pending
|
156
|
-
|
157
|
-
beforeAll: (description, block)=> addHook description, block, @_beforeAllBlocks_
|
158
|
-
before: (description, block)=> addHook description, block, @_beforeBlocks_
|
159
|
-
after: (description, block)=> addHook description, block, @_afterBlocks_
|
160
|
-
afterAll: (description, block)=> addHook description, block, @_afterAllBlocks_
|
161
|
-
describe: (description, block)=>
|
162
|
-
@_examples_.push new Description(description, block, @_beforeBlocks_, @_afterBlocks_)
|
163
|
-
example: (description, block)=>
|
164
|
-
throw new Error("Examples must have a description and a block") unless description and block
|
165
|
-
@_examplesCount_++
|
166
|
-
@_examples_.push new ExampleWithHooks(description, @_beforeBlocks_, @_afterBlocks_, block)
|
167
|
-
pending: (description)=>
|
168
|
-
@_examplesCount_++
|
169
|
-
@_examples_.push {description, pending: true}
|
170
|
-
|
171
|
-
class AroundBlock
|
172
|
-
constructor: (@beforeBlocks, @afterBlocks, @block)->
|
173
|
-
|
174
|
-
run: (@runner, @assertions, @binding, @bare, @onFinish)->
|
175
|
-
@runGroup @beforeBlocks, ((e)=> @onBeforeError e), (wasSuccessful)=>
|
176
|
-
if wasSuccessful
|
177
|
-
@runMainBlock @block, (error)=>
|
178
|
-
@registerError error if error
|
179
|
-
@runAfterGroup()
|
180
|
-
else @runAfterGroup()
|
181
|
-
|
182
|
-
registerError: (error)->
|
183
|
-
@runner.emit 'oojspec:log:error', error
|
184
|
-
@error or= error
|
185
|
-
|
186
|
-
runMainBlock: (block, onFinish)->
|
187
|
-
try
|
188
|
-
block onFinish
|
189
|
-
catch error
|
190
|
-
error = new Error(error) if typeof error is 'string'
|
191
|
-
@registerError error
|
192
|
-
onFinish error
|
193
|
-
|
194
|
-
runGroup: (group, onError, onFinish)->
|
195
|
-
new ExampleGroupWithoutHooks(@assertions, @binding, @bare, group, onFinish, onError).run()
|
196
|
-
|
197
|
-
onBeforeError: (error)-> error.source = "before hook"; @registerError error
|
198
|
-
onAfterError: (error)-> error.source = "after hook"; @registerError error
|
199
|
-
runAfterGroup: -> @runGroup @afterBlocks, ((e)=> @onAfterError e), (=> @onAfterHooks())
|
200
|
-
onAfterHooks: -> @onFinish @error
|
201
|
-
|
202
|
-
class ExampleWithHooks extends AroundBlock
|
203
|
-
constructor: (@description, @beforeBlocks, @afterBlocks, @block)->
|
204
|
-
runMainBlock: (block, onFinish)-> new Example(block).run @assertions, @binding, @bare, onFinish
|
205
|
-
onAfterHooks: ->
|
206
|
-
@handleResult()
|
207
|
-
super
|
208
|
-
|
209
|
-
handleResult: ->
|
210
|
-
(@runner.emit 'test:success', name: @description; return) unless @error
|
211
|
-
@error.handled = true
|
212
|
-
if @error.name is 'AssertionError'
|
213
|
-
@runner.emit 'test:failure', name: @description, error: @error
|
214
|
-
return
|
215
|
-
|
216
|
-
if @error.timeout
|
217
|
-
@error.source or= 'example'
|
218
|
-
@runner.emit 'test:timeout', name: @description, error: @error
|
219
|
-
return
|
220
|
-
@error.name = 'Exception'
|
221
|
-
@error.name += " in #{@error.source}" if @error.source
|
222
|
-
@runner.emit 'test:error', name: @description, error: @error
|
223
|
-
|
224
|
-
class ExampleGroupWithoutHooks
|
225
|
-
constructor: (@assertions, @binding, @bare, @blocks, @onFinish, @onError)-> @nextIndex = 0
|
226
|
-
|
227
|
-
run: ->
|
228
|
-
@wasSuccessful = true
|
229
|
-
setTimeout @nextTick, 0
|
230
|
-
|
231
|
-
nextTick: =>
|
232
|
-
(@onFinish(@wasSuccessful); return) unless @nextIndex < @blocks.length
|
233
|
-
block = @blocks[@nextIndex++]
|
234
|
-
new Example(block).run @assertions, @binding, @bare, (error)=>
|
235
|
-
(@wasSuccessful = false; @onError error) if error
|
236
|
-
setTimeout @nextTick, 0
|
237
|
-
|
238
|
-
class Example
|
239
|
-
TICK = 10 # ms
|
240
|
-
constructor: (@exampleBlock)-> @describeDsl = {}
|
241
|
-
|
242
|
-
run: (@assertions, @binding, @bare, @onFinish)->
|
243
|
-
@dsl = new ExampleDsl(@assertions.assert, @assertions.expect, @assertions.fail, \
|
244
|
-
@assertions.refute)
|
245
|
-
if @binding and not @bare
|
246
|
-
for m in RESERVED_FOR_DESCRIPTION_DSL
|
247
|
-
@describeDsl[m] = b if b = @binding[m]
|
248
|
-
delete @binding[m]
|
249
|
-
(@binding[m] = b if b = @dsl[m]) for m in RESERVED_FOR_EXAMPLE_DSL
|
250
|
-
@tryBlock @exampleBlock, ->
|
251
|
-
if @binding and not @bare
|
252
|
-
delete @binding.runs
|
253
|
-
delete @binding.waitsFor
|
254
|
-
(@finish(); return) unless (@steps = @dsl._asyncQueue_).length
|
255
|
-
@runNextAsyncStep()
|
256
|
-
|
257
|
-
tryBlock: (block, onSuccess)->
|
258
|
-
try
|
259
|
-
binding = @binding or @dsl
|
260
|
-
onSuccess.call this, block.call(binding, @dsl)
|
261
|
-
catch error
|
262
|
-
error = new Error(error) if typeof error is 'string'
|
263
|
-
error.message = "'#{error.message}' in '#{block.description}'" if block?.description
|
264
|
-
@finish error
|
265
|
-
|
266
|
-
runNextAsyncStep: ->
|
267
|
-
(@finish(); return) unless @steps.length
|
268
|
-
step = @steps.shift()
|
269
|
-
if step instanceof Function
|
270
|
-
@tryBlock step, @runNextAsyncStep
|
271
|
-
else
|
272
|
-
@waitsFor step...
|
273
|
-
|
274
|
-
waitsFor: (@condition, timeout = @binding?.timeout or oojspec.timeout, @description)->
|
275
|
-
@deadline = timeout + new Date().getTime()
|
276
|
-
@keepTryingCondition()
|
277
|
-
|
278
|
-
keepTryingCondition: =>
|
279
|
-
@tryBlock @condition, (result)->
|
280
|
-
(@runNextAsyncStep(); return) if result
|
281
|
-
(@finish {timeout: true, @description}; return) if new Date().getTime() > @deadline
|
282
|
-
setTimeout @keepTryingCondition, TICK
|
283
|
-
|
284
|
-
finish: ->
|
285
|
-
if @binding and not @bare
|
286
|
-
(@binding[m] = b if b = @describeDsl[m]) for m in RESERVED_FOR_DESCRIPTION_DSL
|
287
|
-
delete @binding[m] for m in RESERVED_FOR_EXAMPLE_DSL
|
288
|
-
@onFinish.apply null, arguments
|
289
|
-
|
290
|
-
class ExampleDsl
|
291
|
-
constructor: (@assert, @expect, @fail, @refute)-> @_asyncQueue_ = []
|
292
|
-
|
293
|
-
runs: (step)=> @_asyncQueue_.push step
|
294
|
-
|
295
|
-
waitsFor: =>
|
296
|
-
for a in arguments
|
297
|
-
(condition = a; continue) if typeof a is "function"
|
298
|
-
(timeout = a; continue) if typeof a is "number"
|
299
|
-
(description = a; continue) if typeof a is "string"
|
300
|
-
@_asyncQueue_.push [condition, timeout, description]
|
301
|
-
|
302
|
-
class StepContext
|
303
|
-
constructor: (@assert, @expect, @fail)->
|
9
|
+
(_ = @oojspec._).extend = (extended, extender)->
|
10
|
+
extended[p] = v for p, v of extender when p[0] isnt '_'
|
@@ -0,0 +1,316 @@
|
|
1
|
+
# =require buster/all
|
2
|
+
# =require ./utils
|
3
|
+
|
4
|
+
_ = oojspec._
|
5
|
+
|
6
|
+
_.extend oojspec, new class OojspecRunner
|
7
|
+
constructor: ->
|
8
|
+
@timeout = 1000 # 1s - default timeout
|
9
|
+
@events = buster.create buster.eventEmitter
|
10
|
+
@descriptions = []
|
11
|
+
@_registerEventHandlers()
|
12
|
+
@_initializeStats()
|
13
|
+
@params = _.parseParams()
|
14
|
+
# avoid too much parameters between methods, acts like a context:
|
15
|
+
@params.events = @events
|
16
|
+
@params.assertions = @assertions
|
17
|
+
|
18
|
+
_registerEventHandlers: ->
|
19
|
+
@assertions = buster.assertions
|
20
|
+
(logFormatter = buster.create buster.format).quoteStrings = false
|
21
|
+
@assertions.format = buster.bind logFormatter, "ascii"
|
22
|
+
@assertions.on 'pass', => @stats.assertions++
|
23
|
+
@assertions.on 'failure', => @stats.failures++
|
24
|
+
#@events.on 'context:start', => @stats.contexts++
|
25
|
+
@events.on 'test:timeout', => @stats.timeouts++; @assertions.emit 'failure'
|
26
|
+
@events.on 'test:error', => @stats.errors++
|
27
|
+
@events.on 'test:deferred', => @stats.deferred++
|
28
|
+
@events.on 'oojspec:examples:add', (count)=> @stats.tests += count
|
29
|
+
|
30
|
+
_initializeStats: ->
|
31
|
+
@stats =
|
32
|
+
contexts: 0
|
33
|
+
tests: 0
|
34
|
+
assertions: 0
|
35
|
+
errors: 0
|
36
|
+
failures: 0
|
37
|
+
timeouts: 0
|
38
|
+
deferred: 0
|
39
|
+
|
40
|
+
exposeAll: => window.describe = @describe
|
41
|
+
autorun: => @runSpecs() unless @disableAutorun
|
42
|
+
|
43
|
+
runSpecs: =>
|
44
|
+
@reporter = buster.reporters.html.create detectCssPath: false
|
45
|
+
@reporter.listen @events
|
46
|
+
d.processDsl @params for d in @descriptions
|
47
|
+
@events.emit 'suite:start', name: "Specs"
|
48
|
+
@_runNextDescription()
|
49
|
+
|
50
|
+
_runNextDescription: =>
|
51
|
+
(@events.emit 'suite:end', @stats; return) unless @descriptions.length
|
52
|
+
@descriptions.shift().run @params, @_runNextDescription
|
53
|
+
|
54
|
+
describe: (description, block)=>
|
55
|
+
@stats.contexts++ # only root descriptions will be count
|
56
|
+
@descriptions.push new Description(description, block)
|
57
|
+
|
58
|
+
RESERVED_FOR_DESCRIPTION_DSL = ['beforeAll', 'before', 'after', 'afterAll', 'describe', 'context',
|
59
|
+
'example', 'it', 'specify', 'pending', 'xit']
|
60
|
+
RESERVED_FOR_EXAMPLE_DSL = ['assert', 'expect', 'fail', 'refute', 'waitsFor', 'runs']
|
61
|
+
class Description
|
62
|
+
RESERVED = RESERVED_FOR_DESCRIPTION_DSL.concat RESERVED_FOR_EXAMPLE_DSL
|
63
|
+
|
64
|
+
constructor: (@description, @block)->
|
65
|
+
if @description.runSpecs or @description.prototype?.runSpecs
|
66
|
+
@block = @description
|
67
|
+
@description = @block.description or @block.name
|
68
|
+
|
69
|
+
processDsl: (@params, @binding, @bare)->
|
70
|
+
@events = params.events
|
71
|
+
@dsl = new DescribeDsl
|
72
|
+
(@block.runSpecs or @block.prototype?.runSpecs) and @detectBindingError()
|
73
|
+
|
74
|
+
@binding or= {}
|
75
|
+
@injectDsl() unless @bare
|
76
|
+
if @block.runSpecs or @block.prototype?.runSpecs
|
77
|
+
@binding.runSpecs @dsl
|
78
|
+
else
|
79
|
+
@block.call @binding, @dsl
|
80
|
+
@events.emit 'oojspec:examples:add', @dsl._examplesCount_
|
81
|
+
@removeDsl() unless @bare
|
82
|
+
@bare or= @binding.bare
|
83
|
+
|
84
|
+
d.processDsl @params, @binding, @bare for d in @dsl._examples_ when d instanceof Description
|
85
|
+
|
86
|
+
detectBindingError: ->
|
87
|
+
try
|
88
|
+
@binding = if @block.prototype then new @block else @block
|
89
|
+
if @binding and not (@bare = @block.bare)
|
90
|
+
for reserved in RESERVED when @binding[reserved]
|
91
|
+
throw new Error("'#{reserved}' method is reserved for oojspec usage only")
|
92
|
+
catch e
|
93
|
+
e.name = "syntax error"
|
94
|
+
@bindingError = e
|
95
|
+
|
96
|
+
injectDsl: -> @binding[p] = v for p, v of @dsl; return
|
97
|
+
|
98
|
+
removeDsl: -> delete @binding[p] for p in RESERVED_FOR_DESCRIPTION_DSL; return
|
99
|
+
|
100
|
+
run: (@params, @onFinish, @beforeBlocks = [], @afterBlocks = [])->
|
101
|
+
@events.emit 'context:start', name: @description
|
102
|
+
if @bindingError
|
103
|
+
@events.emit 'test:error', name: @description, error: @bindingError
|
104
|
+
@onDescriptionFinished @bindingError
|
105
|
+
else
|
106
|
+
@doRun()
|
107
|
+
|
108
|
+
doRun: -> @runAround @beforeBlocks, @afterBlocks, @onDescriptionFinished, @processDescriptionBlock
|
109
|
+
|
110
|
+
onDescriptionFinished: (error)=>
|
111
|
+
if error and not error.handled
|
112
|
+
error.handled = true
|
113
|
+
@events.emit 'test:error', { name: 'Error running describe statements', error }
|
114
|
+
@events.emit 'context:end'
|
115
|
+
@onFinish error
|
116
|
+
|
117
|
+
runAround: (befores, afters, onFinish, block)->
|
118
|
+
new AroundBlock(befores, afters, block).run @params, @binding, @bare, onFinish
|
119
|
+
|
120
|
+
processDescriptionBlock: (onFinish)=>
|
121
|
+
@runAround @dsl._beforeAllBlocks_, @dsl._afterAllBlocks_, onFinish, (@onExamplesFinished)=>
|
122
|
+
@runNextStep()
|
123
|
+
|
124
|
+
runNextStep: =>
|
125
|
+
(@onExamplesFinished(); return) unless @dsl._examples_.length
|
126
|
+
nextStep = @dsl._examples_.shift()
|
127
|
+
(@reportDeferred(nextStep.description); @runNextStep(); return) if nextStep.pending
|
128
|
+
nextTick =
|
129
|
+
if nextStep instanceof Description then =>
|
130
|
+
nextStep.run @params, @runNextStep, @dsl._beforeBlocks_, @dsl._afterBlocks_
|
131
|
+
else => # ExampleWithHooks
|
132
|
+
nextStep.run @params, @binding, @bare, @onExampleFinished
|
133
|
+
setTimeout nextTick, 0
|
134
|
+
|
135
|
+
onExampleFinished: (error)=>
|
136
|
+
(@runNextStep(); return) unless error and not error.handled
|
137
|
+
error.handled = true
|
138
|
+
console.log error
|
139
|
+
name = @description
|
140
|
+
name += " in #{error.source}" if error.source
|
141
|
+
@events.emit 'test:error', { name, error }
|
142
|
+
@onFinish(error)
|
143
|
+
|
144
|
+
reportDeferred: (description)-> @events.emit 'test:deferred', name: description
|
145
|
+
|
146
|
+
class DescribeDsl
|
147
|
+
addHook = (description, block, container)->
|
148
|
+
if typeof description is 'string'
|
149
|
+
return unless block # pending hook
|
150
|
+
block.description = description
|
151
|
+
else
|
152
|
+
block = description
|
153
|
+
throw new Error("block missing") unless block
|
154
|
+
container.push block
|
155
|
+
|
156
|
+
constructor: ->
|
157
|
+
@_beforeAllBlocks_ = []
|
158
|
+
@_beforeBlocks_ = []
|
159
|
+
@_afterBlocks_ = []
|
160
|
+
@_afterAllBlocks_ = []
|
161
|
+
@_examples_ = []
|
162
|
+
@_examplesCount_ = 0 # only examples, not describes
|
163
|
+
# aliases:
|
164
|
+
@it = @specify = @example
|
165
|
+
@context = @describe
|
166
|
+
@xit = @pending
|
167
|
+
|
168
|
+
beforeAll: (description, block)=> addHook description, block, @_beforeAllBlocks_
|
169
|
+
before: (description, block)=> addHook description, block, @_beforeBlocks_
|
170
|
+
after: (description, block)=> addHook description, block, @_afterBlocks_
|
171
|
+
afterAll: (description, block)=> addHook description, block, @_afterAllBlocks_
|
172
|
+
describe: (description, block)=>
|
173
|
+
@_examples_.push new Description(description, block, @_beforeBlocks_, @_afterBlocks_)
|
174
|
+
example: (description, block)=>
|
175
|
+
throw new Error("Examples must have a description and a block") unless description and block
|
176
|
+
@_examplesCount_++
|
177
|
+
@_examples_.push new ExampleWithHooks(description, @_beforeBlocks_, @_afterBlocks_, block)
|
178
|
+
pending: (description)=>
|
179
|
+
@_examplesCount_++
|
180
|
+
@_examples_.push {description, pending: true}
|
181
|
+
|
182
|
+
class AroundBlock
|
183
|
+
constructor: (@beforeBlocks, @afterBlocks, @block)->
|
184
|
+
|
185
|
+
run: (@params, @binding, @bare, @onFinish)->
|
186
|
+
@events = @params.events
|
187
|
+
@runGroup @beforeBlocks, ((e)=> @onBeforeError e), (wasSuccessful)=>
|
188
|
+
if wasSuccessful
|
189
|
+
@runMainBlock @block, (error)=>
|
190
|
+
@registerError error if error
|
191
|
+
@runAfterGroup()
|
192
|
+
else @runAfterGroup()
|
193
|
+
|
194
|
+
registerError: (error)->
|
195
|
+
@events.emit 'oojspec:log:error', error
|
196
|
+
@error or= error
|
197
|
+
|
198
|
+
runMainBlock: (block, onFinish)->
|
199
|
+
try
|
200
|
+
block onFinish
|
201
|
+
catch error
|
202
|
+
error = new Error(error) if typeof error is 'string'
|
203
|
+
@registerError error
|
204
|
+
onFinish error
|
205
|
+
|
206
|
+
runGroup: (group, onError, onFinish)->
|
207
|
+
new ExampleGroupWithoutHooks(@params, @binding, @bare, group, onFinish, onError).run()
|
208
|
+
|
209
|
+
onBeforeError: (error)-> error.source = "before hook"; @registerError error
|
210
|
+
onAfterError: (error)-> error.source = "after hook"; @registerError error
|
211
|
+
runAfterGroup: -> @runGroup @afterBlocks, ((e)=> @onAfterError e), (=> @onAfterHooks())
|
212
|
+
onAfterHooks: -> @onFinish @error
|
213
|
+
|
214
|
+
class ExampleWithHooks extends AroundBlock
|
215
|
+
constructor: (@description, @beforeBlocks, @afterBlocks, @block)->
|
216
|
+
runMainBlock: (block, onFinish)-> new Example(block).run @params, @binding, @bare, onFinish
|
217
|
+
onAfterHooks: ->
|
218
|
+
@handleResult()
|
219
|
+
super
|
220
|
+
|
221
|
+
handleResult: ->
|
222
|
+
(@events.emit 'test:success', name: @description; return) unless @error
|
223
|
+
@error.handled = true
|
224
|
+
if @error.name is 'AssertionError'
|
225
|
+
@events.emit 'test:failure', name: @description, error: @error
|
226
|
+
return
|
227
|
+
|
228
|
+
if @error.timeout
|
229
|
+
@error.source or= 'example'
|
230
|
+
@events.emit 'test:timeout', name: @description, error: @error
|
231
|
+
return
|
232
|
+
@error.name = 'Exception'
|
233
|
+
@error.name += " in #{@error.source}" if @error.source
|
234
|
+
@events.emit 'test:error', name: @description, error: @error
|
235
|
+
|
236
|
+
class ExampleGroupWithoutHooks
|
237
|
+
constructor: (@params, @binding, @bare, @blocks, @onFinish, @onError)->
|
238
|
+
@nextIndex = 0
|
239
|
+
|
240
|
+
run: ->
|
241
|
+
@wasSuccessful = true
|
242
|
+
setTimeout @nextTick, 0
|
243
|
+
|
244
|
+
nextTick: =>
|
245
|
+
(@onFinish(@wasSuccessful); return) unless @nextIndex < @blocks.length
|
246
|
+
block = @blocks[@nextIndex++]
|
247
|
+
new Example(block).run @params, @binding, @bare, (error)=>
|
248
|
+
(@wasSuccessful = false; @onError error) if error
|
249
|
+
setTimeout @nextTick, 0
|
250
|
+
|
251
|
+
class Example
|
252
|
+
TICK = 10 # ms
|
253
|
+
constructor: (@exampleBlock)-> @describeDsl = {}
|
254
|
+
|
255
|
+
run: (@params, @binding, @bare, @onFinish)->
|
256
|
+
a = @params.assertions
|
257
|
+
@dsl = new ExampleDsl(a.assert, a.expect, a.fail, a.refute)
|
258
|
+
if @binding and not @bare
|
259
|
+
for m in RESERVED_FOR_DESCRIPTION_DSL
|
260
|
+
@describeDsl[m] = b if b = @binding[m]
|
261
|
+
delete @binding[m]
|
262
|
+
(@binding[m] = b if b = @dsl[m]) for m in RESERVED_FOR_EXAMPLE_DSL
|
263
|
+
@tryBlock @exampleBlock, ->
|
264
|
+
if @binding and not @bare
|
265
|
+
delete @binding.runs
|
266
|
+
delete @binding.waitsFor
|
267
|
+
(@finish(); return) unless (@steps = @dsl._asyncQueue_).length
|
268
|
+
@runNextAsyncStep()
|
269
|
+
|
270
|
+
tryBlock: (block, onSuccess)->
|
271
|
+
try
|
272
|
+
binding = @binding or @dsl
|
273
|
+
onSuccess.call this, block.call(binding, @dsl)
|
274
|
+
catch error
|
275
|
+
error = new Error(error) if typeof error is 'string'
|
276
|
+
error.message = "'#{error.message}' in '#{block.description}'" if block?.description
|
277
|
+
@finish error
|
278
|
+
|
279
|
+
runNextAsyncStep: ->
|
280
|
+
(@finish(); return) unless @steps.length
|
281
|
+
step = @steps.shift()
|
282
|
+
if typeof step is 'function'
|
283
|
+
@tryBlock step, @runNextAsyncStep
|
284
|
+
else
|
285
|
+
@waitsFor step...
|
286
|
+
|
287
|
+
waitsFor: (@condition, timeout = @binding?.timeout or oojspec.timeout, @description)->
|
288
|
+
@deadline = timeout + new Date().getTime()
|
289
|
+
@keepTryingCondition()
|
290
|
+
|
291
|
+
keepTryingCondition: =>
|
292
|
+
@tryBlock @condition, (result)->
|
293
|
+
(@runNextAsyncStep(); return) if result
|
294
|
+
(@finish {timeout: true, @description}; return) if new Date().getTime() > @deadline
|
295
|
+
setTimeout @keepTryingCondition, TICK
|
296
|
+
|
297
|
+
finish: ->
|
298
|
+
if @binding and not @bare
|
299
|
+
(@binding[m] = b if b = @describeDsl[m]) for m in RESERVED_FOR_DESCRIPTION_DSL
|
300
|
+
delete @binding[m] for m in RESERVED_FOR_EXAMPLE_DSL
|
301
|
+
@onFinish.apply null, arguments
|
302
|
+
|
303
|
+
class ExampleDsl
|
304
|
+
constructor: (@assert, @expect, @fail, @refute)-> @_asyncQueue_ = []
|
305
|
+
|
306
|
+
runs: (step)=> @_asyncQueue_.push step
|
307
|
+
|
308
|
+
waitsFor: =>
|
309
|
+
for a in arguments
|
310
|
+
(condition = a; continue) if typeof a is "function"
|
311
|
+
(timeout = a; continue) if typeof a is "number"
|
312
|
+
(description = a; continue) if typeof a is "string"
|
313
|
+
@_asyncQueue_.push [condition, timeout, description]
|
314
|
+
|
315
|
+
class StepContext
|
316
|
+
constructor: (@assert, @expect, @fail)->
|
data/lib/oojspec/version.rb
CHANGED
metadata
CHANGED
@@ -1,50 +1,46 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oojspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.9
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Rodrigo Rosenfeld Rosas
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-01-28 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: coffee-rails
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rails-sandbox-assets
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
|
-
description:
|
47
|
-
|
41
|
+
description: |2-
|
42
|
+
A test runner similar to RSpec for client-side code built
|
43
|
+
on top of Buster.js that is more suited for integration tests.
|
48
44
|
email:
|
49
45
|
- rr.rosas@gmail.com
|
50
46
|
executables: []
|
@@ -52,7 +48,9 @@ extensions: []
|
|
52
48
|
extra_rdoc_files: []
|
53
49
|
files:
|
54
50
|
- app/views/oojspec/runner.html.erb
|
55
|
-
- lib/assets/javascripts/
|
51
|
+
- lib/assets/javascripts/oojspec/utils.js.coffee
|
52
|
+
- lib/assets/javascripts/oojspec/runner.js.coffee
|
53
|
+
- lib/assets/javascripts/oojspec/progress.js.coffee
|
56
54
|
- lib/assets/javascripts/oojspec.js.coffee
|
57
55
|
- lib/assets/stylesheets/oojspec.css.erb
|
58
56
|
- lib/assets/stylesheets/oojspec/progress.css
|
@@ -75,32 +73,25 @@ files:
|
|
75
73
|
- README.md
|
76
74
|
homepage: http://github.com/rosenfeld/oojspec
|
77
75
|
licenses: []
|
76
|
+
metadata: {}
|
78
77
|
post_install_message:
|
79
78
|
rdoc_options: []
|
80
79
|
require_paths:
|
81
80
|
- lib
|
82
81
|
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
-
none: false
|
84
82
|
requirements:
|
85
|
-
- -
|
83
|
+
- - '>='
|
86
84
|
- !ruby/object:Gem::Version
|
87
85
|
version: '0'
|
88
|
-
segments:
|
89
|
-
- 0
|
90
|
-
hash: -2878099860768326426
|
91
86
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
-
none: false
|
93
87
|
requirements:
|
94
|
-
- -
|
88
|
+
- - '>='
|
95
89
|
- !ruby/object:Gem::Version
|
96
90
|
version: '0'
|
97
|
-
segments:
|
98
|
-
- 0
|
99
|
-
hash: -2878099860768326426
|
100
91
|
requirements: []
|
101
92
|
rubyforge_project:
|
102
|
-
rubygems_version:
|
93
|
+
rubygems_version: 2.0.14
|
103
94
|
signing_key:
|
104
|
-
specification_version:
|
95
|
+
specification_version: 4
|
105
96
|
summary: Object-oriented client-side testing
|
106
97
|
test_files: []
|