Completed
Push — master ( 4703e1...97bad7 )
by
unknown
11:22
created

AppControllerTest::testPostMalformedApp()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 29
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

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