Completed
Push — master ( 930ba5...99d635 )
by Narcotic
29:20
created

testPatchToInvalidShowcase()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 29
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 15
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.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
        $this->assertEquals($filtred, $client->getResults());
460
461
        foreach ([
462
                     '500' => $filtred[0],
463
                     '600' => $filtred[1],
464
                 ] as $id => $item) {
465
            $client = static::createRestClient();
466
            $client->request('GET', '/hans/showcase/'.$id.'?'.$rqlSelect);
467
            $this->assertEquals($item, $client->getResults());
468
        }
469
    }
470
471
    /**
472
     * Test to see if we can do like() searches on identifier fields
473
     *
474
     * @return void
475
     */
476
    public function testLikeSearchOnIdentifierField()
477
    {
478
        // Load fixtures
479
        $this->loadFixtures(
480
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
481
            null,
482
            'doctrine_mongodb'
483
        );
484
485
        $client = static::createRestClient();
486
        $client->request('GET', '/hans/showcase/?like(id,5*)');
487
488
        // we should only get 1 ;-)
489
        $this->assertEquals(1, count($client->getResults()));
490
491
        $client = static::createRestClient();
492
        $client->request('GET', '/hans/showcase/?like(id,*0)');
493
494
        // this should get both
495
        $this->assertEquals(2, count($client->getResults()));
496
    }
497
498
    /**
499
     * Test PATCH for deep nested attribute
500
     *
501
     * @return void
502
     */
503 View Code Duplication
    public function testPatchDeepNestedProperty()
504
    {
505
        // Load fixtures
506
        $this->loadFixtures(
507
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
508
            null,
509
            'doctrine_mongodb'
510
        );
511
512
        // Apply PATCH request
513
        $client = static::createRestClient();
514
        $patchJson = json_encode(
515
            [
516
                [
517
                    'op' => 'replace',
518
                    'path' => '/unstructuredObject/hashField/anotherField',
519
                    'value' => 'changed nested hash field with patch'
520
                ]
521
            ]
522
        );
523
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
524
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
525
526
        // Get changed showcase
527
        $client = static::createRestClient();
528
        $client->request('GET', '/hans/showcase/500');
529
530
        $result = $client->getResults();
531
        $this->assertEquals(
532
            'changed nested hash field with patch',
533
            $result->unstructuredObject->hashField->anotherField
534
        );
535
    }
536
537
    /**
538
     * Test success PATCH method - response headers contains link to resource
539
     *
540
     * @return void
541
     */
542
    public function testPatchSuccessResponseHeaderContainsResourceLink()
543
    {
544
        // Load fixtures
545
        $this->loadFixtures(
546
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
547
            null,
548
            'doctrine_mongodb'
549
        );
550
551
        // Apply PATCH request
552
        $client = static::createRestClient();
553
        $patchJson = json_encode(
554
            [
555
                [
556
                    'op' => 'replace',
557
                    'path' => '/testField/en',
558
                    'value' => 'changed value'
559
                ]
560
            ]
561
        );
562
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
563
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
564
565
        $this->assertEquals(
566
            '/hans/showcase/500',
567
            $client->getResponse()->headers->get('Content-Location')
568
        );
569
    }
570
571
    /**
572
     * Test PATCH method - remove/change ID not allowed
573
     *
574
     * @return void
575
     */
576
    public function testPatchRemoveAndChangeIdNotAllowed()
577
    {
578
        // Load fixtures
579
        $this->loadFixtures(
580
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
581
            null,
582
            'doctrine_mongodb'
583
        );
584
585
        // Apply PATCH request
586
        $client = static::createRestClient();
587
        $patchJson = json_encode(
588
            [
589
                [
590
                    'op' => 'remove',
591
                    'path' => '/id'
592
                ]
593
            ]
594
        );
595
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
596
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
597
    }
598
599
    /**
600
     * Test PATCH: add property to free object structure
601
     *
602
     * @return void
603
     */
604 View Code Duplication
    public function testPatchAddPropertyToFreeObject()
605
    {
606
        // Load fixtures
607
        $this->loadFixtures(
608
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
609
            null,
610
            'doctrine_mongodb'
611
        );
612
613
        // Apply PATCH request
614
        $client = static::createRestClient();
615
        $patchJson = json_encode(
616
            [
617
                [
618
                    'op' => 'add',
619
                    'path' => '/unstructuredObject/hashField/newAddedField',
620
                    'value' => 'new field value'
621
                ]
622
            ]
623
        );
624
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
625
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
626
627
        // Get changed showcase
628
        $client = static::createRestClient();
629
        $client->request('GET', '/hans/showcase/500');
630
631
        $result = $client->getResults();
632
        $this->assertEquals(
633
            'new field value',
634
            $result->unstructuredObject->hashField->newAddedField
635
        );
636
    }
