Completed
Push — feature/other-validation ( 1442c4...18a759 )
by Narcotic
64:54
created

testPatchAddComplexObjectToSpecificIndexInArray()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 35
Code Lines 20

Duplication

Lines 35
Ratio 100 %

Importance

Changes 0
Metric Value
dl 35
loc 35
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 20
nc 1
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.uri',
166
                    'message'       => 'The property uri is required',
167
                ],
168
                (object) [
169
                    'propertyPath'  => 'contact.type',
170
                    'message'       => 'Must be at least 1 characters long',
171
                ],
172
                (object) [
173
                    'propertyPath'  => 'contact.protocol',
174
                    'message'       => 'Must be at least 1 characters long',
175
                ],
176
                (object) [
177
                    'propertyPath'  => 'contact.value',
178
                    'message'       => 'Must be at least 1 characters long',
179
                ]
180
            ],
181
            $client->getResults()
182
        );
183
    }
184
185
    /**
186
     * see how our empty fields are explained to us
187
     *
188
     * @return void
189
     */
190
    public function testEmptyFields()
191
    {
192
        $document = [
193
            'anotherInt'  => 6555488894525,
194
            'testField'   => ['en' => 'a test string'],
195
            'aBoolean'    => true,
196
            'contactCode' => [
197
                'text'     => ['en' => 'Some Text'],
198
                'someDate' => '1984-05-01T00:00:00+0000',
199
            ],
200
            'contact'     => [
201
                'type'      => 'abc',
202
                'value'     => '',
203
                'protocol'  => '',
204
            ],
205
        ];
206
207
        $client = static::createRestClient();
208
        $client->post('/hans/showcase', $document);
209
210
        $this->assertEquals(
211
            Response::HTTP_BAD_REQUEST,
212
            $client->getResponse()->getStatusCode()
213
        );
214
215
        $this->assertEquals(
216
            [
217
                (object) [
218
                    'propertyPath'  => 'choices',
219
                    'message'       => 'The property choices is required',
220
                ],
221
                (object) [
222
                    'propertyPath'  => 'contact.uri',
223
                    'message'       => 'The property uri is required',
224
                ],
225
                (object) [
226
                    'propertyPath'  => 'contact.protocol',
227
                    'message'       => 'Must be at least 1 characters long',
228
                ],
229
                (object) [
230
                    'propertyPath'  => 'contact.value',
231
                    'message'       => 'Must be at least 1 characters long',
232
                ],
233
            ],
234
            $client->getResults()
235
        );
236
    }
237
238
    /**
239
     * make sure an invalid choice value is detected
240
     *
241
     * @return void
242
     */
243
    public function testWrongChoiceValue()
244
    {
245
        $payload = json_decode(file_get_contents($this->postCreationDataProvider()['minimal'][0]));
246
        $payload->choices = 'invalidChoice';
247
248
        $client = static::createRestClient();
249
        $client->post('/hans/showcase', $payload);
250
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
251
252
        $expectedErrors = [];
253
        $expectedErrors[0] = new \stdClass();
254
        $expectedErrors[0]->propertyPath = "choices";
255
        $expectedErrors[0]->message = 'Does not have a value in the enumeration ["<",">","=",">=","<=","<>"]';
256
257
        $this->assertJsonStringEqualsJsonString(
258
            json_encode($expectedErrors),
259
            json_encode($client->getResults())
260
        );
261
    }
262
263
    /**
264
     * insert various formats to see if all works as expected
265
     *
266
     * @dataProvider postCreationDataProvider
267
     *
268
     * @param string $filename filename
269
     *
270
     * @return void
271
     */
272
    public function testPost($filename)
273
    {
274
        // showcase contains some datetime fields that we need rendered as UTC in the case of this test
275
        ini_set('date.timezone', 'UTC');
276
        $document = json_decode(
277
            file_get_contents($filename),
278
            false
279
        );
280
281
        $client = static::createRestClient();
282
        $client->post('/hans/showcase/', $document);
283
        $response = $client->getResponse();
284
285
        $this->assertEquals(Response::HTTP_CREATED, $response->getStatusCode());
286
287
        $client = static::createRestClient();
288
        $client->request('GET', $response->headers->get('Location'));
289
290
        $result = $client->getResults();
291
292
        // unset id as we cannot compare and don't care
293
        $this->assertNotNull($result->id);
294
        unset($result->id);
295
296
        $this->assertJsonStringEqualsJsonString(
297
            json_encode($document),
298
            json_encode($result)
299
        );
300
    }
