Skip to content

Commit e7218a7

Browse files
committed
Add tests for the PopulatePostProcessor
1 parent 409debf commit e7218a7

File tree

6 files changed

+179
-4
lines changed

6 files changed

+179
-4
lines changed

docs/source/generator/postProcessor.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ Now let's have a look at the behaviour of the generated model:
7070
// if the update of the model fails no values will be updated
7171
$example->getRawModelDataInput(); // returns ['value' => 'Good night!', 'additionalValue' => 12]
7272
73+
.. warning::
74+
75+
If the **PopulatePostProcessor** is added to your model generator the populate method will be added to the model independently of the `immutable setting <../gettingStarted.html#immutable-classes>`__.
76+
7377
Custom Post Processors
7478
----------------------
7579

@@ -91,3 +95,7 @@ A custom post processor which adds a custom trait to the generated model (eg. a
9195
$schema->addTrait(ActiveRecordTrait::class);
9296
}
9397
}
98+
99+
.. hint::
100+
101+
For examples how to implement a custom post processor have a look at the built in post processors located at **src/SchemaProcessor/PostProcessor/**

src/PropertyProcessor/Property/BaseProcessor.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ class BaseProcessor extends AbstractPropertyProcessor
3333
{
3434
protected const TYPE = 'object';
3535

36+
private const COUNT_PROPERTIES =
37+
'count(
38+
array_unique(
39+
array_merge(
40+
array_keys($this->rawModelDataInput),
41+
array_keys($modelData)
42+
)
43+
)
44+
)';
45+
3646
/**
3747
* @inheritdoc
3848
*
@@ -147,7 +157,8 @@ protected function addMaxPropertiesValidator(string $propertyName, array $proper
147157
$this->schema->addBaseValidator(
148158
new PropertyValidator(
149159
sprintf(
150-
'count(array_merge(array_keys($this->rawModelDataInput), array_keys($modelData))) > %d',
160+
'%s > %d',
161+
self::COUNT_PROPERTIES,
151162
$propertyData['maxProperties']
152163
),
153164
MaxPropertiesException::class,
@@ -171,7 +182,8 @@ protected function addMinPropertiesValidator(string $propertyName, array $proper
171182
$this->schema->addBaseValidator(
172183
new PropertyValidator(
173184
sprintf(
174-
'count(array_merge(array_keys($this->rawModelDataInput), array_keys($modelData))) < %d',
185+
'%s < %d',
186+
self::COUNT_PROPERTIES,
175187
$propertyData['minProperties']
176188
),
177189
MinPropertiesException::class,

src/SchemaProcessor/PostProcessor/SerializationPostProcessor.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use JsonSerializable;
88
use PHPModelGenerator\Interfaces\SerializationInterface;
99
use PHPModelGenerator\Model\GeneratorConfiguration;
10-
use PHPModelGenerator\Model\Property\Serializer\TransformingFilterSerializer;
1110
use PHPModelGenerator\Model\Schema;
1211
use PHPModelGenerator\Model\Validator\FilterValidator;
1312
use PHPModelGenerator\PropertyProcessor\Filter\TransformingFilterInterface;

tests/AbstractPHPModelGeneratorTest.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
abstract class AbstractPHPModelGeneratorTest extends TestCase
3030
{
3131
protected const EXTERNAL_JSON_DIRECTORIES = [];
32+
protected const POST_PROCESSORS = [];
3233

3334
private $names = [];
3435

@@ -238,7 +239,12 @@ public function getClassName(
238239
default: throw new Exception("Schema provider $schemaProviderClass not supported");
239240
}
240241

241-
$generatedFiles = (new ModelGenerator($generatorConfiguration))->generateModels(
242+
$generator = new ModelGenerator($generatorConfiguration);
243+
foreach (static::POST_PROCESSORS as $postProcessor) {
244+
$generator->addPostProcessor(new $postProcessor());
245+
}
246+
247+
$generatedFiles = $generator->generateModels(
242248
$schemaProvider,
243249
$baseDir . DIRECTORY_SEPARATOR . 'Models' . DIRECTORY_SEPARATOR
244250
);
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<?php
2+
3+
namespace PHPModelGenerator\Tests\PostProcessor;
4+
5+
use Exception;
6+
use PHPModelGenerator\Exception\ErrorRegistryException;
7+
use PHPModelGenerator\Exception\Object\InvalidAdditionalPropertiesException;
8+
use PHPModelGenerator\Exception\Object\InvalidPropertyNamesException;
9+
use PHPModelGenerator\Exception\Object\MaxPropertiesException;
10+
use PHPModelGenerator\Exception\String\PatternException;
11+
use PHPModelGenerator\Model\GeneratorConfiguration;
12+
use PHPModelGenerator\SchemaProcessor\PostProcessor\PopulatePostProcessor;
13+
use PHPModelGenerator\Tests\AbstractPHPModelGeneratorTest;
14+
15+
class PopulatePostProcessorTest extends AbstractPHPModelGeneratorTest
16+
{
17+
protected const POST_PROCESSORS = [PopulatePostProcessor::class];
18+
19+
public function testPopulateMethod(): void
20+
{
21+
$className = $this->generateClassFromFile(
22+
'BasicSchema.json',
23+
(new GeneratorConfiguration())->setSerialization(true)
24+
);
25+
$object = new $className(['name' => 'Albert']);
26+
27+
$this->assertTrue(is_callable([$object, 'populate']));
28+
29+
// test an empty populate call doesn't change the internal behaviour
30+
$object->populate([]);
31+
$this->assertSame(['name' => 'Albert'], $object->getRawModelDataInput());
32+
$this->assertSame(['name' => 'Albert', 'age' => null], $object->toArray());
33+
34+
// test adding an additional property to the model
35+
$object->populate(['birthdate' => '10.10.1990']);
36+
$this->assertSame(['name' => 'Albert', 'birthdate' => '10.10.1990'], $object->getRawModelDataInput());
37+
$this->assertSame(['name' => 'Albert', 'age' => null], $object->toArray());
38+
39+
// test overwriting a single property
40+
$object->populate(['age' => 30]);
41+
$this->assertSame(
42+
['name' => 'Albert', 'birthdate' => '10.10.1990', 'age' => 30],
43+
$object->getRawModelDataInput()
44+
);
45+
$this->assertSame(['name' => 'Albert', 'age' => 30], $object->toArray());
46+
47+
// test overwriting multiple properties
48+
$object->populate(['age' => 26, 'name' => 'Harry']);
49+
$this->assertSame(
50+
['name' => 'Harry', 'birthdate' => '10.10.1990', 'age' => 26],
51+
$object->getRawModelDataInput()
52+
);
53+
$this->assertSame(['name' => 'Harry', 'age' => 26], $object->toArray());
54+
}
55+
56+
/**
57+
* @dataProvider invalidPopulateDataProvider
58+
*/
59+
public function testInvalidPopulateThrowsAnException(
60+
array $data,
61+
bool $collectErrors,
62+
string $expectedException,
63+
string $expectedMessage
64+
): void {
65+
$this->expectException($expectedException);
66+
$this->expectExceptionMessage($expectedMessage);
67+
68+
$className = $this->generateClassFromFile(
69+
'BasicSchema.json',
70+
(new GeneratorConfiguration())->setCollectErrors($collectErrors)
71+
);
72+
$object = new $className(['name' => 'Albert', 'age' => 30]);
73+
74+
try {
75+
$object->populate($data);
76+
$this->fail('No exception thrown');
77+
} catch (Exception $exception) {
78+
// test if the internal state hasn't been changed
79+
$this->assertSame(['name' => 'Albert', 'age' => 30], $object->getRawModelDataInput());
80+
81+
throw $exception;
82+
}
83+
}
84+
85+
public function invalidPopulateDataProvider(): array
86+
{
87+
return [
88+
'No error collection - multiple violations' => [
89+
['name' => 'Anne-Marie', 'age' => false],
90+
false,
91+
PatternException::class,
92+
"Value for name doesn't match pattern ^[a-zA-Z]*$"
93+
],
94+
'Error collection - multiple violations' => [
95+
['name' => 'Anne-Marie', 'age' => false],
96+
true,
97+
ErrorRegistryException::class,
98+
"Value for name doesn't match pattern ^[a-zA-Z]*$
99+
Value for name must not be longer than 8
100+
Invalid type for age. Requires int, got boolean"
101+
],
102+
'Invalid additional property' => [
103+
['numeric' => 9],
104+
false,
105+
InvalidAdditionalPropertiesException::class,
106+
"contains invalid additional properties.
107+
- invalid additional property 'numeric'
108+
* Invalid type for additional property. Requires string, got integer"
109+
],
110+
'Invalid additional property name' => [
111+
['invalid name' => 'Hi'],
112+
false,
113+
InvalidPropertyNamesException::class,
114+
"contains properties with invalid names.
115+
- invalid property 'invalid name'
116+
* Value for property name doesn't match pattern ^[a-zA-Z]*$"
117+
],
118+
'Too many properties' => [
119+
['additional' => 'Hi', 'another' => 'Ho'],
120+
false,
121+
MaxPropertiesException::class,
122+
"must not contain more than 3 properties"
123+
],
124+
];
125+
}
126+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"type": "object",
3+
"properties": {
4+
"name": {
5+
"type": "string",
6+
"maxLength": 8,
7+
"pattern": "^[a-zA-Z]*$"
8+
},
9+
"age": {
10+
"type": "integer",
11+
"minimum": 0
12+
}
13+
},
14+
"additionalProperties": {
15+
"type": "string"
16+
},
17+
"propertyNames": {
18+
"pattern": "^[a-zA-Z]*$"
19+
},
20+
"maxProperties": 3,
21+
"required": [
22+
"name"
23+
]
24+
}

0 commit comments

Comments
 (0)