637
638
    /**
639
     * Test PATCH for $ref attribute
640
     *
641
     * @return void
642
     * @incomplete
643
     */
644
    public function testApplyPatchForRefAttribute()
645
    {
646
        // Load fixtures
647
        $this->loadFixtures(
648
            [
649
                'GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'
650
            ],
651
            null,
652
            'doctrine_mongodb'
653
        );
654
655
        // Apply PATCH request
656
        $client = static::createRestClient();
657
        $patchJson = json_encode(
658
            [
659
                [
660
                    'op' => 'replace',
661
                    'path' => '/nestedApps/0',
662
                    'value' => [
663
                        '$ref' => 'http://localhost/core/app/admin'
664
                    ]
665
                ]
666
            ]
667
        );
668
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
669
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
670
671
        // Check patched result
672
        $client = static::createRestClient();
673
        $client->request('GET', '/hans/showcase/500');
674
675
        $result = $client->getResults();
676
        $this->assertEquals(
677
            'http://localhost/core/app/admin',
678
            $result->nestedApps[0]->{'$ref'}
679
        );
680
    }
681
682
    /**
683
     * Test PATCH: apply patch which results to invalid Showcase schema
684
     *
685
     * @return void
686
     */
687
    public function testPatchToInvalidShowcase()
688
    {
689
        // Load fixtures
690
        $this->loadFixtures(
691
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
692
            null,
693
            'doctrine_mongodb'
694
        );
695
696
        // Apply PATCH request, remove required field
697
        $client = static::createRestClient();
698
        $patchJson = json_encode(
699
            [
700
                [
701
                    'op' => 'remove',
702
                    'path' => '/anotherInt'
703
                ]
704
            ]
705
        );
706
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
707
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
708
709
        // Check that Showcase has not been changed
710
        $client = static::createRestClient();
711
        $client->request('GET', '/hans/showcase/500');
712
713
        $result = $client->getResults();
714
        $this->assertObjectHasAttribute('anotherInt', $result);
715
    }
716
717
    /**
718
     * Test PATCH: remove element from array
719
     *
720
     * @return void
721
     */
722 View Code Duplication
    public function testRemoveFromArrayPatch()
723
    {
724
        // Load fixtures
725
        $this->loadFixtures(
726
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
727
            null,
728
            'doctrine_mongodb'
729
        );
730
731
        // Apply PATCH request, remove nested app, initially there are 2 apps
732
        $client = static::createRestClient();
733
        $patchJson = json_encode(
734
            [
735
                [
736
                    'op' => 'remove',
737
                    'path' => '/nestedApps/0'
738
                ]
739
            ]
740
        );
741
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
742
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
743
744
        // Check patched result
745
        $client = static::createRestClient();
746
        $client->request('GET', '/hans/showcase/500');
747
748
        $result = $client->getResults();
749
        $this->assertEquals(1, count($result->nestedApps));
750
        $this->assertEquals('http://localhost/core/app/admin', $result->nestedApps[0]->{'$ref'});
751
    }
752
753
    /**
754
     * Test PATCH: add new element to array
755
     *
756
     * @return void
757
     */
758
    public function testAddElementToSpecificIndexInArrayPatch()
759
    {
760
        // Load fixtures
761
        $this->loadFixtures(
762
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
763
            null,
764
            'doctrine_mongodb'
765
        );
766
767
        // Apply PATCH request, add new element
768
        $client = static::createRestClient();
769
        $newElement = ['name' => 'element three'];
770
        $patchJson = json_encode(
771
            [
772
                [
773
                    'op' => 'add',
774
                    'path' => '/nestedArray/1',
775
                    'value' => $newElement
776
                ]
777
            ]
778
        );
779
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
780
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
781
782
        // Check patched result
783
        $client = static::createRestClient();
784
        $client->request('GET', '/hans/showcase/500');
785
786
        $result = $client->getResults();
787
        $this->assertEquals(3, count($result->nestedArray));
788
        $this->assertJsonStringEqualsJsonString(
789
            json_encode($newElement),
790
            json_encode($result->nestedArray[1])
791
        );
792
    }
793
794
    /**
795
     * Test PATCH: add complex object App to array
796
     *
797
     * @group ref
798
     * @return void
799
     */
