clintegracon 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -2
  3. data/Gemfile.lock +23 -17
  4. data/Rakefile +5 -0
  5. data/clintegracon.gemspec +2 -3
  6. data/lib/CLIntegracon/adapter/bacon.rb +24 -11
  7. data/lib/CLIntegracon/diff.rb +21 -21
  8. data/lib/CLIntegracon/file_tree_spec.rb +78 -58
  9. data/lib/CLIntegracon/file_tree_spec_context.rb +101 -40
  10. data/lib/CLIntegracon/subject.rb +16 -16
  11. data/lib/CLIntegracon/version.rb +1 -1
  12. data/spec/bacon/execution_output.txt +40 -16
  13. data/spec/bacon/spec_helper.rb +10 -1
  14. data/spec/integration/coffeemaker_help/after/execution_output.txt +0 -1
  15. data/spec/integration/coffeemaker_no_milk/after/BlackEye.brewed-coffee.decanted +0 -0
  16. data/spec/integration/coffeemaker_no_milk/after/CaPheSuaDa.brewed-coffee.decanted +0 -0
  17. data/spec/integration/coffeemaker_no_milk/after/RedTux.brewed-coffee.decanted +0 -0
  18. data/spec/integration/coffeemaker_no_milk_sweetner_honey/after/Affogato.brewed-coffee +2 -0
  19. data/spec/integration/coffeemaker_no_milk_sweetner_honey/after/Affogato.brewed-coffee.decanted +0 -0
  20. data/spec/integration/coffeemaker_no_milk_sweetner_honey/after/BlackEye.brewed-coffee +2 -0
  21. data/spec/integration/coffeemaker_no_milk_sweetner_honey/after/BlackEye.brewed-coffee.decanted +0 -0
  22. data/spec/integration/coffeemaker_no_milk_sweetner_honey/after/Coffeemakerfile.yml +2 -0
  23. data/spec/integration/coffeemaker_no_milk_sweetner_honey/after/RedTux.brewed-coffee +2 -0
  24. data/spec/integration/coffeemaker_no_milk_sweetner_honey/after/RedTux.brewed-coffee.decanted +0 -0
  25. data/spec/integration/coffeemaker_no_milk_sweetner_honey/after/execution_output.txt +3 -0
  26. data/spec/integration/coffeemaker_no_milk_sweetner_honey/before/Coffeemakerfile.yml +2 -0
  27. metadata +34 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e7ea45e09d41cdf32e54a9f202b3ef12249cb234
4
- data.tar.gz: 572433ceeea7dbdac41d2408c501f59ecfdda7cd
3
+ metadata.gz: 8783eed598a5361fc795faf244dbd22fe60a35f1
4
+ data.tar.gz: a030a86de14cb5a5a4a9e686b5943a6a1c8fb864
5
5
  SHA512:
6
- metadata.gz: 5800a93a5b745f89a39a65e5c4d2d7dab91ea49f77636d13f69b82976933d24966108305cbf7d19f12a8da4d39ce19b00c26dda6e818412b2d64ee2d16bc9e93
7
- data.tar.gz: 3afc19fc729fea9dfa3327a0941cec7b98c8be85cb1dc521f8f7966f4f09d31f8692af2bdef73398545f76a690ceafac3de67777709ab30c1ba07f152901d46f
6
+ metadata.gz: 6fca68914e6029a04788fb6c99e37abaa8c392fc541f86219a213c6594ae86c848d05e193199179071b66ac90f79a88de8716993510b3592bf6cb27ed3c1b139
7
+ data.tar.gz: 3db0cd2ef3d3dcc8ab501db629bf0121d8587fcb44a765a6c8be18b6cb0488862c543dee168d02750ed8241baf564b52b3beaf8ca41620817ef8865520b4de14
data/.travis.yml CHANGED
@@ -1,7 +1,10 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
4
- - 2.1.1
3
+ # OS X 10.9.5-10.10.0 (2.0.0-p481)
4
+ - 2.0.0-p481
5
+ # OS X 10.9.3-10.9.4
6
+ - 2.0.0-p451
7
+
5
8
 
6
9
  #addons:
7
10
  # code_climate:
data/Gemfile.lock CHANGED
@@ -1,45 +1,52 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- clintegracon (0.6.1)
4
+ clintegracon (0.7.0)
5
5
  colored (~> 1.2)
6
6
  diffy
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activesupport (3.2.20)
12
- i18n (~> 0.6, >= 0.6.4)
13
- multi_json (~> 1.0)
11
+ activesupport (4.2.1)
12
+ i18n (~> 0.7)
13
+ json (~> 1.7, >= 1.7.7)
14
+ minitest (~> 5.1)
15
+ thread_safe (~> 0.3, >= 0.3.4)
16
+ tzinfo (~> 1.1)
14
17
  bacon (1.2.0)
15
- claide (0.7.0)
18
+ claide (0.8.1)
16
19
  coderay (1.1.0)
17
20
  colored (1.2)
18
- diffy (3.0.6)
19
- i18n (0.6.11)
20
- inch (0.5.0)
21
+ diffy (3.0.7)
22
+ i18n (0.7.0)
23
+ inch (0.6.1)
21
24
  pry
22
25
  sparkr (>= 0.2.0)
23
26
  term-ansicolor
24
- yard (~> 0.8.7)
27
+ yard (~> 0.8.7.5)
28
+ json (1.8.2)
25
29
  metaclass (0.0.4)
26
30
  method_source (0.8.2)
27
- mocha (1.0.0)
31
+ minitest (5.6.1)
32
+ mocha (1.1.0)
28
33
  metaclass (~> 0.0.1)
29
34
  mocha-on-bacon (0.2.2)
30
35
  mocha (>= 0.13.0)
31
- multi_json (1.10.1)
32
36
  pry (0.10.1)
