Completed
Pull Request — master (#19)
by Alejandro
05:54
created

convertToDatabaseValueWithCastingMethodProperlyCastsIt()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 8
Ratio 100 %

Importance

Changes 0
Metric Value
dl 8
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Acelaya\Test\Doctrine\Type;
5
6
use Acelaya\Doctrine\Exception\InvalidArgumentException;
7
use Acelaya\Doctrine\Type\PhpEnumType;
8
use Acelaya\Test\Doctrine\Enum\Action;
9
use Acelaya\Test\Doctrine\Enum\Gender;
10
use Acelaya\Test\Doctrine\Enum\WithCastingMethods;
11
use Acelaya\Test\Doctrine\Enum\WithIntegerValues;
12
use Doctrine\DBAL\Platforms\AbstractPlatform;
13
use Doctrine\DBAL\Types\Type;
14
use MyCLabs\Enum\Enum;
15
use PHPUnit\Framework\TestCase;
16
use Prophecy\Argument;
17
use Prophecy\Prophecy\ObjectProphecy;
18
19
class PhpEnumTypeTest extends TestCase
20
{
21
    /**
22
     * @var ObjectProphecy
23
     */
24
    protected $platform;
25
26
    public function setUp()
27
    {
28
        $this->platform = $this->prophesize(AbstractPlatform::class);
29
30
        // Before every test, clean registered types
31
        $refProp = new \ReflectionProperty(Type::class, '_typeObjects');
32
        $refProp->setAccessible(true);
33
        $refProp->setValue(null, []);
34
        $refProp = new \ReflectionProperty(Type::class, '_typesMap');
35
        $refProp->setAccessible(true);
36
        $refProp->setValue(null, []);
37
    }
38
39
    /**
40
     * @test
41
     */
42
    public function enumTypesAreProperlyRegistered()
43
    {
44
        $this->assertFalse(Type::hasType(Action::class));
45
        $this->assertFalse(Type::hasType('gender'));
46
47
        PhpEnumType::registerEnumType(Action::class);
48
        PhpEnumType::registerEnumTypes([
49
            'gender' => Gender::class,
50
        ]);
51
52
        $this->assertTrue(Type::hasType(Action::class));
53
        $this->assertTrue(Type::hasType('gender'));
54
    }
55
56
    /**
57
     * @test
58
     */
59
    public function enumTypesAreProperlyCustomizedWhenRegistered()
60
    {
61
        $this->assertFalse(Type::hasType(Action::class));
62
        $this->assertFalse(Type::hasType(Gender::class));
63
64
        PhpEnumType::registerEnumTypes([
65
            'gender' => Gender::class,
66
            Action::class,
67
        ]);
68
69
        /** @var Type $actionType */
70
        $actionType = Type::getType(Action::class);
71
        $this->assertInstanceOf(PhpEnumType::class, $actionType);
72
        $this->assertEquals(Action::class, $actionType->getName());
73
74
        /** @var Type $actionType */
75
        $genderType = Type::getType('gender');
76
        $this->assertInstanceOf(PhpEnumType::class, $genderType);
77
        $this->assertEquals('gender', $genderType->getName());
78
    }
79
80
    /**
81
     * @test
82
     */
83
    public function registerInvalidEnumThrowsException()
84
    {
85
        $this->expectException(InvalidArgumentException::class);
86
        $this->expectExceptionMessage(sprintf(
87
            'Provided enum class "%s" is not valid. Enums must extend "%s"',
88
            \stdClass::class,
89
            Enum::class
90
        ));
91
        PhpEnumType::registerEnumType(\stdClass::class);
92
    }
93
94
    /**
95
     * @test
96
     */
97
    public function getSQLDeclarationReturnsValueFromPlatform()
98
    {
99
        $this->platform->getVarcharTypeDeclarationSQL(Argument::cetera())->willReturn('declaration');
100
101
        PhpEnumType::registerEnumType(Gender::class);
102
        $type = Type::getType(Gender::class);
103
104
        $this->assertEquals('declaration', $type->getSQLDeclaration([], $this->platform->reveal()));
105
    }
106
107
    /**
108
     * @test
109
     * @dataProvider provideValues
110
     * @param string $typeName
111
     * @param $phpValue
112
     * @param string $expectedValue
113
     */
114
    public function convertToDatabaseValueParsesEnum(string $typeName, $phpValue, string $expectedValue)
115
    {
116
        PhpEnumType::registerEnumType($typeName);
117
        $type = Type::getType($typeName);
118
119
        $actualValue = $type->convertToDatabaseValue($phpValue, $this->platform->reveal());
120
121
        $this->assertEquals($expectedValue, $actualValue);
122
    }
123
124
    public function provideValues(): array
125
    {
126
        return [
127
            [Action::class, Action::CREATE(), Action::CREATE],
128
            [Action::class, Action::READ(), Action::READ],
129
            [Action::class, Action::UPDATE(), Action::UPDATE],
130
            [Action::class, Action::DELETE(), Action::DELETE],
131
            [Gender::class, Gender::FEMALE(), Gender::FEMALE],
132
            [Gender::class, Gender::MALE(), Gender::MALE],
133
        ];
134
    }
135
136
    /**
137
     * @test
138
     */
139 View Code Duplication
    public function convertToDatabaseValueReturnsNullWhenNullIsProvided()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
140
    {
141
        PhpEnumType::registerEnumType(Action::class);
142
        $type = Type::getType(Action::class);
143
144
        $this->assertNull($type->convertToDatabaseValue(null, $this->platform->reveal()));
145
    }
146
147
    /**
148
     * @test
149
     */
150
    public function convertToPHPValueWithValidValueReturnsParsedData()
151
    {
152
        PhpEnumType::registerEnumType(Action::class);
153
        $type = Type::getType(Action::class);
154
155
        /** @var Action $value */
156
        $value = $type->convertToPHPValue(Action::CREATE, $this->platform->reveal());
157
        $this->assertInstanceOf(Action::class, $value);
158
        $this->assertEquals(Action::CREATE, $value->getValue());
159
160
        $value = $type->convertToPHPValue(Action::DELETE, $this->platform->reveal());
161
        $this->assertInstanceOf(Action::class, $value);
162
        $this->assertEquals(Action::DELETE, $value->getValue());
163
    }
164
165
    /**
166
     * @test
167
     */
168 View Code Duplication
    public function convertToPHPValueWithNullReturnsNull()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
169
    {
170
        PhpEnumType::registerEnumType(Action::class);
171
        $type = Type::getType(Action::class);
172
173
        $value = $type->convertToPHPValue(null, $this->platform->reveal());
174
        $this->assertNull($value);
175
    }
176
177
    /**
178
     * @test
179
     */
180
    public function convertToPHPValueWithInvalidValueThrowsException()
181
    {
182
        PhpEnumType::registerEnumType(Action::class);
183
        $type = Type::getType(Action::class);
184
185
        $this->expectException(InvalidArgumentException::class);
186
        $this->expectExceptionMessage(sprintf(
187
            'The value "invalid" is not valid for the enum "%s". Expected one of ["%s"]',
188
            Action::class,
189
            implode('", "', Action::toArray())
190
        ));
191
        $type->convertToPHPValue('invalid', $this->platform->reveal());
192
    }
193
194
    /**
195
     * @test
196
     */
197
    public function convertToPHPValueWithCastingMethodProperlyCastsIt()
198
    {
199
        PhpEnumType::registerEnumType(WithCastingMethods::class);
200
        $type = Type::getType(WithCastingMethods::class);
201
202
        $value = $type->convertToPHPValue('foo VALUE', $this->platform->reveal());
203
        $this->assertInstanceOf(WithCastingMethods::class, $value);
204
        $this->assertEquals(WithCastingMethods::FOO, $value->getValue());
205
206
        PhpEnumType::registerEnumType(WithIntegerValues::class);
207
        $intType = Type::getType(WithIntegerValues::class);
208
209
        $value = $intType->convertToPHPValue('1', $this->platform->reveal());
210
        $this->assertInstanceOf(WithIntegerValues::class, $value);
211
        $this->assertEquals(1, $value->getValue());
212
    }
213
214
    /**
215
     * @test
216
     */
217 View Code Duplication
    public function convertToDatabaseValueWithCastingMethodProperlyCastsIt()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
218
    {
219
        PhpEnumType::registerEnumType(WithCastingMethods::class);
220
        $type = Type::getType(WithCastingMethods::class);
221
222
        $value = $type->convertToDatabaseValue(WithCastingMethods::FOO(), $this->platform->reveal());
223
        $this->assertEquals('FOO VALUE', $value);
224
    }
225
226
    /**
227
     * @test
228
     */
229 View Code Duplication
    public function usingChildCustomEnumTypeRegisteredValueIsCorrect()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
230
    {
231
        MyCustomEnumType::registerEnumType(Action::class);
232
        $type = MyCustomEnumType::getType(Action::class);
233
234
        $this->assertInstanceOf(MyCustomEnumType::class, $type);
235
        $this->assertEquals(
236
            'ENUM("create", "read", "update", "delete") COMMENT "Acelaya\Test\Doctrine\Enum\Action"',
237
            $type->getSQLDeclaration([], $this->platform->reveal())
238
        );
239
    }
240
241
    /**
242
     * @test
243
     */
244
    public function SQLCommentHintIsAlwaysRequired()
245
    {
246
        PhpEnumType::registerEnumType(Gender::class);
247
        $type = Type::getType(Gender::class);
248
249
        $this->assertTrue($type->requiresSQLCommentHint($this->platform->reveal()));
250
    }
251
}
252