Completed
Pull Request — master (#31)
by Chad
01:44
created

ReaderTest::current()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 11
nc 1
nop 0
1
<?php
2
namespace SubjectivePHPTest\Csv;
3
4
use SubjectivePHP\Csv\CsvOptions;
5
use SubjectivePHP\Csv\DeriveHeaderStrategy;
6
use SubjectivePHP\Csv\MappedHeaderStrategy;
7
use SubjectivePHP\Csv\NoHeaderStrategy;
8
use SubjectivePHP\Csv\ProvidedHeaderStrategy;
9
use SubjectivePHP\Csv\Reader;
10
use PHPUnit\Framework\TestCase;
11
12
/**
13
 * Unit tests for the SubjectivePHP\Csv\Reader class
14
 *
15
 * @coversDefaultClass \SubjectivePHP\Csv\Reader
16
 * @covers ::__construct
17
 * @covers ::__destruct
18
 * @covers ::<private>
19
 */
20
final class ReaderTest extends TestCase
21
{
22
    /**
23
     * Verify basic usage of Reader.
24
     *
25
     * @test
26
     * @covers ::getIterator
27
     * @dataProvider getReaders()
28
     *
29
     * @param Reader $reader The Reader instance to use in the test.
30
     *
31
     * @return void
32
     */
33
    public function basicUsage(Reader $reader)
34
    {
35
        $expected = [
36
            [
37
                'id' => 'bk101',
38
                'author' => 'Gambardella, Matthew',
39
                'title' => 'XML Developer\'s Guide',
40
                'genre' => 'Computer',
41
                'price' => '44.95',
42
                'publish_date' => '2000-10-01',
43
                'description' => 'An in-depth look at creating applications with XML.',
44
            ],
45
            [
46
                'id' => 'bk102',
47
                'author' => 'Ralls, Kim',
48
                'title' => 'Midnight Rain',
49
                'genre' => 'Fantasy',
50
                'price' => '5.95',
51
                'publish_date' => '2000-12-16',
52
                'description' => 'A former architect battles corporate zombies and an evil sorceress.',
53
            ],
54
            [
55
                'id' => 'bk103',
56
                'author' => 'Corets, Eva',
57
                'title' => 'Maeve Ascendant',
58
                'genre' => 'Fantasy',
59
                'price' => '5.95',
60
                'publish_date' => '2000-11-17',
61
                'description' => 'Young survivors lay the foundation for a new society in England.',
62
            ],
63
        ];
64
65
        $this->assertSame($expected, array_values(iterator_to_array($reader)));
66
    }
67
68
    /**
69
     * @test
70
     * @covers ::getIterator
71
     */
72
    public function readWithCustomHeaders()
73
    {
74
        $expected = [
75
            [
76
                'Book ID' => 'bk101',
77
                'Author' => 'Gambardella, Matthew',
78
                'Title' => 'XML Developer\'s Guide',
79
                'Genre' => 'Computer',
80
                'Price' => '44.95',
81
                'Publish Date' => '2000-10-01',
82
                'Description' => 'An in-depth look at creating applications with XML.',
83
            ],
84
            [
85
                'Book ID' => 'bk102',
86
                'Author' => 'Ralls, Kim',
87
                'Title' => 'Midnight Rain',
88
                'Genre' => 'Fantasy',
89
                'Price' => '5.95',
90
                'Publish Date' => '2000-12-16',
91
                'Description' => 'A former architect battles corporate zombies and an evil sorceress.',
92
            ],
93
            [
94
                'Book ID' => 'bk103',
95
                'Author' => 'Corets, Eva',
96
                'Title' => 'Maeve Ascendant',
97
                'Genre' => 'Fantasy',
98
                'Price' => '5.95',
99
                'Publish Date' => '2000-11-17',
100
                'Description' => 'Young survivors lay the foundation for a new society in England.',
101
            ],
102
        ];
103
104
        $strategy = new MappedHeaderStrategy(
105
            [
106
                'id' => 'Book ID',
107
                'author' => 'Author',
108
                'title' => 'Title',
109
                'genre' => 'Genre',
110
                'price' => 'Price',
111
                'publish_date' => 'Publish Date',
112
                'description' => 'Description',
113
            ]
114
        );
115
116
        $reader = new Reader(__DIR__ . '/_files/basic.csv', $strategy);
117
        $this->assertSame($expected, array_values(iterator_to_array($reader)));
118
    }
119
120
    /**
121
     * @test
122
     * @covers ::getIterator
123
     */
124
    public function readNoHeaders()
125
    {
126
        $expected = [
127
            [
128
                'bk101',
129
                'Gambardella, Matthew',
130
                'XML Developer\'s Guide',
131
                'Computer',
132
                '44.95',
133
                '2000-10-01',
134
                'An in-depth look at creating applications with XML.',
135
            ],
136
            [
137
                'bk102',
138
                'Ralls, Kim',
139
                'Midnight Rain',
140
                'Fantasy',
141
                '5.95',
142
                '2000-12-16',
143
                'A former architect battles corporate zombies and an evil sorceress.',
144
            ],
145
            [
146
                'bk103',
147
                'Corets, Eva',
148
                'Maeve Ascendant',
149
                'Fantasy',
150
                '5.95',
151
                '2000-11-17',
152
                'Young survivors lay the foundation for a new society in England.',
153
            ],
154
        ];
155
156
        $reader = new Reader(__DIR__ . '/_files/no_headers.csv', new NoHeaderStrategy());
157
        $this->assertSame($expected, array_values(iterator_to_array($reader)));
158
    }
159
160
    /**
161
     * Data provider for basic usage test
162
     *
163
     * @return array
164
     */
165
    public function getReaders()
166
    {
167
        $headers = ['id', 'author', 'title', 'genre', 'price', 'publish_date', 'description'];
168
        return [
169
            [new Reader(__DIR__ . '/_files/basic.csv')],
170
            [new Reader(__DIR__ . '/_files/basic.csv', new ProvidedHeaderStrategy($headers))],
171
            [new Reader(__DIR__ . '/_files/no_headers.csv', new ProvidedHeaderStrategy($headers))],
172
            [
173
                new Reader(
174
                    __DIR__ . '/_files/pipe_delimited.txt',
175
                    new ProvidedHeaderStrategy($headers),
176
                    new CsvOptions('|')
177
                )
178
            ],
179
            [
180
                new Reader(
181
                    __DIR__ . '/_files/tab_delimited.txt',
182
                    new ProvidedHeaderStrategy($headers),
183
                    new CsvOptions("\t")
184
                )
185
            ],
186
        ];
187
    }
188
189
    /**
190
     * Verify parameter checks for $file in __construct().
191
     *
192
     * @test
193
     * @covers ::__construct
194
     * @expectedException \InvalidArgumentException
195
     * @expectedExceptionMessage $file must be a string containing a full path to a readable delimited file
196
     *
197
     * @return void
198
     */
199
    public function constructWithFileThatDoesNotExist()
200
    {
201
        new Reader(__DIR__ . '/_files/not_found.csv');
202
    }
203
204
    /**
205
     * @test
206
     * @covers ::__construct
207
     */
208
    public function constructWithUnreadableFile()
209
    {
210
        try {
211
            $unreadableFilePath = tempnam(sys_get_temp_dir(), 'csv');
212
            touch($unreadableFilePath);
213
            chmod($unreadableFilePath, 0220);
214
            new Reader($unreadableFilePath);
215
        } catch (\InvalidArgumentException $e) {
216
            $this->assertSame(
217
                '$file must be a string containing a full path to a readable delimited file',
218
                $e->getMessage()
219
            );
220
        } finally {
221
            unlink($unreadableFilePath);
222
        }
223
    }
224
225
    /**
226
     * Verify behavior of Reader with an empty file
227
     *
228
     * @test
229
     * @covers ::getIterator
230
     * @dataProvider getEmptyFiles
231
     *
232
     * @param Reader $reader The reader instance to use in the tests.
233
     *
234
     * @return void
235
     */
236
    public function emptyFiles(Reader $reader)
237
    {
238
        $total = 0;
239
240
        foreach ($reader as $row) {
241
            $total++;
242
        }
243
244
        $this->assertSame(0, $total);
245
    }
246
247
    /**
248
     * Data provider for empty file test.
249
     *
250
     * @return array
251
     */
252
    public function getEmptyFiles()
253
    {
254
        $headers = ['id', 'author', 'title', 'genre', 'price', 'publish_date', 'description'];
255
        return [
256
            [new Reader(__DIR__ . '/_files/empty.csv')],
257
            [new Reader(__DIR__ . '/_files/headers_only.csv')],
258
            [new Reader(__DIR__ . '/_files/headers_only.csv', new ProvidedHeaderStrategy($headers))],
259
        ];
260
    }
261
}
262