33
37
  coderay (~> 1.1.0)
34
38
  method_source (~> 0.8.1)
35
39
  slop (~> 3.4)
36
- rake (10.1.1)
40
+ rake (10.4.2)
37
41
  slop (3.6.0)
38
42
  sparkr (0.4.1)
39
43
  term-ansicolor (1.3.0)
40
44
  tins (~> 1.0)
41
- tins (1.3.3)
42
- yard (0.8.7.4)
45
+ thread_safe (0.3.5)
46
+ tins (1.5.1)
47
+ tzinfo (1.2.2)
48
+ thread_safe (~> 0.1)
49
+ yard (0.8.7.6)
43
50
 
44
51
  PLATFORMS
45
52
  ruby
@@ -48,9 +55,8 @@ DEPENDENCIES
48
55
  activesupport (>= 3.1)
49
56
  bacon
50
57
  bundler (~> 1.3)
51
- claide
58
+ claide (~> 0.8)
52
59
  clintegracon!
53
60
  inch
54
- mocha (~> 1.0.0)
55
61
  mocha-on-bacon
56
- rake (~> 10.1.0)
62
+ rake
data/Rakefile CHANGED
@@ -39,6 +39,11 @@ begin
39
39
  ].join " | "
40
40
  end
41
41
 
42
+ desc 'Approve the bacon integration execution output as acceptable'
43
+ task :rebuild_bacon_integration do
44
+ `bundle exec rake spec:bacon_integration_runner > spec/bacon/execution_output.txt`
45
+ end
46
+
42
47
  desc 'Run all integration specs'
43
48
  task :integration => [
44
49
  'spec:bacon_integration'
data/clintegracon.gemspec CHANGED
@@ -23,11 +23,10 @@ Gem::Specification.new do |spec|
23
23
  spec.require_paths = ["lib"]
24
24
 
25
25
  spec.add_development_dependency "bundler", "~> 1.3"
26
- spec.add_development_dependency "rake", '~> 10.1.0' # Ruby 1.8.7
26
+ spec.add_development_dependency "rake"
27
27
  spec.add_development_dependency "bacon"
28
- spec.add_development_dependency "mocha", "~> 1.0.0" # Ruby 1.8.7
29
28
  spec.add_development_dependency "mocha-on-bacon"
30
- spec.add_development_dependency "claide" # Example CLI
29
+ spec.add_development_dependency "claide", "~> 0.8" # Example CLI
31
30
  spec.add_development_dependency "inch"
32
31
  spec.add_development_dependency 'activesupport', '>= 3.1'
33
32
 
@@ -48,11 +48,11 @@ module CLIntegracon::Adapter::Bacon
48
48
 
49
49
  # Works like `behaves_like`, but takes arguments for the shared example
50
50
  #
51
- # @param [String] name
52
- # name of the shared context.
51
+ # @param [String] name
52
+ # name of the shared context.
53
53
  #
54
- # @param [...] args
55
- # params to pass to the shared context
54
+ # @param [...] args
55
+ # params to pass to the shared context
56
56
  #
57
57
  def behaves_like_a(name, *args)
58
58
  instance_exec(*args, &Bacon::Shared[name])
@@ -69,17 +69,26 @@ module CLIntegracon::Adapter::Bacon
69
69
  # @param [String] spec_dir
70
70
  # the concrete directory of the spec, see {file_spec}.
71
71
  #
72
- # @param [String] args
73
- # the additional arguments to pass on launch to {CLIntegracon::Subject}.
72
+ # @param [String] head_args
73
+ # the arguments to pass before the +default_args+ on launch to {CLIntegracon::Subject}.
74
+ #
75
+ # @param [String] tail_args
76
+ # the arguments to pass after the +default_args+ on launch to {CLIntegracon::Subject}.
77
+ #
78
+ # @param [String] based_on
79
+ # Allows to specify an optional base spec, whose after directory will be used
80
+ # as before directory. You have to ensure that the specs are defined in order,
81
+ # so that the base spec was executed before.
74
82
  #
75
83
  # @return [String]
76
84
  # name of the set of shared expectations
77
85
  #
78
- def cli_spec(spec_dir, *args)
79
- file_spec spec_dir do
80
- output = subject.launch(*args)
86
+ def cli_spec(spec_dir, head_args=nil, tail_args=nil, based_on: nil)
87
+ file_spec(spec_dir, based_on: based_on) do
88
+ output = subject.launch(head_args, tail_args)
81
89
  status = $?
82
90
 
91
+ args = [head_args, tail_args].compact
83
92
  it "$ #{subject.name} #{args.join(' ')}" do
84
93
  status.should.satisfy("Binary failed\n\n#{output}") do
85
94
  status.success?
@@ -102,6 +111,10 @@ module CLIntegracon::Adapter::Bacon
102
111
  # the concrete directory of the spec to be passed to
103
112
  # {FileTreeSpecContext.spec}
104
113
  #
114
+ # @param [String] based_on
115
+ # Allows to specify an optional base spec, whose after directory will be used
116
+ # as before directory.
117
+ #
105
118
  # @param [Block<() -> ()>] block
106
119
  # the block which will be executed after the before state is laid out in the
107
120
  # temporary directory, which normally will make modifications to file system,
@@ -110,13 +123,13 @@ module CLIntegracon::Adapter::Bacon
110
123
  # @return [String]
111
124
  # name of the set of shared expectations
112
125
  #
113
- def file_spec(spec_dir, &block)
126
+ def file_spec(spec_dir, based_on: nil, &block)
114
127
  raise ArgumentError.new("Spec directory is missing!") if spec_dir.nil?
115
128
 
116
129
  shared_name = spec_dir
117
130
 
118
131
  shared shared_name do
119
- file_tree_spec_context.spec(spec_dir).run do |spec|
132
+ file_tree_spec_context.spec(spec_dir, based_on: based_on).run do |spec|
120
133
  instance_eval &block
121
134
 
122
135
  formatter = spec.formatter.lazy
@@ -20,45 +20,45 @@ module CLIntegracon
20
20
 
21
21
  # @return [Proc<(Pathname)->(to_s)>]
22
22
  # the proc, which transforms the files in a better comparable form
23
- attr_accessor :preparator
23
+ attr_accessor :preprocessor
24
24
 
25
25
  # Init a new diff
26
26
  #
27
- # @param [Pathname] expected
28
- # the expected file
27
+ # @param [Pathname] expected
28
+ # the expected file
29
29
  #
30
- # @param [Pathname] produced
31
- # the produced file
30
+ # @param [Pathname] produced
31
+ # the produced file
32
32
  #
33
- # @param [Pathname] relative_path
34
- # the relative path to the expected file
33
+ # @param [Pathname] relative_path
34
+ # the relative path to the expected file
35
35
  #
36
- # @param [Block<(Pathname)->(to_s)>] preparator
37
- # the block, which transforms the files in a better comparable form
36
+ # @param [Block<(Pathname)->(to_s)>] preprocessor
37
+ # the block, which preprocess the files in a better comparable form
38
38
  #
39
- def initialize(expected, produced, relative_path=nil, &preparator)
39
+ def initialize(expected, produced, relative_path=nil, &preprocessor)
40
40
  @expected = expected
41
41
  @produced = produced
42
42
  @relative_path = relative_path
43
- preparator ||= Proc.new { |x| x } #id
44
- self.preparator = preparator
43
+ preprocessor ||= Proc.new { |x| x } #id
44
+ self.preprocessor = preprocessor
45
45
  end
46
46
 
47
- def prepared_expected
48
- @prepared_expected ||= preparator.call(expected)
47
+ def preprocessed_expected
48
+ @preprocessed_expected ||= preprocessor.call(expected)
49
49
  end
50
50
 
51
- def prepared_produced
52
- @prepared_produced ||= preparator.call(produced)
51
+ def preprocessed_produced
52
+ @preprocessed_produced ||= preprocessor.call(produced)
53
53
  end
54
54
 
55
- # Check if the prepared inputs are files or need to be dumped first to
55
+ # Check if the preprocessed inputs are files or need to be dumped first to
56
56
  # temporary files to be compared.
57
57
  #
58
58
  # @return [Bool]
59
59
  #
60
60
  def compares_files?
61
- prepared_expected.is_a? Pathname
61
+ preprocessed_expected.is_a? Pathname
62
62
  end
63
63
 
64
64
  # Check if the produced output equals the expected
@@ -68,9 +68,9 @@ module CLIntegracon
68
68
  #
69
69
  def is_equal?
70
70
  @is_equal ||= if compares_files?
71
- FileUtils.compare_file(prepared_expected, prepared_produced)
71
+ FileUtils.compare_file(preprocessed_expected, preprocessed_produced)
72
72
  else
73
- prepared_expected == prepared_produced
73
+ preprocessed_expected == preprocessed_produced
74
74
  end
75
75
  end
76
76
 
@@ -86,7 +86,7 @@ module CLIntegracon
86
86
  :source => compares_files? ? 'files' : 'strings',
87
87
  :context => 3
88
88
  }.merge options
