marso 0.1.29059 → 0.1.47959

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a08f2eab4f5f38a5535d05665390b8347c14e6a
4
- data.tar.gz: 4e149e94f8d799fba81e2110dd3e9a789f7cc8b4
3
+ metadata.gz: 5b15c69b1ea0796955f65f15d9d09947265e98eb
4
+ data.tar.gz: a0df6d7123bf9c574eddf135376c764527b5e6b5
5
5
  SHA512:
6
- metadata.gz: 280f7dd08d67f994ec84f8cd3c5a158acd15e76bc1823e4f5d212fabf67a9ec213c132bc17ab7d43a4a7c77b2bbbb4bc76f18b7c2112f1d5fd8101b09fe0f569
7
- data.tar.gz: f3119c5e80021f7e4a3d189879bb4e7ce8dae2088eb239544c2162eab0148fd6492bfbb3c419facfaa905964f6766ea01e95f44f03db370bf6e64cc832d034c7
6
+ metadata.gz: a43a302bfcd8b22af168d865d9c882979fdb5d92b1fe65769181ee6a73ed355e89eba35e543bc1ef6173016f075b66265927894d9a29c49d11aed68328c8e725
7
+ data.tar.gz: edae46912cfc7fd0b33452dd7f8f6e89361b05ba83b700dad47aad2d83caf79894e3539e5d011aeddd6f5ac3b704485f0d75c960e2fd8037ecb505e491c4321b
data/Rakefile CHANGED
@@ -1,2 +1,9 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rake/testtask'
2
3
 
