gherkin_lint 0.3.1 → 0.4.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 (33) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +12 -6
  3. data/Gemfile +1 -1
  4. data/Rakefile +2 -2
  5. data/gherkin_lint.gemspec +3 -3
  6. data/lib/gherkin_lint.rb +8 -13
  7. data/lib/gherkin_lint/linter.rb +39 -34
  8. data/lib/gherkin_lint/linter/avoid_outline_for_single_example.rb +4 -4
  9. data/lib/gherkin_lint/linter/avoid_period.rb +3 -3
  10. data/lib/gherkin_lint/linter/avoid_scripting.rb +4 -4
  11. data/lib/gherkin_lint/linter/background_does_more_than_setup.rb +2 -2
  12. data/lib/gherkin_lint/linter/background_requires_multiple_scenarios.rb +1 -1
  13. data/lib/gherkin_lint/linter/bad_scenario_name.rb +2 -2
  14. data/lib/gherkin_lint/linter/be_declarative.rb +2 -2
  15. data/lib/gherkin_lint/linter/file_name_differs_feature_name.rb +2 -2
  16. data/lib/gherkin_lint/linter/invalid_step_flow.rb +5 -5
  17. data/lib/gherkin_lint/linter/missing_example_name.rb +4 -4
  18. data/lib/gherkin_lint/linter/missing_feature_description.rb +1 -1
  19. data/lib/gherkin_lint/linter/missing_feature_name.rb +1 -1
  20. data/lib/gherkin_lint/linter/missing_scenario_name.rb +1 -1
  21. data/lib/gherkin_lint/linter/missing_test_action.rb +1 -1
  22. data/lib/gherkin_lint/linter/missing_verification.rb +1 -1
  23. data/lib/gherkin_lint/linter/same_tag_for_all_scenarios.rb +12 -12
  24. data/lib/gherkin_lint/linter/too_clumsy.rb +1 -1
  25. data/lib/gherkin_lint/linter/too_long_step.rb +2 -2
  26. data/lib/gherkin_lint/linter/too_many_different_tags.rb +2 -2
  27. data/lib/gherkin_lint/linter/too_many_steps.rb +2 -2
  28. data/lib/gherkin_lint/linter/unique_scenario_names.rb +2 -2
  29. data/lib/gherkin_lint/linter/unknown_variable.rb +13 -8
  30. data/lib/gherkin_lint/linter/unused_variable.rb +12 -11
  31. data/lib/gherkin_lint/linter/use_background.rb +17 -15
  32. data/lib/gherkin_lint/linter/use_outline.rb +5 -5
  33. metadata +21 -33
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5e776cabb83c6f00b485d9e88b7193bfd421ab79
4
+ data.tar.gz: 63e15be6fb1920e3a587b75163af5d18b959f3d3
5
+ SHA512:
6
+ metadata.gz: 03ccf86a4b33104ba1cb5f65d98df1a72a660ebb27a53997be9c38b95a1271ea2ced2c55522e10dbd2a25c57e4d141ebcca647d6ffd1617885b9b6ddf5ae1e65
7
+ data.tar.gz: 31f0d3b395b1e4661d5d0705429c4a057008c719a0fcebffecf68b423e73778279d37d2f77cccdc0f7978787f48005e24dc0a566aa61820d46d5099db71b30fb
data/.rubocop.yml CHANGED
@@ -1,24 +1,30 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2016-02-28 15:30:26 +0100 using RuboCop version 0.37.2.
3
+ # on 2016-08-11 02:27:52 +0200 using RuboCop version 0.42.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
+ # Offense count: 1
10
+ Metrics/AbcSize:
11
+ Max: 16
12
+
9
13
  # Offense count: 1
10
14
  # Configuration parameters: CountComments.
11
15
  Metrics/ClassLength:
12
- Max: 119
16
+ Max: 121
13
17
 
14
- # Offense count: 28
18
+ # Offense count: 33
15
19
  # Configuration parameters: AllowHeredoc, AllowURI, URISchemes.
16
20
  # URISchemes: http, https
17
21
  Metrics/LineLength:
18
- Max: 118
22
+ Max: 116
19
23
 
20
24
  # Offense count: 1
21
25
  # Cop supports --auto-correct.
22
- Performance/Casecmp:
26
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
27
+ # SupportedStyles: predicate, comparison
28
+ Style/NumericPredicate:
23
29
  Exclude:
24
- - 'lib/gherkin_lint/linter/invalid_file_name.rb'
30
+ - 'lib/gherkin_lint/linter/file_name_differs_feature_name.rb'
data/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
  gem 'aruba'
3
3
  gem 'amatch'
4
- gem 'gherkin', '=2.12.2'
4
+ gem 'gherkin', '>=4.0.0'
5
5
  gem 'gherkin_format'
6
6
  gem 'gherkin_language'
7
7
  gem 'rake'
data/Rakefile CHANGED
@@ -11,12 +11,12 @@ end
11
11
 
12
12
  desc 'Publishes the Gem'
13
13
  task :push do
14
- sh 'gem push gherkin_lint-0.3.1.gem'
14
+ sh 'gem push gherkin_lint-0.4.0.gem'
15
15
  end
16
16
 
17
17
  desc 'Checks ruby style'