89
- Diffy::Diff.new(prepared_expected.to_s, prepared_produced.to_s, options).each &block
89
+ Diffy::Diff.new(preprocessed_expected.to_s, preprocessed_produced.to_s, options).each &block
90
90
  end
91
91
 
92
92
  end
@@ -3,6 +3,14 @@ require 'CLIntegracon/diff'
3
3
  require 'CLIntegracon/formatter'
4
4
 
5
5
  module CLIntegracon
6
+ # FileTreeSpec represents a single specification, which is mirrored
7
+ # on the file system in the spec directory by a direct children.
8
+ # It contains a before directory (#before_path) and an after
9
+ # directory (#after_path) or if it is initialized with a #base_spec,
10
+ # the before directory of this spec is used. The before directory
11
+ # contents in the #spec_path of the child spec, can contain further
12
+ # files, which overwrite, if given, the inherited contents.
13
+ #
6
14
  class FileTreeSpec
7
15
 
8
16
  # @return [FileTreeSpecContext]
@@ -37,26 +45,49 @@ module CLIntegracon
37
45
  context.temp_path + spec_folder
38
46
  end
39
47
 
48
+ # @return [String|NilClass]
49
+ # The name of an optional #base_spec.
50
+ attr_reader :base_spec_name
51
+
52
+ # Return whether this spec is based on another spec.
53
+ #
54
+ # @return [Bool]
55
+ #
56
+ def has_base?
57
+ !base_spec_name.nil?
58
+ end
59
+
60
+ # @return [FileTreeSpec|NilClass]
61
+ # The spec on whose #after_path will be used as #before_path
62
+ # for this spec.
63
+ def base_spec
64
+ has_base? ? context.spec(base_spec_name) : nil
65
+ end
66
+
40
67
  # Init a spec with a given context
41
68
  #
42
- # @param [FileTreeSpecContext] context
43
- # The context, which configures path and file behaviors
69
+ # @param [FileTreeSpecContext] context
70
+ # The context, which configures path and file behaviors
44
71
  #
45
- # @param [String] spec_folder
46
- # The concrete spec folder
72
+ # @param [String] spec_folder
73
+ # The concrete spec folder
47
74
  #
48
- def initialize(context, spec_folder)
75
+ # @param [String] based_on
76
+ # @see #base_spec_name
77
+ #
78
+ def initialize(context, spec_folder, based_on: nil)
49
79
  @context = context
50
80
  @spec_folder = spec_folder
81
+ @base_spec_name = based_on
51
82
  end
52
83
 
