Skip to content

Commit 039dc0f

Browse files
authored
Add unit/feature tests (#25)
* Add tests * Fix `::labels()` method * add `AsFullEnumCollection::of(...)` method
1 parent 8e9b81c commit 039dc0f

File tree

18 files changed

+397
-48
lines changed

18 files changed

+397
-48
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/art export-ignore
1010
/docs export-ignore
1111
/tests export-ignore
12+
/workbench export-ignore
1213
/.editorconfig export-ignore
1314
/.php_cs.dist.php export-ignore
1415
/psalm.xml export-ignore

.github/workflows/run-tests.yml

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,10 @@ jobs:
1212
strategy:
1313
fail-fast: true
1414
matrix:
15-
os: [ubuntu-latest, windows-latest]
16-
php: [8.1]
17-
laravel: [10.*]
15+
os: [ubuntu-latest]
16+
php: [8.2]
17+
laravel: [11.*]
1818
stability: [prefer-lowest, prefer-stable]
19-
include:
20-
- laravel: 10.*
21-
testbench: 8.*
22-
carbon: ^2.63
2319

2420
name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}
2521

@@ -41,8 +37,7 @@ jobs:
4137
4238
- name: Install dependencies
4339
run: |
44-
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
45-
composer update --${{ matrix.stability }} --prefer-dist --no-interaction
40+
composer install
4641
4742
- name: Execute tests
4843
run: vendor/bin/pest

README.md

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ enum VolumeUnitEnum: string implements BackedEnum
2626
{
2727
use IsBackedEnum;
2828

29-
case MILLIGRAMS = "MILLIGRAMS";
30-
case GRAMS = "GRAMS";
31-
case KILOGRAMS = "KILOGRAMS";
32-
case TONNE = "TONNE";
29+
case MILLIGRAMS = "milligrams";
30+
case GRAMS = "grams";
31+
case KILOGRAMS = "kilograms";
32+
case TONNE = "tonne";
3333
}
3434
```
3535

@@ -112,7 +112,7 @@ returns
112112
[
113113
[
114114
'name' => 'MILLIGRAMS'
115-
'value' => 'MILLIGRAMS',
115+
'value' => 'milligrams',
116116
'label' => 'mg',
117117
'meta' => [
118118
'background_color' => 'bg-green-100',
@@ -121,7 +121,7 @@ returns
121121
],
122122
[
123123
'name' => 'GRAMS',
124-
'value' => 'GRAMS',
124+
'value' => 'grams',
125125
'label' => 'g',
126126
'meta' => [
127127
'background_color' => 'bg-red-100',
@@ -167,10 +167,10 @@ returns
167167

168168
```php
169169
[
170-
'MILLIGRAMS',
171-
'GRAMS',
172-
'KILOGRAMS',
173-
'TONNE',
170+
'milligrams',
171+
'grams',
172+
'killograms',
173+
'tonne',
174174
]
175175
```
176176

@@ -209,10 +209,10 @@ returns
209209

210210
```php
211211
[
212-
'MILLIGRAMS'=>'mg',
213-
'GRAMS' =>'g',
214-
'KILOGRAMS' =>'kg',
215-
'TONNE' =>'t',
212+
'MILLIGRAMS' => 'mg',
213+
'GRAMS' => 'g',
214+
'KILOGRAMS' => 'kg',
215+
'TONNE' => 't',
216216
]
217217
```
218218

@@ -231,10 +231,10 @@ returns
231231
```php
232232
[
233233
'name' => 'MILLIGRAMS'
234-
'value' => 'MILLIGRAMS',
234+
'value' => 'milligrams',
235235
'label' => 'mg',
236236
'meta' => [
237-
'color' => 'bg-green-100',
237+
'color' => 'bg-green-100',
238238
'text_color' => 'text-green-800',
239239
],
240240
]
@@ -253,20 +253,12 @@ VolumeUnitEnum::MILLIGRAMS->toHtml();
253253
returns
254254

255255
```php
256-
[
257-
'name' => 'MILLIGRAMS'
258-
'value' => 'MILLIGRAMS',
259-
'label' => 'mg',
260-
'meta' => [
261-
'color' => 'bg-green-100',
262-
'text_color' => 'text-green-800',
263-
],
264-
]
256+
mg
265257
```
266258

267259
### toJson
268260

