Skip to content

Commit

Permalink
Merge pull request #52 from WebFiori/dev
Browse files Browse the repository at this point in the history
feat: Added a Class to Help in API Testing
  • Loading branch information
usernane authored Apr 14, 2024
2 parents e1efcc5 + 94a2d06 commit 3aad4f9
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 50 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ tests/json.json
php-cs-fixer-v2.phar
.idea/*
php-cs-fixer.phar
.php-cs-fixer.cache
1 change: 1 addition & 0 deletions tests/loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
require_once $rootDir.'webfiori'.$DS.'http'.$DS.'ObjectMapper.php';
require_once $rootDir.'webfiori'.$DS.'http'.$DS.'RequestMethod.php';
require_once $rootDir.'webfiori'.$DS.'http'.$DS.'ResponseMessage.php';
require_once $rootDir.'webfiori'.$DS.'http'.$DS.'APITestCase.php';

require_once $rootDir.'tests'.$DS.'webfiori'.$DS.'tests'.$DS.'http'.$DS.'testServices'.$DS.'TestServiceObj.php';
require_once $rootDir.'tests'.$DS.'webfiori'.$DS.'tests'.$DS.'http'.$DS.'testServices'.$DS.'SampleServicesManager.php';
Expand Down
70 changes: 20 additions & 50 deletions tests/webfiori/tests/http/WebServicesManagerTest.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?php
namespace webfiori\tests\http;

use PHPUnit\Framework\TestCase;
use webfiori\http\AbstractWebService;
use webfiori\http\APITestCase;
use webfiori\http\Request;
use webfiori\http\ResponseMessage;
use webfiori\http\WebServicesManager;
Expand All @@ -15,36 +15,22 @@
*
* @author Eng.Ibrahim
*/
class WebServicesManagerTest extends TestCase {
class WebServicesManagerTest extends APITestCase {
private $outputStreamName = __DIR__.DIRECTORY_SEPARATOR.'outputStream.txt';
/**
* @test
*/

public function test00() {
$this->clrearVars();
$manager = new WebServicesManager();
$manager->addService(new NoAuthService());
$_GET['service'] = 'ok-service';
$manager->setOutputStream(fopen($this->outputStreamName,'w'));
$manager->process();
$this->assertEquals('{"message":"You are authorized.","http-code":200}', $manager->readOutputStream());
$this->assertEquals('{"message":"You are authorized.","http-code":200}', $this->getRequest($manager, 'ok-service'));
return $manager;
}
/**
* @test
*/

public function test01() {
$this->clrearVars();
putenv('REQUEST_METHOD=POST');
$manager = new WebServicesManager();
$manager->addService(new NotImplService());
$_SERVER['CONTENT_TYPE'] = 'multipart/form-data';
$_POST['service'] = 'not-implemented';
$manager->setOutputStream(fopen($this->outputStreamName,'w'));
$manager->process();
$this->assertEquals('{"message":"Service not implemented.","type":"error","http-code":404}', $manager->readOutputStream());
$this->assertEquals('{"message":"Service not implemented.","type":"error","http-code":404}', $this->postRequest($manager, 'not-implemented'));
return $manager;
}
/**
Expand Down Expand Up @@ -179,14 +165,8 @@ public function testConstructor00() {
* @test
*/
public function testDoNothing00() {
$this->clrearVars();
putenv('REQUEST_METHOD=DELETE');
$_GET['action'] = 'do-nothing';
$_GET['pass'] = '123';
$api = new SampleServicesManager();
$api->setOutputStream($this->outputStreamName);
$api->process();
$this->assertEquals('{"message":"Service not supported.","type":"error","http-code":404}', $api->readOutputStream());
$this->assertEquals('{"message":"Service not supported.","type":"error","http-code":404}', $this->getRequest($api, 'do-nothen'));
}
/**
* @depends testSumTwoIntegers05
Expand All @@ -204,45 +184,35 @@ public function testGetNonFiltered00($api) {
* @test
*/
public function testGetUser00() {
$this->clrearVars();
putenv('REQUEST_METHOD=GET');
$_GET['action'] = 'get-user-profile';
$_GET['user-id'] = '-9';
$_GET['pass'] = '123';
$api = new SampleServicesManager();
$api->setOutputStream($this->outputStreamName);
$api->process();
$this->assertEquals('{"message":"Method Not Allowed.","type":"error","http-code":405}', $api->readOutputStream());
$this->assertEquals('{"message":"Method Not Allowed.","type":"error","http-code":405}', $this->getRequest($api, 'get-user-profile', [
'user-id' => -9,
'pass' => '123'
]));
}
/**
* @test
*/
public function testGetUser01() {
$this->clrearVars();
putenv('REQUEST_METHOD=POST');
$_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
$_POST['action'] = 'get-user-profile';
$_POST['user-id'] = '-9';
$_POST['pass'] = '123';
$api = new SampleServicesManager();
$api->setOutputStream($this->outputStreamName);
$api->process();
$this->assertEquals('{"message":"Database Error.","type":"error","http-code":500}', $api->readOutputStream());
$this->assertEquals('{"message":"Database Error.","type":"error","http-code":500}', $this->postRequest($api, 'get-user-profile', [
'user-id' => -9,
'pass' => '123'
]));

}
/**
* @test
*/
public function testGetUser02() {
$this->clrearVars();
putenv('REQUEST_METHOD=POST');
$_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
$_POST['action'] = 'get-user-profile';
$_POST['user-id'] = '99';
$_POST['pass'] = '123';
$api = new SampleServicesManager();
$api->setOutputStream($this->outputStreamName);
$api->process();
$this->assertEquals('{"user-name":"Ibrahim","bio":"A software engineer who is ready to help anyone in need."}', $api->readOutputStream());

$this->assertEquals('{"user-name":"Ibrahim","bio":"A software engineer who is ready to help anyone in need."}', $this->postRequest($api, 'get-user-profile', [
'user-id' => '99',
'pass' => '123'
]));

}
/**
* @test
Expand Down
191 changes: 191 additions & 0 deletions webfiori/http/APITestCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
<?php
/**
* This file is licensed under MIT License.
*
* Copyright (c) 2024 Ibrahim BinAlshikh
*
* For more information on the license, please visit:
* https://github.com/WebFiori/http/blob/master/LICENSE
*/
namespace webfiori\http;

use PHPUnit\Framework\TestCase;
/**
* A helper class which is used to implement test cases for API calls.
*
* @author Ibrahim
*/
class APITestCase extends TestCase {
const NL = "\r\n";
const OUTPUT_STREAM = __DIR__.DIRECTORY_SEPARATOR.'outputStream.txt';
/**
* Adds a file to the array $_FILES for testing API with upload.
*
* @param string $fileIdx The name of the index that will hold the blob.
* This is usually represented by the attribute 'name' of file input in
* the front-end.
*
* @param string $filePath The path of the file within testing environment.
*
* @param bool $reset If set to true, the array $_FILES will be re-initialized.
*/
public function addFile(string $fileIdx, string $filePath, bool $reset = false) {
if ($reset) {
$_FILES = [];
}

if (!isset($_FILES[$fileIdx])) {
$_FILES[$fileIdx] = [];
$_FILES[$fileIdx]['name'] = [];
$_FILES[$fileIdx]['type'] = [];
$_FILES[$fileIdx]['size'] = [];
$_FILES[$fileIdx]['tmp_name'] = [];
$_FILES[$fileIdx]['error'] = [];
}
$info = $this->extractPathAndName($filePath);
$path = $info['path'].DS.$info['name'];

$_FILES[$fileIdx]['name'][] = $info['name'];
$_FILES[$fileIdx]['type'][] = mime_content_type($path);
$_FILES[$fileIdx]['size'][] = filesize($this->getAbsolutePath());
$_FILES[$fileIdx]['tmp_name'][] = $path;
$_FILES[$fileIdx]['error'][] = 0;
}
/**
* Performs a call to an endpoint.
*
* @param WebServicesManager $manager The services manager instance that is used to
* manage the service.
*
* @param string $requestMethod A string that represents the name of request
* method such as 'get' or 'post'.
*
* @param string $apiEndpointName The name of the endpoint that will be called such as 'add-user'.
*
* @param array $parameters A dictionary thar represents the parameters that
* will be sent to the endpoint. The name is parameter name as it appears in
* service implementation and its value is the value of the parameter.
*
* @return string The method will return the output of the endpoint.
*/
public function callEndpoint(WebServicesManager $manager, string $requestMethod, string $apiEndpointName, array $parameters = []) : string {
$manager->setOutputStream(fopen(self::OUTPUT_STREAM,'w'));
$method = strtoupper($requestMethod);
putenv('REQUEST_METHOD='.$method);

if ($method == 'GET' || $method == 'DELETE') {
foreach ($parameters as $key => $val) {
$_GET[$key] = $val;
}
$_GET['service'] = $apiEndpointName;
$this->unset($_GET, $parameters, $manager);
} else if ($method == 'POST' || $method == 'PUT') {
foreach ($parameters as $key => $val) {
$_POST[$key] = $val;
}
$_POST['service'] = $apiEndpointName;
$_SERVER['CONTENT_TYPE'] = 'multipart/form-data';
$this->unset($_POST, $parameters, $manager);
}

$retVal = $manager->readOutputStream();
unlink(self::OUTPUT_STREAM);

return $retVal;
}
/**
* Sends a DELETE request to specific endpoint.
*
* @param WebServicesManager $manager The manager which is used to manage the endpoint.
*
* @param string $endpoint The name of the endpoint.
*
* @param array $parameters An optional array of request parameters that can be
* passed to the endpoint.
*
* @return string The method will return the output that was produced by
* the endpoint as string.
*/
public function deletRequest(WebServicesManager $manager, string $endpoint, array $parameters = []) : string {
return $this->callEndpoint($manager, RequestMethod::DELETE, $endpoint, $parameters);
}
/**
* Sends a GET request to specific endpoint.
*
* @param WebServicesManager $manager The manager which is used to manage the endpoint.
*
* @param string $endpoint The name of the endpoint.
*
* @param array $parameters An optional array of request parameters that can be
* passed to the endpoint.
*
* @return string The method will return the output that was produced by
* the endpoint as string.
*/
public function getRequest(WebServicesManager $manager, string $endpoint, array $parameters = []) : string {
return $this->callEndpoint($manager, RequestMethod::GET, $endpoint, $parameters);
}
/**
* Sends a POST request to specific endpoint.
*
* @param WebServicesManager $manager The manager which is used to manage the endpoint.
*
* @param string $endpoint The name of the endpoint.
*
* @param array $parameters An optional array of request parameters that can be
* passed to the endpoint.
*
* @return string The method will return the output that was produced by
* the endpoint as string.
*/
public function postRequest(WebServicesManager $manager, string $endpoint, array $parameters = []) : string {
return $this->callEndpoint($manager, RequestMethod::POST, $endpoint, $parameters);
}
/**
* Sends a PUT request to specific endpoint.
*
* @param WebServicesManager $manager The manager which is used to manage the endpoint.
*
* @param string $endpoint The name of the endpoint.
*
* @param array $parameters An optional array of request parameters that can be
* passed to the endpoint.
*
* @return string The method will return the output that was produced by
* the endpoint as string.
*/
public function putRequest(WebServicesManager $manager, string $endpoint, array $parameters = []) : string {
return $this->callEndpoint($manager, RequestMethod::PUT, $endpoint, $parameters);
}
private function extractPathAndName($absPath): array {
$DS = DIRECTORY_SEPARATOR;
$cleanPath = str_replace('\\', $DS, str_replace('/', $DS, trim($absPath)));
$pathArr = explode($DS, $cleanPath);

if (count($pathArr) != 0) {
$fPath = '';
$name = $pathArr[count($pathArr) - 1];

for ($x = 0 ; $x < count($pathArr) - 1 ; $x++) {
$fPath .= $pathArr[$x].$DS;
}

return [
'path' => $fPath,
'name' => $name
];
}

return [
'name' => $cleanPath,
'path' => ''
];
}
private function unset(array &$arr, array $params, WebServicesManager $m) {
$m->process();

foreach ($params as $key => $val) {
unset($arr[$key]);
}
}
}
2 changes: 2 additions & 0 deletions webfiori/http/WebServicesManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -850,9 +850,11 @@ private function _AfterParamsCheck($processReq) {
*/
private function _checkAction(): bool {
$serviceName = $this->getCalledServiceName();

//first, check if action is set and not null
if ($serviceName !== null) {
$calledService = $this->getServiceByName($serviceName);

//after that, check if action is supported by the API.
if ($calledService !== null) {
$allowedMethods = $calledService->getRequestMethods();
Expand Down

0 comments on commit 3aad4f9

Please sign in to comment.