53
84
  # Run this spec
54
85
  #
55
- # @param [Block<(FileTreeSpec)->()>] block
56
- # The block, which will be executed after chdir into the created temporary
57
- # directory. In this block you will likely run your modifications to the
58
- # file system and use the received FileTreeSpec instance to make asserts
59
- # with the test framework of your choice.
86
+ # @param [Block<(FileTreeSpec)->()>] block
87
+ # The block, which will be executed after chdir into the created temporary
88
+ # directory. In this block you will likely run your modifications to the
89
+ # file system and use the received FileTreeSpec instance to make asserts
90
+ # with the test framework of your choice.
60
91
  #
61
92
  def run(&block)
62
93
  prepare!
@@ -71,9 +102,9 @@ module CLIntegracon
71
102
  # Compares the expected and produced directory by using the rules
72
103
  # defined in the context
73
104
  #
74
- # @param [Block<(Diff)->()>] diff_block
75
- # The block, where you will likely define a test for each file to compare.
76
- # It will receive a Diff of each of the expected and produced files.
105
+ # @param [Block<(Diff)->()>] diff_block
106
+ # The block, where you will likely define a test for each file to compare.
107
+ # It will receive a Diff of each of the expected and produced files.
77
108
  #
78
109
  def compare(&diff_block)
79
110
  transform_paths!
@@ -82,12 +113,10 @@ module CLIntegracon
82
113
  expected = after_path + relative_path
83
114
 
84
115
  next unless expected.file?
116
+ next if context.ignores?(relative_path)
85
117
 
86
- block = special_behavior_for_path relative_path
87
- next if block == context.class.nop
88
-
89
- diff = diff_files(expected, relative_path)
90
- diff.preparator = block unless block.nil?
118
+ block = context.preprocessors_for(relative_path).first
119
+ diff = diff_files(expected, relative_path, &block)
91
120
 
92
121
  diff_block.call diff
93
122
  end
@@ -100,9 +129,9 @@ module CLIntegracon
100
129
  # test case for each file, which wasn't expected at all. So you can
101
130
  # keep your test cases consistent.
102
131
  #
103
- # @param [Block<(Array)->()>] diff_block
104
- # The block, where you will likely define a test that no unexpected files exists.
105
- # It will receive an Array.
132
+ # @param [Block<(Array)->()>] diff_block
133
+ # The block, where you will likely define a test that no unexpected files exists.
134
+ # It will receive an Array.
106
135
  #
107
136
  def check_unexpected_files(&block)
108
137
  expected_files = glob_all after_path
@@ -110,10 +139,10 @@ module CLIntegracon
110
139
  unexpected_files = produced_files - expected_files
111
140
 
112
141
  # Select only files
113
- unexpected_files.reject! { |path| !path.file? }
142
+ unexpected_files.select! { |path| path.file? }
114
143
 
115
144
  # Filter ignored paths
116
- unexpected_files.reject! { |path| special_behavior_for_path(path) == context.class.nop }
145
+ unexpected_files.reject! { |path| context.ignores?(path) }
117
146
 
118
147
  block.call unexpected_files
119
148
  end
@@ -141,18 +170,25 @@ module CLIntegracon
141
170
  # directory.
142
171
  #
143
172
  def copy_files!
144
- source = before_path
145
173
  destination = temp_path
146
- FileUtils.cp_r("#{source}/.", destination)
174
+
175
+ if has_base?
176
+ FileUtils.cp_r("#{base_spec.after_path}/.", destination)
177
+ end
178
+
179
+ begin
180
+ FileUtils.cp_r("#{before_path}/.", destination)
181
+ rescue Errno::ENOENT => e
182
+ raise e unless has_base?
183
+ end
147
184
  end
148
185
 
149
186
  # Applies the in the context configured transformations.
150
187
  #
151
188
  def transform_paths!
152
- context.transform_paths.each do |path, block|
153
- Dir.glob(path) do |produced_path|
154
- produced = Pathname(produced_path)
155
- block.call(produced)
189
+ glob_all.each do |path|
190
+ context.transformers_for(path).each do |transformer|
191
+ transformer.call(path)
156
192
  end
157
193
  end
158
194
  end
@@ -160,53 +196,37 @@ module CLIntegracon
160
196
  # Searches recursively for all files and take care for including hidden files
161
197
  # if this is configured in the context.
162
198
  #
163
- # @param [String] path
164
- # The relative or absolute path to search in (optional)
199
+ # @param [String] path
200
+ # The relative or absolute path to search in (optional)
165
201
  #
166
202
  # @return [Array<Pathname>]
167
203
  #
168
204
  def glob_all(path=nil)
169
205
  Dir.chdir path || '.' do
170
- Dir.glob("**/*", context.include_hidden_files? ? File::FNM_DOTMATCH : 0).sort.map { |path|
171
- Pathname(path)
172
- }
173
- end
174
- end
175
-
176
- # Find the special behavior for a given path
177
- #
178
- # @return [Block<(Pathname) -> to_s>]
179
- # This block takes the Pathname and transforms the file in a better comparable
180
- # state. If it returns nil, the file is ignored.
181
- #
182
- def special_behavior_for_path(path)
183
- context.special_paths.each do |key, block|
184
- matched = if key.is_a?(Regexp)
185
- path.to_s.match(key)
186
- else
187
- File.fnmatch(key, path)
206
+ Dir.glob("**/*", context.include_hidden_files? ? File::FNM_DOTMATCH : 0).sort.map do |p|
207
+ Pathname(p)
188
208
  end
189
- next unless matched
190
- return block
191
209
  end
192
- return nil
193
210
  end
194
211
 
195
212
  # Compares two files to check if they are identical and produces a clear diff
196
213
  # to highlight the differences.
197
214
  #