269-
An alias for toArray.
261+
Returns a json string represention of the toArray return value.
270262

271263
### is/isA/isAn
272264

@@ -336,7 +328,7 @@ public function rules(): array
336328
## Other Classes
337329

338330
### AsFullEnumCollection
339-
This cast is similar to the Laravel built in `AsEnumCollection` cast but unlike the built in will maintain the full `toArray` structure
331+
This cast is similar to the Laravel built in `AsEnumCollection` cast but unlike the built-in will maintain the full `toArray` structure
340332
when converting to json.
341333

342334
E.g. the Laravel built in `AsEnumCollection` cast will return the following json:

composer.json

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"require-dev": {
2424
"laravel/pint": "^1.0",
2525
"nunomaduro/collision": "^6.1",
26-
"nunomaduro/larastan": "^2.0.1",
26+
"larastan/larastan": "^v2.9.2",
2727
"orchestra/testbench": "^8.0",
2828
"pestphp/pest": "^1.21",
2929
"pestphp/pest-plugin-laravel": "^1.1",
@@ -39,14 +39,33 @@
3939
},
4040
"autoload-dev": {
4141
"psr-4": {
42-
"Webfox\\LaravelBackedEnums\\Tests\\": "tests"
42+
"Webfox\\LaravelBackedEnums\\Tests\\": "tests",
43+
"Workbench\\App\\": "workbench/app/",
44+
"Workbench\\Database\\Factories\\": "workbench/database/factories/",
45+
"Workbench\\Database\\Seeders\\": "workbench/database/seeders/"
4346
}
4447
},
4548
"scripts": {
4649
"analyse": "vendor/bin/phpstan analyse",
4750
"test": "vendor/bin/pest",
4851
"test-coverage": "vendor/bin/pest --coverage",
49-
"format": "vendor/bin/pint"
52+
"format": "vendor/bin/pint",
53+
"post-autoload-dump": [
54+
"@clear",
55+
"@prepare"
56+
],
57+
"clear": "@php vendor/bin/testbench package:purge-skeleton --ansi",
58+
"prepare": "@php vendor/bin/testbench package:discover --ansi",
59+
"build": "@php vendor/bin/testbench workbench:build --ansi",
60+
"serve": [
61+
"Composer\\Config::disableProcessTimeout",
62+
"@build",
63+
"@php vendor/bin/testbench serve"
64+
],
65+
"lint": [
66+
"@php vendor/bin/pint",
67+
"@php vendor/bin/phpstan analyse"
68+
]
5069
},
5170
"config": {
5271
"sort-packages": true,
@@ -64,4 +83,4 @@
6483
},
6584
"minimum-stability": "dev",
6685
"prefer-stable": true
67-
}
86+
}

src/Casts/AsFullEnumCollection.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ public function __construct(protected string $enumClass)
2828
{
2929
}
3030

31+
/**
32+
* @param class-string<T> $class
33+
*/
34+
public static function of(string $class): string
35+
{
36+
return static::class.':'.$class;
37+
}
38+
3139
/**
3240
* @return \Illuminate\Support\Collection<T>|null
3341
*/

src/IsBackedEnum.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public static function map(): array
5555
public static function labels(): array
5656
{
5757
static::ensureImplementsInterface();
58-
return array_map(fn($enum) => self::getLabel($enum->name), self::cases());
58+
return array_map(fn($enum) => self::labelFor($enum), self::cases());
5959
}
6060

6161
public static function labelFor(self $value): string

