Passed
Pull Request — develop (#31)
by Glynn
02:43
created

ArrayFunctionTests::testCanUseColumn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 57
Code Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 44
nc 1
nop 0
dl 0
loc 57
rs 9.216
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
require_once dirname(__FILE__, 2) . '/FunctionsLoader.php';
6
7
/**
8
 * Tests for the Array functions class.
9
 *
10
 * @since 0.1.0
11
 * @author Glynn Quelch <[email protected]>
12
 */
13
14
use PHPUnit\Framework\TestCase;
15
use PinkCrab\FunctionConstructors\Arrays as Arr;
16
use PinkCrab\FunctionConstructors\Numbers as Num;
17
use PinkCrab\FunctionConstructors\Strings as Str;
18
use PinkCrab\FunctionConstructors\FunctionsLoader;
19
use PinkCrab\FunctionConstructors\GeneralFunctions as Func;
20
21
use function PHPUnit\Framework\throwException;
22
23
/**
24
 * ArrayFunction class.
25
 */
26
class ArrayFunctionTests extends TestCase
27
{
28
    /**
29
     * Random pollyfills
30
     */
31
    public function __call($method, $params)
32
    {
33
        switch ($method) {
34
            case 'assertIsArray':
35
                $this->assertTrue(is_array($params));
36
                break;
37
        }
38
    }
39
40
    public function setup(): void
41
    {
42
        FunctionsLoader::include();
43
    }
44
45
    public function testCanPushToHead(): void
46
    {
47
        $pushToHead = Arr\pushHead(array( 3, 4, 5, 6 ));
48
        $added2     = $pushToHead(2);
49
        $this->assertEquals(2, $added2[0]);
50
51
        $pushToHead = Arr\pushHead($added2);
52
        $added1     = $pushToHead(1);
53
        $this->assertEquals(1, $added1[0]);
54
55
        // As curried.
56
        $curried = Arr\pushHead(array( 3, 4, 5, 6 ))(2);
57
        $this->assertEquals(2, $curried[0]);
58
    }
59
60
    public function testCanPushToTail(): void
61
    {
62
        $pushToTail = Arr\pushTail(array( 1, 2, 3, 4 ));
63
        $added2     = $pushToTail(5);
64
        $this->assertEquals(5, $added2[4]);
65
66
        $pushToTail = Arr\pushTail($added2);
67
        $added1     = $pushToTail(6);
68
        $this->assertEquals(6, $added1[5]);
69
70
        // As curried.
71
        $curried = Arr\pushTail(array( 1, 2, 3, 4 ))(5);
72
        $this->assertEquals(5, $curried[4]);
73
    }
74
75
    public function testCanUseTail()
76
    {
77
        $names = array( 'Sam Smith', 'Barry Smith', 'Sam Power', 'Rebecca Smith' );
78
        $this->assertEquals('Rebecca Smith', Arr\tail($names));
79
        // Check returns null if empty.
80
        $this->assertNull(Arr\tail(array()));
81
    }
82
83
    public function testCanUseHead()
84
    {
85
        $names = array( 'Sam Smith', 'Barry Smith', 'Sam Power', 'Rebecca Smith' );
86
        $this->assertEquals('Sam Smith', Arr\head($names));
87
        // Check returns null if empty.
88
        $this->assertNull(Arr\head(array()));
89
    }
90
91
    public function testCanCompileArray(): void
92
    {
93
        $arrayCompiler = Arr\arrayCompiler();
94
        $arrayCompiler = $arrayCompiler('Hello');
95
        $arrayCompiler = $arrayCompiler('ERROR');
96
        $this->assertEquals('Hello', $arrayCompiler()[0]);
97
        $this->assertEquals('ERROR', $arrayCompiler()[1]);
98
99
        // As curried
100
        $arrayCompiler = $arrayCompiler('NO PLEASE GOD NO')('what')('more');
101
        $this->assertEquals('NO PLEASE GOD NO', $arrayCompiler()[2]);
102
        $this->assertEquals('what', $arrayCompiler()[3]);
103
        $this->assertEquals('more', $arrayCompiler()[4]);
104
105
        // Test can output on invoke.
106
        $this->assertTrue(is_array($arrayCompiler()));
107
    }
108
109
    public function testCanCompileArrayTyped()
110
    {
111
        $arrayCompiler = Arr\arrayCompilerTyped('is_string');
112
        $arrayCompiler = $arrayCompiler('Hello');
113
        $arrayCompiler = $arrayCompiler('ERROR');
114
        $arrayCompiler = $arrayCompiler(array( 'ERROR' ));
115
        $this->assertCount(2, $arrayCompiler());
116
117
        $arrayCompiler = $arrayCompiler('Hello')(1)(NAN)('so 4?');
118
        $this->assertCount(4, $arrayCompiler());
119
    }
120
121
    public function testCanGroupByArray(): void
122
    {
123
        $groupByPerfectNumbers = Arr\groupBy(
124
            function ($e) {
125
                return in_array($e, array( 1, 2, 3, 6, 12 )) ? 'Perfect' : 'Not Perfect';
126
            }
127
        );
128
129
        $grouped = $groupByPerfectNumbers(range(1, 12));
130
131
        $this->assertArrayHasKey('Perfect', $grouped);
132
        $this->assertArrayHasKey('Not Perfect', $grouped);
133
        $this->assertContains(1, $grouped['Perfect']);
134
        $this->assertContains(2, $grouped['Perfect']);
135
        $this->assertContains(3, $grouped['Perfect']);
136
        $this->assertContains(5, $grouped['Not Perfect']);
137
        $this->assertContains(7, $grouped['Not Perfect']);
138
        $this->assertContains(9, $grouped['Not Perfect']);
139
    }
140
141
    public function testCanChunk(): void
142
    {
143
        $chunkIn5     = Arr\chunk(5);
144
        $chunkedRange = $chunkIn5(range(1, 500));
145
        $this->assertCount(100, $chunkedRange);
146
        $this->assertCount(5, $chunkedRange[5]);
147
        $this->assertCount(5, $chunkedRange[78]);
148
149
        // Check that keys are retained.
150
        $chunkInPairs = Arr\chunk(2, true);
151
        $chunkedNames = $chunkInPairs(array( 'Jim', 'Bob', 'Gem', 'Fay' ));
152
        $this->assertCount(2, $chunkedNames);
153
        $this->assertEquals('Bob', $chunkedNames[0][1]);
154
        $this->assertEquals('Fay', $chunkedNames[1][3]);
155
    }
156
157
    public function testCanUseZip()
158
    {
159
        $array = array( 'a', 'b', 'c' );
160
161
        // Missing Key.
162
        $arrayMissing    = array( 'A', 'B' );
163
        $expectedMissing = array( array( 'a', 'A' ), array( 'b', 'B' ), array( 'c', 'FALLBACK' ) );
164
        $resultMissing   = Arr\zip($arrayMissing, 'FALLBACK')($array);
165
        $this->assertSame($resultMissing, $expectedMissing);
166
167
        // Matching length.
168
        $arrayFull    = array( 'A', 'B', 'C' );
169
        $expectedFull = array( array( 'a', 'A' ), array( 'b', 'B' ), array( 'c', 'C' ) );
170
        $resultFull   = Arr\zip($arrayFull, 'FALLBACK')($array);
171
        $this->assertSame($resultFull, $expectedFull);
172
    }
173
174
    public function testCanUseColumn(): void
175
    {
176
        $data = array(
177
            array(
178
                'id'   => 41,
179
                'name' => 'Bob',
180
                'foo'  => rand(1, 7),
181
            ),
182
            array(
183
                'id'   => 26,
184
                'name' => 'Jane',
185
                'foo'  => rand(1, 7),
186
            ),
187
            array(
188
                'id'   => 53,
189
                'name' => 'Sam',
190
                'foo'  => rand(1, 7),
191
            ),
192
            array(
193
                'id'   => 64,
194
                'name' => 'Bev',
195
                'foo'  => rand(1, 7),
196
            ),
197
            array(
198
                'id'   => 55,
199
                'name' => 'Joan',
200
                'foo'  => rand(1, 7),
201
            ),
202
            array(
203
                'id'   => 644,
204
                'name' => 'Bazza',
205
                'foo'  => rand(1, 7),
206
            ),
207
            array(
208
                'id'   => 66667,
209
                'name' => 'Duke',
210
                'foo'  => rand(1, 7),
211
            ),
212
            array(
213
                'id'   => 666668,
214
                'name' => 'Guybrush',
215
                'foo'  => rand(1, 7),
216
            ),
217
        );
218
219
        $getUsersNames = Arr\column('name', 'id');
220
        $this->assertCount(8, $getUsersNames($data));
221
        $this->assertEquals('Bob', $getUsersNames($data)[41]);
222
        $this->assertEquals('Bev', $getUsersNames($data)[64]);
223
        $this->assertEquals('Guybrush', $getUsersNames($data)[666668]);
224
225
        $getUsersRandoms = Arr\column('foo', 'name');
226
        $this->assertCount(8, $getUsersRandoms($data));
227
        $this->assertArrayHasKey('Bev', $getUsersRandoms($data));
228
        $this->assertArrayHasKey('Duke', $getUsersRandoms($data));
229
        $this->assertArrayNotHasKey(2, $getUsersRandoms($data));
230
        $this->assertArrayHasKey('Bazza', $getUsersRandoms($data));
231
    }
232
233
    public function testCanFlattenArray(): void
234
    {
235
        $array = array(
236
            1,
237
            2,
238
            array( 3, 4 ),
239
            array(
240
                5,
241
                6,
242
                7,
243
                8,
244
                array(
245
                    9,
246
                    10,
247
                    array( 11, 12, 13 ),
248
                ),
249
            ),
250
        );
251
        $this->assertArrayHasKey(2, Arr\flattenByN(2)($array));
252
        $this->assertIsArray(Arr\flattenByN(1)($array)[8]);
253
254
        $this->assertArrayHasKey(9, Arr\flattenByN(2)($array));
255
        $this->assertIsArray(Arr\flattenByN(2)($array)[10]);
256
257
        $this->assertArrayHasKey(12, Arr\flattenByN(3)($array));
258
        $this->assertEquals(13, Arr\flattenByN(3)($array)[12]);
259
260
        // Check will fully flatten if no depth defined.
261
        $this->assertArrayHasKey(12, Arr\flattenByN()($array));
262
        $this->assertEquals(13, Arr\flattenByN()($array)[12]);
263
    }
264
265
    public function testCanUseReplace()
266
    {
267
        $base          = array( 'orange', 'banana', 'apple', 'raspberry' );
268
        $replacements  = array(
269
            0 => 'pineapple',
270
            4 => 'cherry',
271
        );
272
        $replacements2 = array( 0 => 'grape' );
273
274
        $replaceItems = Arr\replace($replacements, $replacements2);
275
276
        $this->assertIsArray($replaceItems($base));
277
        $this->assertEquals('grape', $replaceItems($base)[0]);
278
        $this->assertEquals('banana', $replaceItems($base)[1]);
279
        $this->assertEquals('apple', $replaceItems($base)[2]);
280
        $this->assertEquals('raspberry', $replaceItems($base)[3]);
281
        $this->assertEquals('cherry', $replaceItems($base)[4]);
282
    }
283
    public function testCanUseReplaceRecursive(): void
284
    {
285
        $base = array(
286
            'citrus'  => array( 'orange' ),
287
            'berries' => array( 'apple', 'raspberry' ),
288
        );
289
290
        $replacements = array(
291
            'citrus'  => array( 'pineapple' ),
292
            'berries' => array( 'blueberry' ),
293
        );
294
295
        $replaceItems = Arr\replaceRecursive($replacements);
296
297
        $this->assertIsArray($replaceItems($base));
298
        $this->assertArrayHasKey('citrus', $replaceItems($base));
299
        $this->assertArrayHasKey('berries', $replaceItems($base));
300
        $this->assertEquals('pineapple', $replaceItems($base)['citrus'][0]);
301
        $this->assertEquals('raspberry', $replaceItems($base)['berries'][1]);
302
    }
303
304
    public function testCanUseSumWhere()
305
    {
306
        $data = array(
307
            (object) array(
308
                'id'   => 1,
309
                'cost' => 12.55,
310
            ),
311
            (object) array(
312
                'id'   => 3,
313
                'cost' => 2.45,
314
            ),
315
            (object) array(
316
                'id'   => 34,
317
                'cost' => 99.99,
318
            ),
319
            (object) array(
320
                'id'   => 12,
321
                'cost' => 100.01,
322
            ),
323
        );
324
325
        $costSum = Arr\sumWhere(
326
            function ($e) {
327
                return $e->cost;
328
            }
329
        );
330
331
        $this->assertEquals(215.00, $costSum($data));
332
    }
333
334
335
336
    public function testCanSortArray(): void
337
    {
338
        $array         = array( 'b', 'c', 'a', 'f', 'd', 'z', 'g' );
339
        $sortAsStrings = Arr\sort(SORT_STRING);
340
341
        $sortedArray = $sortAsStrings($array);
342
        $this->assertEquals('a', $sortedArray[0]);
343
        $this->assertEquals('b', $sortedArray[1]);
344
        $this->assertEquals('c', $sortedArray[2]);
345
        $this->assertEquals('z', $sortedArray[6]);
346
347
        // Check hasnt changed inital array.
348
        $this->assertEquals('c', $array[1]);
349
        $this->assertEquals('a', $array[2]);
350
    }
351
352
    public function testCanDoUasortOnArray(): void
353
    {
354
        $array = array(
355
            'a' => 4,
356
            'b' => 8,
357
            'c' => -1,
358
            'd' => -9,
359
            'e' => 2,
360
            'f' => 5,
361
            'g' => 3,
362
            'h' => -4,
363
        );
364
365
        $lowestFirstCallback = function ($a, $b) {
366
            if ($a == $b) {
367
                return 0;
368
            }
369
            return ($a < $b) ? -1 : 1;
370
        };
371
372
        $sortByLowest = Arr\uasort($lowestFirstCallback);
373
374
        // Still retains the key.
375
        $sortedArray = $sortByLowest($array);
376
377
        $this->assertEquals(-9, $sortedArray['d']);
378
        $this->assertEquals(-9, array_values($sortedArray)[0]);
379
380
        $this->assertEquals(2, $sortedArray['e']);
381
        $this->assertEquals(2, array_values($sortedArray)[3]);
382
383
        $this->assertEquals(8, $sortedArray['b']);
384
        $this->assertEquals(8, array_values($sortedArray)[7]);
385
    }
386
387
388
    public function testCanDoUsortOnArray(): void
389
    {
390
        $array = array( 3, 2, 5, 6, 1 );
391
392
        $lowestFirstCallback = function ($a, $b) {
393
            if ($a == $b) {
394
                return 0;
395
            }
396
            return ($a < $b) ? -1 : 1;
397
        };
398
399
        $sortByLowest = Arr\usort($lowestFirstCallback);
400
401
        // Still retains the key.
402
        $sortedArray = $sortByLowest($array);
403
404
        $this->assertEquals(1, $sortedArray[0]);
405
        $this->assertEquals(2, $sortedArray[1]);
406
        $this->assertEquals(5, $sortedArray[3]);
407
        $this->assertEquals(6, $sortedArray[4]);
408
    }
409
410
    public function testCanPartitionTable()
411
    {
412
        $isEven = function ($e) {
413
            return $e % 2 === 0;
414
        };
415
416
        $sortByOddEven = Arr\partition($isEven);
417
418
        $data = array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );
419
420
        $sorted = $sortByOddEven($data);
421
        $this->assertCount(5, $sorted[0]);
422
        $this->assertCount(5, $sorted[1]);
423
424
        $this->assertContains(2, $sorted[1]);
425
        $this->assertContains(4, $sorted[1]);
426
        $this->assertContains(8, $sorted[1]);
427
        $this->assertContains(3, $sorted[0]);
428
        $this->assertContains(7, $sorted[0]);
429
    }
430
431
    public function testCanDoToString(): void
432
    {
433
        $source = array(
434
            'hi',
435
            'there',
436
            'how',
437
            'are',
438
            'you',
439
            3,
440
            12.7,
441
            true,
442
            null,
443
        );
444
445
        $noSpacing   = Arr\toString();
446
        $withSpacing = Arr\toString(' ');
447
448
        $this->assertEquals('hitherehowareyou312.71', $noSpacing($source));
449
        $this->assertEquals('hi there how are you 3 12.7 1 ', $withSpacing($source));
450
    }
451
452
    /** @testdox It should be possible to create a function which allows for calling scan on a passed array */
453
    public function testScanL(): void
454
    {
455
        $initial  = array( 1, 2, 3, 4, 5 );
456
        $expected = array( 0, 1, 3, 6, 10, 15 );
457
458
        $scan = Arr\scan(
459
            function ($carry, $item) {
460
                return $carry + $item;
461
            },
462
            0
463
        );
464
465
        $this->assertEquals($expected, $scan($initial));
466
467
        // Get a ruuning max value using scan.
468
        $max = Arr\scan(
469
            function ($carry, $item) {
470
                return max($carry, $item);
471
            },
472
            0
473
        );
474
475
        $data = [1,3,4,1,5,9,2,6,5,3,5,8,9,7,9];
476
        $expected = [0,1,3,4,4,5,9,9,9,9,9,9,9,9,9,9];
477
        $this->assertEquals($expected, $max($data));
478
    }
479
480
    /** @testdox It should be possible to create a function which allows for calling scanr on a passed array.     */
481
    public function testScanR(): void
482
    {
483
        $initial  = array( 1, 2, 3 );
484
        $expected = array( 6, 5, 3, 0 );
485
486
        $scanR = Arr\scanR(
487
            function ($carry, $item) {
488
                return $carry + $item;
489
            },
490
            0
491
        );
492
493
        $this->assertEquals($expected, $scanR($initial));
494
    }
495
}
496