198
- # @param [Pathname] expected
199
- # The file in the after directory
215
+ # @param [Pathname] expected
216
+ # The file in the after directory
217
+ #
218
+ # @param [Pathname] relative_path
219
+ # The file in the temp directory
200
220
  #
201
- # @param [Pathname] relative_path
202
- # The file in the temp directory
221
+ # @param [Block<(Pathname)->(to_s)>] block
222
+ # the block, which transforms the files in a better comparable form
203
223
  #
204
224
  # @return [Diff]
205
225
  # An object holding a diff
206
226
  #
207
- def diff_files(expected, relative_path)
227
+ def diff_files(expected, relative_path, &block)
208
228
  produced = temp_path + relative_path
209
- Diff.new(expected, produced, relative_path)
229
+ Diff.new(expected, produced, relative_path, &block)
210
230
  end
211
231
 
212
232
  end
@@ -29,13 +29,17 @@ module CLIntegracon
29
29
  #
30
30
  attr_accessor :temp_path
31
31
 
32
- # @return [Hash<String,Block>]
33
- # the special paths of files, which need to be transformed in a better comparable form
32
+ # @return [Hash<String|Regexp,Block>]
33
+ # the paths of files, which need to be transformed in a better comparable form
34
34
  attr_accessor :transform_paths
35
35
 
36
- # @return [Hash<String,Block>]
37
- # the special paths of files, where an individual file diff handling is needed
38
- attr_accessor :special_paths
36
+ # @return [Hash<String|Regexp,Block>]
37
+ # the paths of files, where an individual file diff handling is needed
38
+ attr_accessor :preprocess_paths
39
+
40
+ # @return [Array<String|Regexp>]
41
+ # the paths of files to exclude from comparison
42
+ attr_accessor :ignore_paths
39
43
 
40
44
  # @return [Bool]
41
45
  # whether to include hidden files, when searching directories (true by default)
@@ -49,12 +53,12 @@ module CLIntegracon
49
53
 
50
54
  # "Designated" initializer
51
55
  #
52
- # @param [Hash<Symbol,String>] properties
53
- # The configuration parameter (optional):
54
- # :spec_path => see self.spec_path
55
- # :before_dir => see self.before_dir
56
- # :after_dir => see self.after_dir
57
- # :temp_path => see self.temp_path
56
+ # @param [Hash<Symbol,String>] properties
57
+ # The configuration parameter (optional):
58
+ # :spec_path => see self.spec_path
59
+ # :before_dir => see self.before_dir
60
+ # :after_dir => see self.after_dir
61
+ # :temp_path => see self.temp_path
58
62
  #
59
63
  def initialize(properties={})
60
64
  self.spec_path = properties[:spec_path] || '.'
@@ -62,24 +66,12 @@ module CLIntegracon
62
66
  self.before_dir = properties[:before_dir] || 'before'
63
67
  self.after_dir = properties[:after_dir] || 'after'
64
68
  self.transform_paths = {}
65
- self.special_paths = {}
69
+ self.preprocess_paths = {}
70
+ self.ignore_paths = []
66
71
  self.include_hidden_files = true
67
72
  end
68
73
 
69
74
 
70
- #-----------------------------------------------------------------------------#
71
-
72
- # @!group Helper
73
-
74
- # This value is used for ignored paths
75
- #
76
- # @return [Proc]
77
- # Does nothing
78
- def self.nop
79
- @nop ||= Proc.new {}
80
- end
81
-
82
-
83
75
  #-----------------------------------------------------------------------------#
84
76
 
85
77
  # @!group Setter
@@ -109,11 +101,12 @@ module CLIntegracon
109
101
 
110
102
  # @!group DSL-like Setter
111
103
 
112
- # Registers a block for special handling certain files, matched with globs.
104
+ # Registers a block to transform certain files, matched with globs or
105
+ # regular expressions.
113
106
  # Multiple transformers can match a single file.
114
107
  #
115
108
  # @param [String...] file_paths
116
- # The file path(s) of the files, which were created/changed and need transformation
109
+ # The path(s), which need to be transformed in a better comparable form
117
110
  #
118
111
  # @param [Block<(Pathname) -> ()>] block
119
112
  # The block, which takes each of the matched files, transforms it if needed
@@ -127,31 +120,70 @@ module CLIntegracon
127
120
  end
128
121
  end
129
122
 
130
- # Registers a block for special handling certain files, matched with globs.
123
+ # Registers a block to preprocess certain files, matched with globs or
124
+ # regular expressions.
131
125
  # Registered file paths will be excluded from default comparison by `diff`.
132
- # Multiple special handlers can match a single file.
126
+ # A file is preprocessed with the first matching preprocessor.
133
127
  #
134
128
  # @param [String|Regexp...] file_paths
135
- # The file path(s) of the files, which were created/changed and need special comparison
129
+ # The path(s)s, where an individual file diff handling is needed
136
130
  #
137
131
  # @param [Block<(Pathname) -> (String)>] block
138
132
  # The block, which takes each of the matched files, transforms it if needed
139
133
  # in a better comparable form.
140
134
  #
141
- def has_special_handling_for(*file_paths, &block)
135
+ def preprocess(*file_paths, &block)
142
136
  file_paths.each do |file_path|
143
- self.special_paths[file_path] = block
137
+ self.preprocess_paths[file_path] = block
144
138
  end
145
139
  end
146
140
 
147
141
  # Copies the before subdirectory of the given tests folder in the temporary
148
142
  # directory.
149
143
  #
