Passed
Push — master ( 4f0280...b89b05 )
by Alexander
01:15
created

$2   A

Complexity

Total Complexity 1

Size/Duplication

Total Lines 5
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 5
rs 10
c 1
b 0
f 0
wmc 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Yiisoft\Data\Tests\Reader;
5
6
use PHPUnit\Framework\TestCase;
7
use Yiisoft\Data\Reader\Filter\All;
8
use Yiisoft\Data\Reader\Filter\Any;
9
use Yiisoft\Data\Reader\Filter\Equals;
10
use Yiisoft\Data\Reader\Filter\FilterInterface;
11
use Yiisoft\Data\Reader\Filter\GreaterThan;
12
use Yiisoft\Data\Reader\Filter\GreaterThanOrEqual;
13
use Yiisoft\Data\Reader\Filter\In;
14
use Yiisoft\Data\Reader\Filter\LessThan;
15
use Yiisoft\Data\Reader\Filter\LessThanOrEqual;
16
use Yiisoft\Data\Reader\Filter\Like;
17
use Yiisoft\Data\Reader\Filter\Not;
18
use Yiisoft\Data\Reader\Iterable\IterableDataReader;
19
use Yiisoft\Data\Reader\Sort;
20
21
final class IterableDataReaderTest extends TestCase
22
{
23
    private function getDataSet(): array
24
    {
25
        return [
26
            [
27
                'id' => 1,
28
                'name' => 'Codename Boris',
29
            ],
30
            [
31
                'id' => 2,
32
                'name' => 'Codename Doris',
33
            ],
34
            [
35
                'id' => 3,
36
                'name' => 'Agent K',
37
            ],
38
            [
39
                'id' => 5,
40
                'name' => 'Agent J',
41
            ],
42
            [
43
                'id' => 6,
44
                'name' => '007',
45
            ],
46
        ];
47
    }
48
49
    private function getDataSetSortedByName(): array
50
    {
51
        return [
52
            [
53
                'id' => 6,
54
                'name' => '007',
55
            ],
56
            [
57
                'id' => 5,
58
                'name' => 'Agent J',
59
            ],
60
            [
61
                'id' => 3,
62
                'name' => 'Agent K',
63
            ],
64
            [
65
                'id' => 1,
66
                'name' => 'Codename Boris',
67
            ],
68
            [
69
                'id' => 2,
70
                'name' => 'Codename Doris',
71
            ],
72
        ];
73
    }
74
75
    public function testWithLimitIsImmutable(): void
76
    {
77
        $reader = new IterableDataReader([]);
78
79
        $this->assertNotSame($reader, $reader->withLimit(1));
80
    }
81
82
    public function testLimitIsApplied(): void
83
    {
84
        $reader = (new IterableDataReader($this->getDataSet()))
85
            ->withLimit(5);
86
87
        $data = $reader->read();
88
89
        $this->assertCount(5, $data);
90
        $this->assertSame(array_slice($this->getDataSet(), 0, 5), $data);
91
    }
92
93
    public function testOffsetIsApplied(): void
94
    {
95
        $reader = (new IterableDataReader($this->getDataSet()))
96
            ->withOffset(2);
97
98
        $data = $reader->read();
99
100
        $this->assertCount(3, $data);
101
        $this->assertSame(array_slice($this->getDataSet(), 2, 3), $data);
102
    }
103
104
    public function testsWithSortIsImmutable(): void
105
    {
106
        $reader = new IterableDataReader([]);
107
108
        $this->assertNotSame($reader, $reader->withSort(null));
109
    }
110
111
    public function testSorting(): void
112
    {
113
        $sorting = new Sort([
114
            'id',
115
            'name'
116
        ]);
117
118
        $sorting = $sorting->withOrder(['name' => 'asc']);
119
120
        $reader = (new IterableDataReader($this->getDataSet()))
121
            ->withSort($sorting);
122
123
        $data = $reader->read();
124
125
        $this->assertSame($this->getDataSetSortedByName(), $data);
126
    }
127
128
    public function testCounting(): void
129
    {
130
        $reader = new IterableDataReader($this->getDataSet());
131
        $this->assertSame(5, $reader->count());
132
        $this->assertCount(5, $reader);
133
    }
134
135
    public function testsWithFilterIsImmutable(): void
136
    {
137
        $reader = new IterableDataReader([]);
138
139
        $this->assertNotSame($reader, $reader->withFilter(null));
140
    }
141
142
    public function testEqualsFiltering(): void
143
    {
144
        $filter = new Equals('id', 3);
145
        $reader = (new IterableDataReader($this->getDataSet()))
146
            ->withFilter($filter);
147
148
        $this->assertSame([
149
            [
150
                'id' => 3,
151
                'name' => 'Agent K',
152
            ],
153
        ], $reader->read());
154
    }
155
156
    public function testGreaterThanFiltering(): void
157
    {
158
        $filter = new GreaterThan('id', 3);
159
        $reader = (new IterableDataReader($this->getDataSet()))
160
            ->withFilter($filter);
161
162
        $this->assertSame([
163
            [
164
                'id' => 5,
165
                'name' => 'Agent J',
166
            ],
167
            [
168
                'id' => 6,
169
                'name' => '007',
170
            ],
171
        ], $reader->read());
172
    }
173
174
    public function testGreaterThanOrEqualFiltering(): void
175
    {
176
        $filter = new GreaterThanOrEqual('id', 3);
177
        $reader = (new IterableDataReader($this->getDataSet()))
178
            ->withFilter($filter);
179
180
        $this->assertSame([
181
            [
182
                'id' => 3,
183
                'name' => 'Agent K',
184
            ],
185
            [
186
                'id' => 5,
187
                'name' => 'Agent J',
188
            ],
189
            [
190
                'id' => 6,
191
                'name' => '007',
192
            ],
193
        ], $reader->read());
194
    }
195
196
    public function testLessThanFiltering(): void
197
    {
198
        $filter = new LessThan('id', 3);
199
        $reader = (new IterableDataReader($this->getDataSet()))
200
            ->withFilter($filter);
201
202
        $this->assertSame([
203
            [
204
                'id' => 1,
205
                'name' => 'Codename Boris',
206
            ],
207
            [
208
                'id' => 2,
209
                'name' => 'Codename Doris',
210
            ],
211
        ], $reader->read());
212
    }
213
214
    public function testLessThanOrEqualFiltering(): void
215
    {
216
        $filter = new LessThanOrEqual('id', 3);
217
        $reader = (new IterableDataReader($this->getDataSet()))
218
            ->withFilter($filter);
219
220
        $this->assertSame([
221
            [
222
                'id' => 1,
223
                'name' => 'Codename Boris',
224
            ],
225
            [
226
                'id' => 2,
227
                'name' => 'Codename Doris',
228
            ],
229
            [
230
                'id' => 3,
231
                'name' => 'Agent K',
232
            ],
233
        ], $reader->read());
234
    }
235
236
    public function testInFiltering(): void
237
    {
238
        $filter = new In('id', [1, 2]);
239
        $reader = (new IterableDataReader($this->getDataSet()))
240
            ->withFilter($filter);
241
242
        $this->assertSame([
243
            [
244
                'id' => 1,
245
                'name' => 'Codename Boris',
246
            ],
247
            [
248
                'id' => 2,
249
                'name' => 'Codename Doris',
250
            ],
251
        ], $reader->read());
252
    }
253
254
    public function testLikeFiltering(): void
255
    {
256
        $filter = new Like('name', 'agent');
257
        $reader = (new IterableDataReader($this->getDataSet()))
258
            ->withFilter($filter);
259
260
        $this->assertSame([
261
            [
262
                'id' => 3,
263
                'name' => 'Agent K',
264
            ],
265
            [
266
                'id' => 5,
267
                'name' => 'Agent J',
268
            ],
269
        ], $reader->read());
270
    }
271
272
    public function testNotFiltering(): void
273
    {
274
        $filter = new Not(new Equals('id', 1));
275
        $reader = (new IterableDataReader($this->getDataSet()))
276
            ->withFilter($filter);
277
278
        $this->assertSame([
279
            [
280
                'id' => 2,
281
                'name' => 'Codename Doris',
282
            ],
283
            [
284
                'id' => 3,
285
                'name' => 'Agent K',
286
            ],
287
            [
288
                'id' => 5,
289
                'name' => 'Agent J',
290
            ],
291
            [
292
                'id' => 6,
293
                'name' => '007',
294
            ],
295
        ], $reader->read());
296
    }
297
298
    public function testAnyFiltering(): void
299
    {
300
        $filter = new Any(
301
            new Equals('id', 1),
302
            new Equals('id', 2)
303
        );
304
        $reader = (new IterableDataReader($this->getDataSet()))
305
            ->withFilter($filter);
306
307
        $this->assertSame([
308
            [
309
                'id' => 1,
310
                'name' => 'Codename Boris',
311
            ],
312
            [
313
                'id' => 2,
314
                'name' => 'Codename Doris',
315
            ],
316
        ], $reader->read());
317
    }
318
319
    public function testAllFiltering(): void
320
    {
321
        $filter = new All(
322
            new GreaterThan('id', 3),
323
            new Like('name', 'agent')
324
        );
325
        $reader = (new IterableDataReader($this->getDataSet()))
326
            ->withFilter($filter);
327
328
        $this->assertSame([
329
            [
330
                'id' => 5,
331
                'name' => 'Agent J',
332
            ],
333
        ], $reader->read());
334
    }
335
336
    public function testLimitedSort(): void
337
    {
338
        $readerMin = (new IterableDataReader($this->getDataSet()))
339
            ->withSort(
340
                (new Sort(['id']))->withOrder(['id' => 'asc'])
341
            )
342
            ->withLimit(1);
343
        $min = $readerMin->read()[0]['id'];
344
        $this->assertSame(1, $min, 'Wrong min value found');
345
346
        $readerMax = (new IterableDataReader($this->getDataSet()))
347
            ->withSort(
348
                (new Sort(['id']))->withOrder(['id' => 'desc'])
349
            )
350
            ->withLimit(1);
351
        $max = $readerMax->read()[0]['id'];
352
        $this->assertSame(6, $max, 'Wrong max value found');
353
    }
354
355
    public function testFilteredCount(): void
356
    {
357
        $reader = new IterableDataReader($this->getDataSet());
358
        $total = count($reader);
359
360
        $this->assertSame(5, $total, 'Wrong count of elements');
361
362
        $reader = $reader->withFilter(new Like('name', 'agent'));
363
        $totalAgents = count($reader);
364
        $this->assertSame(2, $totalAgents, 'Wrong count of filtered elements');
365
    }
366
367
    public function testIteratorIteratorAsDataSet(): void
368
    {
369
        $reader = new IterableDataReader(new \ArrayIterator($this->getDataSet()));
370
        $sorting = new Sort([
371
            'id',
372
            'name'
373
        ]);
374
        $sorting = $sorting->withOrder(['name' => 'asc']);
375
        $this->assertSame($this->getDataSetSortedByName(), $reader->withSort($sorting)->read());
376
    }
377
378
    private function getDataSetAsGenerator(): \Generator
379
    {
380
        yield from $this->getDataSet();
381
    }
382
383
    public function testGeneratorAsDataSet(): void
384
    {
385
        $reader = new IterableDataReader($this->getDataSetAsGenerator());
386
        $sorting = new Sort([
387
            'id',
388
            'name'
389
        ]);
390
        $sorting = $sorting->withOrder(['name' => 'asc']);
391
        $this->assertSame($this->getDataSetSortedByName(), $reader->withSort($sorting)->read());
392
    }
393
394
    public function testCustomFilter(): void
395
    {
396
        $digitalFilter = new class /*Digital*/
397
        ('name') implements FilterInterface
398
        {
399
            private $field;
400
401
            public function __construct(string $field)
402
            {
403
                $this->field = $field;
404
            }
405
406
            public function toArray(): array
407
            {
408
                return [self::getOperator(), $this->field];
409
            }
410
411
            public static function getOperator(): string
412
            {
413
                return 'digital';
414
            }
415
        };
416
        $reader = new class ($this->getDataSet()) extends IterableDataReader
417
        {
418
            protected function matchFilter(array $item, array $filter): bool
419
            {
420
                [$operation, $field] = $filter;
421
422
                if ($operation === 'digital' /*Digital::getOperator()*/) {
423
                    return ctype_digit($item[$field]);
424
                }
425
426
                return parent::matchFilter($item, $filter);
427
            }
428
        };
429
430
        $reader = $reader->withFilter($digitalFilter);
431
432
        $filtered = $reader->read();
433
        $this->assertCount(1, $filtered);
434
        $this->assertSame('007', $filtered[0]['name']);
435
    }
436
437
    public function testNotSupportedOperator()
438
    {
439
        $dataReader = (new IterableDataReader($this->getDataSet()))
440
            ->withFilter(new class('id', 2) extends \Yiisoft\Data\Reader\Filter\Equals
441
            {
442
                public static function getOperator(): string
443
                {
444
                    return '----';
445
                }
446
            });
447
        $this->expectException(\RuntimeException::class);
448
        $dataReader->read();
449
    }
450
451
}
452