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