cuke_linter 0.13.0 → 1.0.0

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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -1
  3. data/README.md +4 -4
  4. data/cuke_linter.gemspec +3 -3
  5. data/lib/cuke_linter.rb +5 -3
  6. data/lib/cuke_linter/version.rb +1 -1
  7. metadata +2 -86
  8. data/.gitignore +0 -19
  9. data/.simplecov +0 -8
  10. data/.travis.yml +0 -33
  11. data/CONTRIBUTING.md +0 -26
  12. data/Gemfile +0 -6
  13. data/Rakefile +0 -63
  14. data/appveyor.yml +0 -43
  15. data/bin/console +0 -14
  16. data/bin/setup +0 -8
  17. data/environments/common_env.rb +0 -12
  18. data/environments/cucumber_env.rb +0 -22
  19. data/environments/rspec_env.rb +0 -50
  20. data/testing/cucumber/step_definitions/action_steps.rb +0 -84
  21. data/testing/cucumber/step_definitions/setup_steps.rb +0 -258
  22. data/testing/cucumber/step_definitions/verification_steps.rb +0 -94
  23. data/testing/file_helper.rb +0 -41
  24. data/testing/formatter_factory.rb +0 -15
  25. data/testing/gemfiles/cuke_modeler1.gemfile +0 -8
  26. data/testing/gemfiles/cuke_modeler2.gemfile +0 -8
  27. data/testing/linter_factory.rb +0 -60
  28. data/testing/model_factory.rb +0 -109
  29. data/testing/rspec/spec/integration/cli_integration_spec.rb +0 -556
  30. data/testing/rspec/spec/integration/configuration_spec.rb +0 -811
  31. data/testing/rspec/spec/integration/cuke_linter_integration_spec.rb +0 -243
  32. data/testing/rspec/spec/integration/formatters/formatter_integration_specs.rb +0 -5
  33. data/testing/rspec/spec/integration/formatters/pretty_formatter_integration_spec.rb +0 -8
  34. data/testing/rspec/spec/integration/linters/background_does_more_than_setup_linter_integration_spec.rb +0 -8
  35. data/testing/rspec/spec/integration/linters/element_with_common_tags_linter_integration_spec.rb +0 -8
  36. data/testing/rspec/spec/integration/linters/element_with_duplicate_tags_linter_integration_spec.rb +0 -8
  37. data/testing/rspec/spec/integration/linters/element_with_too_many_tags_linter_integration_spec.rb +0 -8
  38. data/testing/rspec/spec/integration/linters/example_without_name_linter_integration_spec.rb +0 -8
  39. data/testing/rspec/spec/integration/linters/feature_file_with_invalid_name_integration_spec.rb +0 -8
  40. data/testing/rspec/spec/integration/linters/feature_file_with_mismatched_name_integration_spec.rb +0 -8
  41. data/testing/rspec/spec/integration/linters/feature_with_too_many_different_tags_linter_integration_spec.rb +0 -8
  42. data/testing/rspec/spec/integration/linters/feature_without_description_linter_integration_spec.rb +0 -8
  43. data/testing/rspec/spec/integration/linters/feature_without_name_linter_integration_spec.rb +0 -8
  44. data/testing/rspec/spec/integration/linters/feature_without_scenarios_linter_integration_spec.rb +0 -8
  45. data/testing/rspec/spec/integration/linters/linter_integration_spec.rb +0 -8
  46. data/testing/rspec/spec/integration/linters/linter_integration_specs.rb +0 -7
  47. data/testing/rspec/spec/integration/linters/outline_with_single_example_row_linter_integration_spec.rb +0 -8
  48. data/testing/rspec/spec/integration/linters/single_test_background_linter_integration_spec.rb +0 -8
  49. data/testing/rspec/spec/integration/linters/step_with_end_period_linter_integration_spec.rb +0 -8
  50. data/testing/rspec/spec/integration/linters/step_with_too_many_characters_linter_integration_spec.rb +0 -8
  51. data/testing/rspec/spec/integration/linters/test_should_use_background_linter_integration_spec.rb +0 -8
  52. data/testing/rspec/spec/integration/linters/test_with_action_step_as_final_step_linter_integration_spec.rb +0 -8
  53. data/testing/rspec/spec/integration/linters/test_with_bad_name_integration_spec.rb +0 -8
  54. data/testing/rspec/spec/integration/linters/test_with_no_action_step_integration_spec.rb +0 -8
  55. data/testing/rspec/spec/integration/linters/test_with_no_name_integration_spec.rb +0 -8
  56. data/testing/rspec/spec/integration/linters/test_with_no_verification_step_integration_spec.rb +0 -8
  57. data/testing/rspec/spec/integration/linters/test_with_setup_step_after_action_step_linter_integration_spec.rb +0 -8
  58. data/testing/rspec/spec/integration/linters/test_with_setup_step_after_verification_step_linter_integration_spec.rb +0 -8
  59. data/testing/rspec/spec/integration/linters/test_with_setup_step_as_final_step_linter_integration_spec.rb +0 -8
  60. data/testing/rspec/spec/integration/linters/test_with_too_many_steps_linter_integration_spec.rb +0 -8
  61. data/testing/rspec/spec/unit/cuke_linter_unit_spec.rb +0 -114
  62. data/testing/rspec/spec/unit/formatters/formatter_unit_specs.rb +0 -11
  63. data/testing/rspec/spec/unit/formatters/pretty_formatter_unit_spec.rb +0 -115
  64. data/testing/rspec/spec/unit/linters/background_does_more_than_setup_linter_unit_spec.rb +0 -186
  65. data/testing/rspec/spec/unit/linters/configurable_linter_unit_specs.rb +0 -11
  66. data/testing/rspec/spec/unit/linters/element_with_common_tags_linter_unit_spec.rb +0 -248
  67. data/testing/rspec/spec/unit/linters/element_with_duplicate_tags_linter_unit_spec.rb +0 -203
  68. data/testing/rspec/spec/unit/linters/element_with_too_many_tags_linter_unit_spec.rb +0 -296
  69. data/testing/rspec/spec/unit/linters/example_without_name_linter_unit_spec.rb +0 -81
  70. data/testing/rspec/spec/unit/linters/feature_file_with_invalid_name_linter_unit_spec.rb +0 -106
  71. data/testing/rspec/spec/unit/linters/feature_file_with_mismatched_name_linter_unit_spec.rb +0 -124
  72. data/testing/rspec/spec/unit/linters/feature_with_too_many_different_tags_linter_unit_spec.rb +0 -293
  73. data/testing/rspec/spec/unit/linters/feature_without_description_linter_unit_spec.rb +0 -80
  74. data/testing/rspec/spec/unit/linters/feature_without_name_linter_unit_spec.rb +0 -84
  75. data/testing/rspec/spec/unit/linters/feature_without_scenarios_linter_unit_spec.rb +0 -102
  76. data/testing/rspec/spec/unit/linters/linter_unit_spec.rb +0 -197
  77. data/testing/rspec/spec/unit/linters/linter_unit_specs.rb +0 -57
  78. data/testing/rspec/spec/unit/linters/outline_with_single_example_row_linter_unit_spec.rb +0 -184
  79. data/testing/rspec/spec/unit/linters/single_test_background_linter_unit_spec.rb +0 -89
  80. data/testing/rspec/spec/unit/linters/step_with_end_period_linter_unit_spec.rb +0 -54
  81. data/testing/rspec/spec/unit/linters/step_with_too_many_characters_linter_unit_spec.rb +0 -155
  82. data/testing/rspec/spec/unit/linters/test_should_use_background_linter_unit_spec.rb +0 -464
  83. data/testing/rspec/spec/unit/linters/test_with_action_step_as_final_step_linter_unit_spec.rb +0 -165
  84. data/testing/rspec/spec/unit/linters/test_with_bad_name_linter_unit_spec.rb +0 -81
  85. data/testing/rspec/spec/unit/linters/test_with_no_action_step_linter_unit_spec.rb +0 -244
  86. data/testing/rspec/spec/unit/linters/test_with_no_name_linter_unit_spec.rb +0 -88
  87. data/testing/rspec/spec/unit/linters/test_with_no_verification_step_linter_unit_spec.rb +0 -246
  88. data/testing/rspec/spec/unit/linters/test_with_setup_step_after_action_step_linter_unit_spec.rb +0 -233
  89. data/testing/rspec/spec/unit/linters/test_with_setup_step_after_verification_step_linter_unit_spec.rb +0 -233
  90. data/testing/rspec/spec/unit/linters/test_with_setup_step_as_final_step_linter_unit_spec.rb +0 -164
  91. data/testing/rspec/spec/unit/linters/test_with_too_many_steps_linter_unit_spec.rb +0 -192
