Completed
Push — ezp26179-rest_session_refresh_... ( b20337...d0f758 )
by
unknown
24:25
created

TestCase::getContentLocations()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 10
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 1
dl 10
loc 10
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the Functional\TestCase 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
 * @version //autogentag//
10
 */
11
namespace eZ\Bundle\EzPublishRestBundle\Tests\Functional;
12
13
use Buzz\Message\Request as HttpRequest;
14
use Buzz\Message\Response as HttpResponse;
15
use PHPUnit_Framework_TestCase;
16
17
class TestCase extends PHPUnit_Framework_TestCase
18
{
19
    /**
20
     * @var \Buzz\Client\ClientInterface
21
     */
22
    private $httpClient;
23
24
    /**
25
     * @var string
26
     */
27
    private $httpHost;
28
29
    /**
30
     * @var string
31
     * Basic auth login:password
32
     */
33
    private $httpAuth;
34
35
    protected static $testSuffix;
36
37
    /**
38
     * @var array
39
     */
40
    private $headers = [];
41
42
    /**
43
     * If true, a login request is automatically done during setUp().
44
     * @var bool
45
     */
46
    protected $autoLogin = true;
47
48
    protected function setUp()
49
    {
50
        parent::setUp();
51
52
        $this->httpHost = getenv('EZP_TEST_REST_HOST') ?: 'localhost';
53
        $this->httpAuth = getenv('EZP_TEST_REST_AUTH') ?: 'admin:publish';
54
55
        $this->httpClient = new \Buzz\Client\Curl();
56
        $this->httpClient->setVerifyPeer(false);
57
        $this->httpClient->setTimeout(90);
58
        $this->httpClient->setOption(CURLOPT_FOLLOWLOCATION, false);
59
60
        if ($this->autoLogin) {
61
            $session = $this->login();
62
            $this->headers[] = sprintf('Cookie: %s=%s', $session->name, $session->identifier);
63
            $this->headers[] = sprintf('X-CSRF-Token: %s', $session->csrfToken);
64
        }
65
    }
66
67
    /**
68
     * @return HttpResponse
69
     */
70
    public function sendHttpRequest(HttpRequest $request)
71
    {
72
        $response = new HttpResponse();
73
        $this->httpClient->send($request, $response);
74
75
        return $response;
76
    }
77
78
    protected function getHttpHost()
79
    {
80
        return $this->httpHost;
81
    }
82
83
    /**
84
     * @return HttpRequest
85
     */
86
    public function createHttpRequest($method, $uri, $contentType = '', $acceptType = '')
87
    {
88
        $headers = array_merge(
89
            $method === 'POST' && $uri === '/api/ezp/v2/user/sessions' ? [] : $this->headers,
90
            [
91
                'Content-Type: ' . $this->generateMediaTypeString($contentType),
92
                'Accept: ' . $this->generateMediaTypeString($acceptType),
93
            ]
94
        );
95
96
        switch ($method) {
97
            case 'PUBLISH': $method = 'POST';  $headers[] = 'X-HTTP-Method-Override: PUBLISH'; break;
98
            case 'MOVE':    $method = 'POST';  $headers[] = 'X-HTTP-Method-Override: MOVE';    break;
99
            case 'PATCH':   $method = 'PATCH'; $headers[] = 'X-HTTP-Method-Override: PATCH';   break;
100
            case 'COPY':    $method = 'POST';  $headers[] = 'X-HTTP-Method-Override: COPY';    break;
101
        }
102
103
        $request = new HttpRequest($method, $uri, $this->httpHost);
104
        $request->addHeaders($headers);
105
106
        return $request;
107
    }
108
109
    protected function assertHttpResponseCodeEquals(HttpResponse $response, $expected)
110
    {
111
        $responseCode = $response->getStatusCode();
112
        if ($responseCode != $expected) {
113
            $errorMessageString = '';
114
            if (strpos($response->getHeader('Content-Type'), 'application/vnd.ez.api.ErrorMessage+xml') !== false) {
115
                $body = \simplexml_load_string($response->getContent());
116
                $errorMessageString = $this->getHttpResponseCodeErrorMessage($body);
117
            } elseif (strpos($response->getHeader('Content-Type'), 'application/vnd.ez.api.ErrorMessage+json') !== false) {
118
                $body = json_decode($response->getContent());
119
                $errorMessageString = $this->getHttpResponseCodeErrorMessage($body->ErrorMessage);
120
            }
121
122
            self::assertEquals($expected, $responseCode, $errorMessageString);
123
        }
124
    }
125
126
    private function getHttpResponseCodeErrorMessage($errorMessage)
127
    {
128
        $errorMessageString = <<< EOF
129
Server error message ({$errorMessage->errorCode}): {$errorMessage->errorMessage}
130
131
{$errorMessage->errorDescription}
132
133
EOF;
134
135
        // If server is in debug mode it will return file, line and trace.
136
        if (!empty($errorMessage->file)) {
137
            $errorMessageString .= "\nIn {$errorMessage->file}:{$errorMessage->line}\n\n{$errorMessage->trace}";
138
        } else {
139
            $errorMessageString .= "\nIn \<no trace, debug disabled\>";
140
        }
141
142
        return $errorMessageString;
143
    }
144
145
    protected function assertHttpResponseHasHeader(HttpResponse $response, $header, $expectedValue = null)
146
    {
147
        $headerValue = $response->getHeader($header);
148
        self::assertNotNull($headerValue, "Failed asserting that response has a $header header");
149
        if ($expectedValue !== null) {
150
            self::assertEquals($expectedValue, $headerValue);
151
        }
152
    }
153
154
    protected function generateMediaTypeString($typeString)
155
    {
156
        return "application/vnd.ez.api.$typeString";
157
    }
158
159
    protected function addCreatedElement($href)
160
    {
161
        $testCase = $this;
162
        self::$createdContent[$href] = function () use ($href, $testCase) {
163
            $testCase->sendHttpRequest(
164
                $testCase->createHttpRequest('DELETE', $href)
165
            );
166
        };
167
    }
168
169
    public static function tearDownAfterClass()
170
    {
171
        self::clearCreatedElement(self::$createdContent);
172
    }
173
174
    private static function clearCreatedElement(array $contentArray)
175
    {
176
        foreach (array_reverse($contentArray) as $href => $callback) {
177
            $callback();
178
        }
179
    }
180
181
    /**
182
     * @param string $parentLocationId The REST id of the parent location
183
     *
184
     * @return array created Content, as an array
185
     */
186
    protected function createFolder($string, $parentLocationId)
187
    {
188
        $string = $this->addTestSuffix($string);
189
        $xml = <<< XML
190
<?xml version="1.0" encoding="UTF-8"?>
191
<ContentCreate>
192
  <ContentType href="/api/ezp/v2/content/types/1" />
193
  <mainLanguageCode>eng-GB</mainLanguageCode>
194
  <LocationCreate>
195
    <ParentLocation href="{$parentLocationId}" />
196
    <priority>0</priority>
197
    <hidden>false</hidden>
198
    <sortField>PATH</sortField>
199
    <sortOrder>ASC</sortOrder>
200
  </LocationCreate>
201
  <Section href="/api/ezp/v2/content/sections/1" />
202
  <alwaysAvailable>true</alwaysAvailable>
203
  <remoteId>{$string}</remoteId>
204
  <User href="/api/ezp/v2/user/users/14" />
205
  <modificationDate>2012-09-30T12:30:00</modificationDate>
206
  <fields>
207
    <field>
208
      <fieldDefinitionIdentifier>name</fieldDefinitionIdentifier>
209
      <languageCode>eng-GB</languageCode>
210
      <fieldValue>{$string}</fieldValue>
211
    </field>
212
  </fields>
213
</ContentCreate>
214
XML;
215
216
        return $this->createContent($xml);
217
    }
218
219
    /**
220
     * @param $xml
221
     *
222
     * @return array Content key of the Content struct array
223
     */
224
    protected function createContent($xml)
225
    {
226
        $request = $this->createHttpRequest('POST', '/api/ezp/v2/content/objects', 'ContentCreate+xml', 'Content+json');
227
        $request->setContent($xml);
228
229
        $response = $this->sendHttpRequest($request);
230
231
        self::assertHttpResponseCodeEquals($response, 201);
232
233
        $content = json_decode($response->getContent(), true);
234
235
        if (!isset($content['Content']['CurrentVersion']['Version'])) {
236
            self::fail("Incomplete response (no version):\n" . $response->getContent() . "\n");
237
        }
238
239
        $response = $this->sendHttpRequest(
240
            $request = $this->createHttpRequest('PUBLISH', $content['Content']['CurrentVersion']['Version']['_href'])
241
        );
242
243
        self::assertHttpResponseCodeEquals($response, 204);
244
245
        $this->addCreatedElement($content['Content']['_href'], true);
246
247
        return $content['Content'];
248
    }
249
250
    /**
251
     * @param string $contentHref
252
     *
253
     * @return array
254
     */
255 View Code Duplication
    protected function getContentLocations($contentHref)
256
    {
257
        $response = $this->sendHttpRequest(
258
            $this->createHttpRequest('GET', "$contentHref/locations", '', 'LocationList+json')
259
        );
260
        self::assertHttpResponseCodeEquals($response, 200);
261
        $folderLocations = json_decode($response->getContent(), true);
262
263
        return $folderLocations;
264
    }
265
266
    protected function addTestSuffix($string)
267
    {
268
        if (!isset(self::$testSuffix)) {
269
            self::$testSuffix = uniqid();
270
        }
271
272
        return $string . '_' . self::$testSuffix;
273
    }
274
275
    /**
276
     * List of REST contentId (/content/objects/12345) created by tests.
277
     *
278
     * @var array
279
     */
280
    private static $createdContent = array();
281
282
    /**
283
     * Sends a login request to the REST server.
284
     *
285
     * @return \stdClass an object with the name, identifier, csrftoken properties.
286
     */
287 View Code Duplication
    protected function login()
288
    {
289
        $request = $this->createHttpRequest('POST', '/api/ezp/v2/user/sessions', 'SessionInput+json', 'Session+json');
290
        $request->setContent('{"SessionInput": {"login": "admin", "password": "publish"}}');
291
        $response = $this->sendHttpRequest($request);
292
        self::assertHttpResponseCodeEquals($response, 201);
293
294
        return json_decode($response->getContent())->Session;
295
    }
296
}
297