marso 0.1.29059 → 0.1.47959

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.
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