chutney 2.2.1 → 3.0.0.beta.1
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/.rubocop.yml +7 -1
- data/Gemfile +2 -0
- data/Rakefile +2 -0
- data/chutney.gemspec +8 -4
- data/config/cucumber.yml +1 -0
- data/exe/chutney +2 -0
- data/lib/chutney.rb +9 -11
- data/lib/chutney/configuration.rb +2 -0
- data/lib/chutney/formatter.rb +2 -0
- data/lib/chutney/formatter/json_formatter.rb +2 -0
- data/lib/chutney/formatter/pie_formatter.rb +2 -0
- data/lib/chutney/formatter/rainbow_formatter.rb +2 -0
- data/lib/chutney/issue.rb +2 -0
- data/lib/chutney/linter.rb +58 -59
- data/lib/chutney/linter/avoid_full_stop.rb +3 -1
- data/lib/chutney/linter/avoid_outline_for_single_example.rb +8 -6
- data/lib/chutney/linter/avoid_scripting.rb +6 -4
- data/lib/chutney/linter/avoid_typographers_quotes.rb +16 -14
- data/lib/chutney/linter/background_does_more_than_setup.rb +8 -6
- data/lib/chutney/linter/background_requires_multiple_scenarios.rb +6 -3
- data/lib/chutney/linter/bad_scenario_name.rb +4 -2
- data/lib/chutney/linter/empty_feature_file.rb +2 -0
- data/lib/chutney/linter/file_name_differs_feature_name.rb +4 -2
- data/lib/chutney/linter/givens_after_background.rb +5 -6
- data/lib/chutney/linter/invalid_file_name.rb +2 -0
- data/lib/chutney/linter/invalid_step_flow.rb +7 -7
- data/lib/chutney/linter/missing_example_name.rb +7 -5
- data/lib/chutney/linter/missing_feature_description.rb +4 -3
- data/lib/chutney/linter/missing_feature_name.rb +3 -2
- data/lib/chutney/linter/missing_scenario_name.rb +3 -4
- data/lib/chutney/linter/missing_test_action.rb +3 -1
- data/lib/chutney/linter/missing_verification.rb +3 -1
- data/lib/chutney/linter/required_tags_starts_with.rb +2 -0
- data/lib/chutney/linter/same_tag_for_all_scenarios.rb +11 -10
- data/lib/chutney/linter/scenario_names_match.rb +4 -3
- data/lib/chutney/linter/tag_used_multiple_times.rb +2 -0
- data/lib/chutney/linter/too_clumsy.rb +3 -1
- data/lib/chutney/linter/too_long_step.rb +4 -2
- data/lib/chutney/linter/too_many_different_tags.rb +4 -2
- data/lib/chutney/linter/too_many_steps.rb +4 -2
- data/lib/chutney/linter/too_many_tags.rb +2 -0
- data/lib/chutney/linter/unique_scenario_names.rb +3 -3
- data/lib/chutney/linter/unknown_variable.rb +13 -13
- data/lib/chutney/linter/unused_variable.rb +13 -13
- data/lib/chutney/linter/use_background.rb +17 -16
- data/lib/chutney/linter/use_outline.rb +8 -7
- data/lib/chutney/version.rb +3 -1
- data/spec/chutney_spec.rb +2 -0
- data/spec/spec_helper.rb +2 -0
- metadata +33 -12
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Chutney
|
2
4
|
# service class to lint for too long steps
|
3
5
|
class TooLongStep < Linter
|
4
6
|
def lint
|
5
7
|
steps do |feature, scenario, step|
|
6
|
-
next if step
|
8
|
+
next if step.text.length <= maxlength
|
7
9
|
|
8
10
|
add_issue(
|
9
|
-
I18n.t('linters.too_long_step', length: step
|
11
|
+
I18n.t('linters.too_long_step', length: step.text.length, max: maxlength),
|
10
12
|
feature, scenario
|
11
13
|
)
|
12
14
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Chutney
|
2
4
|
# service class to lint for too many different tags
|
3
5
|
class TooManyDifferentTags < Linter
|
@@ -16,9 +18,9 @@ module Chutney
|
|
16
18
|
end
|
17
19
|
|
18
20
|
def all_tags
|
19
|
-
return [] unless feature&.
|
21
|
+
return [] unless feature&.scenarios
|
20
22
|
|
21
|
-
tags_for(feature) + feature
|
23
|
+
tags_for(feature) + feature.scenarios.map { |scenario| tags_for(scenario) }.flatten
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Chutney
|
2
4
|
# service class to lint for too many steps
|
3
5
|
class TooManySteps < Linter
|
4
6
|
def lint
|
5
7
|
filled_scenarios do |feature, scenario|
|
6
|
-
next if scenario
|
8
|
+
next if scenario.steps.length <= maxcount
|
7
9
|
|
8
10
|
add_issue(
|
9
|
-
I18n.t('linters.too_many_steps', count: scenario
|
11
|
+
I18n.t('linters.too_many_steps', count: scenario.steps.length, max: maxcount),
|
10
12
|
feature
|
11
13
|
)
|
12
14
|
end
|
@@ -1,12 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Chutney
|
2
4
|
# service class to lint for unique scenario names
|
3
5
|
class UniqueScenarioNames < Linter
|
4
6
|
def lint
|
5
7
|
references_by_name = {}
|
6
8
|
scenarios do |feature, scenario|
|
7
|
-
|
8
|
-
|
9
|
-
name = scenario[:name]
|
9
|
+
name = scenario.name
|
10
10
|
if references_by_name[name]
|
11
11
|
issue(name, references_by_name[name], scenario)
|
12
12
|
else
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Chutney
|
2
4
|
# service class to lint for unknown variables
|
3
5
|
class UnknownVariable < Linter
|
4
6
|
def lint
|
5
7
|
filled_scenarios do |feature, scenario|
|
6
8
|
known_vars = Set.new(known_variables(scenario))
|
7
|
-
scenario
|
9
|
+
scenario.steps.each do |step|
|
8
10
|
step_vars(step).each do |used_var|
|
9
11
|
next if known_vars.include? used_var
|
10
12
|
|
@@ -17,17 +19,17 @@ module Chutney
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def step_vars(step)
|
20
|
-
vars = gather_vars step
|
21
|
-
return vars unless step.
|
22
|
+
vars = gather_vars step.text
|
23
|
+
return vars unless step.block
|
22
24
|
|
23
|
-
vars + gather_vars_from_argument(step
|
25
|
+
vars + gather_vars_from_argument(step.block)
|
24
26
|
end
|
25
27
|
|
26
28
|
def gather_vars_from_argument(argument)
|
27
|
-
return gather_vars argument
|
28
|
-
|
29
|
-
|
30
|
-
row
|
29
|
+
return gather_vars argument.content if argument.is_a? CukeModeler::DocString
|
30
|
+
|
31
|
+
argument.rows.map do |row|
|
32
|
+
row.cells.map { |cell| gather_vars cell.value }.flatten
|
31
33
|
end.flatten
|
32
34
|
end
|
33
35
|
|
@@ -36,11 +38,9 @@ module Chutney
|
|
36
38
|
end
|
37
39
|
|
38
40
|
def known_variables(scenario)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
example[:tableHeader][:cells].map { |cell| cell[:value].strip }
|
43
|
-
end.flatten
|
41
|
+
return [] unless scenario.is_a? CukeModeler::Outline
|
42
|
+
|
43
|
+
scenario.examples.map { |ex| ex.rows.first.cells.map(&:value) }.flatten
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -1,14 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Chutney
|
2
4
|
# service class to lint for unused variables
|
3
5
|
class UnusedVariable < Linter
|
4
6
|
def lint
|
5
7
|
scenarios do |feature, scenario|
|
6
|
-
next unless scenario.
|
7
|
-
|
8
|
-
scenario
|
9
|
-
next unless example.key?(:tableHeader)
|
8
|
+
next unless scenario.is_a? CukeModeler::Outline
|
9
|
+
|
10
|
+
scenario.examples.each do |example|
|
10
11
|
|
11
|
-
example
|
12
|
+
example.rows.first.cells.map(&:value).each do |variable|
|
12
13
|
next if used?(variable, scenario)
|
13
14
|
|
14
15
|
add_issue(I18n.t('linters.unused_variable', variable: variable), feature, scenario, example)
|
@@ -19,11 +20,10 @@ module Chutney
|
|
19
20
|
|
20
21
|
def used?(variable, scenario)
|
21
22
|
variable = "<#{variable}>"
|
22
|
-
return false unless scenario.key? :steps
|
23
23
|
|
24
|
-
scenario
|
25
|
-
return true if step
|
26
|
-
next unless step.
|
24
|
+
scenario.steps.each do |step|
|
25
|
+
return true if step.text.include? variable
|
26
|
+
next unless step.block
|
27
27
|
return true if used_in_docstring?(variable, step)
|
28
28
|
return true if used_in_table?(variable, step)
|
29
29
|
end
|
@@ -31,14 +31,14 @@ module Chutney
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def used_in_docstring?(variable, step)
|
34
|
-
step
|
34
|
+
step.block.is_a?(CukeModeler::DocString) && step.block.content.include?(variable)
|
35
35
|
end
|
36
36
|
|
37
37
|
def used_in_table?(variable, step)
|
38
|
-
return false unless step
|
38
|
+
return false unless step.block.is_a?(CukeModeler::Table)
|
39
39
|
|
40
|
-
step
|
41
|
-
row
|
40
|
+
step.block.rows.each do |row|
|
41
|
+
row.cells.each { |cell| return true if cell.value.include?(variable) }
|
42
42
|
end
|
43
43
|
false
|
44
44
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Chutney
|
2
4
|
# service class to lint for using background
|
3
5
|
class UseBackground < Linter
|
@@ -13,14 +15,13 @@ module Chutney
|
|
13
15
|
end
|
14
16
|
|
15
17
|
def gather_givens
|
16
|
-
return unless feature.
|
18
|
+
return unless feature.children
|
17
19
|
|
18
20
|
has_non_given_step = false
|
19
|
-
|
20
|
-
next unless scenario.
|
21
|
-
next if scenario[:steps].empty?
|
21
|
+
scenarios do |_feature, scenario|
|
22
|
+
next unless scenario.steps
|
22
23
|
|
23
|
-
has_non_given_step = true unless given_word?(scenario
|
24
|
+
has_non_given_step = true unless given_word?(scenario.steps.first.keyword)
|
24
25
|
end
|
25
26
|
return if has_non_given_step
|
26
27
|
|
@@ -29,15 +30,13 @@ module Chutney
|
|
29
30
|
result
|
30
31
|
end
|
31
32
|
|
32
|
-
def expanded_steps
|
33
|
-
|
34
|
-
next unless scenario
|
35
|
-
next unless scenario.include? :steps
|
36
|
-
next if scenario[:steps].empty?
|
33
|
+
def expanded_steps(&block)
|
34
|
+
scenarios do |_feature, scenario|
|
35
|
+
next unless scenario.steps
|
37
36
|
|
38
|
-
prototypes = [render_step(scenario
|
39
|
-
prototypes = expand_examples(scenario
|
40
|
-
prototypes.each
|
37
|
+
prototypes = [render_step(scenario.steps.first)]
|
38
|
+
prototypes = expand_examples(scenario.examples, prototypes) if scenario.is_a? CukeModeler::Outline
|
39
|
+
prototypes.each(&block)
|
41
40
|
end
|
42
41
|
end
|
43
42
|
|
@@ -50,10 +49,12 @@ module Chutney
|
|
50
49
|
|
51
50
|
def expand_outlines(sentence, example)
|
52
51
|
result = []
|
53
|
-
headers = example
|
54
|
-
example
|
52
|
+
headers = example.rows.first.cells.map(&:value)
|
53
|
+
example.rows.each_with_index do |row, idx|
|
54
|
+
next if idx.zero? # skip the header
|
55
|
+
|
55
56
|
modified_sentence = sentence.dup
|
56
|
-
headers.zip(row
|
57
|
+
headers.zip(row.cells.map(&:value)).map do |key, value|
|
57
58
|
modified_sentence.gsub!("<#{key}>", value)
|
58
59
|
end
|
59
60
|
result.push modified_sentence
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Chutney
|
2
4
|
# service class to lint for using outline
|
3
5
|
class UseOutline < Linter
|
@@ -36,12 +38,11 @@ module Chutney
|
|
36
38
|
|
37
39
|
def gather_scenarios(feature)
|
38
40
|
scenarios = []
|
39
|
-
return scenarios if feature.nil? || !feature.
|
41
|
+
return scenarios if feature.nil? || !feature.tests
|
40
42
|
|
41
|
-
|
42
|
-
next unless scenario
|
43
|
-
next
|
44
|
-
next if scenario[:steps].empty?
|
43
|
+
scenarios do |_feature, scenario|
|
44
|
+
next unless scenario.steps
|
45
|
+
next if scenario.steps.empty?
|
45
46
|
|
46
47
|
scenarios.push generate_reference(feature, scenario)
|
47
48
|
end
|
@@ -51,8 +52,8 @@ module Chutney
|
|
51
52
|
def generate_reference(feature, scenario)
|
52
53
|
reference = {}
|
53
54
|
reference[:reference] = location(feature, scenario, nil)
|
54
|
-
reference[:name] = "#{scenario
|
55
|
-
reference[:text] = scenario
|
55
|
+
reference[:name] = "#{scenario.keyword}: #{scenario.name}"
|
56
|
+
reference[:text] = scenario.steps.map { |step| render_step(step) }.join ' '
|
56
57
|
reference
|
57
58
|
end
|
58
59
|
end
|
data/lib/chutney/version.rb
CHANGED
data/spec/chutney_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chutney
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0.beta.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nigel Brookes-Thomas
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: exe
|
13
13
|
cert_chain: []
|
14
|
-
date: 2020-
|
14
|
+
date: 2020-09-02 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: amatch
|
@@ -28,19 +28,39 @@ dependencies:
|
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 0.4.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
|
-
name:
|
31
|
+
name: cuke_modeler
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
requirements:
|
34
34
|
- - "~>"
|
35
35
|
- !ruby/object:Gem::Version
|
36
|
-
version:
|
36
|
+
version: '3.3'
|
37
37
|
type: :runtime
|
38
38
|
prerelease: false
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
40
40
|
requirements:
|
41
41
|
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '3.3'
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: gherkin
|
46
|
+
requirement: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
42
49
|
- !ruby/object:Gem::Version
|
43
50
|
version: 5.1.0
|
51
|
+
- - "<"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '9.1'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 5.1.0
|
61
|
+
- - "<"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '9.1'
|
44
64
|
- !ruby/object:Gem::Dependency
|
45
65
|
name: i18n
|
46
66
|
requirement: !ruby/object:Gem::Requirement
|
@@ -103,14 +123,14 @@ dependencies:
|
|
103
123
|
requirements:
|
104
124
|
- - "~>"
|
105
125
|
- !ruby/object:Gem::Version
|
106
|
-
version: '
|
126
|
+
version: '5.1'
|
107
127
|
type: :development
|
108
128
|
prerelease: false
|
109
129
|
version_requirements: !ruby/object:Gem::Requirement
|
110
130
|
requirements:
|
111
131
|
- - "~>"
|
112
132
|
- !ruby/object:Gem::Version
|
113
|
-
version: '
|
133
|
+
version: '5.1'
|
114
134
|
- !ruby/object:Gem::Dependency
|
115
135
|
name: pry-byebug
|
116
136
|
requirement: !ruby/object:Gem::Requirement
|
@@ -196,7 +216,7 @@ dependencies:
|
|
196
216
|
- !ruby/object:Gem::Version
|
197
217
|
version: '3.8'
|
198
218
|
description: A linter for your Cucumber features. It supports any spoken language
|
199
|
-
Cucumber
|
219
|
+
Cucumber supports.
|
200
220
|
email:
|
201
221
|
- nigel@brookes-thomas.co.uk
|
202
222
|
executables:
|
@@ -216,6 +236,7 @@ files:
|
|
216
236
|
- Rakefile
|
217
237
|
- chutney.gemspec
|
218
238
|
- config/chutney.yml
|
239
|
+
- config/cucumber.yml
|
219
240
|
- docs/.keep
|
220
241
|
- docs/_config.yml
|
221
242
|
- docs/credits.md
|
@@ -289,17 +310,17 @@ require_paths:
|
|
289
310
|
- lib
|
290
311
|
required_ruby_version: !ruby/object:Gem::Requirement
|
291
312
|
requirements:
|
292
|
-
- - "
|
313
|
+
- - "~>"
|
293
314
|
- !ruby/object:Gem::Version
|
294
|
-
version: '
|
315
|
+
version: '2.6'
|
295
316
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
296
317
|
requirements:
|
297
|
-
- - "
|
318
|
+
- - ">"
|
298
319
|
- !ruby/object:Gem::Version
|
299
|
-
version:
|
320
|
+
version: 1.3.1
|
300
321
|
requirements: []
|
301
322
|
rubygems_version: 3.1.2
|
302
323
|
signing_key:
|
303
324
|
specification_version: 4
|
304
|
-
summary: A linter for
|
325
|
+
summary: A linter for multi-lingual Gherkin
|
305
326
|
test_files: []
|