301
302
    /**
303
     * Provides test sets for the testPost() test.
304
     *
305
     * @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...
306
     */
307
    public function postCreationDataProvider()
308
    {
309
        $basePath = dirname(__FILE__).'/../resources/';
310
311
        return array(
312
            'minimal' => array($basePath.'showcase-minimal.json'),
313
            'complete' => array($basePath.'showcase-complete.json')
314
        );
315
    }
316
317
    /**
318
     * test if we can save & retrieve extrefs inside 'free form objects'
319
     *
320
     * @return void
321
     */
322
    public function testFreeFormExtRefs()
323
    {
324
        $minimalExample = $this->postCreationDataProvider()['minimal'][0];
325
326
        $document = json_decode(
327
            file_get_contents($minimalExample),
328
            false
329
        );
330
331
        $document->id = 'dynextreftest';
332
333
        // insert some refs!
334
        $document->unstructuredObject = new \stdClass();
335
        $document->unstructuredObject->testRef = new \stdClass();
336
        $document->unstructuredObject->testRef->{'$ref'} = 'http://localhost/hans/showcase/500';
337
338
        // let's go more deep..
339
        $document->unstructuredObject->go = new \stdClass();
340
        $document->unstructuredObject->go->more = new \stdClass();
341
        $document->unstructuredObject->go->more->deep = new \stdClass();
342
        $document->unstructuredObject->go->more->deep->{'$ref'} = 'http://localhost/hans/showcase/500';
343
344
        // array?
345
        $document->unstructuredObject->refArray = [];
346
        $document->unstructuredObject->refArray[0] = new \stdClass();
347
        $document->unstructuredObject->refArray[0]->{'$ref'} = 'http://localhost/core/app/dude';
348
        $document->unstructuredObject->refArray[1] = new \stdClass();
349
        $document->unstructuredObject->refArray[1]->{'$ref'} = 'http://localhost/core/app/dude2';
350
351
        $client = static::createRestClient();
352
        $client->put('/hans/showcase/'.$document->id, $document);
353
354
        $this->assertEquals(204, $client->getResponse()->getStatusCode());
355
356
        $client = static::createRestClient();
357
        $client->request('GET', '/hans/showcase/'.$document->id);
358
359
        // all still the same?
360
        $this->assertEquals($document, $client->getResults());
361
    }
362
363
    /**
364
     * are extra fields denied?
365
     *
366
     * @return void
367
     */
368
    public function testExtraFieldPost()
369
    {
370
        ini_set('date.timezone', 'UTC');
371
        $document = json_decode(
372
            file_get_contents(dirname(__FILE__).'/../resources/showcase-minimal.json'),
373
            false
374
        );
375
        $document->extraFields = "nice field";
376
        $document->anotherExtraField = "one more";
377
378
        $client = static::createRestClient();
379
        $client->post('/hans/showcase', $document);
380
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
381
382
        $expectedErrors = [];
383
        $expectedErrors[0] = new \stdClass();
384
        $expectedErrors[0]->propertyPath = "";
385
        $expectedErrors[0]->message = 'The property extraFields is not defined and the definition '.
386
            'does not allow additional properties';
387
        $expectedErrors[1] = new \stdClass();
388
        $expectedErrors[1]->propertyPath = "";
389
        $expectedErrors[1]->message = 'The property anotherExtraField is not defined and the definition '.
390
            'does not allow additional properties';
391
392
        $this->assertJsonStringEqualsJsonString(
393
            json_encode($expectedErrors),
394
            json_encode($client->getResults())
395
        );
396
    }
397
398
    /**
399
     * Test RQL select statement
400
     *
401
     * @return void
402
     */
403
    public function testRqlSelect()