18
18
  task :rubocop do
19
- # sh 'rubocop'
19
+ sh 'rubocop'
20
20
  end
21
21
 
22
22
  task test: :rubocop
data/gherkin_lint.gemspec CHANGED
@@ -1,14 +1,14 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'gherkin_lint'
3
- s.version = '0.3.1'
4
- s.date = '2016-05-01'
3
+ s.version = '0.4.0'
4
+ s.date = '2016-08-11'
5
5
  s.summary = 'Gherkin Lint'
6
6
  s.description = 'Lint Gherkin Files'
7
7
  s.authors = ['Stefan Rohe']
8
8
  s.homepage = 'http://github.com/funkwerk/gherkin_lint/'
9
9
  s.files = `git ls-files`.split("\n")
10
10
  s.executables = s.files.grep(%r{^bin/}) { |file| File.basename(file) }
11
- s.add_runtime_dependency 'gherkin', ['= 2.12.2']
11
+ s.add_runtime_dependency 'gherkin', ['>= 4.0.0']
12
12
  s.add_runtime_dependency 'term-ansicolor', ['>= 1.3.2']
13
13
  s.add_runtime_dependency 'amatch', ['>= 0.3.0']
14
14
  s.add_runtime_dependency 'engtagger', ['>=0.2.0']
data/lib/gherkin_lint.rb CHANGED
@@ -1,7 +1,6 @@
1
- gem 'gherkin', '=2.12.2'
1
+ gem 'gherkin', '>=4.0.0'
2
2
 
3
- require 'gherkin/formatter/json_formatter'
4
- require 'gherkin/parser/parser'
3
+ require 'gherkin/parser'
5
4
  require 'gherkin_lint/linter/avoid_outline_for_single_example'
6
5
  require 'gherkin_lint/linter/avoid_period'
7
6
  require 'gherkin_lint/linter/avoid_scripting'
@@ -29,7 +28,6 @@ require 'gherkin_lint/linter/unknown_variable'
29
28
  require 'gherkin_lint/linter/unused_variable'
30
29
  require 'gherkin_lint/linter/use_background'
31
30
  require 'gherkin_lint/linter/use_outline'
32
- require 'stringio'
33
31
  require 'multi_json'
34
32
  require 'set'
35
33
 
@@ -102,8 +100,7 @@ module GherkinLint
102
100
  end
103
101
 
104
102
  def parse(file)
105
- content = File.read file
106
- to_json(content, file)
103
+ to_json File.read(file)
107
104
  end
108
105
 
109
106
  def report
@@ -122,13 +119,11 @@ module GherkinLint
122
119
  LINTER.map { |lint| "disable#{lint.new.class.name.split('::').last}" }
123
120
  end
124
121
 
125
- def to_json(input, file = 'generated.feature')
126
- io = StringIO.new
127
- formatter = Gherkin::Formatter::JSONFormatter.new(io)
128
- parser = Gherkin::Parser::Parser.new(formatter, true)
129
- parser.parse(input, file, 0)
130
- formatter.done
131
- MultiJson.load io.string
122
+ def to_json(input)
123
+ parser = Gherkin::Parser.new
124
+ scanner = Gherkin::TokenScanner.new input
125
+
126
+ parser.parse(scanner)
132
127
  end
133
128
 
134
129
  def print(issues)
@@ -13,9 +13,9 @@ module GherkinLint
13
13
 
14
14
  def features
15
15
  @files.each do |file, content|
16
- content.each do |feature|
17
- yield(file, feature)
18
- end
16
+ feature = content[:feature]
17
+
18
+ yield(file, feature)
19
19
  end
20
20
  end
21
21
 
@@ -25,39 +25,40 @@ module GherkinLint
25
25
 
26
26
  def scenarios
27
27
  elements do |file, feature, scenario|
28
- next if scenario['keyword'] == 'Background'
28
+ next if scenario[:type] == :Background
29
29
  yield(file, feature, scenario)
30
30
  end
31
31
  end
32
32
 
33
33
  def filled_scenarios
34
34
  scenarios do |file, feature, scenario|
35
- next unless scenario.include? 'steps'
35
+ next unless scenario.include? :steps
36
36
  yield(file, feature, scenario)
37
37
  end
38
38
  end
39
39
 
40
40
  def steps
41
41
  elements do |file, feature, scenario|
42
- next unless scenario.include? 'steps'
43
- scenario['steps'].each { |step| yield(file, feature, scenario, step) }
42
+ next unless scenario.include? :steps
43
+ scenario[:steps].each { |step| yield(file, feature, scenario, step) }
44
44
  end
45
45
  end
46
46
 
47
47
  def backgrounds
48
48
  elements do |file, feature, scenario|
49
- next unless scenario['keyword'] == 'Background'
49
+ next unless scenario[:type] == :Background
50
50
  yield(file, feature, scenario)
51
51
  end
52
52
  end
53
53
 
54
54
  def elements
55
55
  @files.each do |file, content|
56
- content.each do |feature|
57
- next unless feature.key? 'elements'
58
- feature['elements'].each do |scenario|
59
- yield(file, feature, scenario)
60
- end
56
+ feature = content[:feature]
57
+
58
+ next if feature.nil?
59
+ next unless feature.key? :children
60
+ feature[:children].each do |scenario|
61
+ yield(file, feature, scenario)
61
62
  end
