Completed
Push — master ( 0e8d0b...b4cd42 )
by
unknown
43s queued 34s
created

CsvTest::testDelimiterDetection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 13
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpOffice\PhpSpreadsheetTests\Reader\Csv;
6
7
use PhpOffice\PhpSpreadsheet\Reader\Csv;
8
use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;
9
use PHPUnit\Framework\Attributes\DataProvider;
10
use PHPUnit\Framework\TestCase;
11
12
class CsvTest extends TestCase
13
{
14
    #[DataProvider('providerDelimiterDetection')]
15
    public function testDelimiterDetection(string $filename, string $expectedDelimiter, string $cell, string|float|int|null $expectedValue): void
16
    {
17
        $reader = new Csv();
18
        $delim1 = $reader->getDelimiter();
19
        self::assertNull($delim1);
20
21
        $spreadsheet = $reader->load($filename);
22
23
        self::assertSame($expectedDelimiter, $reader->getDelimiter(), 'should be able to infer the delimiter');
24
25
        $actual = $spreadsheet->getActiveSheet()->getCell($cell)->getValue();
26
        self::assertSame($expectedValue, $actual, 'should be able to retrieve correct value');
27
    }
28
29
    public static function providerDelimiterDetection(): array
30
    {
31
        return [
32
            [
33
                'tests/data/Reader/CSV/enclosure.csv',
34
                ',',
35
                'C4',
36
                'username2',
37
            ],
38
            [
39
                'tests/data/Reader/CSV/semicolon_separated.csv',
40
                ';',
41
                'C2',
42
                '25,5',
43
            ],
44
            [
45
                'tests/data/Reader/CSV/line_break_in_enclosure.csv',
46
                ',',
47
                'A3',
48
                'Test',
49
            ],
50
            [
51
                'tests/data/Reader/CSV/line_break_in_enclosure_with_escaped_quotes.csv',
52
                ',',
53
                'A3',
54
                'Test',
55
            ],
56
            [
57
                'tests/data/Reader/HTML/csv_with_angle_bracket.csv',
58
                ',',
59
                'B1',
60
                'Number of items with weight <= 50kg',
61
            ],
62
            [
63
                'samples/Reader2/sampleData/example1.csv',
64
                ',',
65
                'I4',
66
                '100%',
67
            ],
68
            [
69
                'samples/Reader2/sampleData/example2.csv',
70
                ',',
71
                'D8',
72
                -58.373161,
73
            ],
74
            [
75
                'tests/data/Reader/CSV/empty.csv',
76
                ',',
77
                'A1',
78
                null,
79
            ],
80
            [
81
                'tests/data/Reader/CSV/no_delimiter.csv',
82
                ',',
83
                'A1',
84
                'SingleLine',
85
            ],
86
        ];
87
    }
88
89
    #[DataProvider('providerCanLoad')]
90
    public function testCanLoad(bool $expected, string $filename): void
91
    {
92
        $reader = new Csv();
93
        self::assertSame($expected, $reader->canRead($filename));
94
    }
95
96
    public static function providerCanLoad(): array
97
    {
98
        return [
99
            [false, 'tests/data/Reader/Ods/data.ods'],
100
            [false, 'samples/templates/excel2003.xml'],
101
            [true, 'tests/data/Reader/CSV/enclosure.csv'],
102
            [true, 'tests/data/Reader/CSV/semicolon_separated.csv'],
103
            [true, 'tests/data/Reader/CSV/contains_html.csv'],
104
            [true, 'tests/data/Reader/CSV/csv_without_extension'],
105
            [true, 'tests/data/Reader/HTML/csv_with_angle_bracket.csv'],
106
            [true, 'tests/data/Reader/CSV/empty.csv'],
107
            [true, 'samples/Reader2/sampleData/example1.csv'],
108
            [true, 'samples/Reader2/sampleData/example2.csv'],
109
        ];
110
    }
111
112
    #[DataProvider('providerVersion')]
113
    public function testEscapeCharacters(int $version): void
114
    {
115
        if ($version >= 90000) {
116
            $this->expectException(ReaderException::class);
117
            $this->expectExceptionMessage('Escape character must be null string');
118
        }
119
        $reader = new Csv();
120
        if ($version === PHP_VERSION_ID) {
121
            $reader->setEscapeCharacter('"');
122
        } else {
123
            $reader->setEscapeCharacter('"', $version);
124
        }
125
        $worksheet = $reader->load('tests/data/Reader/CSV/backslash.csv')
126
            ->getActiveSheet();
127
128
        $expected = [
129
            ['field 1', 'field 2\\'],
130
            ['field 3\\', 'field 4'],
131
        ];
132
133
        self::assertSame('"', $reader->getEscapeCharacter());
134
        self::assertSame($expected, $worksheet->toArray());
135
    }
136
137
    public static function providerVersion(): array
138
    {
139
        return [
140
            [PHP_VERSION_ID],
141
            [90000],
142
        ];
143
    }
144
145
    public function testInvalidWorkSheetInfo(): void
146
    {
147
        $this->expectException(ReaderException::class);
148
        $reader = new Csv();
149
        $reader->listWorksheetInfo('');
150
    }
151
152
    public function testUtf16LineBreak(): void
153
    {
154
        $reader = new Csv();
155
        $reader->setInputEncoding('UTF-16BE');
156
        $spreadsheet = $reader->load('tests/data/Reader/CSV/utf16be.line_break_in_enclosure.csv');
157
        $sheet = $spreadsheet->getActiveSheet();
158
        $expected = <<<EOF
159
            This is a test
160
            with line breaks
161
            that breaks the
162
            delimiters
163
            EOF;
164
        self::assertEquals($expected, $sheet->getCell('B3')->getValue());
165
    }
166
167
    public function testLineBreakEscape(): void
168
    {
169
        $reader = new Csv();
170
        $spreadsheet = $reader->load('tests/data/Reader/CSV/line_break_in_enclosure_with_escaped_quotes.csv');
171
        $sheet = $spreadsheet->getActiveSheet();
172
        $expected = <<<EOF
173
            This is a "test csv file"
174
            with both "line breaks"
175
            and "escaped
176
            quotes" that breaks
177
            the delimiters
178
            EOF;
179
        self::assertEquals($expected, $sheet->getCell('B3')->getValue());
180
    }
181
182
    public function testUtf32LineBreakEscape(): void
183
    {
184
        $reader = new Csv();
185
        $reader->setInputEncoding('UTF-32LE');
186
        $spreadsheet = $reader->load('tests/data/Reader/CSV/line_break_escaped_32le.csv');
187
        $sheet = $spreadsheet->getActiveSheet();
188
        $expected = <<<EOF
189
            This is a "test csv file"
190
            with both "line breaks"
191
            and "escaped
192
            quotes" that breaks
193
            the delimiters
194
            EOF;
195
        self::assertEquals($expected, $sheet->getCell('B3')->getValue());
196
    }
197
198
    public function testSeparatorLine(): void
199
    {
200
        $reader = new Csv();
201
        $reader->setSheetIndex(3);
202
        $spreadsheet = $reader->load('tests/data/Reader/CSV/sep.csv');
203
        self::assertEquals(';', $reader->getDelimiter());
204
        $sheet = $spreadsheet->getActiveSheet();
205
        self::assertEquals(3, $reader->getSheetIndex());
206
        self::assertEquals(3, $spreadsheet->getActiveSheetIndex());
207
        self::assertEquals('A', $sheet->getCell('A1')->getValue());
208
        self::assertEquals(1, $sheet->getCell('B1')->getValue());
209
        self::assertEquals(2, $sheet->getCell('A2')->getValue());
210
        self::assertEquals(3, $sheet->getCell('B2')->getValue());
211
    }
212
213
    public function testDefaultSettings(): void
214
    {
215
        $reader = new Csv();
216
        self::assertEquals('UTF-8', $reader->getInputEncoding());
217
        self::assertEquals('"', $reader->getEnclosure());
218
        $reader->setEnclosure('\'');
219
        self::assertEquals('\'', $reader->getEnclosure());
220
        $reader->setEnclosure('');
221
        self::assertEquals('"', $reader->getEnclosure());
222
        // following tests from BaseReader
223
        self::assertTrue($reader->getReadEmptyCells());
224
        self::assertFalse($reader->getIncludeCharts());
225
        self::assertNull($reader->getLoadSheetsOnly());
226
    }
227
228
    public function testReadEmptyFileName(): void
229
    {
230
        $this->expectException(ReaderException::class);
231
        $reader = new Csv();
232
        $filename = '';
233
        $reader->load($filename);
234
    }
235
236
    public function testReadNonexistentFileName(): void
237
    {
238
        $this->expectException(ReaderException::class);
239
        $reader = new Csv();
240
        $reader->load('tests/data/Reader/CSV/encoding.utf8.csvxxx');
241
    }
242
243
    #[DataProvider('providerEscapes')]
244
    public function testInferSeparator(string $escape, string $delimiter, int $version = PHP_VERSION_ID): void
245
    {
246
        if ($version >= 90000 && $escape !== '') {
247
            $this->expectException(ReaderException::class);
248
            $this->expectExceptionMessage('Escape character must be null string');
249
        }
250
        $reader = new Csv();
251
        if ($version === PHP_VERSION_ID) {
252
            $reader->setEscapeCharacter($escape);
253
        } else {
254
            $reader->setEscapeCharacter($escape, $version);
255
        }
256
        $filename = 'tests/data/Reader/CSV/escape.csv';
257
        $reader->listWorksheetInfo($filename);
258
        self::assertEquals($delimiter, $reader->getDelimiter());
259
    }
260
261
    public static function providerEscapes(): array
262
    {
263
        return [
264
            ['\\', ';'],
265
            ["\x0", ','],
266
            ['', ','],
267
            ['\\', ';', 90000],
268
        ];
269
    }
270
271
    public function testSetDelimiterNull(): void
272
    {
273
        $reader = new Csv();
274
        $reader->setDelimiter(',');
275
        self::assertSame(',', $reader->getDelimiter());
276
        $reader->setDelimiter(null);
277
        self::assertNull($reader->getDelimiter());
278
    }
279
}
280