tests/EnumTest.php

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
<?php
2+
3+
use Workbench\App\Enums\VolumeUnitEnum;
4+
use Workbench\App\Enums\VolumeUnitWithoutMetaEnum;
5+
6+
it('can create an enum', function () {
7+
expect(VolumeUnitEnum::GRAMS->value)->toEqual('grams');
8+
});
9+
10+
it('can get the label', function () {
11+
expect(VolumeUnitEnum::GRAMS->label())->toEqual('g')
12+
->and(VolumeUnitEnum::labelFor(VolumeUnitEnum::GRAMS))->toEqual('g');
13+
});
14+
15+
it('can get the metadata', function () {
16+
expect(VolumeUnitWithoutMetaEnum::GRAMS->toArray())->toMatchArray([
17+
'meta' => []
18+
])
19+
->and(VolumeUnitEnum::GRAMS->toArray())->toMatchArray([
20+
'meta' => [
21+
'background_color' => 'bg-red-100',
22+
'text_color' => 'text-red-800',
23+
]
24+
]);
25+
26+
});
27+
28+
it('can list all options', function () {
29+
expect(VolumeUnitEnum::options())->toEqual([
30+
[
31+
'name' => 'MILLIGRAMS',
32+
'value' => 'milligrams',
33+
'label' => 'mg',
34+
'meta' => [
35+
'background_color' => 'bg-green-100',
36+
'text_color' => 'text-green-800',
37+
]
38+
],
39+
[
40+
'name' => 'GRAMS',
41+
'value' => 'grams',
42+
'label' => 'g',
43+
'meta' => [
44+
'background_color' => 'bg-red-100',
45+
'text_color' => 'text-red-800',
46+
]
47+
],
48+
[
49+
'name' => 'KILOGRAMS',
50+
'value' => 'kilograms',
51+
'label' => 'kg',
52+
'meta' => [
53+
'background_color' => 'bg-gray-100',
54+
'text_color' => 'text-gray-800',
55+
]
56+
],
57+
[
58+
'name' => 'TONNE',
59+
'value' => 'tonne',
60+
'label' => 't',
61+
'meta' => [
62+
'background_color' => 'bg-gray-100',
63+
'text_color' => 'text-gray-800',
64+
],
65+
]
66+
]);
67+
});
68+
69+
it('can get the names', function () {
70+
expect(VolumeUnitEnum::names())->toEqual([
71+
'MILLIGRAMS',
72+
'GRAMS',
73+
'KILOGRAMS',
74+
'TONNE',
75+
]);
76+
});
77+
78+
it('can get the values', function () {
79+
expect(VolumeUnitEnum::values())->toEqual([
80+
'milligrams',
81+
'grams',
82+
'kilograms',
83+
'tonne',
84+
]);
85+
});
86+
87+
it('can get the labels', function () {
88+
expect(VolumeUnitEnum::labels())->toEqual([
89+
'mg',
90+
'g',
91+
'kg',
92+
't',
93+
]);
94+
});
95+
96+
it('can get the value => label map', function () {
97+
expect(VolumeUnitEnum::map())->toEqual([
98+
'milligrams' => 'mg',
99+
'grams' => 'g',
100+
'kilograms' => 'kg',
101+
'tonne' => 't',
102+
]);
103+
});
104+
105+
it('can convert a single value to an array', function () {
106+
expect(VolumeUnitEnum::MILLIGRAMS->toArray())->toEqual([
107+
'name' => 'MILLIGRAMS',
108+
'value' => 'milligrams',
109+
'label' => 'mg',
110+
'meta' => [
111+
'background_color' => 'bg-green-100',
112+
'text_color' => 'text-green-800',
113+
]
114+
]);
115+
});
116+
117+
it('will return the label if toHtml it called', function () {
118+
expect(VolumeUnitEnum::MILLIGRAMS->toHtml())->toEqual('mg');
119+
});
120+
121+
it('will return the json string format of toArray if toJson is called', function () {
122+
expect(VolumeUnitEnum::MILLIGRAMS->toJson())->toEqual('{"name":"MILLIGRAMS","value":"milligrams","label":"mg","meta":{"background_color":"bg-green-100","text_color":"text-green-800"}}');
123+
});
124+
125+
it('can compare enums', function () {
126+
// is methods
127+
expect(VolumeUnitEnum::MILLIGRAMS->is(VolumeUnitEnum::MILLIGRAMS))->toBeTrue()
128+
->and(VolumeUnitEnum::MILLIGRAMS->is(VolumeUnitEnum::GRAMS))->toBeFalse()
129+
->and(VolumeUnitEnum::MILLIGRAMS->is('milligrams'))->toBeTrue()
130+
->and(VolumeUnitEnum::MILLIGRAMS->is('grams'))->toBeFalse()
131+
// isA methods
132+
->and(VolumeUnitEnum::MILLIGRAMS->isA(VolumeUnitEnum::MILLIGRAMS))->toBeTrue()
133+
->and(VolumeUnitEnum::MILLIGRAMS->isA(VolumeUnitEnum::GRAMS))->toBeFalse()
134+
->and(VolumeUnitEnum::MILLIGRAMS->isA('milligrams'))->toBeTrue()
135+
->and(VolumeUnitEnum::MILLIGRAMS->isA('grams'))->toBeFalse()
136+
// isAn methods
137+
->and(VolumeUnitEnum::MILLIGRAMS->isAn(VolumeUnitEnum::MILLIGRAMS))->toBeTrue()
138+
->and(VolumeUnitEnum::MILLIGRAMS->isAn(VolumeUnitEnum::GRAMS))->toBeFalse()
139+
->and(VolumeUnitEnum::MILLIGRAMS->isAn('milligrams'))->toBeTrue()
140+
->and(VolumeUnitEnum::MILLIGRAMS->isAn('grams'))->toBeFalse()
141+
// isAny methods
142+
->and(VolumeUnitEnum::MILLIGRAMS->isAny([VolumeUnitEnum::MILLIGRAMS, VolumeUnitEnum::TONNE]))->toBeTrue()
143+
->and(VolumeUnitEnum::MILLIGRAMS->isAny([VolumeUnitEnum::GRAMS, VolumeUnitEnum::TONNE]))->toBeFalse()
144+
->and(VolumeUnitEnum::MILLIGRAMS->isAny(['milligrams', 'tonne']))->toBeTrue()
145+
->and(VolumeUnitEnum::MILLIGRAMS->isAny(['grams', 'tonne']))->toBeFalse();
146+
});
147+
148+
it('can negative compare enums', function () {
149+
expect(VolumeUnitEnum::MILLIGRAMS->isNot(VolumeUnitEnum::MILLIGRAMS))->toBeFalse()
150+
->and(VolumeUnitEnum::MILLIGRAMS->isNot(VolumeUnitEnum::GRAMS))->toBeTrue()
151+
->and(VolumeUnitEnum::MILLIGRAMS->isNot('milligrams'))->toBeFalse()
152+
->and(VolumeUnitEnum::MILLIGRAMS->isNot('grams'))->toBeTrue()
153+
//
154+
->and(VolumeUnitEnum::MILLIGRAMS->isNotA(VolumeUnitEnum::MILLIGRAMS))->toBeFalse()
155+
->and(VolumeUnitEnum::MILLIGRAMS->isNotA(VolumeUnitEnum::GRAMS))->toBeTrue()
156+
->and(VolumeUnitEnum::MILLIGRAMS->isNotA('milligrams'))->toBeFalse()
157+
->and(VolumeUnitEnum::MILLIGRAMS->isNotA('grams'))->toBeTrue()
158+
//
159+
->and(VolumeUnitEnum::MILLIGRAMS->isNotAn(VolumeUnitEnum::MILLIGRAMS))->toBeFalse()
160+
->and(VolumeUnitEnum::MILLIGRAMS->isNotAn(VolumeUnitEnum::GRAMS))->toBeTrue()
161+
->and(VolumeUnitEnum::MILLIGRAMS->isNotAn('milligrams'))->toBeFalse()
162+
->and(VolumeUnitEnum::MILLIGRAMS->isNotAn('grams'))->toBeTrue()
163+
// isNotAny methods
164+
->and(VolumeUnitEnum::MILLIGRAMS->isNotAny([VolumeUnitEnum::MILLIGRAMS, VolumeUnitEnum::TONNE]))->toBeFalse()
165+
->and(VolumeUnitEnum::MILLIGRAMS->isNotAny([VolumeUnitEnum::GRAMS, VolumeUnitEnum::TONNE]))->toBeTrue()
166+
->and(VolumeUnitEnum::MILLIGRAMS->isNotAny(['milligrams', 'tonne']))->toBeFalse()
167+
->and(VolumeUnitEnum::MILLIGRAMS->isNotAny(['grams', 'tonne']))->toBeTrue();
168+
});
169+
170+
it('throws an exception when comparing against an invalid value', function () {
171+
expect(fn() => VolumeUnitEnum::MILLIGRAMS->is('invalid'))
172+
->toThrow('"invalid" is not a valid backing value for enum Workbench\App\Enums\VolumeUnitEnum');
173+
});
174+
175+
it('can get the validation rule', function () {
176+
expect(VolumeUnitEnum::rule())->toBeInstanceOf(\Illuminate\Validation\Rules\Enum::class);
177+
});

0 commit comments

Comments
 (0)