62
63
  end
63
64
  end
@@ -75,7 +76,8 @@ module GherkinLint
75
76
 
76
77
  def filter_tag(data, tag)
77
78
  return data.select { |item| !tag?(item, tag) }.map { |item| filter_tag(item, tag) } if data.class == Array
78
- return data unless data.class == Hash
79
+ return {} if (data.class == Hash) && (data.include? :feature) && tag?(data[:feature], tag)
80
+ return data unless data.respond_to? :each_pair
79
81
  result = {}
80
82
 
81
83
  data.each_pair { |key, value| result[key] = filter_tag(value, tag) }
@@ -84,8 +86,8 @@ module GherkinLint
84
86
 
85
87
  def tag?(data, tag)
86
88
  return false if data.class != Hash
87
- return false unless data.key? 'tags'
88
- data['tags'].map { |item| item['name'] }.include? "@#{tag}"
89
+ return false unless data.include? :tags
90
+ data[:tags].map { |item| item[:name] }.include? "@#{tag}"
89
91
  end
90
92
 
91
93
  def suppress_tags(data, tags)
@@ -94,7 +96,7 @@ module GherkinLint
94
96
  result = {}
95
97
 
96
98
  data.each_pair do |key, value|
97
- value = suppress(value, tags) if key == 'tags'
99
+ value = suppress(value, tags) if key == :tags
98
100
 
99
101
  result[key] = suppress_tags(value, tags)
100
102
  end
@@ -102,7 +104,7 @@ module GherkinLint
102
104
  end
103
105
 
104
106
  def suppress(data, tags)
105
- data.select { |item| !tags.map { |tag| "@#{tag}" }.include? item['name'] }
107
+ data.select { |item| !tags.map { |tag| "@#{tag}" }.include? item[:name] }
106
108
  end
107
109
 
108
110
  def lint
@@ -110,17 +112,17 @@ module GherkinLint
110
112
  end
111
113
 
112
114
  def reference(file, feature = nil, scenario = nil, step = nil)
113
- return file if feature.nil? || feature['name'].empty?
114
- result = "#{file} (#{line(feature, scenario, step)}): #{feature['name']}"
115
- result += ".#{scenario['name']}" unless scenario.nil? || scenario['name'].empty?
116
- result += " step: #{step['name']}" unless step.nil?
115
+ return file if feature.nil? || feature[:name].empty?
116
+ result = "#{file} (#{line(feature, scenario, step)}): #{feature[:name]}"
117
+ result += ".#{scenario[:name]}" unless scenario.nil? || scenario[:name].empty?
118
+ result += " step: #{step[:text]}" unless step.nil?
117
119
  result
118
120
  end
119
121
 
120
122
  def line(feature, scenario, step)
121
- line = feature.nil? ? nil : feature['line']
122
- line = scenario['line'] unless scenario.nil?
123
- line = step['line'] unless step.nil?
123
+ line = feature.nil? ? nil : feature[:location][:line]
124
+ line = scenario[:location][:line] unless scenario.nil?
125
+ line = step[:location][:line] unless step.nil?
124
126
  line
125
127
  end
126
128
 
@@ -133,19 +135,22 @@ module GherkinLint
133
135
  end
134
136
 
135
137
  def gather_tags(element)
136
- return [] unless element.include? 'tags'
137
- element['tags'].map { |tag| tag['name'][1..-1] }
138
+ return [] unless element.include? :tags
139
+ element[:tags].map { |tag| tag[:name][1..-1] }
138
140
  end
139
141
 
140
142
  def render_step(step)
141
- value = "#{step['keyword']}#{step['name']}"
142
- value += "\n#{step['doc_string']['value']}" if step.include? 'doc_string'
143
- if step.include? 'rows'
144
- value += step['rows'].map do |row|
145
- row['cells'].join '|'
146
- end.join "|\n"
147
- end
143
+ value = "#{step[:keyword]}#{step[:text]}"
144
+ value += render_step_argument step[:argument] if step.include? :argument
148
145
  value
149
146
  end
147
+
148
+ def render_step_argument(argument)
149
+ return "\n#{argument[:content]}" if argument[:type] == :DocString
150
+ result = argument[:rows].map do |row|
151
+ "|#{row[:cells].map { |cell| cell[:value] }.join '|'}|"
152
+ end.join "\n"
153
+ "\n#{result}"
154
+ end
150
155
  end
151
156
  end
@@ -5,11 +5,11 @@ module GherkinLint
5
5
  class AvoidOutlineForSingleExample < Linter
6
6
  def lint
7
7
  scenarios do |file, feature, scenario|
8
- next unless scenario['keyword'] == 'Scenario Outline'
8
+ next unless scenario[:type] == :ScenarioOutline
9
9
 
10
- next unless scenario.key? 'examples'
11
- next if scenario['examples'].length > 1
12
- next if scenario['examples'].first['rows'].length > 2
10
+ next unless scenario.key? :examples
11
+ next if scenario[:examples].length > 1
12
+ next if scenario[:examples].first[:tableBody].length > 1
13
13
 
14
14
  references = [reference(file, feature, scenario)]