@@ -1,41 +0,0 @@
1
- require 'tmpdir'
2
-
3
-
4
- module CukeLinter
5
- module FileHelper
6
-
7
- class << self
8
-
9
- def created_directories
10
- @created_directories ||= []
11
- end
12
-
13
- def create_directory(options = {})
14
- options[:name] ||= 'test_directory'
15
- options[:directory] ||= Dir.mktmpdir
16
-
17
- path = "#{options[:directory]}/#{options[:name]}"
18
-
19
- Dir::mkdir(path)
20
- created_directories << options[:directory]
21
-
22
- path
23
- end
24
-
25
- def create_file(options = {})
26
- options[:text] ||= ''
27
- options[:name] ||= 'test_file'
28
- options[:extension] ||= '.txt'
29
- options[:directory] ||= create_directory
30
-
31
- file_path = "#{options[:directory]}/#{options[:name]}#{options[:extension]}"
32
- FileUtils.mkdir_p(File.dirname(file_path)) # Ensuring that the target directory already exists
33
- File.write(file_path, options[:text])
34
-
35
- file_path
36
- end
37
-
38
- end
39
-
40
- end
41
- end
@@ -1,15 +0,0 @@
1
- module CukeLinter
2
- module FormatterFactory
3
-
4
- def self.generate_fake_formatter(name: 'FakeFormater')
5
- formatter = Object.new
6
-
7
- formatter.define_singleton_method('format') do |data|
8
- data.reduce("#{name}: ") { |final, lint_error| final << "#{lint_error[:problem]}: #{lint_error[:location]}\n" }
9
- end
10
-
11
- formatter
12
- end
13
-
14
- end
15
- end
@@ -1,8 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
-
5
- # Specify your gem's dependencies in cuke_linter.gemspec
6
- gemspec :path => "../../"
7
-
8
- gem 'cuke_modeler', '~> 1.0'
@@ -1,8 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
-
5
- # Specify your gem's dependencies in cuke_linter.gemspec
6
- gemspec :path => "../../"
7
-
8
- gem 'cuke_modeler', '~> 2.0'
@@ -1,60 +0,0 @@
1
- module CukeLinter
2
- module LinterFactory
3
-
4
- def self.generate_fake_linter(name: 'FakeLinter', finds_problems: true)
5
- linter = Object.new
6
-
7
- linter.define_singleton_method('lint') do |model|
8
- location = model.respond_to?(:source_line) ? "#{model.get_ancestor(:feature_file).path}:#{model.source_line}" : model.path
9
- problem = @problem || "#{name} problem"
10
-
11
- if finds_problems
12
- { problem: problem,
13
- location: location }
14
- else
15
- nil
16
- end
17
- end
18
-
19
- linter.define_singleton_method('name') do
20
- name
21
- end
22
-
23
- linter.define_singleton_method('configure') do |options|
24
- @problem = options['Problem'] if options['Problem']
25
- end
26
-
27
-
28
- linter
29
- end
30
-
31
- def self.generate_fake_linter_class(module_name: nil, class_name: 'FakeLinter', name: 'Some Name', finds_problems: true)
32
-
33
- if module_name
34
- parent_module = Kernel.const_defined?(module_name) ? Kernel.const_get(module_name) : Kernel.const_set(module_name, Module.new)
35
- end
36
-
37
- (parent_module || Kernel).const_set(class_name, Class.new do
38
-
39
- define_method('lint') do |model|
40
- location = model.respond_to?(:source_line) ? "#{model.get_ancestor(:feature_file).path}:#{model.source_line}" : model.path
41
- problem = @problem || "#{name} problem"
42
-
43
- if finds_problems
44
- { problem: problem,
45
- location: location }
46
- else
47
- nil
48
- end
49
- end
50
-
51
- define_method('name') do
52
- name
53
- end
54
-
55
- end)
56
-
57
- end
58
-
59
- end
60
- end
@@ -1,109 +0,0 @@
1
- module CukeLinter
2
-
3
- # A simple model used for testing
4
-
5
- class TestModel < CukeModeler::Model
6
-
7
- include CukeModeler::Sourceable
8
- include CukeModeler::Taggable
9
-
10
- def initialize
11
- super
12
-
13
- @tags = []
14
- end
15
-
16
- end
17
- end
18
-
19
-
20
- module CukeLinter
21
-
22
- # A helper module that generates various models for use in testing
23
-
24
- module ModelFactory
25
-
26
- def self.generate_feature_model(source_text: 'Feature:', parent_file_path: 'path_to_file')
27
- fake_parent_model = CukeModeler::FeatureFile.new
28
- fake_parent_model.path = parent_file_path
29
-
30
- model = CukeModeler::Feature.new(source_text)
31
- model.parent_model = fake_parent_model
32
-
33
- fake_parent_model.feature = model
34
-
35
- model
36
- end
37
-
38
- def self.generate_feature_file_model
39
- model = CukeModeler::FeatureFile.new
40
-
41
- model
42
- end
43
-
44
- def self.generate_example_model(source_text: 'Examples:', parent_file_path: 'path_to_file')
45
- fake_parent_model = generate_outline_model(parent_file_path: parent_file_path)
46
-
47
- model = CukeModeler::Example.new(source_text)
48
- model.parent_model = fake_parent_model
49
-
50
- model
51
- end
52
-
53
- def self.generate_outline_model(source_text: "Scenario Outline:", parent_file_path: 'path_to_file')
54
- fake_parent_model = generate_feature_model(parent_file_path: parent_file_path)
55
-
56
- model = CukeModeler::Outline.new(source_text)
57
- model.parent_model = fake_parent_model
58
-
59
- model
60
- end
61
-
62
- def self.generate_scenario_model(source_text: 'Scenario:', parent_file_path: 'path_to_file')
63
- fake_parent_model = generate_feature_model(parent_file_path: parent_file_path)
64
-
65
- model = CukeModeler::Scenario.new(source_text)
66
- model.parent_model = fake_parent_model
67
-
68
- model
69
- end
70
-
71
- def self.generate_background_model(source_text: "Background:\n* a step", parent_file_path: 'path_to_file')
72
- fake_parent_model = generate_feature_model(parent_file_path: parent_file_path)
73
-
74
- model = CukeModeler::Background.new(source_text)
75
- model.parent_model = fake_parent_model
76
-
77
- model
78
- end
79
-
80
- def self.generate_step_model(source_text: '* a step', parent_file_path: 'path_to_file')
81
- fake_parent_model = generate_scenario_model(parent_file_path: parent_file_path)
82
-
83
- model = CukeModeler::Step.new(source_text)
84
- model.parent_model = fake_parent_model
85
-
86
- model
87
- end
88
-
89
- def self.generate_tag_model(source_text: '@a_tag')
90
- CukeModeler::Tag.new(source_text)
91
- end
92
-
93
- def self.generate_lintable_model(parent_file_path: 'path_to_file', source_line: 1, children: [])
94
- fake_file_model = CukeModeler::FeatureFile.new
95
- fake_file_model.path = parent_file_path
96
-
97
- model = CukeLinter::TestModel.new
98
- model.parent_model = fake_file_model
99
- model.source_line = source_line
100
-
101
- model.define_singleton_method('children') do
102
- children
103
- end
104
-
105
- model
106
- end
107
-
108
- end
109
- end
@@ -1,556 +0,0 @@
1
- require_relative '../../../../environments/rspec_env'
2
- require 'open3'
3
-
4
-
5
- RSpec.describe 'the Command Line Interface' do
6
-
7
- # Exit codes that are expected during normal use of the CLI
8
- let(:normal_exit_codes) { [0, 1] }
9
-
10
- # A minimal fake test suite that should be available for every spec
11
- let!(:test_directory) { CukeLinter::FileHelper.create_directory }
12
- let!(:linted_file) { CukeLinter::FileHelper.create_file(directory: test_directory,
13
- name: 'lacking_a_description',
14
- extension: '.feature',
15
- text: 'Feature:
16
- Scenario: A scenario
17
- When a step
18
- Then a step') }
19
-
20
- # Stuff that is not always needed and so can be lazy instantiated
21
- let(:executable_directory) { "#{PROJECT_ROOT}/exe" }
22
- let(:executable_name) { 'cuke_linter' }
23
- let(:executable_path) { "#{executable_directory}/#{executable_name}" }
24
- let(:command) { "bundle exec ruby #{executable_path}" }
25
- let(:results) { std_out, std_err, status = [nil, nil, nil]
26
-
27
- Dir.chdir(test_directory) do
28
- std_out, std_err, status = Open3.capture3(command)
29
- end
30
-
31
- { std_out: std_out, std_err: std_err, status: status } }
32
- let(:expected_help_text) { ['Usage: cuke_linter [options]',
33
- ' -p, --path PATH The file path that should be linted. Can be a file or directory.',
34
- ' This option can be specified multiple times in order to lint',
35
- ' multiple, unconnected locations.',
36
- ' -f, --formatter FORMATTER The formatter used for generating linting output. This option',
37
- ' can be specified multiple times in order to use more than one',
38
- ' formatter. Formatters must be specified using their fully',
39
- ' qualified class name (e.g CukeLinter::PrettyFormatter). Uses',
40
- ' the default formatter if none are specified.',
41
- ' -o, --out OUT The file path to which linting results are output. Can be specified',
42
- ' multiple times. Specified files are matched to formatters in the',
43
- ' same order that the formatters are specified. Any formatter without',
44
- ' a corresponding file path will output to STDOUT instead.',
45
- ' -r, --require FILEPATH A file that will be required before further processing. Likely',
46
- ' needed when using custom linters or formatters in order to ensure',
47
- ' that the specified classes have been read into memory. This option',
48
- ' can be specified multiple times in order to load more than one file.',
49
- ' -c, --config FILEPATH The configuration file that will be used. Will use the default',
50
- ' configuration file (if present) if this option is not specified.',
51
- ' -h, --help Display the help that you are reading now.',
52
- ' -v, --version Display the version of the gem being used.',
53
- ''].join("\n") }
54
-
55
- context 'with no additional arguments' do
56
-
57
- let(:command) { "bundle exec ruby #{executable_path}" }
58
-
59
- it 'can run cleanly by default' do
60
- expect(normal_exit_codes).to include(results[:status].exitstatus)
61
- end
62
-
63
- context 'when the default configuration file exists' do
64
-
65
- before(:each) do
66
- CukeLinter::FileHelper.create_file(directory: test_directory,
67
- name: '.cuke_linter',
68
- extension: '',
69
- text: 'AllLinters:
70
- Enabled: false')
71
- end
72
-
73
- it 'uses the default configuration file by default' do
74
- expect(results[:std_out]).to include("0 issues found\n")
75
- end
76
-
77
- end
78
-
79
- context 'when the default configuration file does not exist' do
80
-
81
- before(:each) do
82
- Dir.chdir(test_directory) do
83
- FileUtils.rm('./.cuke_linter') if File.exist?('./.cuke_linter')
84
- end
85
- end
86
-
87
- it 'can still run cleanly' do
88
- expect(normal_exit_codes).to include(results[:status].exitstatus)
89
- end
90
-
91
- end
92
-
93
- end
94
-
95
- describe 'exit codes' do
96
-
97
- context 'when no problems are found' do
98
- # This file does not have any problems with the current linter set
99
- let!(:linted_file) { CukeLinter::FileHelper.create_file(directory: test_directory,
100
- name: 'nothing_wrong',
101
- extension: '.feature',
102
- text: 'Feature: Nothing wrong
103
- A description
104
- Scenario: A scenario
105
- When a step
106
- Then a step') }
107
-
108
- it 'returns a zero exit code' do
109
- expect(results[:status].exitstatus).to eq(0)
110
- end
111
-
112
- end
113
-
114
- context 'when linting problems are found' do
115
- # This should be a problematic feature file
116
- let!(:linted_file) { CukeLinter::FileHelper.create_file(directory: test_directory,
117
- name: 'pretty_empty',
118
- extension: '.feature',
119
- text: 'Feature: ') }
120
-
121
- it 'returns a non-zero exit code' do
122
- expect(results[:status].exitstatus).to eq(1)
123
- end
124
-
125
- end
126
-
127
- context 'when something else goes wrong' do
128
-
129
- # Bad CLI usage due to missing required flag arguments
130
- let(:command) { "bundle exec ruby #{executable_path} -r" }
131
-
132
- it 'returns a different non-zero exit code' do
133
- expect(results[:status].exitstatus).to eq(2)
134
- end
135
-
136
- end
137
- end
138
-
139
-
140
- describe 'option flags' do
141
-
142
- context 'with a path flag' do
143
- ['-p', '--path'].each do |path_flag|
144
-
145
- context "using the '#{path_flag}' form" do
146
-
147
- let(:flag) { path_flag }
148
-
149
- context 'with path arguments' do
150
- let(:file_1) { CukeLinter::FileHelper.create_file(directory: test_directory,
151
- name: 'some_feature',
152
- extension: '.feature',
153
- text: 'Feature: Some feature
154
- Scenario: A scenario
155
- When a step
156
- Then a step') }
157
- let(:file_2) { CukeLinter::FileHelper.create_file(directory: test_directory,
158
- name: 'a_directory/with/some_feature',
159
- extension: '.feature',
160
- text: 'Feature: Some feature
161
- Scenario: A scenario
162
- When a step
163
- Then a step') }
164
- let(:file_1_path) { file_1 }
165
- let(:file_2_directory) { File.dirname(file_2) }
166
- let(:command) { "bundle exec ruby #{executable_path} #{flag} #{file_1_path} #{flag} #{file_2_directory}" }
167
-
168
- # TODO: add a negative test that makes sure that non-included paths aren't linted when paths are explicitly included
169
-
170
- it "lints that locations specified by '#{path_flag}'" do
171
- expect(results[:std_out]).to eq(['FeatureWithoutDescriptionLinter',
172
- ' Feature has no description',
173
- ' <path_to>/a_directory/with/some_feature.feature:1',
174
- ' <path_to>/some_feature.feature:1',
175
- '',
176
- '2 issues found',
177
- ''].join("\n").gsub('<path_to>', test_directory))
178
- end
179
-
180
- end
181
-
182
- context 'without path arguments' do
183
-
184
- let(:command) { "bundle exec ruby #{executable_path} #{flag}" }
185
-
186
-
187
- it 'complains about the missing argument' do
188
- expect(results[:std_out]).to include("missing argument: #{flag}")
189
- end
190
-
191
- it 'displays the help text' do
192
- expect(results[:std_out]).to include(expected_help_text)
193
- end
194
-
195
- it 'exits with an error' do
196
- expect(results[:status].exitstatus).to eq(2)
197
- end
198
-
199
- end
200
-
201
- end
202
- end
203
- end
204
-
205
- context 'with a formatter flag' do
206
- ['-f', '--formatter'].each do |formatter_flag|
207
-
208
- context "using the '#{formatter_flag}' form" do
209
-
210
- let(:flag) { formatter_flag }
211
-
212
- context 'with formatter arguments' do
213
- let(:linted_file) { CukeLinter::FileHelper.create_file(name: 'some_feature',
214
- extension: '.feature',
215
- text: 'Feature: Some feature
216
- Scenario: A scenario
217
- When a step
218
- Then a step') }
219
- let(:formatter_class) { 'AFakeFormatter' }
220
- let(:formatter_class_in_module) { 'CukeLinter::AnotherFakeFormatter' }
221
- let(:formatter_class_file) { CukeLinter::FileHelper.create_file(extension: '.rb',
222
- text: 'class AFakeFormatter
223
- def format(data)
224
- data.reduce("#{self.class}: ") { |final, lint_error| final << "#{lint_error[:problem]}: #{lint_error[:location]}\n" }
225
- end
226
- end') }
227
- let(:formatter_class_in_module_file) { CukeLinter::FileHelper.create_file(extension: '.rb',
228
- text: 'module CukeLinter
229
- class AnotherFakeFormatter
230
- def format(data)
231
- data.reduce("#{self.class}: ") { |final, lint_error| final << "#{lint_error[:problem]}: #{lint_error[:location]}\n" }
232
- end
233
- end
234
- end') }
235
- let(:command) { "bundle exec ruby #{executable_path} #{flag} #{formatter_class} #{flag} #{formatter_class_in_module} -p #{linted_file} -r #{formatter_class_file} -r #{formatter_class_in_module_file}" }
236
-
237
-
238
- it "uses the formatters specified by '#{formatter_flag}'" do
239
- expect(results[:std_out]).to eq(['AFakeFormatter: Feature has no description: <path_to_file>:1',
240
- 'CukeLinter::AnotherFakeFormatter: Feature has no description: <path_to_file>:1',
241
- ''].join("\n").gsub('<path_to_file>', linted_file))
242
- end
243
-
244
- end
245
-
246
- context 'without formatter arguments' do
247
-
248
- let(:command) { "bundle exec ruby #{executable_path} #{flag}" }
249
-
250
-
251
- it 'complains about the missing argument' do
252
- expect(results[:std_out]).to include("missing argument: #{flag}")
253
- end
254
-
255
- it 'displays the help text' do
256
- expect(results[:std_out]).to include(expected_help_text)
257
- end
258
-
259
- it 'exits with an error' do
260
- expect(results[:status].exitstatus).to eq(2)
261
- end
262
-
263
- end
264
-
265
- end
266
- end
267
- end
268
-
269
- context 'with an output flag' do
270
- ['-o', '--out'].each do |output_flag|
271
-
272
- context "using the '#{output_flag}' form" do
273
-
274
- let(:flag) { output_flag }
275
-
276
- context 'with output arguments' do
277
- let(:output_location) { "#{CukeLinter::FileHelper.create_directory}/output.txt" }
278
- let(:other_output_location) { "#{CukeLinter::FileHelper.create_directory}/other_output.txt" }
279
- let(:linted_file) { CukeLinter::FileHelper.create_file(name: 'some_feature',
280
- extension: '.feature',
281
- text: 'Feature: Some feature
282
- Scenario: A scenario
283
- When a step
284
- Then a step') }
285
- let(:formatter_class_1) { 'AFakeFormatter' }
286
- let(:formatter_class_2) { 'AnotherFakeFormatter' }
287
- let(:formatter_class_file) { CukeLinter::FileHelper.create_file(extension: '.rb',
288
- text: 'class AFakeFormatter
289
- def format(data)
290
- "Formatting done by #{self.class}"
291
- end
292
- end
293
-
294
- class AnotherFakeFormatter
295
- def format(data)
296
- "Formatting done by #{self.class}"
297
- end
298
- end') }
299
- let(:command) { "bundle exec ruby #{executable_path} -f #{formatter_class_1} -f #{formatter_class_2} #{flag} #{output_location} #{flag} #{other_output_location} -p #{linted_file} -r #{formatter_class_file}" }
300
-
301
-
302
- it 'matches output locations to formatters in the same order that they are specified' do
303
- # Have to trigger the command
304
- results
305
-
306
- expect(File.read(output_location)).to eq('Formatting done by AFakeFormatter')
307
- expect(File.read(other_output_location)).to eq('Formatting done by AnotherFakeFormatter')
308
- end
309
-
310
-
311
- context 'with unmatched output arguments' do
312
- let(:command) { "bundle exec ruby #{executable_path} #{flag} #{output_location} -p #{linted_file}" }
313
-
314
-
315
- it "outputs to the location specified by '#{output_flag}'" do
316
- # Have to trigger the command
317
- results
318
-
319
- expect(File.read(output_location)).to eq(['FeatureWithoutDescriptionLinter',
320
- ' Feature has no description',
321
- ' <path_to_file>:1',
322
- '',
323
- '1 issues found'].join("\n").gsub('<path_to_file>', linted_file))
324
- end
325
-
326
- it 'does not output to STDOUT' do
327
- expect(results[:std_out]).to eq('')
328
- end
329
-
330
- it 'uses the default formatter' do
331
- # Have to trigger the command
332
- results
333
-
334
- expect(File.read(output_location)).to eq(['FeatureWithoutDescriptionLinter',
335
- ' Feature has no description',
336
- ' <path_to_file>:1',
337
- '',
338
- '1 issues found'].join("\n").gsub('<path_to_file>', linted_file))
339
- end
340
-
341
- end
342
-
343
- context 'with unmatched formatter arguments' do
344
- let(:command) { "bundle exec ruby #{executable_path} #{flag} #{output_location} -f #{formatter_class_1} -f #{formatter_class_2} -p #{linted_file} -r #{formatter_class_file}" }
345
-
346
-
347
- it "outputs to the location specified by '#{output_flag}' for the matched formatters" do
348
- # Have to trigger the command
349
- results
350
-
351
- expect(File.read(output_location)).to eq("Formatting done by #{formatter_class_1}")
352
- end
353
-
354
- it 'outputs to STDOUT for the unmatched formatters' do
355
- expect(results[:std_out]).to eq("Formatting done by #{formatter_class_2}\n")
356
- end
357
-
358
- end
359
-
360
- end
361
-
362
-
363
- context 'without output arguments' do
364
-
365
- let(:command) { "bundle exec ruby #{executable_path} #{flag}" }
366
-
367
-
368
- it 'complains about the missing argument' do
369
- expect(results[:std_out]).to include("missing argument: #{flag}")
370
- end
371
-
372
- it 'displays the help text' do
373
- expect(results[:std_out]).to include(expected_help_text)
374
- end
375
-
376
- it 'exits with an error' do
377
- expect(results[:status].exitstatus).to eq(2)
378
- end
379
-
380
- end
381
-
382
- end
383
- end
384
- end
385
-
386
- context 'with a require flag' do
387
- ['-r', '--require'].each do |require_flag|
388
-
389
- context "using the '#{require_flag}' form" do
390
-
391
- let(:flag) { require_flag }
392
-
393
- context 'with require arguments' do
394
- let(:file_1) { CukeLinter::FileHelper.create_file(extension: '.rb',
395
- text: "puts 'This file was loaded'") }
396
- let(:file_1_path) { file_1 }
397
- let(:file_2) { CukeLinter::FileHelper.create_file(extension: '.rb',
398
- text: "puts 'This file was also loaded'") }
399
- let(:file_2_path) { file_2 }
400
- let(:command) { "bundle exec ruby #{executable_path} #{flag} #{file_1_path} #{flag} #{file_2_path}" }
401
-
402
-
403
- it "require the files specified by '#{require_flag}' before linting" do
404
- expect(results[:std_out]).to include('This file was loaded')
405
- expect(results[:std_out]).to include('This file was also loaded')
406
- end
407
-
408
- end
409
-
410
- context 'without require arguments' do
411
-
412
- let(:command) { "bundle exec ruby #{executable_path} #{flag}" }
413
-
414
-
415
- it 'complains about the missing argument' do
416
- expect(results[:std_out]).to include("missing argument: #{flag}")
417
- end
418
-
419
- it 'displays the help text' do
420
- expect(results[:std_out]).to include(expected_help_text)
421
- end
422
-
423
- it 'exits with an error' do
424
- expect(results[:status].exitstatus).to eq(2)
425
- end
426
-
427
- end
428
-
429
- end
430
- end
431
- end
432
-
433
- context 'with a config flag' do
434
- ['-c', '--config'].each do |config_flag|
435
-
436
- context "using the '#{config_flag}' form" do
437
-
438
- let(:flag) { config_flag }
439
-
440
- context 'with a single config argument' do
441
-
442
- let(:config_file) { CukeLinter::FileHelper.create_file(name: 'my_config_file',
443
- extension: '.yml',
444
- text: 'AllLinters:
445
- Enabled: false') }
446
- let(:command) { "bundle exec ruby #{executable_path} #{flag} #{config_file}" }
447
-
448
- it "uses the configuration file specified by '#{config_flag}'" do
449
- expect(results[:std_out]).to include("0 issues found\n")
450
- end
451
-
452
- end
453
-
454
- context 'with multiple config arguments' do
455
-
456
- let(:command) { "bundle exec ruby #{executable_path} #{flag} foo #{flag} bar" }
457
-
458
- it 'complains that more than one configuration file is specified' do
459
- expect(results[:std_out]).to eq("Cannot specify more than one configuration file!\n")
460
- end
461
-
462
- it 'exits with an error' do
463
- expect(results[:status].exitstatus).to eq(2)
464
- end
465
-
466
- end
467
-
468
- context 'without config arguments' do
469
-
470
- let(:command) { "bundle exec ruby #{executable_path} #{flag}" }
471
-
472
-
473
- it 'complains about the missing argument' do
474
- expect(results[:std_out]).to include("missing argument: #{flag}")
475
- end
476
-
477
- it 'displays the help text' do
478
- expect(results[:std_out]).to include(expected_help_text)
479
- end
480
-
481
- it 'exits with an error' do
482
- expect(results[:status].exitstatus).to eq(2)
483
- end
484
-
485
- end
486
-
487
- end
488
- end
489
- end
490
-
491
- context 'with a help flag' do
492
-
493
- let(:command) { "bundle exec ruby #{executable_path} #{flag}" }
494
-
495
- ['-h', '--help'].each do |help_flag|
496
-
497
- context "using the '#{help_flag}' form" do
498
-
499
- let(:flag) { help_flag }
500
-
501
- it "'#{help_flag}' displays the help text" do
502
- expect(results[:std_out]).to eq(expected_help_text)
503
- end
504
-
505
- it 'exits cleanly' do
506
- expect(results[:status].exitstatus).to eq(0)
507
- end
508
-
509
- end
510
- end
511
- end
512
-
513
- context 'with a version flag' do
514
-
515
- let(:command) { "bundle exec ruby #{executable_path} #{flag}" }
516
-
517
- ['-v', '--version'].each do |version_flag|
518
-
519
- context "using the '#{version_flag}' form" do
520
-
521
- let(:flag) { version_flag }
522
-
523
- it "'#{version_flag}' displays the version being used" do
524
- expect(results[:std_out]).to eq("#{CukeLinter::VERSION}\n")
525
- end
526
-
527
- it 'exits cleanly' do
528
- expect(results[:status].exitstatus).to eq(0)
529
- end
530
-
531
- end
532
- end
533
- end
534
-
535
- context 'with an invalid flag' do
536
-
537
- let(:command) { "bundle exec ruby #{executable_path} #{flag}" }
538
- let(:flag) { '--not_a_real_flag' }
539
-
540
- it 'complains about the invalid flag' do
541
- expect(results[:std_out]).to include("invalid option: #{flag}")
542
- end
543
-
544
- it 'displays the help text' do
545
- expect(results[:std_out]).to include(expected_help_text)
546
- end
547
-
548
- it 'exits with an error' do
549
- expect(results[:status].exitstatus).to eq(2)
550
- end
551
-
552
- end
553
-
554
- end
555
-
556
- end