Completed
Push — master ( d75c00...042f84 )
by Narcotic
21:29 queued 08:56
created

AppControllerTest::testPutAppNoIdInPayload()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.3142
c 0
b 0
f 0
cc 1
eloc 14
nc 1
nop 0
1
<?php
2
/**
3
 * functional test for /core/app
4
 */
5
6
namespace Graviton\CoreBundle\Tests\Controller;
7
8
use Graviton\TestBundle\Test\RestTestCase;
9
use Symfony\Component\HttpFoundation\Response;
10
11
/**
12
 * Basic functional test for /core/app.
13
 *
14
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
15
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
16
 * @link     http://swisscom.ch
17
 */
18
class AppControllerTest extends RestTestCase
19
{
20
    /**
21
     * @const complete content type string expected on a resouce
22
     */
23
    const CONTENT_TYPE = 'application/json; charset=UTF-8; profile=http://localhost/schema/core/app/item';
24
25
    /**
26
     * @const corresponding vendorized schema mime type
27
     */
28
    const COLLECTION_TYPE = 'application/json; charset=UTF-8; profile=http://localhost/schema/core/app/collection';
29
30
    /**
31
     * setup client and load fixtures
32
     *
33
     * @return void
34
     */
35
    public function setUp()
36
    {
37
        $this->loadFixtures(
38
            array(
39
                'Graviton\CoreBundle\DataFixtures\MongoDB\LoadAppData',
40
                'Graviton\I18nBundle\DataFixtures\MongoDB\LoadLanguageData',
41
                'Graviton\I18nBundle\DataFixtures\MongoDB\LoadMultiLanguageData',
42
                'Graviton\I18nBundle\DataFixtures\MongoDB\LoadTranslatableData',
43
                'Graviton\I18nBundle\DataFixtures\MongoDB\LoadTranslatablesApp'
44
            ),
45
            null,
46
            'doctrine_mongodb'
47
        );
48
    }
49
    /**
50
     * check if all fixtures are returned on GET
51
     *
52
     * @return void
53
     */
54
    public function testFindAll()
55
    {
56
        $client = static::createRestClient();
57
        $client->request('GET', '/core/app/');
58
59
        $response = $client->getResponse();
60
        $results = $client->getResults();
61
62
        $this->assertResponseContentType(self::COLLECTION_TYPE, $response);
63
        $this->assertEquals(2, count($results));
64
65
        $this->assertEquals('admin', $results[0]->id);
66
        $this->assertEquals('Administration', $results[0]->name->en);
67
        $this->assertEquals(true, $results[0]->showInMenu);
68
        $this->assertEquals(2, $results[0]->order);
69
70
        $this->assertEquals('tablet', $results[1]->id);
71
        $this->assertEquals('Tablet', $results[1]->name->en);
72
        $this->assertEquals(true, $results[1]->showInMenu);
73
        $this->assertEquals(1, $results[1]->order);
74
75
        $this->assertContains(
76
            '<http://localhost/core/app/>; rel="self"',
77
            $response->headers->get('Link')
78
        );
79
        $this->assertEquals('*', $response->headers->get('Access-Control-Allow-Origin'));
80
    }
81
82
    /**
83
     * test that our paging headers are correct if client does NOT provide rql BUT
84
     * we have more records in the db then the default pagesize (= we will add limit() clauses to Link elements)
85
     *
86
     * @return void
87
     */
88 View Code Duplication
    public function testGeneratedPagingHeadersNoRql()
89
    {
90
        $this->loadFixtures(
91
            [
92
                'Graviton\CoreBundle\DataFixtures\MongoDB\LoadAppDataExceedSinglePageLimit'
93
            ],
94
            null,
95
            'doctrine_mongodb'
96
        );
97
98
        $client = static::createRestClient();
99
        $client->request('GET', '/core/app/');
100
101
        $response = $client->getResponse();
102
103
        $this->assertContains(
104
            '<http://localhost/core/app/?limit(10%2C0)>; rel="self"',
105
            $response->headers->get('Link')
106
        );
107
108
        $this->assertContains(
109
            '<http://localhost/core/app/?limit(10%2C10)>; rel="next"',
110
            $response->headers->get('Link')
111
        );
112
113
        $this->assertContains(
114
            '<http://localhost/core/app/?limit(10%2C10)>; rel="last"',
115
            $response->headers->get('Link')
116
        );
117
    }
118
119
    /**
120
     * test if we can get list of apps, paged and with filters..
121
     *
122
     * @return void
123
     */
124 View Code Duplication
    public function testGetAppWithFilteringAndPaging()
125
    {
126
        $client = static::createRestClient();
127
        $client->request('GET', '/core/app/?eq(showInMenu,true)&limit(1)');
128
        $response = $client->getResponse();
129
130
        $this->assertEquals(1, count($client->getResults()));
131
132
        $this->assertContains(
133
            '<http://localhost/core/app/?eq(showInMenu%2Ctrue)&limit(1)>; rel="self"',
134
            $response->headers->get('Link')
135
        );
136
137
        $this->assertContains(
138
            '<http://localhost/core/app/?eq(showInMenu%2Ctrue)&limit(1%2C1)>; rel="next"',
139
            $response->headers->get('Link')
140
        );
141
142
        $this->assertContains(
143
            '<http://localhost/core/app/?eq(showInMenu%2Ctrue)&limit(1%2C1)>; rel="last"',
144
            $response->headers->get('Link')
145
        );
146
    }
147
148
    /**
149
     * rql limit() should *never* be overwritten by default value
150
     *
151
     * @return void
152
     */
153
    public function testGetAppPagingWithRql()
154
    {
155
        // does limit work?
156
        $client = static::createRestClient();
157
        $client->request('GET', '/core/app/?limit(1)');
158
        $this->assertEquals(1, count($client->getResults()));
159
160
        $response = $client->getResponse();
161
162
        $this->assertContains(
163
            '<http://localhost/core/app/?limit(1)>; rel="self"',
164
            $response->headers->get('Link')
165
        );
166
167
        $this->assertContains(
168
            '<http://localhost/core/app/?limit(1%2C1)>; rel="next"',
169
            $response->headers->get('Link')
170
        );
171
172
        $this->assertContains(
173
            '<http://localhost/core/app/?limit(1%2C1)>; rel="last"',
174
            $response->headers->get('Link')
175
        );
176
177
        $this->assertSame('2', $response->headers->get('X-Total-Count'));
178
179
        /*** pagination tests **/
180
        $client = static::createRestClient();
181
        $client->request('GET', '/core/app/?limit(1,1)');
182
        $this->assertEquals(1, count($client->getResults()));
183
184
        $response = $client->getResponse();
185
186
        $this->assertContains(
187
            '<http://localhost/core/app/?limit(1%2C1)>; rel="self"',
188
            $response->headers->get('Link')
189
        );
190
191
        $this->assertContains(
192
            '<http://localhost/core/app/?limit(1%2C0)>; rel="prev"',
193
            $response->headers->get('Link')
194
        );
195
196
        // we're on the 'last' page - so 'last' should not be in in Link header
197
        $this->assertNotContains(
198
            'rel="last"',
199
            $response->headers->get('Link')
200
        );
201
202
        $this->assertSame('2', $response->headers->get('X-Total-Count'));
203
204
        /*** pagination with different rql test **/
205
        $client = static::createRestClient();
206
        $client->request('GET', '/core/app/?limit(1)&select(id)&sort(-order)');
207
        $this->assertEquals(1, count($client->getResults()));
208
209
        $response = $client->getResponse();
210
211
        $this->assertContains(
212
            'http://localhost/core/app/?limit(1)&select(id)&sort(-order)>; rel="self"',
213
            $response->headers->get('Link')
214
        );
215
216
        $this->assertContains(
217
            '<http://localhost/core/app/?limit(1%2C1)&select(id)&sort(-order)>; rel="next"',
218
            $response->headers->get('Link')
219
        );
220
221
        $this->assertContains(
222
            '<http://localhost/core/app/?limit(1%2C1)&select(id)&sort(-order)>; rel="last"',
223
            $response->headers->get('Link')
224
        );
225
226
        $this->assertNotContains(
227
            'rel="prev"',
228
            $response->headers->get('Link')
229
        );
230
231
        $this->assertSame('2', $response->headers->get('X-Total-Count'));
232
    }
233
234
    /**
235
     * check for a client error if invalid limit value is provided
236
     *
237
     * @dataProvider invalidPagingPageSizeProvider
238
     *
239
     * @param integer $limit limit value that should fail
240
     * @return void
241
     */
242 View Code Duplication
    public function testInvalidPagingPageSize($limit)
243
    {
244
        $client = static::createRestClient();
245
        $client->request('GET', sprintf('/core/app/?limit(%s)', $limit));
246
247
        $this->assertEquals(Response::HTTP_BAD_REQUEST, $client->getResponse()->getStatusCode());
248
        $this->assertContains('negative or null limit in rql', $client->getResults()->message);
249
    }
250
251
    /**
252
     * page size test provides
253
     *
254
     * @return array[]
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use 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...
255
     */
256
    public function invalidPagingPageSizeProvider()
257
    {
258
        return [
259
            [0],
260
            [-1],
261
        ];
262
    }
263
264
    /**
265
     * RQL is parsed only when we get apps
266
     *
267
     * @return void
268
     */
269
    public function testRqlIsParsedOnlyOnGetRequest()
270
    {
271
        $appData = [
272
            'showInMenu' => false,
273
            'order'      => 100,
274
            'name'      => ['en' => 'Administration'],
275
        ];
276
277
        $client = static::createRestClient();
278
        $client->request('GET', '/core/app/?invalidrqlquery');
279
        $this->assertEquals(Response::HTTP_BAD_REQUEST, $client->getResponse()->getStatusCode());
280
        $this->assertContains('syntax error in rql', $client->getResults()->message);
281
282
        $client = static::createRestClient();
283
        $client->request('GET', '/core/app/admin?invalidrqlquery');
284
        $this->assertEquals(Response::HTTP_BAD_REQUEST, $client->getResponse()->getStatusCode());
285
        $this->assertContains('syntax error in rql', $client->getResults()->message);
286
287
        $client = static::createRestClient();
288
        $client->request('OPTIONS', '/core/app/?invalidrqlquery');
289
        $this->assertEquals(Response::HTTP_NO_CONTENT, $client->getResponse()->getStatusCode());
290
291
        $client = static::createRestClient();
292
        $client->request('OPTIONS', '/schema/core/app/collection?invalidrqlquery');
293
        $this->assertEquals(Response::HTTP_NO_CONTENT, $client->getResponse()->getStatusCode());
294
295
        $client = static::createRestClient();
296
        $client->request('OPTIONS', '/schema/core/app/item?invalidrqlquery');
297
        $this->assertEquals(Response::HTTP_NO_CONTENT, $client->getResponse()->getStatusCode());
298
299
        $client = static::createRestClient();
300
        $client->request('GET', '/schema/core/app/collection?invalidrqlquery');
301
        $this->assertEquals(Response::HTTP_OK, $client->getResponse()->getStatusCode());
302
303
        $client = static::createRestClient();
304
        $client->request('GET', '/schema/core/app/item?invalidrqlquery');
305
        $this->assertEquals(Response::HTTP_OK, $client->getResponse()->getStatusCode());
306
307
308
        $client = static::createRestClient();
309
        $client->post('/core/app/?invalidrqlquery', $appData);
310
        $this->assertEquals(Response::HTTP_CREATED, $client->getResponse()->getStatusCode());
311
312
        $client = static::createRestClient();
313
        $client->put('/core/app/admin?invalidrqlquery', $appData);
314
        $this->assertEquals(Response::HTTP_NO_CONTENT, $client->getResponse()->getStatusCode());
315
316
        $client = static::createRestClient();
317
        $client->request('DELETE', '/core/app/admin?invalidrqlquery');
318
        $this->assertEquals(Response::HTTP_NO_CONTENT, $client->getResponse()->getStatusCode());
319
    }
320
321
    /**
322
     * Test only RQL select() operator is allowed for GET one
323
     *
324
     * @return void
325
     * @group tmp
326
     */
327
    public function testOnlyRqlSelectIsAllowedOnGetOne()
328
    {
329
        $client = static::createRestClient();
330
        $client->request('GET', '/core/app/?select(id)');
331
        $this->assertEquals(Response::HTTP_OK, $client->getResponse()->getStatusCode());
332
333
        $client = static::createRestClient();
334
        $client->request('GET', '/core/app/admin?select(id)');
335
        $this->assertEquals(Response::HTTP_OK, $client->getResponse()->getStatusCode());
336
337
        foreach ([
338
                     'limit' => 'limit(1)',
339
                     'sort'  => 'sort(+id)',
340
                     'eq'    => 'eq(id,a)',
341
                 ] as $extraRqlOperator => $extraRqlOperatorQuery) {
342
            $client = static::createRestClient();
343
            $client->request('GET', '/core/app/?select(id)&'.$extraRqlOperatorQuery);
344
            $this->assertEquals(Response::HTTP_OK, $client->getResponse()->getStatusCode());
345
346
            $client = static::createRestClient();
347
            $client->request('GET', '/core/app/admin?select(id)&'.$extraRqlOperatorQuery);
348
            $this->assertEquals(Response::HTTP_BAD_REQUEST, $client->getResponse()->getStatusCode());
349
            $this->assertEquals(
350
                sprintf('RQL operator "%s" is not allowed for this request', $extraRqlOperator),
351
                $client->getResults()->message
352
            );
353
        }
354
    }
355
356
    /**
357
     * check for empty collections when no fixtures are loaded
358
     *
359
     * @return void
360
     */
361 View Code Duplication
    public function testFindAllEmptyCollection()
362
    {
363
        // reset fixtures since we already have some from setUp
364
        $this->loadFixtures(array(), null, 'doctrine_mongodb');
365
        $client = static::createRestClient();
366
        $client->request('GET', '/core/app/');
367
368
        $response = $client->getResponse();
369
        $results = $client->getResults();
370
371
        $this->assertResponseContentType(self::COLLECTION_TYPE, $response);
372
373
        $this->assertEquals(array(), $results);
374
    }
375
376
    /**
377
     * test if we can get an app by id
378
     *
379
     * @return void
380
     */
381
    public function testGetApp()
382
    {
383
        $client = static::createRestClient();
384
        $client->request('GET', '/core/app/admin');
385
        $response = $client->getResponse();
386
        $results = $client->getResults();
387
388
        $this->assertResponseContentType(self::CONTENT_TYPE, $response);
389
390
        $this->assertEquals('admin', $results->id);
391
        $this->assertEquals('Administration', $results->name->en);
392
        $this->assertEquals(true, $results->showInMenu);
393
394
        $this->assertContains(
395
            '<http://localhost/core/app/admin>; rel="self"',
396
            $response->headers->get('Link')
397
        );
398
        $this->assertEquals('*', $response->headers->get('Access-Control-Allow-Origin'));
399
    }
400
401
    /**
402
     * test if we can create an app through POST
403
     *
404
     * @return void
405
     */
406
    public function testPostApp()
407
    {
408
        $testApp = new \stdClass;
409
        $testApp->name = new \stdClass;
410
        $testApp->name->en = 'new Test App';
411
        $testApp->showInMenu = true;
412
413
        $client = static::createRestClient();
414
        $client->post('/core/app/', $testApp);
415
        $response = $client->getResponse();
416
        $results = $client->getResults();
417
418
        // we sent a location header so we don't want a body
419
        $this->assertNull($results);
420
        $this->assertContains('/core/app/', $response->headers->get('Location'));
421
422
        $client = static::createRestClient();
423
        $client->request('GET', $response->headers->get('Location'));
424
        $response = $client->getResponse();
425
        $results = $client->getResults();
426
427
        $this->assertResponseContentType(self::CONTENT_TYPE, $response);
428
        $this->assertEquals('new Test App', $results->name->en);
429
        $this->assertTrue($results->showInMenu);
430
        $this->assertContains(
431
            '<http://localhost/core/app/'.$results->id.'>; rel="self"',
432
            explode(',', $response->headers->get('Link'))
433
        );
434
    }
435
436
    /**
437
     * test if we get a correct return if we post empty.
438
     *
439
     * @return void
440
     */
441
    public function testPostEmptyApp()
442
    {
443
        $client = static::createRestClient();
444
445
        // send nothing really..
446
        $client->post('/core/app/', "", array(), array(), array(), false);
447
448
        $response = $client->getResponse();
449
450
        $this->assertContains(
451
            'No input data',
452
            $response->getContent()
453
        );
454
455
        $this->assertEquals(400, $response->getStatusCode());
456
    }
457
458
    /**
459
     * test if we get a correct return if we post empty.
460
     *
461
     * @return void
462
     */
463
    public function testPostNonObjectApp()
464
    {
465
        $client = static::createRestClient();
466
        $client->post('/core/app/', "non-object value");
467
468
        $response = $client->getResponse();
469
        $this->assertContains('JSON request body must be an object', $response->getContent());
470
        $this->assertEquals(400, $response->getStatusCode());
471
    }
472
473
    /**
474
     * test if 500 error is reported when posting an malformed input
475
     *
476
     * @return void
477
     */
478
    public function testPostMalformedApp()
479
    {
480
        $testApp = new \stdClass;
481
        $testApp->name = new \stdClass;
482
        $testApp->name->en = 'new Test App';
483
        $testApp->showInMenu = true;
484
485
        // malform it ;-)
486
        $input = str_replace(":", ";", json_encode($testApp));
487
488
        $client = static::createRestClient();
489
490
        // make sure this is sent as 'raw' input (not json_encoded again)
491
        $client->post('/core/app/', $input, array(), array(), array(), false);
492
493
        $response = $client->getResponse();
494
495
        // Check that error message contains detailed reason
496
        json_decode($input);
497
        $lastJsonError = function_exists('json_last_error_msg')
498
            ? json_last_error_msg()
499
            : 'Unable to decode JSON string';
500
        $this->assertContains(
501
            $lastJsonError,
502
            $client->getResults()->message
503
        );
504
505
        $this->assertEquals(400, $response->getStatusCode());
506
    }
507
508
    /**
509
     * Tests if an error is returned when an id is send in a post
510
     *
511
     * @return void
512
     */
513
    public function testPostWithId()
514
    {
515
        $helloApp = new \stdClass();
516
        $helloApp->id = 101;
517
        $helloApp->name = "tubel";
518
519
        $client = static::createRestClient();
520
        $client->post('/person/customer', $helloApp);
521
522
        $this->assertEquals(
523
            'Bad Request - "id" can not be given on a POST request. '.
524
            'Do a PUT request instead to update an existing record.',
525
            $client->getResults()->message
526
        );
527
    }
528
    /**
529
     * test updating apps
530
     *
531
     * @return void
532
     */
533
    public function testPutApp()
534
    {
535
        $helloApp = new \stdClass();
536
        $helloApp->id = "tablet";
537
        $helloApp->name = new \stdClass();
538
        $helloApp->name->en = "Tablet";
539
        $helloApp->showInMenu = false;
540
541
        $client = static::createRestClient();
542
        $client->put('/core/app/tablet', $helloApp);
543
544
        $this->assertNull($client->getResults());
545
        $this->assertNull($client->getResponse()->headers->get('Location'));
546
547
        $client = static::createRestClient();
548
        $client->request('GET', '/core/app/tablet');
549
        $response = $client->getResponse();
550
        $results = $client->getResults();
551
552
        $this->assertResponseContentType(self::CONTENT_TYPE, $response);
553
        $this->assertEquals('Tablet', $results->name->en);
554
        $this->assertFalse($results->showInMenu);
555
        $this->assertContains(
556
            '<http://localhost/core/app/tablet>; rel="self"',
557
            explode(',', $response->headers->get('Link'))
558
        );
559
    }
560
561
    /**
562
     * Test for PATCH Request
563
     *
564
     * @return void
565
     */
566
    public function testPatchAppRequestApplyChanges()
567
    {
568
        $helloApp = new \stdClass();
569
        $helloApp->id = "testapp";
570
        $helloApp->name = new \stdClass();
571
        $helloApp->name->en = "Test App";
572
        $helloApp->showInMenu = false;
573
574
        // 1. Create some App
575
        $client = static::createRestClient();
576
        $client->put('/core/app/' . $helloApp->id, $helloApp);
577
578
        // 2. PATCH request
579
        $client = static::createRestClient();
580
        $patchJson = json_encode(
581
            [
582
                [
583
                    'op' => 'replace',
584
                    'path' => '/name/en',
585
                    'value' => 'Test App Patched'
586
                ]
587
            ]
588
        );
589
        $client->request('PATCH', '/core/app/' . $helloApp->id, array(), array(), array(), $patchJson);
590
        $response = $client->getResponse();
591
592
        $this->assertEquals(200, $response->getStatusCode());
593
594
        // 3. Get changed App and check changed title
595
        $client = static::createRestClient();
596
        $client->request('GET', '/core/app/' . $helloApp->id);
597
598
        $response = $client->getResponse();
599
        $results = $client->getResults();
600
601
        $this->assertResponseContentType(self::CONTENT_TYPE, $response);
602
        $this->assertEquals('Test App Patched', $results->name->en);
603
    }
604
605
    /**
606
     * Test for Malformed PATCH Request
607
     *
608
     * @return void
609
     */
610
    public function testMalformedPatchAppRequest()
611
    {
612
        $helloApp = new \stdClass();
613
        $helloApp->id = "testapp";
614
        $helloApp->title = new \stdClass();
615
        $helloApp->title->en = "Test App";
616
        $helloApp->showInMenu = false;
617
618
        // 1. Create some App
619
        $client = static::createRestClient();
620
        $client->put('/core/app/' . $helloApp->id, $helloApp);
621
622
        // 2. PATCH request
623
        $client = static::createRestClient();
624
        $patchJson = json_encode(
625
            array(
626
                'op' => 'unknown',
627
                'path' => '/title/en'
628
            )
629
        );
630
        $client->request('PATCH', '/core/app/' . $helloApp->id, array(), array(), array(), $patchJson);
631
        $response = $client->getResponse();
632
633
        $this->assertEquals(400, $response->getStatusCode());
634
        $this->assertContains(
635
            'Invalid JSON patch request',
636
            $response->getContent()
637
        );
638
    }
639
640
    /**
641
     * Try to update an app with a non matching ID in GET and req body
642
     *
643
     * @return void
644
     */
645
    public function testNonMatchingIdPutApp()
646
    {
647
        $helloApp = new \stdClass();
648
        $helloApp->id = "tablet";
649
        $helloApp->name = new \stdClass();
650
        $helloApp->name->en = "Tablet";
651
        $helloApp->showInMenu = false;
652
653
        $client = static::createRestClient();
654
        $client->put('/core/app/someotherapp', $helloApp);
655
656
        $response = $client->getResponse();
657
658
        $this->assertContains(
659
            'Record ID in your payload must be the same',
660
            $response->getContent()
661
        );
662
663
        $this->assertEquals(400, $response->getStatusCode());
664
    }
665
666
    /**
667
     * We had an issue when PUTing without ID would create a new record.
668
     * This test ensures that we don't do that, instead we should apply the ID from the GET req.
669
     *
670
     * @return void
671
     */
672
    public function testPutAppNoIdInPayload()
673
    {
674
        $helloApp = new \stdClass();
675
        $helloApp->name = new \stdClass();
676
        $helloApp->name->en = 'New tablet';
677
        $helloApp->showInMenu = false;
678
679
        $client = static::createRestClient();
680
        $client->put('/core/app/tablet', $helloApp);
681
682
        // we sent a location header so we don't want a body
683
        $this->assertNull($client->getResults());
684
685
        $client = static::createRestClient();
686
        $client->request('GET', '/core/app/tablet');
687
        $results = $client->getResults();
688
689
        $this->assertEquals('tablet', $results->id);
690
        $this->assertEquals('New tablet', $results->name->en);
691
        $this->assertFalse($results->showInMenu);
692
    }
693
694
    /**
695
     * test updating an inexistant document (upsert)
696
     *
697
     * @return void
698
     */
699
    public function testUpsertApp()
700
    {
701
        $isnogudApp = new \stdClass;
702
        $isnogudApp->id = 'isnogud';
703
        $isnogudApp->name = new \stdClass;
704
        $isnogudApp->name->en = 'I don\'t exist';
705
        $isnogudApp->showInMenu = true;
706
707
        $client = static::createRestClient();
708
        $client->put('/core/app/isnogud', $isnogudApp);
709
710
        $this->assertEquals(204, $client->getResponse()->getStatusCode());
711
    }
712
713
    /**
714
     * test deleting an app
715
     *
716
     * @return void
717
     */
718
    public function testDeleteApp()
719
    {
720
        $testApp = new \stdClass;
721
        $testApp->id = 'tablet';
722
        $testApp->name = 'Tablet';
723
        $testApp->showInMenu = true;
724
        $testApp->order = 1;
725
726
        $client = static::createRestClient();
727
        $client->request('DELETE', '/core/app/tablet');
728
729
        $response = $client->getResponse();
730
731
        $this->assertEquals(204, $response->getStatusCode());
732
        $this->assertEquals('*', $response->headers->get('Access-Control-Allow-Origin'));
733
        $this->assertEmpty($response->getContent());
734
735
        $client->request('GET', '/core/app/tablet');
736
        $this->assertEquals(404, $client->getResponse()->getStatusCode());
737
    }
738
739
    /**
740
     * test failing validation on boolean field
741
     *
742
     * @return void
743
     */
744
    public function testFailingBooleanValidationOnAppUpdate()
745
    {
746
        $helloApp = new \stdClass;
747
        $helloApp->id = 'tablet';
748
        $helloApp->name = new \stdClass;
749
        $helloApp->name->en = 'Tablet';
750
        $helloApp->showInMenu = 'false';
751
752
        $client = static::createRestClient();
753
        $client->put('/core/app/tablet', $helloApp);
754
755
        $results = $client->getResults();
756
757
        $this->assertEquals(400, $client->getResponse()->getStatusCode());
758
759
        $this->assertContains('showInMenu', $results[0]->propertyPath);
760
        $this->assertEquals('String value found, but a boolean is required', $results[0]->message);
761
    }
762
763
    /**
764
     * test getting schema information
765
     *
766
     * @return void
767
     */
768 View Code Duplication
    public function testGetAppSchemaInformation()
769
    {
770
        $client = static::createRestClient();
771
        $client->request('OPTIONS', '/core/app/hello');
772
773
        $response = $client->getResponse();
774
775
        $this->assertCorsHeaders('GET, POST, PUT, PATCH, DELETE, OPTIONS', $response);
776
    }
777
778
    /**
779
     * requests on OPTIONS and HEAD shall not lead graviton to get any data from mongodb.
780
     * if we page limit(1) this will lead to presence of the x-total-count header if
781
     * data is generated (asserted by testGetAppPagingWithRql()). thus, if we don't
782
     * have this header, we can safely assume that no data has been processed in RestController.
783
     *
784
     * @return void
785
     */
786 View Code Duplication
    public function testNoRecordsAreGeneratedOnPreRequests()
787
    {
788
        $client = static::createRestClient();
789
        $client->request('OPTIONS', '/core/app/?limit(1)');
790
        $response = $client->getResponse();
791
        $this->assertArrayNotHasKey('x-total-count', $response->headers->all());
792
793
        $client = static::createRestClient();
794
        $client->request('HEAD', '/core/app/?limit(1)');
795
        $response = $client->getResponse();
796
        $this->assertArrayNotHasKey('x-total-count', $response->headers->all());
797
    }
798
799
    /**
800
     * test getting schema information from canonical url
801
     *
802
     * @return void
803
     */
804
    public function testGetAppSchemaInformationCanonical()
805
    {
806
        $client = static::createRestClient();
807
        $client->request('GET', '/schema/core/app/item');
808
809
        $this->assertIsSchemaResponse($client->getResponse());
810
        $this->assertIsAppSchema($client->getResults());
811
    }
812
813
    /**
814
     * test getting collection schema
815
     *
816
     * @return void
817
     */
818
    public function testGetAppCollectionSchemaInformation()
819
    {
820
        $client = static::createRestClient();
821
822
        $client->request('GET', '/schema/core/app/collection');
823
824
        $response = $client->getResponse();
825
        $results = $client->getResults();
826
827
        $this->assertResponseContentType('application/schema+json', $response);
828
        $this->assertEquals(200, $response->getStatusCode());
829
830
        $this->assertEquals('Array of app objects', $results->title);
831
        $this->assertEquals('array', $results->type);
832
        $this->assertIsAppSchema($results->items);
833
        $this->assertEquals('en', $results->items->properties->name->required[0]);
834
835
        $this->assertCorsHeaders('GET, POST, PUT, PATCH, DELETE, OPTIONS', $response);
836
        $this->assertContains(
837
            'Link',
838
            explode(',', $response->headers->get('Access-Control-Expose-Headers'))
839
        );
840
841
        $this->assertContains(
842
            '<http://localhost/schema/core/app/collection>; rel="self"',
843
            explode(',', $response->headers->get('Link'))
844
        );
845
    }
846
847
    /**
848
     * Test for searchable translations
849
     *
850
     * @dataProvider searchableTranslationDataProvider
851
     *
852
     * @param string $expr     expression
853
     * @param int    $expCount count
854
     *
855
     * @return void
856
     */
857
    public function testSearchableTranslations($expr, $expCount)
858
    {
859
        $client = static::createRestClient();
860
        $client->request(
861
            'GET',
862
            '/core/app/?'.$expr,
863
            array(),
864
            array(),
865
            array('HTTP_ACCEPT_LANGUAGE' => 'en, de')
866
        );
867
868
        $result = $client->getResults();
869
        $this->assertCount($expCount, $result);
870
    }
871
872
    /**
873
     * see that if primary locale is not in accept languages, that we ca apply
874
     * changes on translatables anyway..
875
     *
876
     * @return void
877
     */
878
    public function testUpdateTranslatableOnlySecondaryLocale()
879
    {
880
        // 2. PATCH request
881
        $client = static::createRestClient();
882
        $patchJson = json_encode(
883
            [
884
                [
885
                    'op' => 'replace',
886
                    'path' => '/name/de',
887
                    'value' => 'Mein neuer Name'
888
                ]
889
            ]
890
        );
891
        $client->request('PATCH', '/core/app/tablet', [], [], ['HTTP_ACCEPT_LANGUAGE' => 'de'], $patchJson);
892
        $response = $client->getResponse();
893
894
        $this->assertEquals(200, $response->getStatusCode());
895
896
        $client = static::createRestClient();
897
898
        $client->request('GET', '/core/app/tablet', [], [], ['HTTP_ACCEPT_LANGUAGE' => 'de,en']);
899
        $result = $client->getResults();
900
901
        $this->assertEquals(200, $response->getStatusCode());
902
        $this->assertEquals('Tablet', $result->name->en);
903
        $this->assertEquals('Mein neuer Name', $result->name->de);
904
    }
905
906
    /**
907
     * data provider for searchable translations
908
     *
909
     * @return array data
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...
910
     */
911
    public function searchableTranslationDataProvider()
912
    {
913
        return [
914
            'simple-de' => array('eq(name.de,Die%20Administration)', 1),
915
            'non-existent' => array('eq(name.de,Administration)', 0),
916
            'english' => array('eq(name.en,Administration)', 1),
917
            'no-lang' => array('eq(name,Administration)', 1),
918
            'glob' => array('like(name.de,*Administr*)', 1),
919
            'all-glob' => array('like(name.de,*a*)', 2)
920
        ];
921
    }
922
923
    /**
924
     * ensure we have nice parse error output in rql parse failure
925
     *
926
     * @return void
927
     */
928 View Code Duplication
    public function testRqlSyntaxError()
929
    {
930
        $client = static::createRestClient();
931
932
        $client->request('GET', '/core/app/?eq(name)');
933
934
        $response = $client->getResponse();
935
        $results = $client->getResults();
936
937
        $this->assertEquals(400, $response->getStatusCode());
938
939
        $this->assertContains('syntax error in rql: ', $results->message);
940
        $this->assertContains('Unexpected token', $results->message);
941
    }
942
943
    /**
944
     * check if response looks like schema
945
     *
946
     * @param object $response response
947
     *
948
     * @return void
949
     */
950
    private function assertIsSchemaResponse($response)
951
    {
952
        $this->assertResponseContentType('application/schema+json', $response);
953
        $this->assertEquals(200, $response->getStatusCode());
954
    }
955
956
    /**
957
     * check if a schema is of the app type
958
     *
959
     * @param \stdClass $schema schema from service to validate
960
     *
961
     * @return void
962
     */
963
    private function assertIsAppSchema(\stdClass $schema)
964
    {
965
        $this->assertEquals('App', $schema->title);
966
        $this->assertEquals('A graviton based app.', $schema->description);
967
        $this->assertEquals('object', $schema->type);
968
969
        $this->assertEquals('string', $schema->properties->id->type);
970
        $this->assertEquals('ID', $schema->properties->id->title);
971
        $this->assertEquals('Unique identifier for an app.', $schema->properties->id->description);
972
        $this->assertContains('id', $schema->required);
973
974
        $this->assertEquals('object', $schema->properties->name->type);
975
        $this->assertEquals('translatable', $schema->properties->name->format);
976
        $this->assertEquals('Name', $schema->properties->name->title);
977
        $this->assertEquals('Display name for an app.', $schema->properties->name->description);
978
        $this->assertEquals('string', $schema->properties->name->properties->en->type);
979
        $this->assertContains('name', $schema->required);
980
981
        $this->assertEquals('boolean', $schema->properties->showInMenu->type);
982
        $this->assertEquals('Show in Menu', $schema->properties->showInMenu->title);
983
        $this->assertEquals(
984
            'Define if an app should be exposed on the top level menu.',
985
            $schema->properties->showInMenu->description
986
        );
987
    }
988
}
989