404
    {
405
        $this->loadFixtures(
406
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
407
            null,
408
            'doctrine_mongodb'
409
        );
410
411
        $filtred = json_decode(
412
            file_get_contents(dirname(__FILE__).'/../resources/showcase-rql-select-filtred.json'),
413
            false
414
        );
415
416
        $fields = [
417
            'someFloatyDouble',
418
            'contact.uri',
419
            'contactCode.text.en',
420
            'unstructuredObject.booleanField',
421
            'unstructuredObject.hashField.someField',
422
            'unstructuredObject.nestedArrayField.anotherField',
423
            'nestedCustomers.$ref',
424
            'choices'
425
        ];
426
        $rqlSelect = 'select('.implode(',', array_map([$this, 'encodeRqlString'], $fields)).')';
427
428
        $client = static::createRestClient();
429
        $client->request('GET', '/hans/showcase/?'.$rqlSelect);
430
431
        $this->assertEquals($filtred, $client->getResults());
432
433
434
        foreach ([
435
                     '500' => $filtred[0],
436
                     '600' => $filtred[1],
437
                 ] as $id => $item) {
438
            $client = static::createRestClient();
439
            $client->request('GET', '/hans/showcase/'.$id.'?'.$rqlSelect);
440
            $this->assertEquals($item, $client->getResults());
441
        }
442
    }
443
444
    /**
445
     * Test to see if we can do like() searches on identifier fields
446
     *
447
     * @return void
448
     */
449
    public function testLikeSearchOnIdentifierField()
450
    {
451
        // Load fixtures
452
        $this->loadFixtures(
453
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
454
            null,
455
            'doctrine_mongodb'
456
        );
457
458
        $client = static::createRestClient();
459
        $client->request('GET', '/hans/showcase/?like(id,5*)');
460
461
        // we should only get 1 ;-)
462
        $this->assertEquals(1, count($client->getResults()));
463
464
        $client = static::createRestClient();
465
        $client->request('GET', '/hans/showcase/?like(id,*0)');
466
467
        // this should get both
468
        $this->assertEquals(2, count($client->getResults()));
469
    }
470
471
    /**
472
     * Test PATCH for deep nested attribute
473
     *
474
     * @return void
475
     */
476 View Code Duplication
    public function testPatchDeepNestedProperty()
477
    {
478
        // Load fixtures
479
        $this->loadFixtures(
480
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
481
            null,
482
            'doctrine_mongodb'
483
        );
484
485
        // Apply PATCH request
486
        $client = static::createRestClient();
487
        $patchJson = json_encode(
488
            [
489
                [
490
                    'op' => 'replace',
491
                    'path' => '/unstructuredObject/hashField/anotherField',
492
                    'value' => 'changed nested hash field with patch'
493
                ]
494
            ]
495
        );
496
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
497
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
498
499
        // Get changed showcase
500
        $client = static::createRestClient();
501
        $client->request('GET', '/hans/showcase/500');
502
503
        $result = $client->getResults();
504
        $this->assertEquals(
505
            'changed nested hash field with patch',
506
            $result->unstructuredObject->hashField->anotherField
507
        );
508
    }
509
510
    /**
511
     * Test success PATCH method - response headers contains link to resource
512
     *
513
     * @return void
514
     */
515
    public function testPatchSuccessResponseHeaderContainsResourceLink()
516
    {
517
        // Load fixtures
518
        $this->loadFixtures(
519
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
520
            null,
521
            'doctrine_mongodb'
522
        );
523
524
        // Apply PATCH request
525
        $client = static::createRestClient();
526
        $patchJson = json_encode(
527
            [
528
                [
529
                    'op' => 'replace',
530
                    'path' => '/testField/en',
531
                    'value' => 'changed value'
532
                ]
533
            ]
534
        );
535
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
536
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
537
538
        $this->assertEquals(
539
            '/hans/showcase/500',
540
            $client->getResponse()->headers->get('Content-Location')
541
        );
542
    }
543
544
    /**
545
     * Test PATCH method - remove/change ID not allowed
546
     *
547
     * @return void
548
     */
549
    public function testPatchRemoveAndChangeIdNotAllowed()
550
    {
551
        // Load fixtures
552
        $this->loadFixtures(
553
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
554
            null,
555
            'doctrine_mongodb'
556
        );
557
558
        // Apply PATCH request
559
        $client = static::createRestClient();
560
        $patchJson = json_encode(
561
            [
562
                [
563
                    'op' => 'remove',
564
                    'path' => '/id'
565
                ]
566
            ]
567
        );
568
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
569
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
570
    }
