oojspec 0.0.8 → 0.0.9
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.
- 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
|
+
[](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: []
|