cukedep 0.1.11 → 0.2.00

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +6 -14
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +10 -10
  4. data/CHANGELOG.md +6 -0
  5. data/Gemfile +5 -5
  6. data/LICENSE.txt +1 -1
  7. data/README.md +1 -1
  8. data/Rakefile +30 -30
  9. data/bin/cukedep +15 -15
  10. data/lib/cukedep/application.rb +105 -112
  11. data/lib/cukedep/cli/cmd-line.rb +11 -13
  12. data/lib/cukedep/config.rb +85 -89
  13. data/lib/cukedep/constants.rb +5 -5
  14. data/lib/cukedep/cuke-runner.rb +191 -198
  15. data/lib/cukedep/customization.rb +30 -30
  16. data/lib/cukedep/feature-model.rb +43 -46
  17. data/lib/cukedep/feature-rep.rb +9 -11
  18. data/lib/cukedep/file-action.rb +11 -18
  19. data/lib/cukedep/gherkin-facade.rb +11 -6
  20. data/lib/cukedep/gherkin-listener.rb +12 -42
  21. data/lib/cukedep/hook-dsl.rb +78 -78
  22. data/lib/cukedep/sandbox.rb +15 -16
  23. data/lib/cukedep.rb +1 -2
  24. data/sample/features/step_definitions/steps.rb +2 -2
  25. data/sample/model/model.rb +19 -20
  26. data/spec/cukedep/application_spec.rb +80 -80
  27. data/spec/cukedep/cli/cmd-line_spec.rb +88 -88
  28. data/spec/cukedep/cuke-runner_spec.rb +74 -74
  29. data/spec/cukedep/customization_spec.rb +31 -31
  30. data/spec/cukedep/debug-file-action.rb +29 -29
  31. data/spec/cukedep/feature-model_spec.rb +100 -100
  32. data/spec/cukedep/feature-rep_spec.rb +2 -1
  33. data/spec/cukedep/file-action_spec.rb +365 -366
  34. data/spec/cukedep/file-parsing.rb +39 -41
  35. data/spec/cukedep/gherkin-facade_spec.rb +48 -49
  36. data/spec/cukedep/gherkin-listener_spec.rb +55 -57
  37. data/spec/cukedep/hook-dsl_spec.rb +182 -182
  38. data/spec/cukedep/sample_features/cukedep_hooks.rb +30 -30
  39. data/spec/cukedep/sample_features/standalone.feature +1 -1
  40. data/templates/rake.erb +12 -21
  41. metadata +80 -58
  42. data/sample/result.html +0 -472
  43. data/spec/cukedep/sample_features/cukedep.rake +0 -215
  44. data/spec/cukedep/sample_features/dependencies.dot +0 -38
  45. data/spec/cukedep/sample_features/feature2id.csv +0 -7
@@ -3,10 +3,10 @@
3
3
 
4
4
  module Cukedep # Module used as a namespace
5
5
  # The version number of the gem.
6
- Version = '0.1.11'
6
+ Version = '0.2.00'.freeze
7
7
 
8
8
  # Brief description of the gem.
9
- Description = 'Manage dependencies between Cucumber feature files'
9
+ Description = 'Manage dependencies between Cucumber feature files'.freeze
10
10
 
11
11
  # Constant Cukedep::RootDir contains the absolute path of Rodent's
12
12
  # root directory. Note: it also ends with a slash character.
@@ -22,11 +22,11 @@ module Cukedep # Module used as a namespace
22
22
  end
23
23
 
24
24
  # The file name for the user's settings
25
- YMLFilename = '.cukedep.yml'
26
-
25
+ YMLFilename = '.cukedep.yml'.freeze
26
+
27
27
  # The file name for the custom block codes associated
28
28
  # with before/after events.
29
- HookFilename = 'cukedep_hooks.rb'
29
+ HookFilename = 'cukedep_hooks.rb'.freeze
30
30
  end