571
572
    /**
573
     * Test PATCH: add property to free object structure
574
     *
575
     * @return void
576
     */
577 View Code Duplication
    public function testPatchAddPropertyToFreeObject()
578
    {
579
        // Load fixtures
580
        $this->loadFixtures(
581
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
582
            null,
583
            'doctrine_mongodb'
584
        );
585
586
        // Apply PATCH request
587
        $client = static::createRestClient();
588
        $patchJson = json_encode(
589
            [
590
                [
591
                    'op' => 'add',
592
                    'path' => '/unstructuredObject/hashField/newAddedField',
593
                    'value' => 'new field value'
594
                ]
595
            ]
596
        );
597
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
598
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
599
600
        // Get changed showcase
601
        $client = static::createRestClient();
602
        $client->request('GET', '/hans/showcase/500');
603
604
        $result = $client->getResults();
605
        $this->assertEquals(
606
            'new field value',
607
            $result->unstructuredObject->hashField->newAddedField
608
        );
609
    }
610
611
    /**
612
     * Test PATCH for $ref attribute
613
     *
614
     * @return void
615
     * @incomplete
616
     */
617 View Code Duplication
    public function testApplyPatchForRefAttribute()
618
    {
619
        // Load fixtures
620
        $this->loadFixtures(
621
            [
622
                'GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'
623
            ],
624
            null,
625
            'doctrine_mongodb'
626
        );
627
628
        // Apply PATCH request
629
        $client = static::createRestClient();
630
        $patchJson = json_encode(
631
            [
632
                [
633
                    'op' => 'replace',
634
                    'path' => '/nestedApps/0/$ref',
635
                    'value' => 'http://localhost/core/app/admin'
636
                ]
637
            ]
638
        );
639
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
640
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
641
642
        // Check patched result
643
        $client = static::createRestClient();
644
        $client->request('GET', '/hans/showcase/500');
645
646
        $result = $client->getResults();
647
        $this->assertEquals(
648
            'http://localhost/core/app/admin',
649
            $result->nestedApps[0]->{'$ref'}
650
        );
651
    }
652
653
    /**
654
     * Test PATCH: apply patch which results to invalid Showcase schema
655
     *
656
     * @return void
657
     */
658
    public function testPatchToInvalidShowcase()
659
    {
660
        // Load fixtures
661
        $this->loadFixtures(
662
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
663
            null,
664
            'doctrine_mongodb'
665
        );
666
667
        // Apply PATCH request, remove required field
668
        $client = static::createRestClient();
669
        $patchJson = json_encode(
670
            [
671
                [
672
                    'op' => 'remove',
673
                    'path' => '/anotherInt'
674
                ]
675
            ]
676
        );
677
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
678
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
679
680
        // Check that Showcase has not been changed
681
        $client = static::createRestClient();
682
        $client->request('GET', '/hans/showcase/500');
683
684
        $result = $client->getResults();
685
        $this->assertObjectHasAttribute('anotherInt', $result);
686
    }
687
688
    /**
689
     * Test PATCH: remove element from array
690
     *
691
     * @return void
692
     */
693 View Code Duplication
    public function testRemoveFromArrayPatch()
694
    {
695
        // Load fixtures
696
        $this->loadFixtures(
697
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
698
            null,
699
            'doctrine_mongodb'
700
        );
701
702
        // Apply PATCH request, remove nested app, initially there are 2 apps
703
        $client = static::createRestClient();
704
        $patchJson = json_encode(
705
            [
706
                [
707
                    'op' => 'remove',
708
                    'path' => '/nestedApps/0'
709
                ]
710
            ]
711
        );
712
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
713
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
714
715
        // Check patched result
716
        $client = static::createRestClient();
717
        $client->request('GET', '/hans/showcase/500');
718
719
        $result = $client->getResults();
720
        $this->assertEquals(1, count($result->nestedApps));
721
        $this->assertEquals('http://localhost/core/app/admin', $result->nestedApps[0]->{'$ref'});
722
    }
723
724
    /**
725
     * Test PATCH: add new element to array
726
     *
727
     * @return void
728
     */
729
    public function testAddElementToSpecificIndexInArrayPatch()