4
+ Rake::TestTask.new do |t|
5
+ t.libs << "lib"
6
+ t.libs << "test"
7
+ t.test_files = FileList['test/**/*test.rb']
8
+ t.verbose = true
9
+ end
@@ -0,0 +1,342 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'marso'
4
+ require 'colorize'
5
+ require 'pathname'
6
+ require 'fileutils'
7
+
8
+ LAUNCHER_OPTIONS_KEYS_MAP = {
9
+ "-p" => :rootpath,
10
+ "-f" => :select,
11
+ "-m" => :include_mode
12
+ }
13
+
14
+ def help
15
+ puts "Usage: No documentation yet"
16
+ end
17
+
18
+ def location_is_stories?(path=nil)
19
+ path = path || Dir.pwd
20
+ File.basename(path).casecmp("stories") == 0
21
+ end
22
+
23
+ def location_is_features?(path=nil)
24
+ path = path || Dir.pwd
25
+ File.basename(path).casecmp("features") == 0
26
+ end
27
+
28
+ def location_is_scenarios?(path=nil)
29
+ path = path || Dir.pwd
30
+ File.basename(path).casecmp("scenarios") == 0
31
+ end
32
+
33
+ def location_is_story?(path=nil)
34
+ path = path || Dir.pwd
35
+ parent_path = File.expand_path("../", path)
36
+ location_is_stories? parent_path
37
+ end
38
+
39
+ def location_is_feature?(path=nil)
40
+ path = path || Dir.pwd
41
+ parent_path = File.expand_path("../", path)
42
+ location_is_features? parent_path
43
+ end
44
+
45
+ def location_is_scenario?(path=nil)
46
+ path = path || Dir.pwd
47
+ parent_path = File.expand_path("../", path)
48
+ location_is_scenarios? parent_path
49
+ end
50
+
51
+ def location_is_stories_realm?(path=nil)
52
+ path = path || Dir.pwd
53
+ location_is_stories?(path) || location_is_story?(path)
54
+ end
55
+
56
+ def location_is_features_realm?(path=nil)
57
+ path = path || Dir.pwd
58
+ location_is_features?(path) || location_is_feature?(path)
59
+ end
60
+
61
+ def location_is_scenarios_realm?(path=nil)
62
+ path = path || Dir.pwd
63
+ location_is_scenarios?(path) || location_is_scenario?(path)
64
+ end
65
+
66
+ def create_feature(name)
67
+ if location_is_scenarios_realm?
68
+ puts "Impossible to create a feature under scenarios. Please browse to another location".colorize(:red)
69
+ elsif location_is_stories_realm?
70
+ puts "Impossible to create a feature under stories. Please browse to another location".colorize(:red)
71
+ else
72
+ feature_factory = Marso::FeatureFactory.new
73
+ unless name
74
+ print "Enter feature's name: ".colorize(:cyan)
75
+ name = $stdin.gets.chomp
76
+ end
77
+ print "Do you want to describe your feature now(y/n)? ".colorize(:cyan)
78
+ answer = $stdin.gets.chomp
79
+ feat_description = nil
80
+ if answer.casecmp("y") == 0
81
+ print "In order to: ".colorize(:cyan)
82
+ in_order_to = $stdin.gets.chomp
83
+ print "As a: ".colorize(:cyan)
84
+ as_a = $stdin.gets.chomp
85
+ print "I: ".colorize(:cyan)
86
+ i = $stdin.gets.chomp
87
+ feat_description = {
88
+ :name => name,
89
+ :in_order_to => in_order_to,
90
+ :as_a => as_a,
91
+ :i => i
92
+ }
93
+ else
94
+ feat_description = { :name => name }
95
+ end
96
+
97
+ fname = nil
98
+ feat_folder = name.downcase.gsub(' ','_')
99
+ cancel_operation = false
100
+ current_folder_is_features = File.basename(Dir.pwd).casecmp("features") == 0
101
+ if current_folder_is_features
102
+ fname = feature_factory.create_feature_file(feat_description)
103
+ else # the question now is whether or not we want to create the Features folder
104
+ features_folder_is_a_subfolder = Dir.entries(Dir.pwd)
105
+ .select{ |f| File.directory? File.join(Dir.pwd,f ) }
106
+ .any?{ |f| f == "Features" }
107
+
108
+ unless features_folder_is_a_subfolder
109
+ print "The current folder is not the 'Features' folder and it doesn't contain it either. Do you want to create[y] it, or cancel[n] the operation(y/n)? ".colorize(:cyan)
110
+ create_answer = $stdin.gets.chomp
111
+ if create_answer.casecmp("y") == 0
112
+ FileUtils.mkdir "Features"
113
+ else
114
+ cancel_operation = true
115
+ end
116
+ end
117
+ feat_root = File.join(Dir.pwd, "Features", feat_folder)
118
+ fname = feature_factory.create_feature_file(feat_description, feat_root)
119
+ end
120
+
121
+ if cancel_operation
122
+ puts "Operation cancelled".colorize(:pink)
123
+ else
124
+ puts "Feature file #{feat_folder}/#{fname} successfully created".colorize(:green)
125
+ end
126
+ end
127
+ end
128
+
129
+ def create_story(name)
130
+ if location_is_scenarios_realm?
131
+ puts "Impossible to create a story under scenarios. Please browse to another location".colorize(:red)
132
+ elsif location_is_features?
133
+ puts "Impossible to create a story straight under the Features folder. Please browse to a specific feature or story".colorize(:red)
134
+ elsif !location_is_feature? && !location_is_stories?
135
+ puts "Impossible to create a story here. Please browse to specific a feature or story".colorize(:red)
136
+ else
137
+ story_factory = Marso::StoryFactory.new
138
+ unless name
139
+ print "Enter story's name: ".colorize(:cyan)
140
+ name = $stdin.gets.chomp
141
+ end
142
+ print "Do you want to describe your story now(y/n)? ".colorize(:cyan)
143
+ answer = $stdin.gets.chomp
144
+ story_description = nil
145
+ if answer.casecmp("y") == 0
146
+ print "In order to: ".colorize(:cyan)
147
+ in_order_to = $stdin.gets.chomp
148
+ print "As a: ".colorize(:cyan)
149
+ as_a = $stdin.gets.chomp
150
+ print "I: ".colorize(:cyan)
151
+ i = $stdin.gets.chomp
152
+ story_description = {
153
+ :name => name,
154
+ :in_order_to => in_order_to,
155
+ :as_a => as_a,
156
+ :i => i
157
+ }
158
+ else
159
+ story_description = { :name => name }
160
+ end
161
+
162
+ fname = nil
163
+ story_folder = name.downcase.gsub(' ','_')
164
+ cancel_operation = false
165
+ current_folder_is_stories = File.basename(Dir.pwd).casecmp("stories") == 0
166
+ if current_folder_is_stories
167
+ fname = story_factory.create_story_file(story_description)
168
+ else # the question now is whether or not we want to create the Stories folder
169
+ stories_folder_is_a_subfolder = Dir.entries(Dir.pwd)
170
+ .select{ |f| File.directory? File.join(Dir.pwd,f ) }
171
+ .any?{ |f| f == "Stories" }
172
+
173
+ unless stories_folder_is_a_subfolder
174
+ print "The current folder is not the 'Stories' folder and it doesn't contain it either. Do you want to create[y] it, or cancel[n] the operation(y/n)? ".colorize(:cyan)
175
+ create_answer = $stdin.gets.chomp
176
+ if create_answer.casecmp("y") == 0
177
+ FileUtils.mkdir "Stories"
178
+ else
179
+ cancel_operation = true
180
+ end
181
+ end
182
+ feat_root = File.join(Dir.pwd, "Stories", story_folder)
183
+ fname = story_factory.create_story_file(story_description, feat_root)
184
+ end
185
+
186
+ if cancel_operation
187
+ puts "Operation cancelled".colorize(:pink)
188
+ else
189
+ puts "Story file #{story_folder}/#{fname} successfully created".colorize(:green)
190
+ end
191
+ end
192
+ end
193
+
194
+ def create_scenario(name)
195
+ if location_is_features?
196
+ puts "Impossible to create a scenario straight under the Features folder. Please browse to a specific feature or story".colorize(:red)
197
+ elsif location_is_stories?
198
+ puts "Impossible to create a scenario straight under the Stories folder. Please browse to a specific feature or story".colorize(:red)
199
+ elsif !location_is_feature? && !location_is_story?
200
+ puts "Impossible to create a scenario here. Please browse to specific a feature or story".colorize(:red)
201
+ else
202
+ scenario_factory = Marso::ScenarioFactory.new
203
+ unless name
204
+ print "Enter scenario's name: ".colorize(:cyan)
205
+ name = $stdin.gets.chomp
206
+ end
207
+ print "Do you want to describe your scenario now(y/n)? ".colorize(:cyan)
208
+ answer = $stdin.gets.chomp
209
+ scenario_description = nil
210
+ if answer.casecmp("y") == 0
211
+ print "Given: ".colorize(:cyan)
212
+ _given = $stdin.gets.chomp
213
+ print "When: ".colorize(:cyan)
214
+ _when = $stdin.gets.chomp
215
+ print "Then: ".colorize(:cyan)
216
+ _then = $stdin.gets.chomp
217
+ scenario_description = {
218
+ :name => name,
219
+ :given => _given,
220
+ :when => _when,
221
+ :then => _then
222
+ }
223
+ else
224
+ scenario_description = { :name => name }
225
+ end
226
+
227
+ fname = nil
228
+ cancel_operation = false
229
+ current_folder_is_scenarios = File.basename(Dir.pwd).casecmp("stories") == 0
230
+ if current_folder_is_scenarios
231
+ fname = scenario_factory.create_scenario_file(scenario_description)
232
+ else # the question now is whether or not we want to create the Scenarios folder
233
+ scenarios_folder_is_a_subfolder = Dir.entries(Dir.pwd)
234
+ .select{ |f| File.directory? File.join(Dir.pwd,f ) }
235
+ .any?{ |f| f == "Scenarios" }
236
+
237
+ unless scenarios_folder_is_a_subfolder
238
+ print "The current folder is not the 'Scenarios' folder and it doesn't contain it either. Do you want to create[y] it, or cancel[n] the operation(y/n)? ".colorize(:cyan)
239
+ create_answer = $stdin.gets.chomp
240
+ if create_answer.casecmp("y") == 0
241
+ FileUtils.mkdir "Scenarios"
242
+ else
243
+ cancel_operation = true
244
+ end
245
+ end
246
+ feat_root = File.join(Dir.pwd, "Scenarios")
247
+ fname = scenario_factory.create_scenario_file(scenario_description, feat_root)
248
+ end
249
+
250
+ if cancel_operation
251
+ puts "Operation cancelled".colorize(:pink)
252
+ else
253
+ puts "Scenario file #{fname} successfully created".colorize(:green)
254
+ end
255
+ end
256
+ end
257
+
258
+ def get_options
259
+ options = {}
260
+ if ARGV.size > 1
261
+ args = ARGV.clone
262
+ args.shift(2)
263
+ args.each do |arg|
264
+ puts arg
265
+ kv = arg.split('=')
266
+ key = LAUNCHER_OPTIONS_KEYS_MAP[kv[0]]
267
+ puts key
268
+ case key
269
+ when :rootpath
270
+ options[:rootpath] = kv[1]
271
+ when :select
272
+ options[:select] = kv[1].split(',')
273
+ when :include_mode
274
+ modes = kv[1].split(',')
275
+ if modes.any? { |m| m == "all"}
276
+ options[:include_mode] = :with_all
277
+ elsif modes.any? { |m| m == "scenarios"} && modes.any? { |m| m == "stories"}
278
+ options[:include_mode] = :with_stories_scenarios
279
+ elsif modes.any? { |m| m == "scenarios"}
280
+ options[:include_mode] = :with_scenarios
281
+ elsif modes.any? { |m| m == "stories"}
282
+ options[:include_mode] = :with_stories
283
+ end
284
+ end
285
+ end
286
+ end
287
+ return options
288
+ end
289
+
290
+ def show_features
291
+ options = get_options
292
+ puts options
293
+ Marso.show_features_text options
294
+ end
295
+
296
+ if ARGV.size > 0
297
+ main_command = ARGV[0].downcase
298
+ case main_command
299
+ when "add"
300
+ if ARGV.size == 1
301
+ puts "Missing argument(0 for 1). Use 'marso help' to find out about the usage".colorize(:red)
302
+ else
303
+ gherkin_type = ARGV[1].downcase
304
+ case gherkin_type
305
+ when "feature"
306
+ create_feature ARGV[2]
307
+ when "f"
308
+ create_feature ARGV[2]
309
+ when "story"
310
+ create_story ARGV[2]
311
+ when "s"
312
+ create_story ARGV[2]
313
+ when "scenario"
314
+ create_scenario ARGV[2]
315
+ when "scn"
316
+ create_scenario ARGV[2]
317
+ else
318
+ puts "#{gherkin_type} is not a Gherkin type. Use 'marso help' to find out about the usage".colorize(:red)
319
+ end
320
+ end
321
+ when "show"
322
+ if ARGV.size == 1
323
+ puts "Missing argument(0 for 1). Use 'marso help' to find out about the usage".colorize(:red)
324
+ else
325
+ gherkin_type = ARGV[1].downcase
326
+ case gherkin_type
327
+ when "feature"
328
+ show_features
329
+ when "f"
330
+ show_features
331
+ else
332
+ puts "#{gherkin_type} is not a Gherkin type. Use 'marso help' to find out about the usage".colorize(:red)
333
+ end
334
+ end
335
+ when "help"
336
+ help
337
+ when "h"
338
+ help
339
+ else
340
+ puts "#{main_command} is an invalid command. Use 'marso help' to find out about the usage".colorize(:red)
341
+ end
342
+ end
@@ -6,12 +6,15 @@ require "marso/domain/step/step"
6
6
  require "marso/domain/step/step_publish"
