GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 89c4ce...795e68 )
by Tomasz
10:48
created

EnumTest::testOneOfValuesExists()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 8
rs 10
c 1
b 0
f 1
1
<?php
2
declare(strict_types=1);
3
namespace Thunder\Platenum\Tests;
4
5
use Thunder\Platenum\Enum\AbstractConstantsEnum;
6
use Thunder\Platenum\Enum\AbstractStaticEnum;
7
use Thunder\Platenum\Enum\EnumTrait;
8
use Thunder\Platenum\Exception\PlatenumException;
9
use Thunder\Platenum\Tests\Fake\FakeEnum;
10
11
/**
12
 * @author Tomasz Kowalczyk <[email protected]>
13
 */
14
final class EnumTest extends AbstractTestCase
15
{
16
    /* --- CREATE --- */
17
18
    public function testCreateFromMember(): void
19
    {
20
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
21
        $first = $enum::fromMember('FIRST');
22
        $second = $enum::fromMember('SECOND');
23
24
        $this->assertSame('FIRST', $first->getMember());
25
        $this->assertSame('SECOND', $second->getMember());
26
    }
27
28
    public function testCreateFromValue(): void
29
    {
30
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
31
        $first = $enum::fromValue(1);
32
        $second = $enum::fromValue(2);
33
34
        $this->assertSame('FIRST', $first->getMember());
35
        $this->assertSame('SECOND', $second->getMember());
36
        $this->assertSame(1, $first->getValue());
37
        $this->assertSame(2, $second->getValue());
38
    }
39
40
    public function testCreateFromConstant(): void
41
    {
42
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
43
        $first = $enum::FIRST();
44
        $second = $enum::SECOND();
45
46
        $this->assertSame('FIRST', $first->getMember());
47
        $this->assertSame('SECOND', $second->getMember());
48
        $this->assertSame(1, $first->getValue());
49
        $this->assertSame(2, $second->getValue());
50
    }
51
52
    public function testCreateFromEnum(): void
53
    {
54
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
55
        $first = $enum::fromMember('FIRST');
56
        $otherFirst = $enum::fromEnum($first);
57
58
        $this->assertSame('FIRST', $otherFirst->getMember());
59
        $this->assertSame(1, $otherFirst->getValue());
60
    }
61
62
    public function testGetInstances(): void
63
    {
64
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
65
        $first = $enum::fromMember('FIRST');
66
        $otherFirst = $enum::fromEnum($first);
0 ignored issues
show
Unused Code introduced by
The assignment to $otherFirst is dead and can be removed.
Loading history...
67
68
        $this->assertSame([$enum::FIRST(), $enum::SECOND()], $enum::getInstances());
69
    }
70
71
    public function testExceptionNonScalarValue(): void
72
    {
73
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
74
75
        $this->expectException(PlatenumException::class);
76
        $this->expectExceptionMessage('Enum `'.$enum.'` value must be a scalar, `array` given.');
77
        $enum::fromValue([]);
78
    }
79
80
    public function testExceptionInvalidMemberConstant(): void
81
    {
82
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
83
84
        $this->expectException(PlatenumException::class);
85
        $this->expectExceptionMessage('Enum `'.$enum.'` does not contain member `THIRD` among `FIRST,SECOND`.');
86
        $enum::THIRD();
87
    }
88
89
    public function testExceptionInvalidMember(): void
90
    {
91
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
92
93
        $this->expectException(PlatenumException::class);
94
        $this->expectExceptionMessage('Enum `'.$enum.'` does not contain member `THIRD` among `FIRST,SECOND`.');
95
        $enum::fromMember('THIRD');
96
    }
97
98
    public function testExceptionInvalidValue(): void
99
    {
100
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
101
102
        $this->expectException(PlatenumException::class);
103
        $this->expectExceptionMessage('Enum `'.$enum.'` does not contain any member with value `42`.');
104
        $enum::fromValue(42);
105
    }
106
107
    public function testExceptionNonEmptyConstantArguments(): void
108
    {
109
        $enum = $this->makeRawEnum(['FIRST' => 'first', 'SECOND' => 'second']);
110
111
        $this->expectException(PlatenumException::class);
112
        $this->expectExceptionMessage('Enum `'.$enum.'` constant methods must not have any arguments.');
113
        $enum::SECOND('invalid');
114
    }
115
116
    public function testExceptionCreateFromEnumDifferentClass(): void
117
    {
118
        $enumA = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
119
        $enumB = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
120
121
        $this->expectException(PlatenumException::class);
122
        $this->expectExceptionMessage('Attempting to recreate enum '.$enumA.' from instance of '.$enumB.'.');
123
        $enumA::fromEnum($enumB::FIRST());
124
    }
125
126
    public function testExceptionCreateFromInstanceDifferentClass(): void
127
    {
128
        $enumA = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
129
        $enumB = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
130
131
        $b = $enumB::FIRST();
132
        $this->expectException(PlatenumException::class);
133
        $this->expectExceptionMessage('Attempting to recreate enum '.$enumA.' from instance of '.$enumB.'.');
134
        $enumA::FIRST()->fromInstance($b);
135
    }
136
137
    public function testExceptionMissingResolveMethod(): void
138
    {
139
        /** @var FakeEnum $enum */
140
        $enum = $this->computeUniqueClassName('ExtendsExtends');
141
        eval('class '.$enum.' { use Thunder\Platenum\Enum\EnumTrait; }');
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
142
143
        $this->expectException(PlatenumException::class);
144
        $this->expectExceptionMessage('Enum `'.$enum.'` does not implement resolve() method.');
145
        $enum::FIRST();
146
    }
147
148
    public function testExceptionNonStringMember(): void
149
    {
150
        $enum = $this->makeRawEnum([42 => 'invalid']);
151
152
        $this->expectException(PlatenumException::class);
153
        $this->expectExceptionMessage('Enum `'.$enum.'` requires all members to be strings.');
154
        $enum::fromValue(42);
155
    }
156
157
    public function testExceptionNonUniformValueType(): void
158
    {
159
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => '2', 'THIRD' => '3']);
160
161
        $this->expectException(PlatenumException::class);