800 View Code Duplication
    public function testPatchAddComplexObjectToSpecificIndexInArray()
801
    {
802
        // Load fixtures
803
        $this->loadFixtures(
804
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
805
            null,
806
            'doctrine_mongodb'
807
        );
808
809
        // Apply PATCH request, add new element
810
        $client = static::createRestClient();
811
        $newApp = ['$ref' => 'http://localhost/core/app/admin'];
812
        $patchJson = json_encode(
813
            [
814
                [
815
                    'op' => 'add',
816
                    'path' => '/nestedApps/0',
817
                    'value' => $newApp
818
                ]
819
            ]
820
        );
821
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
822
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
823
824
        // Check patched result
825
        $client = static::createRestClient();
826
        $client->request('GET', '/hans/showcase/500');
827
828
        $result = $client->getResults();
829
        $this->assertEquals(3, count($result->nestedApps));
830
        $this->assertEquals(
831
            'http://localhost/core/app/admin',
832
            $result->nestedApps[0]->{'$ref'}
833
        );
834
    }
835
836
    /**
837
     * Test PATCH: add complex object App to array
838
     *
839
     * @group ref
840
     * @return void
841
     */
842 View Code Duplication
    public function testPatchAddComplexObjectToTheEndOfArray()
843
    {
844
        // Load fixtures
845
        $this->loadFixtures(
846
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
847
            null,
848
            'doctrine_mongodb'
849
        );
850
851
        // Apply PATCH request, add new element
852
        $client = static::createRestClient();
853
        $newApp = ['$ref' => 'http://localhost/core/app/test'];
854
        $patchJson = json_encode(
855
            [
856
                [
857
                    'op' => 'add',
858
                    'path' => '/nestedApps/-',
859
                    'value' => $newApp
860
                ]
861
            ]
862
        );
863
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
864
        $this->assertEquals(200, $client->getResponse()->getStatusCode());
865
866
        // Check patched result
867
        $client = static::createRestClient();
868
        $client->request('GET', '/hans/showcase/500');
869
870
        $result = $client->getResults();
871
        $this->assertEquals(3, count($result->nestedApps));
872
        $this->assertEquals(
873
            'http://localhost/core/app/test',
874
            $result->nestedApps[2]->{'$ref'}
875
        );
876
    }
877
878
    /**
879
     * Test PATCH: test operation to undefined index
880
     *
881
     * @group ref
882
     * @return void
883
     */
884
    public function testPatchTestOperationToUndefinedIndexThrowsException()
885
    {
886
        // Load fixtures
887
        $this->loadFixtures(
888
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
889
            null,
890
            'doctrine_mongodb'
891
        );
892
893
        // Apply PATCH request, add new element
894
        $client = static::createRestClient();
895
        $newApp = ['ref' => 'http://localhost/core/app/test'];
896
        $patchJson = json_encode(
897
            [
898
                [
899
                    'op' => 'test',
900
                    'path' => '/nestedApps/9',
901
                    'value' => $newApp
902
                ]
903
            ]
904
        );
905
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
906
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
907
    }
908
909
    /**
910
     * Test PATCH: add complex object App to array
911
     *
912
     * @group ref
913
     * @return void
914
     */
915
    public function testPatchAddElementToUndefinedIndexResponseAsBadRequest()
916
    {
917
        // Load fixtures
918
        $this->loadFixtures(
919
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
920
            null,
921
            'doctrine_mongodb'
922
        );
923
924
        // Apply PATCH request, add new element
925
        $client = static::createRestClient();
926
        $newApp = ['ref' => 'http://localhost/core/app/admin'];
927
        $patchJson = json_encode(
928
            [
929
                [
930
                    'op' => 'add',
931
                    'path' => '/nestedApps/9',
932
                    'value' => $newApp
933
                ]
934
            ]
935
        );
936
        $client->request('PATCH', '/hans/showcase/500', array(), array(), array(), $patchJson);
937
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
938
939
        // Check that patched document not changed
940
        $client = static::createRestClient();
941
        $client->request('GET', '/hans/showcase/500');
942
943
        $result = $client->getResults();
944
        $this->assertEquals(2, count($result->nestedApps));
945
    }
946
947
    /**
948
     * Encode string value in RQL
949
     *
950
     * @param string $value String value
951
     * @return string
952
     */
953 View Code Duplication
    private function encodeRqlString($value)