15
15
  add_error(references, 'Better write a scenario')
@@ -5,11 +5,11 @@ module GherkinLint
5
5
  class AvoidPeriod < Linter
6
6
  def lint
7
7
  scenarios do |file, feature, scenario|
8
- next unless scenario.key? 'steps'
8
+ next unless scenario.key? :steps
9
9
 
10
- scenario['steps'].each do |step|
10
+ scenario[:steps].each do |step|
11
11
  references = [reference(file, feature, scenario, step)]
12
- add_error(references) if step['name'].strip.end_with? '.'
12
+ add_error(references) if step[:text].strip.end_with? '.'
13
13
  end
14
14
  end
15
15
  end
@@ -5,7 +5,7 @@ module GherkinLint
5
5
  class AvoidScripting < Linter
6
6
  def lint
7
7
  filled_scenarios do |file, feature, scenario|
8
- steps = filter_when_steps scenario['steps']
8
+ steps = filter_when_steps scenario[:steps]
9
9
 
10
10
  next if steps.length <= 1
11
11
  references = [reference(file, feature, scenario)]
@@ -14,9 +14,9 @@ module GherkinLint
14
14
  end
15
15
 
16
16
  def filter_when_steps(steps)
17
- steps = steps.drop_while { |step| step['keyword'] != 'When ' }
18
- steps = steps.reverse.drop_while { |step| step['keyword'] != 'Then ' }.reverse
19
- steps.select { |step| step['keyword'] != 'Then ' }
17
+ steps = steps.drop_while { |step| step[:keyword] != 'When ' }
18
+ steps = steps.reverse.drop_while { |step| step[:keyword] != 'Then ' }.reverse
19
+ steps.select { |step| step[:keyword] != 'Then ' }
20
20
  end
21
21
  end
22
22
  end
@@ -5,8 +5,8 @@ module GherkinLint
5
5
  class BackgroundDoesMoreThanSetup < Linter
6
6
  def lint
7
7
  backgrounds do |file, feature, background|
8
- next unless background.key? 'steps'
9
- invalid_steps = background['steps'].select { |step| step['keyword'] == 'When ' || step['keyword'] == 'Then ' }
8
+ next unless background.key? :steps
9
+ invalid_steps = background[:steps].select { |step| step[:keyword] == 'When ' || step[:keyword] == 'Then ' }
10
10
  next if invalid_steps.empty?
11
11
  references = [reference(file, feature, background, invalid_steps[0])]
12
12
  add_error(references, 'Just Given Steps allowed')
@@ -5,7 +5,7 @@ module GherkinLint
5
5
  class BackgroundRequiresMultipleScenarios < Linter
6
6
  def lint
7
7
  backgrounds do |file, feature, background|
8
- scenarios = feature['elements'].select { |element| element['keyword'] != 'Background' }
8
+ scenarios = feature[:children].select { |element| element[:type] != :Background }
9
9
  next if scenarios.length >= 2
10
10
 
11
11
  references = [reference(file, feature, background)]
@@ -5,12 +5,12 @@ module GherkinLint
5
5
  class BadScenarioName < Linter
6
6
  def lint
7
7
  scenarios do |file, feature, scenario|
8
- next if scenario['name'].empty?
8
+ next if scenario[:name].empty?
9
9
  references = [reference(file, feature, scenario)]
10
10
  description = 'Prefer to rely just on Given and When steps when name your scenario to keep it stable'
11
11
  bad_words = %w(test verif check)
12
12
  bad_words.each do |bad_word|
13
- add_error(references, description) if scenario['name'].downcase.include? bad_word
13
+ add_error(references, description) if scenario[:name].downcase.include? bad_word
14
14
  end
15
15
  end
16
16
  end
@@ -10,7 +10,7 @@ module GherkinLint
10
10
 
11
11
  def lint
12
12
  filled_scenarios do |file, feature, scenario|
13
- scenario['steps'].each do |step|
13
+ scenario[:steps].each do |step|
14
14
  references = [reference(file, feature, scenario, step)]
15
15
  add_warning(references, 'no verb') unless verb? step
16
16
  end
@@ -18,7 +18,7 @@ module GherkinLint
18
18
  end
19
19
 
20
20
  def verb?(step)
21
- tagged = tagger.add_tags step['name']
21
+ tagged = tagger.add_tags step[:text]
22
22
  step_verbs = verbs tagged
23
23
 
24
24
  !step_verbs.empty?
@@ -5,9 +5,9 @@ module GherkinLint
5
5
  class FileNameDiffersFeatureName < Linter
6
6
  def lint
7
7
  features do |file, feature|
8
- next unless feature.include? 'name'
8
+ next unless feature.include? :name
9
9
  expected_feature_name = title_case file
10
- next if feature['name'].casecmp(expected_feature_name) == 0
10
+ next if feature[:name].casecmp(expected_feature_name) == 0
11
11
  references = [reference(file, feature)]
12
12
  add_error(references, "Feature name should be '#{expected_feature_name}'")
13
13
  end
@@ -5,7 +5,7 @@ module GherkinLint
5
5
  class InvalidStepFlow < Linter
6
6
  def lint
7
7
  filled_scenarios do |file, feature, scenario|