730
    {
731
        // Load fixtures
732
        $this->loadFixtures(
733
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
734
            null,
735
            'doctrine_mongodb'
736
        );
737
738
        // Apply PATCH request, add new element
739
        $client = static::createRestClient();
740
        $newElement = ['name' => 'element three'];
741
        $patchJson = json_encode(
742
            [
743
                [
744
                    'op' => 'add',
745
                    'path' => '/nestedArray/1',
746
                    'value' => $newElement
747
                ]
748
            ]
749
        );
750
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
751
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
752
753
        // Check patched result
754
        $client = static::createRestClient();
755
        $client->request('GET', '/hans/showcase/500');
756
757
        $result = $client->getResults();
758
        $this->assertEquals(3, count($result->nestedArray));
759
        $this->assertJsonStringEqualsJsonString(
760
            json_encode($newElement),
761
            json_encode($result->nestedArray[1])
762
        );
763
    }
764
765
    /**
766
     * Test PATCH: add complex object App to array
767
     *
768
     * @group ref
769
     * @return void
770
     */
771 View Code Duplication
    public function testPatchAddComplexObjectToSpecificIndexInArray()
772
    {
773
        // Load fixtures
774
        $this->loadFixtures(
775
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
776
            null,
777
            'doctrine_mongodb'
778
        );
779
780
        // Apply PATCH request, add new element
781
        $client = static::createRestClient();
782
        $newApp = ['$ref' => 'http://localhost/core/app/admin'];
783
        $patchJson = json_encode(
784
            [
785
                [
786
                    'op' => 'add',
787
                    'path' => '/nestedApps/0',
788
                    'value' => $newApp
789
                ]
790
            ]
791
        );
792
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
793
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
794
795
        // Check patched result
796
        $client = static::createRestClient();
797
        $client->request('GET', '/hans/showcase/500');
798
799
        $result = $client->getResults();
800
        $this->assertEquals(3, count($result->nestedApps));
801
        $this->assertEquals(
802
            'http://localhost/core/app/admin',
803
            $result->nestedApps[0]->{'$ref'}
804
        );
805
    }
806
807
    /**
808
     * Test PATCH: add complex object App to array
809
     *
810
     * @group ref
811
     * @return void
812
     */
813 View Code Duplication
    public function testPatchAddComplexObjectToTheEndOfArray()
814
    {
815
        // Load fixtures
816
        $this->loadFixtures(
817
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
818
            null,
819
            'doctrine_mongodb'
820
        );
821
822
        // Apply PATCH request, add new element
823
        $client = static::createRestClient();
824
        $newApp = ['$ref' => 'http://localhost/core/app/test'];
825
        $patchJson = json_encode(
826
            [
827
                [
828
                    'op' => 'add',
829
                    'path' => '/nestedApps/-',
830
                    'value' => $newApp
831
                ]
832
            ]
833
        );
834
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
835
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
836
837
        // Check patched result
838
        $client = static::createRestClient();
839
        $client->request('GET', '/hans/showcase/500');
840
841
        $result = $client->getResults();
842
        $this->assertEquals(3, count($result->nestedApps));
843
        $this->assertEquals(
844
            'http://localhost/core/app/test',
845
            $result->nestedApps[2]->{'$ref'}
846
        );
847
    }
848
849
    /**
850
     * Test PATCH: test operation to undefined index
851
     *
852
     * @group ref
853
     * @return void
854
     */
855
    public function testPatchTestOperationToUndefinedIndexThrowsException()
856
    {
857
        // Load fixtures
858
        $this->loadFixtures(
859
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
860
            null,
861
            'doctrine_mongodb'
862
        );
863
864
        // Apply PATCH request, add new element
865
        $client = static::createRestClient();
866
        $newApp = ['ref' => 'http://localhost/core/app/test'];
867
        $patchJson = json_encode(
868
            [
869
                [
870
                    'op' => 'test',
871
                    'path' => '/nestedApps/9',
872
                    'value' => $newApp
873
                ]
874
            ]
875
        );
876
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
877
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
878
    }
879
880
    /**
881
     * Test PATCH: add complex object App to array
882
     *
883
     * @group ref
884
     * @return void
885
     */
886
    public function testPatchAddElementToUndefinedIndexResponseAsBadRequest()
