Completed
Push — master ( 714b6a...f9d007 )
by Narcotic
06:13
created

ShowcaseControllerTest::testRqlSelect()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 50
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 50
rs 9.3333
c 0
b 0
f 0
cc 2
eloc 35
nc 2
nop 0
1
<?php
2
/**
3
 * functional test for /hans/showcase
4
 */
5
6
namespace Graviton\CoreBundle\Tests\Controller;
7
8
use Graviton\I18nBundle\DataFixtures\MongoDB\LoadLanguageData;
9
use Graviton\TestBundle\Test\RestTestCase;
10
use Symfony\Component\HttpFoundation\Response;
11
12
/**
13
 * Functional test for /hans/showcase
14
 *
15
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
16
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
17
 * @link     http://swisscom.ch
18
 */
19
class ShowcaseControllerTest extends RestTestCase
20
{
21
    /**
22
     * @const complete content type string expected on a resouce
23
     */
24
    const CONTENT_TYPE = 'application/json; charset=UTF-8; profile=http://localhost/schema/hans/showcase/item';
25
26
    /**
27
     * @const corresponding vendorized schema mime type
28
     */
29
    const COLLECTION_TYPE = 'application/json; charset=UTF-8; profile=http://localhost/schema/hans/showcase/collection';
30
31
    /**
32
     * suppress setup client and load fixtures of parent class
33
     *
34
     * @return void
35
     */
36
    public function setUp()
37
    {
38
        $this->loadFixtures(
39
            [
40
                LoadLanguageData::class
41
            ],
42
            null,
43
            'doctrine_mongodb'
44
        );
45
    }
46
47
    /**
48
     * checks empty objects
49
     *
50
     * @return void
51
     */
52
    public function testGetEmptyObject()
53
    {
54
        $showCase = (object) [
55
            'anotherInt'            => 100,
56
            'aBoolean'              => true,
57
            'testField'             => ['en' => 'test'],
58
            'someOtherField'        => ['en' => 'other'],
59
            'contactCode'           => [
60
                'someDate'          => '2015-06-07T06:30:00+0000',
61
                'text'              => ['en' => 'text'],
62
            ],
63
            'contact'               => [
64
                'type'      => 'type',
65
                'value'     => 'value',
66
                'protocol'  => 'protocol',
67
                'uri'       => 'protocol:value',
68
            ],
69
70
            'nestedApps'            => [],
71
            'unstructuredObject'    => (object) [],
72
            'choices'               => "<>"
73
        ];
74
75
        $client = static::createRestClient();
76
        $client->post('/hans/showcase/', $showCase);
77
        $this->assertEquals(Response::HTTP_CREATED, $client->getResponse()->getStatusCode());
78
        $this->assertNull($client->getResults());
79
80
        $url = $client->getResponse()->headers->get('Location');
81
        $this->assertNotNull($url);
82
83
        $client = static::createRestClient();
84
        $client->request('GET', $url);
85
        $this->assertEquals(Response::HTTP_OK, $client->getResponse()->getStatusCode());
86
87
        $created = $client->getResults();
88
        $this->assertEquals($showCase->nestedApps, $created->nestedApps);
89
        $this->assertEquals($showCase->unstructuredObject, $created->unstructuredObject);
90
    }
91
92
    /**
93
     * see how our missing fields are explained to us
94
     *
95
     * @return void
96
     */
97
    public function testMissingFields()
98
    {
99
        $document = json_decode(
100
            file_get_contents(dirname(__FILE__).'/../resources/showcase-incomplete.json'),
101
            true
102
        );
103
104
        $client = static::createRestClient();
105
        $client->post('/hans/showcase', $document);
106
107
        $expectedErrors = [];
108
        $notNullError = new \stdClass();
109
        $notNullError->propertyPath = 'aBoolean';
110
        $notNullError->message = 'The property aBoolean is required';
111
        $expectedErrors[] = $notNullError;
112
        // test choices field (string should not be blank)
113
        $notNullErrorChoices = new \stdClass();
114
        $notNullErrorChoices->propertyPath = 'choices';
115
        $notNullErrorChoices->message = 'The property choices is required';
116
        $expectedErrors[] = $notNullErrorChoices;
117
118
        $this->assertJsonStringEqualsJsonString(
119
            json_encode($expectedErrors),
120
            json_encode($client->getResults())
121
        );
122
    }
123
124
    /**
125
     * see how our empty fields are explained to us
126
     *
127
     * @return void
128
     */
129
    public function testEmptyAllFields()
130
    {
131
        $document = [
132
            'anotherInt'  => 6555488894525,
133
            'testField'   => ['en' => 'a test string'],
134
            'aBoolean'    => '',
135
            'contactCode' => [
136
                'text'     => ['en' => 'Some Text'],
137
                'someDate' => '1984-05-01T00:00:00+0000',
138
            ],
139
            'contact'     => [
140
                'type'      => '',
141
                'value'     => '',
142
                'protocol'  => '',
143
            ],
144
        ];
145
146
        $client = static::createRestClient();
147
        $client->post('/hans/showcase', $document);
148
149
        $this->assertEquals(
150
            Response::HTTP_BAD_REQUEST,
151
            $client->getResponse()->getStatusCode()
152
        );
153
154
        $this->assertEquals(
155
            [
156
                (object) [
157
                    'propertyPath'  => 'choices',
158
                    'message'       => 'The property choices is required',
159
                ],
160
                (object) [
161
                    'propertyPath'  => 'aBoolean',
162
                    'message'       => 'String value found, but a boolean is required',
163
                ],
164
                (object) [
165
                    'propertyPath'  => 'contact.type',
166
                    'message'       => 'Must be at least 1 characters long',
167
                ],
168
                (object) [
169
                    'propertyPath'  => 'contact.protocol',
170
                    'message'       => 'Must be at least 1 characters long',
171
                ],
172
                (object) [
173
                    'propertyPath'  => 'contact.value',
174
                    'message'       => 'Must be at least 1 characters long',
175
                ]
176
            ],
177
            $client->getResults()
178
        );
179
    }
180
181
    /**
182
     * see how our empty fields are explained to us
183
     *
184
     * @return void
185
     */
186
    public function testEmptyFields()
187
    {
188
        $document = [
189
            'anotherInt'  => 6555488894525,
190
            'testField'   => ['en' => 'a test string'],
191
            'aBoolean'    => true,
192
            'contactCode' => [
193
                'text'     => ['en' => 'Some Text'],
194
                'someDate' => '1984-05-01T00:00:00+0000',
195
            ],
196
            'contact'     => [
197
                'type'      => 'abc',
198
                'value'     => '',
199
                'protocol'  => '',
200
            ],
201
        ];
202
203
        $client = static::createRestClient();
204
        $client->post('/hans/showcase', $document);
205
206
        $this->assertEquals(
207
            Response::HTTP_BAD_REQUEST,
208
            $client->getResponse()->getStatusCode()
209
        );
210
211
        $this->assertEquals(
212
            [
213
                (object) [
214
                    'propertyPath'  => 'choices',
215
                    'message'       => 'The property choices is required',
216
                ],
217
                (object) [
218
                    'propertyPath'  => 'contact.protocol',
219
                    'message'       => 'Must be at least 1 characters long',
220
                ],
221
                (object) [
222
                    'propertyPath'  => 'contact.value',
223
                    'message'       => 'Must be at least 1 characters long',
224
                ],
225
            ],
226
            $client->getResults()
227
        );
228
    }
229
230
    /**
231
     * make sure an invalid choice value is detected
232
     *
233
     * @return void
234
     */
235
    public function testWrongChoiceValue()
236
    {
237
        $payload = json_decode(file_get_contents($this->postCreationDataProvider()['minimal'][0]));
238
        $payload->choices = 'invalidChoice';
239
240
        $client = static::createRestClient();
241
        $client->post('/hans/showcase', $payload);
242
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
243
244
        $expectedErrors = [];
245
        $expectedErrors[0] = new \stdClass();
246
        $expectedErrors[0]->propertyPath = "choices";
247
        $expectedErrors[0]->message = 'Does not have a value in the enumeration ["<",">","=",">=","<=","<>"]';
248
249
        $this->assertJsonStringEqualsJsonString(
250
            json_encode($expectedErrors),
251
            json_encode($client->getResults())
252
        );
253
    }
254
255
    /**
256
     * make sure an invalid extref value is detected
257
     *
258
     * @return void
259
     */
260
    public function testWrongExtRef()
261
    {
262
        $payload = json_decode(file_get_contents($this->postCreationDataProvider()['minimal'][0]));
263
        $payload->nestedApps = [
264
            (object) ['$ref' => 'http://localhost/core/module/name'],
265
            (object) ['$ref' => 'unknown']
266
        ];
267
268
        $client = static::createRestClient();
269
        $client->post('/hans/showcase', $payload);
270
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
271
272
        $expectedErrors = [
273
            (object) [
274
                'propertyPath' => "nestedApps[0].\$ref",
275
                'message' =>
276
                    'Value "http://localhost/core/module/name" does not refer to a correct collection for this extref.'
277
            ],
278
            (object) [
279
                'propertyPath' => "nestedApps[1].\$ref",
280
                'message' =>
281
                    'Does not match the regex pattern (\/core\/app\/)([a-zA-Z0-9\-_\+\040\'\.]+)$'
282
            ]
283
        ];
284
285
        $this->assertJsonStringEqualsJsonString(
286
            json_encode($expectedErrors),
287
            json_encode($client->getResults())
288
        );
289
    }
290
291
    /**
292
     * insert various formats to see if all works as expected
293
     *
294
     * @dataProvider postCreationDataProvider
295
     *
296
     * @param string $filename filename
297
     *
298
     * @return void
299
     */
300
    public function testPost($filename)
301
    {
302
        // showcase contains some datetime fields that we need rendered as UTC in the case of this test
303
        ini_set('date.timezone', 'UTC');
304
        $document = json_decode(
305
            file_get_contents($filename),
306
            false
307
        );
308
309
        $client = static::createRestClient();
310
        $client->post('/hans/showcase/', $document);
311
        $response = $client->getResponse();
312
313
        $this->assertEquals(Response::HTTP_CREATED, $response->getStatusCode());
314
315
        $client = static::createRestClient();
316
        $client->request('GET', $response->headers->get('Location'));
317
318
        $result = $client->getResults();
319
320
        // unset id as we cannot compare and don't care
321
        $this->assertNotNull($result->id);
322
        unset($result->id);
323
324
        $this->assertJsonStringEqualsJsonString(
325
            json_encode($document),
326
            json_encode($result)
327
        );
328
    }
329
330
    /**
331
     * Provides test sets for the testPost() test.
332
     *
333
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,string[]>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
334
     */
335
    public function postCreationDataProvider()
336
    {
337
        $basePath = dirname(__FILE__).'/../resources/';
338
339
        return array(
340
            'minimal' => array($basePath.'showcase-minimal.json'),
341
            'complete' => array($basePath.'showcase-complete.json')
342
        );
343
    }
344
345
    /**
346
     * test if we can save & retrieve extrefs inside 'free form objects'
347
     *
348
     * @return void
349
     */
350
    public function testFreeFormExtRefs()
351
    {
352
        $minimalExample = $this->postCreationDataProvider()['minimal'][0];
353
354
        $document = json_decode(
355
            file_get_contents($minimalExample),
356
            false
357
        );
358
359
        $document->id = 'dynextreftest';
360
361
        // insert some refs!
362
        $document->unstructuredObject = new \stdClass();
363
        $document->unstructuredObject->testRef = new \stdClass();
364
        $document->unstructuredObject->testRef->{'$ref'} = 'http://localhost/hans/showcase/500';
365
366
        // let's go more deep..
367
        $document->unstructuredObject->go = new \stdClass();
368
        $document->unstructuredObject->go->more = new \stdClass();
369
        $document->unstructuredObject->go->more->deep = new \stdClass();
370
        $document->unstructuredObject->go->more->deep->{'$ref'} = 'http://localhost/hans/showcase/500';
371
372
        // array?
373
        $document->unstructuredObject->refArray = [];
374
        $document->unstructuredObject->refArray[0] = new \stdClass();
375
        $document->unstructuredObject->refArray[0]->{'$ref'} = 'http://localhost/core/app/dude';
376
        $document->unstructuredObject->refArray[1] = new \stdClass();
377
        $document->unstructuredObject->refArray[1]->{'$ref'} = 'http://localhost/core/app/dude2';
378
379
        $client = static::createRestClient();
380
        $client->put('/hans/showcase/'.$document->id, $document);
381
382
        $this->assertEquals(204, $client->getResponse()->getStatusCode());
383
384
        $client = static::createRestClient();
385
        $client->request('GET', '/hans/showcase/'.$document->id);
386
387
        // all still the same?
388
        $this->assertEquals($document, $client->getResults());
389
    }
390
391
    /**
392
     * are extra fields denied?
393
     *
394
     * @return void
395
     */
396
    public function testExtraFieldPost()
397
    {
398
        ini_set('date.timezone', 'UTC');
399
        $document = json_decode(
400
            file_get_contents(dirname(__FILE__).'/../resources/showcase-minimal.json'),
401
            false
402
        );
403
        $document->extraFields = "nice field";
404
        $document->anotherExtraField = "one more";
405
406
        $client = static::createRestClient();
407
        $client->post('/hans/showcase', $document);
408
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
409
410
        $expectedErrors = [];
411
        $expectedErrors[0] = new \stdClass();
412
        $expectedErrors[0]->propertyPath = "";
413
        $expectedErrors[0]->message = 'The property extraFields is not defined and the definition '.
414
            'does not allow additional properties';
415
        $expectedErrors[1] = new \stdClass();
416
        $expectedErrors[1]->propertyPath = "";
417
        $expectedErrors[1]->message = 'The property anotherExtraField is not defined and the definition '.
418
            'does not allow additional properties';
419
420
        $this->assertJsonStringEqualsJsonString(
421
            json_encode($expectedErrors),
422
            json_encode($client->getResults())
423
        );
424
    }
425
426
    /**
427
     * Test RQL select statement
428
     *
429
     * @return void
430
     */
431
    public function testRqlSelect()
432
    {
433
        $this->loadFixtures(
434
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
435
            null,
436
            'doctrine_mongodb'
437
        );
438
439
        $filtred = json_decode(
440
            file_get_contents(dirname(__FILE__).'/../resources/showcase-rql-select-filtred.json'),
441
            false
442
        );
443
444
        $fields = [
445
            'someFloatyDouble',
446
            'contact',
447
            'contactCode.text',
448
            'unstructuredObject.booleanField',
449
            'unstructuredObject.hashField.someField',
450
            'unstructuredObject.nestedArrayField.anotherField',
451
            'nestedCustomers',
452
            'choices'
453
        ];
454
        $rqlSelect = 'select('.implode(',', array_map([$this, 'encodeRqlString'], $fields)).')';
455
456
        $client = static::createRestClient();
457
        $client->request('GET', '/hans/showcase/?'.$rqlSelect);
458
459
        /* expect empty arrays */
460
        $filtred = array_map(
461
            function ($entry) {
462
                $entry->contacts = [];
463
                $entry->nestedArray = [];
464
                $entry->nestedApps = [];
465
                return $entry;
466
            },
467
            $filtred
468
        );
469
470
        $this->assertEquals($filtred, $client->getResults());
471
472
        foreach ([
473
                     '500' => $filtred[0],
474
                     '600' => $filtred[1],
475
                 ] as $id => $item) {
476
            $client = static::createRestClient();
477
            $client->request('GET', '/hans/showcase/'.$id.'?'.$rqlSelect);
478
            $this->assertEquals($item, $client->getResults());
479
        }
480
    }
481
482
    /**
483
     * Test to see if we can do like() searches on identifier fields
484
     *
485
     * @return void
486
     */
487
    public function testLikeSearchOnIdentifierField()
488
    {
489
        // Load fixtures
490
        $this->loadFixtures(
491
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
492
            null,
493
            'doctrine_mongodb'
494
        );
495
496
        $client = static::createRestClient();
497
        $client->request('GET', '/hans/showcase/?like(id,5*)');
498
499
        // we should only get 1 ;-)
500
        $this->assertEquals(1, count($client->getResults()));
501
502
        $client = static::createRestClient();
503
        $client->request('GET', '/hans/showcase/?like(id,*0)');
504
505
        // this should get both
506
        $this->assertEquals(2, count($client->getResults()));
507
    }
508
509
    /**
510
     * Test PATCH for deep nested attribute
511
     *
512
     * @return void
513
     */
514 View Code Duplication
    public function testPatchDeepNestedProperty()
515
    {
516
        // Load fixtures
517
        $this->loadFixtures(
518
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
519
            null,
520
            'doctrine_mongodb'
521
        );
522
523
        // Apply PATCH request
524
        $client = static::createRestClient();
525
        $patchJson = json_encode(
526
            [
527
                [
528
                    'op' => 'replace',
529
                    'path' => '/unstructuredObject/hashField/anotherField',
530
                    'value' => 'changed nested hash field with patch'
531
                ]
532
            ]
533
        );
534
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
535
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
536
537
        // Get changed showcase
538
        $client = static::createRestClient();
539
        $client->request('GET', '/hans/showcase/500');
540
541
        $result = $client->getResults();
542
        $this->assertEquals(
543
            'changed nested hash field with patch',
544
            $result->unstructuredObject->hashField->anotherField
545
        );
546
    }
547
548
    /**
549
     * Test success PATCH method - response headers contains link to resource
550
     *
551
     * @return void
552
     */
553
    public function testPatchSuccessResponseHeaderContainsResourceLink()
554
    {
555
        // Load fixtures
556
        $this->loadFixtures(
557
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
558
            null,
559
            'doctrine_mongodb'
560
        );
561
562
        // Apply PATCH request
563
        $client = static::createRestClient();
564
        $patchJson = json_encode(
565
            [
566
                [
567
                    'op' => 'replace',
568
                    'path' => '/testField/en',
569
                    'value' => 'changed value'
570
                ]
571
            ]
572
        );
573
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
574
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
575
576
        $this->assertEquals(
577
            '/hans/showcase/500',
578
            $client->getResponse()->headers->get('Content-Location')
579
        );
580
    }
581
582
    /**
583
     * Test PATCH method - remove/change ID not allowed
584
     *
585
     * @return void
586
     */
587
    public function testPatchRemoveAndChangeIdNotAllowed()
588
    {
589
        // Load fixtures
590
        $this->loadFixtures(
591
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
592
            null,
593
            'doctrine_mongodb'
594
        );
595
596
        // Apply PATCH request
597
        $client = static::createRestClient();
598
        $patchJson = json_encode(
599
            [
600
                [
601
                    'op' => 'remove',
602
                    'path' => '/id'
603
                ]
604
            ]
605
        );
606
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
607
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
608
    }
609
610
    /**
611
     * Test PATCH: add property to free object structure
612
     *
613
     * @return void
614
     */
615 View Code Duplication
    public function testPatchAddPropertyToFreeObject()
616
    {
617
        // Load fixtures
618
        $this->loadFixtures(
619
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
620
            null,
621
            'doctrine_mongodb'
622
        );
623
624
        // Apply PATCH request
625
        $client = static::createRestClient();
626
        $patchJson = json_encode(
627
            [
628
                [
629
                    'op' => 'add',
630
                    'path' => '/unstructuredObject/hashField/newAddedField',
631
                    'value' => 'new field value'
632
                ]
633
            ]
634
        );
635
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
636
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
637
638
        // Get changed showcase
639
        $client = static::createRestClient();
640
        $client->request('GET', '/hans/showcase/500');
641
642
        $result = $client->getResults();
643
        $this->assertEquals(
644
            'new field value',
645
            $result->unstructuredObject->hashField->newAddedField
646
        );
647
    }
648
649
    /**
650
     * Test PATCH for $ref attribute
651
     *
652
     * @return void
653
     * @incomplete
654
     */
655
    public function testApplyPatchForRefAttribute()
656
    {
657
        // Load fixtures
658
        $this->loadFixtures(
659
            [
660
                'GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'
661
            ],
662
            null,
663
            'doctrine_mongodb'
664
        );
665
666
        // Apply PATCH request
667
        $client = static::createRestClient();
668
        $patchJson = json_encode(
669
            [
670
                [
671
                    'op' => 'replace',
672
                    'path' => '/nestedApps/0',
673
                    'value' => [
674
                        '$ref' => 'http://localhost/core/app/admin'
675
                    ]
676
                ]
677
            ]
678
        );
679
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
680
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
681
682
        // Check patched result
683
        $client = static::createRestClient();
684
        $client->request('GET', '/hans/showcase/500');
685
686
        $result = $client->getResults();
687
        $this->assertEquals(
688
            'http://localhost/core/app/admin',
689
            $result->nestedApps[0]->{'$ref'}
690
        );
691
    }
692
693
    /**
694
     * Test PATCH: apply patch which results to invalid Showcase schema
695
     *
696
     * @return void
697
     */
698
    public function testPatchToInvalidShowcase()
699
    {
700
        // Load fixtures
701
        $this->loadFixtures(
702
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
703
            null,
704
            'doctrine_mongodb'
705
        );
706
707
        // Apply PATCH request, remove required field
708
        $client = static::createRestClient();
709
        $patchJson = json_encode(
710
            [
711
                [
712
                    'op' => 'remove',
713
                    'path' => '/anotherInt'
714
                ]
715
            ]
716
        );
717
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
718
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
719
720
        // Check that Showcase has not been changed
721
        $client = static::createRestClient();
722
        $client->request('GET', '/hans/showcase/500');
723
724
        $result = $client->getResults();
725
        $this->assertObjectHasAttribute('anotherInt', $result);
726
    }
727
728
    /**
729
     * Test PATCH: remove element from array
730
     *
731
     * @return void
732
     */
733 View Code Duplication
    public function testRemoveFromArrayPatch()
734
    {
735
        // Load fixtures
736
        $this->loadFixtures(
737
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
738
            null,
739
            'doctrine_mongodb'
740
        );
741
742
        // Apply PATCH request, remove nested app, initially there are 2 apps
743
        $client = static::createRestClient();
744
        $patchJson = json_encode(
745
            [
746
                [
747
                    'op' => 'remove',
748
                    'path' => '/nestedApps/0'
749
                ]
750
            ]
751
        );
752
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
753
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
754
755
        // Check patched result
756
        $client = static::createRestClient();
757
        $client->request('GET', '/hans/showcase/500');
758
759
        $result = $client->getResults();
760
        $this->assertEquals(1, count($result->nestedApps));
761
        $this->assertEquals('http://localhost/core/app/admin', $result->nestedApps[0]->{'$ref'});
762
    }
763
764
    /**
765
     * Test PATCH: add new element to array
766
     *
767
     * @return void
768
     */
769
    public function testAddElementToSpecificIndexInArrayPatch()
770
    {
771
        // Load fixtures
772
        $this->loadFixtures(
773
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
774
            null,
775
            'doctrine_mongodb'
776
        );
777
778
        // Apply PATCH request, add new element
779
        $client = static::createRestClient();
780
        $newElement = ['name' => 'element three'];
781
        $patchJson = json_encode(
782
            [
783
                [
784
                    'op' => 'add',
785
                    'path' => '/nestedArray/1',
786
                    'value' => $newElement
787
                ]
788
            ]
789
        );
790
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
791
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
792
793
        // Check patched result
794
        $client = static::createRestClient();
795
        $client->request('GET', '/hans/showcase/500');
796
797
        $result = $client->getResults();
798
        $this->assertEquals(3, count($result->nestedArray));
799
        $this->assertJsonStringEqualsJsonString(
800
            json_encode($newElement),
801
            json_encode($result->nestedArray[1])
802
        );
803
    }
804
805
    /**
806
     * Test PATCH: add complex object App to array
807
     *
808
     * @group ref
809
     * @return void
810
     */
811 View Code Duplication
    public function testPatchAddComplexObjectToSpecificIndexInArray()
812
    {
813
        // Load fixtures
814
        $this->loadFixtures(
815
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
816
            null,
817
            'doctrine_mongodb'
818
        );
819
820
        // Apply PATCH request, add new element
821
        $client = static::createRestClient();
822
        $newApp = ['$ref' => 'http://localhost/core/app/admin'];
823
        $patchJson = json_encode(
824
            [
825
                [
826
                    'op' => 'add',
827
                    'path' => '/nestedApps/0',
828
                    'value' => $newApp
829
                ]
830
            ]
831
        );
832
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
833
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
834
835
        // Check patched result
836
        $client = static::createRestClient();
837
        $client->request('GET', '/hans/showcase/500');
838
839
        $result = $client->getResults();
840
        $this->assertEquals(3, count($result->nestedApps));
841
        $this->assertEquals(
842
            'http://localhost/core/app/admin',
843
            $result->nestedApps[0]->{'$ref'}
844
        );
845
    }
846
847
    /**
848
     * Test PATCH: add complex object App to array
849
     *
850
     * @group ref
851
     * @return void
852
     */
853 View Code Duplication
    public function testPatchAddComplexObjectToTheEndOfArray()
854
    {
855
        // Load fixtures
856
        $this->loadFixtures(
857
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
858
            null,
859
            'doctrine_mongodb'
860
        );
861
862
        // Apply PATCH request, add new element
863
        $client = static::createRestClient();
864
        $newApp = ['$ref' => 'http://localhost/core/app/test'];
865
        $patchJson = json_encode(
866
            [
867
                [
868
                    'op' => 'add',
869
                    'path' => '/nestedApps/-',
870
                    'value' => $newApp
871
                ]
872
            ]
873
        );
874
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
875
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
876
877
        // Check patched result
878
        $client = static::createRestClient();
879
        $client->request('GET', '/hans/showcase/500');
880
881
        $result = $client->getResults();
882
        $this->assertEquals(3, count($result->nestedApps));
883
        $this->assertEquals(
884
            'http://localhost/core/app/test',
885
            $result->nestedApps[2]->{'$ref'}
886
        );
887
    }
888
889
    /**
890
     * Test PATCH: test operation to undefined index
891
     *
892
     * @group ref
893
     * @return void
894
     */
895
    public function testPatchTestOperationToUndefinedIndexThrowsException()
896
    {
897
        // Load fixtures
898
        $this->loadFixtures(
899
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
900
            null,
901
            'doctrine_mongodb'
902
        );
903
904
        // Apply PATCH request, add new element
905
        $client = static::createRestClient();
906
        $newApp = ['ref' => 'http://localhost/core/app/test'];
907
        $patchJson = json_encode(
908
            [
909
                [
910
                    'op' => 'test',
911
                    'path' => '/nestedApps/9',
912
                    'value' => $newApp
913
                ]
914
            ]
915
        );
916
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
917
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
918
    }
919
920
    /**
921
     * Test PATCH: add complex object App to array
922
     *
923
     * @group ref
924
     * @return void
925
     */
926
    public function testPatchAddElementToUndefinedIndexResponseAsBadRequest()
927
    {
928
        // Load fixtures
929
        $this->loadFixtures(
930
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
931
            null,
932
            'doctrine_mongodb'
933
        );
934
935
        // Apply PATCH request, add new element
936
        $client = static::createRestClient();
937
        $newApp = ['ref' => 'http://localhost/core/app/admin'];
938
        $patchJson = json_encode(
939
            [
940
                [
941
                    'op' => 'add',
942
                    'path' => '/nestedApps/9',
943
                    'value' => $newApp
944
                ]
945
            ]
946
        );
947
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
948
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
949
950
        // Check that patched document not changed
951
        $client = static::createRestClient();
952
        $client->request('GET', '/hans/showcase/500');
953
954
        $result = $client->getResults();
955
        $this->assertEquals(2, count($result->nestedApps));
956
    }
957
958
    /**
959
     * Encode string value in RQL
960
     *
961
     * @param string $value String value
962
     * @return string
963
     */
964 View Code Duplication
    private function encodeRqlString($value)
965
    {
966
        return strtr(
967
            rawurlencode($value),
968
            [
969
                '-' => '%2D',
970
                '_' => '%5F',
971
                '.' => '%2E',
972
                '~' => '%7E',
973
            ]
974
        );
975
    }
976
977
    /**
978
     * Trigger a 301 Status code
979
     *
980
     * @param string $url         requested url
981
     * @param string $redirectUrl redirected url
982
     * @dataProvider rqlDataProvider
983
     * @return void
984
     */
985 View Code Duplication
    public function testTrigger301($url, $redirectUrl)
986
    {
987
        $client = static::createRestClient();
988
        $client->request('GET', $url);
989
        $this->assertEquals(301, $client->getResponse()->getStatusCode());
990
        $this->assertEquals($redirectUrl, $client->getResponse()->headers->get('Location'));
991
    }
992
993
    /**
994
     * Provides urls for the testTrigger301() test.
995
     *
996
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array<string,string>>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
997
     */
998
    public function rqlDataProvider()
999
    {
1000
        return [
1001
            'rql' => ['url' => '/hans/showcase?id=blah' , 'redirect_url' => 'http://localhost/hans/showcase/?id=blah'],
1002
            'noRql' => ['url' => '/hans/showcase' , 'redirect_url' => 'http://localhost/hans/showcase/']
1003
        ];
1004
    }
1005
1006
    /**
1007
     * Here we test the client expectation in "id" property exposing in the json schema.
1008
     *
1009
     * They want
1010
     * * "id" of an extref object should *not* be described/present in schema
1011
     * * "id" of others, including embedded objects, *should* be described/present in schema
1012
     *
1013
     * @return void
1014
     */
1015
    public function testCorrectIdExposingInSchema()
1016
    {
1017
        // get the schema
1018
        $client = static::createRestClient();
1019
        $client->request('GET', '/schema/hans/showcase/item');
1020
1021
        $schema = $client->getResults();
1022
1023
        // make sure we have an extref field here
1024
        $this->assertEquals('extref', $schema->properties->nestedApps->items->properties->{'$ref'}->format);
1025
        // and that 'id' is not there
1026
        $this->assertObjectNotHasAttribute('id', $schema->properties->nestedApps->items->properties);
1027
1028
        // embed case - check the embedded 'contactCode'
1029
        $this->assertStringEndsWith('Embedded', $schema->properties->contactCode->{'x-documentClass'});
1030
        $this->assertObjectHasAttribute('id', $schema->properties->contactCode->properties);
1031
    }
1032
1033
    /**
1034
     * test finding of showcases by ref
1035
     *
1036
     * @dataProvider findByExtrefProvider
1037
     *
1038
     * @param string  $field which reference to search in
1039
     * @param mixed   $url   ref to search for
1040
     * @param integer $count number of results to expect
1041
     *
1042
     * @return void
1043
     */
1044
    public function testFindByExtref($field, $url, $count)
1045
    {
1046
        $this->loadFixtures(
1047
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
1048
            null,
1049
            'doctrine_mongodb'
1050
        );
1051
1052
        $url = sprintf(
1053
            '/hans/showcase/?%s=%s',
1054
            $this->encodeRqlString($field),
1055
            $this->encodeRqlString($url)
1056
        );
1057
1058
        $client = static::createRestClient();
1059
        $client->request('GET', $url);
1060
        $this->assertEquals(Response::HTTP_OK, $client->getResponse()->getStatusCode());
1061
        $this->assertCount($count, $client->getResults());
1062
    }
1063
1064
    /**
1065
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array<string|integer>>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
1066
     */
1067 View Code Duplication
    public function findByExtrefProvider()
1068
    {
1069
        return [
1070
            'find a linked record when searching for "tablet" ref by array field' => [
1071
                'nestedApps.0.$ref',
1072
                'http://localhost/core/app/tablet',
1073
                1
1074
            ],
1075
            'find a linked record when searching for "admin" ref by array field' => [
1076
                'nestedApps.0.$ref',
1077
                'http://localhost/core/app/admin',
1078
                1
1079
            ],
1080
            'find nothing when searching for inextistant (and unlinked) ref by array field' => [
1081
                'nestedApps.0.$ref',
1082
                'http://localhost/core/app/inexistant',
1083
                0
1084
            ],
1085
            'return nothing when searching with incomplete ref by array field' => [
1086
                'nestedApps.0.$ref',
1087
                'http://localhost/core/app',
1088
                0
1089
            ],
1090
        ];
1091
    }
1092
}
1093