7
7
  require "marso/domain/scenario/scenario"
8
8
  require "marso/domain/scenario/scenario_publish"
9
+ require "marso/domain/scenario/scenario_factory"
9
10
  require "marso/domain/story/story"
10
11
  require "marso/domain/story/story_load"
11
12
  require "marso/domain/story/story_publish"
13
+ require "marso/domain/story/story_factory"
12
14
  require "marso/domain/feature/feature"
13
15
  require "marso/domain/feature/feature_load"
14
16
  require "marso/domain/feature/feature_publish"
17
+ require "marso/domain/feature/feature_factory"
15
18
  require "marso/helpers/texthelper"
16
19
  require "marso/helpers/statushelper"
17
20
  require "marso/helpers/componenthelper"
@@ -0,0 +1,13 @@
1
+
2
+ module Marso
3
+ module BaseFactory
4
+ private
5
+ def get_template(path)
6
+ template = nil
7
+ File.open(path, "rb") do |f|
8
+ template = f.read
9
+ end
10
+ return template
11
+ end
12
+ end
13
+ end
@@ -10,12 +10,12 @@ module Marso
10
10
  include FeaturePublish
11
11
 
12
12
  attr_reader :id, :description, :status, :ctx, :stories, :scenario_contexts,
13
- :rootpath, :header, :text, :tree_position, :color_theme
13
+ :rootpath, :header, :text, :tree_position, :color_theme, :name, :fname
14
14
 
