iostreams 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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
|