Completed
Push — feature/other-validation ( 994f75...586e28 )
by Narcotic
10:05
created

ShowcaseControllerTest::testWrongExtRef()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 30
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

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