162
        $this->expectExceptionMessage('Enum `'.$enum.'` member values must be of the same type, `integer,string` given.');
163
        $enum::fromValue(42);
164
    }
165
166
    /* --- GENERIC --- */
167
168
    public function testExtendedExtendedEnum(): void
169
    {
170
        /** @var FakeEnum $classA */
171
        $classA = $this->computeUniqueClassName('X');
172
        /** @var FakeEnum $classB */
173
        $classB = $this->computeUniqueClassName('X');
174
        eval('class '.$classA.' extends '.AbstractConstantsEnum::class.' {
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
175
            protected const A = 1;
176
            protected const B = 2;
177
        }
178
179
        final class '.$classB.' extends '.$classA.' {}');
180
181
        $this->assertSame('B', $classA::B()->getMember());
182
        $this->assertSame('B', $classB::B()->getMember());
183
    }
184
185
    /* --- COMPARE --- */
186
187
    public function testSameEnumEquality(): void
188
    {
189
        $enumA = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
190
        $enumB = $this->makeRawEnum(['FIRST' => 'first', 'SECOND' => 'second']);
191
192
        $this->assertTrue($enumA::FIRST()->equals($enumA::FIRST()), 'constant equals constant');
193
        $this->assertSame($enumA::SECOND(), $enumA::SECOND(), 'constant === constant');
194
        $this->assertEquals($enumA::SECOND(), $enumA::SECOND(), 'constant == constant');
195
        $this->assertSame($enumA::fromMember('FIRST'), $enumA::fromMember('FIRST'), 'key === key');
196
        $this->assertSame($enumA::fromMember('FIRST'), $enumA::FIRST(), 'key === constant');
197
198
        $this->assertTrue($enumB::fromValue('first')->equals($enumB::FIRST()), 'value equals constant');
199
        $this->assertTrue($enumB::fromValue('first')->equals($enumB::fromValue('first')), 'value equals value');
200
        $this->assertTrue($enumB::FIRST()->equals($enumB::fromValue('first')), 'constant equals value');
201
        $this->assertSame($enumB::FIRST(), $enumB::fromValue('first'), 'constant === value');
202
        $this->assertSame($enumB::fromValue('second'), $enumB::SECOND(), 'value === constant');
203
    }
204
205
    public function testSameEnumInequality(): void
