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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -1
- data/README.md +4 -4
- data/cuke_linter.gemspec +3 -3
- data/lib/cuke_linter.rb +5 -3
- data/lib/cuke_linter/version.rb +1 -1
- metadata +2 -86
- data/.gitignore +0 -19
- data/.simplecov +0 -8
- data/.travis.yml +0 -33
- data/CONTRIBUTING.md +0 -26
- data/Gemfile +0 -6
- data/Rakefile +0 -63
- data/appveyor.yml +0 -43
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/environments/common_env.rb +0 -12
- data/environments/cucumber_env.rb +0 -22
- data/environments/rspec_env.rb +0 -50
- data/testing/cucumber/step_definitions/action_steps.rb +0 -84
- data/testing/cucumber/step_definitions/setup_steps.rb +0 -258
- data/testing/cucumber/step_definitions/verification_steps.rb +0 -94
- data/testing/file_helper.rb +0 -41
- data/testing/formatter_factory.rb +0 -15
- data/testing/gemfiles/cuke_modeler1.gemfile +0 -8
- data/testing/gemfiles/cuke_modeler2.gemfile +0 -8
- data/testing/linter_factory.rb +0 -60
- data/testing/model_factory.rb +0 -109
- data/testing/rspec/spec/integration/cli_integration_spec.rb +0 -556
- data/testing/rspec/spec/integration/configuration_spec.rb +0 -811
- data/testing/rspec/spec/integration/cuke_linter_integration_spec.rb +0 -243
- data/testing/rspec/spec/integration/formatters/formatter_integration_specs.rb +0 -5
- data/testing/rspec/spec/integration/formatters/pretty_formatter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/background_does_more_than_setup_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/element_with_common_tags_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/element_with_duplicate_tags_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/element_with_too_many_tags_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/example_without_name_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/feature_file_with_invalid_name_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/feature_file_with_mismatched_name_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/feature_with_too_many_different_tags_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/feature_without_description_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/feature_without_name_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/feature_without_scenarios_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/linter_integration_specs.rb +0 -7
- data/testing/rspec/spec/integration/linters/outline_with_single_example_row_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/single_test_background_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/step_with_end_period_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/step_with_too_many_characters_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/test_should_use_background_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/test_with_action_step_as_final_step_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/test_with_bad_name_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/test_with_no_action_step_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/test_with_no_name_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/test_with_no_verification_step_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/test_with_setup_step_after_action_step_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/test_with_setup_step_after_verification_step_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/test_with_setup_step_as_final_step_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/integration/linters/test_with_too_many_steps_linter_integration_spec.rb +0 -8
- data/testing/rspec/spec/unit/cuke_linter_unit_spec.rb +0 -114
- data/testing/rspec/spec/unit/formatters/formatter_unit_specs.rb +0 -11
- data/testing/rspec/spec/unit/formatters/pretty_formatter_unit_spec.rb +0 -115
- data/testing/rspec/spec/unit/linters/background_does_more_than_setup_linter_unit_spec.rb +0 -186
- data/testing/rspec/spec/unit/linters/configurable_linter_unit_specs.rb +0 -11
- data/testing/rspec/spec/unit/linters/element_with_common_tags_linter_unit_spec.rb +0 -248
- data/testing/rspec/spec/unit/linters/element_with_duplicate_tags_linter_unit_spec.rb +0 -203
- data/testing/rspec/spec/unit/linters/element_with_too_many_tags_linter_unit_spec.rb +0 -296
- data/testing/rspec/spec/unit/linters/example_without_name_linter_unit_spec.rb +0 -81
- data/testing/rspec/spec/unit/linters/feature_file_with_invalid_name_linter_unit_spec.rb +0 -106
- data/testing/rspec/spec/unit/linters/feature_file_with_mismatched_name_linter_unit_spec.rb +0 -124
- data/testing/rspec/spec/unit/linters/feature_with_too_many_different_tags_linter_unit_spec.rb +0 -293
- data/testing/rspec/spec/unit/linters/feature_without_description_linter_unit_spec.rb +0 -80
- data/testing/rspec/spec/unit/linters/feature_without_name_linter_unit_spec.rb +0 -84
- data/testing/rspec/spec/unit/linters/feature_without_scenarios_linter_unit_spec.rb +0 -102
- data/testing/rspec/spec/unit/linters/linter_unit_spec.rb +0 -197
- data/testing/rspec/spec/unit/linters/linter_unit_specs.rb +0 -57
- data/testing/rspec/spec/unit/linters/outline_with_single_example_row_linter_unit_spec.rb +0 -184
- data/testing/rspec/spec/unit/linters/single_test_background_linter_unit_spec.rb +0 -89
- data/testing/rspec/spec/unit/linters/step_with_end_period_linter_unit_spec.rb +0 -54
- data/testing/rspec/spec/unit/linters/step_with_too_many_characters_linter_unit_spec.rb +0 -155
- data/testing/rspec/spec/unit/linters/test_should_use_background_linter_unit_spec.rb +0 -464
- data/testing/rspec/spec/unit/linters/test_with_action_step_as_final_step_linter_unit_spec.rb +0 -165
- data/testing/rspec/spec/unit/linters/test_with_bad_name_linter_unit_spec.rb +0 -81
- data/testing/rspec/spec/unit/linters/test_with_no_action_step_linter_unit_spec.rb +0 -244
- data/testing/rspec/spec/unit/linters/test_with_no_name_linter_unit_spec.rb +0 -88
- data/testing/rspec/spec/unit/linters/test_with_no_verification_step_linter_unit_spec.rb +0 -246
- data/testing/rspec/spec/unit/linters/test_with_setup_step_after_action_step_linter_unit_spec.rb +0 -233
- data/testing/rspec/spec/unit/linters/test_with_setup_step_after_verification_step_linter_unit_spec.rb +0 -233
- data/testing/rspec/spec/unit/linters/test_with_setup_step_as_final_step_linter_unit_spec.rb +0 -164
- data/testing/rspec/spec/unit/linters/test_with_too_many_steps_linter_unit_spec.rb +0 -192
data/testing/file_helper.rb
DELETED
|
@@ -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
|
data/testing/linter_factory.rb
DELETED
|
@@ -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
|
data/testing/model_factory.rb
DELETED
|
@@ -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
|