cuke_cataloger 1.6.0 → 2.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 +27 -3
- data/LICENSE.txt +1 -1
- data/README.md +11 -11
- data/cuke_cataloger.gemspec +33 -13
- data/exe/cuke_cataloger +53 -0
- data/lib/cuke_cataloger/formatters/text_report_formatter.rb +7 -2
- data/lib/cuke_cataloger/rake_tasks.rb +9 -4
- data/lib/cuke_cataloger/unique_test_case_tagger.rb +152 -147
- data/lib/cuke_cataloger/version.rb +1 -1
- data/lib/cuke_cataloger.rb +0 -1
- metadata +90 -51
- data/.cucumberproignore +0 -1
- data/.gitignore +0 -18
- data/.simplecov +0 -7
- data/.travis.yml +0 -67
- data/Gemfile +0 -41
- data/Rakefile +0 -70
- data/appveyor.yml +0 -188
- data/bin/cuke_cataloger +0 -49
- data/testing/cucumber/step_definitions/action_steps.rb +0 -64
- data/testing/cucumber/step_definitions/setup_steps.rb +0 -76
- data/testing/cucumber/step_definitions/verification_steps.rb +0 -211
- data/testing/cucumber/support/env.rb +0 -40
- data/testing/file_helper.rb +0 -42
- data/testing/fixtures/Rakefile +0 -19
- data/testing/fixtures/tests/foo.feature +0 -11
- data/testing/gemfiles/cql1.gemfile +0 -40
- data/testing/gemfiles/cuke_modeler0.gemfile +0 -35
- data/testing/gemfiles/cuke_modeler1.gemfile +0 -35
- data/testing/gemfiles/cuke_modeler2.gemfile +0 -35
- data/testing/gemfiles/cuke_modeler3.gemfile +0 -9
- data/testing/gemfiles/rake10.gemfile +0 -38
- data/testing/gemfiles/rake11.gemfile +0 -30
- data/testing/gemfiles/rake12.gemfile +0 -35
- data/testing/gemfiles/rake13.gemfile +0 -8
- data/testing/gemfiles/thor0.gemfile +0 -39
- data/testing/gemfiles/thor1.gemfile +0 -11
- data/testing/rspec/spec/cuke_cataloger_spec.rb +0 -22
- data/testing/rspec/spec/spec_helper.rb +0 -23
- data/testing/rspec/spec/unique_test_case_tagger_integration_spec.rb +0 -295
- data/testing/rspec/spec/unique_test_case_tagger_unit_spec.rb +0 -81
- data/todo.txt +0 -5
@@ -1,14 +1,15 @@
|
|
1
|
+
# TODO: have better testing so that this can be safely refactored
|
2
|
+
# rubocop:disable Metrics/ClassLength, Metrics/AbcSize, Metrics/MethodLength
|
1
3
|
module CukeCataloger
|
2
4
|
|
3
5
|
# A tagger that handles test case cataloging.
|
4
|
-
|
5
6
|
class UniqueTestCaseTagger
|
6
7
|
|
7
8
|
# The pattern of a sub id
|
8
|
-
SUB_ID_PATTERN = /^\d+\-\d+$/
|
9
|
+
SUB_ID_PATTERN = /^\d+\-\d+$/ # Not a part of the public API. Subject to change at any time.
|
9
10
|
|
10
11
|
# The pattern of a sub id, with id capture
|
11
|
-
SUB_ID_MATCH_PATTERN = /^\d+\-(\d+)$/
|
12
|
+
SUB_ID_MATCH_PATTERN = /^\d+\-(\d+)$/ # Not a part of the public API. Subject to change at any time.
|
12
13
|
|
13
14
|
|
14
15
|
# Where the id tag should be placed, relative to the other tags on the test
|
@@ -21,15 +22,18 @@ module CukeCataloger
|
|
21
22
|
end
|
22
23
|
|
23
24
|
# Adds id tags based on *tag_prefix* to the tests found in *feature_directory*
|
24
|
-
def tag_tests(feature_directory, tag_prefix = '@test_case_', explicit_indexes = {}, tag_rows = true, id_column_name = 'test_case_id')
|
25
|
-
warn(
|
25
|
+
def tag_tests(feature_directory, tag_prefix = '@test_case_', explicit_indexes = {}, tag_rows = true, id_column_name = 'test_case_id') # rubocop:disable Metrics/LineLength
|
26
|
+
warn('This script will potentially rewrite all of your feature files. Please be patient and remember to tip your source control system.') # rubocop:disable Metrics/LineLength
|
26
27
|
|
27
28
|
@known_id_tags = {}
|
28
29
|
|
29
|
-
|
30
|
-
|
30
|
+
configure_id_tag(tag_prefix)
|
31
|
+
configure_test_suite_model(feature_directory)
|
31
32
|
|
32
|
-
@start_indexes = merge_indexes(default_start_indexes(determine_known_ids(feature_directory,
|
33
|
+
@start_indexes = merge_indexes(default_start_indexes(determine_known_ids(feature_directory,
|
34
|
+
tag_prefix,
|
35
|
+
id_column_name)),
|
36
|
+
explicit_indexes)
|
33
37
|
@next_index = @start_indexes[:primary]
|
34
38
|
|
35
39
|
# Analysis and output
|
@@ -40,7 +44,7 @@ module CukeCataloger
|
|
40
44
|
when test.is_a?(CukeModeler::Outline)
|
41
45
|
process_outline(test, tag_rows, id_column_name)
|
42
46
|
else
|
43
|
-
raise("Unknown test type: #{test.class
|
47
|
+
raise("Unknown test type: #{test.class}")
|
44
48
|
end
|
45
49
|
end
|
46
50
|
end
|
@@ -50,19 +54,19 @@ module CukeCataloger
|
|
50
54
|
@results = []
|
51
55
|
@known_id_tags = {}
|
52
56
|
|
53
|
-
|
54
|
-
|
57
|
+
configure_id_tag(tag_prefix)
|
58
|
+
configure_test_suite_model(feature_directory)
|
55
59
|
|
56
60
|
@tests.each do |test|
|
57
|
-
add_to_results(test) if
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
61
|
+
add_to_results(test) if id_tag?(test)
|
62
|
+
|
63
|
+
next unless test.is_a?(CukeModeler::Outline)
|
64
|
+
|
65
|
+
test.examples.each do |example|
|
66
|
+
next unless id_parameter?(example, id_column_name)
|
67
|
+
|
68
|
+
example_rows_for(example).each do |row|
|
69
|
+
add_to_results(row) if row_id?(row, id_column_name)
|
66
70
|
end
|
67
71
|
end
|
68
72
|
end
|
@@ -71,12 +75,12 @@ module CukeCataloger
|
|
71
75
|
end
|
72
76
|
|
73
77
|
# Checks for cataloging problems in *feature_directory* based on *tag_prefix*
|
74
|
-
def validate_test_ids(feature_directory, tag_prefix = '@test_case_', tag_rows = true, id_column_name = 'test_case_id')
|
78
|
+
def validate_test_ids(feature_directory, tag_prefix = '@test_case_', tag_rows = true, id_column_name = 'test_case_id') # rubocop:disable Metrics/LineLength
|
75
79
|
@results = []
|
76
80
|
@known_id_tags = {}
|
77
81
|
|
78
|
-
|
79
|
-
|
82
|
+
configure_id_tag(tag_prefix)
|
83
|
+
configure_test_suite_model(feature_directory)
|
80
84
|
|
81
85
|
@features.each { |feature| validate_feature(feature) }
|
82
86
|
@tests.each { |test| validate_test(test, tag_rows, id_column_name) }
|
@@ -88,7 +92,8 @@ module CukeCataloger
|
|
88
92
|
def determine_known_ids(feature_directory, tag_prefix = '@test_case_', id_column_name = 'test_case_id')
|
89
93
|
known_ids = []
|
90
94
|
|
91
|
-
found_tagged_objects = scan_for_tagged_tests(feature_directory, tag_prefix, id_column_name)
|
95
|
+
found_tagged_objects = scan_for_tagged_tests(feature_directory, tag_prefix, id_column_name)
|
96
|
+
.collect { |result| result[:object] }
|
92
97
|
|
93
98
|
found_tagged_objects.each do |element|
|
94
99
|
if element.is_a?(CukeModeler::Row)
|
@@ -106,26 +111,40 @@ module CukeCataloger
|
|
106
111
|
private
|
107
112
|
|
108
113
|
|
109
|
-
def
|
110
|
-
# todo - should include the '@' in this or anchor the pattern to the beginning of the tag
|
114
|
+
def configure_id_tag(tag_prefix)
|
111
115
|
@tag_prefix = tag_prefix
|
112
|
-
#
|
113
|
-
@tag_pattern = Regexp.new("
|
116
|
+
# TODO: should probably escape these characters
|
117
|
+
@tag_pattern = Regexp.new("^#{@tag_prefix}\\d+$")
|
114
118
|
end
|
115
119
|
|
116
|
-
def
|
120
|
+
def configure_test_suite_model(feature_directory)
|
117
121
|
@directory = CukeModeler::Directory.new(feature_directory)
|
118
122
|
@model_repo = CQL::Repository.new(@directory)
|
119
123
|
|
120
124
|
@tests = @model_repo.query do
|
121
125
|
select :self
|
122
126
|
from scenarios, outlines
|
123
|
-
end.collect { |result| result[:self] }
|
127
|
+
end.collect { |result| result[:self] } # rubocop:disable Style/MultilineBlockChain - Idiomatic CQL
|
128
|
+
|
129
|
+
# Sorting for consistency, regardless of how the model tree happened to be traversed
|
130
|
+
@tests.sort! do |a, b|
|
131
|
+
if a.get_ancestor(:feature_file).path < b.get_ancestor(:feature_file).path # Earlier file
|
132
|
+
-1
|
133
|
+
elsif a.get_ancestor(:feature_file).path > b.get_ancestor(:feature_file).path # Later file
|
134
|
+
1
|
135
|
+
elsif a.source_line < b.source_line # Same file, earlier line
|
136
|
+
-1
|
137
|
+
elsif a.source_line > b.source_line # Same file, later line
|
138
|
+
1
|
139
|
+
else # Same file, same line number (shouldn't ever happen)
|
140
|
+
0
|
141
|
+
end
|
142
|
+
end
|
124
143
|
|
125
144
|
@features = @model_repo.query do
|
126
145
|
select :self
|
127
146
|
from features
|
128
|
-
end.collect { |result| result[:self] }
|
147
|
+
end.collect { |result| result[:self] } # rubocop:disable Style/MultilineBlockChain - Idiomatic CQL
|
129
148
|
end
|
130
149
|
|
131
150
|
def validate_feature(feature)
|
@@ -137,17 +156,17 @@ module CukeCataloger
|
|
137
156
|
check_for_multiple_test_id_tags(test)
|
138
157
|
check_for_duplicated_test_id_tags(test)
|
139
158
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
159
|
+
return unless test.is_a?(CukeModeler::Outline) && tag_rows
|
160
|
+
|
161
|
+
check_for_missing_id_columns(test, id_column_name)
|
162
|
+
check_for_missing_row_tags(test, id_column_name)
|
163
|
+
check_for_duplicated_row_tags(test, id_column_name)
|
164
|
+
check_for_mismatched_row_tags(test, id_column_name)
|
165
|
+
check_for_malformed_row_tags(test, id_column_name)
|
147
166
|
end
|
148
167
|
|
149
168
|
def check_for_feature_level_test_tag(feature)
|
150
|
-
add_to_results(feature, :feature_test_tag) if
|
169
|
+
add_to_results(feature, :feature_test_tag) if id_tag?(feature)
|
151
170
|
end
|
152
171
|
|
153
172
|
def check_for_duplicated_test_id_tags(test)
|
@@ -155,9 +174,9 @@ module CukeCataloger
|
|
155
174
|
@existing_tags = @model_repo.query do
|
156
175
|
select tags
|
157
176
|
from features, scenarios, outlines, examples
|
158
|
-
end.collect { |result| result['tags'] }.flatten
|
177
|
+
end.collect { |result| result['tags'] }.flatten # rubocop:disable Style/MultilineBlockChain - Idiomatic CQL
|
159
178
|
|
160
|
-
@existing_tags.
|
179
|
+
@existing_tags.map!(&:name)
|
161
180
|
end
|
162
181
|
|
163
182
|
test_id_tag = static_id_tag_for(test)
|
@@ -168,9 +187,7 @@ module CukeCataloger
|
|
168
187
|
end
|
169
188
|
|
170
189
|
def check_for_multiple_test_id_tags(test)
|
171
|
-
tags = test.tags
|
172
|
-
|
173
|
-
tags = tags.collect { |tag| tag.name } unless cuke_modeler?(0)
|
190
|
+
tags = test.tags.map(&:name)
|
174
191
|
|
175
192
|
id_tags_found = tags.select { |tag| tag =~ @tag_pattern }
|
176
193
|
|
@@ -178,33 +195,33 @@ module CukeCataloger
|
|
178
195
|
end
|
179
196
|
|
180
197
|
def check_for_missing_test_tag(test)
|
181
|
-
add_to_results(test, :missing_tag) unless
|
198
|
+
add_to_results(test, :missing_tag) unless id_tag?(test)
|
182
199
|
end
|
183
200
|
|
184
201
|
def check_for_missing_id_columns(test, id_column_name)
|
185
202
|
test.examples.each do |example|
|
186
|
-
add_to_results(example, :missing_id_column) unless
|
203
|
+
add_to_results(example, :missing_id_column) unless id_column?(example, id_column_name)
|
187
204
|
end
|
188
205
|
end
|
189
206
|
|
190
207
|
def check_for_duplicated_row_tags(test, id_column_name)
|
191
|
-
validate_rows(test, :duplicate_row_id, false, :
|
208
|
+
validate_rows(test, :duplicate_row_id, false, :duplicate_row_id?, id_column_name)
|
192
209
|
end
|
193
210
|
|
194
211
|
def check_for_missing_row_tags(test, id_column_name)
|
195
|
-
validate_rows(test, :missing_row_id, true, :
|
212
|
+
validate_rows(test, :missing_row_id, true, :row_id?, id_column_name)
|
196
213
|
end
|
197
214
|
|
198
215
|
def check_for_mismatched_row_tags(test, id_column_name)
|
199
|
-
validate_rows(test, :mismatched_row_id, true, :
|
216
|
+
validate_rows(test, :mismatched_row_id, true, :matching_id?, id_column_name)
|
200
217
|
end
|
201
218
|
|
202
219
|
def check_for_malformed_row_tags(test, id_column_name)
|
203
220
|
test.examples.each do |example|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
221
|
+
next unless id_column?(example, id_column_name)
|
222
|
+
|
223
|
+
example_rows_for(example).each do |row|
|
224
|
+
add_to_results(row, :malformed_sub_id) if row_id?(row, id_column_name) && !well_formed_sub_id?(row_id_for(row, id_column_name)) # rubocop:disable Metrics/LineLength
|
208
225
|
end
|
209
226
|
end
|
210
227
|
end
|
@@ -212,14 +229,11 @@ module CukeCataloger
|
|
212
229
|
# Checks the rows of the given test for the given problem
|
213
230
|
def validate_rows(test, rule, desired, row_check, id_column_name)
|
214
231
|
test.examples.each do |example|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
add_to_results(row, rule) if self.send(row_check, row, id_column_name)
|
221
|
-
end
|
222
|
-
end
|
232
|
+
next unless id_column?(example, id_column_name)
|
233
|
+
|
234
|
+
example_rows_for(example).each do |row|
|
235
|
+
row_flagged = send(row_check, row, id_column_name)
|
236
|
+
add_to_results(row, rule) if desired != row_flagged
|
223
237
|
end
|
224
238
|
end
|
225
239
|
end
|
@@ -230,49 +244,49 @@ module CukeCataloger
|
|
230
244
|
|
231
245
|
def process_outline(test, tag_rows, id_column_name)
|
232
246
|
apply_tag_if_needed(test)
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
247
|
+
|
248
|
+
return unless tag_rows
|
249
|
+
|
250
|
+
update_parameters_if_needed(test, id_column_name)
|
251
|
+
update_rows_if_needed(test, determine_next_sub_id(test), id_column_name)
|
237
252
|
end
|
238
253
|
|
239
254
|
def apply_tag_if_needed(test)
|
240
|
-
|
241
|
-
tag = "#{@tag_prefix}#{@next_index}"
|
242
|
-
@next_index += 1
|
255
|
+
return if id_tag?(test)
|
243
256
|
|
244
|
-
|
245
|
-
|
257
|
+
tag = "#{@tag_prefix}#{@next_index}"
|
258
|
+
@next_index += 1
|
259
|
+
|
260
|
+
tag_test(test, tag, (' ' * determine_test_indentation(test)))
|
246
261
|
end
|
247
262
|
|
248
|
-
def
|
249
|
-
|
263
|
+
def id_tag?(test)
|
264
|
+
!fast_id_tag_for(test).nil?
|
250
265
|
end
|
251
266
|
|
252
|
-
def
|
267
|
+
def id_column?(example, id_column_name)
|
253
268
|
example.parameters.any? { |param| param == id_column_name }
|
254
269
|
end
|
255
270
|
|
256
271
|
def row_id_for(row, id_column_name)
|
257
272
|
id_index = determine_row_id_cell_index(row, id_column_name)
|
258
273
|
|
259
|
-
|
260
|
-
cell_value = row.cells[id_index]
|
261
|
-
cell_value = cell_value.value unless cuke_modeler?(0)
|
274
|
+
return nil unless id_index
|
262
275
|
|
263
|
-
|
264
|
-
|
276
|
+
cell_value = row.cells[id_index].value
|
277
|
+
|
278
|
+
cell_value != '' ? cell_value : nil
|
265
279
|
end
|
266
280
|
|
267
|
-
def
|
268
|
-
|
281
|
+
def row_id?(row, id_column_name)
|
282
|
+
!row_id_for(row, id_column_name).nil?
|
269
283
|
end
|
270
284
|
|
271
285
|
def well_formed_sub_id?(id)
|
272
|
-
|
286
|
+
!(id =~ SUB_ID_PATTERN).nil?
|
273
287
|
end
|
274
288
|
|
275
|
-
def
|
289
|
+
def matching_id?(row, id_column_name)
|
276
290
|
row_id = row_id_for(row, id_column_name)
|
277
291
|
|
278
292
|
# A lack of id counts as 'matching'
|
@@ -283,13 +297,13 @@ module CukeCataloger
|
|
283
297
|
if parent_tag
|
284
298
|
parent_id = parent_tag.sub(@tag_prefix, '')
|
285
299
|
|
286
|
-
row_id =~ /#{parent_id}-/
|
300
|
+
!(row_id =~ /#{parent_id}-/).nil?
|
287
301
|
else
|
288
302
|
row_id.nil?
|
289
303
|
end
|
290
304
|
end
|
291
305
|
|
292
|
-
def
|
306
|
+
def duplicate_row_id?(row, id_column_name)
|
293
307
|
row_id = row_id_for(row, id_column_name)
|
294
308
|
|
295
309
|
return false unless row_id && well_formed_sub_id?(row_id)
|
@@ -309,7 +323,7 @@ module CukeCataloger
|
|
309
323
|
|
310
324
|
def determine_used_sub_ids(test, id_column_name)
|
311
325
|
ids = test.examples.collect do |example|
|
312
|
-
if
|
326
|
+
if id_parameter?(example, id_column_name)
|
313
327
|
example_rows_for(example).collect do |row|
|
314
328
|
row_id_for(row, id_column_name)
|
315
329
|
end
|
@@ -343,31 +357,26 @@ module CukeCataloger
|
|
343
357
|
File.open(file_path, 'w') { |file| file.print file_lines.join }
|
344
358
|
@file_line_increases[file_path] += 1
|
345
359
|
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
new_tag = CukeModeler::Tag.new
|
350
|
-
new_tag.name = tag
|
351
|
-
test.tags << new_tag
|
352
|
-
end
|
360
|
+
new_tag = CukeModeler::Tag.new
|
361
|
+
new_tag.name = tag
|
362
|
+
test.tags << new_tag
|
353
363
|
end
|
354
364
|
|
355
365
|
def update_parameters_if_needed(test, id_column_name)
|
356
366
|
feature_file = test.get_ancestor(:feature_file)
|
357
367
|
file_path = feature_file.path
|
358
368
|
index_adjustment = @file_line_increases[file_path]
|
359
|
-
method_for_rows = cuke_modeler?(0) ? :row_elements : :rows
|
360
369
|
|
361
370
|
test.examples.each do |example|
|
362
|
-
|
363
|
-
parameter_line_index = (example.send(method_for_rows).first.source_line - 1) + index_adjustment
|
371
|
+
next if id_parameter?(example, id_column_name)
|
364
372
|
|
365
|
-
|
373
|
+
parameter_line_index = (example.rows.first.source_line - 1) + index_adjustment
|
366
374
|
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
375
|
+
file_lines = File.readlines(file_path)
|
376
|
+
|
377
|
+
new_parameter = id_column_name.ljust(parameter_spacing(example, id_column_name))
|
378
|
+
update_parameter_row(file_lines, parameter_line_index, new_parameter)
|
379
|
+
File.open(file_path, 'w') { |file| file.print file_lines.join }
|
371
380
|
end
|
372
381
|
end
|
373
382
|
|
@@ -375,32 +384,35 @@ module CukeCataloger
|
|
375
384
|
feature_file = test.get_ancestor(:feature_file)
|
376
385
|
file_path = feature_file.path
|
377
386
|
index_adjustment = @file_line_increases[file_path]
|
378
|
-
method_for_rows = cuke_modeler?(0) ? :row_elements : :rows
|
379
387
|
|
380
388
|
tag_index = fast_id_tag_for(test)[/\d+/]
|
381
389
|
|
382
390
|
file_lines = File.readlines(file_path)
|
383
391
|
|
384
392
|
test.examples.each do |example|
|
385
|
-
example.
|
386
|
-
|
387
|
-
row_id = "#{tag_index}-#{sub_id}".ljust(parameter_spacing(example, id_column_name))
|
393
|
+
example.rows[1..(example.rows.count - 1)].each do |row|
|
394
|
+
next if row_id?(row, id_column_name)
|
388
395
|
|
389
|
-
|
396
|
+
row_id = "#{tag_index}-#{sub_id}".ljust(parameter_spacing(example, id_column_name))
|
390
397
|
|
391
|
-
|
392
|
-
|
393
|
-
|
398
|
+
row_line_index = (row.source_line - 1) + index_adjustment
|
399
|
+
|
400
|
+
update_value_row(file_lines, row_line_index, row, row_id, id_column_name)
|
401
|
+
sub_id += 1
|
394
402
|
end
|
395
403
|
|
396
404
|
File.open(file_path, 'w') { |file| file.print file_lines.join }
|
397
405
|
end
|
398
406
|
end
|
399
407
|
|
400
|
-
|
401
408
|
# Slowest way to get the id tag. Will check the object every time.
|
402
409
|
def current_id_tag_for(thing)
|
403
|
-
|
410
|
+
tags = thing.tags
|
411
|
+
id_tag = tags.detect { |tag| tag.name =~ @tag_pattern }
|
412
|
+
|
413
|
+
return unless id_tag
|
414
|
+
|
415
|
+
id_tag.name
|
404
416
|
end
|
405
417
|
|
406
418
|
# Faster way to get the id tag. Will skip checking the object if an id for it is already known.
|
@@ -417,12 +429,13 @@ module CukeCataloger
|
|
417
429
|
id
|
418
430
|
end
|
419
431
|
|
420
|
-
# Fastest way to get the id tag. Will skip checking the object if it
|
432
|
+
# Fastest way to get the id tag. Will skip checking the object if it
|
433
|
+
# has been checked before, even if no id was found.
|
421
434
|
def static_id_tag_for(thing)
|
422
435
|
@known_id_tags ||= {}
|
423
436
|
id_key = thing.object_id
|
424
437
|
|
425
|
-
return @known_id_tags[id_key] if @known_id_tags.
|
438
|
+
return @known_id_tags[id_key] if @known_id_tags.key?(id_key)
|
426
439
|
|
427
440
|
id = current_id_tag_for(thing)
|
428
441
|
@known_id_tags[id_key] = id
|
@@ -430,20 +443,12 @@ module CukeCataloger
|
|
430
443
|
id
|
431
444
|
end
|
432
445
|
|
433
|
-
def id_tag_for(thing)
|
434
|
-
tags = thing.tags
|
435
|
-
|
436
|
-
tags = tags.collect { |tag| tag.name } unless cuke_modeler?(0)
|
437
|
-
|
438
|
-
tags.select { |tag| tag =~ @tag_pattern }.first
|
439
|
-
end
|
440
|
-
|
441
446
|
def test_id_for(test)
|
442
|
-
#
|
447
|
+
# TODO: should probably be escaping these in case regex characters used in prefix...
|
443
448
|
fast_id_tag_for(test).match(/#{@tag_prefix}(.*)/)[1]
|
444
449
|
end
|
445
450
|
|
446
|
-
def
|
451
|
+
def id_parameter?(example, id_column_name)
|
447
452
|
example.parameters.any? { |parameter| parameter == id_column_name }
|
448
453
|
end
|
449
454
|
|
@@ -465,11 +470,11 @@ module CukeCataloger
|
|
465
470
|
end
|
466
471
|
|
467
472
|
def needs_adding?(row, id_column_name)
|
468
|
-
!
|
473
|
+
!id_parameter?(row.get_ancestor(:example), id_column_name)
|
469
474
|
end
|
470
475
|
|
471
476
|
def needs_filled_in?(row, id_column_name)
|
472
|
-
|
477
|
+
id_parameter?(row.get_ancestor(:example), id_column_name)
|
473
478
|
end
|
474
479
|
|
475
480
|
# Replaces the indicated line of text with the provided line of tet
|
@@ -494,17 +499,15 @@ module CukeCataloger
|
|
494
499
|
end
|
495
500
|
|
496
501
|
def example_rows_for(example)
|
497
|
-
|
498
|
-
|
499
|
-
rows = example.send(method_for_rows).dup
|
502
|
+
rows = example.rows.dup
|
500
503
|
rows.shift
|
501
504
|
|
502
505
|
rows
|
503
506
|
end
|
504
507
|
|
505
508
|
def add_to_results(item, issue = nil)
|
506
|
-
result = { :
|
507
|
-
result
|
509
|
+
result = { test: "#{item.get_ancestor(:feature_file).path}:#{item.source_line}", object: item }
|
510
|
+
result[:problem] = issue if issue
|
508
511
|
|
509
512
|
@results << result
|
510
513
|
end
|
@@ -513,39 +516,43 @@ module CukeCataloger
|
|
513
516
|
primary_ids = known_ids.select { |id| id =~ /^\d+$/ }
|
514
517
|
sub_ids = known_ids.select { |id| id =~ /^\d+-\d+$/ }
|
515
518
|
|
516
|
-
max_primary_id = primary_ids.
|
517
|
-
default_indexes = { :
|
518
|
-
:
|
519
|
+
max_primary_id = primary_ids.map(&:to_i).max || 0
|
520
|
+
default_indexes = { primary: max_primary_id + 1,
|
521
|
+
sub: {} }
|
519
522
|
|
520
523
|
sub_primaries = sub_ids.collect { |sub_id| sub_id[/^\d+/] }
|
521
524
|
|
522
525
|
sub_primaries.each do |primary|
|
523
|
-
default_indexes[:sub][primary] = sub_ids.select { |sub_id| sub_id[/^\d+/] == primary }
|
526
|
+
default_indexes[:sub][primary] = sub_ids.select { |sub_id| sub_id[/^\d+/] == primary }
|
527
|
+
.collect { |sub_id| sub_id[/\d+$/].to_i }.max + 1
|
524
528
|
end
|
525
529
|
|
526
530
|
default_indexes
|
527
531
|
end
|
528
532
|
|
529
|
-
# Merges the given index sets (of the shape {:
|
530
|
-
def merge_indexes(
|
531
|
-
|
532
|
-
key == :sub ?
|
533
|
-
|
533
|
+
# Merges the given index sets (of the shape {primary: Integer, sub: Hash}) into a new one
|
534
|
+
def merge_indexes(set_1, set_2)
|
535
|
+
set_1.merge(set_2) do |key, set_1_value, set_2_value|
|
536
|
+
key == :sub ? set_1_value.merge(set_2_value) : set_2_value
|
537
|
+
end
|
534
538
|
end
|
535
539
|
|
540
|
+
# Determines how wide a parameter string needs to be in order to correctly fit the column in which it resides
|
536
541
|
def parameter_spacing(example, id_column_name)
|
537
542
|
test = example.get_ancestor(:test)
|
538
543
|
test_id = fast_id_tag_for(test)[/\d+$/]
|
539
|
-
row_count = test.examples.reduce(0) { |sum,
|
544
|
+
row_count = test.examples.reduce(0) { |sum, example_table| sum + example_table.rows.count }
|
540
545
|
|
541
|
-
|
546
|
+
# TODO: Possible bug - what if old test rows have been removed and the existing
|
547
|
+
# sub IDs are a lot longer than the number of current rows?
|
548
|
+
max_id_length = test_id.length + 1 + row_count.to_s.length # base ID + hyphen + sub ID
|
542
549
|
param_length = id_column_name.length
|
543
550
|
|
544
551
|
[param_length, max_id_length].max
|
545
552
|
end
|
546
553
|
|
547
554
|
def determine_test_indentation(test)
|
548
|
-
#
|
555
|
+
# TODO: replace with 'get_most_recent_file_text'
|
549
556
|
feature_file = test.get_ancestor(:feature_file)
|
550
557
|
file_path = feature_file.path
|
551
558
|
|
@@ -586,17 +593,13 @@ module CukeCataloger
|
|
586
593
|
def determine_highest_tag_line(test)
|
587
594
|
return adjacent_tag_line(test) if test.tags.empty?
|
588
595
|
|
589
|
-
|
590
|
-
|
591
|
-
test.send(method_for_tag_models).collect { |tag_element| tag_element.source_line }.min - 1
|
596
|
+
test.tags.map(&:source_line).min - 1
|
592
597
|
end
|
593
598
|
|
594
599
|
def determine_lowest_tag_line(test)
|
595
600
|
return adjacent_tag_line(test) if test.tags.empty?
|
596
601
|
|
597
|
-
|
598
|
-
|
599
|
-
test.send(method_for_tag_models).collect { |tag_element| tag_element.source_line }.max
|
602
|
+
test.tags.map(&:source_line).max
|
600
603
|
end
|
601
604
|
|
602
605
|
def adjacent_tag_line(test)
|
@@ -613,3 +616,5 @@ module CukeCataloger
|
|
613
616
|
|
614
617
|
end
|
615
618
|
end
|
619
|
+
|
620
|
+
# rubocop:enable Metrics/ClassLength, Metrics/AbcSize, Metrics/MethodLength
|