206
    {
207
        $enumA = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
208
        $enumB = $this->makeRawEnum(['FIRST' => 'first', 'SECOND' => 'second']);
209
210
        $this->assertFalse($enumA::FIRST()->equals($enumA::SECOND()), 'constant !equals constant');
211
        $this->assertNotSame($enumA::FIRST(), $enumA::SECOND(), 'constant !== constant');
212
213
        $this->assertFalse($enumB::fromValue('first')->equals($enumB::SECOND()), 'value !equals constant');
214
        $this->assertFalse($enumB::fromValue('first')->equals($enumB::fromValue('second')), 'value !equals value');
215
        $this->assertFalse($enumB::FIRST()->equals($enumB::fromValue('second')), 'constant !equals value');
216
        $this->assertNotSame($enumB::FIRST(), $enumB::fromValue('second'), 'constant !== value');
217
        $this->assertNotSame($enumB::fromValue('first'), $enumB::SECOND(), 'value !== constant');
218
    }
219
220
    public function testDifferentEnumsInequality(): void
221
    {
222
        $enumA = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
223
        $enumB = $this->makeRawEnum(['FIRST' => 'first', 'SECOND' => 'second']);
224
225
        $this->assertFalse($enumA::FIRST()->equals($enumB::FIRST()));
226
        $this->assertNotSame($enumA::FIRST(), $enumB::FIRST());
227
        $this->assertNotSame($enumA::SECOND(), $enumB::SECOND());
228
    }
229
230
    /* --- LOGIC --- */
231
232
    public function testExceptionNoMembers(): void
233
    {
234
        $enum = $this->makeRawEnum([]);
235
236
        $this->expectException(PlatenumException::class);
237
        $this->expectExceptionMessage('Enum `'.$enum.'` does not contain any members.');
238
        $enum::memberExists('WHICH_IT_DOES_NOT');
239
    }
240
241
    public function testExceptionNonUniqueMemberValues(): void
242
    {
243
        $enum = $this->makeRawEnum(['X1' => 1, 'X2' => 1]);
244
245
        $this->expectException(PlatenumException::class);
246
        $this->expectExceptionMessage('Enum `'.$enum.'` members values are not unique.');
247
        $enum::X1();
248
    }
249
250
    /* --- CHECK --- */
251
252
    public function testHasMember(): void
253
    {
254
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
255
256
        $this->assertTrue($enum::SECOND()->hasMember('SECOND'));
257
        $this->assertFalse($enum::SECOND()->hasMember('FIRST'));
258
    }
259
260
    public function testHasValue(): void
261
    {
262
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
263
264
        $this->assertTrue($enum::SECOND()->hasValue(2));
265
        $this->assertFalse($enum::SECOND()->hasValue(1));
266
    }
267
268
    public function testHasOneOfMembers(): void
269
    {
270
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
271
272
        $this->assertTrue($enum::SECOND()->hasOneOfMembers(['FIRST', 'SECOND']));
273
        $this->assertTrue($enum::SECOND()->hasOneOfMembers(['SECOND', 'THIRD']));
274
        $this->assertFalse($enum::SECOND()->hasOneOfMembers(['THIRD', 'FOURTH']));
275
        $this->assertFalse($enum::SECOND()->hasOneOfMembers(['FIRST', 'FOURTH']));
276
        $this->assertFalse($enum::SECOND()->hasOneOfMembers([1.5, null, 'invalid']));
277
    }
278
279
    public function testHasOneOfValues(): void
280
    {
281
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
282
283
        $this->assertTrue($enum::SECOND()->hasOneOfValues([1, 2]));
284
        $this->assertTrue($enum::SECOND()->hasOneOfValues([2, 3]));
285
        $this->assertFalse($enum::SECOND()->hasOneOfValues([1, 4]));
286
        $this->assertFalse($enum::SECOND()->hasOneOfValues([3, 4]));
287
        $this->assertFalse($enum::SECOND()->hasOneOfValues([1.5, null, 'invalid']));
288
    }
289
290
    public function testMemberExists(): void
291
    {
292
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
293
294
        $this->assertTrue($enum::memberExists('FIRST'));
295
        $this->assertFalse($enum::memberExists('THIRD'));
296
    }
297
298
    public function testValueExists(): void
299
    {
300
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
301
302
        $this->assertTrue($enum::valueExists(1));
303
        $this->assertFalse($enum::valueExists(3));
304
    }
305
306
    public function testOneOfMembersExists(): void
