roo-andyw8 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.simplecov +4 -0
  4. data/.travis.yml +13 -0
  5. data/CHANGELOG +438 -0
  6. data/Gemfile +24 -0
  7. data/Guardfile +24 -0
  8. data/LICENSE +22 -0
  9. data/README.md +121 -0
  10. data/Rakefile +23 -0
  11. data/examples/roo_soap_client.rb +50 -0
  12. data/examples/roo_soap_server.rb +26 -0
  13. data/examples/write_me.rb +31 -0
  14. data/lib/roo.rb +28 -0
  15. data/lib/roo/base.rb +717 -0
  16. data/lib/roo/csv.rb +110 -0
  17. data/lib/roo/excelx.rb +540 -0
  18. data/lib/roo/excelx/comments.rb +23 -0
  19. data/lib/roo/excelx/extractor.rb +20 -0
  20. data/lib/roo/excelx/relationships.rb +26 -0
  21. data/lib/roo/excelx/shared_strings.rb +40 -0
  22. data/lib/roo/excelx/sheet_doc.rb +175 -0
  23. data/lib/roo/excelx/styles.rb +62 -0
  24. data/lib/roo/excelx/workbook.rb +59 -0
  25. data/lib/roo/font.rb +17 -0
  26. data/lib/roo/libre_office.rb +5 -0
  27. data/lib/roo/link.rb +15 -0
  28. data/lib/roo/open_office.rb +652 -0
  29. data/lib/roo/spreadsheet.rb +31 -0
  30. data/lib/roo/utils.rb +81 -0
  31. data/lib/roo/version.rb +3 -0
  32. data/roo.gemspec +27 -0
  33. data/scripts/txt2html +67 -0
  34. data/spec/fixtures/vcr_cassettes/google_drive.yml +165 -0
  35. data/spec/fixtures/vcr_cassettes/google_drive_access_token.yml +73 -0
  36. data/spec/fixtures/vcr_cassettes/google_drive_set.yml +857 -0
  37. data/spec/lib/roo/base_spec.rb +4 -0
  38. data/spec/lib/roo/csv_spec.rb +48 -0
  39. data/spec/lib/roo/excelx/format_spec.rb +51 -0
  40. data/spec/lib/roo/excelx_spec.rb +363 -0
  41. data/spec/lib/roo/libreoffice_spec.rb +13 -0
  42. data/spec/lib/roo/openoffice_spec.rb +15 -0
  43. data/spec/lib/roo/spreadsheet_spec.rb +88 -0
  44. data/spec/lib/roo/utils_spec.rb +105 -0
  45. data/spec/spec_helper.rb +9 -0
  46. data/test/all_ss.rb +11 -0
  47. data/test/files/1900_base.xlsx +0 -0
  48. data/test/files/1904_base.xlsx +0 -0
  49. data/test/files/Bibelbund.csv +3741 -0
  50. data/test/files/Bibelbund.ods +0 -0
  51. data/test/files/Bibelbund.xlsx +0 -0
  52. data/test/files/Bibelbund1.ods +0 -0
  53. data/test/files/Pfand_from_windows_phone.xlsx +0 -0
  54. data/test/files/advanced_header.ods +0 -0
  55. data/test/files/bbu.ods +0 -0
  56. data/test/files/bbu.xlsx +0 -0
  57. data/test/files/bode-v1.ods.zip +0 -0
  58. data/test/files/bode-v1.xls.zip +0 -0
  59. data/test/files/boolean.csv +2 -0
  60. data/test/files/boolean.ods +0 -0
  61. data/test/files/boolean.xlsx +0 -0
  62. data/test/files/borders.ods +0 -0
  63. data/test/files/borders.xlsx +0 -0
  64. data/test/files/bug-numbered-sheet-names.xlsx +0 -0
  65. data/test/files/comments.ods +0 -0
  66. data/test/files/comments.xlsx +0 -0
  67. data/test/files/csvtypes.csv +1 -0
  68. data/test/files/datetime.ods +0 -0
  69. data/test/files/datetime.xlsx +0 -0
  70. data/test/files/dreimalvier.ods +0 -0
  71. data/test/files/emptysheets.ods +0 -0
  72. data/test/files/emptysheets.xlsx +0 -0
  73. data/test/files/encrypted-letmein.ods +0 -0
  74. data/test/files/file_item_error.xlsx +0 -0
  75. data/test/files/formula.ods +0 -0
  76. data/test/files/formula.xlsx +0 -0
  77. data/test/files/formula_string_error.xlsx +0 -0
  78. data/test/files/html-escape.ods +0 -0
  79. data/test/files/link.csv +1 -0
  80. data/test/files/link.xlsx +0 -0
  81. data/test/files/matrix.ods +0 -0
  82. data/test/files/named_cells.ods +0 -0
  83. data/test/files/named_cells.xlsx +0 -0
  84. data/test/files/no_spreadsheet_file.txt +1 -0
  85. data/test/files/numbers-export.xlsx +0 -0
  86. data/test/files/numbers1.csv +18 -0
  87. data/test/files/numbers1.ods +0 -0
  88. data/test/files/numbers1.xlsx +0 -0
  89. data/test/files/numbers1withnull.xlsx +0 -0
  90. data/test/files/numeric-link.xlsx +0 -0
  91. data/test/files/only_one_sheet.ods +0 -0
  92. data/test/files/only_one_sheet.xlsx +0 -0
  93. data/test/files/paragraph.ods +0 -0
  94. data/test/files/paragraph.xlsx +0 -0
  95. data/test/files/ric.ods +0 -0
  96. data/test/files/sheet1.xml +109 -0
  97. data/test/files/simple_spreadsheet.ods +0 -0
  98. data/test/files/simple_spreadsheet.xlsx +0 -0
  99. data/test/files/simple_spreadsheet_from_italo.ods +0 -0
  100. data/test/files/so_datetime.csv +8 -0
  101. data/test/files/style.ods +0 -0
  102. data/test/files/style.xlsx +0 -0
  103. data/test/files/time-test.csv +2 -0
  104. data/test/files/time-test.ods +0 -0
  105. data/test/files/time-test.xlsx +0 -0
  106. data/test/files/type_excel.ods +0 -0
  107. data/test/files/type_excel.xlsx +0 -0
  108. data/test/files/type_excelx.ods +0 -0
  109. data/test/files/type_openoffice.xlsx +0 -0
  110. data/test/files/whitespace.ods +0 -0
  111. data/test/files/whitespace.xlsx +0 -0
  112. data/test/test_generic_spreadsheet.rb +211 -0
  113. data/test/test_helper.rb +58 -0
  114. data/test/test_roo.rb +1977 -0
  115. metadata +318 -0
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe Roo::Base do
4
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Roo::CSV do
4
+ let(:path) { 'test/files/csvtypes.csv' }
5
+ let(:csv) { Roo::CSV.new(path) }
6
+
7
+ describe '.new' do
8
+ it 'creates an instance' do
9
+ expect(csv).to be_a(Roo::CSV)
10
+ end
11
+ end
12
+
13
+ describe '#parse' do
14
+ subject do
15
+ csv.parse(options)
16
+ end
17
+ context 'with headers: true' do
18
+ let(:options) { { headers: true } }
19
+
20
+ it "doesn't blow up" do
21
+ expect { subject }.to_not raise_error
22
+ end
23
+ end
24
+ end
25
+
26
+ describe '#csv_options' do
27
+ context 'when created with the csv_options option' do
28
+ let(:options) do
29
+ {
30
+ col_sep: '\t',
31
+ quote_char: "'"
32
+ }
33
+ end
34
+
35
+ it 'returns the csv options' do
36
+ csv = Roo::CSV.new(path, csv_options: options)
37
+ expect(csv.csv_options).to eq(options)
38
+ end
39
+ end
40
+
41
+ context 'when created without the csv_options option' do
42
+ it 'returns a hash' do
43
+ csv = Roo::CSV.new(path)
44
+ expect(csv.csv_options).to eq({})
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe Roo::Excelx::Format do
4
+ describe '#to_type' do
5
+ FORMATS = {
6
+ 'General' => :float,
7
+ '0' => :float,
8
+ '0.00' => :float,
9
+ '#,##0' => :float,
10
+ '#,##0.00' => :float,
11
+ '0%' => :percentage,
12
+ '0.00%' => :percentage,
13
+ '0.00E+00' => :float,
14
+ '# ?/?' => :float, # ??? TODO:
15
+ '# ??/??' => :float, # ??? TODO:
16
+ 'mm-dd-yy' => :date,
17
+ 'd-mmm-yy' => :date,
18
+ 'd-mmm' => :date,
19
+ 'mmm-yy' => :date,
20
+ 'h:mm AM/PM' => :date,
21
+ 'h:mm:ss AM/PM' => :date,
22
+ 'h:mm' => :time,
23
+ 'h:mm:ss' => :time,
24
+ 'm/d/yy h:mm' => :datetime,
25
+ '#,##0 ;(#,##0)' => :float,
26
+ '#,##0 ;[Red](#,##0)' => :float,
27
+ '#,##0.00;(#,##0.00)' => :float,
28
+ '#,##0.00;[Red](#,##0.00)' => :float,
29
+ '#,##0_);[Red](#,##0)' => :float,
30
+ 'mm:ss' => :time,
31
+ '[h]:mm:ss' => :time,
32
+ 'mmss.0' => :time,
33
+ '##0.0E+0' => :float,
34
+ '@' => :float,
35
+ #-- zusaetzliche Formate, die nicht standardmaessig definiert sind:
36
+ 'yyyy\\-mm\\-dd' => :date,
37
+ 'dd/mm/yy' => :date,
38
+ 'hh:mm:ss' => :time,
39
+ 'dd/mm/yy\\ hh:mm' => :datetime,
40
+ 'dd/mmm/yy\\ hh:mm' => :datetime,
41
+ 'dd/mmm/yy' => :date, # 2011-05-21
42
+ 'yyyy-mm-dd' => :date, # 2011-09-16
43
+ 'yyyy-mm-dd;@' => :date,
44
+ '#0_);[Red]\(0\)' => :float
45
+ }.each do |format, type|
46
+ it "translates #{format} to #{type}" do
47
+ expect(Roo::Excelx::Format.to_type(format)).to eq(type)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,363 @@
1
+ require 'spec_helper'
2
+
3
+ describe Roo::Excelx do
4
+ subject(:xlsx) do
5
+ Roo::Excelx.new(path)
6
+ end
7
+
8
+ describe '.new' do
9
+ let(:path) { 'test/files/numeric-link.xlsx' }
10
+
11
+ it 'creates an instance' do
12
+ expect(subject).to be_a(Roo::Excelx)
13
+ end
14
+
15
+ context 'given a file with missing rels' do
16
+ let(:path) { 'test/files/file_item_error.xlsx' }
17
+
18
+ it 'creates an instance' do
19
+ expect(subject).to be_a(Roo::Excelx)
20
+ end
21
+ end
22
+
23
+ context 'with more cells than specified max' do
24
+ let(:path) { 'test/files/only_one_sheet.xlsx' }
25
+
26
+ it 'raises an appropriate error' do
27
+ expect { Roo::Excelx.new(path, cell_max: 1) }.to raise_error(Roo::Excelx::ExceedsMaxError)
28
+ end
29
+ end
30
+
31
+ context 'with fewer cells than specified max' do
32
+ let(:path) { 'test/files/only_one_sheet.xlsx' }
33
+
34
+ it 'creates an instance' do
35
+ expect(Roo::Excelx.new(path, cell_max: 100)).to be_a(Roo::Excelx)
36
+ end
37
+ end
38
+ end
39
+
40
+ describe '#cell' do
41
+ context 'for a link cell' do
42
+ context 'with numeric contents' do
43
+ let(:path) { 'test/files/numeric-link.xlsx' }
44
+
45
+ subject do
46
+ xlsx.cell('A', 1)
47
+ end
48
+
49
+ it 'returns a link with the number as a string value' do
50
+ expect(subject).to be_a(Roo::Link)
51
+ expect(subject).to eq('8675309.0')
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '#parse' do
58
+ let(:path) { 'test/files/numeric-link.xlsx' }
59
+
60
+ context 'with a columns hash' do
61
+ context 'when not present in the sheet' do
62
+ it 'does not raise' do
63
+ expect do
64
+ xlsx.sheet(0).parse(
65
+ this: 'This',
66
+ that: 'That'
67
+ )
68
+ end.to raise_error("Couldn't find header row.")
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ describe '#sheets' do
75
+ let(:path) { 'test/files/numbers1.xlsx' }
76
+
77
+ it 'returns the expected result' do
78
+ expect(subject.sheets).to eq ["Tabelle1", "Name of Sheet 2", "Sheet3", "Sheet4", "Sheet5"]
79
+ end
80
+ end
81
+
82
+ describe '#sheet_for' do
83
+ let(:path) { 'test/files/numbers1.xlsx' }
84
+
85
+ # This is kinda gross
86
+ it 'returns the expected result' do
87
+ expect(subject.sheet_for("Tabelle1").instance_variable_get("@name")).to eq "Tabelle1"
88
+ end
89
+ end
90
+
91
+ describe '#row' do
92
+ let(:path) { 'test/files/numbers1.xlsx' }
93
+
94
+ it 'returns the expected result' do
95
+ expect(subject.row(1, "Sheet5")).to eq [1.0, 5.0, 5.0, nil, nil]
96
+ end
97
+ end
98
+
99
+ describe '#column' do
100
+ let(:path) { 'test/files/numbers1.xlsx' }
101
+
102
+ it 'returns the expected result' do
103
+ expect(subject.column(1, "Sheet5")).to eq [1.0, 2.0, 3.0, Date.new(2007,11,21), 42.0, "ABC"]
104
+ end
105
+ end
106
+
107
+ describe '#first_row' do
108
+ let(:path) { 'test/files/numbers1.xlsx' }
109
+
110
+ it 'returns the expected result' do
111
+ expect(subject.first_row("Sheet5")).to eq 1
112
+ end
113
+ end
114
+
115
+ describe '#last_row' do
116
+ let(:path) { 'test/files/numbers1.xlsx' }
117
+
118
+ it 'returns the expected result' do
119
+ expect(subject.last_row("Sheet5")).to eq 6
120
+ end
121
+ end
122
+
123
+ describe '#first_column' do
124
+ let(:path) { 'test/files/numbers1.xlsx' }
125
+
126
+ it 'returns the expected result' do
127
+ expect(subject.first_column("Sheet5")).to eq 1
128
+ end
129
+ end
130
+
131
+ describe '#last_column' do
132
+ let(:path) { 'test/files/numbers1.xlsx' }
133
+
134
+ it 'returns the expected result' do
135
+ expect(subject.last_column("Sheet5")).to eq 5
136
+ end
137
+ end
138
+
139
+ describe '#set' do
140
+
141
+ before do
142
+ subject.set(1, 2, "Foo", "Sheet5")
143
+ end
144
+
145
+ let(:path) { 'test/files/numbers1.xlsx' }
146
+ let(:cell) { subject.cell(1, 2, "Sheet5") }
147
+
148
+ it 'returns the expected result' do
149
+ expect(cell).to eq "Foo"
150
+ end
151
+ end
152
+
153
+ describe '#formula' do
154
+ let(:path) { 'test/files/formula.xlsx' }
155
+
156
+ it 'returns the expected result' do
157
+ expect(subject.formula(1, 1, "Sheet1")).to eq nil
158
+ expect(subject.formula(7, 2, "Sheet1")).to eq "SUM($A$1:B6)"
159
+ end
160
+ end
161
+
162
+ describe '#formula?' do
163
+ let(:path) { 'test/files/formula.xlsx' }
164
+
165
+ it 'returns the expected result' do
166
+ expect(subject.formula?(1, 1, "Sheet1")).to eq false
167
+ expect(subject.formula?(7, 2, "Sheet1")).to eq true
168
+ end
169
+ end
170
+
171
+ describe '#formulas' do
172
+ let(:path) { 'test/files/formula.xlsx' }
173
+
174
+ it 'returns the expected result' do
175
+ expect(subject.formulas("Sheet1")).to eq [[7, 1, "SUM(A1:A6)"], [7, 2, "SUM($A$1:B6)"]]
176
+ end
177
+ end
178
+
179
+ describe '#font' do
180
+ let(:path) { 'test/files/style.xlsx' }
181
+
182
+ it 'returns the expected result' do
183
+ expect(subject.font(1, 1).bold?).to eq true
184
+ expect(subject.font(1, 1).italic?).to eq false
185
+ expect(subject.font(1, 1).underline?).to eq false
186
+
187
+ expect(subject.font(7, 1).bold?).to eq false
188
+ expect(subject.font(7, 1).italic?).to eq true
189
+ expect(subject.font(7, 1).underline?).to eq true
190
+ end
191
+ end
192
+
193
+ describe '#celltype' do
194
+ let(:path) { 'test/files/numbers1.xlsx' }
195
+
196
+ it 'returns the expected result' do
197
+ expect(subject.celltype(1, 1, "Sheet4")).to eq :date
198
+ expect(subject.celltype(1, 2, "Sheet4")).to eq :float
199
+ expect(subject.celltype(6, 2, "Sheet5")).to eq :string
200
+ end
201
+ end
202
+
203
+ describe '#excelx_type' do
204
+ let(:path) { 'test/files/numbers1.xlsx' }
205
+
206
+ it 'returns the expected result' do
207
+ expect(subject.excelx_type(1, 1, "Sheet5")).to eq [:numeric_or_formula, "General"]
208
+ expect(subject.excelx_type(6, 2, "Sheet5")).to eq :string
209
+ end
210
+ end
211
+
212
+ describe '#excelx_value' do
213
+ let(:path) { 'test/files/numbers1.xlsx' }
214
+
215
+ it 'returns the expected result' do
216
+ # These values are the index in the shared strings table, might be a better
217
+ # way to get these rather than hardcoding.
218
+ expect(subject.excelx_value(1, 1, "Sheet5")).to eq "1"
219
+ expect(subject.excelx_value(6, 2, "Sheet5")).to eq "16"
220
+ end
221
+ end
222
+
223
+ describe '#excelx_format' do
224
+ let(:path) { 'test/files/style.xlsx' }
225
+
226
+ it 'returns the expected result' do
227
+ # These are the index of the style for a given document
228
+ # might be more reliable way to get this info.
229
+ expect(subject.excelx_value(1, 1)).to eq "0"
230
+ expect(subject.excelx_value(5, 1)).to eq "4"
231
+ end
232
+ end
233
+
234
+ describe '#empty?' do
235
+ let(:path) { 'test/files/style.xlsx' }
236
+
237
+ it 'returns the expected result' do
238
+ # These are the index of the style for a given document
239
+ # might be more reliable way to get this info.
240
+ expect(subject.empty?(1, 1)).to eq false
241
+ expect(subject.empty?(13, 1)).to eq true
242
+ end
243
+ end
244
+
245
+ describe '#label' do
246
+ let(:path) { 'test/files/named_cells.xlsx' }
247
+
248
+ it 'returns the expected result' do
249
+ expect(subject.label("berta")).to eq [4, 2, "Sheet1"]
250
+ expect(subject.label("dave")).to eq [nil, nil, nil]
251
+ end
252
+ end
253
+
254
+ describe '#labels' do
255
+ let(:path) { 'test/files/named_cells.xlsx' }
256
+
257
+ it 'returns the expected result' do
258
+ expect(subject.labels).to eq [["anton", [5, 3, "Sheet1"]], ["berta", [4, 2, "Sheet1"]], ["caesar", [7, 2, "Sheet1"]]]
259
+ end
260
+ end
261
+
262
+ describe '#hyperlink?' do
263
+ let(:path) { 'test/files/link.xlsx' }
264
+
265
+ it 'returns the expected result' do
266
+ expect(subject.hyperlink?(1, 1)).to eq true
267
+ expect(subject.hyperlink?(1, 2)).to eq false
268
+ end
269
+ end
270
+
271
+ describe '#hyperlink' do
272
+ let(:path) { 'test/files/link.xlsx' }
273
+
274
+ it 'returns the expected result' do
275
+ expect(subject.hyperlink(1, 1)).to eq "http://www.google.com"
276
+ expect(subject.hyperlink(1, 2)).to eq nil
277
+ end
278
+ end
279
+
280
+ describe '#comment' do
281
+ let(:path) { 'test/files/comments.xlsx' }
282
+
283
+ it 'returns the expected result' do
284
+ expect(subject.comment(4, 2)).to eq "Kommentar fuer B4"
285
+ expect(subject.comment(1, 2)).to eq nil
286
+ end
287
+ end
288
+
289
+ describe '#comment?' do
290
+ let(:path) { 'test/files/comments.xlsx' }
291
+
292
+ it 'returns the expected result' do
293
+ expect(subject.comment?(4, 2)).to eq true
294
+ expect(subject.comment?(1, 2)).to eq false
295
+ end
296
+ end
297
+
298
+ describe '#comments' do
299
+ let(:path) { 'test/files/comments.xlsx' }
300
+
301
+ it 'returns the expected result' do
302
+ expect(subject.comments).to eq [[4, 2, "Kommentar fuer B4"], [5, 2, "Kommentar fuer B5"]]
303
+ end
304
+ end
305
+
306
+ # nil, nil, nil, nil, nil
307
+ # nil, nil, nil, nil, nil
308
+ # Date Start time End time Pause Sum Comment
309
+ # 2007-05-07 9.25 10.25 0 1 Task 1
310
+ # 2007-05-07 10.75 12.50 0 1.75 Task 1
311
+ # 2007-05-07 18.00 19.00 0 1 Task 2
312
+ # 2007-05-08 9.25 10.25 0 1 Task 2
313
+ # 2007-05-08 14.50 15.50 0 1 Task 3
314
+ # 2007-05-08 8.75 9.25 0 0.5 Task 3
315
+ # 2007-05-14 21.75 22.25 0 0.5 Task 3
316
+ # 2007-05-14 22.50 23.00 0 0.5 Task 3
317
+ # 2007-05-15 11.75 12.75 0 1 Task 3
318
+ # 2007-05-07 10.75 10.75 0 0 Task 1
319
+ # nil
320
+ describe '#each_row_streaming' do
321
+ let(:path) { 'test/files/simple_spreadsheet.xlsx' }
322
+
323
+ let(:expected_rows) do
324
+ [
325
+ [nil, nil, nil, nil, nil],
326
+ [nil, nil, nil, nil, nil],
327
+ ["Date", "Start time", "End time", "Pause", "Sum", "Comment", nil, nil],
328
+ [Date.new(2007, 5, 7), 9.25, 10.25, 0.0, 1.0, "Task 1"],
329
+ [Date.new(2007, 5, 7), 10.75, 12.50, 0.0, 1.75, "Task 1"],
330
+ [Date.new(2007, 5, 7), 18.0, 19.0, 0.0, 1.0, "Task 2"],
331
+ [Date.new(2007, 5, 8), 9.25, 10.25, 0.0, 1.0, "Task 2"],
332
+ [Date.new(2007, 5, 8), 14.5, 15.5, 0.0, 1.0, "Task 3"],
333
+ [Date.new(2007, 5, 8), 8.75, 9.25, 0.0, 0.5, "Task 3"],
334
+ [Date.new(2007, 5, 14), 21.75, 22.25, 0.0, 0.5, "Task 3"],
335
+ [Date.new(2007, 5, 14), 22.5, 23.0, 0.0, 0.5, "Task 3"],
336
+ [Date.new(2007, 5, 15), 11.75, 12.75, 0.0, 1.0, "Task 3"],
337
+ [Date.new(2007, 5, 7), 10.75, 10.75, 0.0, 0.0, "Task 1"],
338
+ [nil]
339
+ ]
340
+ end
341
+
342
+ it 'returns the expected result' do
343
+ index = 0
344
+ subject.each_row_streaming do |row|
345
+ expect(row.map(&:value)).to eq expected_rows[index]
346
+ index += 1
347
+ end
348
+ end
349
+
350
+ context 'with max_rows options' do
351
+ it 'returns the expected result' do
352
+ index = 0
353
+ subject.each_row_streaming(max_rows: 3) do |row|
354
+ expect(row.map(&:value)).to eq expected_rows[index]
355
+ index += 1
356
+ end
357
+ # Expect this to get incremented one time more than max (because of the increment at the end of the block)
358
+ # but it should not be near expected_rows.size
359
+ expect(index).to eq 4
360
+ end
361
+ end
362
+ end
363
+ end