150
- # @param [String|RegExp...] file_path
151
- # the file path of the files, which were changed and need special comparison
144
+ # @param [String|RegExp...] file_paths
145
+ # the file path(s) of the files to exclude from comparison
146
+ #
147
+ def ignores(*file_paths)
148
+ self.ignore_paths += file_paths
149
+ end
150
+
151
+
152
+ #-----------------------------------------------------------------------------#
153
+
154
+ # @!group Path accessors
155
+
156
+ # Returns a list of transformers to apply for a given file path.
157
+ #
158
+ # @param [Pathname] file_path
159
+ # The file path to match
160
+ #
161
+ # @return [Array<Block<(Pathname) -> ()>>]
162
+ #
163
+ def transformers_for(file_path)
164
+ select_matching_file_patterns(transform_paths, file_path).values
165
+ end
166
+
167
+ # Returns a list of preprocessors to apply for a given file path.
168
+ #
169
+ # @param [Pathname] file_path
170
+ # The file path to match
171
+ #
172
+ # @return [Array<Block<(Pathname) -> (String)>>]
173
+ #
174
+ def preprocessors_for(file_path)
175
+ select_matching_file_patterns(preprocess_paths, file_path).values
176
+ end
177
+
178
+ # Checks whether a given file path is to ignore.
179
+ #
180
+ # @param [Pathname] file_path
181
+ # The file path to match
182
+ #
183
+ # @return [Bool]
152
184
  #
153
- def ignores(*file_path)
154
- has_special_handling_for *file_path, &self.class.nop
185
+ def ignores?(file_path)
186
+ !select_matching_file_patterns(ignore_paths, file_path).empty?
155
187
  end
156
188
 
157
189
 
@@ -168,13 +200,42 @@ module CLIntegracon
168
200
 
169
201
  # Get a specific spec with given folder to run it
170
202
  #
171
- # @param [String] folder
172
- # The name of the folder of the tests
203
+ # @param [String] folder
204
+ # The name of the folder of the tests
205
+ #
206
+ # @param [String] based_on
207
+ # @see FileTreeSpec#base_spec_name
173
208
  #
174
209
  # @return [FileTreeSpec]
175
210
  #
176
- def spec(spec_folder)
177
- FileTreeSpec.new(self, spec_folder)
211
+ def spec(spec_folder, based_on: nil)
212
+ FileTreeSpec.new(self, spec_folder, based_on: based_on)
213
+ end
214
+
215
+ #-----------------------------------------------------------------------------#
216
+
217
+ private
218
+
219
+ # @!group Helpers
220
+
221
+ # Select elements in an enumerable which match the given path.
222
+ #
223
+ # @param [Enumerable<String|RegExp>] patterns
224
+ # The patterns to check
225
+ #
226
+ # @param [Pathname] path
227
+ # The file to match
228
+ #
229
+ # @return [Enumerable<String|RegExp>]
230
+ #
231
+ def select_matching_file_patterns(patterns, path)
232
+ patterns.select do |pattern|
233
+ if pattern.is_a?(Regexp)
234
+ path.to_s.match(pattern)
235
+ else
236
+ File.fnmatch(pattern, path)
237
+ end
238
+ end
178
239
  end
179
240
 
180
241
  end
@@ -42,11 +42,11 @@ module CLIntegracon
42
42
 
43
43
  # "Designated" initializer
44
44
  #
45
- # @param [String] name
46
- # The name of the binary
45
+ # @param [String] name
46
+ # The name of the binary
47
47
  #
48
- # @param [String] executable
49
- # The executable subject statement (optional)
48
+ # @param [String] executable
49
+ # The executable subject statement (optional)
50
50
  #
51
51
  def initialize(name='subject', executable=nil)
52
52
  self.name = name
@@ -65,11 +65,11 @@ module CLIntegracon
65
65
  # Define a pattern, whose occurrences in the output should be replaced by a
66
66
  # given placeholder.
67
67
  #
68
- # @param [Regexp|String] pattern
69
- # The pattern
68
+ # @param [Regexp|String] pattern
69
+ # The pattern
70
70
  #
71
- # @param [String] replacement
72
- # The replacement
71
+ # @param [String] replacement
72
+ # The replacement
73
73
  #
74
74
  def replace_pattern(pattern, replacement)
75
75
  self.replace_patterns[replacement] = pattern
@@ -78,11 +78,11 @@ module CLIntegracon
78
78
  # Define a path, whose occurrences in the output should be replaced by
79
79
  # either its basename or a given placeholder.
80
80
  #
81
- # @param [String] path
82
- # The path
81
+ # @param [String] path
82
+ # The path
83
83
  #
84
- # @param [String] name
85
- # The name of the path, or the basename of the given path
84
+ # @param [String] name
85
+ # The name of the path, or the basename of the given path
86
86
  #
87
87
  def replace_path(path, name=nil)
88
88
  name ||= File.basename path
@@ -92,11 +92,11 @@ module CLIntegracon
92
92
  # Define a path in the user directory, whose occurrences in the output
93
93
  # should be replaced by either its basename or a given placeholder.
94
94
  #
95
- # @param [String] path
96
- # The path
95
+ # @param [String] path
96
+ # The path
97
97
  #
98
- # @param [String] name
99
- # The name of the path, or the given path
98
+ # @param [String] name
99
+ # The name of the path, or the given path
100
100
  #
101
101
  def replace_user_path(path, name=nil)
102
102
  name ||= "$HOME/#{path}"
@@ -1,3 +1,3 @@
1
1
  module CLIntegracon
2
- VERSION = "0.6.1"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -4,9 +4,12 @@ CLIntegracon::Adapter::Bacon
4
4
  without milk
5
5
  - $ coffee-maker --no-milk
6
6
  - BlackEye.brewed-coffee
7
+ - BlackEye.brewed-coffee.decanted
7
8
  - CaPheSuaDa.brewed-coffee [FAILED]
9
+ - CaPheSuaDa.brewed-coffee.decanted
8
10
  - Coffeemakerfile.yml
9
11
  - RedTux.brewed-coffee
12
+ - RedTux.brewed-coffee.decanted
10
13
  - execution_output.txt
11
14
  - should not produce unexpected files [FAILED]