307
    {
308
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
309
310
        $this->assertTrue($enum::oneOfMembersExists(['FIRST', 'SECOND']));
311
        $this->assertTrue($enum::oneOfMembersExists(['FIRST', 'THIRD']));
312
        $this->assertFalse($enum::oneOfMembersExists(['THIRD', 'FOURTH']));
313
        $this->assertFalse($enum::oneOfMembersExists([1.5, null, 'invalid']));
314
    }
315
316
    public function testOneOfValuesExists(): void
317
    {
318
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
319
320
        $this->assertTrue($enum::oneOfValuesExists([1, 2]));
321
        $this->assertTrue($enum::oneOfValuesExists([1, 3]));
322
        $this->assertFalse($enum::oneOfValuesExists([3, 4]));
323
        $this->assertFalse($enum::oneOfValuesExists([1.5, null, 'invalid']));
324
    }
325
326
    public function testIsOneOfInstances(): void
327
    {
328
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
329
330
        $this->assertTrue($enum::SECOND()->isOneOfInstances([$enum::FIRST(), $enum::SECOND()]));
331
        $this->assertTrue($enum::SECOND()->isOneOfInstances([$enum::SECOND(), new \stdClass()]));
332
        $this->assertFalse($enum::SECOND()->isOneOfInstances([new \stdClass(), new \DateTimeImmutable()]));
333
        $this->assertFalse($enum::SECOND()->isOneOfInstances([1.5, null, 'invalid']));
334
    }
335
336
    /* --- CONVERT --- */
337
338
    public function testGetMember(): void
339
    {
340
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
341
342
        $this->assertSame('FIRST', $enum::FIRST()->getMember());
343
        $this->assertSame('SECOND', $enum::SECOND()->getMember());
344
    }
345
346
    public function testGetValue(): void
347
    {
348
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
349
350
        $this->assertSame(1, $enum::FIRST()->getValue());
351
        $this->assertSame(2, $enum::SECOND()->getValue());
352
    }
353
354
    public function testMemberToValue(): void
355
    {
356
        $intEnum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
357
        $stringEnum = $this->makeRawEnum(['FIRST' => 'first', 'SECOND' => 'second']);
358
359
        $this->assertSame(1, $intEnum::memberToValue('FIRST'));
360
        $this->assertSame('first', $stringEnum::memberToValue('FIRST'));
361
    }
362
363
    public function testValueToMember(): void
364
    {
365
        $intEnum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
366
        $stringEnum = $this->makeRawEnum(['FIRST' => 'first', 'SECOND' => 'second']);
367
368
        $this->assertSame('FIRST', $intEnum::valueToMember(1));
369
        $this->assertSame('FIRST', $stringEnum::valueToMember('first'));
370
    }
371
372
    public function testImpossibleValueToMemberInvalidMemberTypeException(): void
373
    {
374
        $enum = $this->makeRawEnum(['FIRST' => 'first', 'SECOND' => 'second']);
375
        $ref = new \ReflectionClass($enum);
376
        $members = $ref->getProperty('members');
377
        $members->setAccessible(true);
378
        $members->setValue($enum, [$enum => [0 => 'first']]);
379
380
        $this->assertSame('0', $enum::valueToMember('first'));
381
    }
382
383
    public function testJsonEncode(): void
384
    {
385
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
386
387
        $this->assertSame('2', json_encode($enum::SECOND()));
388
    }
389
390
    public function testCastToString(): void
391
    {
392
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
393
394
        $this->assertSame('2', (string)$enum::SECOND());
395
    }
396
397
    public function testExceptionInvalidMemberToValue(): void
398
    {
399
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
400
401
        $this->expectException(PlatenumException::class);
402
        $this->expectExceptionMessage('Enum `'.$enum.'` does not contain member `INVALID` among `FIRST,SECOND`.');
403
        $enum::memberToValue('INVALID');
404
    }
405
406
    public function testExceptionInvalidValueToMember(): void
407
    {
408
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
409
410
        $this->expectException(PlatenumException::class);
411
        $this->expectExceptionMessage('Enum `'.$enum.'` does not contain any member with value `invalid`.');
412
        $enum::valueToMember('invalid');
413
    }
414
415
    /* --- LIST --- */
416
417
    public function testListMembers(): void
