]> git.openstreetmap.org Git - rails.git/blob - vendor/gems/rspec-1.1.2/lib/spec/story/world.rb
added RSpec and RSpec on Rails
[rails.git] / vendor / gems / rspec-1.1.2 / lib / spec / story / world.rb
1 require 'rubygems'
2 require 'spec/expectations'
3 require 'spec/matchers'
4 require 'spec/example/pending'
5
6 module Spec
7   module Story
8 =begin
9   A World represents the actual instance a scenario will run in.
10   
11   The runner ensures any instance variables and methods defined anywhere
12   in a story block are available to all the scenarios. This includes
13   variables that are created or referenced inside Given, When and Then
14   blocks.
15 =end
16     module World
17       include ::Spec::Example::Pending
18       include ::Spec::Matchers
19       # store steps and listeners in the singleton metaclass.
20       # This serves both to keep them out of the way of runtime Worlds
21       # and to make them available to all instances.
22       class << self
23         def create(cls = Object, *args)
24           cls.new(*args).extend(World)
25         end
26         
27         def listeners
28           @listeners ||= []
29         end
30         
31         def add_listener(listener)
32           listeners() << listener
33         end
34         
35         def step_mother
36           @step_mother ||= StepMother.new
37         end
38                 
39         def use(steps)
40           step_mother.use(steps)
41         end
42         
43         def step_names
44           @step_names ||= []
45         end
46
47         def run_given_scenario_with_suspended_listeners(world, type, name, scenario)
48           current_listeners = Array.new(listeners)
49           begin
50             listeners.each { |l| l.found_scenario(type, name) }
51             @listeners.clear
52             scenario.perform(world, name) unless ::Spec::Story::Runner.dry_run
53           ensure
54             @listeners.replace(current_listeners)
55           end
56         end
57         
58         def store_and_call(world, type, name, *args, &block)
59           if block_given?
60             step_mother.store(type, Step.new(name, &block))
61           end
62           step = step_mother.find(type, name)
63
64           step_name = step.name
65           step_names << step_name
66           
67           # It's important to have access to the parsed args here, so
68           # we can give them to the listeners. The HTML reporter needs
69           # the args so it can style them. See the generated output in
70           # story_server/prototype/rspec_stories.html (generated by rake stories)
71           args = step.parse_args(name) if args.empty?
72           begin
73             step.perform(world, *args) unless ::Spec::Story::Runner.dry_run
74             listeners.each { |l| l.step_succeeded(type, step_name, *args) }
75           rescue Exception => e
76             case e
77             when Spec::Example::ExamplePendingError
78               @listeners.each { |l| l.step_pending(type, step_name, *args) }
79             else
80               @listeners.each { |l| l.step_failed(type, step_name, *args) }
81             end
82             errors << e
83           end
84         end
85         
86         def errors
87           @errors ||= []
88         end
89       end # end of class << self
90       
91       def start_collecting_errors
92         errors.clear
93       end
94       
95       def errors
96         World.errors
97       end
98       
99       def GivenScenario(name)
100         World.run_given_scenario_with_suspended_listeners(self, :'given scenario', name, GivenScenario.new(name))
101         @__previous_step = :given
102       end
103       
104       def Given(name, *args, &block)
105         World.store_and_call self, :given, name, *args, &block
106         @__previous_step = :given
107       end
108       
109       def When(name, *args, &block)
110         World.store_and_call self, :when, name, *args, &block
111         @__previous_step = :when
112       end
113       
114       def Then(name, *args, &block)
115         World.store_and_call self, :then, name, *args, &block
116         @__previous_step = :then
117       end
118       
119       def And(name, *args, &block)
120         World.store_and_call self, @__previous_step, name, *args, &block
121       end
122     end
123   end
124 end