Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
AbstractRenderTestCase
n/a
0 / 0
n/a
0 / 0
4
n/a
0 / 0
 getRenderer
n/a
0 / 0
n/a
0 / 0
0
 getFixturesPath
n/a
0 / 0
n/a
0 / 0
0
 shouldOverwriteFixture
n/a
0 / 0
n/a
0 / 0
1
 testRender
n/a
0 / 0
n/a
0 / 0
2
 provideComponents
n/a
0 / 0
n/a
0 / 0
1
1<?php
2namespace Apie\HtmlBuilders\TestHelpers;
3
4use Apie\Common\ActionDefinitions\CreateResourceActionDefinition;
5use Apie\Core\Attributes\CmsSingleInput;
6use Apie\Core\BoundedContext\BoundedContextId;
7use Apie\Core\Context\ApieContext;
8use Apie\Core\Dto\CmsInputOption;
9use Apie\Core\Enums\RequestMethod;
10use Apie\Core\Lists\StringSet;
11use Apie\Core\Translator\ApieTranslator;
12use Apie\Core\Translator\ApieTranslatorInterface;
13use Apie\Core\Translator\Lists\TranslationStringSet;
14use Apie\Core\Translator\ValueObjects\TranslationString;
15use Apie\Core\ValueObjects\DatabaseText;
16use Apie\Fixtures\BoundedContextFactory;
17use Apie\Fixtures\Entities\Order;
18use Apie\Fixtures\Entities\Polymorphic\Animal;
19use Apie\Fixtures\Entities\UserWithAddress;
20use Apie\Fixtures\Entities\UserWithAutoincrementKey;
21use Apie\Fixtures\Identifiers\OrderIdentifier;
22use Apie\Fixtures\Identifiers\UserWithAddressIdentifier;
23use Apie\Fixtures\Lists\OrderLineList;
24use Apie\Fixtures\ValueObjects\AddressWithZipcodeCheck;
25use Apie\HtmlBuilders\Components\Dashboard\RawContents;
26use Apie\HtmlBuilders\Components\Forms\Csrf;
27use Apie\HtmlBuilders\Components\Forms\Form;
28use Apie\HtmlBuilders\Components\Forms\FormGroup;
29use Apie\HtmlBuilders\Components\Forms\FormPrototypeHashmap;
30use Apie\HtmlBuilders\Components\Forms\FormPrototypeList;
31use Apie\HtmlBuilders\Components\Forms\FormSplit;
32use Apie\HtmlBuilders\Components\Forms\PolymorphicForm;
33use Apie\HtmlBuilders\Components\Forms\RemoveConfirm;
34use Apie\HtmlBuilders\Components\Forms\SingleInput;
35use Apie\HtmlBuilders\Components\Layout;
36use Apie\HtmlBuilders\Components\Layout\BoundedContextSelect;
37use Apie\HtmlBuilders\Components\Layout\LoginSelect;
38use Apie\HtmlBuilders\Components\Layout\Logo;
39use Apie\HtmlBuilders\Components\Layout\ShowProfile;
40use Apie\HtmlBuilders\Components\Resource\Detail;
41use Apie\HtmlBuilders\Components\Resource\FieldDisplay\BooleanDisplay;
42use Apie\HtmlBuilders\Components\Resource\FieldDisplay\LinkDisplay;
43use Apie\HtmlBuilders\Components\Resource\FieldDisplay\ListDisplay;
44use Apie\HtmlBuilders\Components\Resource\FieldDisplay\NullDisplay;
45use Apie\HtmlBuilders\Components\Resource\FieldDisplay\SegmentDisplay;
46use Apie\HtmlBuilders\Components\Resource\FilterColumns;
47use Apie\HtmlBuilders\Components\Resource\Overview;
48use Apie\HtmlBuilders\Components\Resource\ResourceActionList;
49use Apie\HtmlBuilders\Components\Resource\SingleResourceActionList;
50use Apie\HtmlBuilders\Configuration\CurrentConfiguration;
51use Apie\HtmlBuilders\Interfaces\ComponentInterface;
52use Apie\HtmlBuilders\Interfaces\ComponentRendererInterface;
53use Apie\HtmlBuilders\Lists\ActionList;
54use Apie\HtmlBuilders\Lists\ComponentHashmap;
55use Apie\HtmlBuilders\ResourceActions\CreateResourceAction;
56use Apie\HtmlBuilders\ValueObjects\FormName;
57use Apie\TypeConverter\ReflectionTypeFactory;
58use Generator;
59use PHPUnit\Framework\TestCase;
60use ReflectionClass;
61
62/**
63 * @codeCoverageIgnore
64 */
65abstract class AbstractRenderTestCase extends TestCase
66{
67    abstract public function getRenderer(): ComponentRendererInterface;
68
69    abstract public function getFixturesPath(): string;
70
71    /**
72     * Overwriting this method to return true means the fixtures will be overwritten to ease big refactorings.
73     */
74    protected function shouldOverwriteFixture(): bool
75    {
76        return true;//false;
77    }
78
79    #[\PHPUnit\Framework\Attributes\DataProvider('provideComponents')]
80    public function testRender(string $expectedFixtureFile, ComponentInterface $component): void
81    {
82        $renderer = $this->getRenderer();
83        $context = new ApieContext([
84            ApieTranslatorInterface::class => new ApieTranslator(),
85        ]);
86        $actual = $renderer->render($component, $context);
87        $fixtureFile = $this->getFixturesPath() . DIRECTORY_SEPARATOR . $expectedFixtureFile;
88        if ($this->shouldOverwriteFixture()) {
89            file_put_contents($fixtureFile, $actual);
90        }
91        $expected = file_get_contents($fixtureFile);
92        $this->assertEquals($expected, $actual);
93    }
94
95    public static function provideComponents(): Generator
96    {
97        $rawContents = new RawContents('<marquee>Hello world</marquee>');
98        $defaultConfiguration = new CurrentConfiguration([], new ApieContext(), BoundedContextFactory::createHashmap(), new BoundedContextId('default'));
99        yield 'Raw HTML concents' => [
100            'expected-raw-contents.html',
101            $rawContents,
102        ];
103        yield 'Simple layout' => [
104            'expected-simple-layout.html',
105            new Layout(
106                'Title',
107                $defaultConfiguration,
108                $rawContents
109            )
110        ];
111        yield 'Bounded context select => nothing selected' => [
112            'expected-bounded-context-select-nothing.html',
113            new BoundedContextSelect(
114                new CurrentConfiguration([], new ApieContext(), BoundedContextFactory::createHashmap(), null)
115            )
116        ];
117        yield 'Bounded context select => unknown selection' => [
118            'expected-bounded-context-select-unknown.html',
119            new BoundedContextSelect(
120                new CurrentConfiguration([], new ApieContext(), BoundedContextFactory::createHashmap(), new BoundedContextId('unknown'))
121            )
122        ];
123        yield 'Bounded context select => single bounded context' => [
124            'expected-bounded-context-select.html',
125            new BoundedContextSelect(
126                $defaultConfiguration
127            )
128        ];
129        yield 'Bounded context select => multiple bounded context' => [
130            'expected-bounded-context-select-multiple.html',
131            new BoundedContextSelect(
132                new CurrentConfiguration([], new ApieContext(), BoundedContextFactory::createHashmapWithMultipleContexts(), new BoundedContextId('default'))
133            )
134        ];
135        yield 'Logo' => [
136            'expected-logo.html',
137            new Logo($defaultConfiguration),
138        ];
139        yield 'Login select' => [
140            'expected-login-select.html',
141            new LoginSelect(
142                $defaultConfiguration
143            )
144        ];
145
146        yield 'Profile' => [
147            'expected-profile.html',
148            new ShowProfile(
149                $defaultConfiguration,
150                new UserWithAddress(
151                    new AddressWithZipcodeCheck(
152                        new DatabaseText('Evergreen Terrace'),
153                        new DatabaseText('742'),
154                        new DatabaseText('11111'),
155                        new DatabaseText('Springfield'),
156                    ),
157                    new UserWithAddressIdentifier('d788c9f5-6493-4386-89f4-374be3b28764'),
158                )
159            )
160        ];
161
162        yield 'Simple Menu' => [
163            'expected-menu.html',
164            new Layout\Menu($defaultConfiguration),
165        ];
166
167        yield 'Resource overview filters' => [
168            'expected-resource-overview-filters.html',
169            new FilterColumns(
170                new StringSet(['id', 'description']),
171                'text search',
172                ['description' => 'test'],
173            )
174            ];
175        
176        yield 'Resource overview' => [
177            'expected-resource-overview.html',
178            new Overview(
179                [['id' => 12, 'name' => 'Pizza']],
180                ['id', 'name'],
181                new ResourceActionList(
182                    $defaultConfiguration,
183                    new ActionList([]),
184                    new FilterColumns(new StringSet(), '', []),
185                )
186            )
187        ];
188
189        $createResourceAction = new CreateResourceAction(
190            new ReflectionClass(UserWithAutoincrementKey::class),
191            new CreateResourceActionDefinition(
192                new ReflectionClass(UserWithAutoincrementKey::class),
193                new BoundedContextId('default')
194            )
195        );
196        $resourceActionList = new ResourceActionList(
197            $defaultConfiguration,
198            new ActionList([$createResourceAction]),
199            new FilterColumns(new StringSet(), '', []),
200        );
201        yield 'Resource action list' => [
202            'expected-resource-action-list.html',
203            $resourceActionList
204        ];
205
206        yield 'Resource overview large list' => [
207            'expected-resource-overview-large-list.html',
208            new Overview(
209                array_fill(0, 100, ['id' => 12, 'name' => 'Pizza']),
210                ['id', 'name'],
211                $resourceActionList
212            )
213        ];
214
215        yield 'Form' => [
216            'expected-form.html',
217            new Form(RequestMethod::POST, null, [], [], false, new RawContents('test'), new RawContents('test2')),
218        ];
219        yield 'Form-Upload' => [
220            'expected-form-with-upload.html',
221            new Form(RequestMethod::POST, null, [], [], true, new RawContents('test'), new RawContents('test2')),
222        ];
223        yield 'Polymorphic Form' => [
224            'expected-polymorphic-form.html',
225            new PolymorphicForm(
226                RequestMethod::POST,
227                new ReflectionClass(Animal::class),
228                null,
229                [],
230                [],
231                false,
232                new Csrf('temp'),
233                new ComponentHashmap([
234                    'test1' => new RawContents('test3'),
235                    'test2' => new RawContents('test4'),
236                ])
237            ),
238        ];
239        yield 'Polymorphic Form-Upload' => [
240            'expected-polymorphic-form-with-upload.html',
241            new PolymorphicForm(
242                RequestMethod::POST,
243                new ReflectionClass(Animal::class),
244                null,
245                [],
246                [],
247                true,
248                new Csrf('temp'),
249                new ComponentHashmap([
250                    'test1' => new RawContents('test3'),
251                    'test2' => new RawContents('test4'),
252                ])
253            ),
254        ];
255        yield 'Form with validation errors' => [
256            'expected-form-with-unknown-validation-error.html',
257            new Form(RequestMethod::POST, null, ['id' => 'unknown field'], [], false, new RawContents('test')),
258        ];
259
260        yield 'Form group with validation errors' => [
261            'expected-form-group-with-validation-error.html',
262            new FormGroup(new FormName('test'), null, ['id' => 'unknown field'], new RawContents('test')),
263        ];
264
265        yield 'Form with validation error' => [
266            'expected-form-with-validation-error.html',
267            new Form(RequestMethod::POST, 'validation error', [], [], false, new RawContents('test'), new RawContents('test2')),
268        ];
269
270        yield 'Configured input' => [
271            'expected-single-input.html',
272            new SingleInput(
273                new FormName('name'),
274                42,
275                new TranslationStringSet([new TranslationString('test')]),
276                false,
277                ReflectionTypeFactory::createReflectionType('string'),
278                new CmsSingleInput(['datetimetz', 'text'], new CmsInputOption())
279            )
280        ];
281        $type = ReflectionTypeFactory::createReflectionType('string');
282        yield 'Union type' => [
283            'expected-type-split.html',
284            new FormSplit(
285                new FormName('name'),
286                false,
287                false,
288                '42',
289                new ComponentHashmap([
290                    'input' => new SingleInput(new FormName('input'), null, new TranslationStringSet([]), false, $type, new CmsSingleInput(['text'])),
291                    'password' => new SingleInput(new FormName('password'), null, new TranslationStringSet([]), false, $type, new CmsSingleInput(['text'])),
292                ])
293            )
294        ];
295
296        yield 'Form list' => [
297            'expected-form-list.html',
298            new FormPrototypeList(
299                new FormName('name'),
300                [],
301                '__NAME__',
302                new RawContents('<div>Row</div>')
303            )
304        ];
305
306        yield 'Form list with values' => [
307            'expected-form-list-with-values.html',
308            new FormPrototypeList(
309                new FormName('name'),
310                [
311                    '0611223344',
312                    '0123456789',
313                ],
314                '__NAME__',
315                new RawContents('<div>Row</div>')
316            )
317        ];
318
319        yield 'Form hashmap' => [
320            'expected-form-hashmap.html',
321            new FormPrototypeHashmap(
322                new FormName('name'),
323                [],
324                '__NAME__',
325                new RawContents('<div>Row</div>')
326            )
327        ];
328
329        yield 'Form hashmap with values' => [
330            'expected-form-hashmap-with-values.html',
331            new FormPrototypeHashmap(
332                new FormName('name'),
333                [
334                    'first' => '0611223344',
335                    'second' => '0123456789',
336                ],
337                '__NAME__',
338                new RawContents('<div>Row</div>')
339            )
340        ];
341
342        yield 'CSRF token' => [
343            'expected-csrf-token.html',
344            new Csrf('token-123')
345        ];
346        yield 'List display' => [
347            'expected-list-display.html',
348            new ListDisplay(
349                [
350                    [
351                        'id' => 1,
352                        'description' => 'Description of 1',
353                    ],
354                    [
355                        'id' => 2,
356                        'description' => 'Description of 2',
357                        'extra' => 'extra field',
358                    ]
359                ],
360                ['id', 'description', 'extra'],
361            )
362        ];
363        yield 'Empty list display' => [
364            'expected-empty-list-display.html',
365            new ListDisplay(
366                [],
367                ['id', 'description', 'extra'],
368            )
369        ];
370        yield 'Segment display' => [
371            'expected-segment-display.html',
372            new SegmentDisplay([
373                'test' => new RawContents('value1'),
374                'test2' => new RawContents('value2'),
375            ]),
376        ];
377        yield 'Segment display, hide keys' => [
378            'expected-segment-display-no-keys.html',
379            new SegmentDisplay(
380                [
381                    new RawContents('value1'),
382                    new RawContents('value2'),
383                ],
384                showKeys: false,
385            ),
386        ];
387        yield 'Empty segment display' => [
388            'expected-empty-segment-display.html',
389            new SegmentDisplay([
390            ]),
391        ];
392        yield 'Link display' => [
393            'expected-link-display.html',
394            new LinkDisplay('this is a link', 'https://apie-lib.github.io/projectCoverage/index.html')
395        ];
396        yield 'Display true' => [
397            'expected-true-display.html',
398            new BooleanDisplay(true)
399        ];
400        yield 'Display false' => [
401            'expected-false-display.html',
402            new BooleanDisplay(false)
403        ];
404        yield 'Display null' => [
405             'expected-null-display.html',
406             new NullDisplay()
407        ];
408        $entity = new Order(OrderIdentifier::fromNative('35eadea7-b93b-4031-acaf-c9759886627d'), new OrderLineList());
409        $singleResourceActionList = new SingleResourceActionList($defaultConfiguration, new ActionList([]), $entity->getId());
410        yield 'Single resource action list' => [
411            'expected-single-resource-action-list.html',
412            $singleResourceActionList,
413        ];
414        
415        yield 'Resource details' => [
416            'expected-resource-details.html',
417            new Detail(
418                $entity,
419                $singleResourceActionList,
420                new SegmentDisplay([
421                    'test' => new RawContents('value1'),
422                    'test2' => new RawContents('value2'),
423                ]),
424            )
425        ];
426
427        yield 'Remove confirmation text' => [
428            'expected-remove-confirm.html',
429            new RemoveConfirm(new ReflectionClass(Order::class))
430        ];
431    }
432}