dchelimsky-rspec-stories 1.0.0

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.
Files changed (79) hide show
  1. data/History.txt +5 -0
  2. data/License.txt +22 -0
  3. data/Manifest.txt +78 -0
  4. data/README.txt +23 -0
  5. data/Rakefile +87 -0
  6. data/init.rb +4 -0
  7. data/lib/spec/runner/formatter/story/html_formatter.rb +174 -0
  8. data/lib/spec/runner/formatter/story/plain_text_formatter.rb +194 -0
  9. data/lib/spec/runner/formatter/story/progress_bar_formatter.rb +42 -0
  10. data/lib/spec/runner/options_extensions.rb +25 -0
  11. data/lib/spec/stories.rb +11 -0
  12. data/lib/spec/story/extensions.rb +3 -0
  13. data/lib/spec/story/extensions/main.rb +86 -0
  14. data/lib/spec/story/extensions/regexp.rb +9 -0
  15. data/lib/spec/story/extensions/string.rb +9 -0
  16. data/lib/spec/story/given_scenario.rb +14 -0
  17. data/lib/spec/story/runner.rb +57 -0
  18. data/lib/spec/story/runner/plain_text_story_runner.rb +48 -0
  19. data/lib/spec/story/runner/scenario_collector.rb +18 -0
  20. data/lib/spec/story/runner/scenario_runner.rb +54 -0
  21. data/lib/spec/story/runner/story_mediator.rb +137 -0
  22. data/lib/spec/story/runner/story_parser.rb +247 -0
  23. data/lib/spec/story/runner/story_runner.rb +74 -0
  24. data/lib/spec/story/scenario.rb +14 -0
  25. data/lib/spec/story/step.rb +70 -0
  26. data/lib/spec/story/step_group.rb +89 -0
  27. data/lib/spec/story/step_mother.rb +38 -0
  28. data/lib/spec/story/story.rb +39 -0
  29. data/lib/spec/story/version.rb +15 -0
  30. data/lib/spec/story/world.rb +124 -0
  31. data/resources/rake/verify_rcov.rake +7 -0
  32. data/rspec-stories.gemspec +35 -0
  33. data/spec/spec.opts +6 -0
  34. data/spec/spec/runner/formatter/story/html_formatter_spec.rb +135 -0
  35. data/spec/spec/runner/formatter/story/plain_text_formatter_spec.rb +600 -0
  36. data/spec/spec/runner/formatter/story/progress_bar_formatter_spec.rb +82 -0
  37. data/spec/spec/runner/most_recent_spec.rb +0 -0
  38. data/spec/spec/runner/options_extensions_spec.rb +31 -0
  39. data/spec/spec/runner/resources/a_bar.rb +0 -0
  40. data/spec/spec/runner/resources/a_foo.rb +0 -0
  41. data/spec/spec/runner/resources/a_spec.rb +1 -0
  42. data/spec/spec/runner/resources/custom_example_group_runner.rb +14 -0
  43. data/spec/spec/runner/resources/utf8_encoded.rb +7 -0
  44. data/spec/spec/runner_spec.rb +11 -0
  45. data/spec/spec/spec_classes.rb +133 -0
  46. data/spec/spec/story/builders.rb +46 -0
  47. data/spec/spec/story/extensions/main_spec.rb +161 -0
  48. data/spec/spec/story/extensions_spec.rb +14 -0
  49. data/spec/spec/story/given_scenario_spec.rb +27 -0
  50. data/spec/spec/story/runner/plain_text_story_runner_spec.rb +90 -0
  51. data/spec/spec/story/runner/scenario_collector_spec.rb +27 -0
  52. data/spec/spec/story/runner/scenario_runner_spec.rb +214 -0
  53. data/spec/spec/story/runner/story_mediator_spec.rb +143 -0
  54. data/spec/spec/story/runner/story_parser_spec.rb +401 -0
  55. data/spec/spec/story/runner/story_runner_spec.rb +294 -0
  56. data/spec/spec/story/runner_spec.rb +93 -0
  57. data/spec/spec/story/scenario_spec.rb +18 -0
  58. data/spec/spec/story/step_group_spec.rb +157 -0
  59. data/spec/spec/story/step_mother_spec.rb +84 -0
  60. data/spec/spec/story/step_spec.rb +272 -0
  61. data/spec/spec/story/story_helper.rb +2 -0
  62. data/spec/spec/story/story_spec.rb +84 -0
  63. data/spec/spec/story/world_spec.rb +423 -0
  64. data/spec/spec_helper.rb +84 -0
  65. data/story_server/prototype/javascripts/builder.js +136 -0
  66. data/story_server/prototype/javascripts/controls.js +972 -0
  67. data/story_server/prototype/javascripts/dragdrop.js +976 -0
  68. data/story_server/prototype/javascripts/effects.js +1117 -0
  69. data/story_server/prototype/javascripts/prototype.js +4140 -0
  70. data/story_server/prototype/javascripts/rspec.js +149 -0
  71. data/story_server/prototype/javascripts/scriptaculous.js +58 -0
  72. data/story_server/prototype/javascripts/slider.js +276 -0
  73. data/story_server/prototype/javascripts/sound.js +55 -0
  74. data/story_server/prototype/javascripts/unittest.js +568 -0
  75. data/story_server/prototype/lib/server.rb +24 -0
  76. data/story_server/prototype/stories.html +176 -0
  77. data/story_server/prototype/stylesheets/rspec.css +136 -0
  78. data/story_server/prototype/stylesheets/test.css +90 -0
  79. metadata +154 -0
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require File.dirname(__FILE__) + '/builders'
@@ -0,0 +1,84 @@
1
+ require File.dirname(__FILE__) + '/story_helper'
2
+
3
+ module Spec
4
+ module Story
5
+ describe Story do
6
+ it 'should run itself in a given object' do
7
+ # given
8
+ $instance = nil
9
+ story = Story.new 'title', 'narrative' do
10
+ $instance = self
11
+ end
12
+ object = Object.new
13
+
14
+ # when
15
+ story.run_in(object)
16
+
17
+ # then
18
+ $instance.should be(object)
19
+ end
20
+
21
+ it 'should not raise an error if no block is supplied' do
22
+ # when
23
+ error = exception_from { Story.new 'title', 'narrative' }
24
+
25
+ # then
26
+ error.should be_nil
27
+ end
28
+
29
+ it "should raise an error when an error is raised running in another object" do
30
+ #given
31
+ story = Story.new 'title', 'narrative' do
32
+ raise "this is raised in the story"
33
+ end
34
+ object = Object.new
35
+
36
+ # when/then
37
+ lambda do
38
+ story.run_in(object)
39
+ end.should raise_error
40
+ end
41
+
42
+ it "should use the steps it is told to using a StepGroup" do
43
+ story = Story.new("title", "narrative", :steps_for => steps = StepGroup.new) do end
44
+ assignee = mock("assignee")
45
+ assignee.should_receive(:use).with(steps)
46
+ story.assign_steps_to(assignee)
47
+ end
48
+
49
+ it "should use the steps it is told to using a key" do
50
+ begin
51
+ orig_rspec_story_steps = $rspec_story_steps
52
+ $rspec_story_steps = StepGroupHash.new
53
+ $rspec_story_steps[:foo] = steps = Object.new
54
+
55
+ story = Story.new("title", "narrative", :steps_for => :foo) do end
56
+ assignee = mock("assignee")
57
+
58
+ assignee.should_receive(:use).with(steps)
59
+ story.assign_steps_to(assignee)
60
+ ensure
61
+ $rspec_story_steps = orig_rspec_story_steps
62
+ end
63
+ end
64
+
65
+ it "should use the steps it is told to using multiple keys" do
66
+ begin
67
+ orig_rspec_story_steps = $rspec_story_steps
68
+ $rspec_story_steps = StepGroupHash.new
69
+ $rspec_story_steps[:foo] = foo_steps = Object.new
70
+ $rspec_story_steps[:bar] = bar_steps = Object.new
71
+
72
+ story = Story.new("title", "narrative", :steps_for => [:foo, :bar]) do end
73
+ assignee = mock("assignee")
74
+
75
+ assignee.should_receive(:use).with(foo_steps)
76
+ assignee.should_receive(:use).with(bar_steps)
77
+ story.assign_steps_to(assignee)
78
+ ensure
79
+ $rspec_story_steps = orig_rspec_story_steps
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,423 @@
1
+ require File.dirname(__FILE__) + '/story_helper'
2
+
3
+ require 'spec/story'
4
+
5
+ module Spec
6
+ module Story
7
+ describe World do
8
+ before :each do
9
+ World.listeners.clear
10
+ end
11
+
12
+ after :each do
13
+ World.listeners.clear
14
+ World.step_mother.clear
15
+ end
16
+
17
+ it 'should create an object that mixes in a World' do
18
+ # when
19
+ obj = World::create
20
+
21
+ # then
22
+ obj.should be_kind_of(World)
23
+ end
24
+
25
+ it 'should create a World from any object type' do
26
+ # when
27
+ obj = World::create String
28
+
29
+ # then
30
+ obj.should be_kind_of(String)
31
+ obj.should be_kind_of(World)
32
+ end
33
+
34
+ it 'should pass arguments to #new when creating an object of a specified type that mixes in a world' do
35
+ # given
36
+ Thing = Struct.new(:name, :age)
37
+
38
+ # when
39
+ obj = World::create Thing, "David", "I'm not telling"
40
+
41
+ # then
42
+ obj.should be_an_instance_of(Thing)
43
+ obj.name.should == "David"
44
+ obj.age.should == "I'm not telling"
45
+ obj.should be_kind_of(World)
46
+ end
47
+
48
+ def ensure_world_executes_step(&block)
49
+ # given
50
+ obj = World::create
51
+ $step_ran = false
52
+
53
+ # when
54
+ obj.instance_eval(&block)
55
+
56
+ # then
57
+ $step_ran.should be_true
58
+ end
59
+
60
+ it 'should execute a Given, When or Then step' do
61
+ ensure_world_executes_step do
62
+ Given 'a given' do
63
+ $step_ran = true
64
+ end
65
+ end
66
+
67
+ ensure_world_executes_step do
68
+ When 'an event' do
69
+ $step_ran = true
70
+ end
71
+ end
72
+
73
+ ensure_world_executes_step do
74
+ Then 'an outcome' do
75
+ $step_ran = true
76
+ end
77
+ end
78
+ end
79
+
80
+ it 'should interpret Given... And... as multiple givens' do
81
+ # given
82
+ world = World.create
83
+ $steps = []
84
+
85
+ # when
86
+ world.instance_eval do
87
+ Given 'step 1' do
88
+ $steps << 1
89
+ end
90
+ And 'step 2' do
91
+ $steps << 2
92
+ end
93
+ end
94
+
95
+ # then
96
+ $steps.should == [1,2]
97
+ World.step_mother.find(:given, 'step 1').should_not be_nil
98
+ World.step_mother.find(:given, 'step 2').should_not be_nil
99
+ end
100
+
101
+ it 'should interpret When... And... as multiple events' do
102
+ # given
103
+ world = World.create
104
+ $steps = []
105
+
106
+ # when
107
+ world.instance_eval do
108
+ When 'step 1' do
109
+ $steps << 1
110
+ end
111
+ And 'step 2' do
112
+ $steps << 2
113
+ end
114
+ end
115
+
116
+ # then
117
+ $steps.should == [1,2]
118
+ World.step_mother.find(:when, 'step 1').should_not be_nil
119
+ World.step_mother.find(:when, 'step 2').should_not be_nil
120
+ end
121
+
122
+ it 'should interpret Then... And... as multiple outcomes' do
123
+ # given
124
+ world = World.create
125
+ $steps = []
126
+
127
+ # when
128
+ world.instance_eval do
129
+ Then 'step 1' do
130
+ $steps << 1
131
+ end
132
+ And 'step 2' do
133
+ $steps << 2
134
+ end
135
+ end
136
+
137
+ # then
138
+ $steps.should == [1,2]
139
+ World.step_mother.find(:then, 'step 1').should_not be_nil
140
+ World.step_mother.find(:then, 'step 2').should_not be_nil
141
+ end
142
+
143
+ it 'should reuse a given across scenarios' do
144
+ # given
145
+ $num_invoked = 0
146
+ a_world = World::create
147
+ a_world.instance_eval do
148
+ Given 'a given' do
149
+ $num_invoked += 1
150
+ end
151
+ end
152
+ another_world = World::create
153
+
154
+ # when
155
+ another_world.instance_eval do
156
+ Given 'a given' # without a body
157
+ end
158
+
159
+ # then
160
+ $num_invoked.should == 2
161
+ end
162
+
163
+ it 'should reuse an event across scenarios' do
164
+ # given
165
+ $num_invoked = 0
166
+ a_world = World::create
167
+ a_world.instance_eval do
168
+ When 'an event' do
169
+ $num_invoked += 1
170
+ end
171
+ end
172
+
173
+ another_world = World::create
174
+
175
+ # when
176
+ another_world.instance_eval do
177
+ When 'an event' # without a body
178
+ end
179
+
180
+ # then
181
+ $num_invoked.should == 2
182
+ end
183
+
184
+ it 'should reuse an outcome across scenarios' do
185
+ # given
186
+ $num_invoked = 0
187
+ a_world = World::create
188
+ a_world.instance_eval do
189
+ Then 'an outcome' do
190
+ $num_invoked += 1
191
+ end
192
+ end
193
+
194
+ another_world = World::create
195
+
196
+ # when
197
+ another_world.instance_eval do
198
+ Then 'an outcome' # without a body
199
+ end
200
+
201
+ # then
202
+ $num_invoked.should == 2
203
+ end
204
+
205
+ it 'should preserve instance variables between steps within a scenario' do
206
+ # given
207
+ world = World::create
208
+ $first = nil
209
+ $second = nil
210
+
211
+ # when
212
+ world.instance_eval do
213
+ Given 'given' do
214
+ @first = 'first'
215
+ end
216
+ When 'event' do
217
+ @second = @first # from given
218
+ end
219
+ Then 'outcome' do
220
+ $first = @first # from given
221
+ $second = @second # from event
222
+ end
223
+ end
224
+
225
+ # then
226
+ $first.should == 'first'
227
+ $second.should == 'first'
228
+ end
229
+
230
+ it 'should invoke a reused step in the new object instance' do
231
+ # given
232
+ $instances = []
233
+ $debug = true
234
+ world1 = World.create
235
+ world1.instance_eval do
236
+ Given 'a given' do
237
+ $instances << self.__id__
238
+ end
239
+ end
240
+ world2 = World.create
241
+
242
+ # when
243
+ world2.instance_eval do
244
+ Given 'a given' # reused
245
+ Then 'an outcome' do
246
+ $instances << __id__
247
+ end
248
+ end
249
+ $debug = false
250
+ # then
251
+ $instances.should == [ world1.__id__, world2.__id__, world2.__id__ ]
252
+ end
253
+
254
+ def ensure_world_collects_error(expected_error, &block)
255
+ # given
256
+ world = World.create
257
+ # $error = nil
258
+
259
+ # when
260
+ world.start_collecting_errors
261
+ world.instance_eval(&block)
262
+
263
+ # then
264
+ world.should have(1).errors
265
+ world.errors[0].should be_kind_of(expected_error)
266
+ end
267
+
268
+ it 'should collect a failure from a Given step' do
269
+ ensure_world_collects_error RuntimeError do
270
+ Given 'a given' do
271
+ raise RuntimeError, "oops"
272
+ end
273
+ end
274
+ end
275
+
276
+ it 'should collect a failure from a When step' do
277
+ ensure_world_collects_error RuntimeError do
278
+ When 'an event' do
279
+ raise RuntimeError, "oops"
280
+ end
281
+ end
282
+ end
283
+
284
+ it 'should collect a failure from a Then step' do
285
+ ensure_world_collects_error RuntimeError do
286
+ Then 'an outcome' do
287
+ raise RuntimeError, "oops"
288
+ end
289
+ end
290
+ end
291
+
292
+ it 'should inform listeners when it runs a Given, When or Then step' do
293
+ # given
294
+ world = World.create
295
+ mock_listener1 = mock('listener1')
296
+ mock_listener2 = mock('listener2')
297
+ World.add_listener(mock_listener1)
298
+ World.add_listener(mock_listener2)
299
+
300
+ # expect
301
+ mock_listener1.should_receive(:step_upcoming).with(:given, 'a context')
302
+ mock_listener1.should_receive(:step_succeeded).with(:given, 'a context')
303
+ mock_listener1.should_receive(:step_upcoming).with(:when, 'an event')
304
+ mock_listener1.should_receive(:step_succeeded).with(:when, 'an event')
305
+ mock_listener1.should_receive(:step_upcoming).with(:then, 'an outcome')
306
+ mock_listener1.should_receive(:step_succeeded).with(:then, 'an outcome')
307
+
308
+ mock_listener2.should_receive(:step_upcoming).with(:given, 'a context')
309
+ mock_listener2.should_receive(:step_succeeded).with(:given, 'a context')
310
+ mock_listener2.should_receive(:step_upcoming).with(:when, 'an event')
311
+ mock_listener2.should_receive(:step_succeeded).with(:when, 'an event')
312
+ mock_listener2.should_receive(:step_upcoming).with(:then, 'an outcome')
313
+ mock_listener2.should_receive(:step_succeeded).with(:then, 'an outcome')
314
+
315
+ # when
316
+ world.instance_eval do
317
+ Given 'a context' do end
318
+ When 'an event' do end
319
+ Then 'an outcome' do end
320
+ end
321
+
322
+ # then
323
+ end
324
+
325
+ it 'should tell listeners but not execute the step in dry-run mode' do
326
+ # given
327
+ World.stub!(:dry_run).and_return(true)
328
+ mock_listener = mock('listener')
329
+ World.add_listener(mock_listener)
330
+ $step_invoked = false
331
+ world = World.create
332
+
333
+ # expect
334
+ mock_listener.should_receive(:step_upcoming).with(:given, 'a context')
335
+ mock_listener.should_receive(:step_succeeded).with(:given, 'a context')
336
+
337
+ # when
338
+ world.instance_eval do
339
+ Given 'a context' do
340
+ $step_invoked = true
341
+ end
342
+ end
343
+
344
+ # then
345
+ $step_invoked.should be(false)
346
+ end
347
+
348
+ it 'should suppress listeners while it runs a GivenScenario' do
349
+ # given
350
+ scenario_ran = false
351
+
352
+ scenario = ScenarioBuilder.new.name('a scenario').to_scenario do
353
+ scenario_ran = true
354
+ Given 'given' do end
355
+ When 'event' do end
356
+ Then 'outcome' do end
357
+ end
358
+
359
+ given_scenario = GivenScenario.new('a scenario')
360
+ Runner::StoryRunner.should_receive(:scenario_from_current_story).
361
+ with('a scenario').and_return(scenario)
362
+
363
+ world = World.create
364
+ listener = mock('listener')
365
+ World.add_listener(listener)
366
+
367
+ # expect
368
+ listener.should_receive(:found_scenario).with(:'given scenario', 'a scenario')
369
+ listener.should_receive(:step_succeeded).never.with(:given, 'given')
370
+ listener.should_receive(:step_succeeded).never.with(:when, 'event')
371
+ listener.should_receive(:step_succeeded).never.with(:then, 'outcome')
372
+
373
+ # when
374
+ world.GivenScenario 'a scenario'
375
+
376
+ # then
377
+ scenario_ran.should be_true
378
+ end
379
+
380
+ it 'should interpret GivenScenario... And... as multiple givens' do
381
+ # given
382
+ world = World.create
383
+ steps = []
384
+
385
+ scenario = ScenarioBuilder.new.name('a scenario').to_scenario do
386
+ steps << 1
387
+ end
388
+ Runner::StoryRunner.should_receive(:scenario_from_current_story).
389
+ with('a scenario').and_return(scenario)
390
+
391
+ # when
392
+ world.instance_eval do
393
+ GivenScenario 'a scenario'
394
+ And 'step 2' do
395
+ steps << 2
396
+ end
397
+ end
398
+
399
+ # then
400
+ steps.should == [1,2]
401
+ World.step_mother.find(:given, 'step 2').should_not be_nil
402
+ end
403
+
404
+ it 'should provide rspec matchers' do
405
+ # given
406
+ world = World.create
407
+
408
+ # then
409
+ world.instance_eval do
410
+ 'hello'.should match(/^hello$/)
411
+ end
412
+ end
413
+
414
+ it "should use assigned matchers" do
415
+ world = World.create
416
+
417
+ World.should_receive(:use).with(steps = Object.new)
418
+
419
+ World.use(steps)
420
+ end
421
+ end
422
+ end
423
+ end