418
    {
419
        $intEnum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
420
        $stringEnum = $this->makeRawEnum(['FIRST' => 'first', 'SECOND' => 'second']);
421
422
        $this->assertSame(['FIRST', 'SECOND'], $intEnum::getMembers());
423
        $this->assertSame(['FIRST', 'SECOND'], $stringEnum::getMembers());
424
    }
425
426
    public function testListValues(): void
427
    {
428
        $intEnum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
429
        $stringEnum = $this->makeRawEnum(['FIRST' => 'first', 'SECOND' => 'second']);
430
431
        $this->assertSame([1, 2], $intEnum::getValues());
432
        $this->assertSame(['first', 'second'], $stringEnum::getValues());
433
    }
434
435
    public function testListMembersAndValues(): void
436
    {
437
        $intEnum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
438
        $stringEnum = $this->makeRawEnum(['FIRST' => 'first', 'SECOND' => 'second']);
439
440
        $this->assertSame(['FIRST' => 1, 'SECOND' => 2], $intEnum::getMembersAndValues());
441
        $this->assertSame(['FIRST' => 'first', 'SECOND' => 'second'], $stringEnum::getMembersAndValues());
442
    }
443
444
    /* --- RUNTIME --- */
445
446
    public function testSerialize(): void
447
    {
448
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
449
        $className = $this->computeUniqueClassName('X');
450
        eval('final class '.$className.' {
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
451
            /** @var EnumTrait; */
452
            private $enum;
453
            public function __construct($enum) { $this->enum = $enum; }
454
            public function getEnum() { return $this->enum; }
455
            public function __wakeup() { $this->enum->fromInstance($this->enum); }
456
        };');
457
458
        $original = $enum::FIRST();
459
        $unserialized = unserialize(serialize(new $className($original)))->getEnum();
460
461
        $this->assertSame($original, $unserialized);
462
    }
463
464
    public function testExceptionMagicClone(): void
465
    {
466
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
467
468
        $this->expectException(PlatenumException::class);
469
        $this->expectExceptionMessage('Enum `'.$enum.'` does not allow magic `__clone` method.');
470
        $var = clone $enum::FIRST();
0 ignored issues
show
Unused Code introduced by
The assignment to $var is dead and can be removed.
Loading history...
471
    }
472
473
    public function testExceptionMagicInvoke(): void
474
    {
475
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
476
477
        $this->expectException(PlatenumException::class);
478
        $this->expectExceptionMessage('Enum `'.$enum.'` does not allow magic `__invoke` method.');
479
        $enum::FIRST()();
480
    }
481
482
    public function testExceptionMagicCall(): void
483
    {
484
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
485
486
        $this->expectException(PlatenumException::class);
487
        $this->expectExceptionMessage('Enum `'.$enum.'` does not allow magic `__call` method.');
488
        $enum::FIRST()->invalidMethod();
489
    }
490
491
    public function testExceptionMagicGet(): void
492
    {
493
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
494
495
        $this->expectException(PlatenumException::class);
496
        $this->expectExceptionMessage('Enum `'.$enum.'` does not allow magic `__get` method.');
497
        $enum::FIRST()->invalidProperty;
498
    }
499
500
    public function testExceptionMagicSet(): void
501
    {
502
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
503
504
        $this->expectException(PlatenumException::class);
505
        $this->expectExceptionMessage('Enum `'.$enum.'` does not allow magic `__set` method.');
506
        $enum::FIRST()->invalidProperty = 'value';
507
    }
508
509
    public function testExceptionMagicIsset(): void
510
    {
511
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
512
513
        $this->expectException(PlatenumException::class);
514
        $this->expectExceptionMessage('Enum `'.$enum.'` does not allow magic `__isset` method.');
515
        $is = isset($enum::FIRST()->invalidProperty);
0 ignored issues
show
Unused Code introduced by
The assignment to $is is dead and can be removed.
Loading history...
516
    }
517
518
    public function testExceptionMagicUnset(): void
519
    {
520
        $enum = $this->makeRawEnum(['FIRST' => 1, 'SECOND' => 2]);
521
522
        $this->expectException(PlatenumException::class);
523
        $this->expectExceptionMessage('Enum `'.$enum.'` does not allow magic `__unset` method.');
524
        unset($enum::FIRST()->invalidProperty);
525
    }
526
527
    /* --- CUSTOM EXCEPTION --- */
528
529
    /** @dataProvider provideCustomExceptions */
530
    public function testTraitCustomException(string $type, callable $handler): void