15
15
  # description (optional): Hash defined as follow
16
16
  # :id => Arbitrary number or string. Default is randomly generated
17
- # (hex string (length 8))
18
- # :name => Story's name
17
+ # (hex string (length 6))
18
+ # :name => Feature's name
19
19
  # :in_order_to => String that describes the fundamental story's business
20
20
  # value
21
21
  # :as_a => String that describes the user(s)
@@ -37,9 +37,11 @@ module Marso
37
37
 
38
38
  @description[:scenario_contexts] = [] if description[:scenario_contexts].nil?
39
39
  @description[:stories] = [] if description[:stories].nil?
40
- @description[:id] = SecureRandom.hex(4) if description[:id].nil?
40
+ @description[:id] = SecureRandom.hex(3) if description[:id].nil?
41
41
  @description[:rootpath] = File.dirname(caller[0]) if description[:rootpath].nil?
42
42
 
43
+ @name = @description[:name]
44
+ @fname = @description[:name].downcase.gsub(' ', '_')
43
45
  @rootpath = @description[:rootpath]
44
46
  @id = @description[:id]
45
47
  @scenario_contexts = @description[:scenario_contexts]
@@ -73,6 +75,7 @@ module Marso
73
75
  def validate_arguments(description, ctx)
74
76
  raise ArgumentError, "Argument 'description' cannot be nil" if description.nil?
75
77
  raise ArgumentError, "Argument 'description' must be a Hash" unless description.is_a?(Hash)
78
+ raise ArgumentError, "Argument 'description[:name]' is required" if description[:name].nil?
76
79
  raise ArgumentError, "Argument 'ctx' must be a Hash" unless ctx.is_a?(Hash)
77
80
  unless description[:scenario_contexts].nil?
78
81
  unless description[:scenario_contexts].empty?
