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.
Completed
Pull Request — master (#152)
by joseph
17:58
created

AbstractFieldTraitTest::createDatabaseSchema()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 21
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 16
nc 4
nop 0
dl 0
loc 21
rs 9.7333
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\Tests\Large\C\Entity\Fields\Traits;
4
5
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\AbstractGenerator;
6
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\FakerData\FakerDataProviderInterface;
7
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\EntityInterface;
8
use EdmondsCommerce\DoctrineStaticMeta\Entity\Savers\EntitySaver;
9
use EdmondsCommerce\DoctrineStaticMeta\Entity\Testing\EntityTestInterface;
10
use EdmondsCommerce\DoctrineStaticMeta\Exception\ValidationException;
11
use EdmondsCommerce\DoctrineStaticMeta\Tests\Assets\AbstractLargeTest;
12
use Faker\Generator;
13
14
/**
15
 * Extend this test with your Field Trait test to get basic test coverage.
16
 *
17
 * You should extend your field trait test to test your validation
18
 *
19
 * Class AbstractFieldTraitTest
20
 *
21
 * @package EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits
22
 * @SuppressWarnings(PHPMD.NumberOfChildren)
23
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
24
 * @large
25
 */
26
abstract class AbstractFieldTraitTest extends AbstractLargeTest
27
{
28
    protected const TEST_ENTITY_FQN_BASE = self::TEST_PROJECT_ROOT_NAMESPACE
29
                                           . '\\' . AbstractGenerator::ENTITIES_FOLDER_NAME
30
                                           . '\\';
31
32
    protected const TEST_FIELD_FQN = 'Override Me';
33
34
    /**
35
     * The expected default value for the field. Most fields are marked as nullable so the default is null.
36
     * Should be overriden in the actual field test for any fields that are not nullable
37
     */
38
    protected const TEST_FIELD_DEFAULT = null;
39
40
    protected const TEST_FIELD_PROP = 'Override Me';
41
42
    /**
43
     * set to false for read only fields (with no setter)
44
     */
45
    protected const HAS_SETTER = true;
46
47
    /**
48
     * set to false for fields that do not have a validator configuration
49
     */
50
    protected const VALIDATES = true;
51
52
    /**
53
     * Override this with an array of valid values to set
54
     */
55
    protected const VALID_VALUES = [];
56
57
    /**
58
     * Override this with an array of invalid values to set.
59
     */
60
    protected const INVALID_VALUES = [];
61
62
    /**
63
     * @var Generator
64
     */
65
    protected static $fakerGenerator;
66
    protected static $buildOnce = true;
67
    protected $entitySuffix;
68
69
    public function setup()
70
    {
71
        parent::setUp();
72
        $this->entitySuffix = substr(static::class, strrpos(static::class, '\\') + 1);
73
        if (false === static::$built) {
74
            $this->generateCode();
75
            static::$built = true;
76
        }
77
        $this->setupCopiedWorkDir();
78
        $this->recreateDtos();
79
    }
80
81
    protected function generateCode()
82
    {
83
        $this->getEntityGenerator()
84
             ->generateEntity(static::TEST_ENTITY_FQN_BASE . $this->entitySuffix);
85
        $this->getFieldSetter()
86
             ->setEntityHasField(
87
                 static::TEST_ENTITY_FQN_BASE . $this->entitySuffix,
88
                 static::TEST_FIELD_FQN
89
             );
90
    }
91
92
    /**
93
     * @SuppressWarnings(PHPMD.StaticAccess)
94
     */
95
    public static function setUpBeforeClass()
96
    {
97
        parent::setUpBeforeClass();
98
        self::$fakerGenerator = \Faker\Factory::create();
99
    }
100
101
    /**
102
     * @throws \ReflectionException
103
     * @large
104
     * @test
105
     */
106
    public function createEntityWithField(): void
107
    {
108
        $entity = $this->getEntity();
109
        $getter = $this->getGetter($entity);
110
        self::assertTrue(\method_exists($entity, $getter));
111
        $value = $entity->$getter();
112
        self::assertSame(
113
            static::TEST_FIELD_DEFAULT,
114
            $value,
115
            'The getter on a newly created entity returns ' . var_export($value, true)
116
            . ' whereas the configured default value is ' . var_export(static::TEST_FIELD_DEFAULT, true)
117
        );
118
        if (false === static::HAS_SETTER) {
0 ignored issues
show
introduced by
The condition false === static::HAS_SETTER is always false.
Loading history...
119
            return;
120
        }
121
        $setValue = $this->setFakerValueForProperty($entity);
122
        self::assertSame($setValue, $entity->$getter());
123
    }
124
125
    protected function getEntity()
126
    {
127
        return $this->createEntity($this->getEntityFqn());
128
    }
129
130
    protected function getEntityFqn(): string
131
    {
132
        return $this->getCopiedFqn(self::TEST_ENTITY_FQN_BASE . $this->entitySuffix);
133
    }
134
135
    /**
136
     * @param EntityInterface $entity
137
     *
138
     * @return string
139
     * @throws \Exception
140
     */
141
    protected function getGetter(EntityInterface $entity): string
142
    {
143
        foreach (['get', 'is', 'has'] as $prefix) {
144
            $method = $prefix . static::TEST_FIELD_PROP;
145
            if (\method_exists($entity, $method)) {
146
                return $method;
147
            }
148
        }
149
        throw new \RuntimeException('Failed finding a getter in ' . __METHOD__);
150
    }
151
152
    /**
153
     * @param EntityInterface $entity
154
     *
155
     * @return mixed
156
     * @throws \ReflectionException
157
     * @throws \Exception
158
     */
159
    protected function setFakerValueForProperty(EntityInterface $entity)
160
    {
161
        $setter        = 'set' . static::TEST_FIELD_PROP;
162
        $fakerProvider = $this->getFakerDataProvider();
163
        if ($fakerProvider instanceof FakerDataProviderInterface) {
164
            $setValue = $fakerProvider();
165
            $this->updateWithDto($setter, $entity, $setValue);
166
167
            return $setValue;
168
        }
169
170
        $reflection       = new  \ts\Reflection\ReflectionClass(\get_class($entity));
171
        $setterReflection = $reflection->getMethod($setter);
172
173
        $setParamType = current($setterReflection->getParameters())->getType()->getName();
174
        switch ($setParamType) {
175
            case 'string':
176
                $setValue = self::$fakerGenerator->text();
177
                break;
178
            case 'int':
179
                $setValue = self::$fakerGenerator->numberBetween(0, PHP_INT_MAX);
180
                break;
181
            case 'float':
182
                $setValue = self::$fakerGenerator->randomFloat(12, 0, 10000);
183
                break;
184
            case 'bool':
185
                $setValue = self::$fakerGenerator->boolean;
186
                break;
187
            case 'DateTime':
188
                $setValue = self::$fakerGenerator->dateTime;
189
                break;
190
            case 'DateTimeImmutable':
191
                $setValue = new \DateTimeImmutable(
192
                    self::$fakerGenerator->dateTime->format('Y-m-d')
193
                );
194
                break;
195
            default:
196
                throw new \RuntimeException('Failed getting a data provider for the property type ' . $setParamType);
197
        }
198
        $this->updateWithDto($setter, $entity, $setValue);
199
200
        return $setValue;
201
    }
202
203
    protected function getFakerDataProvider(): ?FakerDataProviderInterface
204
    {
205
        if (isset(EntityTestInterface::FAKER_DATA_PROVIDERS[static::TEST_FIELD_PROP])) {
206
            $provider = EntityTestInterface::FAKER_DATA_PROVIDERS[static::TEST_FIELD_PROP];
207
208
            return new $provider(self::$fakerGenerator);
209
        }
210
211
        return null;
212
    }
213
214
    private function updateWithDto(string $setterName, EntityInterface $entity, $setValue): void
215
    {
216
        $dto = $this->getEntityDtoFactory()->createDtoFromEntity($entity);
217
        $dto->$setterName($setValue);
218
        $entity->update($dto);
219
    }
220
221
    /**
222
     * @test
223
     * @large
224
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
225
     * @throws \ReflectionException
226
     */
227
    public function createDatabaseSchema()
228
    {
229
        $this->createDatabase();
230
        $entity   = $this->getEntity();
231
        $setValue = null;
232
        if (false !== static::HAS_SETTER) {
0 ignored issues
show
introduced by
The condition false !== static::HAS_SETTER is always true.
Loading history...
233
            $setValue = $this->setFakerValueForProperty($entity);
234
        }
235
        $saver = $this->container->get(EntitySaver::class);
236
        $saver->save($entity);
237
        $repository  = $this->getRepositoryFactory()->getRepository($this->getEntityFqn());
238
        $entities    = $repository->findAll();
239
        $savedEntity = current($entities);
240
        $getter      = $this->getGetter($entity);
241
        $gotValue    = $savedEntity->$getter();
242
        if (false !== static::HAS_SETTER) {
0 ignored issues
show
introduced by
The condition false !== static::HAS_SETTER is always true.
Loading history...
243
            self::assertEquals($setValue, $gotValue);
244
245
            return;
246
        }
247
        self::assertNotNull($gotValue);
248
    }
249
250
    /**
251
     * @test
252
     * @large
253
     */
254
    public function validValuesAreAccepted(): void
255
    {
256
        if (false === static::VALIDATES) {
0 ignored issues
show
introduced by
The condition false === static::VALIDATES is always false.
Loading history...
257
            self::markTestSkipped('This field does has no validation');
258
        }
259
        if (false === static::HAS_SETTER) {
0 ignored issues
show
introduced by
The condition false === static::HAS_SETTER is always false.
Loading history...
260
            self::markTestSkipped('No setter for this field');
261
        }
262
        if ([] === static::VALID_VALUES) {
263
            self::fail('You need to assign some valid values to ' . static::class . '::VALID_VALUES');
264
        }
265
        $entity = $this->getEntity();
266
        $setter = 'set' . static::TEST_FIELD_PROP;
267
        $getter = $this->getGetter($entity);
268
        foreach (static::VALID_VALUES as $value) {
269
            $this->updateWithDto($setter, $entity, $value);
270
            self::assertSame($value, $entity->$getter());
271
        }
272
    }
273
274
    /**
275
     * @test
276
     * @large
277
     * @dataProvider invalidValuesProvider
278
     */
279
    public function invalidValuesAreNotAccepted($invalidValue): void
280
    {
281
        if (false === static::VALIDATES) {
0 ignored issues
show
introduced by
The condition false === static::VALIDATES is always false.
Loading history...
282
            self::markTestSkipped('This field does has no validation');
283
        }
284
        if (false === static::HAS_SETTER) {
0 ignored issues
show
introduced by
The condition false === static::HAS_SETTER is always false.
Loading history...
285
            self::markTestSkipped('No setter for this field');
286
        }
287
        $entity = $this->getEntity();
288
        $setter = 'set' . static::TEST_FIELD_PROP;
289
        $this->expectException(ValidationException::class);
290
        try {
291
            $this->updateWithDto($setter, $entity, $invalidValue);
292
        } catch (\TypeError $e) {
293
            self::markTestSkipped(
294
                'You have set an INVALID_VALUE item of ' .
295
                $invalidValue .
296
                ' which has caused a TypeError as the setter does not accept this type of value.'
297
            );
298
        }
299
    }
300
301
    /**
302
     * Yield the invalid data, keyed by a namespace safe version of the value
303
     *
304
     * @return \Generator
305
     */
306
    public function invalidValuesProvider(): \Generator
307
    {
308
        if (false === static::VALIDATES) {
0 ignored issues
show
introduced by
The condition false === static::VALIDATES is always false.
Loading history...
309
            self::markTestSkipped('This field does not validate');
310
        }
311
        if ([] === static::INVALID_VALUES) {
312
            self::fail('You need to assign some invalid values to ' . static::class . '::INVALID_VALUES');
313
        }
314
        foreach (static::INVALID_VALUES as $invalidValue) {
315
            yield $invalidValue => [$invalidValue];
316
        }
317
    }
318
}
319