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