iostreams 0.14.0 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +202 -0
- data/README.md +155 -47
- data/lib/io_streams/file/reader.rb +7 -8
- data/lib/io_streams/file/writer.rb +7 -8
- data/lib/io_streams/io_streams.rb +313 -129
- data/lib/io_streams/{delimited → line}/reader.rb +20 -30
- data/lib/io_streams/line/writer.rb +81 -0
- data/lib/io_streams/pgp.rb +4 -14
- data/lib/io_streams/record/reader.rb +55 -0
- data/lib/io_streams/record/writer.rb +63 -0
- data/lib/io_streams/row/reader.rb +60 -0
- data/lib/io_streams/row/writer.rb +62 -0
- data/lib/io_streams/s3.rb +25 -0
- data/lib/io_streams/s3/reader.rb +64 -0
- data/lib/io_streams/s3/writer.rb +13 -0
- data/lib/io_streams/streams.rb +1 -1
- data/lib/io_streams/tabular.rb +163 -0
- data/lib/io_streams/tabular/errors.rb +14 -0
- data/lib/io_streams/tabular/header.rb +146 -0
- data/lib/io_streams/tabular/parser/array.rb +26 -0
- data/lib/io_streams/tabular/parser/base.rb +12 -0
- data/lib/io_streams/tabular/parser/csv.rb +35 -0
- data/lib/io_streams/tabular/parser/fixed.rb +88 -0
- data/lib/io_streams/tabular/parser/hash.rb +21 -0
- data/lib/io_streams/tabular/parser/json.rb +25 -0
- data/lib/io_streams/tabular/parser/psv.rb +34 -0
- data/lib/io_streams/tabular/utility/csv_row.rb +115 -0
- data/lib/io_streams/version.rb +2 -2
- data/lib/io_streams/xlsx/reader.rb +1 -1
- data/lib/io_streams/zip/reader.rb +1 -1
- data/lib/io_streams/zip/writer.rb +1 -1
- data/lib/iostreams.rb +21 -10
- data/test/bzip2_reader_test.rb +21 -22
- data/test/bzip2_writer_test.rb +38 -32
- data/test/file_reader_test.rb +19 -18
- data/test/file_writer_test.rb +23 -22
- data/test/files/test.json +3 -0
- data/test/gzip_reader_test.rb +21 -22
- data/test/gzip_writer_test.rb +35 -29
- data/test/io_streams_test.rb +137 -61
- data/test/line_reader_test.rb +105 -0
- data/test/line_writer_test.rb +50 -0
- data/test/pgp_reader_test.rb +29 -29
- data/test/pgp_test.rb +149 -195
- data/test/pgp_writer_test.rb +63 -62
- data/test/record_reader_test.rb +61 -0
- data/test/record_writer_test.rb +73 -0
- data/test/row_reader_test.rb +34 -0
- data/test/row_writer_test.rb +51 -0
- data/test/tabular_test.rb +184 -0
- data/test/xlsx_reader_test.rb +13 -17
- data/test/zip_reader_test.rb +21 -22
- data/test/zip_writer_test.rb +40 -36
- metadata +41 -17
- data/lib/io_streams/csv/reader.rb +0 -21
- data/lib/io_streams/csv/writer.rb +0 -20
- data/lib/io_streams/delimited/writer.rb +0 -67
- data/test/csv_reader_test.rb +0 -34
- data/test/csv_writer_test.rb +0 -35
- data/test/delimited_reader_test.rb +0 -115
- data/test/delimited_writer_test.rb +0 -44
data/test/pgp_writer_test.rb
CHANGED
@@ -1,92 +1,93 @@
|
|
1
1
|
require_relative 'test_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@data = File.read(file_name)
|
3
|
+
class PgpWriterTest < Minitest::Test
|
4
|
+
describe IOStreams::Pgp::Writer do
|
5
|
+
let :temp_file do
|
6
|
+
Tempfile.new('iostreams')
|
7
|
+
end
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
let :file_name do
|
10
|
+
temp_file.path
|
11
|
+
end
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
let :decrypted do
|
14
|
+
file_name = File.join(File.dirname(__FILE__), 'files', 'text.txt')
|
15
|
+
File.read(file_name)
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
io.write(@data)
|
22
|
-
end
|
18
|
+
after do
|
19
|
+
temp_file.delete
|
20
|
+
end
|
23
21
|
|
24
|
-
|
25
|
-
|
22
|
+
describe '.open' do
|
23
|
+
it 'writes encrypted text file' do
|
24
|
+
IOStreams::Pgp::Writer.open(file_name, recipient: 'receiver@example.org', binary: false) do |io|
|
25
|
+
io.write(decrypted)
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
result = IOStreams::Pgp::Reader.open(file_name, passphrase: 'receiver_passphrase', binary: false) { |file| file.read }
|
29
|
+
assert_equal decrypted, result
|
30
|
+
end
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
32
|
+
it 'writes encrypted binary file' do
|
33
|
+
binary_file_name = File.join(File.dirname(__FILE__), 'files', 'spreadsheet.xlsx')
|
34
|
+
binary_data = File.open(binary_file_name, 'rb') { |file| file.read }
|
37
35
|
|
38
|
-
|
39
|
-
|
36
|
+
File.open(binary_file_name, 'rb') do |input|
|
37
|
+
IOStreams::Pgp::Writer.open(file_name, recipient: 'receiver@example.org') do |output|
|
38
|
+
IOStreams.copy(input, output)
|
39
|
+
end
|
40
40
|
end
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
42
|
+
result = IOStreams::Pgp::Reader.open(file_name, passphrase: 'receiver_passphrase') { |file| file.read }
|
43
|
+
assert_equal binary_data, result
|
44
|
+
end
|
46
45
|
|
47
|
-
|
48
|
-
|
46
|
+
it 'writes and signs encrypted file' do
|
47
|
+
IOStreams::Pgp::Writer.open(file_name, recipient: 'receiver@example.org', signer: 'sender@example.org', signer_passphrase: 'sender_passphrase') do |io|
|
48
|
+
io.write(decrypted)
|
49
49
|
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
result = IOStreams::Pgp::Reader.open(file_name, passphrase: 'receiver_passphrase') { |file| file.read }
|
52
|
+
assert_equal decrypted, result
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'fails with bad signer passphrase' do
|
56
|
+
skip 'GnuPG v2.1 and above passes when it should not' if IOStreams::Pgp.pgp_version.to_f >= 2.1
|
57
|
+
assert_raises IOStreams::Pgp::Failure do
|
58
|
+
IOStreams::Pgp::Writer.open(file_name, recipient: 'receiver@example.org', signer: 'sender@example.org', signer_passphrase: 'BAD') do |io|
|
59
|
+
io.write(decrypted)
|
57
60
|
end
|
58
61
|
end
|
62
|
+
end
|
59
63
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
64
|
+
it 'fails with bad recipient' do
|
65
|
+
assert_raises IOStreams::Pgp::Failure do
|
66
|
+
IOStreams::Pgp::Writer.open(file_name, recipient: 'BAD@example.org', signer: 'sender@example.org', signer_passphrase: 'sender_passphrase') do |io|
|
67
|
+
io.write(decrypted)
|
68
|
+
# Allow process to terminate
|
69
|
+
sleep 1
|
70
|
+
io.write(decrypted)
|
68
71
|
end
|
69
72
|
end
|
73
|
+
end
|
70
74
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
75
|
+
it 'fails with bad signer' do
|
76
|
+
assert_raises IOStreams::Pgp::Failure do
|
77
|
+
IOStreams::Pgp::Writer.open(file_name, recipient: 'receiver@example.org', signer: 'BAD@example.org', signer_passphrase: 'sender_passphrase') do |io|
|
78
|
+
io.write(decrypted)
|
76
79
|
end
|
77
80
|
end
|
81
|
+
end
|
78
82
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
end
|
83
|
+
it 'fails with stream output' do
|
84
|
+
string_io = StringIO.new
|
85
|
+
assert_raises NotImplementedError do
|
86
|
+
IOStreams::Pgp::Writer.open(string_io, recipient: 'receiver@example.org') do |io|
|
87
|
+
io.write(decrypted)
|
85
88
|
end
|
86
89
|
end
|
87
|
-
|
88
90
|
end
|
89
|
-
|
90
91
|
end
|
91
92
|
end
|
92
93
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class RecordReaderTest < Minitest::Test
|
4
|
+
describe IOStreams::Record::Reader do
|
5
|
+
let :file_name do
|
6
|
+
File.join(File.dirname(__FILE__), 'files', 'test.csv')
|
7
|
+
end
|
8
|
+
|
9
|
+
let :json_file_name do
|
10
|
+
File.join(File.dirname(__FILE__), 'files', 'test.json')
|
11
|
+
end
|
12
|
+
|
13
|
+
let :csv_rows do
|
14
|
+
CSV.read(file_name)
|
15
|
+
end
|
16
|
+
|
17
|
+
let :expected do
|
18
|
+
rows = csv_rows.dup
|
19
|
+
header = rows.shift
|
20
|
+
rows.collect { |row| header.zip(row).to_h }
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#each' do
|
24
|
+
it 'csv file' do
|
25
|
+
records = []
|
26
|
+
IOStreams::Record::Reader.open(file_name, cleanse_header: false) do |io|
|
27
|
+
io.each { |row| records << row }
|
28
|
+
end
|
29
|
+
assert_equal expected, records
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'json file' do
|
33
|
+
records = []
|
34
|
+
IOStreams::Record::Reader.open(json_file_name, cleanse_header: false) do |input|
|
35
|
+
input.each { |row| records << row }
|
36
|
+
end
|
37
|
+
assert_equal expected, records
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'stream' do
|
41
|
+
rows = []
|
42
|
+
IOStreams.line_reader(file_name) do |file|
|
43
|
+
IOStreams::Record::Reader.open(file, cleanse_header: false) do |io|
|
44
|
+
io.each { |row| rows << row }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
assert_equal expected, rows
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#collect' do
|
52
|
+
it 'json file' do
|
53
|
+
records = IOStreams::Record::Reader.open(json_file_name) do |input|
|
54
|
+
input.collect { |record| record["state"] }
|
55
|
+
end
|
56
|
+
assert_equal expected.collect { |record| record["state"] }, records
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
require 'csv'
|
3
|
+
|
4
|
+
class RecordWriterTest < Minitest::Test
|
5
|
+
describe IOStreams::Record::Writer do
|
6
|
+
let :csv_file_name do
|
7
|
+
File.join(File.dirname(__FILE__), 'files', 'test.csv')
|
8
|
+
end
|
9
|
+
|
10
|
+
let :json_file_name do
|
11
|
+
File.join(File.dirname(__FILE__), 'files', 'test.json')
|
12
|
+
end
|
13
|
+
|
14
|
+
let :raw_csv_data do
|
15
|
+
File.read(csv_file_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
let :raw_json_data do
|
19
|
+
File.read(json_file_name)
|
20
|
+
end
|
21
|
+
|
22
|
+
let :csv_rows do
|
23
|
+
CSV.read(csv_file_name)
|
24
|
+
end
|
25
|
+
|
26
|
+
let :inputs do
|
27
|
+
rows = csv_rows.dup
|
28
|
+
header = rows.shift
|
29
|
+
rows.collect { |row| header.zip(row).to_h }
|
30
|
+
end
|
31
|
+
|
32
|
+
let :temp_file do
|
33
|
+
Tempfile.new('iostreams')
|
34
|
+
end
|
35
|
+
|
36
|
+
let :file_name do
|
37
|
+
temp_file.path
|
38
|
+
end
|
39
|
+
|
40
|
+
after do
|
41
|
+
temp_file.delete
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#<<' do
|
45
|
+
it 'file' do
|
46
|
+
IOStreams::Record::Writer.open(file_name) do |io|
|
47
|
+
inputs.each { |hash| io << hash }
|
48
|
+
end
|
49
|
+
result = File.read(file_name)
|
50
|
+
assert_equal raw_csv_data, result
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'json file' do
|
54
|
+
IOStreams::Record::Writer.open(file_name, file_name: 'abc.json') do |io|
|
55
|
+
inputs.each { |hash| io << hash }
|
56
|
+
end
|
57
|
+
result = File.read(file_name)
|
58
|
+
assert_equal raw_json_data, result
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'stream' do
|
62
|
+
io_string = StringIO.new
|
63
|
+
IOStreams::Line::Writer.open(io_string) do |io|
|
64
|
+
IOStreams::Record::Writer.open(io) do |stream|
|
65
|
+
inputs.each { |row| stream << row }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
assert_equal raw_csv_data, io_string.string
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class RowReaderTest < Minitest::Test
|
4
|
+
describe IOStreams::Row::Reader do
|
5
|
+
let :file_name do
|
6
|
+
File.join(File.dirname(__FILE__), 'files', 'test.csv')
|
7
|
+
end
|
8
|
+
|
9
|
+
let :expected do
|
10
|
+
CSV.read(file_name)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '.open' do
|
14
|
+
it 'file' do
|
15
|
+
rows = []
|
16
|
+
IOStreams::Row::Reader.open(file_name) do |io|
|
17
|
+
io.each { |row| rows << row }
|
18
|
+
end
|
19
|
+
assert_equal expected, rows
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'stream' do
|
23
|
+
rows = []
|
24
|
+
IOStreams.line_reader(file_name) do |file|
|
25
|
+
IOStreams::Row::Reader.open(file) do |io|
|
26
|
+
io.each { |row| rows << row }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
assert_equal expected, rows
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
require 'csv'
|
3
|
+
|
4
|
+
class RowWriterTest < Minitest::Test
|
5
|
+
describe IOStreams::Row::Writer do
|
6
|
+
let :csv_file_name do
|
7
|
+
File.join(File.dirname(__FILE__), 'files', 'test.csv')
|
8
|
+
end
|
9
|
+
|
10
|
+
let :raw_csv_data do
|
11
|
+
File.read(csv_file_name)
|
12
|
+
end
|
13
|
+
|
14
|
+
let :csv_rows do
|
15
|
+
CSV.read(csv_file_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
let :temp_file do
|
19
|
+
Tempfile.new('iostreams')
|
20
|
+
end
|
21
|
+
|
22
|
+
let :file_name do
|
23
|
+
temp_file.path
|
24
|
+
end
|
25
|
+
|
26
|
+
after do
|
27
|
+
temp_file.delete
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '.open' do
|
31
|
+
it 'file' do
|
32
|
+
IOStreams::Row::Writer.open(file_name) do |io|
|
33
|
+
csv_rows.each { |array| io << array }
|
34
|
+
end
|
35
|
+
result = File.read(file_name)
|
36
|
+
assert_equal raw_csv_data, result
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'stream' do
|
40
|
+
io_string = StringIO.new
|
41
|
+
IOStreams::Line::Writer.open(io_string) do |io|
|
42
|
+
IOStreams::Row::Writer.open(io) do |stream|
|
43
|
+
csv_rows.each { |array| stream << array }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
assert_equal raw_csv_data, io_string.string
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class TabularTest < Minitest::Test
|
4
|
+
describe IOStreams::Tabular do
|
5
|
+
let :format do
|
6
|
+
:csv
|
7
|
+
end
|
8
|
+
|
9
|
+
let :tabular do
|
10
|
+
IOStreams::Tabular.new(columns: ['first_field', 'second', 'third'], format: format)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#parse_header' do
|
14
|
+
it 'parses and sets the csv header' do
|
15
|
+
tabular = IOStreams::Tabular.new(format: :csv)
|
16
|
+
header = tabular.parse_header('first field,Second,thirD')
|
17
|
+
assert_equal ['first field', 'Second', 'thirD'], header
|
18
|
+
assert_equal header, tabular.header.columns
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#cleanse_header!' do
|
23
|
+
describe 'cleanses' do
|
24
|
+
it 'a csv header' do
|
25
|
+
tabular = IOStreams::Tabular.new(columns: ['first field', 'Second', 'thirD'])
|
26
|
+
header = tabular.cleanse_header!
|
27
|
+
assert_equal ['first_field', "second", "third"], header
|
28
|
+
assert_equal header, tabular.header.columns
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'white listed snake cased alphanumeric columns' do
|
32
|
+
tabular = IOStreams::Tabular.new(
|
33
|
+
columns: ['Ard Vark', 'password', 'robot version', '$$$'],
|
34
|
+
allowed_columns: %w( ard_vark robot_version )
|
35
|
+
)
|
36
|
+
expected_header = ['ard_vark', nil, 'robot_version', nil]
|
37
|
+
cleansed_header = tabular.cleanse_header!
|
38
|
+
assert_equal(expected_header, cleansed_header)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'allowed_columns' do
|
43
|
+
before do
|
44
|
+
@allowed_columns = ['first', 'second', 'third', 'fourth', 'fifth']
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'passes' do
|
48
|
+
tabular = IOStreams::Tabular.new(columns: [' first ', 'Second', 'thirD '], allowed_columns: @allowed_columns)
|
49
|
+
header = tabular.cleanse_header!
|
50
|
+
assert_equal ['first', 'second', 'third'], header
|
51
|
+
assert_equal header, tabular.header.columns
|
52
|
+
assert_equal @allowed_columns, tabular.header.allowed_columns
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'nils columns not in the whitelist' do
|
56
|
+
tabular = IOStreams::Tabular.new(columns: [' first ', 'Unknown Column', 'thirD '], allowed_columns: @allowed_columns)
|
57
|
+
header = tabular.cleanse_header!
|
58
|
+
assert_equal ['first', nil, 'third'], header
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'raises exception for columns not in the whitelist' do
|
62
|
+
tabular = IOStreams::Tabular.new(columns: [' first ', 'Unknown Column', 'thirD '], allowed_columns: @allowed_columns, skip_unknown: false)
|
63
|
+
exc = assert_raises IOStreams::Tabular::Errors::InvalidHeader do
|
64
|
+
tabular.cleanse_header!
|
65
|
+
end
|
66
|
+
assert_equal 'Unknown columns after cleansing: Unknown Column', exc.message
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'raises exception missing required columns' do
|
70
|
+
required = ['first', 'second', 'fifth']
|
71
|
+
tabular = IOStreams::Tabular.new(columns: [' first ', 'Second', 'thirD '], allowed_columns: @allowed_columns, required_columns: required)
|
72
|
+
exc = assert_raises IOStreams::Tabular::Errors::InvalidHeader do
|
73
|
+
tabular.cleanse_header!
|
74
|
+
end
|
75
|
+
assert_equal 'Missing columns after cleansing: fifth', exc.message
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'raises exception when no columns left' do
|
79
|
+
tabular = IOStreams::Tabular.new(columns: ['one', 'two', 'three'], allowed_columns: @allowed_columns)
|
80
|
+
exc = assert_raises IOStreams::Tabular::Errors::InvalidHeader do
|
81
|
+
tabular.cleanse_header!
|
82
|
+
end
|
83
|
+
assert_equal 'All columns are unknown after cleansing: one,two,three', exc.message
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe '#record_parse' do
|
89
|
+
describe ':array format' do
|
90
|
+
let :format do
|
91
|
+
:array
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'renders' do
|
95
|
+
assert hash = tabular.record_parse([1, 2, 3])
|
96
|
+
assert_equal({'first_field' => 1, 'second' => 2, 'third' => 3}, hash)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'format :csv' do
|
101
|
+
assert hash = tabular.record_parse('1,2,3')
|
102
|
+
assert_equal({'first_field' => '1', 'second' => '2', 'third' => '3'}, hash)
|
103
|
+
end
|
104
|
+
|
105
|
+
describe ':hash format' do
|
106
|
+
let :format do
|
107
|
+
:hash
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'renders' do
|
111
|
+
assert hash = tabular.record_parse('first_field' => 1, 'second' => 2, 'third' => 3)
|
112
|
+
assert_equal({'first_field' => 1, 'second' => 2, 'third' => 3}, hash)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe ':json format' do
|
117
|
+
let :format do
|
118
|
+
:json
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'renders' do
|
122
|
+
assert hash = tabular.record_parse('{"first_field":1,"second":2,"third":3}')
|
123
|
+
assert_equal({'first_field' => 1, 'second' => 2, 'third' => 3}, hash)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe ':psv format' do
|
128
|
+
let :format do
|
129
|
+
:psv
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'renders' do
|
133
|
+
assert hash = tabular.record_parse('1|2|3')
|
134
|
+
assert_equal({'first_field' => '1', 'second' => '2', 'third' => '3'}, hash)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'skips columns not in the whitelist' do
|
139
|
+
tabular.header.allowed_columns = ['first', 'second', 'third', 'fourth', 'fifth']
|
140
|
+
tabular.cleanse_header!
|
141
|
+
assert hash = tabular.record_parse('1,2,3')
|
142
|
+
assert_equal({'second' => '2', 'third' => '3'}, hash)
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'handles missing values' do
|
146
|
+
assert hash = tabular.record_parse('1,2')
|
147
|
+
assert_equal({'first_field' => '1', 'second' => '2', 'third' => nil}, hash)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#render' do
|
152
|
+
it 'renders an array of values' do
|
153
|
+
assert csv_string = tabular.render([5, 6, 9])
|
154
|
+
assert_equal '5,6,9', csv_string
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'renders a hash' do
|
158
|
+
assert csv_string = tabular.render({'third' => '3', 'first_field' => '1'})
|
159
|
+
assert_equal '1,,3', csv_string
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'renders a hash including nil and boolean' do
|
163
|
+
assert csv_string = tabular.render({'third' => true, 'first_field' => false, 'second' => nil})
|
164
|
+
assert_equal 'false,,true', csv_string
|
165
|
+
end
|
166
|
+
|
167
|
+
describe ':psv format' do
|
168
|
+
let :format do
|
169
|
+
:psv
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'renders psv nil and boolean' do
|
173
|
+
assert psv_string = tabular.render({'third' => true, 'first_field' => false, 'second' => nil})
|
174
|
+
assert_equal 'false||true', psv_string
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'renders psv numeric and pipe data' do
|
178
|
+
assert psv_string = tabular.render({'third' => 23, 'first_field' => 'a|b|c', 'second' => '|'})
|
179
|
+
assert_equal 'a:b:c|:|23', psv_string
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|