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 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 = ['beforeAll', 'before', 'after', 'afterAll', 'describe', 'context',
46
- 'example', 'it', 'specify', 'pending', 'xit']
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, @context, @onFinish, @beforeBlocks = [], @afterBlocks = [])->
55
+ run: (@runner, @assertions, @binding, @bare, @onFinish, @beforeBlocks = [], @afterBlocks = [])->
50
56
  @runner.emit 'context:start', name: @description
51
57
  @dsl = new DescribeDsl
52
- if c = @context
53
- for reserved in RESERVED
54
- try
55
- throw new Error("'#{reserved}' method is reserved for oojspec usage only") if c[reserved]
56
- catch e
57
- e.name = "syntax error"
58
- @runner.emit 'test:error', name: @description, error: e
59
- @onDescriptionFinished(e)
60
- c[reserved] = @dsl[reserved]
61
- @runAround @beforeBlocks, @afterBlocks, @onDescriptionFinished, @processDescriptionBlock
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, @context, onFinish
87
+ new AroundBlock(befores, afters, block).run @runner, @assertions, @binding, @bare, onFinish
72
88
 
73
89
  processDescriptionBlock: (onFinish)=>
74
- context = @context or @dsl
75
- @block.call context, context
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 => nextStep
85
- .run @runner, @assertions, @context, @runNextStep, @dsl._beforeBlocks_, @dsl._afterBlocks_
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, @context, @onExampleFinished
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, @context, @onFinish)->
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, @context, group, onFinish, onError).run()
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, @context, onFinish
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, @context, @blocks, @onFinish, @onError)-> @nextIndex = 0
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, @context, (error)=>
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, @context, @onFinish)->
224
+ run: (@assertions, @binding, @bare, @onFinish)->
203
225
  @dsl = new ExampleDsl(@assertions.assert, @assertions.expect, @assertions.fail, \
204
226
  @assertions.refute)
205
- if @context
206
- throw "runs and waitsFor are reserved attributes" if @context.runs or @context.waitsFor
207
- @context.runs = @dsl.runs
208
- @context.waitsFor = @dsl.waitsFor
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 @context
211
- delete @context.runs
212
- delete @context.waitsFor
213
- (@onFinish(); return) unless (@steps = @dsl._asyncQueue_).length
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
- context = @context or @dsl
219
- onSuccess.call this, block.call context, context
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.description
223
- @onFinish error
245
+ error.message = "'#{error.message}' in '#{block.description}'" if block?.description
246
+ @finish error
224
247
 
225
248
  runNextAsyncStep: ->
226
- (@onFinish(); return) unless @steps.length
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
- (@onFinish {timeout: true, @description}; return) if new Date().getTime() > @deadline
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
 
@@ -1,3 +1,3 @@
1
1
  module Oojspec
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -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) cssPath = busterTestPath(reporter.doc) + "buster-test.css";
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(path.join(__dirname, "../../../resources/buster-test.css"))
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.2
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-15 00:00:00.000000000 Z
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: -240007266511017517
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: -240007266511017517
97
+ hash: -1275332504698129146
98
98
  requirements: []
99
99
  rubyforge_project:
100
100
  rubygems_version: 1.8.24