libis-tools 1.0.5-java
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 +7 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +16 -0
- data/.rspec +2 -0
- data/.travis.yml +40 -0
- data/Gemfile +7 -0
- data/README.md +202 -0
- data/Rakefile +11 -0
- data/bin/libis_tool +5 -0
- data/lib/libis-tools.rb +1 -0
- data/lib/libis/tools.rb +25 -0
- data/lib/libis/tools/assert.rb +52 -0
- data/lib/libis/tools/checksum.rb +106 -0
- data/lib/libis/tools/cli/cli_helper.rb +189 -0
- data/lib/libis/tools/cli/reorg.rb +416 -0
- data/lib/libis/tools/command.rb +133 -0
- data/lib/libis/tools/command_line.rb +23 -0
- data/lib/libis/tools/config.rb +147 -0
- data/lib/libis/tools/config_file.rb +85 -0
- data/lib/libis/tools/csv.rb +38 -0
- data/lib/libis/tools/deep_struct.rb +71 -0
- data/lib/libis/tools/extend/array.rb +16 -0
- data/lib/libis/tools/extend/empty.rb +7 -0
- data/lib/libis/tools/extend/hash.rb +147 -0
- data/lib/libis/tools/extend/kernel.rb +25 -0
- data/lib/libis/tools/extend/ostruct.rb +3 -0
- data/lib/libis/tools/extend/roo.rb +91 -0
- data/lib/libis/tools/extend/string.rb +94 -0
- data/lib/libis/tools/extend/struct.rb +29 -0
- data/lib/libis/tools/extend/symbol.rb +8 -0
- data/lib/libis/tools/logger.rb +130 -0
- data/lib/libis/tools/mets_dnx.rb +61 -0
- data/lib/libis/tools/mets_file.rb +504 -0
- data/lib/libis/tools/mets_objects.rb +547 -0
- data/lib/libis/tools/parameter.rb +372 -0
- data/lib/libis/tools/spreadsheet.rb +196 -0
- data/lib/libis/tools/temp_file.rb +42 -0
- data/lib/libis/tools/thread_safe.rb +31 -0
- data/lib/libis/tools/version.rb +5 -0
- data/lib/libis/tools/xml_document.rb +583 -0
- data/libis-tools.gemspec +55 -0
- data/spec/assert_spec.rb +65 -0
- data/spec/checksum_spec.rb +68 -0
- data/spec/command_spec.rb +90 -0
- data/spec/config_file_spec.rb +83 -0
- data/spec/config_spec.rb +113 -0
- data/spec/csv_spec.rb +159 -0
- data/spec/data/test-headers.csv +2 -0
- data/spec/data/test-headers.tsv +2 -0
- data/spec/data/test-noheaders.csv +1 -0
- data/spec/data/test-noheaders.tsv +1 -0
- data/spec/data/test.data +9 -0
- data/spec/data/test.xlsx +0 -0
- data/spec/data/test.xml +8 -0
- data/spec/data/test.yml +2 -0
- data/spec/data/test_config.yml +15 -0
- data/spec/deep_struct_spec.rb +138 -0
- data/spec/logger_spec.rb +165 -0
- data/spec/mets_file_spec.rb +223 -0
- data/spec/parameter_container_spec.rb +152 -0
- data/spec/parameter_spec.rb +148 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/spreadsheet_spec.rb +1820 -0
- data/spec/temp_file_spec.rb +76 -0
- data/spec/test.xsd +20 -0
- data/spec/thread_safe_spec.rb +64 -0
- data/spec/xmldocument_spec.rb +421 -0
- data/test/test_helper.rb +7 -0
- data/test/webservices/test_ca_item_info.rb +59 -0
- data/test/webservices/test_ca_search.rb +35 -0
- metadata +437 -0
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# require 'codeclimate-test-reporter'
|
2
|
+
# ::CodeClimate::TestReporter.start
|
3
|
+
|
4
|
+
# if !defined?(RUBY_ENGINE) || RUBY_ENGINE != 'jruby'
|
5
|
+
require 'coveralls'
|
6
|
+
Coveralls.wear!
|
7
|
+
# end
|
8
|
+
|
9
|
+
# noinspection RubyResolve
|
10
|
+
require 'bundler/setup'
|
11
|
+
# noinspection RubyResolve
|
12
|
+
Bundler.setup
|
13
|
+
|
14
|
+
require 'rspec'
|
15
|
+
require 'libis-tools'
|
16
|
+
|
17
|
+
# RSpec.configure do |config|
|
18
|
+
# original_stderr = $stderr
|
19
|
+
# original_stdout = $stdout
|
20
|
+
# config.before(:all) do
|
21
|
+
# # Redirect stderr and stdout
|
22
|
+
# $stderr = File.open(File::NULL, 'w')
|
23
|
+
# $stdout = File.open(File::NULL, 'w')
|
24
|
+
# end
|
25
|
+
# config.after(:all) do
|
26
|
+
# $stderr = original_stderr
|
27
|
+
# $stdout = original_stdout
|
28
|
+
# end
|
29
|
+
# end
|
@@ -0,0 +1,1820 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require_relative 'spec_helper'
|
3
|
+
require 'rspec/matchers'
|
4
|
+
require 'libis/tools/spreadsheet'
|
5
|
+
|
6
|
+
describe 'Libis::Tools::Spreadsheet' do
|
7
|
+
|
8
|
+
let(:path) {File.absolute_path('data', File.dirname(__FILE__))}
|
9
|
+
let(:options) { {} }
|
10
|
+
let(:ss) {
|
11
|
+
Libis::Tools::Spreadsheet.new(
|
12
|
+
File.join(path, file_name),
|
13
|
+
{ required: required_headers,
|
14
|
+
optional: optional_headers
|
15
|
+
}.merge(options)
|
16
|
+
)
|
17
|
+
}
|
18
|
+
|
19
|
+
let(:optional_headers) {[]}
|
20
|
+
|
21
|
+
context 'CSV file' do
|
22
|
+
context 'with headers' do
|
23
|
+
let(:file_name) {'test-headers.csv'}
|
24
|
+
|
25
|
+
context 'well-formed' do
|
26
|
+
|
27
|
+
let(:required_headers) {%w'FirstName LastName'}
|
28
|
+
|
29
|
+
it 'opens correctly' do
|
30
|
+
expect {ss}.not_to raise_error
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'contains expected headers' do
|
34
|
+
required_headers.each do |header|
|
35
|
+
expect(ss.headers).to include header
|
36
|
+
end
|
37
|
+
expect(ss.headers).to eq %w'FirstName LastName address'
|
38
|
+
end
|
39
|
+
|
40
|
+
it '#shift returns Hash object' do
|
41
|
+
row = ss.shift
|
42
|
+
expect(row).to be_a Hash
|
43
|
+
expect(row['FirstName']).to eq 'John'
|
44
|
+
expect(row['LastName']).to eq 'Smith'
|
45
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
46
|
+
expect(row['phone']).to be_nil
|
47
|
+
end
|
48
|
+
|
49
|
+
it '#parse returns Array of Hash objects' do
|
50
|
+
rows = ss.parse
|
51
|
+
expect(rows).to be_a Array
|
52
|
+
expect(rows.size).to eq 1
|
53
|
+
row = rows[0]
|
54
|
+
expect(row).to be_a Hash
|
55
|
+
expect(row['FirstName']).to eq 'John'
|
56
|
+
expect(row['LastName']).to eq 'Smith'
|
57
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
58
|
+
expect(row['phone']).to be_nil
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'not specified' do
|
64
|
+
|
65
|
+
let(:required_headers) {[]}
|
66
|
+
|
67
|
+
it 'opens correctly' do
|
68
|
+
expect {ss}.not_to raise_error
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'contains expected headers' do
|
72
|
+
expect(ss.headers).to eq %w'FirstName LastName address'
|
73
|
+
end
|
74
|
+
|
75
|
+
it '#shift returns Hash object' do
|
76
|
+
row = ss.shift
|
77
|
+
expect(row).to be_a Hash
|
78
|
+
expect(row['FirstName']).to eq 'John'
|
79
|
+
expect(row['LastName']).to eq 'Smith'
|
80
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
81
|
+
expect(row['phone']).to be_nil
|
82
|
+
end
|
83
|
+
|
84
|
+
it '#parse returns Array of Hash objects' do
|
85
|
+
rows = ss.parse
|
86
|
+
expect(rows).to be_a Array
|
87
|
+
expect(rows.size).to eq 1
|
88
|
+
row = rows[0]
|
89
|
+
expect(row).to be_a Hash
|
90
|
+
expect(row['FirstName']).to eq 'John'
|
91
|
+
expect(row['LastName']).to eq 'Smith'
|
92
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
93
|
+
expect(row['phone']).to be_nil
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'not well-formed' do
|
99
|
+
|
100
|
+
let(:required_headers) {%w'FirstName LastName address phone'}
|
101
|
+
|
102
|
+
it 'throws error when opened' do
|
103
|
+
expect {ss}.to raise_error(RuntimeError, 'Headers not found: ["phone"].')
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'without headers' do
|
110
|
+
let(:file_name) {'test-noheaders.csv'}
|
111
|
+
|
112
|
+
context 'well-formed and strict' do
|
113
|
+
let(:required_headers) {%w'FirstName LastName'}
|
114
|
+
|
115
|
+
it 'opens correctly' do
|
116
|
+
expect {ss}.not_to raise_error
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'contains only required headers' do
|
120
|
+
required_headers.each do |header|
|
121
|
+
expect(ss.headers).to include header
|
122
|
+
end
|
123
|
+
expect(ss.headers).to eq %w'FirstName LastName'
|
124
|
+
end
|
125
|
+
|
126
|
+
it '#shift returns Hash object' do
|
127
|
+
row = ss.shift
|
128
|
+
expect(row).to be_a Hash
|
129
|
+
expect(row['FirstName']).to eq 'John'
|
130
|
+
expect(row['LastName']).to eq 'Smith'
|
131
|
+
expect(row['address']).to be_nil
|
132
|
+
expect(row['phone']).to be_nil
|
133
|
+
end
|
134
|
+
|
135
|
+
it '#parse returns Array of Hash objects' do
|
136
|
+
rows = ss.parse
|
137
|
+
expect(rows).to be_a Array
|
138
|
+
expect(rows.size).to eq 1
|
139
|
+
row = rows[0]
|
140
|
+
expect(row).to be_a Hash
|
141
|
+
expect(row['FirstName']).to eq 'John'
|
142
|
+
expect(row['LastName']).to eq 'Smith'
|
143
|
+
expect(row['address']).to be_nil
|
144
|
+
expect(row['phone']).to be_nil
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
context 'well-formed with optional headers' do
|
150
|
+
let(:required_headers) {%w'FirstName LastName'}
|
151
|
+
let(:optional_headers) {%w'address'}
|
152
|
+
|
153
|
+
it 'opens correctly' do
|
154
|
+
expect {ss}.not_to raise_error
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'contains required and optional headers' do
|
158
|
+
required_headers.each do |header|
|
159
|
+
expect(ss.headers).to include header
|
160
|
+
end
|
161
|
+
optional_headers.each do |header|
|
162
|
+
expect(ss.headers).to include header
|
163
|
+
end
|
164
|
+
expect(ss.headers).to eq %w'FirstName LastName address'
|
165
|
+
end
|
166
|
+
|
167
|
+
it '#shift returns Hash object' do
|
168
|
+
row = ss.shift
|
169
|
+
expect(row).to be_a Hash
|
170
|
+
expect(row['FirstName']).to eq 'John'
|
171
|
+
expect(row['LastName']).to eq 'Smith'
|
172
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
173
|
+
expect(row['phone']).to be_nil
|
174
|
+
end
|
175
|
+
|
176
|
+
it '#parse returns Array of Hash objects' do
|
177
|
+
rows = ss.parse
|
178
|
+
expect(rows).to be_a Array
|
179
|
+
expect(rows.size).to eq 1
|
180
|
+
row = rows[0]
|
181
|
+
expect(row).to be_a Hash
|
182
|
+
expect(row['FirstName']).to eq 'John'
|
183
|
+
expect(row['LastName']).to eq 'Smith'
|
184
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
185
|
+
expect(row['phone']).to be_nil
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
context 'missing optional headers' do
|
191
|
+
|
192
|
+
let(:required_headers) {%w'FirstName LastName address'}
|
193
|
+
let(:optional_headers) {%w'phone'}
|
194
|
+
|
195
|
+
it 'opens correctly' do
|
196
|
+
expect {ss}.not_to raise_error
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'contains only required headers' do
|
200
|
+
required_headers.each do |header|
|
201
|
+
expect(ss.headers).to include header
|
202
|
+
end
|
203
|
+
optional_headers.each do |header|
|
204
|
+
expect(ss.headers).not_to include header
|
205
|
+
end
|
206
|
+
expect(ss.headers).to eq %w'FirstName LastName address'
|
207
|
+
end
|
208
|
+
|
209
|
+
it '#shift returns Hash object' do
|
210
|
+
row = ss.shift
|
211
|
+
expect(row).to be_a Hash
|
212
|
+
expect(row['FirstName']).to eq 'John'
|
213
|
+
expect(row['LastName']).to eq 'Smith'
|
214
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
215
|
+
expect(row['phone']).to be_nil
|
216
|
+
end
|
217
|
+
|
218
|
+
it '#parse returns Array of Hash objects' do
|
219
|
+
rows = ss.parse
|
220
|
+
expect(rows).to be_a Array
|
221
|
+
expect(rows.size).to eq 1
|
222
|
+
row = rows[0]
|
223
|
+
expect(row).to be_a Hash
|
224
|
+
expect(row['FirstName']).to eq 'John'
|
225
|
+
expect(row['LastName']).to eq 'Smith'
|
226
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
227
|
+
expect(row['phone']).to be_nil
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|
231
|
+
|
232
|
+
context 'missing required header' do
|
233
|
+
let(:required_headers) {%w'FirstName LastName address phone'}
|
234
|
+
|
235
|
+
it 'throws error when opened' do
|
236
|
+
expect {ss}.to raise_error(RuntimeError, 'Sheet does not contain enough columns.')
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
244
|
+
|
245
|
+
context 'TSV file' do
|
246
|
+
|
247
|
+
let(:options) { {
|
248
|
+
col_sep: "\t",
|
249
|
+
extension: 'csv'
|
250
|
+
}}
|
251
|
+
|
252
|
+
context 'with headers' do
|
253
|
+
|
254
|
+
let(:file_name) {'test-headers.tsv'}
|
255
|
+
|
256
|
+
context 'well-formed' do
|
257
|
+
|
258
|
+
let(:required_headers) {%w'FirstName LastName'}
|
259
|
+
|
260
|
+
it 'opens correctly' do
|
261
|
+
expect {ss}.not_to raise_error
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'contains expected headers' do
|
265
|
+
required_headers.each do |header|
|
266
|
+
expect(ss.headers).to include header
|
267
|
+
end
|
268
|
+
expect(ss.headers).to eq %w'FirstName LastName address'
|
269
|
+
end
|
270
|
+
|
271
|
+
it '#shift returns Hash object' do
|
272
|
+
row = ss.shift
|
273
|
+
expect(row).to be_a Hash
|
274
|
+
expect(row['FirstName']).to eq 'John'
|
275
|
+
expect(row['LastName']).to eq 'Smith'
|
276
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
277
|
+
expect(row['phone']).to be_nil
|
278
|
+
end
|
279
|
+
|
280
|
+
it '#parse returns Array of Hash objects' do
|
281
|
+
rows = ss.parse
|
282
|
+
expect(rows).to be_a Array
|
283
|
+
expect(rows.size).to eq 1
|
284
|
+
row = rows[0]
|
285
|
+
expect(row).to be_a Hash
|
286
|
+
expect(row['FirstName']).to eq 'John'
|
287
|
+
expect(row['LastName']).to eq 'Smith'
|
288
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
289
|
+
expect(row['phone']).to be_nil
|
290
|
+
end
|
291
|
+
|
292
|
+
end
|
293
|
+
|
294
|
+
context 'not specified' do
|
295
|
+
|
296
|
+
let(:required_headers) {[]}
|
297
|
+
|
298
|
+
it 'opens correctly' do
|
299
|
+
expect {ss}.not_to raise_error
|
300
|
+
end
|
301
|
+
|
302
|
+
it 'contains expected headers' do
|
303
|
+
expect(ss.headers).to eq %w'FirstName LastName address'
|
304
|
+
end
|
305
|
+
|
306
|
+
it '#shift returns Hash object' do
|
307
|
+
row = ss.shift
|
308
|
+
expect(row).to be_a Hash
|
309
|
+
expect(row['FirstName']).to eq 'John'
|
310
|
+
expect(row['LastName']).to eq 'Smith'
|
311
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
312
|
+
expect(row['phone']).to be_nil
|
313
|
+
end
|
314
|
+
|
315
|
+
it '#parse returns Array of Hash objects' do
|
316
|
+
rows = ss.parse
|
317
|
+
expect(rows).to be_a Array
|
318
|
+
expect(rows.size).to eq 1
|
319
|
+
row = rows[0]
|
320
|
+
expect(row).to be_a Hash
|
321
|
+
expect(row['FirstName']).to eq 'John'
|
322
|
+
expect(row['LastName']).to eq 'Smith'
|
323
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
324
|
+
expect(row['phone']).to be_nil
|
325
|
+
end
|
326
|
+
|
327
|
+
end
|
328
|
+
|
329
|
+
context 'not well-formed' do
|
330
|
+
|
331
|
+
let(:required_headers) {%w'FirstName LastName address phone'}
|
332
|
+
|
333
|
+
it 'throws error when opened' do
|
334
|
+
expect {ss}.to raise_error(RuntimeError, 'Headers not found: ["phone"].')
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
end
|
339
|
+
|
340
|
+
context 'without headers' do
|
341
|
+
let(:file_name) {'test-noheaders.tsv'}
|
342
|
+
|
343
|
+
context 'well-formed and strict' do
|
344
|
+
let(:required_headers) {%w'FirstName LastName'}
|
345
|
+
|
346
|
+
it 'opens correctly' do
|
347
|
+
expect {ss}.not_to raise_error
|
348
|
+
end
|
349
|
+
|
350
|
+
it 'contains only required headers' do
|
351
|
+
required_headers.each do |header|
|
352
|
+
expect(ss.headers).to include header
|
353
|
+
end
|
354
|
+
expect(ss.headers).to eq %w'FirstName LastName'
|
355
|
+
end
|
356
|
+
|
357
|
+
it '#shift returns Hash object' do
|
358
|
+
row = ss.shift
|
359
|
+
expect(row).to be_a Hash
|
360
|
+
expect(row['FirstName']).to eq 'John'
|
361
|
+
expect(row['LastName']).to eq 'Smith'
|
362
|
+
expect(row['address']).to be_nil
|
363
|
+
expect(row['phone']).to be_nil
|
364
|
+
end
|
365
|
+
|
366
|
+
it '#parse returns Array of Hash objects' do
|
367
|
+
rows = ss.parse
|
368
|
+
expect(rows).to be_a Array
|
369
|
+
expect(rows.size).to eq 1
|
370
|
+
row = rows[0]
|
371
|
+
expect(row).to be_a Hash
|
372
|
+
expect(row['FirstName']).to eq 'John'
|
373
|
+
expect(row['LastName']).to eq 'Smith'
|
374
|
+
expect(row['address']).to be_nil
|
375
|
+
expect(row['phone']).to be_nil
|
376
|
+
end
|
377
|
+
|
378
|
+
end
|
379
|
+
|
380
|
+
context 'well-formed with optional headers' do
|
381
|
+
let(:required_headers) {%w'FirstName LastName'}
|
382
|
+
let(:optional_headers) {%w'address'}
|
383
|
+
|
384
|
+
it 'opens correctly' do
|
385
|
+
expect {ss}.not_to raise_error
|
386
|
+
end
|
387
|
+
|
388
|
+
it 'contains required and optional headers' do
|
389
|
+
required_headers.each do |header|
|
390
|
+
expect(ss.headers).to include header
|
391
|
+
end
|
392
|
+
optional_headers.each do |header|
|
393
|
+
expect(ss.headers).to include header
|
394
|
+
end
|
395
|
+
expect(ss.headers).to eq %w'FirstName LastName address'
|
396
|
+
end
|
397
|
+
|
398
|
+
it '#shift returns Hash object' do
|
399
|
+
row = ss.shift
|
400
|
+
expect(row).to be_a Hash
|
401
|
+
expect(row['FirstName']).to eq 'John'
|
402
|
+
expect(row['LastName']).to eq 'Smith'
|
403
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
404
|
+
expect(row['phone']).to be_nil
|
405
|
+
end
|
406
|
+
|
407
|
+
it '#parse returns Array of Hash objects' do
|
408
|
+
rows = ss.parse
|
409
|
+
expect(rows).to be_a Array
|
410
|
+
expect(rows.size).to eq 1
|
411
|
+
row = rows[0]
|
412
|
+
expect(row).to be_a Hash
|
413
|
+
expect(row['FirstName']).to eq 'John'
|
414
|
+
expect(row['LastName']).to eq 'Smith'
|
415
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
416
|
+
expect(row['phone']).to be_nil
|
417
|
+
end
|
418
|
+
|
419
|
+
end
|
420
|
+
|
421
|
+
context 'missing optional headers' do
|
422
|
+
|
423
|
+
let(:required_headers) {%w'FirstName LastName address'}
|
424
|
+
let(:optional_headers) {%w'phone'}
|
425
|
+
|
426
|
+
it 'opens correctly' do
|
427
|
+
expect {ss}.not_to raise_error
|
428
|
+
end
|
429
|
+
|
430
|
+
it 'contains only required headers' do
|
431
|
+
required_headers.each do |header|
|
432
|
+
expect(ss.headers).to include header
|
433
|
+
end
|
434
|
+
optional_headers.each do |header|
|
435
|
+
expect(ss.headers).not_to include header
|
436
|
+
end
|
437
|
+
expect(ss.headers).to eq %w'FirstName LastName address'
|
438
|
+
end
|
439
|
+
|
440
|
+
it '#shift returns Hash object' do
|
441
|
+
row = ss.shift
|
442
|
+
expect(row).to be_a Hash
|
443
|
+
expect(row['FirstName']).to eq 'John'
|
444
|
+
expect(row['LastName']).to eq 'Smith'
|
445
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
446
|
+
expect(row['phone']).to be_nil
|
447
|
+
end
|
448
|
+
|
449
|
+
it '#parse returns Array of Hash objects' do
|
450
|
+
rows = ss.parse
|
451
|
+
expect(rows).to be_a Array
|
452
|
+
expect(rows.size).to eq 1
|
453
|
+
row = rows[0]
|
454
|
+
expect(row).to be_a Hash
|
455
|
+
expect(row['FirstName']).to eq 'John'
|
456
|
+
expect(row['LastName']).to eq 'Smith'
|
457
|
+
expect(row['address']).to eq 'mystreet 1, myplace'
|
458
|
+
expect(row['phone']).to be_nil
|
459
|
+
end
|
460
|
+
|
461
|
+
end
|
462
|
+
|
463
|
+
context 'missing required header' do
|
464
|
+
let(:required_headers) {%w'FirstName LastName address phone'}
|
465
|
+
|
466
|
+
it 'throws error when opened' do
|
467
|
+
expect {ss}.to raise_error(RuntimeError, 'Sheet does not contain enough columns.')
|
468
|
+
end
|
469
|
+
|
470
|
+
end
|
471
|
+
|
472
|
+
end
|
473
|
+
|
474
|
+
end
|
475
|
+
|
476
|
+
context 'XLSX file' do
|
477
|
+
|
478
|
+
let(:real_headers) {%w'Date Amount Code Remark'}
|
479
|
+
# noinspection RubyStringKeysInHashInspection
|
480
|
+
let(:header_row) {{'Date' => 'Date', 'Amount' => 'Amount', 'Code' => 'Code', 'Remark' => 'Remark'}}
|
481
|
+
# noinspection RubyStringKeysInHashInspection
|
482
|
+
let(:first_data_row) {{'Date' => Date.new(2016, 05, 10), 'Amount' => 1270.0, 'Code' => 1, 'Remark' => 'a'}}
|
483
|
+
# noinspection RubyStringKeysInHashInspection
|
484
|
+
let(:data_row_13) {{'Date' => Date.new(2016, 7, 1), 'Amount' => 3705.0, 'Code' => 3, 'Remark' => 'b'}}
|
485
|
+
let(:size_with_headers) { 18 }
|
486
|
+
let(:size_without_headers) { 17 }
|
487
|
+
|
488
|
+
context 'with headers' do
|
489
|
+
let(:file_name) {'test.xlsx|Expenses'}
|
490
|
+
|
491
|
+
context 'well-formed' do
|
492
|
+
|
493
|
+
let(:required_headers) {%w'Date Amount'}
|
494
|
+
|
495
|
+
it 'opens correctly' do
|
496
|
+
expect {ss}.not_to raise_error
|
497
|
+
end
|
498
|
+
|
499
|
+
it 'contains expected headers' do
|
500
|
+
required_headers.each do |header|
|
501
|
+
expect(ss.headers).to include header
|
502
|
+
end
|
503
|
+
expect(ss.headers).to eq real_headers
|
504
|
+
end
|
505
|
+
|
506
|
+
it 'each returns header and data rows' do
|
507
|
+
expect(ss.each.count).to eq size_with_headers
|
508
|
+
expect(ss.each.first).to eq header_row
|
509
|
+
end
|
510
|
+
|
511
|
+
it '#shift returns Hash object' do
|
512
|
+
row = ss.shift
|
513
|
+
expect(row).to be_a Hash
|
514
|
+
expect(row['Date']).to eq first_data_row['Date']
|
515
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
516
|
+
expect(row['Code']).to eq first_data_row['Code']
|
517
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
518
|
+
expect(row['dummy']).to be_nil
|
519
|
+
end
|
520
|
+
|
521
|
+
it '#parse returns Array of Hash objects' do
|
522
|
+
rows = ss.parse
|
523
|
+
expect(rows).to be_a Array
|
524
|
+
expect(rows.size).to eq size_without_headers
|
525
|
+
row = rows[0]
|
526
|
+
expect(row).to be_a Hash
|
527
|
+
expect(row['Date']).to eq first_data_row['Date']
|
528
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
529
|
+
expect(row['Code']).to eq first_data_row['Code']
|
530
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
531
|
+
expect(row['dummy']).to be_nil
|
532
|
+
row = rows[13]
|
533
|
+
expect(row).to be_a Hash
|
534
|
+
expect(row['Date']).to eq data_row_13['Date']
|
535
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
536
|
+
expect(row['Code']).to eq data_row_13['Code']
|
537
|
+
expect(row['Remark']).to eq data_row_13['Remark']
|
538
|
+
expect(row['dummy']).to be_nil
|
539
|
+
end
|
540
|
+
|
541
|
+
end
|
542
|
+
|
543
|
+
context 'not specified' do
|
544
|
+
|
545
|
+
let(:required_headers) {[]}
|
546
|
+
|
547
|
+
|
548
|
+
it 'opens correctly' do
|
549
|
+
expect {ss}.not_to raise_error
|
550
|
+
end
|
551
|
+
|
552
|
+
it 'contains expected headers' do
|
553
|
+
required_headers.each do |header|
|
554
|
+
expect(ss.headers).to include header
|
555
|
+
end
|
556
|
+
expect(ss.headers).to eq real_headers
|
557
|
+
end
|
558
|
+
|
559
|
+
it 'each returns header and data rows' do
|
560
|
+
expect(ss.each.count).to eq size_with_headers
|
561
|
+
expect(ss.each.first).to eq header_row
|
562
|
+
end
|
563
|
+
|
564
|
+
it '#shift returns Hash object' do
|
565
|
+
row = ss.shift
|
566
|
+
expect(row).to be_a Hash
|
567
|
+
expect(row['Date']).to eq first_data_row['Date']
|
568
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
569
|
+
expect(row['Code']).to eq first_data_row['Code']
|
570
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
571
|
+
expect(row['dummy']).to be_nil
|
572
|
+
end
|
573
|
+
|
574
|
+
it '#parse returns Array of Hash objects' do
|
575
|
+
rows = ss.parse
|
576
|
+
expect(rows).to be_a Array
|
577
|
+
expect(rows.size).to eq size_without_headers
|
578
|
+
row = rows[0]
|
579
|
+
expect(row).to be_a Hash
|
580
|
+
expect(row['Date']).to eq first_data_row['Date']
|
581
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
582
|
+
expect(row['Code']).to eq first_data_row['Code']
|
583
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
584
|
+
expect(row['dummy']).to be_nil
|
585
|
+
row = rows[13]
|
586
|
+
expect(row).to be_a Hash
|
587
|
+
expect(row['Date']).to eq data_row_13['Date']
|
588
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
589
|
+
expect(row['Code']).to eq data_row_13['Code']
|
590
|
+
expect(row['Remark']).to eq data_row_13['Remark']
|
591
|
+
expect(row['dummy']).to be_nil
|
592
|
+
end
|
593
|
+
|
594
|
+
end
|
595
|
+
|
596
|
+
context 'not well-formed' do
|
597
|
+
|
598
|
+
let(:required_headers) {%w'Date dummy1 Amount dummy2'}
|
599
|
+
|
600
|
+
it 'throws error when opened' do
|
601
|
+
expect {ss}.to raise_error(RuntimeError, 'Headers not found: ["dummy1", "dummy2"].')
|
602
|
+
end
|
603
|
+
end
|
604
|
+
|
605
|
+
end
|
606
|
+
|
607
|
+
context 'without headers' do
|
608
|
+
let(:file_name) {'test.xlsx|ExpensesNoHeaders'}
|
609
|
+
|
610
|
+
context 'well-formed and strict' do
|
611
|
+
let(:required_headers) {%w'Date Amount'}
|
612
|
+
|
613
|
+
it 'opens correctly' do
|
614
|
+
expect {ss}.not_to raise_error
|
615
|
+
end
|
616
|
+
|
617
|
+
it 'contains only required headers' do
|
618
|
+
required_headers.each do |header|
|
619
|
+
expect(ss.headers).to include header
|
620
|
+
end
|
621
|
+
expect(ss.headers).to eq required_headers
|
622
|
+
end
|
623
|
+
|
624
|
+
it 'each returns header and data rows' do
|
625
|
+
expect(ss.each.count).to eq size_with_headers
|
626
|
+
expect(ss.each.first.keys).to eq required_headers
|
627
|
+
end
|
628
|
+
|
629
|
+
it '#shift returns Hash object' do
|
630
|
+
row = ss.shift
|
631
|
+
expect(row).to be_a Hash
|
632
|
+
expect(row['Date']).to eq first_data_row['Date']
|
633
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
634
|
+
expect(row['Code']).to be_nil
|
635
|
+
expect(row['Remark']).to be_nil
|
636
|
+
expect(row['dummy']).to be_nil
|
637
|
+
end
|
638
|
+
|
639
|
+
it '#parse returns Array of Hash objects' do
|
640
|
+
rows = ss.parse
|
641
|
+
expect(rows).to be_a Array
|
642
|
+
expect(rows.size).to eq size_without_headers
|
643
|
+
row = rows[0]
|
644
|
+
expect(row).to be_a Hash
|
645
|
+
expect(row['Date']).to eq first_data_row['Date']
|
646
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
647
|
+
expect(row['Code']).to be_nil
|
648
|
+
expect(row['Remark']).to be_nil
|
649
|
+
expect(row['dummy']).to be_nil
|
650
|
+
row = rows[13]
|
651
|
+
expect(row).to be_a Hash
|
652
|
+
expect(row['Date']).to eq data_row_13['Date']
|
653
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
654
|
+
expect(row['Code']).to be_nil
|
655
|
+
expect(row['Remark']).to be_nil
|
656
|
+
expect(row['dummy']).to be_nil
|
657
|
+
end
|
658
|
+
|
659
|
+
end
|
660
|
+
|
661
|
+
context 'well-formed with optional headers' do
|
662
|
+
let(:required_headers) {%w'Date Amount'}
|
663
|
+
let(:optional_headers) {%w'Code'}
|
664
|
+
|
665
|
+
it 'opens correctly' do
|
666
|
+
expect {ss}.not_to raise_error
|
667
|
+
end
|
668
|
+
|
669
|
+
it 'contains required and optional headers' do
|
670
|
+
required_headers.each do |header|
|
671
|
+
expect(ss.headers).to include header
|
672
|
+
end
|
673
|
+
optional_headers.each do |header|
|
674
|
+
expect(ss.headers).to include header
|
675
|
+
end
|
676
|
+
expect(ss.headers).to eq required_headers + optional_headers
|
677
|
+
end
|
678
|
+
|
679
|
+
it 'each returns header and data rows' do
|
680
|
+
expect(ss.each.count).to eq size_with_headers
|
681
|
+
expect(ss.each.first.keys).to eq required_headers + optional_headers
|
682
|
+
end
|
683
|
+
|
684
|
+
it '#shift returns Hash object' do
|
685
|
+
row = ss.shift
|
686
|
+
expect(row).to be_a Hash
|
687
|
+
expect(row['Date']).to eq first_data_row['Date']
|
688
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
689
|
+
expect(row['Code']).to eq first_data_row['Code']
|
690
|
+
expect(row['Remark']).to be_nil
|
691
|
+
expect(row['dummy']).to be_nil
|
692
|
+
end
|
693
|
+
|
694
|
+
it '#parse returns Array of Hash objects' do
|
695
|
+
rows = ss.parse
|
696
|
+
expect(rows).to be_a Array
|
697
|
+
expect(rows.size).to eq size_without_headers
|
698
|
+
row = rows[0]
|
699
|
+
expect(row).to be_a Hash
|
700
|
+
expect(row['Date']).to eq first_data_row['Date']
|
701
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
702
|
+
expect(row['Code']).to eq first_data_row['Code']
|
703
|
+
expect(row['Remark']).to be_nil
|
704
|
+
expect(row['dummy']).to be_nil
|
705
|
+
row = rows[13]
|
706
|
+
expect(row).to be_a Hash
|
707
|
+
expect(row['Date']).to eq data_row_13['Date']
|
708
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
709
|
+
expect(row['Code']).to eq data_row_13['Code']
|
710
|
+
expect(row['Remark']).to be_nil
|
711
|
+
expect(row['dummy']).to be_nil
|
712
|
+
end
|
713
|
+
|
714
|
+
end
|
715
|
+
|
716
|
+
context 'missing optional headers' do
|
717
|
+
|
718
|
+
let(:required_headers) {%w'Date Amount Code Remark'}
|
719
|
+
let(:optional_headers) {%w'dummy'}
|
720
|
+
|
721
|
+
it 'opens correctly' do
|
722
|
+
expect {ss}.not_to raise_error
|
723
|
+
end
|
724
|
+
|
725
|
+
it 'contains only required headers' do
|
726
|
+
required_headers.each do |header|
|
727
|
+
expect(ss.headers).to include header
|
728
|
+
end
|
729
|
+
optional_headers.each do |header|
|
730
|
+
expect(ss.headers).not_to include header
|
731
|
+
end
|
732
|
+
expect(ss.headers).to eq required_headers
|
733
|
+
end
|
734
|
+
|
735
|
+
it 'each returns header and data rows' do
|
736
|
+
expect(ss.each.count).to eq size_with_headers
|
737
|
+
expect(ss.each.first.keys).to eq required_headers
|
738
|
+
end
|
739
|
+
|
740
|
+
it '#shift returns Hash object' do
|
741
|
+
row = ss.shift
|
742
|
+
expect(row).to be_a Hash
|
743
|
+
expect(row['Date']).to eq first_data_row['Date']
|
744
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
745
|
+
expect(row['Code']).to eq first_data_row['Code']
|
746
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
747
|
+
expect(row['dummy']).to be_nil
|
748
|
+
end
|
749
|
+
|
750
|
+
it '#parse returns Array of Hash objects' do
|
751
|
+
rows = ss.parse
|
752
|
+
expect(rows).to be_a Array
|
753
|
+
expect(rows.size).to eq size_without_headers
|
754
|
+
row = rows[0]
|
755
|
+
expect(row).to be_a Hash
|
756
|
+
expect(row['Date']).to eq first_data_row['Date']
|
757
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
758
|
+
expect(row['Code']).to eq first_data_row['Code']
|
759
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
760
|
+
expect(row['dummy']).to be_nil
|
761
|
+
row = rows[13]
|
762
|
+
expect(row).to be_a Hash
|
763
|
+
expect(row['Date']).to eq data_row_13['Date']
|
764
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
765
|
+
expect(row['Code']).to eq data_row_13['Code']
|
766
|
+
expect(row['Remark']).to eq data_row_13['Remark']
|
767
|
+
expect(row['dummy']).to be_nil
|
768
|
+
end
|
769
|
+
|
770
|
+
end
|
771
|
+
|
772
|
+
context 'missing required header' do
|
773
|
+
let(:required_headers) {%w'Date Amount Code Remark dummy'}
|
774
|
+
|
775
|
+
it 'throws error when opened' do
|
776
|
+
expect {ss}.to raise_error(RuntimeError, 'Sheet does not contain enough columns.')
|
777
|
+
end
|
778
|
+
|
779
|
+
end
|
780
|
+
|
781
|
+
end
|
782
|
+
|
783
|
+
context 'blank rows with headers' do
|
784
|
+
let(:file_name) {'test.xlsx|ExpensesBlankRows'}
|
785
|
+
|
786
|
+
context 'well-formed' do
|
787
|
+
|
788
|
+
let(:required_headers) {%w'Date Amount'}
|
789
|
+
|
790
|
+
it 'opens correctly' do
|
791
|
+
expect {ss}.not_to raise_error
|
792
|
+
end
|
793
|
+
|
794
|
+
it 'contains expected headers' do
|
795
|
+
required_headers.each do |header|
|
796
|
+
expect(ss.headers).to include header
|
797
|
+
end
|
798
|
+
expect(ss.headers).to eq real_headers
|
799
|
+
end
|
800
|
+
|
801
|
+
it 'each returns header and data rows' do
|
802
|
+
expect(ss.each.count).to eq size_with_headers
|
803
|
+
expect(ss.each.first).to eq header_row
|
804
|
+
end
|
805
|
+
|
806
|
+
it '#shift returns Hash object' do
|
807
|
+
row = ss.shift
|
808
|
+
expect(row).to be_a Hash
|
809
|
+
expect(row['Date']).to eq first_data_row['Date']
|
810
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
811
|
+
expect(row['Code']).to eq first_data_row['Code']
|
812
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
813
|
+
expect(row['dummy']).to be_nil
|
814
|
+
end
|
815
|
+
|
816
|
+
it '#parse returns Array of Hash objects' do
|
817
|
+
rows = ss.parse
|
818
|
+
expect(rows).to be_a Array
|
819
|
+
expect(rows.size).to eq size_without_headers
|
820
|
+
row = rows[0]
|
821
|
+
expect(row).to be_a Hash
|
822
|
+
expect(row['Date']).to eq first_data_row['Date']
|
823
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
824
|
+
expect(row['Code']).to eq first_data_row['Code']
|
825
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
826
|
+
expect(row['dummy']).to be_nil
|
827
|
+
row = rows[13]
|
828
|
+
expect(row).to be_a Hash
|
829
|
+
expect(row['Date']).to eq data_row_13['Date']
|
830
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
831
|
+
expect(row['Code']).to eq data_row_13['Code']
|
832
|
+
expect(row['Remark']).to eq data_row_13['Remark']
|
833
|
+
expect(row['dummy']).to be_nil
|
834
|
+
end
|
835
|
+
|
836
|
+
end
|
837
|
+
|
838
|
+
context 'not specified' do
|
839
|
+
|
840
|
+
let(:required_headers) {[]}
|
841
|
+
|
842
|
+
it 'opens correctly' do
|
843
|
+
expect {ss}.not_to raise_error
|
844
|
+
end
|
845
|
+
|
846
|
+
it 'contains expected headers' do
|
847
|
+
required_headers.each do |header|
|
848
|
+
expect(ss.headers).to include header
|
849
|
+
end
|
850
|
+
expect(ss.headers).to eq real_headers
|
851
|
+
end
|
852
|
+
|
853
|
+
it 'each returns header and data rows' do
|
854
|
+
expect(ss.each.count).to eq size_with_headers
|
855
|
+
expect(ss.each.first).to eq header_row
|
856
|
+
end
|
857
|
+
|
858
|
+
it '#shift returns Hash object' do
|
859
|
+
row = ss.shift
|
860
|
+
expect(row).to be_a Hash
|
861
|
+
expect(row['Date']).to eq first_data_row['Date']
|
862
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
863
|
+
expect(row['Code']).to eq first_data_row['Code']
|
864
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
865
|
+
expect(row['dummy']).to be_nil
|
866
|
+
end
|
867
|
+
|
868
|
+
it '#parse returns Array of Hash objects' do
|
869
|
+
rows = ss.parse
|
870
|
+
expect(rows).to be_a Array
|
871
|
+
expect(rows.size).to eq size_without_headers
|
872
|
+
row = rows[0]
|
873
|
+
expect(row).to be_a Hash
|
874
|
+
expect(row['Date']).to eq first_data_row['Date']
|
875
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
876
|
+
expect(row['Code']).to eq first_data_row['Code']
|
877
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
878
|
+
expect(row['dummy']).to be_nil
|
879
|
+
row = rows[13]
|
880
|
+
expect(row).to be_a Hash
|
881
|
+
expect(row['Date']).to eq data_row_13['Date']
|
882
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
883
|
+
expect(row['Code']).to eq data_row_13['Code']
|
884
|
+
expect(row['Remark']).to eq data_row_13['Remark']
|
885
|
+
expect(row['dummy']).to be_nil
|
886
|
+
end
|
887
|
+
|
888
|
+
end
|
889
|
+
|
890
|
+
context 'not well-formed' do
|
891
|
+
|
892
|
+
let(:required_headers) {%w'Date dummy1 Amount dummy2'}
|
893
|
+
|
894
|
+
it 'throws error when opened' do
|
895
|
+
expect {ss}.to raise_error(RuntimeError, 'Headers not found: ["dummy1", "dummy2"].')
|
896
|
+
end
|
897
|
+
end
|
898
|
+
|
899
|
+
end
|
900
|
+
|
901
|
+
context 'blank rows without headers' do
|
902
|
+
let(:file_name) {'test.xlsx|ExpensesBlankRowsNoHeaders'}
|
903
|
+
|
904
|
+
context 'well-formed and strict' do
|
905
|
+
let(:required_headers) {%w'Date Amount'}
|
906
|
+
|
907
|
+
it 'opens correctly' do
|
908
|
+
expect {ss}.not_to raise_error
|
909
|
+
end
|
910
|
+
|
911
|
+
it 'contains only required headers' do
|
912
|
+
required_headers.each do |header|
|
913
|
+
expect(ss.headers).to include header
|
914
|
+
end
|
915
|
+
expect(ss.headers).to eq required_headers
|
916
|
+
end
|
917
|
+
|
918
|
+
it 'each returns header and data rows' do
|
919
|
+
expect(ss.each.count).to eq size_with_headers
|
920
|
+
expect(ss.each.first.keys).to eq required_headers
|
921
|
+
end
|
922
|
+
|
923
|
+
it '#shift returns Hash object' do
|
924
|
+
row = ss.shift
|
925
|
+
expect(row).to be_a Hash
|
926
|
+
expect(row['Date']).to eq first_data_row['Date']
|
927
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
928
|
+
expect(row['Code']).to be_nil
|
929
|
+
expect(row['Remark']).to be_nil
|
930
|
+
expect(row['dummy']).to be_nil
|
931
|
+
end
|
932
|
+
|
933
|
+
it '#parse returns Array of Hash objects' do
|
934
|
+
rows = ss.parse
|
935
|
+
expect(rows).to be_a Array
|
936
|
+
expect(rows.size).to eq size_without_headers
|
937
|
+
row = rows[0]
|
938
|
+
expect(row).to be_a Hash
|
939
|
+
expect(row['Date']).to eq first_data_row['Date']
|
940
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
941
|
+
expect(row['Code']).to be_nil
|
942
|
+
expect(row['Remark']).to be_nil
|
943
|
+
expect(row['dummy']).to be_nil
|
944
|
+
row = rows[13]
|
945
|
+
expect(row).to be_a Hash
|
946
|
+
expect(row['Date']).to eq data_row_13['Date']
|
947
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
948
|
+
expect(row['Code']).to be_nil
|
949
|
+
expect(row['Remark']).to be_nil
|
950
|
+
expect(row['dummy']).to be_nil
|
951
|
+
end
|
952
|
+
|
953
|
+
end
|
954
|
+
|
955
|
+
context 'well-formed with optional headers' do
|
956
|
+
let(:required_headers) {%w'Date Amount'}
|
957
|
+
let(:optional_headers) {%w'Code'}
|
958
|
+
|
959
|
+
it 'opens correctly' do
|
960
|
+
expect {ss}.not_to raise_error
|
961
|
+
end
|
962
|
+
|
963
|
+
it 'contains required and optional headers' do
|
964
|
+
required_headers.each do |header|
|
965
|
+
expect(ss.headers).to include header
|
966
|
+
end
|
967
|
+
optional_headers.each do |header|
|
968
|
+
expect(ss.headers).to include header
|
969
|
+
end
|
970
|
+
expect(ss.headers).to eq required_headers + optional_headers
|
971
|
+
end
|
972
|
+
|
973
|
+
it 'each returns header and data rows' do
|
974
|
+
expect(ss.each.count).to eq size_with_headers
|
975
|
+
expect(ss.each.first.keys).to eq required_headers + optional_headers
|
976
|
+
end
|
977
|
+
|
978
|
+
it '#shift returns Hash object' do
|
979
|
+
row = ss.shift
|
980
|
+
expect(row).to be_a Hash
|
981
|
+
expect(row['Date']).to eq first_data_row['Date']
|
982
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
983
|
+
expect(row['Code']).to eq first_data_row['Code']
|
984
|
+
expect(row['Remark']).to be_nil
|
985
|
+
expect(row['dummy']).to be_nil
|
986
|
+
end
|
987
|
+
|
988
|
+
it '#parse returns Array of Hash objects' do
|
989
|
+
rows = ss.parse
|
990
|
+
expect(rows).to be_a Array
|
991
|
+
expect(rows.size).to eq size_without_headers
|
992
|
+
row = rows[0]
|
993
|
+
expect(row).to be_a Hash
|
994
|
+
expect(row['Date']).to eq first_data_row['Date']
|
995
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
996
|
+
expect(row['Code']).to eq first_data_row['Code']
|
997
|
+
expect(row['Remark']).to be_nil
|
998
|
+
expect(row['dummy']).to be_nil
|
999
|
+
row = rows[13]
|
1000
|
+
expect(row).to be_a Hash
|
1001
|
+
expect(row['Date']).to eq data_row_13['Date']
|
1002
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
1003
|
+
expect(row['Code']).to eq data_row_13['Code']
|
1004
|
+
expect(row['Remark']).to be_nil
|
1005
|
+
expect(row['dummy']).to be_nil
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
end
|
1009
|
+
|
1010
|
+
context 'missing optional headers' do
|
1011
|
+
|
1012
|
+
let(:required_headers) {%w'Date Amount Code Remark'}
|
1013
|
+
let(:optional_headers) {%w'dummy'}
|
1014
|
+
|
1015
|
+
it 'opens correctly' do
|
1016
|
+
expect {ss}.not_to raise_error
|
1017
|
+
end
|
1018
|
+
|
1019
|
+
it 'contains only required headers' do
|
1020
|
+
required_headers.each do |header|
|
1021
|
+
expect(ss.headers).to include header
|
1022
|
+
end
|
1023
|
+
optional_headers.each do |header|
|
1024
|
+
expect(ss.headers).not_to include header
|
1025
|
+
end
|
1026
|
+
expect(ss.headers).to eq required_headers
|
1027
|
+
end
|
1028
|
+
|
1029
|
+
it 'each returns header and data rows' do
|
1030
|
+
expect(ss.each.count).to eq size_with_headers
|
1031
|
+
expect(ss.each.first.keys).to eq required_headers
|
1032
|
+
end
|
1033
|
+
|
1034
|
+
it '#shift returns Hash object' do
|
1035
|
+
row = ss.shift
|
1036
|
+
expect(row).to be_a Hash
|
1037
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1038
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1039
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1040
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
1041
|
+
expect(row['dummy']).to be_nil
|
1042
|
+
end
|
1043
|
+
|
1044
|
+
it '#parse returns Array of Hash objects' do
|
1045
|
+
rows = ss.parse
|
1046
|
+
expect(rows).to be_a Array
|
1047
|
+
expect(rows.size).to eq size_without_headers
|
1048
|
+
row = rows[0]
|
1049
|
+
expect(row).to be_a Hash
|
1050
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1051
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1052
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1053
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
1054
|
+
expect(row['dummy']).to be_nil
|
1055
|
+
row = rows[13]
|
1056
|
+
expect(row).to be_a Hash
|
1057
|
+
expect(row['Date']).to eq data_row_13['Date']
|
1058
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
1059
|
+
expect(row['Code']).to eq data_row_13['Code']
|
1060
|
+
expect(row['Remark']).to eq data_row_13['Remark']
|
1061
|
+
expect(row['dummy']).to be_nil
|
1062
|
+
end
|
1063
|
+
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
context 'missing required header' do
|
1067
|
+
let(:required_headers) {%w'Date Amount Code Remark dummy'}
|
1068
|
+
|
1069
|
+
it 'throws error when opened' do
|
1070
|
+
expect {ss}.to raise_error(RuntimeError, 'Sheet does not contain enough columns.')
|
1071
|
+
end
|
1072
|
+
|
1073
|
+
end
|
1074
|
+
|
1075
|
+
end
|
1076
|
+
|
1077
|
+
context 'blank columns with headers' do
|
1078
|
+
let(:file_name) {'test.xlsx|ExpensesBlankColumns'}
|
1079
|
+
|
1080
|
+
context 'well-formed' do
|
1081
|
+
|
1082
|
+
let(:required_headers) {%w'Date Amount'}
|
1083
|
+
|
1084
|
+
it 'opens correctly' do
|
1085
|
+
expect {ss}.not_to raise_error
|
1086
|
+
end
|
1087
|
+
|
1088
|
+
it 'contains expected headers' do
|
1089
|
+
required_headers.each do |header|
|
1090
|
+
expect(ss.headers).to include header
|
1091
|
+
end
|
1092
|
+
expect(ss.headers).to eq real_headers
|
1093
|
+
end
|
1094
|
+
|
1095
|
+
it 'each returns header and data rows' do
|
1096
|
+
expect(ss.each.count).to eq size_with_headers
|
1097
|
+
expect(ss.each.first).to eq header_row
|
1098
|
+
end
|
1099
|
+
|
1100
|
+
it '#shift returns Hash object' do
|
1101
|
+
row = ss.shift
|
1102
|
+
expect(row).to be_a Hash
|
1103
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1104
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1105
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1106
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
1107
|
+
expect(row['dummy']).to be_nil
|
1108
|
+
end
|
1109
|
+
|
1110
|
+
it '#parse returns Array of Hash objects' do
|
1111
|
+
rows = ss.parse
|
1112
|
+
expect(rows).to be_a Array
|
1113
|
+
expect(rows.size).to eq size_without_headers
|
1114
|
+
row = rows[0]
|
1115
|
+
expect(row).to be_a Hash
|
1116
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1117
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1118
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1119
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
1120
|
+
expect(row['dummy']).to be_nil
|
1121
|
+
row = rows[13]
|
1122
|
+
expect(row).to be_a Hash
|
1123
|
+
expect(row['Date']).to eq data_row_13['Date']
|
1124
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
1125
|
+
expect(row['Code']).to eq data_row_13['Code']
|
1126
|
+
expect(row['Remark']).to eq data_row_13['Remark']
|
1127
|
+
expect(row['dummy']).to be_nil
|
1128
|
+
end
|
1129
|
+
|
1130
|
+
end
|
1131
|
+
|
1132
|
+
context 'not specified' do
|
1133
|
+
|
1134
|
+
let(:required_headers) {[]}
|
1135
|
+
|
1136
|
+
it 'opens correctly' do
|
1137
|
+
expect {ss}.not_to raise_error
|
1138
|
+
end
|
1139
|
+
|
1140
|
+
it 'contains expected headers' do
|
1141
|
+
required_headers.each do |header|
|
1142
|
+
expect(ss.headers).to include header
|
1143
|
+
end
|
1144
|
+
expect(ss.headers).to eq real_headers
|
1145
|
+
end
|
1146
|
+
|
1147
|
+
it 'each returns header and data rows' do
|
1148
|
+
expect(ss.each.count).to eq size_with_headers
|
1149
|
+
expect(ss.each.first).to eq header_row
|
1150
|
+
end
|
1151
|
+
|
1152
|
+
it '#shift returns Hash object' do
|
1153
|
+
row = ss.shift
|
1154
|
+
expect(row).to be_a Hash
|
1155
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1156
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1157
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1158
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
1159
|
+
expect(row['dummy']).to be_nil
|
1160
|
+
end
|
1161
|
+
|
1162
|
+
it '#parse returns Array of Hash objects' do
|
1163
|
+
rows = ss.parse
|
1164
|
+
expect(rows).to be_a Array
|
1165
|
+
expect(rows.size).to eq size_without_headers
|
1166
|
+
row = rows[0]
|
1167
|
+
expect(row).to be_a Hash
|
1168
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1169
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1170
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1171
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
1172
|
+
expect(row['dummy']).to be_nil
|
1173
|
+
row = rows[13]
|
1174
|
+
expect(row).to be_a Hash
|
1175
|
+
expect(row['Date']).to eq data_row_13['Date']
|
1176
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
1177
|
+
expect(row['Code']).to eq data_row_13['Code']
|
1178
|
+
expect(row['Remark']).to eq data_row_13['Remark']
|
1179
|
+
expect(row['dummy']).to be_nil
|
1180
|
+
end
|
1181
|
+
|
1182
|
+
end
|
1183
|
+
|
1184
|
+
context 'not well-formed' do
|
1185
|
+
|
1186
|
+
let(:required_headers) {%w'Date dummy1 Amount dummy2'}
|
1187
|
+
|
1188
|
+
it 'throws error when opened' do
|
1189
|
+
expect {ss}.to raise_error(RuntimeError, 'Headers not found: ["dummy1", "dummy2"].')
|
1190
|
+
end
|
1191
|
+
end
|
1192
|
+
|
1193
|
+
end
|
1194
|
+
|
1195
|
+
context 'blank columns without headers' do
|
1196
|
+
let(:file_name) {'test.xlsx|ExpensesBlankColumnsNoHeaders'}
|
1197
|
+
|
1198
|
+
context 'well-formed and strict' do
|
1199
|
+
let(:required_headers) {%w'Date Amount'}
|
1200
|
+
|
1201
|
+
it 'opens correctly' do
|
1202
|
+
expect {ss}.not_to raise_error
|
1203
|
+
end
|
1204
|
+
|
1205
|
+
it 'contains only required headers' do
|
1206
|
+
required_headers.each do |header|
|
1207
|
+
expect(ss.headers).to include header
|
1208
|
+
end
|
1209
|
+
expect(ss.headers).to eq required_headers
|
1210
|
+
end
|
1211
|
+
|
1212
|
+
it 'each returns header and data rows' do
|
1213
|
+
expect(ss.each.count).to eq size_with_headers
|
1214
|
+
expect(ss.each.first.keys).to eq required_headers
|
1215
|
+
end
|
1216
|
+
|
1217
|
+
it '#shift returns Hash object' do
|
1218
|
+
row = ss.shift
|
1219
|
+
expect(row).to be_a Hash
|
1220
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1221
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1222
|
+
expect(row['Code']).to be_nil
|
1223
|
+
expect(row['Remark']).to be_nil
|
1224
|
+
expect(row['dummy']).to be_nil
|
1225
|
+
end
|
1226
|
+
|
1227
|
+
it '#parse returns Array of Hash objects' do
|
1228
|
+
rows = ss.parse
|
1229
|
+
expect(rows).to be_a Array
|
1230
|
+
expect(rows.size).to eq size_without_headers
|
1231
|
+
row = rows[0]
|
1232
|
+
expect(row).to be_a Hash
|
1233
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1234
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1235
|
+
expect(row['Code']).to be_nil
|
1236
|
+
expect(row['Remark']).to be_nil
|
1237
|
+
expect(row['dummy']).to be_nil
|
1238
|
+
row = rows[13]
|
1239
|
+
expect(row).to be_a Hash
|
1240
|
+
expect(row['Date']).to eq data_row_13['Date']
|
1241
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
1242
|
+
expect(row['Code']).to be_nil
|
1243
|
+
expect(row['Remark']).to be_nil
|
1244
|
+
expect(row['dummy']).to be_nil
|
1245
|
+
end
|
1246
|
+
|
1247
|
+
end
|
1248
|
+
|
1249
|
+
context 'well-formed with optional headers' do
|
1250
|
+
let(:required_headers) {%w'Date Amount'}
|
1251
|
+
let(:optional_headers) {%w'Code'}
|
1252
|
+
|
1253
|
+
it 'opens correctly' do
|
1254
|
+
expect {ss}.not_to raise_error
|
1255
|
+
end
|
1256
|
+
|
1257
|
+
it 'contains required and optional headers' do
|
1258
|
+
required_headers.each do |header|
|
1259
|
+
expect(ss.headers).to include header
|
1260
|
+
end
|
1261
|
+
optional_headers.each do |header|
|
1262
|
+
expect(ss.headers).to include header
|
1263
|
+
end
|
1264
|
+
expect(ss.headers).to eq required_headers + optional_headers
|
1265
|
+
end
|
1266
|
+
|
1267
|
+
it 'each returns header and data rows' do
|
1268
|
+
expect(ss.each.count).to eq size_with_headers
|
1269
|
+
expect(ss.each.first.keys).to eq required_headers + optional_headers
|
1270
|
+
end
|
1271
|
+
|
1272
|
+
it '#shift returns Hash object' do
|
1273
|
+
row = ss.shift
|
1274
|
+
expect(row).to be_a Hash
|
1275
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1276
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1277
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1278
|
+
expect(row['Remark']).to be_nil
|
1279
|
+
expect(row['dummy']).to be_nil
|
1280
|
+
end
|
1281
|
+
|
1282
|
+
it '#parse returns Array of Hash objects' do
|
1283
|
+
rows = ss.parse
|
1284
|
+
expect(rows).to be_a Array
|
1285
|
+
expect(rows.size).to eq size_without_headers
|
1286
|
+
row = rows[0]
|
1287
|
+
expect(row).to be_a Hash
|
1288
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1289
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1290
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1291
|
+
expect(row['Remark']).to be_nil
|
1292
|
+
expect(row['dummy']).to be_nil
|
1293
|
+
row = rows[13]
|
1294
|
+
expect(row).to be_a Hash
|
1295
|
+
expect(row['Date']).to eq data_row_13['Date']
|
1296
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
1297
|
+
expect(row['Code']).to eq data_row_13['Code']
|
1298
|
+
expect(row['Remark']).to be_nil
|
1299
|
+
expect(row['dummy']).to be_nil
|
1300
|
+
end
|
1301
|
+
|
1302
|
+
end
|
1303
|
+
|
1304
|
+
context 'missing optional headers' do
|
1305
|
+
|
1306
|
+
let(:required_headers) {%w'Date Amount Code Remark'}
|
1307
|
+
let(:optional_headers) {%w'dummy'}
|
1308
|
+
|
1309
|
+
it 'opens correctly' do
|
1310
|
+
expect {ss}.not_to raise_error
|
1311
|
+
end
|
1312
|
+
|
1313
|
+
it 'contains only required headers' do
|
1314
|
+
required_headers.each do |header|
|
1315
|
+
expect(ss.headers).to include header
|
1316
|
+
end
|
1317
|
+
optional_headers.each do |header|
|
1318
|
+
expect(ss.headers).not_to include header
|
1319
|
+
end
|
1320
|
+
expect(ss.headers).to eq required_headers
|
1321
|
+
end
|
1322
|
+
|
1323
|
+
it 'each returns header and data rows' do
|
1324
|
+
expect(ss.each.count).to eq size_with_headers
|
1325
|
+
expect(ss.each.first.keys).to eq required_headers
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
it '#shift returns Hash object' do
|
1329
|
+
row = ss.shift
|
1330
|
+
expect(row).to be_a Hash
|
1331
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1332
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1333
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1334
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
1335
|
+
expect(row['dummy']).to be_nil
|
1336
|
+
end
|
1337
|
+
|
1338
|
+
it '#parse returns Array of Hash objects' do
|
1339
|
+
rows = ss.parse
|
1340
|
+
expect(rows).to be_a Array
|
1341
|
+
expect(rows.size).to eq size_without_headers
|
1342
|
+
row = rows[0]
|
1343
|
+
expect(row).to be_a Hash
|
1344
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1345
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1346
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1347
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
1348
|
+
expect(row['dummy']).to be_nil
|
1349
|
+
row = rows[13]
|
1350
|
+
expect(row).to be_a Hash
|
1351
|
+
expect(row['Date']).to eq data_row_13['Date']
|
1352
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
1353
|
+
expect(row['Code']).to eq data_row_13['Code']
|
1354
|
+
expect(row['Remark']).to eq data_row_13['Remark']
|
1355
|
+
expect(row['dummy']).to be_nil
|
1356
|
+
end
|
1357
|
+
|
1358
|
+
end
|
1359
|
+
|
1360
|
+
context 'missing required header' do
|
1361
|
+
let(:required_headers) {%w'Date Amount Code Remark dummy'}
|
1362
|
+
|
1363
|
+
it 'throws error when opened' do
|
1364
|
+
expect {ss}.to raise_error(RuntimeError, 'Sheet does not contain enough columns.')
|
1365
|
+
end
|
1366
|
+
|
1367
|
+
end
|
1368
|
+
|
1369
|
+
end
|
1370
|
+
|
1371
|
+
context 'blank row and columns with headers' do
|
1372
|
+
let(:file_name) {'test.xlsx|ExpensesBlankRowsAndColumns'}
|
1373
|
+
|
1374
|
+
context 'well-formed' do
|
1375
|
+
|
1376
|
+
let(:required_headers) {%w'Date Amount'}
|
1377
|
+
|
1378
|
+
it 'opens correctly' do
|
1379
|
+
expect {ss}.not_to raise_error
|
1380
|
+
end
|
1381
|
+
|
1382
|
+
it 'contains expected headers' do
|
1383
|
+
required_headers.each do |header|
|
1384
|
+
expect(ss.headers).to include header
|
1385
|
+
end
|
1386
|
+
expect(ss.headers).to eq real_headers
|
1387
|
+
end
|
1388
|
+
|
1389
|
+
it 'each returns header and data rows' do
|
1390
|
+
expect(ss.each.count).to eq size_with_headers
|
1391
|
+
expect(ss.each.first).to eq header_row
|
1392
|
+
end
|
1393
|
+
|
1394
|
+
it '#shift returns Hash object' do
|
1395
|
+
row = ss.shift
|
1396
|
+
expect(row).to be_a Hash
|
1397
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1398
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1399
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1400
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
1401
|
+
expect(row['dummy']).to be_nil
|
1402
|
+
end
|
1403
|
+
|
1404
|
+
it '#parse returns Array of Hash objects' do
|
1405
|
+
rows = ss.parse
|
1406
|
+
expect(rows).to be_a Array
|
1407
|
+
expect(rows.size).to eq size_without_headers
|
1408
|
+
row = rows[0]
|
1409
|
+
expect(row).to be_a Hash
|
1410
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1411
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1412
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1413
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
1414
|
+
expect(row['dummy']).to be_nil
|
1415
|
+
row = rows[13]
|
1416
|
+
expect(row).to be_a Hash
|
1417
|
+
expect(row['Date']).to eq data_row_13['Date']
|
1418
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
1419
|
+
expect(row['Code']).to eq data_row_13['Code']
|
1420
|
+
expect(row['Remark']).to eq data_row_13['Remark']
|
1421
|
+
expect(row['dummy']).to be_nil
|
1422
|
+
end
|
1423
|
+
|
1424
|
+
end
|
1425
|
+
|
1426
|
+
context 'not specified' do
|
1427
|
+
|
1428
|
+
let(:required_headers) {[]}
|
1429
|
+
|
1430
|
+
it 'opens correctly' do
|
1431
|
+
expect {ss}.not_to raise_error
|
1432
|
+
end
|
1433
|
+
|
1434
|
+
it 'contains expected headers' do
|
1435
|
+
required_headers.each do |header|
|
1436
|
+
expect(ss.headers).to include header
|
1437
|
+
end
|
1438
|
+
expect(ss.headers).to eq real_headers
|
1439
|
+
end
|
1440
|
+
|
1441
|
+
it 'each returns header and data rows' do
|
1442
|
+
expect(ss.each.count).to eq size_with_headers
|
1443
|
+
expect(ss.each.first).to eq header_row
|
1444
|
+
end
|
1445
|
+
|
1446
|
+
it '#shift returns Hash object' do
|
1447
|
+
row = ss.shift
|
1448
|
+
expect(row).to be_a Hash
|
1449
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1450
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1451
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1452
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
1453
|
+
expect(row['dummy']).to be_nil
|
1454
|
+
end
|
1455
|
+
|
1456
|
+
it '#parse returns Array of Hash objects' do
|
1457
|
+
rows = ss.parse
|
1458
|
+
expect(rows).to be_a Array
|
1459
|
+
expect(rows.size).to eq size_without_headers
|
1460
|
+
row = rows[0]
|
1461
|
+
expect(row).to be_a Hash
|
1462
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1463
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1464
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1465
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
1466
|
+
expect(row['dummy']).to be_nil
|
1467
|
+
row = rows[13]
|
1468
|
+
expect(row).to be_a Hash
|
1469
|
+
expect(row['Date']).to eq data_row_13['Date']
|
1470
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
1471
|
+
expect(row['Code']).to eq data_row_13['Code']
|
1472
|
+
expect(row['Remark']).to eq data_row_13['Remark']
|
1473
|
+
expect(row['dummy']).to be_nil
|
1474
|
+
end
|
1475
|
+
|
1476
|
+
end
|
1477
|
+
|
1478
|
+
context 'not well-formed' do
|
1479
|
+
|
1480
|
+
let(:required_headers) {%w'Date dummy1 Amount dummy2'}
|
1481
|
+
|
1482
|
+
it 'throws error when opened' do
|
1483
|
+
expect {ss}.to raise_error(RuntimeError, 'Headers not found: ["dummy1", "dummy2"].')
|
1484
|
+
end
|
1485
|
+
end
|
1486
|
+
|
1487
|
+
end
|
1488
|
+
|
1489
|
+
context 'blank row and columns without headers' do
|
1490
|
+
let(:file_name) {'test.xlsx|ExpensesBlankRowsAndColumnsNoH'}
|
1491
|
+
|
1492
|
+
context 'well-formed and strict' do
|
1493
|
+
let(:required_headers) {%w'Date Amount'}
|
1494
|
+
|
1495
|
+
it 'opens correctly' do
|
1496
|
+
expect {ss}.not_to raise_error
|
1497
|
+
end
|
1498
|
+
|
1499
|
+
it 'contains only required headers' do
|
1500
|
+
required_headers.each do |header|
|
1501
|
+
expect(ss.headers).to include header
|
1502
|
+
end
|
1503
|
+
expect(ss.headers).to eq required_headers
|
1504
|
+
end
|
1505
|
+
|
1506
|
+
it 'each returns header and data rows' do
|
1507
|
+
expect(ss.each.count).to eq size_with_headers
|
1508
|
+
expect(ss.each.first.keys).to eq required_headers
|
1509
|
+
end
|
1510
|
+
|
1511
|
+
it '#shift returns Hash object' do
|
1512
|
+
row = ss.shift
|
1513
|
+
expect(row).to be_a Hash
|
1514
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1515
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1516
|
+
expect(row['Code']).to be_nil
|
1517
|
+
expect(row['Remark']).to be_nil
|
1518
|
+
expect(row['dummy']).to be_nil
|
1519
|
+
end
|
1520
|
+
|
1521
|
+
it '#parse returns Array of Hash objects' do
|
1522
|
+
rows = ss.parse
|
1523
|
+
expect(rows).to be_a Array
|
1524
|
+
expect(rows.size).to eq size_without_headers
|
1525
|
+
row = rows[0]
|
1526
|
+
expect(row).to be_a Hash
|
1527
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1528
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1529
|
+
expect(row['Code']).to be_nil
|
1530
|
+
expect(row['Remark']).to be_nil
|
1531
|
+
expect(row['dummy']).to be_nil
|
1532
|
+
row = rows[13]
|
1533
|
+
expect(row).to be_a Hash
|
1534
|
+
expect(row['Date']).to eq data_row_13['Date']
|
1535
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
1536
|
+
expect(row['Code']).to be_nil
|
1537
|
+
expect(row['Remark']).to be_nil
|
1538
|
+
expect(row['dummy']).to be_nil
|
1539
|
+
end
|
1540
|
+
|
1541
|
+
end
|
1542
|
+
|
1543
|
+
context 'well-formed with optional headers' do
|
1544
|
+
let(:required_headers) {%w'Date Amount'}
|
1545
|
+
let(:optional_headers) {%w'Code'}
|
1546
|
+
|
1547
|
+
it 'opens correctly' do
|
1548
|
+
expect {ss}.not_to raise_error
|
1549
|
+
end
|
1550
|
+
|
1551
|
+
it 'contains required and optional headers' do
|
1552
|
+
required_headers.each do |header|
|
1553
|
+
expect(ss.headers).to include header
|
1554
|
+
end
|
1555
|
+
optional_headers.each do |header|
|
1556
|
+
expect(ss.headers).to include header
|
1557
|
+
end
|
1558
|
+
expect(ss.headers).to eq required_headers + optional_headers
|
1559
|
+
end
|
1560
|
+
|
1561
|
+
it 'each returns header and data rows' do
|
1562
|
+
expect(ss.each.count).to eq size_with_headers
|
1563
|
+
expect(ss.each.first.keys).to eq required_headers + optional_headers
|
1564
|
+
end
|
1565
|
+
|
1566
|
+
it '#shift returns Hash object' do
|
1567
|
+
row = ss.shift
|
1568
|
+
expect(row).to be_a Hash
|
1569
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1570
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1571
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1572
|
+
expect(row['Remark']).to be_nil
|
1573
|
+
expect(row['dummy']).to be_nil
|
1574
|
+
end
|
1575
|
+
|
1576
|
+
it '#parse returns Array of Hash objects' do
|
1577
|
+
rows = ss.parse
|
1578
|
+
expect(rows).to be_a Array
|
1579
|
+
expect(rows.size).to eq size_without_headers
|
1580
|
+
row = rows[0]
|
1581
|
+
expect(row).to be_a Hash
|
1582
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1583
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1584
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1585
|
+
expect(row['Remark']).to be_nil
|
1586
|
+
expect(row['dummy']).to be_nil
|
1587
|
+
row = rows[13]
|
1588
|
+
expect(row).to be_a Hash
|
1589
|
+
expect(row['Date']).to eq data_row_13['Date']
|
1590
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
1591
|
+
expect(row['Code']).to eq data_row_13['Code']
|
1592
|
+
expect(row['Remark']).to be_nil
|
1593
|
+
expect(row['dummy']).to be_nil
|
1594
|
+
end
|
1595
|
+
|
1596
|
+
end
|
1597
|
+
|
1598
|
+
context 'missing optional headers' do
|
1599
|
+
|
1600
|
+
let(:required_headers) {%w'Date Amount Code Remark'}
|
1601
|
+
let(:optional_headers) {%w'dummy'}
|
1602
|
+
|
1603
|
+
it 'opens correctly' do
|
1604
|
+
expect {ss}.not_to raise_error
|
1605
|
+
end
|
1606
|
+
|
1607
|
+
it 'contains only required headers' do
|
1608
|
+
required_headers.each do |header|
|
1609
|
+
expect(ss.headers).to include header
|
1610
|
+
end
|
1611
|
+
optional_headers.each do |header|
|
1612
|
+
expect(ss.headers).not_to include header
|
1613
|
+
end
|
1614
|
+
expect(ss.headers).to eq required_headers
|
1615
|
+
end
|
1616
|
+
|
1617
|
+
it 'each returns header and data rows' do
|
1618
|
+
expect(ss.each.count).to eq size_with_headers
|
1619
|
+
expect(ss.each.first.keys).to eq required_headers
|
1620
|
+
end
|
1621
|
+
|
1622
|
+
it '#shift returns Hash object' do
|
1623
|
+
row = ss.shift
|
1624
|
+
expect(row).to be_a Hash
|
1625
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1626
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1627
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1628
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
1629
|
+
expect(row['dummy']).to be_nil
|
1630
|
+
end
|
1631
|
+
|
1632
|
+
it '#parse returns Array of Hash objects' do
|
1633
|
+
rows = ss.parse
|
1634
|
+
expect(rows).to be_a Array
|
1635
|
+
expect(rows.size).to eq size_without_headers
|
1636
|
+
row = rows[0]
|
1637
|
+
expect(row).to be_a Hash
|
1638
|
+
expect(row['Date']).to eq first_data_row['Date']
|
1639
|
+
expect(row['Amount']).to eq first_data_row['Amount']
|
1640
|
+
expect(row['Code']).to eq first_data_row['Code']
|
1641
|
+
expect(row['Remark']).to eq first_data_row['Remark']
|
1642
|
+
expect(row['dummy']).to be_nil
|
1643
|
+
row = rows[13]
|
1644
|
+
expect(row).to be_a Hash
|
1645
|
+
expect(row['Date']).to eq data_row_13['Date']
|
1646
|
+
expect(row['Amount']).to eq data_row_13['Amount']
|
1647
|
+
expect(row['Code']).to eq data_row_13['Code']
|
1648
|
+
expect(row['Remark']).to eq data_row_13['Remark']
|
1649
|
+
expect(row['dummy']).to be_nil
|
1650
|
+
end
|
1651
|
+
|
1652
|
+
end
|
1653
|
+
|
1654
|
+
context 'missing required header' do
|
1655
|
+
let(:required_headers) {%w'Date Amount Code Remark dummy'}
|
1656
|
+
|
1657
|
+
it 'throws error when opened' do
|
1658
|
+
expect {ss}.to raise_error(RuntimeError, 'Sheet does not contain enough columns.')
|
1659
|
+
end
|
1660
|
+
|
1661
|
+
end
|
1662
|
+
|
1663
|
+
end
|
1664
|
+
|
1665
|
+
context 'Only headers' do
|
1666
|
+
let(:file_name) {'test.xlsx|ExpensesOnlyHeaders'}
|
1667
|
+
|
1668
|
+
context 'well-formed' do
|
1669
|
+
|
1670
|
+
let(:required_headers) {%w'Date Amount'}
|
1671
|
+
|
1672
|
+
it 'opens correctly' do
|
1673
|
+
expect {ss}.not_to raise_error
|
1674
|
+
end
|
1675
|
+
|
1676
|
+
it 'contains expected headers' do
|
1677
|
+
required_headers.each do |header|
|
1678
|
+
expect(ss.headers).to include header
|
1679
|
+
end
|
1680
|
+
expect(ss.headers).to eq real_headers
|
1681
|
+
end
|
1682
|
+
|
1683
|
+
it 'each returns header and data rows' do
|
1684
|
+
expect(ss.each.count).to be 1
|
1685
|
+
expect(ss.each.first).to eq header_row
|
1686
|
+
end
|
1687
|
+
|
1688
|
+
it '#shift returns nil' do
|
1689
|
+
row = ss.shift
|
1690
|
+
expect(row).to be_nil
|
1691
|
+
end
|
1692
|
+
|
1693
|
+
it '#parse returns empty Array of Hash objects' do
|
1694
|
+
rows = ss.parse
|
1695
|
+
expect(rows).to be_a Array
|
1696
|
+
# noinspection RubyResolve
|
1697
|
+
expect(rows).to be_empty
|
1698
|
+
expect(rows.size).to eq 0
|
1699
|
+
end
|
1700
|
+
|
1701
|
+
end
|
1702
|
+
|
1703
|
+
context 'not specified' do
|
1704
|
+
|
1705
|
+
let(:required_headers) {[]}
|
1706
|
+
|
1707
|
+
it 'opens correctly' do
|
1708
|
+
expect {ss}.not_to raise_error
|
1709
|
+
end
|
1710
|
+
|
1711
|
+
it 'contains expected headers' do
|
1712
|
+
required_headers.each do |header|
|
1713
|
+
expect(ss.headers).to include header
|
1714
|
+
end
|
1715
|
+
expect(ss.headers).to eq %w'Date Amount Code Remark'
|
1716
|
+
end
|
1717
|
+
|
1718
|
+
it '#shift returns nil' do
|
1719
|
+
row = ss.shift
|
1720
|
+
expect(row).to be_nil
|
1721
|
+
end
|
1722
|
+
|
1723
|
+
it '#parse returns empty Array of Hash objects' do
|
1724
|
+
rows = ss.parse
|
1725
|
+
expect(rows).to be_a Array
|
1726
|
+
# noinspection RubyResolve
|
1727
|
+
expect(rows).to be_empty
|
1728
|
+
expect(rows.size).to eq 0
|
1729
|
+
end
|
1730
|
+
|
1731
|
+
end
|
1732
|
+
|
1733
|
+
context 'not well-formed' do
|
1734
|
+
|
1735
|
+
let(:required_headers) {%w'Date dummy1 Amount dummy2'}
|
1736
|
+
|
1737
|
+
it 'throws error when opened' do
|
1738
|
+
expect {ss}.to raise_error(RuntimeError, 'Headers not found: ["dummy1", "dummy2"].')
|
1739
|
+
end
|
1740
|
+
end
|
1741
|
+
|
1742
|
+
end
|
1743
|
+
|
1744
|
+
context 'Only headers with blank rows and columns' do
|
1745
|
+
let(:file_name) {'test.xlsx|ExpensesOnlyHeadersBlankRowsAndColumns'}
|
1746
|
+
|
1747
|
+
context 'well-formed' do
|
1748
|
+
|
1749
|
+
let(:required_headers) {%w'Date Amount'}
|
1750
|
+
|
1751
|
+
it 'opens correctly' do
|
1752
|
+
expect {ss}.not_to raise_error
|
1753
|
+
end
|
1754
|
+
|
1755
|
+
it 'contains expected headers' do
|
1756
|
+
required_headers.each do |header|
|
1757
|
+
expect(ss.headers).to include header
|
1758
|
+
end
|
1759
|
+
expect(ss.headers).to eq %w'Date Amount Code Remark'
|
1760
|
+
end
|
1761
|
+
|
1762
|
+
it '#shift returns nil' do
|
1763
|
+
row = ss.shift
|
1764
|
+
expect(row).to be_nil
|
1765
|
+
end
|
1766
|
+
|
1767
|
+
it '#parse returns empty Array of Hash objects' do
|
1768
|
+
rows = ss.parse
|
1769
|
+
expect(rows).to be_a Array
|
1770
|
+
# noinspection RubyResolve
|
1771
|
+
expect(rows).to be_empty
|
1772
|
+
expect(rows.size).to eq 0
|
1773
|
+
end
|
1774
|
+
|
1775
|
+
end
|
1776
|
+
|
1777
|
+
context 'not specified' do
|
1778
|
+
|
1779
|
+
let(:required_headers) {[]}
|
1780
|
+
|
1781
|
+
it 'opens correctly' do
|
1782
|
+
expect {ss}.not_to raise_error
|
1783
|
+
end
|
1784
|
+
|
1785
|
+
it 'contains expected headers' do
|
1786
|
+
required_headers.each do |header|
|
1787
|
+
expect(ss.headers).to include header
|
1788
|
+
end
|
1789
|
+
expect(ss.headers).to eq %w'Date Amount Code Remark'
|
1790
|
+
end
|
1791
|
+
|
1792
|
+
it '#shift returns nil' do
|
1793
|
+
row = ss.shift
|
1794
|
+
expect(row).to be_nil
|
1795
|
+
end
|
1796
|
+
|
1797
|
+
it '#parse returns empty Array of Hash objects' do
|
1798
|
+
rows = ss.parse
|
1799
|
+
expect(rows).to be_a Array
|
1800
|
+
# noinspection RubyResolve
|
1801
|
+
expect(rows).to be_empty
|
1802
|
+
expect(rows.size).to eq 0
|
1803
|
+
end
|
1804
|
+
|
1805
|
+
end
|
1806
|
+
|
1807
|
+
context 'not well-formed' do
|
1808
|
+
|
1809
|
+
let(:required_headers) {%w'Date dummy1 Amount dummy2'}
|
1810
|
+
|
1811
|
+
it 'throws error when opened' do
|
1812
|
+
expect {ss}.to raise_error(RuntimeError, 'Headers not found: ["dummy1", "dummy2"].')
|
1813
|
+
end
|
1814
|
+
end
|
1815
|
+
|
1816
|
+
end
|
1817
|
+
|
1818
|
+
end
|
1819
|
+
|
1820
|
+
end
|