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

FieldGeneratorTest::setup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\Tests\Large\F\CodeGeneration\Generator\Field;
4
5
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\AbstractGenerator;
6
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field\EntityFieldSetter;
7
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field\FieldGenerator;
8
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
9
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\Boolean\DefaultsEnabledFieldTrait;
10
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\BusinessIdentifierCodeFieldTrait;
11
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\NullableStringFieldTrait;
12
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\UniqueStringFieldTrait;
13
use EdmondsCommerce\DoctrineStaticMeta\Entity\Fields\Traits\String\UrlFieldTrait;
14
use EdmondsCommerce\DoctrineStaticMeta\MappingHelper;
15
use EdmondsCommerce\DoctrineStaticMeta\Tests\Assets\AbstractTest;
16
17
/**
18
 * Class FieldGeneratorIntegrationTest
19
 *
20
 * @package EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator
21
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
22
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
23
 * @covers \EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field\FieldGenerator
24
 */
25
class FieldGeneratorTest extends AbstractTest
26
{
27
    public const WORK_DIR = AbstractTest::VAR_PATH .
28
                            '/' .
29
                            self::TEST_TYPE_LARGE .
30
                            '/FieldGeneratorIntegrationTest/';
31
32
    private const TEST_ENTITY_CAR = self::TEST_PROJECT_ROOT_NAMESPACE . '\\'
33
                                    . AbstractGenerator::ENTITIES_FOLDER_NAME . '\\Car';
34
35
    private const TEST_FIELD_NAMESPACE = self::TEST_PROJECT_ROOT_NAMESPACE
36
                                         . AbstractGenerator::ENTITY_FIELD_TRAIT_NAMESPACE;
37
38
    private const CAR_FIELDS_TO_TYPES = [
39
        [self::TEST_FIELD_NAMESPACE . '\\Brand', MappingHelper::TYPE_STRING],
40
        [self::TEST_FIELD_NAMESPACE . '\\EngineCC', MappingHelper::TYPE_INTEGER],
41
        [self::TEST_FIELD_NAMESPACE . '\\Manufactured', MappingHelper::TYPE_DATETIME],
42
        [self::TEST_FIELD_NAMESPACE . '\\Mpg', MappingHelper::TYPE_FLOAT],
43
        [self::TEST_FIELD_NAMESPACE . '\\Description', MappingHelper::TYPE_TEXT],
44
        [self::TEST_FIELD_NAMESPACE . '\\IsCar', MappingHelper::TYPE_BOOLEAN],
45
    ];
46
47
    private const UNIQUE_FIELDS_TO_TYPES = [
48
        [self::TEST_FIELD_NAMESPACE . '\\UniqueString', MappingHelper::TYPE_STRING],
49
        [self::TEST_FIELD_NAMESPACE . '\\UniqueInt', MappingHelper::TYPE_INTEGER],
50
    ];
51
52
    /**
53
     * @var FieldGenerator
54
     */
55
    private $fieldGenerator;
56
    /**
57
     * @var EntityFieldSetter
58
     */
59
    private $entityFieldSetter;
60
    /**
61
     * @var NamespaceHelper
62
     */
63
    private $namespaceHelper;
64
65
    public function setup()
66
    {
67
        parent::setUp();
68
        $this->getEntityGenerator()->generateEntity(self::TEST_ENTITY_CAR);
69
        $this->fieldGenerator    = $this->getFieldGenerator();
70
        $this->entityFieldSetter = $this->getFieldSetter();
71
        $this->namespaceHelper   = $this->container->get(NamespaceHelper::class);
72
    }
73
74
    /**
75
     * @test
76
     * @large
77
     *      * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
78
     * @throws \ReflectionException
79
     */
80
    public function archetypeFieldCanBeStandardLibraryField(): void
81
    {
82
        foreach (FieldGenerator::STANDARD_FIELDS as $standardField) {
83
            $fieldFqn = \str_replace(
84
                [
85
                    'EdmondsCommerce\\DoctrineStaticMeta',
86
                    $this->namespaceHelper->getClassShortName($standardField),
87
                ],
88
                [
89
                    self::TEST_PROJECT_ROOT_NAMESPACE,
90
                    'Copied' . $this->namespaceHelper->getClassShortName($standardField),
91
                ],
92
                $standardField
93
            );
94
            $this->buildAndCheck(
95
                $fieldFqn,
96
                $standardField
97
            );
98
        }
99
    }
100
101
    /**
102
     * Build and then test a field
103
     *
104
     * @param string $name
105
     * @param string $type
106
     *
107
     * @param mixed  $default
108
     * @param bool   $isUnique
109
     *
110
     * @return string
111
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
112
     * @throws \ReflectionException
113
     * @SuppressWarnings(PHPMD.StaticAccess)
114
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
115
     */
116
    protected function buildAndCheck(
117
        string $name,
118
        string $type,
119
        $default = null,
120
        bool $isUnique = false
121
    ): string {
122
        $fieldTraitFqn = $this->fieldGenerator->generateField(
123
            $name,
124
            $type,
125
            null,
126
            $default,
127
            $isUnique
128
        );
129
        $isArchetype   = !\in_array($type, MappingHelper::ALL_DBAL_TYPES, true);
130
        $this->qaGeneratedCode();
131
        $interfacePath = $this->getPathFromFqn(
132
            \str_replace(
133
                '\\Fields\\Traits\\',
134
                '\\Fields\\Interfaces\\',
135
                $this->namespaceHelper->cropSuffix($fieldTraitFqn, 'Trait') . 'Interface'
136
            )
137
        );
138
        $checkFor      = [];
139
        if (true === $isArchetype) {
140
            $archetypeBasename = $this->namespaceHelper->basename($type);
141
            $newBaseName       = $this->namespaceHelper->basename($name);
142
            if (false === strpos($newBaseName, 'FieldTrait')) {
143
                $newBaseName .= 'FieldTrait';
144
            }
145
            if ($archetypeBasename !== $newBaseName) {
146
                $checkFor = [
147
                    $this->getCodeHelper()->consty($archetypeBasename),
148
                    $this->getCodeHelper()->classy($archetypeBasename),
149
                    $this->getCodeHelper()->propertyIsh($archetypeBasename),
150
                ];
151
            }
152
        }
153
        $this->assertNoMissedReplacements($interfacePath, $checkFor);
154
155
        $traitPath = $this->getPathFromFqn($fieldTraitFqn);
156
        $this->assertNoMissedReplacements($traitPath, $checkFor);
157
158
        $interfaceContents = file_get_contents($interfacePath);
159
        $traitContents     = file_get_contents($traitPath);
160
161
        if (!$isArchetype && !\in_array($type, [MappingHelper::TYPE_TEXT, MappingHelper::TYPE_STRING], true)) {
162
            self::assertNotContains(': string', $interfaceContents);
163
            self::assertNotContains(': string', $traitContents);
164
            self::assertNotContains('(string', $traitContents);
165
            $phpType = MappingHelper::COMMON_TYPES_TO_PHP_TYPES[$type];
166
            if (null === $default) {
167
                $phpType = "?$phpType";
168
            }
169
            self::assertContains(': ' . $phpType, $interfaceContents);
170
            self::assertContains(': ' . $phpType, $traitContents);
171
        }
172
173
        self::assertNotContains('public function isIs', $interfaceContents, '', true);
174
        self::assertNotContains('public function isIs', $traitContents, '', true);
175
        if ($type === MappingHelper::TYPE_BOOLEAN) {
176
            self::assertNotContains('public function get', $interfaceContents);
177
            self::assertNotContains('public function get', $traitContents);
178
        }
179
180
        return $fieldTraitFqn;
181
    }
182
183
    protected function getPathFromFqn(string $fqn): string
184
    {
185
        $path = self::WORK_DIR . 'src/Entity/Fields';
186
        $exp  = explode(
187
            '\\',
188
            \substr(
189
                $fqn,
190
                strpos(
191
                    $fqn,
192
                    '\\Entity\\Fields\\'
193
                ) + \strlen('\\Entity\\Fields\\')
194
            )
195
        );
196
        foreach ($exp as $item) {
197
            $path .= '/' . $item;
198
        }
199
        $path .= '.php';
200
201
        return $path;
202
    }
203
204
    /**
205
     * @test
206
     * @large
207
     *      * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
208
     * @throws \ReflectionException
209
     */
210
    public function itDoesNotClobberValidatorClassNames(): void
211
    {
212
        $this->fieldGenerator->generateField(
213
            self::TEST_FIELD_NAMESPACE . '\\Domain',
214
            UrlFieldTrait::class
215
        );
216
        self::assertNotContains(
217
            'new Domain()',
218
            \ts\file_get_contents(self::WORK_DIR . '/src/Entity/Fields/Traits/DomainFieldTrait.php')
219
        );
220
        self::assertNotContains(
221
            'use Symfony\Component\Validator\Constraints\Domain;',
222
            \ts\file_get_contents(self::WORK_DIR . '/src/Entity/Fields/Traits/DomainFieldTrait.php')
223
        );
224
    }
225
226
    /**
227
     * @test
228
     * @large
229
     *      * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
230
     * @throws \ReflectionException
231
     */
232
    public function archetypeFieldCanBeNonStandardLibraryField(): void
233
    {
234
        $args         = current(self::CAR_FIELDS_TO_TYPES);
235
        $archetypeFqn = $this->fieldGenerator->generateField($args[0], $args[1]);
236
        $this->buildAndCheck(self::TEST_FIELD_NAMESPACE . '\\BrandCopied', $archetypeFqn);
237
    }
238
239
    /**
240
     * @test
241
     * @large
242
     *      */
243
    public function fieldCanBeDeeplyNamespaced(): void
244
    {
245
        $deeplyNamespaced = self::TEST_FIELD_NAMESPACE . '\\Deeply\\Nested\\String';
246
        $this->buildAndCheck($deeplyNamespaced, MappingHelper::TYPE_STRING);
247
    }
248
249
    /**
250
     * @test
251
     * @large
252
     *      */
253
    public function archetypeFieldCanBeDeeplyNested(): void
254
    {
255
        $deeplyNamespaced = self::TEST_FIELD_NAMESPACE . '\\Deeply\\Nested\\StringFieldTrait';
256
        $this->buildAndCheck($deeplyNamespaced, NullableStringFieldTrait::class);
257
    }
258
259
    /**
260
     * @test
261
     * @large
262
     *      */
263
    public function theGeneratedFieldCanHaveTheSameNameAsTheArchetype(): void
264
    {
265
        $deeplyNamespaced = self::TEST_FIELD_NAMESPACE . '\\Deeply\\Nested\\NullableString';
266
        $this->buildAndCheck($deeplyNamespaced, NullableStringFieldTrait::class);
267
    }
268
269
    /**
270
     * @test
271
     * @large
272
     *      */
273
    public function archetypeBooleansBeginningWithIsAreHandledProperly(): void
274
    {
275
        $deeplyNamespaced = self::TEST_FIELD_NAMESPACE . '\\Deeply\\Nested\\IsBoolean';
276
        $this->buildAndCheck($deeplyNamespaced, DefaultsEnabledFieldTrait::class);
277
    }
278
279
    /**
280
     * @test
281
     * @large
282
     *      */
283
    public function fieldMustContainEntityNamespace(): void
284
    {
285
        $this->expectException(\InvalidArgumentException::class);
286
        $this->fieldGenerator->generateField(
287
            '\\Blah\\Foop',
288
            MappingHelper::TYPE_STRING,
289
            null,
290
            null,
291
            true
292
        );
293
    }
294
295
    /**
296
     * @test
297
     * @large
298
     *      */
299
    public function fieldTypeMustBeValid(): void
300
    {
301
        $this->expectException(\InvalidArgumentException::class);
302
        $this->fieldGenerator->generateField(
303
            self::CAR_FIELDS_TO_TYPES[0][0],
304
            'invalid',
305
            null,
306
            null,
307
            true
308
        );
309
    }
310
311
    /**
312
     * @test
313
     * @large
314
     *      */
315
    public function phpTypeMustBeValid(): void
316
    {
317
        $this->expectException(\InvalidArgumentException::class);
318
        $this->fieldGenerator->generateField(
319
            self::CAR_FIELDS_TO_TYPES[0][0],
320
            MappingHelper::PHP_TYPE_FLOAT,
321
            'invalid',
322
            null,
323
            true
324
        );
325
    }
326
327
    /**
328
     * @test
329
     * @large
330
     *      */
331
    public function defaultTypeMustBeValid(): void
332
    {
333
        $this->expectException(\InvalidArgumentException::class);
334
        $this->fieldGenerator->generateField(
335
            self::CAR_FIELDS_TO_TYPES[0][0],
336
            MappingHelper::PHP_TYPE_FLOAT,
337
            'invalid',
338
            'clearly not a float',
339
            true
340
        );
341
    }
342
343
    /**
344
     * @test
345
     * @large
346
     *      */
347
    public function defaultValueIsNormalised(): void
348
    {
349
        $defaultValuesToTypes = [
350
            MappingHelper::TYPE_INTEGER => [
351
                1,
352
                '1',
353
                ' 1',
354
                ' 1 ',
355
            ],
356
            MappingHelper::TYPE_FLOAT   => [
357
                1,
358
                1.0,
359
                '1',
360
                '1.1',
361
                ' 1.1 ',
362
                ' 1.1 ',
363
            ],
364
            MappingHelper::TYPE_BOOLEAN => [
365
                'true',
366
                'false',
367
                'TRUE',
368
                'FALSE',
369
                ' TRue ',
370
                ' FaLse ',
371
            ],
372
        ];
373
        $errors               = [];
374
        foreach ($defaultValuesToTypes as $type => $defaultValues) {
375
            foreach ($defaultValues as $key => $defaultValue) {
376
                try {
377
                    $this->buildAndCheck(
378
                        self::TEST_FIELD_NAMESPACE . '\\normalisedDefault' . $type . $key,
379
                        $type,
380
                        $defaultValue
381
                    );
382
                } catch (\Throwable $e) {
383
                    $errors[] = [
384
                        'type'    => $type,
385
                        'default' => $defaultValue,
386
                        'error'   => $e->getMessage(),
387
                    ];
388
                }
389
            }
390
        }
391
        self::assertSame([], $errors, print_r($errors, true));
392
    }
393
394
    /**
395
     * @test
396
     * @large
397
     *      */
398
    public function buildFieldsAndSetToEntity(): void
399
    {
400
        foreach (self::CAR_FIELDS_TO_TYPES as $args) {
401
            $fieldFqn = $this->buildAndCheck($args[0], $args[1], null);
402
            $this->entityFieldSetter->setEntityHasField(self::TEST_ENTITY_CAR, $fieldFqn);
403
        }
404
        $this->qaGeneratedCode();
405
    }
406
407
    /**
408
     * @test
409
     * @large
410
     *      */
411
    public function buildFieldsWithSuffixAndSetToEntity(): void
412
    {
413
        foreach (self::CAR_FIELDS_TO_TYPES as $args) {
414
            $fieldFqn = $this->buildAndCheck($args[0] . FieldGenerator::FIELD_TRAIT_SUFFIX, $args[1], null);
415
            $this->entityFieldSetter->setEntityHasField(self::TEST_ENTITY_CAR, $fieldFqn);
416
        }
417
        $this->qaGeneratedCode();
418
    }
419
420
    /**
421
     * @test
422
     * @large
423
     *      */
424
    public function buildNullableFieldsAndSetToEntity(): void
425
    {
426
        foreach (self::CAR_FIELDS_TO_TYPES as $args) {
427
            $fieldFqn = $this->buildAndCheck($args[0], $args[1], null);
428
            $this->entityFieldSetter->setEntityHasField(self::TEST_ENTITY_CAR, $fieldFqn);
429
        }
430
        $this->qaGeneratedCode();
431
    }
432
433
    /**
434
     * @test
435
     * @large
436
     *      */
437
    public function buildUniqueFieldsAndSetToEntity(): void
438
    {
439
        foreach (self::UNIQUE_FIELDS_TO_TYPES as $args) {
440
            $fieldFqn = $this->buildAndCheck($args[0], $args[1], null, true);
441
            $this->entityFieldSetter->setEntityHasField(self::TEST_ENTITY_CAR, $fieldFqn);
442
        }
443
        $this->qaGeneratedCode();
444
    }
445
446
    /**
447
     * @test
448
     * @large
449
     *      */
450
    public function buildingAnArchetypeThenNormalField(): void
451
    {
452
        $this->buildAndCheck(self::TEST_FIELD_NAMESPACE . '\\UniqueName', UniqueStringFieldTrait::class);
453
        $this->buildAndCheck(self::TEST_FIELD_NAMESPACE . '\\SimpleString', MappingHelper::TYPE_STRING);
454
        $this->buildAndCheck(self::TEST_FIELD_NAMESPACE . '\\UniqueThing', UniqueStringFieldTrait::class);
455
    }
456
457
    /**
458
     * @test
459
     * @large
460
     *      */
461
    public function notPossibleToAddDuplicateNamedFieldsToSingleEntity(): void
462
    {
463
        $someThing  = self::TEST_FIELD_NAMESPACE . '\\Something\\FooFieldTrait';
464
        $otherThing = self::TEST_FIELD_NAMESPACE . '\\Otherthing\\FooFieldTrait';
465
        $this->buildAndCheck($someThing, UniqueStringFieldTrait::class);
466
        $this->buildAndCheck($otherThing, BusinessIdentifierCodeFieldTrait::class);
467
        $this->entityFieldSetter->setEntityHasField(self::TEST_ENTITY_CAR, $someThing);
468
        $this->expectException(\InvalidArgumentException::class);
469
        $this->entityFieldSetter->setEntityHasField(self::TEST_ENTITY_CAR, $otherThing);
470
    }
471
}
472