8
- steps = scenario['steps'].select { |step| step['keyword'] != 'And ' && step['keyword'] != 'But ' }
8
+ steps = scenario[:steps].select { |step| step[:keyword] != 'And ' && step[:keyword] != 'But ' }
9
9
  last_step_is_an_action(file, feature, scenario, steps)
10
10
  given_after_non_given(file, feature, scenario, steps)
11
11
  verification_before_action(file, feature, scenario, steps)
@@ -14,7 +14,7 @@ module GherkinLint
14
14
 
15
15
  def last_step_is_an_action(file, feature, scenario, steps)
16
16
  references = [reference(file, feature, scenario, steps.last)]
17
- add_error(references, 'Last step is an action') if steps.last['keyword'] == 'When '
17
+ add_error(references, 'Last step is an action') if steps.last[:keyword] == 'When '
18
18
  end
19
19
 
20
20
  def given_after_non_given(file, feature, scenario, steps)
@@ -22,16 +22,16 @@ module GherkinLint
22
22
  steps.each do |step|
23
23
  references = [reference(file, feature, scenario, step)]
24
24
  description = 'Given after Action or Verification'
25
- add_error(references, description) if step['keyword'] == 'Given ' && last_step['keyword'] != 'Given '
25
+ add_error(references, description) if step[:keyword] == 'Given ' && last_step[:keyword] != 'Given '
26
26
  last_step = step
27
27
  end
28
28
  end
29
29
 
30
30
  def verification_before_action(file, feature, scenario, steps)
31
31
  steps.each do |step|
32
- break if step['keyword'] == 'When '
32
+ break if step[:keyword] == 'When '
33
33
  references = [reference(file, feature, scenario, step)]
34
- add_error(references, 'Missing Action') if step['keyword'] == 'Then '
34
+ add_error(references, 'Missing Action') if step[:keyword] == 'Then '
35
35
  end
36
36
  end
37
37
  end
@@ -5,10 +5,10 @@ module GherkinLint
5
5
  class MissingExampleName < Linter
6
6
  def lint
7
7
  scenarios do |file, feature, scenario|
8
- next unless scenario.key? 'examples'
9
- next unless scenario['examples'].length > 1
10
- scenario['examples'].each do |example|
11
- name = example.key?('name') ? example['name'].strip : ''
8
+ next unless scenario.key? :examples
9
+ next unless scenario[:examples].length > 1
10
+ scenario[:examples].each do |example|
11
+ name = example.key?(:name) ? example[:name].strip : ''
12
12
  next unless name.empty?
13
13
  references = [reference(file, feature, scenario)]
14
14
  add_error(references, 'No Example Name')
@@ -5,7 +5,7 @@ module GherkinLint
5
5
  class MissingFeatureDescription < Linter
6
6
  def lint
7
7
  features do |file, feature|
8
- name = feature.key?('description') ? feature['description'].strip : ''
8
+ name = feature.key?(:description) ? feature[:description].strip : ''
9
9
  next unless name.empty?
10
10
  references = [reference(file, feature)]
11
11
  add_error(references, 'Favor a user story as description')
@@ -5,7 +5,7 @@ module GherkinLint
5
5
  class MissingFeatureName < Linter
6
6
  def lint
7
7
  features do |file, feature|
8
- name = feature.key?('name') ? feature['name'].strip : ''
8
+ name = feature.key?(:name) ? feature[:name].strip : ''
9
9
  next unless name.empty?
10
10
  references = [reference(file, feature)]
11
11
  add_error(references, 'No Feature Name')
@@ -5,7 +5,7 @@ module GherkinLint
5
5
  class MissingScenarioName < Linter
6
6
  def lint
7
7
  scenarios do |file, feature, scenario|
8
- name = scenario.key?('name') ? scenario['name'].strip : ''
8
+ name = scenario.key?(:name) ? scenario[:name].strip : ''
9
9
  references = [reference(file, feature, scenario)]
10
10
  next unless name.empty?
11
11
  add_error(references, 'No Scenario Name')
@@ -5,7 +5,7 @@ module GherkinLint
5
5
  class MissingTestAction < Linter
6
6
  def lint
7
7
  filled_scenarios do |file, feature, scenario|
8
- when_steps = scenario['steps'].select { |step| step['keyword'] == 'When ' }
8
+ when_steps = scenario[:steps].select { |step| step[:keyword] == 'When ' }
9
9
  next unless when_steps.empty?
10
10
  references = [reference(file, feature, scenario)]
11
11
  add_error(references, 'No \'When\'-Step')
@@ -5,7 +5,7 @@ module GherkinLint
5
5
  class MissingVerification < Linter
6
6
  def lint
7
7
  filled_scenarios do |file, feature, scenario|
8
- then_steps = scenario['steps'].select { |step| step['keyword'] == 'Then ' }
8
+ then_steps = scenario[:steps].select { |step| step[:keyword] == 'Then ' }
9
9
  next unless then_steps.empty?
10
10
  references = [reference(file, feature, scenario)]
11
11
  add_error(references, 'No verification step')
@@ -5,7 +5,7 @@ module GherkinLint
5
5
  class SameTagForAllScenarios < Linter
6
6
  def lint
7
7
  features do |file, feature|
8
- next unless feature.include? 'elements'
8
+ next unless feature.include? :children
9
9
 
