summaryrefslogtreecommitdiffstats
path: root/t/02-csv.t
blob: 8850620e54e26776ab83f738f4483b47d2721ca3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use strict;
use warnings;
use utf8;

use Test::More;

use Cepis::CSV;

binmode Test::More->builder->output,         ':encoding(UTF-8)';
binmode Test::More->builder->failure_output, ':encoding(UTF-8)';

is_deeply( Cepis::CSV::parse_rows(''), [], 'empty input yields no rows' );

is_deeply(
    Cepis::CSV::parse_rows("a,b,c\n1,2,3\n"),
    [ [qw(a b c)], [qw(1 2 3)] ],
    'plain rows'
);

is_deeply(
    Cepis::CSV::parse_rows("a,b\r\n1,2\r\n"),
    [ [qw(a b)], [qw(1 2)] ],
    'CRLF line endings'
);

is_deeply(
    Cepis::CSV::parse_rows("a,b\n1,2"),
    [ [qw(a b)], [qw(1 2)] ],
    'a missing final newline still closes the row'
);

is_deeply(
    Cepis::CSV::parse_rows(qq{a,b\n"um, dois",3\n}),
    [ [qw(a b)], [ 'um, dois', '3' ] ],
    'a quoted field may hold a comma'
);

is_deeply(
    Cepis::CSV::parse_rows(qq{a\n"he said ""hi"""\n}),
    [ ['a'], ['he said "hi"'] ],
    'a doubled quote is an escaped quote'
);

is_deeply(
    Cepis::CSV::parse_rows(qq{a,b\n"line\none",2\n}),
    [ [qw(a b)], [ "line\none", '2' ] ],
    'a quoted field may hold a newline'
);

is_deeply(
    Cepis::CSV::parse_rows(qq{a,b,c\n,,\n}),
    [ [qw(a b c)], [ '', '', '' ] ],
    'empty fields survive'
);

is_deeply(
    Cepis::CSV::parse_rows(qq{a,b\n"",""\n}),
    [ [qw(a b)], [ '', '' ] ],
    'explicitly quoted empty fields survive'
);

is_deeply(
    Cepis::CSV::parse_rows("\x{FEFF}a,b\n1,2\n"),
    [ [qw(a b)], [qw(1 2)] ],
    'a byte order mark is stripped'
);

is_deeply(
    Cepis::CSV::parse_rows("a,b\n1,2\n\n\n"),
    [ [qw(a b)], [qw(1 2)] ],
    'blank lines are skipped'
);

is_deeply(
    Cepis::CSV::parse_rows("cep,localidade\n01001000,São Paulo\n"),
    [ [qw(cep localidade)], [ '01001000', 'São Paulo' ] ],
    'non-ASCII characters survive'
);

my ( $header, $records )
    = Cepis::CSV::parse_hashes("cep,localidade,uf\n01001000,São Paulo,SP\n99999999,,\n");

is_deeply( $header, [qw(cep localidade uf)], 'the header row comes back' );
is_deeply(
    $records,
    [   { cep => '01001000', localidade => 'São Paulo', uf => 'SP' },
        { cep => '99999999', localidade => '',          uf => '' },
    ],
    'records are keyed by column name'
);

( $header, $records ) = Cepis::CSV::parse_hashes("a,b,c\n1\n");
is_deeply(
    $records,
    [ { a => '1', b => '', c => '' } ],
    'a short row is filled with empty strings'
);

( $header, $records ) = Cepis::CSV::parse_hashes("a\n1,2,3\n");
is_deeply( $records, [ { a => '1' } ], 'fields beyond the header are dropped' );

( $header, $records ) = Cepis::CSV::parse_hashes('');
is_deeply( [ $header, $records ], [ [], [] ], 'empty input yields nothing' );

done_testing();