954
    {
955
        return strtr(
956
            rawurlencode($value),
957
            [
958
                '-' => '%2D',
959
                '_' => '%5F',
960
                '.' => '%2E',
961
                '~' => '%7E',
962
            ]
963
        );
964
    }
965
966
    /**
967
     * Trigger a 301 Status code
968
     *
969
     * @param string $url         requested url
970
     * @param string $redirectUrl redirected url
971
     * @dataProvider rqlDataProvider
972
     * @return void
973
     */
974 View Code Duplication
    public function testTrigger301($url, $redirectUrl)
975
    {
976
        $client = static::createRestClient();
977
        $client->request('GET', $url);
978
        $this->assertEquals(301, $client->getResponse()->getStatusCode());
979
        $this->assertEquals($redirectUrl, $client->getResponse()->headers->get('Location'));
980
    }
981
982
    /**
983
     * Provides urls for the testTrigger301() test.
984
     *
985
     * @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...
986
     */
987
    public function rqlDataProvider()
988
    {
989
        return [
990
            'rql' => ['url' => '/hans/showcase?id=blah' , 'redirect_url' => 'http://localhost/hans/showcase/?id=blah'],
991
            'noRql' => ['url' => '/hans/showcase' , 'redirect_url' => 'http://localhost/hans/showcase/']
992
        ];
993
    }
994
995
    /**
996
     * Here we test the client expectation in "id" property exposing in the json schema.
997
     *
998
     * They want
999
     * * "id" of an extref object should *not* be described/present in schema
1000
     * * "id" of others, including embedded objects, *should* be described/present in schema
1001
     *
1002
     * @return void
1003
     */
1004
    public function testCorrectIdExposingInSchema()
1005
    {
1006
        // get the schema
1007
        $client = static::createRestClient();
1008
        $client->request('GET', '/schema/hans/showcase/item');
1009
1010
        $schema = $client->getResults();
1011
1012
        // make sure we have an extref field here
1013
        $this->assertEquals('extref', $schema->properties->nestedApps->items->properties->{'$ref'}->format);
1014
        // and that 'id' is not there
1015
        $this->assertObjectNotHasAttribute('id', $schema->properties->nestedApps->items->properties);
1016
1017
        // embed case - check the embedded 'contactCode'
1018
        $this->assertStringEndsWith('Embedded', $schema->properties->contactCode->{'x-documentClass'});
1019
        $this->assertObjectHasAttribute('id', $schema->properties->contactCode->properties);
1020
    }
1021
1022
    /**
1023
     * test finding of showcases by ref
1024
     *
1025
     * @dataProvider findByExtrefProvider
1026
     *
1027
     * @param string  $field which reference to search in
1028
     * @param mixed   $url   ref to search for
1029
     * @param integer $count number of results to expect
1030
     *
1031
     * @return void
1032
     */
1033
    public function testFindByExtref($field, $url, $count)
1034
    {
1035
        $this->loadFixtures(
1036
            ['GravitonDyn\ShowCaseBundle\DataFixtures\MongoDB\LoadShowCaseData'],
1037
            null,
1038
            'doctrine_mongodb'
1039
        );
1040
1041
        $url = sprintf(
1042
            '/hans/showcase/?%s=%s',
1043
            $this->encodeRqlString($field),
1044
            $this->encodeRqlString($url)
1045
        );
1046
1047
        $client = static::createRestClient();
1048
        $client->request('GET', $url);
1049
        $this->assertEquals(Response::HTTP_OK, $client->getResponse()->getStatusCode());
1050
        $this->assertCount($count, $client->getResults());
1051
    }
1052
1053
    /**
1054
     * @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...
1055
     */
1056 View Code Duplication
    public function findByExtrefProvider()
1057
    {
1058
        return [
1059
            'find a linked record when searching for "tablet" ref by array field' => [
1060
                'nestedApps.0.$ref',
1061
                'http://localhost/core/app/tablet',
1062
                1
1063
            ],
1064
            'find a linked record when searching for "admin" ref by array field' => [
1065
                'nestedApps.0.$ref',
1066
                'http://localhost/core/app/admin',
1067
                1
1068
            ],
1069
            'find nothing when searching for inextistant (and unlinked) ref by array field' => [
1070
                'nestedApps.0.$ref',
1071
                'http://localhost/core/app/inexistant',
1072
                0
1073
            ],
1074
            'return nothing when searching with incomplete ref by array field' => [
1075
                'nestedApps.0.$ref',
1076
                'http://localhost/core/app',
1077
                0
1078
            ],
1079
        ];
1080
    }
1081
}
1082