From 9cea90862503455813fe21d7ac7bef8936c015ef Mon Sep 17 00:00:00 2001 From: Ibrahim Date: Sun, 14 Apr 2024 17:55:24 +0300 Subject: [PATCH] feat: Added a Class to Help in API Testing --- tests/loader.php | 1 + .../tests/http/WebServicesManagerTest.php | 70 ++----- webfiori/http/APITestCase.php | 193 ++++++++++++++++++ 3 files changed, 214 insertions(+), 50 deletions(-) create mode 100644 webfiori/http/APITestCase.php diff --git a/tests/loader.php b/tests/loader.php index eb56134..422708d 100644 --- a/tests/loader.php +++ b/tests/loader.php @@ -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'; diff --git a/tests/webfiori/tests/http/WebServicesManagerTest.php b/tests/webfiori/tests/http/WebServicesManagerTest.php index df3c031..97189af 100644 --- a/tests/webfiori/tests/http/WebServicesManagerTest.php +++ b/tests/webfiori/tests/http/WebServicesManagerTest.php @@ -1,8 +1,8 @@ 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; } /** @@ -36,15 +28,9 @@ public function test00() { */ 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; } /** @@ -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 @@ -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 diff --git a/webfiori/http/APITestCase.php b/webfiori/http/APITestCase.php new file mode 100644 index 0000000..e78f571 --- /dev/null +++ b/webfiori/http/APITestCase.php @@ -0,0 +1,193 @@ +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); + } + /** + * 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); + } + /** + * 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; + } + /** + * 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; + } + 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]); + } + } +}