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
Branch master (3b9792)
by Tomasz
01:41
created

EnumTest   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 542
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 245
dl 0
loc 542
rs 5.04
c 0
b 0
f 0
wmc 57

51 Methods

Rating   Name   Duplication   Size   Complexity  
A testGetMember() 0 6 1
A testImpossibleValueToMemberInvalidMemberTypeException() 0 9 1
A testListMembers() 0 7 1
A runCustomExceptionEmptyMethodTest() 0 24 4
A provideCustomExceptions() 0 8 1
A testExceptionMagicClone() 0 7 1
A testExceptionInvalidValue() 0 7 1
A testExtendsCustomException() 0 3 1
A testMemberExists() 0 6 1
A testExtendedExtendedEnum() 0 15 1
A testCreateFromEnum() 0 8 1
A testHasMember() 0 6 1
A testExceptionInvalidMemberToValue() 0 7 1
A testExceptionMagicCall() 0 7 1
A testCreateFromMember() 0 8 1
A testExceptionInvalidValueToMember() 0 7 1
A testDifferentEnumsInequality() 0 8 1
A testTraitCustomException() 0 3 1
A testExceptionMagicUnset() 0 7 1
A testExceptionMissingResolveMethod() 0 9 1
A testExceptionCreateFromEnumDifferentClass() 0 8 1
A testExceptionNonEmptyConstantArguments() 0 7 1
A testValueExists() 0 6 1
A testCreateFromValue() 0 10 1
A testExceptionNonUniformValueType() 0 7 1
A testExceptionInvalidMemberConstant() 0 7 1
A testExceptionNonUniqueMemberValues() 0 7 1
A testExceptionMagicInvoke() 0 7 1
A testExceptionNoMembers() 0 7 1
A testJsonEncode() 0 5 1
A runCustomExceptionTest() 0 27 4
A testSameEnumInequality() 0 13 1
A testValueToMember() 0 7 1
A testSameEnumEquality() 0 16 1
A testExceptionCreateFromInstanceDifferentClass() 0 9 1
A testExceptionInvalidMember() 0 7 1
A testGetValue() 0 6 1
A testSerialize() 0 16 1
A testHasValue() 0 6 1
A testListMembersAndValues() 0 7 1
A testExceptionNonScalarValue() 0 7 1
A testExceptionMagicSet() 0 7 1
A testExceptionMagicGet() 0 7 1
A testTraitCustomExceptionEmptyMethod() 0 3 1
A testExtendsCustomExceptionEmptyMethod() 0 3 1
A testMemberToValue() 0 7 1
A testCreateFromConstant() 0 10 1
A testExceptionNonStringMember() 0 7 1
A testListValues() 0 7 1
A testExceptionMagicIsset() 0 7 1
A testCastToString() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like EnumTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EnumTest, and based on these observations, apply Extract Interface, too.

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