10
10
  lint_scenarios file, feature
11
11
  lint_examples file, feature
@@ -16,7 +16,7 @@ module GherkinLint
16
16
  tags = gather_same_tags feature
17
17
  return if tags.nil?
18
18
  return if tags.empty?
19
- return unless feature['elements'].length > 1
19
+ return unless feature[:children].length > 1
20
20
  references = [reference(file, feature)]
21
21
  tags.each do |tag|
22
22
  next if tag == '@skip'
@@ -26,10 +26,10 @@ module GherkinLint
26
26
  end
27
27
 
28
28
  def lint_examples(file, feature)
29
- feature['elements'].each do |scenario|
29
+ feature[:children].each do |scenario|
30
30
  tags = gather_same_tags_for_outline scenario
31
31
  next if tags.nil? || tags.empty?
32
- next unless scenario['examples'].length > 1
32
+ next unless scenario[:examples].length > 1
33
33
  references = [reference(file, feature, scenario)]
34
34
  tags.each do |tag|
35
35
  next if tag == '@skip'
@@ -41,10 +41,10 @@ module GherkinLint
41
41
 
42
42
  def gather_same_tags(feature)
43
43
  result = nil
44
- feature['elements'].each do |scenario|
45
- next if scenario['keyword'] == 'Background'
46
- return nil unless scenario.include? 'tags'
47
- tags = scenario['tags'].map { |tag| tag['name'] }
44
+ feature[:children].each do |scenario|
45
+ next if scenario[:type] == :Background
46
+ return nil unless scenario.include? :tags
47
+ tags = scenario[:tags].map { |tag| tag[:name] }
48
48
  result = tags if result.nil?
49
49
  result &= tags
50
50
  end
@@ -53,10 +53,10 @@ module GherkinLint
53
53
 
54
54
  def gather_same_tags_for_outline(scenario)
55
55
  result = nil
56
- return result unless scenario.include? 'examples'
57
- scenario['examples'].each do |example|
58
- return nil unless example.include? 'tags'
59
- tags = example['tags'].map { |tag| tag['name'] }
56
+ return result unless scenario.include? :examples
57
+ scenario[:examples].each do |example|
58
+ return nil unless example.include? :tags
59
+ tags = example[:tags].map { |tag| tag[:name] }
60
60
  result = tags if result.nil?
61
61
  result &= tags
62
62
  end
@@ -5,7 +5,7 @@ module GherkinLint
5
5
  class TooClumsy < Linter
6
6
  def lint
7
7
  filled_scenarios do |file, feature, scenario|
8
- characters = scenario['steps'].map { |step| step['name'].length }.inject(0, :+)
8
+ characters = scenario[:steps].map { |step| step[:text].length }.inject(0, :+)
9
9
  next if characters < 400
10
10
  references = [reference(file, feature, scenario)]
11
11
  add_error(references, "Used #{characters} Characters")
@@ -5,9 +5,9 @@ module GherkinLint
5
5
  class TooLongStep < Linter
6
6
  def lint
7
7
  steps do |file, feature, scenario, step|
8
- next if step['name'].length < 80
8
+ next if step[:text].length < 80
9
9
  references = [reference(file, feature, scenario, step)]
10
- add_error(references, "Used #{step['name'].length} characters")
10
+ add_error(references, "Used #{step[:text].length} characters")
11
11
  end
12
12
  end
13
13
  end
@@ -31,8 +31,8 @@ module GherkinLint
31
31
  end
32
32
 
33
33
  def tags_for_feature(feature)
34
- return [] unless feature.include? 'elements'
35
- gather_tags(feature) + feature['elements'].map { |scenario| gather_tags(scenario) }.flatten
34
+ return [] unless feature.include? :children
35
+ gather_tags(feature) + feature[:children].map { |scenario| gather_tags(scenario) }.flatten
36
36
  end
37
37
  end
38
38
  end
@@ -5,9 +5,9 @@ module GherkinLint
5
5
  class TooManySteps < Linter
6
6
  def lint
7
7
  filled_scenarios do |file, feature, scenario|
8
- next if scenario['steps'].length < 10
8
+ next if scenario[:steps].length < 10
9
9
  references = [reference(file, feature, scenario)]
10
- add_error(references, "Used #{scenario['steps'].length} Steps")
10
+ add_error(references, "Used #{scenario[:steps].length} Steps")
11
11
  end
12
12
  end
13
13
  end
@@ -6,8 +6,8 @@ module GherkinLint
6
6
  def lint
7
7
  references_by_name = Hash.new []
8
8
  scenarios do |file, feature, scenario|
9
- next unless scenario.key? 'name'
10
- scenario_name = "#{feature['name']}.#{scenario['name']}"
9
+ next unless scenario.key? :name
10
+ scenario_name = "#{feature[:name]}.#{scenario[:name]}"
11
11
  references_by_name[scenario_name] = references_by_name[scenario_name] + [reference(file, feature, scenario)]
12
12
  end
13
13
  references_by_name.each do |name, references|
@@ -6,7 +6,7 @@ module GherkinLint
6
6
  def lint
7
7
  filled_scenarios do |file, feature, scenario|
8
8
  known_vars = Set.new known_variables scenario
