Completed
Push — 6.13 ( 055733...f64074 )
by André
23:24 queued 09:44
created

assertVersionResponseContainsExpectedFields()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 1
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the Functional\ContentTest class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Bundle\EzPublishRestBundle\Tests\Functional;
10
11
use Buzz\Message\Response;
12
use eZ\Bundle\EzPublishRestBundle\Tests\Functional\TestCase as RESTFunctionalTestCase;
13
14
class ContentTest extends RESTFunctionalTestCase
15
{
16
    /**
17
     * Covers POST /content/objects.
18
     *
19
     * @return string REST content ID
20
     */
21 View Code Duplication
    public function testCreateContent()
22
    {
23
        $request = $this->createHttpRequest('POST', '/api/ezp/v2/content/objects', 'ContentCreate+xml', 'ContentInfo+json');
24
        $string = $this->addTestSuffix(__FUNCTION__);
25
        $body = <<< XML
26
<?xml version="1.0" encoding="UTF-8"?>
27
<ContentCreate>
28
  <ContentType href="/api/ezp/v2/content/types/1" />
29
  <mainLanguageCode>eng-GB</mainLanguageCode>
30
  <LocationCreate>
31
    <ParentLocation href="/api/ezp/v2/content/locations/1/2" />
32
    <priority>0</priority>
33
    <hidden>false</hidden>
34
    <sortField>PATH</sortField>
35
    <sortOrder>ASC</sortOrder>
36
  </LocationCreate>
37
  <Section href="/api/ezp/v2/content/sections/1" />
38
  <alwaysAvailable>true</alwaysAvailable>
39
  <remoteId>{$string}</remoteId>
40
  <User href="/api/ezp/v2/user/users/14" />
41
  <modificationDate>2012-09-30T12:30:00</modificationDate>
42
  <fields>
43
    <field>
44
      <fieldDefinitionIdentifier>name</fieldDefinitionIdentifier>
45
      <languageCode>eng-GB</languageCode>
46
      <fieldValue>{$string}</fieldValue>
47
    </field>
48
  </fields>
49
</ContentCreate>
50
XML;
51
        $request->setContent($body);
52
53
        $response = $this->sendHttpRequest($request);
54
55
        self::assertHttpResponseCodeEquals($response, 201);
56
        self::assertHttpResponseHasHeader($response, 'Location');
57
58
        $href = $response->getHeader('Location');
59
        $this->addCreatedElement($href);
60
61
        return $href;
62
    }
63
64
    /**
65
     * @depends testCreateContent
66
     * Covers PUBLISH /content/objects/<contentId>/versions/<versionNumber>
67
     *
68
     * @return string REST content ID
69
     */
70
    public function testPublishContent($restContentHref)
71
    {
72
        $response = $this->sendHttpRequest(
73
            $this->createHttpRequest('PUBLISH', "$restContentHref/versions/1")
74
        );
75
        self::assertHttpResponseCodeEquals($response, 204);
76
77
        return $restContentHref;
78
    }
79
80
    /**
81
     * @depends testPublishContent
82
     * Covers GET /content/objects?remoteId=<remoteId>
83
     */
84
    public function testRedirectContent($restContentHref)
85
    {
86
        $response = $this->sendHttpRequest(
87
            $this->createHttpRequest('GET', '/api/ezp/v2/content/objects?remoteId=' . $this->addTestSuffix('testCreateContent'))
88
        );
89
90
        self::assertHttpResponseCodeEquals($response, 307);
91
        self::assertEquals($response->getHeader('Location'), $restContentHref);
92
    }
93
94
    /**
95
     * @depends testPublishContent
96
     */
97
    public function testLoadContent($restContentHref)
98
    {
99
        $response = $this->sendHttpRequest(
100
            $this->createHttpRequest('GET', $restContentHref)
101
        );
102
103
        self::assertHttpResponseCodeEquals($response, 200);
104
        // @todo test data a bit ?
105
    }
106
107
    /**
108
     * @depends testPublishContent
109
     */
110 View Code Duplication
    public function testUpdateContentMetadata($restContentHref)
111
    {
112
        $string = $this->addTestSuffix(__FUNCTION__);
113
        $content = <<< XML
114
<?xml version="1.0" encoding="UTF-8"?>
115
<ContentUpdate>
116
  <Owner href="/api/ezp/v2/user/users/10"/>
117
  <remoteId>{$string}</remoteId>
118
</ContentUpdate>
119
XML;
120
        $request = $this->createHttpRequest('PATCH', $restContentHref, 'ContentUpdate+xml', 'ContentInfo+json');
121
        $request->setContent($content);
122
        $response = $this->sendHttpRequest($request);
123
        self::assertHttpResponseCodeEquals($response, 200);
124
125
        // @todo test data
126
    }
127
128
    /**
129
     * @depends testPublishContent
130
     *
131
     * @return string ContentVersion REST ID
132
     */
133 View Code Duplication
    public function testCreateDraftFromVersion($restContentHref)
134
    {
135
        $response = $this->sendHttpRequest(
136
            $this->createHttpRequest('COPY', "{$restContentHref}/versions/1")
137
        );
138
139
        self::assertHttpResponseCodeEquals($response, 201);
140
        self::assertEquals($response->getHeader('Location'), "{$restContentHref}/versions/2");
141
142
        return $response->getHeader('Location');
143
    }
144
145
    /**
146
     * @depends testPublishContent
147
     * Covers GET /content/objects/<contentId>/currentversion
148
     * @covers \eZ\Publish\Core\REST\Server\Controller\Content::redirectCurrentVersion
149
     */
150
    public function testRedirectCurrentVersion($restContentHref)
151
    {
152
        $response = $this->sendHttpRequest(
153
            $this->createHttpRequest('GET', "$restContentHref/currentversion")
154
        );
155
156
        self::assertHttpResponseCodeEquals($response, 307);
157
158
        self::assertHttpResponseHasHeader($response, 'Location', "$restContentHref/versions/1");
159
    }
160
161
    /**
162
     * @depends testCreateDraftFromVersion
163
     * Covers GET /content/objects/<contentId>/versions/<versionNumber>
164
     *
165
     * @param string $restContentVersionHref
166
     */
167
    public function testLoadContentVersion($restContentVersionHref)
168
    {
169
        $response = $this->sendHttpRequest(
170
            $this->createHttpRequest('GET', $restContentVersionHref)
171
        );
172
173
        self::assertHttpResponseCodeEquals($response, 200);
174
        $this->assertVersionResponseContainsExpectedFields($response);
175
        // @todo test filtering (language, fields, etc)
176
    }
177
178
    /**
179
     * Covers COPY /content/objects/<contentId>.
180
     * @depends testPublishContent
181
     *
182
     * @return string the copied content href
183
     */
184
    public function testCopyContent($restContentHref)
185
    {
186
        $testContent = $this->loadContent($restContentHref);
187
188
        $request = $this->createHttpRequest('COPY', $restContentHref);
189
        $request->addHeader('Destination: ' . $testContent['MainLocation']['_href']);
190
191
        $response = $this->sendHttpRequest($request);
192
193
        self::assertHttpResponseCodeEquals($response, 201);
194
        self::assertStringStartsWith('/api/ezp/v2/content/objects/', $response->getHeader('Location'));
195
196
        $this->addCreatedElement($response->getHeader('Location'));
197
198
        return $response->getHeader('Location');
199
    }
200
201
    /**
202
     * Covers DELETE /content/objects/<versionNumber>.
203
     * @depends testCopyContent
204
     */
205
    public function testDeleteContent($restContentHref)
206
    {
207
        self::markTestSkipped("Fails as the content created by copyContent isn't found");
208
        $response = $this->sendHttpRequest(
209
            $this->createHttpRequest('DELETE', $restContentHref)
210
        );
211
212
        self::assertHttpResponseCodeEquals($response, 204);
213
    }
214
215
    /**
216
     * @depends testPublishContent
217
     * Covers GET /content/objects/<contentId>/versions
218
     */
219
    public function testLoadContentVersions($restContentHref)
220
    {
221
        $response = $this->sendHttpRequest(
222
            $this->createHttpRequest('GET', "$restContentHref/versions", '', 'VersionList')
223
        );
224
225
        self::assertHttpResponseCodeEquals($response, 200);
226
    }
227
228
    /**
229
     * @depends testPublishContent
230
     *
231
     * @param string $restContentHref /content/objects/<contentId>
232
     * Covers COPY /content/objects/<contentId>/currentversion
233
     *
234
     * @return string the ID of the created version (/content/objects/<contentId>/versions/<versionNumber>
235
     */
236 View Code Duplication
    public function testCreateDraftFromCurrentVersion($restContentHref)
237
    {
238
        $response = $this->sendHttpRequest(
239
            $this->createHttpRequest('COPY', "$restContentHref/currentversion")
240
        );
241
242
        self::assertHttpResponseCodeEquals($response, 201);
243
        self::assertHttpResponseHasHeader($response, 'Location');
244
245
        return $response->getHeader('Location');
246
    }
247
248
    /**
249
     * @depends testCreateDraftFromCurrentVersion
250
     *
251
     * @param string $restContentVersionHref /api/ezp/v2/content/objects/<contentId>/versions>/<versionNumber>
252
     * Covers DELETE /api/ezp/v2/content/objects/<contentId>/versions>/<versionNumber>
253
     */
254
    public function testDeleteContentVersion($restContentVersionHref)
255
    {
256
        $response = $this->sendHttpRequest(
257
            $this->createHttpRequest('DELETE', $restContentVersionHref)
258
        );
259
260
        self::assertHttpResponseCodeEquals($response, 204);
261
    }
262
263
    /**
264
     * @depends testCreateDraftFromVersion
265
     * Covers PATCH /content/objects/<contentId>/versions>/<versionNumber>
266
     *
267
     * @param string $restContentVersionHref /content/objects/<contentId>/versions>/<versionNumber>
268
     */
269 View Code Duplication
    public function testUpdateVersion($restContentVersionHref)
270
    {
271
        $xml = <<< XML
272
<VersionUpdate>
273
    <fields>
274
        <field>
275
            <fieldDefinitionIdentifier>name</fieldDefinitionIdentifier>
276
            <languageCode>eng-GB</languageCode>
277
            <fieldValue>testUpdateVersion</fieldValue>
278
        </field>
279
    </fields>
280
</VersionUpdate>
281
XML;
282
283
        $request = $this->createHttpRequest('PATCH', $restContentVersionHref, 'VersionUpdate+xml', 'Version+json');
284
        $request->setContent($xml);
285
        $response = $this->sendHttpRequest(
286
            $request
287
        );
288
289
        self::assertHttpResponseCodeEquals($response, 200);
290
    }
291
292
    /**
293
     * @depends testPublishContent
294
     * Covers GET /content/objects/<contentId>/relations
295
     */
296
    public function testRedirectCurrentVersionRelations($restContentHref)
297
    {
298
        $response = $this->sendHttpRequest(
299
            $this->createHttpRequest('GET', "$restContentHref/relations")
300
        );
301
302
        self::assertHttpResponseCodeEquals($response, 307);
303
304
        // @todo Fix, see EZP-21059. Meanwhile, the test is skipped if it fails as expected
305
        // self::assertHttpResponseHasHeader( $response, 'Location', "$restContentHref/versions/1/relations" );
306
        self::assertHttpResponseHasHeader($response, 'Location', "$restContentHref/relations?versionNumber=1");
307
        self::markTestIncomplete('@todo Fix issue EZP-21059');
308
    }
309
310
    /**
311
     * @depends testCreateDraftFromVersion
312
     * Covers GET /content/objects/<contentId>/versions/<versionNumber>/relations
313
     */
314
    public function testLoadVersionRelations($restContentVersionHref)
315
    {
316
        $response = $this->sendHttpRequest(
317
            $this->createHttpRequest('GET', "$restContentVersionHref/relations")
318
        );
319
320
        self::assertHttpResponseCodeEquals($response, 200);
321
    }
322
323
    /**
324
     * @depends testCreateDraftFromVersion
325
     * Covers POST /content/objects/<contentId>/versions/<versionNumber>/relations/<relationId>
326
     *
327
     * @return string created relation HREF (/content/objects/<contentId>/versions/<versionNumber>/relations/<relationId>
328
     */
329 View Code Duplication
    public function testCreateRelation($restContentVersionHref)
330
    {
331
        $content = <<< XML
332
<?xml version="1.0" encoding="UTF-8"?>
333
<RelationCreate>
334
  <Destination href="/api/ezp/v2/content/objects/10"/>
335
</RelationCreate>
336
XML;
337
338
        $request = $this->createHttpRequest('POST', "$restContentVersionHref/relations", 'RelationCreate+xml', 'Relation+json');
339
        $request->setContent($content);
340
341
        $response = $this->sendHttpRequest($request);
342
343
        self::assertHttpResponseCodeEquals($response, 201);
344
345
        $response = json_decode($response->getContent(), true);
346
347
        return $response['Relation']['_href'];
348
    }
349
350
    /**
351
     * @depends testCreateRelation
352
     * Covers GET /content/objects/<contentId>/versions/<versionNo>/relations/<relationId>
353
     */
354
    public function testLoadVersionRelation($restContentRelationHref)
355
    {
356
        $response = $this->sendHttpRequest(
357
            $this->createHttpRequest('GET', $restContentRelationHref)
358
        );
359
360
        self::assertHttpResponseCodeEquals($response, 200);
361
362
        // @todo test data
363
    }
364
365
    /**
366
     * Returns the Content key from the decoded JSON of $restContentId's contentInfo.
367
     *
368
     *
369
     * @throws \InvalidArgumentException
370
     *
371
     * @param string $restContentHref /api/ezp/v2/content/objects/<contentId>
372
     *
373
     * @return array
374
     */
375
    private function loadContent($restContentHref)
376
    {
377
        $response = $this->sendHttpRequest(
378
            $this->createHttpRequest('GET', $restContentHref, '', 'ContentInfo+json')
379
        );
380
381
        if ($response->getStatusCode() != 200) {
382
            throw new \InvalidArgumentException("Content with ID $restContentHref could not be loaded");
383
        }
384
385
        $array = json_decode($response->getContent(), true);
386
        if ($array === null) {
387
            self::fail('Error loading content. Response: ' . $response->getContent());
388
        }
389
390
        return $array['Content'];
391
    }
392
393 View Code Duplication
    public function testCreateView()
394
    {
395
        $body = <<< XML
396
<?xml version="1.0" encoding="UTF-8"?>
397
<ViewInput>
398
  <identifier>testCreateView</identifier>
399
  <Query>
400
    <Criteria>
401
      <ContentTypeIdentifierCriterion>folder</ContentTypeIdentifierCriterion>
402
    </Criteria>
403
    <limit>10</limit>
404
    <offset>0</offset>
405
  </Query>
406
</ViewInput>
407
XML;
408
        $request = $this->createHttpRequest('POST', '/api/ezp/v2/content/views', 'ViewInput+xml', 'View+json');
409
        $request->setContent($body);
410
        $response = $this->sendHttpRequest(
411
            $request
412
        );
413
414
        // Returns 301 since 6.0 (deprecated in favour of /views)
415
        self::assertHttpResponseCodeEquals($response, 301);
416
        self::assertHttpResponseHasHeader($response, 'Location');
417
    }
418
419
    /**
420
     * Covers DELETE /content/objects/<contentId>/versions/<versionNo>/translations/<languageCode>.
421
     *
422
     * @depends testCreateDraftFromVersion
423
     *
424
     * @param string $restContentVersionHref
425
     */
426
    public function testDeleteTranslationFromDraft($restContentVersionHref)
427
    {
428
        // create pol-PL Translation
429
        $translationToDelete = 'pol-PL';
430
        $this->createVersionTranslation($restContentVersionHref, $translationToDelete, 'Polish');
431
432
        $response = $this->sendHttpRequest(
433
            $this->createHttpRequest('DELETE', $restContentVersionHref . "/translations/{$translationToDelete}")
434
        );
435
        self::assertHttpResponseCodeEquals($response, 204);
436
437
        // check that the Translation was deleted by reloading Version
438
        $response = $this->sendHttpRequest(
439
            $this->createHttpRequest('GET', $restContentVersionHref, '', 'Version+json')
440
        );
441
442
        $version = json_decode($response->getContent(), true);
443
        self::assertNotContains($translationToDelete, $version['Version']['VersionInfo']['languageCodes']);
444
    }
445
446
    /**
447
     * Test that VersionInfo loaded in VersionList contains working DeleteTranslation resource link.
448
     *
449
     * Covers DELETE /content/objects/<contentId>/versions/<versionNo>/translations/<languageCode>.
450
     * Covers GET /content/objects/<contentId>/versions
451
     *
452
     * @depends testCreateDraftFromVersion
453
     *
454
     * @param string $restContentVersionHref
455
     */
456
    public function testLoadContentVersionsProvidesDeleteTranslationFromDraftResourceLink($restContentVersionHref)
457
    {
458
        $translationToDelete = 'pol-PL';
459
        // create Version Draft containing pol-PL Translation
460
        $this->createVersionTranslation($restContentVersionHref, $translationToDelete, 'Polish');
461
462
        // load Version
463
        $response = $this->sendHttpRequest(
464
            $this->createHttpRequest('GET', $restContentVersionHref, '', 'Version+json')
465
        );
466
        self::assertHttpResponseCodeEquals($response, 200);
467
        $version = json_decode($response->getContent(), true);
468
469
        // load all Versions
470
        self::assertNotEmpty($version['Version']['VersionInfo']['Content']['_href']);
471
        $restLoadContentVersionsHref = $version['Version']['VersionInfo']['Content']['_href'] . '/versions';
472
        $response = $this->sendHttpRequest(
473
            $this->createHttpRequest('GET', $restLoadContentVersionsHref, '', 'VersionList+json')
474
        );
475
        self::assertHttpResponseCodeEquals($response, 200);
476
477
        // load Version list
478
        $versionList = json_decode($response->getContent(), true);
479
        $version = $this->getVersionInfoFromJSONVersionListByStatus(
480
            $versionList['VersionList'],
481
            'DRAFT'
482
        );
483
484
        // validate VersionTranslationInfo structure
485
        self::assertNotEmpty($version['VersionTranslationInfo']['Language']);
486
        foreach ($version['VersionTranslationInfo']['Language'] as $versionTranslationInfo) {
487
            // Other Translation, as the main one, shouldn't be deletable
488
            if ($versionTranslationInfo['languageCode'] !== $translationToDelete) {
489
                // check that endpoint is not provided for non-deletable Translation
490
                self::assertTrue(empty($versionTranslationInfo['DeleteTranslation']['_href']));
491
            } else {
492
                // check that provided endpoint works
493
                self::assertNotEmpty($versionTranslationInfo['DeleteTranslation']['_href']);
494
                $response = $this->sendHttpRequest(
495
                    $this->createHttpRequest(
496
                        'DELETE',
497
                        $versionTranslationInfo['DeleteTranslation']['_href']
498
                    )
499
                );
500
                self::assertHttpResponseCodeEquals($response, 204);
501
            }
502
        }
503
    }
504
505
    /**
506
     * Publish another Version with new Translation.
507
     *
508
     * @param string $restContentVersionHref
509
     *
510
     * @param string $languageCode
511
     * @param string $languageName
512
     *
513
     * @return string
514
     */
515 View Code Duplication
    private function createVersionTranslation($restContentVersionHref, $languageCode, $languageName)
516
    {
517
        $this->ensureLanguageExists($languageCode, $languageName);
518
519
        $xml = <<< XML
520
<VersionUpdate>
521
    <fields>
522
        <field>
523
            <fieldDefinitionIdentifier>name</fieldDefinitionIdentifier>
524
            <languageCode>{$languageCode}</languageCode>
525
            <fieldValue>{$languageName} translated name</fieldValue>
526
        </field>
527
    </fields>
528
</VersionUpdate>
529
XML;
530
531
        $request = $this->createHttpRequest('PATCH', $restContentVersionHref, 'VersionUpdate+xml', 'Version+json');
532
        $request->setContent($xml);
533
        $response = $this->sendHttpRequest(
534
            $request
535
        );
536
537
        self::assertHttpResponseCodeEquals($response, 200);
538
    }
539
540
    /**
541
     * Make REST API calls to check if the given Language exists and create it if it doesn't.
542
     *
543
     * @param string $languageCode
544
     * @param string $languageName
545
     */
546
    private function ensureLanguageExists($languageCode, $languageName)
0 ignored issues
show
Unused Code introduced by
The parameter $languageCode is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $languageName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
547
    {
548
        self::markTestIncomplete('@todo: Implement EZP-21171');
549
    }
550
551
    /**
552
     * Iterate through Version Items returned by REST view for ContentType: VersionList+json
553
     * and return first VersionInfo data matching given status.
554
     *
555
     * @param array $versionList
556
     * @param string $status uppercase string representation of Version status
557
     *
558
     * @return array
559
     */
560
    private function getVersionInfoFromJSONVersionListByStatus(array $versionList, $status)
561
    {
562
        foreach ($versionList['VersionItem'] as $versionItem) {
563
            if ($versionItem['VersionInfo']['status'] === $status) {
564
                return $versionItem['VersionInfo'];
565
            }
566
        }
567
568
        throw new \RuntimeException("Test internal error: Version with status {$status} not found");
569
    }
570
571
    /**
572
     * Assert that Version REST Response contains proper fields.
573
     *
574
     * @param \Buzz\Message\Response $response
575
     */
576
    private function assertVersionResponseContainsExpectedFields(Response $response)
577
    {
578
        $contentType = $response->getHeader('Content-Type');
579
        self::assertNotEmpty($contentType);
580
581
        $responseBody = $response->getContent();
582
583
        // check if response is of an expected Content-Type
584
        self::assertEquals('Version+xml', $this->getMediaFromTypeString($contentType));
585
586
        // validate by custom XSD
587
        $document = new \DOMDocument();
588
        $document->loadXML($responseBody);
589
        $document->schemaValidate(__DIR__ . '/xsd/Version.xsd');
590
    }
591
}
592