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 (#185)
by joseph
24:50
created

FixturesHelperTest   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 498
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 277
dl 0
loc 498
c 0
b 0
f 0
rs 10
wmc 7

25 Methods

Rating   Name   Duplication   Size   Complexity  
A itCanTakeAModifierToCustomiseTheFixtures() 0 22 2
A hp$0 ➔ getString() 0 3 1
A setup() 0 22 2
A getFixture() 0 5 1
A hp$0 ➔ getId() 0 3 1
A hp$1 ➔ getEntityFqn() 0 3 1
A itLoadsAllTheFixturesWithRandomDataByDefault() 0 14 1
B overrideCode() 0 122 1
B hp$1 ➔ getFixtureModifier() 0 156 1
A hp$1 ➔ __construct() 0 5 1
A hp$1 ➔ getAttributesEmails() 0 6 1
A hp$1 ➔ addAnotherEntity() 0 53 1
A getModifiedFixture() 0 5 1
A hp$1 ➔ getId() 0 3 1
getFixtureModifier() 0 156 ?
A hp$0 ➔ __construct() 0 4 1
A hp$2 ➔ modifyEntities() 0 5 1
A hp$1 ➔ getString() 0 3 1
A hp$2 ➔ __construct() 0 12 1
A hp$0 ➔ updateFirstEntity() 0 35 1
A getArrayKeyedByUuid() 0 8 2
A hp$0 ➔ getEntityFqn() 0 3 1
A itUsesTheCacheTheSecondTime() 0 33 2
A getUnmodifiedFixture() 0 3 1
A itCanBeConfiguredNotToLoadFromTheCache() 0 26 2
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\Tests\Large\G\Entity\Testing\Fixtures;
4
5
use Doctrine\Common\Cache\FilesystemCache;
6
use Doctrine\Common\Collections\ArrayCollection;
7
use EdmondsCommerce\DoctrineStaticMeta\Entity\DataTransferObjects\DtoFactory;
8
use EdmondsCommerce\DoctrineStaticMeta\Entity\Factory\EntityFactoryInterface;
9
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Factories\UuidFactory;
10
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\DataTransferObjectInterface;
11
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\EntityInterface;
12
use EdmondsCommerce\DoctrineStaticMeta\Entity\Savers\EntitySaverFactory;
13
use EdmondsCommerce\DoctrineStaticMeta\Entity\Testing\Fixtures\AbstractEntityFixtureLoader;
14
use EdmondsCommerce\DoctrineStaticMeta\Entity\Testing\Fixtures\FixtureEntitiesModifierInterface;
15
use EdmondsCommerce\DoctrineStaticMeta\Entity\Testing\Fixtures\FixturesHelper;
16
use EdmondsCommerce\DoctrineStaticMeta\Schema\Database;
17
use EdmondsCommerce\DoctrineStaticMeta\Schema\Schema;
18
use EdmondsCommerce\DoctrineStaticMeta\Tests\Assets\AbstractLargeTest;
19
use EdmondsCommerce\DoctrineStaticMeta\Tests\Assets\AbstractTest;
20
use EdmondsCommerce\DoctrineStaticMeta\Tests\Assets\TestCodeGenerator;
21
use Ramsey\Uuid\UuidInterface;
22
23
/**
24
 * @covers \EdmondsCommerce\DoctrineStaticMeta\Entity\Testing\Fixtures\AbstractEntityFixtureLoader
25
 * @covers \EdmondsCommerce\DoctrineStaticMeta\Entity\Testing\Fixtures\FixturesHelper
26
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
27
 * @SuppressWarnings(PHPMD.StaticAccess)
28
 */
29
class FixturesHelperTest extends AbstractLargeTest
30
{
31
    public const WORK_DIR = AbstractTest::VAR_PATH .
32
                            self::TEST_TYPE_LARGE .
33
                            '/FixturesTest';
34
35
    private const ENTITY_WITHOUT_MODIFIER = self::TEST_ENTITIES_ROOT_NAMESPACE .
36
                                            TestCodeGenerator::TEST_ENTITY_PERSON;
37
38
    private const ENTITY_WITH_MODIFIER = self::TEST_ENTITIES_ROOT_NAMESPACE .
39
                                         TestCodeGenerator::TEST_ENTITY_PERSON;
40
41
    protected static $buildOnce = true;
42
    /**
43
     * @var FixturesHelper
44
     */
45
    private $helper;
46
47
    public function setup(): void
48
    {
49
        parent::setUp();
50
        if (false === self::$built) {
51
            $this->getTestCodeGenerator()
52
                 ->copyTo(self::WORK_DIR, self::TEST_PROJECT_ROOT_NAMESPACE);
53
            $this->overrideCode();
54
            self::$built = true;
55
        }
56
        $this->setupCopiedWorkDirAndCreateDatabase();
57
        $this->recreateDtos();
58
        $cacheDir = $this->copiedWorkDir . '/cache';
59
        mkdir($cacheDir, 0777, true);
60
        $this->helper = new FixturesHelper(
61
            $this->getEntityManager(),
62
            $this->container->get(Database::class),
63
            $this->container->get(Schema::class),
64
            new FilesystemCache($cacheDir),
65
            $this->container->get(EntitySaverFactory::class),
66
            $this->getNamespaceHelper(),
67
            $this->getTestEntityGeneratorFactory(),
68
            $this->container
69
        );
70
    }
71
72
    private function overrideCode(): void
73
    {
74
        $personClass = <<<'PHP'
75
<?php declare(strict_types=1);
76
77
namespace My\Test\Project\Entities;
78
// phpcs:disable Generic.Files.LineLength.TooLong
79
80
use Doctrine\ORM\Mapping\Builder\ClassMetadataBuilder;
81
use EdmondsCommerce\DoctrineStaticMeta\MappingHelper;
82
use EdmondsCommerce\DoctrineStaticMeta\Entity as DSM;
83
use My\Test\Project\Entity\Fields\Traits\BooleanFieldTrait;
84
use My\Test\Project\Entity\Fields\Traits\DatetimeFieldTrait;
85
use My\Test\Project\Entity\Fields\Traits\DecimalFieldTrait;
86
use My\Test\Project\Entity\Fields\Traits\FloatFieldTrait;
87
use My\Test\Project\Entity\Fields\Traits\IntegerFieldTrait;
88
use My\Test\Project\Entity\Fields\Traits\JsonFieldTrait;
89
use My\Test\Project\Entity\Fields\Traits\StringFieldTrait;
90
use My\Test\Project\Entity\Fields\Traits\TextFieldTrait;
91
use My\Test\Project\Entity\Interfaces\PersonInterface;
92
use My\Test\Project\Entity\Relations\Attributes\Address\Traits\HasAttributesAddress\HasAttributesAddressUnidirectionalManyToOne;
93
use My\Test\Project\Entity\Relations\Attributes\Email\Traits\HasRequiredAttributesEmails\HasRequiredAttributesEmailsOneToMany;
94
use My\Test\Project\Entity\Relations\Company\Director\Traits\HasCompanyDirector\HasCompanyDirectorInverseOneToOne;
95
use My\Test\Project\Entity\Relations\Large\Relation\Traits\HasLargeRelation\HasLargeRelationInverseOneToOne;
96
97
// phpcs:enable
98
class Person implements 
99
    PersonInterface
100
{
101
    /**
102
     * DSM Traits 
103
     */
104
    use DSM\Traits\UsesPHPMetaDataTrait;
105
    use DSM\Traits\ValidatedEntityTrait;
106
    use DSM\Traits\ImplementNotifyChangeTrackingPolicy;
107
    use DSM\Traits\AlwaysValidTrait;
108
109
    /**
110
     * Required Relations 
111
     */
112
    use HasRequiredAttributesEmailsOneToMany;
113
114
    /**
115
     * Relations 
116
     */
117
    use HasAttributesAddressUnidirectionalManyToOne;
118
    use HasCompanyDirectorInverseOneToOne;
119
    use HasLargeRelationInverseOneToOne;
120
121
    /**
122
     * DSM Fields 
123
     */
124
    use DSM\Fields\Traits\PrimaryKey\NonOrderedUuidFieldTrait;
125
126
    /**
127
     * Fields 
128
     */
129
    use StringFieldTrait;
130
    use DatetimeFieldTrait;
131
    use FloatFieldTrait;
132
    use DecimalFieldTrait;
133
    use IntegerFieldTrait;
134
    use TextFieldTrait;
135
    use BooleanFieldTrait;
136
    use JsonFieldTrait;
137
}
138
PHP;
139
        \ts\file_put_contents(self::WORK_DIR . '/src/Entities/Person.php', $personClass);
140
141
        $personFixture = <<<'PHP'
142
<?php declare(strict_types=1);
143
144
namespace My\Test\Project\Assets\Entity\Fixtures;
145
146
use Doctrine\Common\Collections\ArrayCollection;
147
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
148
use EdmondsCommerce\DoctrineStaticMeta\Entity\Testing\Fixtures\AbstractEntityFixtureLoader;
149
use My\Test\Project\Assets\Entity\Fixtures\Attributes\EmailFixture;
150
151
class PersonFixture extends AbstractEntityFixtureLoader implements DependentFixtureInterface
152
{
153
    public const REFERENCE_PREFIX = 'Person_';
154
    
155
    public const BULK_AMOUNT_TO_GENERATE = 2;
156
157
    public function getDependencies(): array
158
    {
159
        return [EmailFixture::class];
160
    }
161
162
    protected function loadBulk(): array
163
    {
164
        $entities = parent::loadBulk();
165
        $num      = 0;
166
        foreach ($entities as $person) {
167
            $collection = new ArrayCollection();
168
            $collection->add($this->getReference(EmailFixture::REFERENCE_PREFIX . $num++));
169
            $person->setAttributesEmails($collection);
170
        }
171
172
        return $entities;
173
    }
174
}
175
PHP;
176
        \ts\file_put_contents(self::WORK_DIR . '/tests/Assets/Entity/Fixtures/PersonFixture.php', $personFixture);
177
178
        $emailFixture = <<<'PHP'
179
<?php declare(strict_types=1);
180
181
namespace My\Test\Project\Assets\Entity\Fixtures\Attributes;
182
183
use EdmondsCommerce\DoctrineStaticMeta\Entity\Testing\Fixtures\AbstractEntityFixtureLoader;
184
185
class EmailFixture extends AbstractEntityFixtureLoader
186
{
187
    public const REFERENCE_PREFIX = 'Email_';
188
    public const BULK_AMOUNT_TO_GENERATE = 2;
189
}
190
191
PHP;
192
        \ts\file_put_contents(self::WORK_DIR . '/tests/Assets/Entity/Fixtures/Attributes/EmailFixture.php',
193
                              $emailFixture);
194
    }
195
196
    /**
197
     * @test
198
     * @large
199
     */
200
    public function itLoadsAllTheFixturesWithRandomDataByDefault(): array
201
    {
202
        $this->helper->setCacheKey(__CLASS__ . '_unmodified');
203
        $fixture = $this->getUnmodifiedFixture();
204
        $this->helper->addFixture($fixture);
205
        $this->helper->createDb();
206
        $entityFqn   = $this->getCopiedFqn(self::ENTITY_WITHOUT_MODIFIER);
207
        $actual      = $this->getRepositoryFactory()
208
                            ->getRepository($entityFqn)
209
                            ->findAll();
210
        $actualCount = count($actual);
211
        self::assertSame($fixture::BULK_AMOUNT_TO_GENERATE, $actualCount);
212
213
        return $actual;
214
    }
215
216
    private function getUnmodifiedFixture(): AbstractEntityFixtureLoader
217
    {
218
        return $this->getFixture($this->getCopiedFqn(self::ENTITY_WITHOUT_MODIFIER));
219
    }
220
221
    private function getFixture(
222
        string $entityFqn,
223
        ?FixtureEntitiesModifierInterface $modifier = null
224
    ): AbstractEntityFixtureLoader {
225
        return $this->helper->createFixtureInstanceForEntityFqn($entityFqn, $modifier);
226
    }
227
228
    /**
229
     * @test
230
     * @large
231
     * @depends itLoadsAllTheFixturesWithRandomDataByDefault
232
     *
233
     * @param array $loadedFirstTime
234
     *
235
     * @return array
236
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
237
     * @throws \ReflectionException
238
     */
239
    public function itUsesTheCacheTheSecondTime(array $loadedFirstTime): array
240
    {
241
        $this->getFileSystem()
242
             ->mirror(
243
                 $this->copiedWorkDir .
244
                 '/../FixturesHelperTest_ItLoadsAllTheFixturesWithRandomDataByDefault_/cache',
245
                 $this->copiedWorkDir . '/cache'
246
             );
247
        $this->helper->setCacheKey(__CLASS__ . '_unmodified');
248
        $fixture = $this->getUnmodifiedFixture();
249
        $this->helper->addFixture($fixture);
250
        $this->helper->createDb();
251
        self::assertTrue($this->helper->isLoadedFromCache());
252
        /**
253
         * @var EntityInterface[] $loadedSecondTime
254
         */
255
        $loadedSecondTime = $this->getRepositoryFactory()
256
                                 ->getRepository($this->getCopiedFqn(self::ENTITY_WITHOUT_MODIFIER))
257
                                 ->findAll();
258
        $actualCount      = count($loadedSecondTime);
259
        $expectedCount    = count($loadedFirstTime);
260
        self::assertSame($expectedCount, $actualCount);
261
        $first  = $this->getArrayKeyedByUuid($loadedFirstTime);
262
        $second = $this->getArrayKeyedByUuid($loadedSecondTime);
263
        foreach ($second as $secondId => $actualEntity) {
264
            self::assertArrayHasKey($secondId, $first, 'Failed finding UUID ' . $secondId . ' in first Entities');
265
            $expectedEntity = $first[$secondId];
266
            $expectedText   = $expectedEntity->getString();
267
            $actualText     = $actualEntity->getString();
268
            self::assertEquals($expectedText, $actualText, 'Cached Faker data does not match');
269
        }
270
271
        return $loadedSecondTime;
272
    }
273
274
    /**
275
     * @param array $entities
276
     *
277
     * @return EntityInterface[]
278
     * @return EntityInterface[]
279
     */
280
    private function getArrayKeyedByUuid(array $entities): array
281
    {
282
        $return = [];
283
        foreach ($entities as $entity) {
284
            $return[$entity->getId()->toString()] = $entity;
285
        }
286
287
        return $return;
288
    }
289
290
    /**
291
     * @test
292
     * @large
293
     * @depends itUsesTheCacheTheSecondTime
294
     *
295
     * @param array $loadedSecondTime
296
     *
297
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
298
     * @throws \ReflectionException
299
     */
300
    public function itCanBeConfiguredNotToLoadFromTheCache(array $loadedSecondTime): void
301
    {
302
        $this->getFileSystem()
303
             ->mirror(
304
                 $this->copiedWorkDir .
305
                 '/../FixturesHelperTest_ItUsesTheCacheTheSecondTime_/cache',
306
                 $this->copiedWorkDir . '/cache'
307
             );
308
        $this->helper->setCacheKey(__CLASS__ . '_unmodified');
309
        $fixture = $this->getUnmodifiedFixture();
310
        $this->helper->setLoadFromCache(false);
311
        $this->helper->addFixture($fixture);
312
        $this->helper->createDb();
313
        self::assertFalse($this->helper->isLoadedFromCache());
314
        /**
315
         * @var EntityInterface[] $loadedThirdTime
316
         */
317
        $loadedThirdTime = $this->getRepositoryFactory()
318
                                ->getRepository($this->getCopiedFqn(self::ENTITY_WITHOUT_MODIFIER))
319
                                ->findAll();
320
        $actualCount     = count($loadedThirdTime);
321
        $expectedCount   = count($loadedSecondTime);
322
        self::assertSame($expectedCount, $actualCount);
323
        $second = $this->getArrayKeyedByUuid($loadedSecondTime);
324
        foreach ($loadedThirdTime as $actualEntity) {
325
            self::assertArrayNotHasKey($actualEntity->getId()->toString(), $second);
326
        }
327
    }
328
329
    /**
330
     * @test
331
     * @large
332
     */
333
    public function itCanTakeAModifierToCustomiseTheFixtures(): void
334
    {
335
        $this->helper->setCacheKey(__CLASS__ . '_modified');
336
        $fixture = $this->getModifiedFixture();
337
        $this->helper->addFixture($fixture);
338
        $this->helper->createDb();
339
        /**
340
         * @var EntityInterface[] $actual
341
         */
342
        $actual      = $this->getRepositoryFactory()
343
                            ->getRepository($this->getCopiedFqn(self::ENTITY_WITH_MODIFIER))
344
                            ->findAll();
345
        $actualCount = count($actual);
346
        self::assertSame($fixture::BULK_AMOUNT_TO_GENERATE + 1, $actualCount);
347
        $foundStrings = [];
348
        foreach ($actual as $entity) {
349
            $foundStrings[$entity->getString()] = true;
0 ignored issues
show
Bug introduced by
The method getString() does not exist on EdmondsCommerce\Doctrine...erfaces\EntityInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

349
            $foundStrings[$entity->/** @scrutinizer ignore-call */ getString()] = true;

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
350
        }
351
        $overwrittenString = 'This has been overridden';
352
        $createdString     = 'This has been created';
353
        self::assertArrayHasKey($overwrittenString, $foundStrings);
354
        self::assertArrayHasKey($createdString, $foundStrings);
355
    }
356
357
    private function getModifiedFixture(): AbstractEntityFixtureLoader
358
    {
359
        return $this->getFixture(
360
            $this->getCopiedFqn(self::ENTITY_WITH_MODIFIER),
361
            $this->getFixtureModifier()
362
        );
363
    }
364
365
    /**
366
     * @return FixtureEntitiesModifierInterface
367
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
368
     * @throws \ReflectionException
369
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
370
     */
371
    private function getFixtureModifier(): FixtureEntitiesModifierInterface
372
    {
373
374
        return new class(
375
            $this->getCopiedFqn(self::ENTITY_WITH_MODIFIER),
376
            $this->getEntityFactory(),
377
            $this->getEntityDtoFactory(),
378
            $this->getUuidFactory(),
379
            $this->getCopiedFqn(self::TEST_ENTITIES_ROOT_NAMESPACE . TestCodeGenerator::TEST_ENTITY_EMAIL)
380
        )
381
            implements FixtureEntitiesModifierInterface
382
        {
383
            /**
384
             * @var string
385
             */
386
            protected $entityFqn;
387
            /**
388
             * @var EntityFactoryInterface
389
             */
390
            protected $factory;
391
            /**
392
             * @var array|EntityInterface[]
393
             */
394
            private $entities;
395
            /**
396
             * @var DtoFactory
397
             */
398
            private $dtoFactory;
399
            /**
400
             * @var UuidFactory
401
             */
402
            private $uuidFactory;
403
            /**
404
             * @var string
405
             */
406
            private $emailFqn;
407
408
            public function __construct(
409
                string $entityFqn,
410
                EntityFactoryInterface $factory,
411
                DtoFactory $dtoFactory,
412
                UuidFactory $uuidFactory,
413
                string $emailFqn
414
            ) {
415
                $this->entityFqn   = $entityFqn;
416
                $this->factory     = $factory;
417
                $this->dtoFactory  = $dtoFactory;
418
                $this->uuidFactory = $uuidFactory;
419
                $this->emailFqn    = $emailFqn;
420
            }
421
422
            /**
423
             * Update the entities array by reference
424
             *
425
             * @param array $entities
426
             */
427
            public function modifyEntities(array &$entities): void
428
            {
429
                $this->entities = &$entities;
430
                $this->updateFirstEntity();
431
                $this->addAnotherEntity();
432
            }
433
434
            private function updateFirstEntity(): void
435
            {
436
                $firstEntity = current($this->entities);
437
                $firstEntity->update(
438
                    new class($this->entityFqn, $firstEntity->getId())
439
                        implements DataTransferObjectInterface
440
                    {
441
                        /**
442
                         * @var string
443
                         */
444
                        private static $entityFqn;
445
                        /**
446
                         * @var UuidInterface
447
                         */
448
                        private $id;
449
450
                        public function __construct(string $entityFqn, UuidInterface $id)
451
                        {
452
                            self::$entityFqn = $entityFqn;
453
                            $this->id        = $id;
454
                        }
455
456
                        public function getString(): string
457
                        {
458
                            return 'This has been overridden';
459
                        }
460
461
                        public static function getEntityFqn(): string
462
                        {
463
                            return self::$entityFqn;
464
                        }
465
466
                        public function getId(): UuidInterface
467
                        {
468
                            return $this->id;
469
                        }
470
                    }
471
                );
472
            }
473
474
            private function addAnotherEntity(): void
475
            {
476
                $address = $this->factory->create($this->emailFqn);
477
                $entity  = $this->factory->create(
478
                    $this->entityFqn,
479
                    new class($this->entityFqn, $this->uuidFactory, $address) implements DataTransferObjectInterface
480
                    {
481
                        /**
482
                         * @var string
483
                         */
484
                        private static $entityFqn;
485
                        /**
486
                         * @var \Ramsey\Uuid\UuidInterface
487
                         */
488
                        private $id;
489
                        /**
490
                         * @var EntityInterface
491
                         */
492
                        private $email;
493
494
                        public function __construct(string $entityFqn, UuidFactory $factory, EntityInterface $email)
495
                        {
496
                            self::$entityFqn = $entityFqn;
497
                            $this->id        = $factory->getOrderedTimeUuid();
498
                            $this->email     = $email;
499
                        }
500
501
                        public function getString(): string
502
                        {
503
                            return 'This has been created';
504
                        }
505
506
                        public static function getEntityFqn(): string
507
                        {
508
                            return self::$entityFqn;
509
                        }
510
511
                        public function getId(): UuidInterface
512
                        {
513
                            return $this->id;
514
                        }
515
516
                        public function getAttributesEmails(): ArrayCollection
517
                        {
518
                            $collection = new ArrayCollection();
519
                            $collection->add($this->email);
520
521
                            return $collection;
522
                        }
523
                    }
524
                );
525
526
                $this->entities[] = $entity;
527
            }
528
        };
529
    }
530
}
531