9
- scenario['steps'].each do |step|
9
+ scenario[:steps].each do |step|
10
10
  step_vars(step).each do |used_var|
11
11
  next if known_vars.include? used_var
12
12
  references = [reference(file, feature, scenario)]
@@ -17,10 +17,15 @@ module GherkinLint
17
17
  end
18
18
 
19
19
  def step_vars(step)
20
- vars = gather_vars step['name']
21
- vars += gather_vars step['doc_string']['value'] if step.key? 'doc_string'
22
- vars + (step['rows'] || []).map do |row|
23
- row['cells'].map { |value| gather_vars value }.flatten
20
+ vars = gather_vars step[:text]
21
+ return vars unless step.include? :argument
22
+ vars + gather_vars_from_argument(step[:argument])
23
+ end
24
+
25
+ def gather_vars_from_argument(argument)
26
+ return gather_vars argument[:content] if argument[:type] == :DocString
27
+ (argument[:rows] || []).map do |row|
28
+ row[:cells].map { |value| gather_vars value[:value] }.flatten
24
29
  end.flatten
25
30
  end
26
31
 
@@ -29,9 +34,9 @@ module GherkinLint
29
34
  end
30
35
 
31
36
  def known_variables(scenario)
32
- (scenario['examples'] || []).map do |example|
33
- next unless example.key? 'rows'
34
- example['rows'].first['cells'].map(&:strip)
37
+ (scenario[:examples] || []).map do |example|
38
+ next unless example.key? :tableHeader
39
+ example[:tableHeader][:cells].map { |cell| cell[:value].strip }
35
40
  end.flatten
36
41
  end
37
42
  end
@@ -5,10 +5,10 @@ module GherkinLint
5
5
  class UnusedVariable < Linter
6
6
  def lint
7
7
  scenarios do |file, feature, scenario|
8
- next unless scenario.key? 'examples'
9
- scenario['examples'].each do |example|
10
- next unless example.key? 'rows'
11
- example['rows'].first['cells'].each do |variable|
8
+ next unless scenario.key? :examples
9
+ scenario[:examples].each do |example|
10
+ next unless example.key? :tableHeader
11
+ example[:tableHeader][:cells].map { |cell| cell[:value] }.each do |variable|
12
12
  references = [reference(file, feature, scenario)]
13
13
  add_error(references, "'<#{variable}>' is unused") unless used?(variable, scenario)
14
14
  end
@@ -18,9 +18,10 @@ module GherkinLint
18
18
 
19
19
  def used?(variable, scenario)
20
20
  variable = "<#{variable}>"
21
- return false unless scenario.key? 'steps'
22
- scenario['steps'].each do |step|
23
- return true if step['name'].include? variable
21
+ return false unless scenario.key? :steps
22
+ scenario[:steps].each do |step|
23
+ return true if step[:text].include? variable
24
+ next unless step.include? :argument
24
25
  return true if used_in_docstring?(variable, step)
25
26
  return true if used_in_table?(variable, step)
26
27
  end
@@ -28,13 +29,13 @@ module GherkinLint
28
29
  end
29
30
 
30
31
  def used_in_docstring?(variable, step)
31
- step.key?('doc_string') && step['doc_string']['value'].include?(variable)
32
+ step[:argument][:type] == :DocString && step[:argument][:content].include?(variable)
32
33
  end
33
34
 
34
35
  def used_in_table?(variable, step)
35
- return false unless step.key? 'rows'
36
- step['rows'].each do |row|
37
- row['cells'].each { |value| return true if value.include?(variable) }
36
+ return false unless step[:argument][:type] == :DataTable
37
+ step[:argument][:rows].each do |row|
38
+ row[:cells].each { |value| return true if value[:value].include?(variable) }
38
39
  end
39
40
  false
40
41
  end
@@ -17,20 +17,20 @@ module GherkinLint
17
17
 
18
18
  def scenarios_with_steps(feature)
19
19
  scenarios = 0
20
- return 0 unless feature.key? 'elements'
21
- feature['elements'].each do |scenario|
22
- next unless scenario.include? 'steps'
20
+ return 0 unless feature.key? :children
21
+ feature[:children].each do |scenario|
22
+ next unless scenario.include? :steps
23
23
  scenarios += 1
24
24
  end
25
25
  scenarios
26
26
  end
27
27
 
28
28
  def gather_givens(feature)
29
- return unless feature.include? 'elements'
29
+ return unless feature.include? :children
30
30
  has_non_given_step = false
31
- feature['elements'].each do |scenario|
32
- next unless scenario.include? 'steps'
33
- has_non_given_step = true unless scenario['steps'].first['keyword'] == 'Given '
31
+ feature[:children].each do |scenario|
32
+ next unless scenario.include? :steps
33
+ has_non_given_step = true unless scenario[:steps].first[:keyword] == 'Given '
34
34
  end
35
35
  return if has_non_given_step
36
36
 
@@ -40,11 +40,11 @@ module GherkinLint
40
40
  end
41
41
 
42
42
  def expanded_steps(feature)
