cuke_cataloger 1.6.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|