12
15
  with honey as sweetner
@@ -16,6 +19,17 @@ CLIntegracon::Adapter::Bacon
16
19
  - Coffeemakerfile.yml
17
20
  - RedTux.brewed-coffee [FAILED]
18
21
  - execution_output.txt
22
+ - should not produce unexpected files [FAILED]
23
+ without milk and honey as sweetner
24
+ - $ coffee-maker --no-milk --sweetner=honey
25
+ - Affogato.brewed-coffee
26
+ - Affogato.brewed-coffee.decanted
27
+ - BlackEye.brewed-coffee
28
+ - BlackEye.brewed-coffee.decanted
29
+ - Coffeemakerfile.yml
30
+ - RedTux.brewed-coffee
31
+ - RedTux.brewed-coffee.decanted
32
+ - execution_output.txt
19
33
  - should not produce unexpected files
20
34
  Get help
21
35
  - $ coffee-maker --help
@@ -28,17 +42,18 @@ Bacon::Error: File comparison error `CaPheSuaDa.brewed-coffee` for coffeemaker_n
28
42
  - @origin = "Việt Nam"
29
43
  --- END ------------------------------------------------------------------------
30
44
 
31
- spec/bacon/spec_helper.rb:45
32
- spec/bacon/spec_helper.rb:44
33
- spec/bacon/spec_helper.rb:42
45
+ spec/bacon/spec_helper.rb:49
46
+ spec/bacon/spec_helper.rb:48
47
+ spec/bacon/spec_helper.rb:46
34
48
  spec/bacon/spec_helper.rb:17
35
49
  spec/bacon/spec_helper.rb:15
36
50
 
37
51
  Bacon::Error: Unexpected files for coffeemaker_no_milk:
38
52
  * Affogato.brewed-coffee
39
- spec/bacon/spec_helper.rb:45
40
- spec/bacon/spec_helper.rb:44
41
- spec/bacon/spec_helper.rb:42
53
+ * Affogato.brewed-coffee.decanted
54
+ spec/bacon/spec_helper.rb:49
55
+ spec/bacon/spec_helper.rb:48
56
+ spec/bacon/spec_helper.rb:46
42
57
  spec/bacon/spec_helper.rb:17
43
58
  spec/bacon/spec_helper.rb:15
44
59
 
@@ -49,17 +64,17 @@ Bacon::Error: File comparison error `Affogato.brewed-coffee` for coffeemaker_swe
49
64
  @sweetner = honey
50
65
  --- END ------------------------------------------------------------------------
51
66
 
52
- spec/bacon/spec_helper.rb:49
53
- spec/bacon/spec_helper.rb:48
54
- spec/bacon/spec_helper.rb:42
67
+ spec/bacon/spec_helper.rb:53
68
+ spec/bacon/spec_helper.rb:52
69
+ spec/bacon/spec_helper.rb:46
55
70
  spec/bacon/spec_helper.rb:17
56
71
  spec/bacon/spec_helper.rb:15
57
72
 
58
73
  Bacon::Error: Missing file for coffeemaker_sweetner_honey:
59
74
  * BlackEye.brewed-coffee
60
- spec/bacon/spec_helper.rb:49
61
- spec/bacon/spec_helper.rb:48
62
- spec/bacon/spec_helper.rb:42
75
+ spec/bacon/spec_helper.rb:53
76
+ spec/bacon/spec_helper.rb:52
77
+ spec/bacon/spec_helper.rb:46
63
78
  spec/bacon/spec_helper.rb:17
64
79
  spec/bacon/spec_helper.rb:15
65
80
 
@@ -71,10 +86,19 @@ Bacon::Error: File comparison error `RedTux.brewed-coffee` for coffeemaker_sweet
71
86
  + @sweetner = honey
72
87
  --- END ------------------------------------------------------------------------
73
88
 
74
- spec/bacon/spec_helper.rb:49
75
- spec/bacon/spec_helper.rb:48
76
- spec/bacon/spec_helper.rb:42
89
+ spec/bacon/spec_helper.rb:53
90
+ spec/bacon/spec_helper.rb:52
91
+ spec/bacon/spec_helper.rb:46
92
+ spec/bacon/spec_helper.rb:17
93
+ spec/bacon/spec_helper.rb:15
94
+
95
+ Bacon::Error: Unexpected files for coffeemaker_sweetner_honey:
96
+ * Affogato.brewed-coffee.decanted
97
+ * RedTux.brewed-coffee.decanted
98
+ spec/bacon/spec_helper.rb:53
99
+ spec/bacon/spec_helper.rb:52
100
+ spec/bacon/spec_helper.rb:46
77
101
  spec/bacon/spec_helper.rb:17
78
102
  spec/bacon/spec_helper.rb:15
79
103
 
80
- 17 specifications (27 requirements), 5 failures, 0 errors
104
+ 30 specifications (51 requirements), 6 failures, 0 errors
@@ -34,7 +34,11 @@ describe CLIntegracon::Adapter::Bacon do
34
34
  c.ignores '.DS_Store'
35
35
  c.ignores '.gitkeep'
36
36
 
37
- c.has_special_handling_for 'CaPheSuaDa.brewed-coffee' do |path|
37
+ c.transform_produced /\.brewed-coffee/ do |path|
38
+ FileUtils.touch("#{path}.decanted")
39
+ end
40
+
41
+ c.preprocess 'CaPheSuaDa.brewed-coffee' do |path|
38
42
  File.read(path)
39
43
  end
40
44
  end
@@ -49,6 +53,11 @@ describe CLIntegracon::Adapter::Bacon do
49
53
  behaves_like cli_spec('coffeemaker_sweetner_honey', '--sweetner=honey')
50
54
  end
51
55
 
