From a4f9ca7cf31c305626305967278f809c28b44ab1 Mon Sep 17 00:00:00 2001 From: andrei-ghenov Date: Sat, 2 Mar 2024 15:29:45 -0500 Subject: [PATCH 1/3] T-006: Update README with additional hints for running tests - Added a hint in the README to guide users on running tests across Composer using the provided script. - Updated the note section to provide clarity and offer flexibility for users in testing their project components. --- README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2989077..36db2e7 100644 --- a/README.md +++ b/README.md @@ -58,13 +58,19 @@ To begin using the project, follow these simple steps: 5. **Start Using the Project**: Once the setup is complete, you're ready to start using the project! Refer to the project documentation or codebase for specific instructions on how to interact with the functionality provided. -**Note:** This project contains unit tests aimed to validate all the mentioned functionality. To check the performance of the components, simply run the tests located in the `project_directory/tests` folder. +**Note:** This project contains unit tests aimed to validate all the mentioned functionality. To check the performance of the components, you can run the tests using PHPUnit from the project directory: + ``` + ./vendor/bin/phpunit tests + ``` -**Hint:** As an example, you can run the tests using PHPUnit from the project directory: +Alternatively, you can run tests across Composer using the provided script: ``` - ./vendor/bin/phpunit tests/Api/ApiClientTest.php + composer test ``` +By running these commands, you can ensure that your project components are functioning as expected. + + ## Configuration If your project requires specific configuration settings, API keys, or environment variables, follow these steps to set them up: From b7ab88e104aba615433be042d11ff9301df6749d Mon Sep 17 00:00:00 2001 From: andrei-ghenov Date: Sat, 2 Mar 2024 15:59:12 -0500 Subject: [PATCH 2/3] T-005: Configure PHPUnit with phpunit.xml for improved testing workflow --- .gitignore | 3 ++- phpunit.xml | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 phpunit.xml diff --git a/.gitignore b/.gitignore index 607642e..604f670 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /vendor/ .env -composer.lock \ No newline at end of file +composer.lock +.phpunit.result.cache \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..ff3d949 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,8 @@ + + + + + tests/ + + + From 88099f97e5c6afdd97b018ce0a854983f1692da3 Mon Sep 17 00:00:00 2001 From: andrei-ghenov Date: Sat, 2 Mar 2024 16:28:38 -0500 Subject: [PATCH 3/3] T-005: Implement initial API Client Test functionality for WSLogin --- composer.json | 5 +++ src/Api/ApiClient.php | 11 ++++-- src/Model/Product.php | 16 ++++---- src/Service/ProductService.php | 6 +-- src/Service/PurchaseService.php | 2 +- tests/Api/ApiClientTest.php | 70 ++++++++++++++++++++++++++------- 6 files changed, 81 insertions(+), 29 deletions(-) diff --git a/composer.json b/composer.json index 85f504c..6d59b82 100644 --- a/composer.json +++ b/composer.json @@ -22,5 +22,10 @@ }, "require-dev": { "phpunit/phpunit": "^11.0" + }, + "scripts": { + "test-api-client": "vendor/bin/phpunit tests/Api/ApiClientTest.php", + "test-service-purchase": "vendor/bin/phpunit tests/Service/PurchaseServiceTest.php", + "test-service-status_check": "vendor/bin/phpunit tests/Service/StatusCheckServiceTest.php" } } diff --git a/src/Api/ApiClient.php b/src/Api/ApiClient.php index 763742d..d89d879 100644 --- a/src/Api/ApiClient.php +++ b/src/Api/ApiClient.php @@ -19,7 +19,7 @@ class ApiClient { * * The Guzzle HTTP client. */ - private $client; + private Client $client; /** * @var string @@ -48,6 +48,7 @@ class ApiClient { public function __construct() { $this->client = new Client([ 'base_uri' => $_ENV['API_BASE_URL'], + 'timeout' => 30, ]); $this->apiUser = $_ENV['API_USER']; $this->apiPassword = $_ENV['API_PASSWORD']; @@ -67,18 +68,20 @@ public function __construct() { * @return mixed * The response from the API. */ - public function sendRequest($method, $endpoint, array $data = []): mixed { + public function sendRequest( + string $method, string $endpoint, array $data = [] + ): mixed { $timestamp = gmdate('c'); $authKey = $this->generateAuthKey($timestamp); $hashedPassword = $this->hashPassword(); // Add authentication parameters to the request data. - $data = array_merge($data, [ + $data = array_merge([ 'DTime' => $timestamp, 'AuthKey' => $authKey, 'User' => $this->apiUser, 'Password' => $hashedPassword, - ]); + ], $data); try { $response = $this->client->request($method, $endpoint, [ diff --git a/src/Model/Product.php b/src/Model/Product.php index ace2d7b..72575aa 100644 --- a/src/Model/Product.php +++ b/src/Model/Product.php @@ -16,42 +16,44 @@ class Product { * * The product ID. */ - public $id; + public int $id; /** * @var string * * The product name. */ - public $name; + public string $name; /** * @var string * * The product description. */ - public $description; + public string $description; /** * @var float * * The product amount. */ - public $amount; + public float $amount; /** * Product constructor. * - * @param int $id + * @param int $id * The product ID. * @param string $name * The product name. * @param string $description * The product description. - * @param float $amount + * @param float $amount * The product amount. */ - public function __construct($id, $name, $description, $amount) { + public function __construct( + int $id, string $name, string $description, float $amount + ) { $this->id = $id; $this->name = $name; $this->description = $description; diff --git a/src/Service/ProductService.php b/src/Service/ProductService.php index c023e79..6fc909d 100644 --- a/src/Service/ProductService.php +++ b/src/Service/ProductService.php @@ -18,7 +18,7 @@ class ProductService { * * The API client. */ - private $apiClient; + private ApiClient $apiClient; /** * ProductService constructor. @@ -36,7 +36,7 @@ public function __construct(ApiClient $apiClient) { * @return array * The products. */ - public function getAllProducts() { + public function getAllProducts(): array { $endpoint = 'WSGetTopUpProducts'; return $this->apiClient->sendRequest('POST', $endpoint); @@ -51,7 +51,7 @@ public function getAllProducts() { * @return array * The product. */ - public function getProductById($productID) { + public function getProductById(int $productID): mixed { $endpoint = "WSGetSingleTopUpProduct"; return $this->apiClient->sendRequest( diff --git a/src/Service/PurchaseService.php b/src/Service/PurchaseService.php index ab1e917..eb0e9cf 100644 --- a/src/Service/PurchaseService.php +++ b/src/Service/PurchaseService.php @@ -18,7 +18,7 @@ class PurchaseService { * * The API client. */ - private $apiClient; + private ApiClient $apiClient; /** * PurchaseService constructor. diff --git a/tests/Api/ApiClientTest.php b/tests/Api/ApiClientTest.php index 904090f..8496a72 100644 --- a/tests/Api/ApiClientTest.php +++ b/tests/Api/ApiClientTest.php @@ -19,32 +19,74 @@ class ApiClientTest extends TestCase { * * The API client. */ - private $apiClient; + private ApiClient $apiClient; /** * Test a successful login request. */ public function testWSLoginSuccess() { - $response = $this->apiClient->sendRequest('POST', 'WSLogin'); + try { + $response = $this->apiClient->sendRequest('POST', 'WSLogin'); - // Assert the response indicates a successful login - $this->assertArrayHasKey('AccessCode', $response); - $this->assertEquals(0, $response['AccessCode']); + // Use PHPUnit assertions to check for successful login + // Display the response for debugging purposes + // (usually done during development only) + echo "Response: "; + var_dump($response); + + // Assert the response indicates a successful login + $this->assertArrayHasKey( + 'AccessCode', $response, "Response does not contain AccessCode" + ); + $this->assertEquals( + 0, $response['AccessCode'], + "AccessCode is not 0, indicating login failure" + ); + } + catch (\Exception $e) { + // Catch and display the error for debugging purposes + // In production or CI environments, it might be better to log this error + // or handle it accordingly. + echo "Error during WSLogin request: ".$e->getMessage(); + // Fail the test if an exception is caught + $this->fail( + "WSLogin request failed with an exception: ".$e->getMessage() + ); + } } /** * Test a failed login request. */ public function testWSLoginFailure() { - // Use intentionally incorrect credentials to test failure response - $response = $this->apiClient->sendRequest('POST', 'WSLogin', [ - 'User' => 'incorrectUser', - 'Password' => 'incorrectPassword', - ]); - - // Assert the response indicates a failed login - $this->assertArrayHasKey('AccessCode', $response); - $this->assertNotEquals(0, $response['AccessCode']); + try { + // Use intentionally incorrect credentials to test failure response. + $response = $this->apiClient->sendRequest('POST', 'WSLogin', [ + 'User' => 'incorrectUser', + 'Password' => 'incorrectPassword', + ]); + + // Debugging output (use sparingly) + echo "Response: "; + var_dump($response); + + // Assert the response indicates a failed login. + $this->assertArrayHasKey( + 'AccessCode', $response, "Response does not contain AccessCode" + ); + $this->assertNotEquals( + 0, $response['AccessCode'], + "AccessCode is 0, indicating unexpected success" + ); + } + catch (\Exception $e) { + // If there's an exception, catch and display it for debugging purposes. + echo "Error during WSLogin failure test: ".$e->getMessage(); + // Optionally fail the test to indicate an unexpected error occurred. + $this->fail( + "WSLogin failure test failed with an exception: ".$e->getMessage() + ); + } } /**