Completed
Push — feature/EVO-7278-created-by-pr... ( a1521a )
by
unknown
66:28
created

AppControllerTest::testFindAllEmptyCollection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 8

Duplication

Lines 14
Ratio 100 %

Importance

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