@@ -0,0 +1,43 @@
1
+ require 'pathname'
2
+ require 'securerandom'
3
+ require 'fileutils'
4
+ require_relative 'feature'
5
+ require_relative '../base_factory'
6
+
7
+ module Marso
8
+
9
+ class FeatureFactory
10
+ include Marso::BaseFactory
11
+
12
+ def create_feature_file(description={}, root=nil)
13
+ raise ArgumentError, "Feature's name is required" unless description[:name]
14
+ id = description[:id] || SecureRandom.hex(3)
15
+ name = description[:name]
16
+ in_order_to = description[:in_order_to] || ""
17
+ as_a = description[:as_a] || ""
18
+ i = description[:i] || ""
19
+
20
+ template = get_template(Pathname("../feature_template.rb").expand_path(__FILE__))
21
+ .gsub(/#\{id\}/, id)
22
+ .gsub(/#\{name\}/, name)
23
+ .gsub(/#\{in_order_to\}/, in_order_to)
24
+ .gsub(/#\{as_a\}/, as_a)
25
+ .gsub(/#\{i\}/, i)
26
+
27
+ fname = name.downcase.gsub(' ', '_')
28
+ feature_file = "#{fname}.rb"
29
+ root = root || File.join(Dir.pwd, fname)
30
+
31
+ FileUtils.mkdir root unless File.directory? root
32
+ FileUtils.mkdir File.join(root, "Stories")
33
+ FileUtils.mkdir File.join(root, "Scenarios")
34
+
35
+ dest = File.join(root, feature_file)
36
+ File.open(dest, "w") do |f|
37
+ f.write(template)
38
+ end
39
+
40
+ return feature_file
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,13 @@
1
+ require 'marso'
2
+
3
+ module MarsoContext
4
+ def self.feature(ctx={})
5
+ Marso::Feature.new({
6
+ :id => "#{id}",
7
+ :name => "#{name}",
8
+ :in_order_to => "#{in_order_to}",
9
+ :as_a => "#{as_a}",
10
+ :i => "#{i}"
11
+ })
12
+ end
13
+ end
@@ -1,4 +1,4 @@
1
- require 'colorize'
1
+ require 'colorize'
2
2
  require 'securerandom'
3
3
  require_relative '../../config'
4
4
  require_relative 'scenario_publish'
@@ -13,16 +13,16 @@ module Marso
13
13
  validate_arguments(description, ctx)
14
14
 
15
15
  @description = description.clone
16
+ @ctx=ctx.clone
16
17
 
17
- @description[:id] = SecureRandom.hex(4) if description[:id].nil?
18
+ @description[:id] = SecureRandom.hex(3) if description[:id].nil?
18
19
  @description[:status] = :none if description[:status].nil?
19
- @ctx=ctx.clone
20
20
 
21
21
  @id = @description[:id]
22
- @before_run=@description[:before_run]
23
- @get_scenario=@description[:get_scenario]
24
- @after_run=@description[:after_run]
25
- @status=@description[:status]
22
+ @before_run = @description[:before_run]
23
+ @get_scenario = @description[:get_scenario]
24
+ @after_run = @description[:after_run]
25
+ @status = @description[:status]
26
26
 
27
27
  @story_id = ctx[:story_id]
28
28
  @feature_id = ctx[:feature_id]
@@ -69,7 +69,7 @@ module Marso
69
69
 
70
70
  attr_reader :name, :steps, :id, :status, :color_theme,
71
71
  :cancel_steps_upon_issues, :realtime_step_stdout, :ctx, :story_id,
72
- :feature_id, :header, :tree_position
72
+ :feature_id, :header, :tree_position, :fname
73
73
 
74
74
  # description: Hash defined as follow
75
75
  # :id => Arbitrary number or string. Default is randomly generated
@@ -107,6 +107,7 @@ module Marso
107
107
  end
108
108
 
109
109
  @name = description[:name]
110
+ @fname = description[:name].downcase.gsub(' ', '_')
110
111
  @ctx = ctx.clone
111
112
 
112
113
  @tree_position = 0
@@ -226,8 +227,9 @@ module Marso
226
227
  private
227
228
 
228
229
  def validate_arguments(description, ctx)
229
- raise ArgumentError, "Argument 'description' must be a Hash" unless description.is_a?(Hash)
230
- raise ArgumentError, "Argument 'ctx' must be a Hash" unless ctx.is_a?(Hash)
230
+ raise ArgumentError, "Argument 'description' must be a Hash" unless description.is_a?(Hash)
231
+ raise ArgumentError, "Argument 'description[:name]' is required" if description[:name].nil?
232
+ raise ArgumentError, "Argument 'ctx' must be a Hash" unless ctx.is_a?(Hash)
231
233
  end
232
234
 
233
235
  def add_step(step_type, assumption_text, *args, &block)
@@ -0,0 +1,39 @@
1
+ require 'pathname'
2
+ require 'securerandom'
3
+ require 'fileutils'
4
+ require_relative 'scenario'
5
+ require_relative '../base_factory'
6
+
7
+ module Marso
8
+
9
+ class ScenarioFactory
10
+ include Marso::BaseFactory
11
+
12
+ def create_scenario_file(description={}, root=nil)
13
+ raise ArgumentError, "Scenario's name is required" unless description[:name]
14
+ id = description[:id] || SecureRandom.hex(3)
15
+ name = description[:name]
16
+ given = description[:given] || ""
17
+ _when = description[:when] || ""
18
+ _then = description[:then] || ""
19
+
20
+ template = get_template(Pathname("../scenario_template.rb").expand_path(__FILE__))
21
+ .gsub(/#\{id\}/, id)
22
+ .gsub(/#\{name\}/, name)
23
+ .gsub(/#\{given\}/, given)
24
+ .gsub(/#\{_when\}/, _when)
25
+ .gsub(/#\{_then\}/, _then)
26
+
27
+ fname = name.downcase.gsub(' ', '_')
28
+ feature_file = "#{fname}.rb"
29
+ root = root || Dir.pwd
30
+
31
+ dest = File.join(root, feature_file)
32
+ File.open(dest, "w") do |f|
33
+ f.write(template)
34
+ end
35
+
36
+ return feature_file
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,31 @@
1
+ require 'marso'
2
+
3
+ module MarsoContext
4
+ def self.scenario_context(ctx={})
5
+ Marso::ScenarioContext.new({
6
+ :id => "#{id}",
7
+ :before_run => lambda { |id, ctx|
8
+ # Enter the code you want to execute before running the scenario.
9
+ # Uncomment the code below if you want to open a Firefox browser.
10
+ # ctx[:browser] = Marso.openNewBrowser()
11
+ },
12
+ :get_scenario => lambda { |id, ctx|
13
+ Marso::Scenario.new({:id => id, :name => "#{name}"}, ctx)
14
+ .given("#{given}") {
15
+ # TODO: Enter your code here
16
+ }
17
+ .when("#{_when}"){
18
+ # TODO: Enter your code here
19
+ }
20
+ .then("#{_then}"){
21
+ # TODO: Enter your code here
22
+ }
23
+ },
24
+ :after_run => lambda { |id, ctx|
25
+ # Enter the code you want to execute after the scenario is done running.
26
+ # Uncomment the code below if you want to close the Firefox browser.
27
+ # ctx[:browser].close
28
+ }
29
+ }, ctx)
30
+ end
31
+ end
@@ -10,11 +10,11 @@ module Marso
10
10
  include StoryPublish
11
11
 
12
12
  attr_reader :id, :description, :status, :ctx, :scenario_contexts,
13
- :feature_id, :tree_position, :header, :text, :color_theme, :rootpath
13
+ :feature_id, :tree_position, :header, :text, :color_theme, :rootpath, :name, :fname
14
14
 
15
15
  # description (optional): Hash defined as follow
16
16
  # :id => Arbitrary number or string. Default is randomly generated
17
- # (hex string (length 8))
17
+ # (hex string (length 6))
18
18
  # :name => Story's name
19
19
  # :in_order_to => String that describes the fundamental story's business
20
20
  # value
@@ -35,9 +35,11 @@ module Marso
35
35
  @ctx = ctx.clone
36
36
 
37
37
  @description[:scenario_contexts] = [] if description[:scenario_contexts].nil?
38
- @description[:id] = SecureRandom.hex(4) if description[:id].nil?
38
+ @description[:id] = SecureRandom.hex(3) if description[:id].nil?
39
39
  @description[:rootpath] = File.dirname(caller[0]) if description[:rootpath].nil?
40
40
 
41
+ @name = @description[:name]
42
+ @fname = @description[:name].downcase.gsub(' ', '_')
41
43
  @rootpath = @description[:rootpath]
42
44
  @id = @description[:id]
43
45
  @scenario_contexts = @description[:scenario_contexts]
@@ -60,6 +62,7 @@ module Marso
60
62
 
61
63
  def validate_arguments(description, ctx)
62
64
  raise ArgumentError, "Argument 'description' cannot be nil" if description.nil?
65
+ raise ArgumentError, "Argument 'description[:name]' is required" if description[:name].nil?
63
66
  raise ArgumentError, "Argument 'description' must be a Hash" unless description.is_a?(Hash)
64
67
  raise ArgumentError, "Argument 'ctx' must be a Hash" unless ctx.is_a?(Hash)
65
68
  unless description[:scenario_contexts].nil?
@@ -0,0 +1,42 @@
1
+ require 'pathname'
2
+ require 'securerandom'
3
+ require 'fileutils'
4
+ require_relative 'story'
5
+ require_relative '../base_factory'
6
+
7
+ module Marso
8
+
9
+ class StoryFactory
10
+ include Marso::BaseFactory
11
+
12
+ def create_story_file(description={}, root=nil)
13
+ raise ArgumentError, "Story's name is required" unless description[:name]
14
+ id = description[:id] || SecureRandom.hex(3)
15
+ name = description[:name]
16
+ in_order_to = description[:in_order_to] || ""
17
+ as_a = description[:as_a] || ""
18
+ i = description[:i] || ""
19
+
20
+ template = get_template(Pathname("../story_template.rb").expand_path(__FILE__))
21
+ .gsub(/#\{id\}/, id)
22
+ .gsub(/#\{name\}/, name)
23
+ .gsub(/#\{in_order_to\}/, in_order_to)
24
+ .gsub(/#\{as_a\}/, as_a)
25
+ .gsub(/#\{i\}/, i)
26
+
27
+ fname = name.downcase.gsub(' ', '_')
28
+ feature_file = "#{fname}.rb"
29
+ root = root || File.join(Dir.pwd, fname)
30
+
31
+ FileUtils.mkdir root unless File.directory? root
32
+ FileUtils.mkdir File.join(root, "Scenarios")
33
+
34
+ dest = File.join(root, feature_file)
35
+ File.open(dest, "w") do |f|
36
+ f.write(template)
37
+ end
38
+
39
+ return feature_file
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,14 @@
1
+ require 'marso'
2
+
3
+ module MarsoContext
4
+ def self.story(ctx={})
5
+ Marso::Story.new({
6
+ :id => "#{id}",
7
+ :name => "#{name}",
8
+ :in_order_to => "#{in_order_to}",
9
+ :as_a => "#{as_a}",
10
+ :i => "#{i}"
11
+ },
12
+ ctx)
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module Marso
2
- VERSION ="0.1.29059"
2
+ VERSION ="0.1.47959"
3
3
  end
@@ -29,12 +29,14 @@ Gem::Specification.new do |spec|
29
29
  spec.license = "MIT"
30
30
 
31
31
  spec.files = `git ls-files -z`.split("\x0")
32
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
32
+ spec.executables = ["marso"]
33
33
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
34
34
  spec.require_paths = ["lib"]
35
35
 
36
36
  spec.add_development_dependency "bundler", "~> 1.6"
37
37
  spec.add_development_dependency "rake", "~> 10.3"
38
+ spec.add_development_dependency('mocha', '~> 1.0')
39
+ spec.add_development_dependency('turn', '~> 0.9')
38
40
  spec.add_runtime_dependency "colorize", "~> 0.7"
39
41
  spec.add_runtime_dependency "watir-webdriver", "~> 0.6"
40
42
  spec.add_runtime_dependency "eventmachine", "~> 1.0"
@@ -0,0 +1,6 @@
1
+ feature:
2
+ id: "8f943a"
3
+ name: "Add to shopping cart"
4
+ in_order_to: "buy more than one item in a single transaction"
5
+ as_a: "online consumer"
6
+ i: "want to add items to a shopping cart"
@@ -0,0 +1,6 @@
1
+ scenario:
2
+ id: "8f943a"
3
+ name: "Add one item to my shopping cart"
4
+ given: "I'm currently browsing a product catalog"
5
+ when: "I click on the 'Add to cart' button of a product"
6
+ then: "a popup box appears saying that the product has been successfully added to my shopping cart"
@@ -0,0 +1,6 @@
1
+ story:
2
+ id: "8f943a"
3
+ name: "Add to shopping cart"
4
+ in_order_to: "buy more than one item in a single transaction"
5
+ as_a: "online consumer"
6
+ i: "want to add items to a shopping cart"
@@ -0,0 +1,15 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'
3
+ require 'marso'
4
+ require 'toolbelt/fixture'
5
+ require 'pathname'
6
+ require 'fileutils'
7
+
8
+ # Attempt to load turn to show formatted test results
9
+ begin
10
+ require "turn"
11
+ Turn.config.format = :pretty
12
+ Turn.config.natural = true
13
+ rescue LoadError
14
+ end
15
+
@@ -0,0 +1,12 @@
1
+ require 'yaml'
2
+ require 'erb'
3
+ require 'pathname'
4
+
5
+ fixture_root = Pathname("../../fixtures").expand_path(__FILE__)
6
+
7
+ Fixtures = Hash.new do |hash, f_name|
8
+ filepath = fixture_root.join("#{f_name}.yml")
9
+ file_contents = open(filepath).read
10
+ YAML.load(ERB.new(file_contents).result).to_hash
11
+ hash[f_name] = YAML.load(ERB.new(file_contents).result).to_hash
12
+ end
@@ -0,0 +1,36 @@
1
+ require 'test_helper'
2
+
3
+ describe Marso::FeatureFactory do
4
+ subject { Marso::FeatureFactory.new }
5
+ let(:new_feature) { Fixtures['create_new_feature_file']['feature'] }
6
+ let(:features_root) { Pathname("../tmp").expand_path(__FILE__) }
7
+
8
+ before do
9
+ FileUtils.remove_dir features_root, true # Delete folder
10
+ FileUtils.mkdir features_root # Create folder
11
+ end
12
+
13
+ after do
14
+ FileUtils.remove_dir features_root, true
15
+ end
16
+
17
+ it "Creates a .rb feature file that contains the feature details" do
18
+ feature_file = subject.create_feature_file({
19
+ :id => new_feature['id'],
20
+ :name => new_feature['name'],
21
+ :in_order_to => new_feature['in_order_to'],
22
+ :as_a => new_feature['as_a'],
23
+ :i => new_feature['i']
24
+ }, features_root)
25
+
26
+ require File.join(features_root, feature_file)
27
+ f = MarsoContext.feature
28
+
29
+ f.id.must_equal new_feature['id']
30
+ f.name.must_equal new_feature['name']
31
+ f.description[:in_order_to].must_equal new_feature['in_order_to']
32
+ f.description[:as_a].must_equal new_feature['as_a']
33
+ f.description[:i].must_equal new_feature['i']
34
+ end
35
+
36
+ end
@@ -0,0 +1,40 @@
1
+ require 'test_helper'
2
+
3
+ describe Marso::ScenarioFactory do
4
+ subject { Marso::ScenarioFactory.new }
5
+ let(:new_scenario) { Fixtures['create_new_scenario_file']['scenario'] }
6
+ let(:scenario_root) { Pathname("../tmp").expand_path(__FILE__) }
7
+
8
+ before do
9
+ FileUtils.remove_dir scenario_root, true # Delete folder
10
+ FileUtils.mkdir scenario_root # Create folder
11
+ end
12
+
13
+ after do
14
+ FileUtils.remove_dir scenario_root, true
15
+ end
16
+
17
+ it "Creates a .rb scenario file that contains the scenario's details" do
18
+ file = subject.create_scenario_file({
19
+ :id => new_scenario['id'],
20
+ :name => new_scenario['name'],
21
+ :given => new_scenario['given'],
22
+ :when => new_scenario['when'],
23
+ :then => new_scenario['then']
24
+ }, scenario_root)
25
+
26
+ require File.join(scenario_root, file)
27
+ scn_ctx = MarsoContext.scenario_context
28
+ scn = scn_ctx.get_scenario.call(new_scenario['id'], {})
29
+
30
+ scn.id.must_equal new_scenario['id']
31
+ scn.name.must_equal new_scenario['name']
32
+ given_step = "Given #{new_scenario['given']}"
33
+ when_step = "When #{new_scenario['when']}"
34
+ then_step = "Then #{new_scenario['then']}"
35
+ scn.steps.any? { |s| s.description == given_step }.must_equal true
36
+ scn.steps.any? { |s| s.description == when_step }.must_equal true
37
+ scn.steps.any? { |s| s.description == then_step }.must_equal true
38
+ end
39
+
40
+ end
@@ -0,0 +1,36 @@
1
+ require 'test_helper'
2
+
3
+ describe Marso::StoryFactory do
4
+ subject { Marso::StoryFactory.new }
5
+ let(:new_story) { Fixtures['create_new_story_file']['story'] }
6
+ let(:stories_root) { Pathname("../tmp").expand_path(__FILE__) }
7
+
8
+ before do
9
+ FileUtils.remove_dir stories_root, true # Delete folder
10
+ FileUtils.mkdir stories_root # Create folder
11
+ end
12
+
13
+ after do
14
+ FileUtils.remove_dir stories_root, true
15
+ end
16
+
17
+ it "Creates a .rb story file that contains the story details" do
18
+ feature_file = subject.create_story_file({
19
+ :id => new_story['id'],
20
+ :name => new_story['name'],
21
+ :in_order_to => new_story['in_order_to'],
22
+ :as_a => new_story['as_a'],
23
+ :i => new_story['i']
24
+ }, stories_root)
25
+
26
+ require File.join(stories_root, feature_file)
27
+ s = MarsoContext.story
28
+
29
+ s.id.must_equal new_story['id']
30
+ s.name.must_equal new_story['name']
31
+ s.description[:in_order_to].must_equal new_story['in_order_to']
32
+ s.description[:as_a].must_equal new_story['as_a']
33
+ s.description[:i].must_equal new_story['i']
34
+ end
35
+
36
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marso
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.29059
4
+ version: 0.1.47959
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nicolas Dao
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-17 00:00:00.000000000 Z
11
+ date: 2014-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mocha
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: turn
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '0.9'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '0.9'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: colorize
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -85,7 +113,8 @@ description: Marso is the beginning of a small lightweight BDD project. Currentl
85
113
  or in red depending on the value of a predicate.
86
114
  email:
87
115
  - nicolas@quivers.com
88
- executables: []
116
+ executables:
117
+ - marso
89
118
  extensions: []
90
119
  extra_rdoc_files: []
91
120
  files:
@@ -95,18 +124,26 @@ files:
95
124
  - LICENSE.txt
96
125
  - README.md
97
126
  - Rakefile
127
+ - bin/marso
98
128
  - lib/marso.rb
99
129
  - lib/marso/config.rb
130
+ - lib/marso/domain/base_factory.rb
100
131
  - lib/marso/domain/feature/feature.rb
132
+ - lib/marso/domain/feature/feature_factory.rb
101
133
  - lib/marso/domain/feature/feature_load.rb
102
134
  - lib/marso/domain/feature/feature_publish.rb
135
+ - lib/marso/domain/feature/feature_template.rb
103
136
  - lib/marso/domain/scenario/scenario.rb
137
+ - lib/marso/domain/scenario/scenario_factory.rb
104
138
  - lib/marso/domain/scenario/scenario_publish.rb
139
+ - lib/marso/domain/scenario/scenario_template.rb
105
140
  - lib/marso/domain/step/step.rb
106
141
  - lib/marso/domain/step/step_publish.rb
107
142
  - lib/marso/domain/story/story.rb
143
+ - lib/marso/domain/story/story_factory.rb
108
144
  - lib/marso/domain/story/story_load.rb
109
145
  - lib/marso/domain/story/story_publish.rb
146
+ - lib/marso/domain/story/story_template.rb
110
147
  - lib/marso/factories.rb
111
148
  - lib/marso/helpers/componenthelper.rb
112
149
  - lib/marso/helpers/statushelper.rb
@@ -117,6 +154,14 @@ files:
117
154
  - lib/marso/validation/symbol.rb
118
155
  - lib/marso/version.rb
119
156
  - marso.gemspec
157
+ - test/fixtures/create_new_feature_file.yml
158
+ - test/fixtures/create_new_scenario_file.yml
159
+ - test/fixtures/create_new_story_file.yml
160
+ - test/test_helper.rb
161
+ - test/toolbelt/Fixture.rb
162
+ - test/unit/feature/feature_factory_test.rb
163
+ - test/unit/scenario/scenario_factory_test.rb
164
+ - test/unit/story/story_factory_test.rb
120
165
  homepage: https://github.com/nicolasdao/marso
121
166
  licenses:
122
167
  - MIT
@@ -141,4 +186,12 @@ rubygems_version: 2.2.2
141
186
  signing_key:
142
187
  specification_version: 4
143
188
  summary: Marso is a lightweight BDD project
144
- test_files: []
189
+ test_files:
190
+ - test/fixtures/create_new_feature_file.yml
191
+ - test/fixtures/create_new_scenario_file.yml
192
+ - test/fixtures/create_new_story_file.yml
193
+ - test/test_helper.rb
194
+ - test/toolbelt/Fixture.rb
195
+ - test/unit/feature/feature_factory_test.rb
196
+ - test/unit/scenario/scenario_factory_test.rb
197
+ - test/unit/story/story_factory_test.rb