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 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
- # =require ./progress
2
+ # =require_tree ./oojspec
4
3
 
5
- window.oojspec = new class OojspecRunner
6
- constructor: ->
7
- @timeout = 1000 # 1s - default timeout
8
- @runner = buster.create buster.eventEmitter
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
- @stats =
22
- contexts: 0
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 '_'
@@ -1,5 +1,7 @@
1
+ # =require ./runner
2
+
1
3
  new class ProgressStats
2
- constructor: (@eh = oojspec.runner)->
4
+ constructor: (@eh = oojspec.events)->
3
5
  @total = @count = 0
4
6
  @eh.on 'suite:start', @createElements
5
7
  @eh.on 'oojspec:examples:add', (count)=> @total += count
@@ -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)->
@@ -0,0 +1,7 @@
1
+ oojspec._.parseParams = (search = window.location.search)->
2
+ d = (str)-> decodeURIComponent str.replace /\+/g, ' '
3
+ query = search.substring 1
4
+ regex = /(.*?)=([^\&]*)&?/g
5
+ params = {}
6
+ params[d(m[1])] = d(m[2]) while m = regex.exec query
7
+ params
@@ -1,3 +1,3 @@
1
1
  module Oojspec
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
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.8
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: 2012-08-01 00:00:00.000000000 Z
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: ! " A test runner similar to RSpec for client-side code built\n on
47
- top of Buster.js that is more suited for integration tests."
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/progress.js.coffee
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: 1.8.24
93
+ rubygems_version: 2.0.14
103
94
  signing_key:
104
- specification_version: 3
95
+ specification_version: 4
105
96
  summary: Object-oriented client-side testing
106
97
  test_files: []