56
+ describe 'without milk and honey as sweetner' do
57
+ behaves_like cli_spec('coffeemaker_no_milk_sweetner_honey', '--no-milk --sweetner=honey',
58
+ based_on: 'coffeemaker_sweetner_honey')
59
+ end
60
+
52
61
  end
53
62
 
54
63
  describe 'Get help' do
@@ -9,7 +9,6 @@ Options:
9
9
 
10
10
  --no-milk Don’t add milk
11
11
  --sweetner=[sugar|honey] Use one of the available sweetners
12
- --completion-script Print the auto-completion script
13
12
  --version Show the version of the tool
14
13
  --verbose Show more debugging information
15
14
  --no-ansi Show output without ANSI codes
@@ -0,0 +1,2 @@
1
+ class Affogato < BrewedCoffee
2
+ @sweetner = honey
@@ -0,0 +1,2 @@
1
+ class BlackEye < BrewedCoffee
2
+ @sweetner = honey
@@ -0,0 +1,2 @@
1
+ class RedTux < BrewedCoffee
2
+ @sweetner = sugar
@@ -0,0 +1,3 @@
1
+ COFFEE_MAKER_FILE=Coffeemakerfile.yml PROJECT_DIR=ROOT bundle exec ruby ROOT/spec/fixtures/bin/coffeemaker.rb --no-milk --sweetner=honey --verbose --no-ansi 2>&1
2
+ * Brewing BlackEye
3
+ * Enjoy!
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clintegracon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marius Rackwitz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-02 00:00:00.000000000 Z
11
+ date: 2015-05-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 10.1.0
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 10.1.0
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bacon
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: mocha
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 1.0.0
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 1.0.0
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: mocha-on-bacon
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -84,16 +70,16 @@ dependencies:
84
70
  name: claide
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
- - - ">="
73
+ - - "~>"
88
74
  - !ruby/object:Gem::Version
89
- version: '0'
75
+ version: '0.8'
90
76
  type: :development
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
94
- - - ">="
80
+ - - "~>"
95
81
  - !ruby/object:Gem::Version
96
- version: '0'
82
+ version: '0.8'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: inch
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -182,11 +168,23 @@ files:
182
168
  - spec/integration/coffeemaker_help/after/execution_output.txt
183
169
  - spec/integration/coffeemaker_help/before/.gitkeep
184
170
  - spec/integration/coffeemaker_no_milk/after/BlackEye.brewed-coffee
171
+ - spec/integration/coffeemaker_no_milk/after/BlackEye.brewed-coffee.decanted
185
172
  - spec/integration/coffeemaker_no_milk/after/CaPheSuaDa.brewed-coffee
173
+ - spec/integration/coffeemaker_no_milk/after/CaPheSuaDa.brewed-coffee.decanted
186
174
  - spec/integration/coffeemaker_no_milk/after/Coffeemakerfile.yml
187
175
  - spec/integration/coffeemaker_no_milk/after/RedTux.brewed-coffee
176
+ - spec/integration/coffeemaker_no_milk/after/RedTux.brewed-coffee.decanted
188
177
  - spec/integration/coffeemaker_no_milk/after/execution_output.txt
189
178
  - spec/integration/coffeemaker_no_milk/before/Coffeemakerfile.yml
179
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/Affogato.brewed-coffee
180
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/Affogato.brewed-coffee.decanted
181
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/BlackEye.brewed-coffee
182
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/BlackEye.brewed-coffee.decanted
183
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/Coffeemakerfile.yml
184
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/RedTux.brewed-coffee
185
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/RedTux.brewed-coffee.decanted
186
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/execution_output.txt
187
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/before/Coffeemakerfile.yml
190
188
  - spec/integration/coffeemaker_sweetner_honey/after/Affogato.brewed-coffee
191
189
  - spec/integration/coffeemaker_sweetner_honey/after/BlackEye.brewed-coffee
192
190
  - spec/integration/coffeemaker_sweetner_honey/after/Coffeemakerfile.yml
@@ -229,11 +227,23 @@ test_files:
229
227
  - spec/integration/coffeemaker_help/after/execution_output.txt
230
228
  - spec/integration/coffeemaker_help/before/.gitkeep
231
229
  - spec/integration/coffeemaker_no_milk/after/BlackEye.brewed-coffee
230
+ - spec/integration/coffeemaker_no_milk/after/BlackEye.brewed-coffee.decanted
232
231
  - spec/integration/coffeemaker_no_milk/after/CaPheSuaDa.brewed-coffee
232
+ - spec/integration/coffeemaker_no_milk/after/CaPheSuaDa.brewed-coffee.decanted
233
233
  - spec/integration/coffeemaker_no_milk/after/Coffeemakerfile.yml
234
234
  - spec/integration/coffeemaker_no_milk/after/RedTux.brewed-coffee
235
+ - spec/integration/coffeemaker_no_milk/after/RedTux.brewed-coffee.decanted
235
236
  - spec/integration/coffeemaker_no_milk/after/execution_output.txt
236
237
  - spec/integration/coffeemaker_no_milk/before/Coffeemakerfile.yml
238
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/Affogato.brewed-coffee
239
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/Affogato.brewed-coffee.decanted
240
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/BlackEye.brewed-coffee
241
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/BlackEye.brewed-coffee.decanted
242
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/Coffeemakerfile.yml
243
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/RedTux.brewed-coffee
244
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/RedTux.brewed-coffee.decanted
245
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/after/execution_output.txt
246
+ - spec/integration/coffeemaker_no_milk_sweetner_honey/before/Coffeemakerfile.yml
237
247
  - spec/integration/coffeemaker_sweetner_honey/after/Affogato.brewed-coffee
238
248
  - spec/integration/coffeemaker_sweetner_honey/after/BlackEye.brewed-coffee
239
249
  - spec/integration/coffeemaker_sweetner_honey/after/Coffeemakerfile.yml