531
    {
532
        $this->runCustomExceptionTest('trait', $type, $handler);
533
    }
534
535
    /** @dataProvider provideCustomExceptions */
536
    public function testExtendsCustomException(string $type, callable $handler): void
537
    {
538
        $this->runCustomExceptionTest('extends', $type, $handler);
539
    }
540
541
    private function runCustomExceptionTest(string $const, string $type, callable $handler): void
542
    {
543
        $members = ['FIRST' => 1];
544
        $methodMap = [
545
            'invalidMember' => 'throwInvalidMemberException(string $member)',
546
            'invalidValue' => 'throwInvalidValueException($value)',
547
        ];
548
        if(false === isset($methodMap[$type])) {
549
            throw new \LogicException(sprintf('Unrecognized override type `%s`.', $type));
550
        }
551
552
        $exceptionClass = $this->computeUniqueClassName('EnumException');
553
        eval('final class '.$exceptionClass.' extends \Exception {}');
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
554
555
        $class = $this->computeUniqueClassName('EnumCustomException');
556
        $resolve = 'private static function resolve(): array { return '.var_export($members, true).'; }';
557
        $mapping = 'protected static $mapping = '.var_export($members, true).';';
558
        $override = 'protected static function '.$methodMap[$type].': void { throw new '.$exceptionClass.'(); }';
559
        switch($const) {
560
            case 'extends': { $code = 'final class '.$class.' extends '.AbstractStaticEnum::class.' {  '.$mapping.$override.' }'; break; }
561
            case 'trait':   { $code = 'final class '.$class.' { use '.EnumTrait::class.'; '.$resolve.$override.' }'; break; }
562
            default: { throw new \LogicException(sprintf('Invalid extension type `%s`.', $const)); }
563
        }
564
        eval($code);
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
565
566
        $this->expectException($exceptionClass);
567
        $handler($class);
568
    }
569
570
    public static function provideCustomExceptions(): array
571
    {
572
        return [
573
            ['invalidMember', function(string $class) { return $class::INVALID(); }],
574
            ['invalidMember', function(string $class) { return $class::fromMember('INVALID'); }],
575
            ['invalidValue', function(string $class) { return $class::fromValue('invalid'); }],
576
            ['invalidMember', function(string $class) { return $class::memberToValue('INVALID'); }],
577
            ['invalidValue', function(string $class) { return $class::valueToMember('invalid'); }],
578
        ];
579
    }
580
581
    /** @dataProvider provideCustomExceptions */
582
    public function testTraitCustomExceptionEmptyMethod(string $type, callable $handler): void
583
    {
584
        $this->runCustomExceptionEmptyMethodTest('trait', $type, $handler);
585
    }
586
587
    /** @dataProvider provideCustomExceptions */
588
    public function testExtendsCustomExceptionEmptyMethod(string $type, callable $handler): void
589
    {
590
        $this->runCustomExceptionEmptyMethodTest('extends', $type, $handler);
591
    }
592
593
    private function runCustomExceptionEmptyMethodTest(string $const, string $type, callable $handler): void
594
    {
595
        $members = ['FIRST' => 1];
596
        $methodMap = [
597
            'invalidMember' => 'throwInvalidMemberException(string $member)',
598
            'invalidValue' => 'throwInvalidValueException($value)',
599
        ];
600
        if(false === isset($methodMap[$type])) {
601
            throw new \LogicException(sprintf('Unrecognized override type `%s`.', $type));
602
        }
603
604
        $class = $this->computeUniqueClassName('EnumCustomException');
605
        $resolve = 'private static function resolve(): array { return '.var_export($members, true).'; }';
606
        $mapping = 'protected static $mapping = '.var_export($members, true).';';
607
        $override = 'protected static function '.$methodMap[$type].': void {}';
608
        switch($const) {
609
            case 'extends': { $code = 'final class '.$class.' extends '.AbstractStaticEnum::class.' {  '.$mapping.$override.' }'; break; }
610
            case 'trait':   { $code = 'final class '.$class.' { use '.EnumTrait::class.'; '.$resolve.$override.' }'; break; }
611
            default: { throw new \LogicException(sprintf('Invalid extension type `%s`.', $const)); }
612
        }
613
        eval($code);
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
614
615
        $this->expectException(PlatenumException::class);
616
        $handler($class);
617
    }
618
}
619