43
- feature['elements'].each do |scenario|
44
- next unless scenario['keyword'] != 'Background'
45
- next unless scenario.include? 'steps'
46
- prototypes = [render_step(scenario['steps'].first)]
47
- prototypes = expand_examples(scenario['examples'], prototypes) if scenario.key? 'examples'
43
+ feature[:children].each do |scenario|
44
+ next unless scenario[:type] != :Background
45
+ next unless scenario.include? :steps
46
+ prototypes = [render_step(scenario[:steps].first)]
47
+ prototypes = expand_examples(scenario[:examples], prototypes) if scenario.key? :examples
48
48
  prototypes.each { |prototype| yield prototype }
49
49
  end
50
50
  end
@@ -58,10 +58,12 @@ module GherkinLint
58
58
 
59
59
  def expand_outlines(sentence, example)
60
60
  result = []
61
- headers = example['rows'][0]['cells']
62
- example['rows'].slice(1, example['rows'].length).each do |row|
61
+ headers = example[:tableHeader][:cells].map { |cell| cell[:value] }
62
+ example[:tableBody].each do |row| # .slice(1, example[:tableBody].length).each do |row|
63
63
  modified_sentence = sentence.dup
64
- headers.zip(row['cells']).map { |key, value| modified_sentence.gsub!("<#{key}>", value) }
64
+ headers.zip(row[:cells].map { |cell| cell[:value] }).map do |key, value|
65
+ modified_sentence.gsub!("<#{key}>", value)
66
+ end
65
67
  result.push modified_sentence
66
68
  end
67
69
  result
@@ -28,10 +28,10 @@ module GherkinLint
28
28
 
29
29
  def gather_scenarios(file, feature)
30
30
  scenarios = []
31
- return scenarios unless feature.include? 'elements'
32
- feature['elements'].each do |scenario|
33
- next unless scenario['keyword'] == 'Scenario'
34
- next unless scenario.include? 'steps'
31
+ return scenarios unless feature.include? :children
32
+ feature[:children].each do |scenario|
33
+ next unless scenario[:type] == :Scenario
34
+ next unless scenario.include? :steps
35
35
  scenarios.push generate_reference(file, feature, scenario)
36
36
  end
37
37
  scenarios
@@ -40,7 +40,7 @@ module GherkinLint
40
40
  def generate_reference(file, feature, scenario)
41
41
  reference = {}
42
42
  reference[:reference] = reference(file, feature, scenario)
43
- reference[:text] = scenario['steps'].map { |step| render_step(step) }.join ' '
43
+ reference[:text] = scenario[:steps].map { |step| render_step(step) }.join ' '
44
44
  reference
45
45
  end
46
46
  end
metadata CHANGED
@@ -1,94 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gherkin_lint
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
5
- prerelease:
4
+ version: 0.4.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Stefan Rohe
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2016-05-01 00:00:00.000000000 Z
11
+ date: 2016-08-11 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: gherkin
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - '='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
- version: 2.12.2
19
+ version: 4.0.0
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - '='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
- version: 2.12.2
26
+ version: 4.0.0
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: term-ansicolor
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
33
  version: 1.3.2
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - ">="
44
39
  - !ruby/object:Gem::Version
45
40
  version: 1.3.2
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: amatch
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - ">="
52
46
  - !ruby/object:Gem::Version
53
47
  version: 0.3.0
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - ">="
60
53
  - !ruby/object:Gem::Version
61
54
  version: 0.3.0
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: engtagger
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - ">="
68
60
  - !ruby/object:Gem::Version
69
61
  version: 0.2.0
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - ">="
76
67
  - !ruby/object:Gem::Version
77
68
  version: 0.2.0
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: aruba
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - ">="
84
74
  - !ruby/object:Gem::Version
85
75
  version: 0.6.2
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - ">="
92
81
  - !ruby/object:Gem::Version
93
82
  version: 0.6.2
94
83
  description: Lint Gherkin Files
@@ -98,8 +87,8 @@ executables:
98
87
  extensions: []
99
88
  extra_rdoc_files: []
100
89
  files:
101
- - .rubocop.yml
102
- - .travis.yml
90
+ - ".rubocop.yml"
91
+ - ".travis.yml"
103
92
  - Dockerfile
104
93
  - Gemfile
105
94
  - Guardfile
@@ -169,26 +158,25 @@ files:
169
158
  - lib/gherkin_lint/linter/use_outline.rb
170
159
  homepage: http://github.com/funkwerk/gherkin_lint/
171
160
  licenses: []
161
+ metadata: {}
172
162
  post_install_message:
173
163
  rdoc_options: []
174
164
  require_paths:
175
165
  - lib
176
166
  required_ruby_version: !ruby/object:Gem::Requirement
177
- none: false
178
167
  requirements:
179
- - - ! '>='
168
+ - - ">="
180
169
  - !ruby/object:Gem::Version
181
170
  version: '0'
182
171
  required_rubygems_version: !ruby/object:Gem::Requirement
183
- none: false
184
172
  requirements:
185
- - - ! '>='
173
+ - - ">="
186
174
  - !ruby/object:Gem::Version
187
175
  version: '0'
188
176
  requirements: []
189
177
  rubyforge_project:
190
- rubygems_version: 1.8.23
178
+ rubygems_version: 2.2.2
191
179
  signing_key:
192
- specification_version: 3
180
+ specification_version: 4
193
181
  summary: Gherkin Lint
194
182
  test_files: []