]> git.openstreetmap.org Git - rails.git/blob - vendor/gems/rspec-1.1.2/lib/spec/story/runner/story_parser.rb
d454df8cb78bdd61314493e10162c76e0ba17231
[rails.git] / vendor / gems / rspec-1.1.2 / lib / spec / story / runner / story_parser.rb
1 module Spec
2   module Story
3     module Runner
4       
5       class IllegalStepError < StandardError
6         def initialize(state, event)
7           super("Illegal attempt to create a #{event} after a #{state}")
8         end
9       end
10
11       class StoryParser
12         def initialize(story_mediator)
13           @story_mediator = story_mediator
14           @current_story_lines = []
15           transition_to(:starting_state)
16         end
17         
18         def parse(lines)
19           lines.reject! {|line| line == ""}
20           until lines.empty?
21             process_line(lines.shift)
22           end
23           @state.eof
24         end
25         
26         def process_line(line)
27           line.strip!
28           case line
29           when /^Story: /           then @state.story(line)
30           when /^Scenario: /        then @state.scenario(line)
31           when /^Given:? /          then @state.given(line)
32           when /^GivenScenario:? /  then @state.given_scenario(line)
33           when /^When:? /           then @state.event(line)
34           when /^Then:? /           then @state.outcome(line)
35           when /^And:? /            then @state.one_more_of_the_same(line)
36           else                           @state.other(line)
37           end
38         end
39
40         def init_story(title)
41           @current_story_lines.clear
42           add_story_line(title)
43         end
44         
45         def add_story_line(line)
46           @current_story_lines << line
47         end
48         
49         def create_story()
50           unless @current_story_lines.empty?
51             @story_mediator.create_story(@current_story_lines[0].gsub("Story: ",""), @current_story_lines[1..-1].join("\n"))
52             @current_story_lines.clear
53           end
54         end
55         
56         def create_scenario(title)
57           @story_mediator.create_scenario(title.gsub("Scenario: ",""))
58         end
59         
60         def create_given(name)
61           @story_mediator.create_given(name)
62         end
63         
64         def create_given_scenario(name)
65           @story_mediator.create_given_scenario(name)
66         end
67         
68         def create_when(name)
69           @story_mediator.create_when(name)
70         end
71         
72         def create_then(name)
73           @story_mediator.create_then(name)
74         end
75
76         def transition_to(key)
77           @state = states[key]
78         end
79         
80         def states
81           @states ||= {
82             :starting_state => StartingState.new(self),
83             :story_state => StoryState.new(self),
84             :scenario_state => ScenarioState.new(self),
85             :given_state => GivenState.new(self),
86             :when_state => WhenState.new(self),
87             :then_state => ThenState.new(self)
88           }
89         end
90         
91         class State
92           def initialize(parser)
93             @parser = parser
94           end
95           
96           def story(line)
97             @parser.init_story(line)
98             @parser.transition_to(:story_state)
99           end
100
101           def scenario(line)
102             @parser.create_scenario(line)
103             @parser.transition_to(:scenario_state)
104           end
105
106           def given(line)
107             @parser.create_given(remove_tag_from(:given, line))
108             @parser.transition_to(:given_state)
109           end
110           
111           def given_scenario(line)
112             @parser.create_given_scenario(remove_tag_from(:givenscenario, line))
113             @parser.transition_to(:given_state)
114           end
115           
116           def event(line)
117             @parser.create_when(remove_tag_from(:when, line))
118             @parser.transition_to(:when_state)
119           end
120           
121           def outcome(line)
122             @parser.create_then(remove_tag_from(:then, line))
123             @parser.transition_to(:then_state)
124           end
125
126           def remove_tag_from(tag, line)
127             tokens = line.split
128             # validation of tag can go here
129             tokens[0].downcase.match(/#{tag.to_s}:?/) ? 
130                                 (tokens[1..-1].join(' ')) : line
131           end
132
133           def eof
134           end
135           
136           def other(line)
137             # no-op - supports header text before the first story in a file
138           end
139         end
140         
141         class StartingState < State
142           def initialize(parser)
143             @parser = parser
144           end
145         end
146         
147         class StoryState < State
148           def one_more_of_the_same(line)
149             other(line)
150           end
151
152           def story(line)
153             @parser.create_story
154             @parser.add_story_line(line)
155           end
156           
157           def scenario(line)
158             @parser.create_story
159             @parser.create_scenario(line)
160             @parser.transition_to(:scenario_state)
161           end
162           
163           def given(line)
164             other(line)
165           end
166           
167           def event(line)
168             other(line)
169           end
170           
171           def outcome(line)
172             other(line)
173           end
174           
175           def other(line)
176             @parser.add_story_line(line)
177           end
178           
179           def eof
180             @parser.create_story
181           end
182         end
183
184         class ScenarioState < State
185           def one_more_of_the_same(line)
186             raise IllegalStepError.new("Scenario", "And")
187           end
188
189           def scenario(line)
190             @parser.create_scenario(line)
191           end
192         end
193         
194         class GivenState < State
195           def one_more_of_the_same(line)
196             @parser.create_given(remove_tag_from(:and, line))
197           end
198           
199           def given(line)
200             @parser.create_given(remove_tag_from(:given, line))
201           end
202         end
203         
204         class WhenState < State
205           def one_more_of_the_same(line)
206             @parser.create_when(remove_tag_from(:and ,line))
207           end
208
209           def event(line)
210             @parser.create_when(remove_tag_from(:when ,line))
211           end
212         end
213
214         class ThenState < State
215           def one_more_of_the_same(line)
216             @parser.create_then(remove_tag_from(:and ,line))
217           end
218
219           def outcome(line)
220             @parser.create_then(remove_tag_from(:then ,line))
221           end
222         end
223
224       end
225     end
226   end
227 end