silverstripe-framework/tests/api/RestfulServiceTest.php

274 lines
8.5 KiB
PHP
Raw Normal View History

<?php
class RestfulServiceTest extends SapphireTest {
function testSpecialCharacters() {
$service = new RestfulServiceTest_MockRestfulService(Director::absoluteBaseURL());
$url = 'RestfulServiceTest_Controller/';
$params = array(
'test1a' => 4352655636.76543, // number test
'test1b' => '$&+,/:;=?@#%', // special char test. These should all get encoded
'test1c' => 'And now for a string test' // string test
);
$service->setQueryString($params);
$responseBody = $service->request($url)->getBody();
foreach ($params as $key => $value) {
$this->assertContains("<request_item name=\"$key\">$value</request_item>", $responseBody);
$this->assertContains("<get_item name=\"$key\">$value</get_item>", $responseBody);
}
}
function testGetDataWithSetQueryString() {
$service = new RestfulServiceTest_MockRestfulService(Director::absoluteBaseURL());
$url = 'RestfulServiceTest_Controller/';
$params = array(
'test1a' => 'val1a',
'test1b' => 'val1b'
);
$service->setQueryString($params);
$responseBody = $service->request($url)->getBody();
foreach ($params as $key => $value) {
$this->assertContains("<request_item name=\"$key\">$value</request_item>", $responseBody);
$this->assertContains("<get_item name=\"$key\">$value</get_item>", $responseBody);
}
}
function testGetDataWithUrlParameters() {
$service = new RestfulServiceTest_MockRestfulService(Director::absoluteBaseURL());
$url = 'RestfulServiceTest_Controller/';
$params = array(
'test1a' => 'val1a',
'test1b' => 'val1b'
);
$url .= '?' . http_build_query($params);
$responseBody = $service->request($url)->getBody();
foreach ($params as $key => $value) {
$this->assertContains("<request_item name=\"$key\">$value</request_item>", $responseBody);
$this->assertContains("<get_item name=\"$key\">$value</get_item>", $responseBody);
}
}
function testPostData() {
$service = new RestfulServiceTest_MockRestfulService(Director::absoluteBaseURL(), 0);
$params = array(
'test1a' => 'val1a',
'test1b' => 'val1b'
);
$responseBody = $service->request('RestfulServiceTest_Controller/', 'POST', $params)->getBody();
foreach ($params as $key => $value) {
$this->assertContains("<request_item name=\"$key\">$value</request_item>", $responseBody);
$this->assertContains("<post_item name=\"$key\">$value</post_item>", $responseBody);
}
}
function testPutData() {
$service = new RestfulServiceTest_MockRestfulService(Director::absoluteBaseURL(), 0);
$data = 'testPutData';
$responseBody = $service->request('RestfulServiceTest_Controller/', 'PUT', $data)->getBody();
$this->assertContains("<body>$data</body>", $responseBody);
}
function testConnectionDoesntCacheWithDifferentUrl() {
$service = new RestfulServiceTest_MockRestfulService(Director::absoluteBaseURL());
$url = 'RestfulServiceTest_Controller/';
// First run
$params = array(
'test1a' => 'first run',
);
$service->setQueryString($params);
$responseBody = $service->request($url)->getBody();
$this->assertContains("<request_item name=\"test1a\">first run</request_item>", $responseBody);
// Second run
$params = array(
'test1a' => 'second run',
);
$service->setQueryString($params);
$responseBody = $service->request($url)->getBody();
$this->assertContains("<request_item name=\"test1a\">second run</request_item>", $responseBody);
}
/**
* @expectedException PHPUnit_Framework_Error
*/
function testIncorrectData() {
$connection = new RestfulService(Director::absoluteBaseURL(), 0);
$test1 = $connection->request('RestfulServiceTest_Controller/invalid?usetestmanifest=1&flush=1');
$test1->xpath("\\fail");
}
function testHttpErrorWithoutCache() {
$connection = new RestfulServiceTest_MockRestfulService(Director::absoluteBaseURL(), 0);
$response = $connection->request('RestfulServiceTest_Controller/httpErrorWithoutCache?usetestmanifest=1&flush=1');
$this->assertEquals(400, $response->getStatusCode());
$this->assertFalse($response->getCachedBody());
$this->assertContains("<error>HTTP Error</error>", $response->getBody());
}
function testHttpErrorWithCache() {
$subUrl = 'RestfulServiceTest_Controller/httpErrorWithCache?usetestmanifest=1&flush=1';
$connection = new RestfulService(Director::absoluteBaseURL(), 0);
$this->createFakeCachedResponse($connection, $subUrl);
$response = $connection->request($subUrl);
$this->assertEquals(400, $response->getStatusCode());
$this->assertEquals("Cache response body",$response->getCachedBody());
$this->assertContains("<error>HTTP Error</error>", $response->getBody());
}
/**
* Simulate cached response file for testing error requests that are supposed to have cache files
*/
private function createFakeCachedResponse($connection, $subUrl) {
$fullUrl = $connection->getAbsoluteRequestURL($subUrl);
$cachedir = TEMP_FOLDER; // Default silverstripe cache
$cache_file = md5($fullUrl); // Encoded name of cache file
$cache_path = $cachedir."/xmlresponse_$cache_file";
$cacheResponse = new RestfulService_Response("Cache response body");
$store = serialize($cacheResponse);
file_put_contents($cache_path, $store);
}
}
class RestfulServiceTest_Controller extends Controller implements TestOnly {
public function init() {
$this->basicAuthEnabled = false;
parent::init();
}
public function index() {
$request = '';
foreach ($this->request->requestVars() as $key=>$value) {
$request .= "\t\t<request_item name=\"$key\">$value</request_item>\n";
}
$get = '';
foreach ($this->request->getVars() as $key => $value) {
$get .= "\t\t<get_item name=\"$key\">$value</get_item>\n";
}
$post = '';
foreach ($this->request->postVars() as $key => $value) {
$post .= "\t\t<post_item name=\"$key\">$value</post_item>\n";
}
$body = $this->request->getBody();
$out = <<<XML
<?xml version="1.0"?>
<test>
<request>$request</request>
<get>$get</get>
<post>$post</post>
<body>$body</body>
</test>
XML;
$this->response->setBody($out);
$this->response->addHeader('Content-type', 'text/xml');
return $this->response;
}
public function invalid() {
$out = <<<XML
<?xml version="1.0"?>
<test>
<fail><invalid>
</test>
XML;
header('Content-type: text/xml');
echo $out;
}
public function httpErrorWithoutCache() {
$out = <<<XML
<?xml version="1.0"?>
<test>
<error>HTTP Error</error>
</test>
XML;
$this->response->setBody($out);
$this->response->setStatusCode(400);
$this->response->addHeader('Content-type', 'text/xml');
return $this->response;
}
/**
* The body of this method is the same as self::httpErrorWithoutCache()
* but we need it for caching since caching using request url to determine path to cache file
*/
public function httpErrorWithCache() {
return $this->httpErrorWithoutCache();
}
}
/**
* Mock implementation of {@link RestfulService}, which uses {@link Director::test()}
* instead of direct curl system calls.
*
* @todo Less overloading of request()
* @todo Currently only works with relative (internal) URLs
*
* @package sapphire
* @subpackage tests
*/
class RestfulServiceTest_MockRestfulService extends RestfulService {
public $session = null;
public function request($subURL = '', $method = "GET", $data = null, $headers = null) {
if(!$this->session) {
$this->session = new Session(array());
}
$url = $this->baseURL . $subURL; // Url for the request
if($this->queryString) {
if(strpos($url, '?') !== false) {
$url .= '&' . $this->queryString;
} else {
$url .= '?' . $this->queryString;
}
}
$url = str_replace(' ', '%20', $url); // Encode spaces
// Custom for mock implementation: Director::test() doesn't cope with absolute URLs
$url = Director::makeRelative($url);
$method = strtoupper($method);
assert(in_array($method, array('GET','POST','PUT','DELETE','HEAD','OPTIONS')));
// Add headers
if($this->customHeaders) {
$headers = array_merge((array)$this->customHeaders, (array)$headers);
}
// Add authentication
if($this->authUsername) {
$headers[] = "Authorization: Basic " . base64_encode(
$this->authUsername.':'.$this->authPassword
);
}
// Custom for mock implementation: Use Director::test()
$body = null;
$postVars = null;
if($method!='POST') $body = $data;
else $postVars = $data;
$responseFromDirector = Director::test($url, $postVars, $this->session, $method, $body, $headers);
$response = new RestfulService_Response(
$responseFromDirector->getBody(),
$responseFromDirector->getStatusCode()
);
return $response;
}
}