31
31
  end # module
32
32
 
@@ -1,198 +1,191 @@
1
- # File: cuke-runner.rb
2
-
3
- require 'pathname'
4
- require 'rake'
5
-
6
- # Run Cucumber via specialized Rake task
7
- require 'cucumber/rake/task'
8
-
9
- require_relative 'file-action'
10
- require_relative 'customization'
11
-
12
- # UGLY workaround for bug in Cucumber's rake task
13
- if Gem::VERSION[0].to_i >= 2 && Cucumber::VERSION <= '1.3.2'
14
- # Monkey-patch a buggy method
15
- module Cucumber
16
- module Rake
17
- class Task
18
- class ForkedCucumberRunner
19
- def gem_available?(gemname)
20
- if Gem::VERSION[0].to_i >= 2
21
- gem_available_new_rubygems?(gemname)
22
- else
23
- gem_available_old_rubygems?(gemname)
24
- end
25
- end
26
- end # class
27
- end # class
28
- end # module
29
- end # module
30
- end
31
-
32
-
33
-
34
- module Cukedep # This module is used as a namespace
35
- # Purpose: to launch Cucumber in the appropriate directory
36
- # and pass it command-line arguments.
37
- # Responsibilities:
38
- # Know how to invoke Cucumber
39
- # Know the base directory
40
- # Know the project's root dir
41
- class CukeRunner
42
- # The current state of the runner.
43
- attr_reader(:state)
44
-
45
- # The absolute path of the root's project directory
46
- attr_reader(:proj_dir)
47
- attr_reader(:base_dir)
48
- attr_reader(:config)
49
- attr_reader(:handlers)
50
-
51
- attr(:cucumber_opts, true)
52
-
53
- # Constructor
54
- def initialize(baseDir, projectDir, aConfig)
55
- @base_dir = baseDir
56
- @proj_dir = validated_proj_dir(projectDir)
57
- @config = aConfig
58
- @handlers = Customization.new.build_handlers(baseDir)
59
-
60
- @state = :Initialized
61
- end
62
-
63
- # Launch Cucumber in the project directory.
64
- def invoke()
65
- options = [] # TODO: retrieve Cucumber options
66
- orig_dir = Dir.getwd
67
- Dir.chdir(proj_dir)
68
-
69
- begin
70
- cuke_task = Cucumber::Rake::Task.new do |t|
71
- t.cucumber_opts = options
72
- end
73
-
74
- cuke_task.runner.run
75
- rescue SystemExit => exc # Cucumber reports a failure.
76
- raise StandardError, "Cucumber exited with status #{exc.status}"
77
- ensure
78
- Dir.chdir(orig_dir)
79
- end
80
- end
81
-
82
- # Event handler that is triggered
83
- # before any other event.
84
- # It executes the before all hook first.
85
- # Then it executes in the following order:
86
- # Built-in save action, Custom save action
87
- # Built-in delete action, Custom delete action
88
- # Built-in copy action, Custom copy action
89
- def before_all()
90
- expected_state(:Initialized)
91
-
92
- # Execute before all hook code
93
- run_code_block
94
-
95
- # Execute file actions
96
- builtin_actions = ActionTriplet.builtin(:before_all)
97
- custom_actions = ActionTriplet.new(config.before_all_f_actions)
98
- run_triplets([builtin_actions, custom_actions])
99
- @state = :ReadyToRun
100
- end
101
-
102
-
103
- # Event handler that is triggered
104
- # after any other event.
105
- # It executes first actions in the following order:
106
- # Built-in save action, Custom save action
107
- # Built-in delete action, Custom delete action
108
- # Built-in copy action, Custom copy action
109
- # Then it executes the after all hook last.
110
- def after_all()
111
- expected_state(:ReadyToRun)
112
-
113
- builtin_actions = ActionTriplet.builtin(:after_all)
114
- custom_actions = ActionTriplet.new(config.after_all_f_actions)
115
- run_triplets([builtin_actions, custom_actions])
116
-
117
- # Execute before all hook code
118
- run_code_block
119
- @state = :Complete
120
- end
121
-
122
-
123
- def run!(fileNames)
124
- expected_state(:ReadyToRun)
125
- before_each(fileNames)
126
- invoke
127
- after_each
128
- end
129
-
130
-
131
- private
132
-
133
- def validated_proj_dir(projectDir)
134
- path = Pathname.new(projectDir)
135
- path = path.expand_path if path.relative?
136
- fail StandardError, "No such project path: '#{path}'" unless path.exist?
137
-
138
- return path.to_s
139
- end
140
-
141
- def expected_state(aState)
142
- return if state == aState
143
- msg = "expected state was '#{aState}' instead of '#{state}'."
144
- fail StandardError, msg
145
- end
146
-
147
-
148
- def before_each(fileNames)
149
- # Execute before each hook code
150
- run_code_block(fileNames)
151
-
152
- builtins = ActionTriplet.builtin(:before_each).dup
153
- builtins.copy_action.patterns = fileNames unless builtins.nil?
154
-
155
- custom_actions = ActionTriplet.new(config.before_each_f_actions)
156
- run_triplets([builtins, custom_actions])
157
- end
158
-
159
-
160
- def after_each()
161
- builtin_actions = ActionTriplet.builtin(:after_each)
162
-
163
- custom_actions = ActionTriplet.new(config.after_each_f_actions)
164
- run_triplets([builtin_actions, custom_actions])
165
-
166
- # Execute after each hook code
167
- run_code_block
168
- end
169
-
170
-
171
- def run_triplets(theTriplets)
172
- all_triplets = theTriplets.compact # Remove nil elements
173
-
174
- # Do all save actions...
175
- all_triplets.each { |t| t.save_action.run!(proj_dir, base_dir) }
176
-
177
- # Do all delete actions...
178
- all_triplets.each { |t| t.delete_action.run!(proj_dir) }
179
-
180
- # Do all copy actions...
181
- all_triplets.each { |t| t.copy_action.run!(base_dir, proj_dir) }
182
- end
183
-
184
-
185
- def run_code_block(*args)
186
- # Retrieve the name of the parent method.
187
- parent_mth = (caller[0].sub(/^(.+):in (.+)$/, '\2'))[1..-2]
188
- kind, scope = parent_mth.split('_')
189
- hook_kind = (kind + '_hooks')
190
-
191
- kode = handlers[hook_kind.to_sym][scope.to_sym]
192
- return if kode.nil?
193
- safe_args = args.map { |one_arg| one_arg.dup.freeze }
194
- kode.call(*safe_args)
195
- end
196
- end # class
197
- end # module
198
- # End of file
1
+ # File: cuke-runner.rb
2
+
3
+ require 'pathname'
4
+ require 'rake'
5
+
6
+ # Run Cucumber via specialized Rake task
7
+ require 'cucumber/rake/task'
8
+
9
+ require_relative 'file-action'
10
+ require_relative 'customization'
11
+
12
+ # UGLY workaround for bug in Cucumber's rake task
13
+ if Gem::VERSION[0].to_i >= 2 && Cucumber::VERSION <= '1.3.2'
14
+ # Monkey-patch a buggy method
15
+ module Cucumber
16
+ module Rake
17
+ class Task
18
+ class ForkedCucumberRunner
19
+ def gem_available?(gemname)
20
+ if Gem::VERSION[0].to_i >= 2
21
+ gem_available_new_rubygems?(gemname)
22
+ else
23
+ gem_available_old_rubygems?(gemname)
24
+ end
25
+ end
26
+ end # class
27
+ end # class
28
+ end # module
29
+ end # module
30
+ end
31
+
32
+
33
+
34
+ module Cukedep # This module is used as a namespace
35
+ # Purpose: to launch Cucumber in the appropriate directory
36
+ # and pass it command-line arguments.
37
+ # Responsibilities:
38
+ # Know how to invoke Cucumber
39
+ # Know the base directory
40
+ # Know the project's root dir
41
+ class CukeRunner
42
+ # The current state of the runner.
43
+ attr_reader(:state)
44
+
45
+ # The absolute path of the root's project directory
46
+ attr_reader(:proj_dir)
47
+ attr_reader(:base_dir)
48
+ attr_reader(:config)
49
+ attr_reader(:handlers)
50
+
51
+ attr_accessor(:cucumber_opts)
52
+
53
+ # Constructor
54
+ def initialize(baseDir, projectDir, aConfig)
55
+ @base_dir = baseDir
56
+ @proj_dir = validated_proj_dir(projectDir)
57
+ @config = aConfig
58
+ @handlers = Customization.new.build_handlers(baseDir)
59
+
60
+ @state = :Initialized
61
+ end
62
+
63
+ # Launch Cucumber in the project directory.
64
+ def invoke
65
+ options = [] # TODO: retrieve Cucumber options
66
+ orig_dir = Dir.getwd
67
+ Dir.chdir(proj_dir)
68
+
69
+ begin
70
+ cuke_task = Cucumber::Rake::Task.new do |t|
71
+ t.cucumber_opts = options
72
+ end
73
+
74
+ cuke_task.runner.run
75
+ rescue SystemExit => exc # Cucumber reports a failure.
76
+ raise StandardError, "Cucumber exited with status #{exc.status}"
77
+ ensure
78
+ Dir.chdir(orig_dir)
79
+ end
80
+ end
81
+
82
+ # Event handler that is triggered
83
+ # before any other event.
84
+ # It executes the before all hook first.
85
+ # Then it executes in the following order:
86
+ # Built-in save action, Custom save action
87
+ # Built-in delete action, Custom delete action
88
+ # Built-in copy action, Custom copy action
89
+ def before_all
90
+ expected_state(:Initialized)
91
+
92
+ # Execute before all hook code
93
+ run_code_block
94
+
95
+ # Execute file actions
96
+ builtin_actions = ActionTriplet.builtin(:before_all)
97
+ custom_actions = ActionTriplet.new(config.before_all_f_actions)
98
+ run_triplets([builtin_actions, custom_actions])
99
+ @state = :ReadyToRun
100
+ end
101
+
102
+ # Event handler that is triggered
103
+ # after any other event.
104
+ # It executes first actions in the following order:
105
+ # Built-in save action, Custom save action
106
+ # Built-in delete action, Custom delete action
107
+ # Built-in copy action, Custom copy action
108
+ # Then it executes the after all hook last.
109
+ def after_all
110
+ expected_state(:ReadyToRun)
111
+
112
+ builtin_actions = ActionTriplet.builtin(:after_all)
113
+ custom_actions = ActionTriplet.new(config.after_all_f_actions)
114
+ run_triplets([builtin_actions, custom_actions])
115
+
116
+ # Execute before all hook code
117
+ run_code_block
118
+ @state = :Complete
119
+ end
120
+
121
+ def run!(fileNames)
122
+ expected_state(:ReadyToRun)
123
+ before_each(fileNames)
124
+ invoke
125
+ after_each
126
+ end
127
+
128
+ private
129
+
130
+ def validated_proj_dir(projectDir)
131
+ path = Pathname.new(projectDir)
132
+ path = path.expand_path if path.relative?
133
+ raise StandardError, "No such project path: '#{path}'" unless path.exist?
134
+
135
+ return path.to_s
136
+ end
137
+
138
+ def expected_state(aState)
139
+ return if state == aState
140
+ msg = "expected state was '#{aState}' instead of '#{state}'."
141
+ raise StandardError, msg
142
+ end
143
+
144
+ def before_each(fileNames)
145
+ # Execute before each hook code
146
+ run_code_block(fileNames)
147
+
148
+ builtins = ActionTriplet.builtin(:before_each).dup
149
+ builtins.copy_action.patterns = fileNames unless builtins.nil?
150
+
151
+ custom_actions = ActionTriplet.new(config.before_each_f_actions)
152
+ run_triplets([builtins, custom_actions])
153
+ end
154
+
155
+ def after_each
156
+ builtin_actions = ActionTriplet.builtin(:after_each)
157
+
158
+ custom_actions = ActionTriplet.new(config.after_each_f_actions)
159
+ run_triplets([builtin_actions, custom_actions])
160
+
161
+ # Execute after each hook code
162
+ run_code_block
163
+ end
164
+
165
+ def run_triplets(theTriplets)
166
+ all_triplets = theTriplets.compact # Remove nil elements
167
+
168
+ # Do all save actions...
169
+ all_triplets.each { |t| t.save_action.run!(proj_dir, base_dir) }
170
+
171
+ # Do all delete actions...
172
+ all_triplets.each { |t| t.delete_action.run!(proj_dir) }
173
+
174
+ # Do all copy actions...
175
+ all_triplets.each { |t| t.copy_action.run!(base_dir, proj_dir) }
176
+ end
177
+
178
+ def run_code_block(*args)
179
+ # Retrieve the name of the parent method.
180
+ parent_mth = (caller[0].sub(/^(.+):in (.+)$/, '\2'))[1..-2]
181
+ kind, scope = parent_mth.split('_')
182
+ hook_kind = (kind + '_hooks')
183
+
184
+ kode = handlers[hook_kind.to_sym][scope.to_sym]
185
+ return if kode.nil?
186
+ safe_args = args.map { |one_arg| one_arg.dup.freeze }
187
+ kode.call(*safe_args)
188
+ end
189
+ end # class
190
+ end # module
191
+ # End of file
@@ -1,30 +1,30 @@
1
- # File: customization.rb
2
-
3
- require_relative 'constants'
4
- require_relative 'hook-dsl'
5
-
6
- module Cukedep # This module is used as a namespace
7
- class Customization
8
- # Retrieve before/after handlers from file
9
- # Handlers are put in a Hash with keys :before_hooks, :after_hooks.
10
- def build_handlers(directory)
11
- handlers = nil
12
-
13
- filepath = directory + '/' + Cukedep::HookFilename
14
- if File.exist? filepath
15
- obj = Object.new
16
- obj.extend(HookDSL)
17
- hook_source = File.read(filepath)
18
- obj.instance_eval(hook_source)
19
- handlers = {
20
- before_hooks: obj.before_hooks,
21
- after_hooks: obj.after_hooks
22
- }
23
- end
24
-
25
- return handlers
26
- end
27
- end # class
28
- end # module
29
-
30
- # End of file
1
+ # File: customization.rb
2
+
3
+ require_relative 'constants'
4
+ require_relative 'hook-dsl'
5
+
6
+ module Cukedep # This module is used as a namespace
7
+ class Customization
8
+ # Retrieve before/after handlers from file
9
+ # Handlers are put in a Hash with keys :before_hooks, :after_hooks.
10
+ def build_handlers(directory)
11
+ handlers = nil
12
+
13
+ filepath = directory + '/' + Cukedep::HookFilename
14
+ if File.exist? filepath
15
+ obj = Object.new
16
+ obj.extend(HookDSL)
17
+ hook_source = File.read(filepath)
18
+ obj.instance_eval(hook_source)
19
+ handlers = {
20
+ before_hooks: obj.before_hooks,
21
+ after_hooks: obj.after_hooks
22
+ }
23
+ end
24
+
25
+ return handlers
26
+ end
27
+ end # class
28
+ end # module
29
+
30
+ # End of file