887
    {
888
        // Load fixtures
889
        $this->loadFixtures(
890
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
891
            null,
892
            'doctrine_mongodb'
893
        );
894
895
        // Apply PATCH request, add new element
896
        $client = static::createRestClient();
897
        $newApp = ['ref' => 'http://localhost/core/app/admin'];
898
        $patchJson = json_encode(
899
            [
900
                [
901
                    'op' => 'add',
902
                    'path' => '/nestedApps/9',
903
                    'value' => $newApp
904
                ]
905
            ]
906
        );
907
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
908
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
909
910
        // Check that patched document not changed
911
        $client = static::createRestClient();
912
        $client->request('GET', '/hans/showcase/500');
913
914
        $result = $client->getResults();
915
        $this->assertEquals(2, count($result->nestedApps));
916
    }
917
918
    /**
919
     * Encode string value in RQL
920
     *
921
     * @param string $value String value
922
     * @return string
923
     */
924 View Code Duplication
    private function encodeRqlString($value)
925
    {
926
        return strtr(
927
            rawurlencode($value),
928
            [
929
                '-' => '%2D',
930
                '_' => '%5F',
931
                '.' => '%2E',
932
                '~' => '%7E',
933
            ]
934
        );
935
    }
936
937
    /**
938
     * Trigger a 301 Status code
939
     *
940
     * @param string $url         requested url
941
     * @param string $redirectUrl redirected url
942
     * @dataProvider rqlDataProvider
943
     * @return void
944
     */
945
    public function testTrigger301($url, $redirectUrl)
946
    {
947
        $client = static::createRestClient();
948
        $client->request('GET', $url);
949
        $this->assertEquals(301, $client->getResponse()->getStatusCode());
950
        $this->assertEquals($redirectUrl, $client->getResponse()->headers->get('Location'));
951
    }
952
953
    /**
954
     * Provides urls for the testTrigger301() test.
955
     *
956
     * @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...
957
     */
958
    public function rqlDataProvider()
959
    {
960
        return [
961
            'rql' => ['url' => '/hans/showcase?id=blah' , 'redirect_url' => 'http://localhost/hans/showcase/?id=blah'],
962
            'noRql' => ['url' => '/hans/showcase' , 'redirect_url' => 'http://localhost/hans/showcase/']
963
        ];
964
    }
965
966
    /**
967
     * test finding of showcases by ref
968
     *
969
     * @dataProvider findByExtrefProvider
970
     *
971
     * @param string  $field which reference to search in
972
     * @param mixed   $url   ref to search for
973
     * @param integer $count number of results to expect
974
     *
975
     * @return void
976
     */
977
    public function testFindByExtref($field, $url, $count)
978
    {
979
        $this->loadFixtures(
980
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
981
            null,
982
            'doctrine_mongodb'
983
        );
984
985
        $url = sprintf(
986
            '/hans/showcase/?%s=%s',
987
            $this->encodeRqlString($field),
988
            $this->encodeRqlString($url)
989
        );
990
991
        $client = static::createRestClient();
992
        $client->request('GET', $url);
993
        $this->assertEquals(Response::HTTP_OK, $client->getResponse()->getStatusCode());
994
        $this->assertCount($count, $client->getResults());
995
    }
996
997
    /**
998
     * @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...
999
     */
1000 View Code Duplication
    public function findByExtrefProvider()
1001
    {
1002
        return [
1003
            'find a linked record when searching for "tablet" ref by array field' => [
1004
                'nestedApps.0.$ref',
1005
                'http://localhost/core/app/tablet',
1006
                1
1007
            ],
1008
            'find a linked record when searching for "admin" ref by array field' => [
1009
                'nestedApps.0.$ref',
1010
                'http://localhost/core/app/admin',
1011
                1
1012
            ],
1013
            'find nothing when searching for inextistant (and unlinked) ref by array field' => [
1014
                'nestedApps.0.$ref',
1015
                'http://localhost/core/app/inexistant',
1016
                0
1017
            ],
1018
            'return nothing when searching with incomplete ref by array field' => [
1019
                'nestedApps.0.$ref',
1020
                'http://localhost/core/app',
1021
                0
1022
            ],
1023
        ];
1024
    }
1025
}
1026