Completed
Push — master ( 25b499...2ea727 )
by Lucas
19:04 queued 08:47
created

AppControllerTest::testGetApp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 13

Duplication

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