These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * |
||
4 | * @todo Test Relation getters |
||
5 | * @todo Test filter and limit through GET params |
||
6 | * @todo Test DELETE verb |
||
7 | * |
||
8 | */ |
||
9 | class RestfulServerTest extends SapphireTest |
||
10 | { |
||
11 | public static $fixture_file = 'RestfulServerTest.yml'; |
||
12 | |||
13 | protected $extraDataObjects = array( |
||
14 | 'RestfulServerTest_Comment', |
||
15 | 'RestfulServerTest_SecretThing', |
||
16 | 'RestfulServerTest_Page', |
||
17 | 'RestfulServerTest_Author', |
||
18 | 'RestfulServerTest_AuthorRating', |
||
19 | ); |
||
20 | |||
21 | View Code Duplication | public function testApiAccess() |
|
0 ignored issues
–
show
testApiAccess uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
22 | { |
||
23 | $comment1 = $this->objFromFixture('RestfulServerTest_Comment', 'comment1'); |
||
24 | $page1 = $this->objFromFixture('RestfulServerTest_Page', 'page1'); |
||
25 | |||
26 | // normal GET should succeed with $api_access enabled |
||
27 | $url = "/api/v1/RestfulServerTest_Comment/" . $comment1->ID; |
||
28 | $response = Director::test($url, null, null, 'GET'); |
||
29 | $this->assertEquals($response->getStatusCode(), 200); |
||
30 | |||
31 | $_SERVER['PHP_AUTH_USER'] = '[email protected]'; |
||
32 | $_SERVER['PHP_AUTH_PW'] = 'user'; |
||
33 | |||
34 | // even with logged in user a GET with $api_access disabled should fail |
||
35 | $url = "/api/v1/RestfulServerTest_Page/" . $page1->ID; |
||
36 | $response = Director::test($url, null, null, 'GET'); |
||
37 | $this->assertEquals($response->getStatusCode(), 401); |
||
38 | |||
39 | unset($_SERVER['PHP_AUTH_USER']); |
||
40 | unset($_SERVER['PHP_AUTH_PW']); |
||
41 | } |
||
42 | |||
43 | public function testApiAccessBoolean() |
||
44 | { |
||
45 | $comment1 = $this->objFromFixture('RestfulServerTest_Comment', 'comment1'); |
||
46 | |||
47 | $url = "/api/v1/RestfulServerTest_Comment/" . $comment1->ID; |
||
48 | $response = Director::test($url, null, null, 'GET'); |
||
49 | $this->assertContains('<ID>', $response->getBody()); |
||
50 | $this->assertContains('<Name>', $response->getBody()); |
||
51 | $this->assertContains('<Comment>', $response->getBody()); |
||
52 | $this->assertContains('<Page', $response->getBody()); |
||
53 | $this->assertContains('<Author', $response->getBody()); |
||
54 | } |
||
55 | |||
56 | View Code Duplication | public function testAuthenticatedGET() |
|
0 ignored issues
–
show
testAuthenticatedGET uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
57 | { |
||
58 | $thing1 = $this->objFromFixture('RestfulServerTest_SecretThing', 'thing1'); |
||
59 | $comment1 = $this->objFromFixture('RestfulServerTest_Comment', 'comment1'); |
||
60 | |||
61 | // @todo create additional mock object with authenticated VIEW permissions |
||
62 | $url = "/api/v1/RestfulServerTest_SecretThing/" . $thing1->ID; |
||
63 | $response = Director::test($url, null, null, 'GET'); |
||
64 | $this->assertEquals($response->getStatusCode(), 401); |
||
65 | |||
66 | $_SERVER['PHP_AUTH_USER'] = '[email protected]'; |
||
67 | $_SERVER['PHP_AUTH_PW'] = 'user'; |
||
68 | |||
69 | $url = "/api/v1/RestfulServerTest_Comment/" . $comment1->ID; |
||
70 | $response = Director::test($url, null, null, 'GET'); |
||
71 | $this->assertEquals($response->getStatusCode(), 200); |
||
72 | |||
73 | unset($_SERVER['PHP_AUTH_USER']); |
||
74 | unset($_SERVER['PHP_AUTH_PW']); |
||
75 | } |
||
76 | |||
77 | public function testAuthenticatedPUT() |
||
0 ignored issues
–
show
testAuthenticatedPUT uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
78 | { |
||
79 | $comment1 = $this->objFromFixture('RestfulServerTest_Comment', 'comment1'); |
||
80 | |||
81 | $url = "/api/v1/RestfulServerTest_Comment/" . $comment1->ID; |
||
82 | $data = array('Comment' => 'created'); |
||
83 | |||
84 | $response = Director::test($url, $data, null, 'PUT'); |
||
85 | $this->assertEquals($response->getStatusCode(), 401); // Permission failure |
||
86 | |||
87 | $_SERVER['PHP_AUTH_USER'] = '[email protected]'; |
||
88 | $_SERVER['PHP_AUTH_PW'] = 'editor'; |
||
89 | $response = Director::test($url, $data, null, 'PUT'); |
||
90 | $this->assertEquals($response->getStatusCode(), 200); // Success |
||
91 | |||
92 | unset($_SERVER['PHP_AUTH_USER']); |
||
93 | unset($_SERVER['PHP_AUTH_PW']); |
||
94 | } |
||
95 | |||
96 | public function testGETRelationshipsXML() |
||
97 | { |
||
98 | $author1 = $this->objFromFixture('RestfulServerTest_Author', 'author1'); |
||
99 | $rating1 = $this->objFromFixture('RestfulServerTest_AuthorRating', 'rating1'); |
||
100 | $rating2 = $this->objFromFixture('RestfulServerTest_AuthorRating', 'rating2'); |
||
101 | |||
102 | // @todo should be set up by fixtures, doesn't work for some reason... |
||
103 | $author1->Ratings()->add($rating1); |
||
104 | $author1->Ratings()->add($rating2); |
||
105 | |||
106 | $url = "/api/v1/RestfulServerTest_Author/" . $author1->ID; |
||
107 | $response = Director::test($url, null, null, 'GET'); |
||
108 | $this->assertEquals($response->getStatusCode(), 200); |
||
109 | |||
110 | $responseArr = Convert::xml2array($response->getBody()); |
||
111 | $ratingsArr = $responseArr['Ratings']['RestfulServerTest_AuthorRating']; |
||
112 | $this->assertEquals(count($ratingsArr), 2); |
||
113 | $ratingIDs = array( |
||
114 | (int)$ratingsArr[0]['@attributes']['id'], |
||
115 | (int)$ratingsArr[1]['@attributes']['id'] |
||
116 | ); |
||
117 | $this->assertContains($rating1->ID, $ratingIDs); |
||
118 | $this->assertContains($rating2->ID, $ratingIDs); |
||
119 | } |
||
120 | |||
121 | public function testGETManyManyRelationshipsXML() |
||
122 | { |
||
123 | // author4 has related authors author2 and author3 |
||
124 | $author2 = $this->objFromFixture('RestfulServerTest_Author', 'author2'); |
||
125 | $author3 = $this->objFromFixture('RestfulServerTest_Author', 'author3'); |
||
126 | $author4 = $this->objFromFixture('RestfulServerTest_Author', 'author4'); |
||
127 | |||
128 | $url = "/api/v1/RestfulServerTest_Author/" . $author4->ID . '/RelatedAuthors'; |
||
129 | $response = Director::test($url, null, null, 'GET'); |
||
130 | $this->assertEquals(200, $response->getStatusCode()); |
||
131 | $arr = Convert::xml2array($response->getBody()); |
||
132 | $authorsArr = $arr['RestfulServerTest_Author']; |
||
133 | |||
134 | $this->assertEquals(count($authorsArr), 2); |
||
135 | $ratingIDs = array( |
||
136 | (int)$authorsArr[0]['ID'], |
||
137 | (int)$authorsArr[1]['ID'] |
||
138 | ); |
||
139 | $this->assertContains($author2->ID, $ratingIDs); |
||
140 | $this->assertContains($author3->ID, $ratingIDs); |
||
141 | } |
||
142 | |||
143 | public function testPUTWithFormEncoded() |
||
0 ignored issues
–
show
testPUTWithFormEncoded uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
144 | { |
||
145 | $comment1 = $this->objFromFixture('RestfulServerTest_Comment', 'comment1'); |
||
146 | |||
147 | $_SERVER['PHP_AUTH_USER'] = '[email protected]'; |
||
148 | $_SERVER['PHP_AUTH_PW'] = 'editor'; |
||
149 | |||
150 | $url = "/api/v1/RestfulServerTest_Comment/" . $comment1->ID; |
||
151 | $body = 'Name=Updated Comment&Comment=updated'; |
||
152 | $headers = array( |
||
153 | 'Content-Type' => 'application/x-www-form-urlencoded' |
||
154 | ); |
||
155 | $response = Director::test($url, null, null, 'PUT', $body, $headers); |
||
156 | $this->assertEquals($response->getStatusCode(), 200); // Success |
||
157 | // Assumption: XML is default output |
||
158 | $responseArr = Convert::xml2array($response->getBody()); |
||
159 | $this->assertEquals($responseArr['ID'], $comment1->ID); |
||
160 | $this->assertEquals($responseArr['Comment'], 'updated'); |
||
161 | $this->assertEquals($responseArr['Name'], 'Updated Comment'); |
||
162 | |||
163 | unset($_SERVER['PHP_AUTH_USER']); |
||
164 | unset($_SERVER['PHP_AUTH_PW']); |
||
165 | } |
||
166 | |||
167 | public function testPOSTWithFormEncoded() |
||
0 ignored issues
–
show
testPOSTWithFormEncoded uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
168 | { |
||
169 | $comment1 = $this->objFromFixture('RestfulServerTest_Comment', 'comment1'); |
||
170 | |||
171 | $_SERVER['PHP_AUTH_USER'] = '[email protected]'; |
||
172 | $_SERVER['PHP_AUTH_PW'] = 'editor'; |
||
173 | |||
174 | $url = "/api/v1/RestfulServerTest_Comment"; |
||
175 | $body = 'Name=New Comment&Comment=created'; |
||
176 | $headers = array( |
||
177 | 'Content-Type' => 'application/x-www-form-urlencoded' |
||
178 | ); |
||
179 | $response = Director::test($url, null, null, 'POST', $body, $headers); |
||
180 | $this->assertEquals($response->getStatusCode(), 201); // Created |
||
181 | // Assumption: XML is default output |
||
182 | $responseArr = Convert::xml2array($response->getBody()); |
||
183 | $this->assertTrue($responseArr['ID'] > 0); |
||
184 | $this->assertNotEquals($responseArr['ID'], $comment1->ID); |
||
185 | $this->assertEquals($responseArr['Comment'], 'created'); |
||
186 | $this->assertEquals($responseArr['Name'], 'New Comment'); |
||
187 | $this->assertEquals( |
||
188 | $response->getHeader('Location'), |
||
189 | Controller::join_links(Director::absoluteBaseURL(), $url, $responseArr['ID']) |
||
190 | ); |
||
191 | |||
192 | unset($_SERVER['PHP_AUTH_USER']); |
||
193 | unset($_SERVER['PHP_AUTH_PW']); |
||
194 | } |
||
195 | |||
196 | public function testPUTwithJSON() |
||
0 ignored issues
–
show
testPUTwithJSON uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
197 | { |
||
198 | $comment1 = $this->objFromFixture('RestfulServerTest_Comment', 'comment1'); |
||
199 | |||
200 | $_SERVER['PHP_AUTH_USER'] = '[email protected]'; |
||
201 | $_SERVER['PHP_AUTH_PW'] = 'editor'; |
||
202 | |||
203 | // by mimetype |
||
204 | $url = "/api/v1/RestfulServerTest_Comment/" . $comment1->ID; |
||
205 | $body = '{"Comment":"updated"}'; |
||
206 | $response = Director::test($url, null, null, 'PUT', $body, array('Content-Type'=>'application/json')); |
||
207 | $this->assertEquals($response->getStatusCode(), 200); // Updated |
||
208 | $obj = Convert::json2obj($response->getBody()); |
||
209 | $this->assertEquals($obj->ID, $comment1->ID); |
||
0 ignored issues
–
show
The method
assertEquals() does not seem to exist on object<RestfulServerTest> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed.
Loading history...
|
|||
210 | $this->assertEquals($obj->Comment, 'updated'); |
||
0 ignored issues
–
show
The method
assertEquals() does not seem to exist on object<RestfulServerTest> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed.
Loading history...
|
|||
211 | |||
212 | // by extension |
||
213 | $url = sprintf("/api/v1/RestfulServerTest_Comment/%d.json", $comment1->ID); |
||
214 | $body = '{"Comment":"updated"}'; |
||
215 | $response = Director::test($url, null, null, 'PUT', $body); |
||
216 | $this->assertEquals($response->getStatusCode(), 200); // Updated |
||
217 | $this->assertEquals( |
||
218 | $response->getHeader('Location'), |
||
219 | Controller::join_links(Director::absoluteBaseURL(), $url) |
||
220 | ); |
||
221 | $obj = Convert::json2obj($response->getBody()); |
||
222 | $this->assertEquals($obj->ID, $comment1->ID); |
||
223 | $this->assertEquals($obj->Comment, 'updated'); |
||
224 | |||
225 | unset($_SERVER['PHP_AUTH_USER']); |
||
226 | unset($_SERVER['PHP_AUTH_PW']); |
||
227 | } |
||
228 | |||
229 | public function testPUTwithXML() |
||
0 ignored issues
–
show
testPUTwithXML uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
230 | { |
||
231 | $comment1 = $this->objFromFixture('RestfulServerTest_Comment', 'comment1'); |
||
232 | |||
233 | $_SERVER['PHP_AUTH_USER'] = '[email protected]'; |
||
234 | $_SERVER['PHP_AUTH_PW'] = 'editor'; |
||
235 | |||
236 | // by mimetype |
||
237 | $url = "/api/v1/RestfulServerTest_Comment/" . $comment1->ID; |
||
238 | $body = '<RestfulServerTest_Comment><Comment>updated</Comment></RestfulServerTest_Comment>'; |
||
239 | $response = Director::test($url, null, null, 'PUT', $body, array('Content-Type'=>'text/xml')); |
||
240 | $this->assertEquals($response->getStatusCode(), 200); // Updated |
||
241 | $obj = Convert::xml2array($response->getBody()); |
||
242 | $this->assertEquals($obj['ID'], $comment1->ID); |
||
0 ignored issues
–
show
The method
assertEquals() does not seem to exist on object<RestfulServerTest> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed.
Loading history...
|
|||
243 | $this->assertEquals($obj['Comment'], 'updated'); |
||
0 ignored issues
–
show
The method
assertEquals() does not seem to exist on object<RestfulServerTest> .
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed.
Loading history...
|
|||
244 | |||
245 | // by extension |
||
246 | $url = sprintf("/api/v1/RestfulServerTest_Comment/%d.xml", $comment1->ID); |
||
247 | $body = '<RestfulServerTest_Comment><Comment>updated</Comment></RestfulServerTest_Comment>'; |
||
248 | $response = Director::test($url, null, null, 'PUT', $body); |
||
249 | $this->assertEquals($response->getStatusCode(), 200); // Updated |
||
250 | $this->assertEquals( |
||
251 | $response->getHeader('Location'), |
||
252 | Controller::join_links(Director::absoluteBaseURL(), $url) |
||
253 | ); |
||
254 | $obj = Convert::xml2array($response->getBody()); |
||
255 | $this->assertEquals($obj['ID'], $comment1->ID); |
||
256 | $this->assertEquals($obj['Comment'], 'updated'); |
||
257 | |||
258 | unset($_SERVER['PHP_AUTH_USER']); |
||
259 | unset($_SERVER['PHP_AUTH_PW']); |
||
260 | } |
||
261 | |||
262 | public function testHTTPAcceptAndContentType() |
||
263 | { |
||
264 | $comment1 = $this->objFromFixture('RestfulServerTest_Comment', 'comment1'); |
||
265 | |||
266 | $url = "/api/v1/RestfulServerTest_Comment/" . $comment1->ID; |
||
267 | |||
268 | $headers = array('Accept' => 'application/json'); |
||
269 | $response = Director::test($url, null, null, 'GET', null, $headers); |
||
270 | $this->assertEquals($response->getStatusCode(), 200); // Success |
||
271 | $obj = Convert::json2obj($response->getBody()); |
||
272 | $this->assertEquals($obj->ID, $comment1->ID); |
||
273 | $this->assertEquals($response->getHeader('Content-Type'), 'application/json'); |
||
274 | } |
||
275 | |||
276 | public function testNotFound() |
||
277 | { |
||
278 | $_SERVER['PHP_AUTH_USER'] = '[email protected]'; |
||
279 | $_SERVER['PHP_AUTH_PW'] = 'user'; |
||
280 | |||
281 | $url = "/api/v1/RestfulServerTest_Comment/99"; |
||
282 | $response = Director::test($url, null, null, 'GET'); |
||
283 | $this->assertEquals($response->getStatusCode(), 404); |
||
284 | |||
285 | unset($_SERVER['PHP_AUTH_USER']); |
||
286 | unset($_SERVER['PHP_AUTH_PW']); |
||
287 | } |
||
288 | |||
289 | View Code Duplication | public function testMethodNotAllowed() |
|
290 | { |
||
291 | $comment1 = $this->objFromFixture('RestfulServerTest_Comment', 'comment1'); |
||
292 | |||
293 | $url = "/api/v1/RestfulServerTest_Comment/" . $comment1->ID; |
||
294 | $response = Director::test($url, null, null, 'UNKNOWNHTTPMETHOD'); |
||
295 | $this->assertEquals($response->getStatusCode(), 405); |
||
296 | } |
||
297 | |||
298 | View Code Duplication | public function testConflictOnExistingResourceWhenUsingPost() |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
299 | { |
||
300 | $rating1 = $this->objFromFixture('RestfulServerTest_AuthorRating', 'rating1'); |
||
301 | |||
302 | $url = "/api/v1/RestfulServerTest_AuthorRating/" . $rating1->ID; |
||
303 | $response = Director::test($url, null, null, 'POST'); |
||
304 | $this->assertEquals($response->getStatusCode(), 409); |
||
305 | } |
||
306 | |||
307 | public function testUnsupportedMediaType() |
||
0 ignored issues
–
show
testUnsupportedMediaType uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
308 | { |
||
309 | $_SERVER['PHP_AUTH_USER'] = '[email protected]'; |
||
310 | $_SERVER['PHP_AUTH_PW'] = 'user'; |
||
311 | |||
312 | $url = "/api/v1/RestfulServerTest_Comment"; |
||
313 | $data = "Comment||\/||updated"; // weird format |
||
314 | $headers = array('Content-Type' => 'text/weirdformat'); |
||
315 | $response = Director::test($url, null, null, 'POST', $data, $headers); |
||
316 | $this->assertEquals($response->getStatusCode(), 415); |
||
317 | |||
318 | unset($_SERVER['PHP_AUTH_USER']); |
||
319 | unset($_SERVER['PHP_AUTH_PW']); |
||
320 | } |
||
321 | |||
322 | public function testXMLValueFormatting() |
||
323 | { |
||
324 | $rating1 = $this->objFromFixture('RestfulServerTest_AuthorRating', 'rating1'); |
||
325 | |||
326 | $url = "/api/v1/RestfulServerTest_AuthorRating/" . $rating1->ID; |
||
327 | $response = Director::test($url, null, null, 'GET'); |
||
328 | $this->assertContains('<ID>' . $rating1->ID . '</ID>', $response->getBody()); |
||
329 | $this->assertContains('<Rating>' . $rating1->Rating . '</Rating>', $response->getBody()); |
||
330 | } |
||
331 | |||
332 | public function testApiAccessFieldRestrictions() |
||
333 | { |
||
334 | $author1 = $this->objFromFixture('RestfulServerTest_Author', 'author1'); |
||
335 | $rating1 = $this->objFromFixture('RestfulServerTest_AuthorRating', 'rating1'); |
||
336 | |||
337 | $url = "/api/v1/RestfulServerTest_AuthorRating/" . $rating1->ID; |
||
338 | $response = Director::test($url, null, null, 'GET'); |
||
339 | $this->assertContains('<ID>', $response->getBody()); |
||
340 | $this->assertContains('<Rating>', $response->getBody()); |
||
341 | $this->assertContains('<Author', $response->getBody()); |
||
342 | $this->assertNotContains('<SecretField>', $response->getBody()); |
||
343 | $this->assertNotContains('<SecretRelation>', $response->getBody()); |
||
344 | |||
345 | $url = "/api/v1/RestfulServerTest_AuthorRating/" . $rating1->ID . '?add_fields=SecretField,SecretRelation'; |
||
346 | $response = Director::test($url, null, null, 'GET'); |
||
347 | $this->assertNotContains('<SecretField>', $response->getBody(), |
||
348 | '"add_fields" URL parameter filters out disallowed fields from $api_access' |
||
349 | ); |
||
350 | $this->assertNotContains('<SecretRelation>', $response->getBody(), |
||
351 | '"add_fields" URL parameter filters out disallowed relations from $api_access' |
||
352 | ); |
||
353 | |||
354 | $url = "/api/v1/RestfulServerTest_AuthorRating/" . $rating1->ID . '?fields=SecretField,SecretRelation'; |
||
355 | $response = Director::test($url, null, null, 'GET'); |
||
356 | $this->assertNotContains('<SecretField>', $response->getBody(), |
||
357 | '"fields" URL parameter filters out disallowed fields from $api_access' |
||
358 | ); |
||
359 | $this->assertNotContains('<SecretRelation>', $response->getBody(), |
||
360 | '"fields" URL parameter filters out disallowed relations from $api_access' |
||
361 | ); |
||
362 | |||
363 | $url = "/api/v1/RestfulServerTest_Author/" . $author1->ID . '/Ratings'; |
||
364 | $response = Director::test($url, null, null, 'GET'); |
||
365 | $this->assertContains('<Rating>', $response->getBody(), |
||
366 | 'Relation viewer shows fields allowed through $api_access' |
||
367 | ); |
||
368 | $this->assertNotContains('<SecretField>', $response->getBody(), |
||
369 | 'Relation viewer on has-many filters out disallowed fields from $api_access' |
||
370 | ); |
||
371 | } |
||
372 | |||
373 | public function testApiAccessRelationRestrictionsInline() |
||
374 | { |
||
375 | $author1 = $this->objFromFixture('RestfulServerTest_Author', 'author1'); |
||
376 | |||
377 | $url = "/api/v1/RestfulServerTest_Author/" . $author1->ID; |
||
378 | $response = Director::test($url, null, null, 'GET'); |
||
379 | $this->assertNotContains('<RelatedPages', $response->getBody(), 'Restricts many-many with api_access=false'); |
||
380 | $this->assertNotContains('<PublishedPages', $response->getBody(), 'Restricts has-many with api_access=false'); |
||
381 | } |
||
382 | |||
383 | public function testApiAccessRelationRestrictionsOnEndpoint() |
||
384 | { |
||
385 | $author1 = $this->objFromFixture('RestfulServerTest_Author', 'author1'); |
||
386 | |||
387 | $url = "/api/v1/RestfulServerTest_Author/" . $author1->ID . "/ProfilePage"; |
||
388 | $response = Director::test($url, null, null, 'GET'); |
||
389 | $this->assertEquals(404, $response->getStatusCode(), 'Restricts has-one with api_access=false'); |
||
390 | |||
391 | $url = "/api/v1/RestfulServerTest_Author/" . $author1->ID . "/RelatedPages"; |
||
392 | $response = Director::test($url, null, null, 'GET'); |
||
393 | $this->assertEquals(404, $response->getStatusCode(), 'Restricts many-many with api_access=false'); |
||
394 | |||
395 | $url = "/api/v1/RestfulServerTest_Author/" . $author1->ID . "/PublishedPages"; |
||
396 | $response = Director::test($url, null, null, 'GET'); |
||
0 ignored issues
–
show
null is of type null , but the function expects a object<Session>|array .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
397 | $this->assertEquals(404, $response->getStatusCode(), 'Restricts has-many with api_access=false'); |
||
398 | } |
||
399 | |||
400 | public function testApiAccessWithPUT() |
||
401 | { |
||
402 | $rating1 = $this->objFromFixture('RestfulServerTest_AuthorRating', 'rating1'); |
||
403 | |||
404 | $url = "/api/v1/RestfulServerTest_AuthorRating/" . $rating1->ID; |
||
405 | $data = array( |
||
406 | 'Rating' => '42', |
||
407 | 'WriteProtectedField' => 'haxx0red' |
||
408 | ); |
||
409 | $response = Director::test($url, $data, null, 'PUT'); |
||
410 | // Assumption: XML is default output |
||
411 | $responseArr = Convert::xml2array($response->getBody()); |
||
412 | $this->assertEquals($responseArr['Rating'], 42); |
||
413 | $this->assertNotEquals($responseArr['WriteProtectedField'], 'haxx0red'); |
||
414 | } |
||
415 | |||
416 | public function testJSONDataFormatter() |
||
417 | { |
||
418 | $formatter = new JSONDataFormatter(); |
||
419 | $editor = $this->objFromFixture('Member', 'editor'); |
||
420 | $user = $this->objFromFixture('Member', 'user'); |
||
421 | |||
422 | $this->assertEquals( |
||
423 | $formatter->convertDataObject($editor, array("FirstName", "Email")), |
||
424 | '{"FirstName":"Editor","Email":"[email protected]"}', |
||
425 | "Correct JSON formatting with field subset"); |
||
426 | |||
427 | $set = DataObject::get( |
||
428 | "Member", |
||
429 | sprintf('"Member"."ID" IN (%s)', implode(',', array($editor->ID, $user->ID))), |
||
430 | '"Email" ASC' // for sorting for postgres |
||
431 | ); |
||
432 | $this->assertEquals( |
||
433 | $formatter->convertDataObjectSet($set, array("FirstName", "Email")), |
||
434 | '{"totalSize":null,"items":[{"FirstName":"Editor","Email":"[email protected]"},' . |
||
435 | '{"FirstName":"User","Email":"[email protected]"}]}', |
||
436 | "Correct JSON formatting on a dataobjectset with field filter"); |
||
437 | } |
||
438 | |||
439 | public function testApiAccessWithPOST() |
||
440 | { |
||
441 | $url = "/api/v1/RestfulServerTest_AuthorRating"; |
||
442 | $data = array( |
||
443 | 'Rating' => '42', |
||
444 | 'WriteProtectedField' => 'haxx0red' |
||
445 | ); |
||
446 | $response = Director::test($url, $data, null, 'POST'); |
||
447 | // Assumption: XML is default output |
||
448 | $responseArr = Convert::xml2array($response->getBody()); |
||
449 | $this->assertEquals($responseArr['Rating'], 42); |
||
450 | $this->assertNotEquals($responseArr['WriteProtectedField'], 'haxx0red'); |
||
451 | } |
||
452 | |||
453 | public function testCanViewRespectedInList() |
||
0 ignored issues
–
show
testCanViewRespectedInList uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
454 | { |
||
455 | // Default content type |
||
456 | $url = "/api/v1/RestfulServerTest_SecretThing/"; |
||
457 | $response = Director::test($url, null, null, 'GET'); |
||
458 | $this->assertEquals($response->getStatusCode(), 200); |
||
459 | $this->assertNotContains('Unspeakable', $response->getBody()); |
||
460 | |||
461 | // JSON content type |
||
462 | $url = "/api/v1/RestfulServerTest_SecretThing.json"; |
||
463 | $response = Director::test($url, null, null, 'GET'); |
||
464 | $this->assertEquals($response->getStatusCode(), 200); |
||
465 | $this->assertNotContains('Unspeakable', $response->getBody()); |
||
466 | |||
467 | // With authentication |
||
468 | $_SERVER['PHP_AUTH_USER'] = '[email protected]'; |
||
469 | $_SERVER['PHP_AUTH_PW'] = 'editor'; |
||
470 | $url = "/api/v1/RestfulServerTest_SecretThing/"; |
||
471 | $response = Director::test($url, null, null, 'GET'); |
||
472 | $this->assertEquals($response->getStatusCode(), 200); |
||
473 | $this->assertContains('Unspeakable', $response->getBody()); |
||
474 | unset($_SERVER['PHP_AUTH_USER']); |
||
475 | unset($_SERVER['PHP_AUTH_PW']); |
||
476 | } |
||
477 | } |
||
478 | |||
479 | /** |
||
480 | * Everybody can view comments, logged in members in the "users" group can create comments, |
||
481 | * but only "editors" can edit or delete them. |
||
482 | * |
||
483 | */ |
||
484 | class RestfulServerTest_Comment extends DataObject implements PermissionProvider,TestOnly |
||
485 | { |
||
486 | public static $api_access = true; |
||
487 | |||
488 | public static $db = array( |
||
489 | "Name" => "Varchar(255)", |
||
490 | "Comment" => "Text" |
||
491 | ); |
||
492 | |||
493 | public static $has_one = array( |
||
494 | 'Page' => 'RestfulServerTest_Page', |
||
495 | 'Author' => 'RestfulServerTest_Author', |
||
496 | ); |
||
497 | |||
498 | public function providePermissions() |
||
499 | { |
||
500 | return array( |
||
501 | 'EDIT_Comment' => 'Edit Comment Objects', |
||
502 | 'CREATE_Comment' => 'Create Comment Objects', |
||
503 | 'DELETE_Comment' => 'Delete Comment Objects', |
||
504 | ); |
||
505 | } |
||
506 | |||
507 | public function canView($member = null) |
||
508 | { |
||
509 | return true; |
||
510 | } |
||
511 | |||
512 | public function canEdit($member = null) |
||
513 | { |
||
514 | return Permission::checkMember($member, 'EDIT_Comment'); |
||
515 | } |
||
516 | |||
517 | public function canDelete($member = null) |
||
518 | { |
||
519 | return Permission::checkMember($member, 'DELETE_Comment'); |
||
520 | } |
||
521 | |||
522 | public function canCreate($member = null) |
||
523 | { |
||
524 | return Permission::checkMember($member, 'CREATE_Comment'); |
||
525 | } |
||
526 | } |
||
527 | |||
528 | class RestfulServerTest_SecretThing extends DataObject implements TestOnly,PermissionProvider |
||
529 | { |
||
530 | public static $api_access = true; |
||
531 | |||
532 | public static $db = array( |
||
533 | "Name" => "Varchar(255)", |
||
534 | ); |
||
535 | |||
536 | public function canView($member = null) |
||
537 | { |
||
538 | return Permission::checkMember($member, 'VIEW_SecretThing'); |
||
539 | } |
||
540 | |||
541 | public function providePermissions() |
||
542 | { |
||
543 | return array( |
||
544 | 'VIEW_SecretThing' => 'View Secret Things', |
||
545 | ); |
||
546 | } |
||
547 | } |
||
548 | |||
549 | class RestfulServerTest_Page extends DataObject implements TestOnly |
||
550 | { |
||
551 | public static $api_access = false; |
||
552 | |||
553 | public static $db = array( |
||
554 | 'Title' => 'Text', |
||
555 | 'Content' => 'HTMLText', |
||
556 | ); |
||
557 | |||
558 | public static $has_one = array( |
||
559 | 'Author' => 'RestfulServerTest_Author', |
||
560 | ); |
||
561 | |||
562 | public static $has_many = array( |
||
563 | 'TestComments' => 'RestfulServerTest_Comment' |
||
564 | ); |
||
565 | |||
566 | public static $belongs_many_many = array( |
||
567 | 'RelatedAuthors' => 'RestfulServerTest_Author', |
||
568 | ); |
||
569 | } |
||
570 | |||
571 | class RestfulServerTest_Author extends DataObject implements TestOnly |
||
572 | { |
||
573 | public static $api_access = true; |
||
574 | |||
575 | public static $db = array( |
||
576 | 'Name' => 'Text', |
||
577 | ); |
||
578 | |||
579 | public static $many_many = array( |
||
580 | 'RelatedPages' => 'RestfulServerTest_Page', |
||
581 | 'RelatedAuthors' => 'RestfulServerTest_Author', |
||
582 | ); |
||
583 | |||
584 | public static $has_many = array( |
||
585 | 'PublishedPages' => 'RestfulServerTest_Page', |
||
586 | 'Ratings' => 'RestfulServerTest_AuthorRating', |
||
587 | ); |
||
588 | |||
589 | public function canView($member = null) |
||
590 | { |
||
591 | return true; |
||
592 | } |
||
593 | } |
||
594 | |||
595 | class RestfulServerTest_AuthorRating extends DataObject implements TestOnly |
||
596 | { |
||
597 | public static $api_access = array( |
||
598 | 'view' => array( |
||
599 | 'Rating', |
||
600 | 'WriteProtectedField', |
||
601 | 'Author' |
||
602 | ), |
||
603 | 'edit' => array( |
||
604 | 'Rating' |
||
605 | ) |
||
606 | ); |
||
607 | |||
608 | public static $db = array( |
||
609 | 'Rating' => 'Int', |
||
610 | 'SecretField' => 'Text', |
||
611 | 'WriteProtectedField' => 'Text', |
||
612 | ); |
||
613 | |||
614 | public static $has_one = array( |
||
615 | 'Author' => 'RestfulServerTest_Author', |
||
616 | 'SecretRelation' => 'RestfulServerTest_Author', |
||
617 | ); |
||
618 | |||
619 | public function canView($member = null) |
||
620 | { |
||
621 | return true; |
||
622 | } |
||
623 | |||
624 | public function canEdit($member = null) |
||
625 | { |
||
626 | return true; |
||
627 | } |
||
628 | |||
629 | public function canCreate($member = null) |
||
630 | { |
||
631 | return true; |
||
632 | } |
||
633 | } |
||
634 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.