major refactor
- add request status to search instance API - use JSend-type response in elixForms clients - readjust namespaces - add more unit tests (manual HTTP requests too)
This commit is contained in:
+5
-5
@@ -12,9 +12,9 @@ use Api\Core\RateLimiter\RateLimiterInterface;
|
||||
use Api\Core\RateLimiter\FileRateLimiter;
|
||||
use Api\Core\RateLimiter\InMemoryRateLimiter;
|
||||
use Api\Core\Log\LoggerFactory;
|
||||
use ElixForms\ElixFormsClient;
|
||||
use ElixForms\Auth\ElixFormsApiClient;
|
||||
use ElixForms\Auth\ElixFormsAuthenticationClient;
|
||||
use ElixForms\Clients\ElixFormsApiClient;
|
||||
use ElixForms\Clients\ElixFormsAuthenticationClient;
|
||||
use ElixForms\Clients\ElixFormsGenericClient;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
$container = new Container();
|
||||
@@ -63,10 +63,10 @@ $container->singleton(LoggerInterface::class, function($c) {
|
||||
});
|
||||
|
||||
// ElixForms client binding
|
||||
$container->singleton(ElixFormsClient::class, function($c) {
|
||||
$container->singleton(ElixFormsGenericClient::class, function($c) {
|
||||
$config = $c->make(Config::class);
|
||||
$baseUrl = $config->get('elixforms_api_base_url');
|
||||
return new ElixFormsClient($baseUrl);
|
||||
return new ElixFormsGenericClient($baseUrl, null);
|
||||
});
|
||||
|
||||
$container->singleton(ElixFormsAuthenticationClient::class, function($c) {
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
@term=MA
|
||||
|
||||
GET http://localhost:8000/api/dipendenti/cerca?term={{term}}
|
||||
Authorization: Basic elixforms_ws:password123
|
||||
X-API-Key: myApiAccessToken
|
||||
|
||||
###
|
||||
|
||||
@term=ID
|
||||
|
||||
GET http://localhost:8000/api/contratti/cerca?term={{term}}&cod_fis=MMMPPL74T17E463A
|
||||
Authorization: Basic elixforms_ws:password123
|
||||
X-API-Key: myApiAccessToken
|
||||
|
||||
###
|
||||
|
||||
@term=ID
|
||||
|
||||
GET http://localhost:8000/contratti/cerca?term={{term}}
|
||||
@@ -4,9 +4,8 @@ namespace Api\Controllers\V1;
|
||||
use Api\Core\Config;
|
||||
use Api\Core\Request;
|
||||
use Api\Core\Response;
|
||||
use ElixForms\Auth\ElixFormsApiClient;
|
||||
use ElixForms\Auth\ElixFormsAuthenticationClient;
|
||||
use ElixForms\Exceptions\ElixFormsException;
|
||||
use ElixForms\Clients\ElixFormsApiClient;
|
||||
use ElixForms\Clients\ElixFormsAuthenticationClient;
|
||||
|
||||
class ElixFormsController
|
||||
{
|
||||
@@ -30,11 +29,15 @@ class ElixFormsController
|
||||
$moduleTag = $this->requiredString($query, 'moduleTag');
|
||||
$fieldName = $this->requiredString($query, 'fieldName');
|
||||
$fieldValue = $this->requiredString($query, 'fieldValue');
|
||||
$requestStatuses = $this->requiredString($query, 'requestStatuses');
|
||||
$exportGroup = $this->optionalNonEmptyString($query, 'exportGroup', 'API');
|
||||
|
||||
if ($moduleTag === null || $fieldName === null || $fieldValue === null || $exportGroup === null) {
|
||||
return $res->json([
|
||||
'error' => 'moduleTag, fieldName e fieldValue sono obbligatori; exportGroup, se specificato, deve essere una stringa non vuota.'
|
||||
'status' => 'fail',
|
||||
'data' => [
|
||||
'parameters' => 'moduleTag, fieldName e fieldValue sono obbligatori; exportGroup, se specificato, deve essere una stringa non vuota.',
|
||||
],
|
||||
], 400);
|
||||
}
|
||||
|
||||
@@ -42,11 +45,31 @@ class ElixFormsController
|
||||
$password = $this->config->secret('elixforms_api_password');
|
||||
|
||||
if (!\is_string($username) || trim($username) === '' || !\is_string($password) || $password === '') {
|
||||
throw new ElixFormsException('Credenziali elixForms non configurate.');
|
||||
return $res->json([
|
||||
'status' => 'error',
|
||||
'message' => 'Credenziali elixForms non configurate.',
|
||||
'code' => 500,
|
||||
], 500);
|
||||
}
|
||||
|
||||
$token = $this->authenticationClient->login($username, $password);
|
||||
$instances = $this->apiClient->lookupByStatus($moduleTag, $token, $username);
|
||||
$login = $this->authenticationClient->login($username, $password);
|
||||
if ($login['status'] !== 'success') {
|
||||
return $this->respondWithJSendFailure($res, $login);
|
||||
}
|
||||
|
||||
$token = $login['data']['authToken'];
|
||||
|
||||
$instancesResponse = $this->apiClient->lookupByStatus(
|
||||
$moduleTag,
|
||||
$token,
|
||||
$username,
|
||||
$requestStatuses
|
||||
);
|
||||
if ($instancesResponse['status'] !== 'success') {
|
||||
return $this->respondWithJSendFailure($res, $instancesResponse);
|
||||
}
|
||||
|
||||
$instances = $instancesResponse['data'];
|
||||
$matchingInstances = [];
|
||||
|
||||
foreach ($instances as $instance) {
|
||||
@@ -59,13 +82,18 @@ class ElixFormsController
|
||||
continue;
|
||||
}
|
||||
|
||||
$exportTags = $this->apiClient->getExportTags(
|
||||
$exportTagsResponse = $this->apiClient->getExportTags(
|
||||
$requestId,
|
||||
$moduleTag,
|
||||
$token,
|
||||
$username,
|
||||
$exportGroup
|
||||
);
|
||||
if ($exportTagsResponse['status'] !== 'success') {
|
||||
return $this->respondWithJSendFailure($res, $exportTagsResponse);
|
||||
}
|
||||
|
||||
$exportTags = $exportTagsResponse['data'];
|
||||
|
||||
$exportTagsByName = array_column($exportTags, null, 'name');
|
||||
if (!\array_key_exists($fieldName, $exportTagsByName)) {
|
||||
@@ -80,7 +108,12 @@ class ElixFormsController
|
||||
}
|
||||
}
|
||||
|
||||
return $res->json($matchingInstances);
|
||||
return $res->json(['status' => 'success', 'data' => $matchingInstances]);
|
||||
}
|
||||
|
||||
private function respondWithJSendFailure(Response $response, array $payload)
|
||||
{
|
||||
return $response->json($payload, $payload['status'] === 'fail' ? 400 : 502);
|
||||
}
|
||||
|
||||
private function requiredString(array $values, string $key): ?string
|
||||
|
||||
+48
-29
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
namespace ElixForms\Auth;
|
||||
namespace ElixForms\Clients;
|
||||
|
||||
use Api\Core\HttpClient;
|
||||
use ElixForms\Exceptions\ElixFormsException;
|
||||
use ElixForms\Enums\ElixFormsRequestStatus;
|
||||
|
||||
class ElixFormsApiClient
|
||||
{
|
||||
@@ -17,39 +17,46 @@ class ElixFormsApiClient
|
||||
|
||||
/**
|
||||
* Restituisce le istanze del modulo, opzionalmente filtrate per stato.
|
||||
* I flag di ElixFormsRequestStatus possono essere combinati con l'operatore |.
|
||||
* Gli stati sono separati da virgole e diventano query parameter requestStatus ripetuti.
|
||||
*
|
||||
* @return array<int,array<string,mixed>>
|
||||
* @return array{status:string,data?:array<int,array<string,mixed>>,message?:string,code?:int}
|
||||
*/
|
||||
public function lookupByStatus(
|
||||
string $moduleTag,
|
||||
string $authToken,
|
||||
string $username,
|
||||
?int $status = null
|
||||
?string $requestStatuses = null
|
||||
): array
|
||||
{
|
||||
$queryParts = [];
|
||||
if ($status !== null) {
|
||||
foreach (ElixFormsRequestStatus::toApiValues($status) as $statusValue) {
|
||||
try {
|
||||
foreach (ElixFormsRequestStatus::fromQueryParameter($requestStatuses) as $statusValue) {
|
||||
$queryParts[] = 'requestStatus=' . rawurlencode($statusValue);
|
||||
}
|
||||
} catch (\InvalidArgumentException $exception) {
|
||||
return $this->fail(['requestStatuses' => $exception->getMessage()]);
|
||||
}
|
||||
$queryParts[] = 'moduleTag=' . rawurlencode($moduleTag);
|
||||
|
||||
$url = "{$this->baseUrl}/api/request/lookup/by-status?" . implode('&', $queryParts);
|
||||
$payload = $this->getJsonAsArray($url, $authToken, $username, 'LookupByStatus');
|
||||
if ($payload['status'] !== 'success') {
|
||||
return $payload;
|
||||
}
|
||||
|
||||
$payload = $payload['data'];
|
||||
$requests = $payload['value']['requests'] ?? [];
|
||||
|
||||
if (!\is_array($requests)) {
|
||||
throw new ElixFormsException('Risposta LookupByStatus non valida: requests deve essere un array.');
|
||||
return $this->error('Risposta LookupByStatus non valida: requests deve essere un array.');
|
||||
}
|
||||
|
||||
return array_values($requests);
|
||||
return $this->success(array_values($requests));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $requestId
|
||||
* @return array<int,array{name?:mixed,value?:mixed}>
|
||||
* @return array{status:string,data?:array<int,array{name?:mixed,value?:mixed}>,message?:string,code?:int}
|
||||
*/
|
||||
public function getExportTags(
|
||||
$requestId,
|
||||
@@ -61,7 +68,7 @@ class ElixFormsApiClient
|
||||
{
|
||||
$exportGroup = trim($exportGroup);
|
||||
if ($exportGroup === '') {
|
||||
throw new \InvalidArgumentException('exportGroup deve essere una stringa non vuota.');
|
||||
return $this->fail(['exportGroup' => 'deve essere una stringa non vuota.']);
|
||||
}
|
||||
|
||||
$url = \sprintf(
|
||||
@@ -72,13 +79,18 @@ class ElixFormsApiClient
|
||||
rawurlencode($exportGroup)
|
||||
);
|
||||
$payload = $this->getJsonAsArray($url, $authToken, $username, 'GetExportTags');
|
||||
if ($payload['status'] !== 'success') {
|
||||
return $payload;
|
||||
}
|
||||
|
||||
$payload = $payload['data'];
|
||||
$exportTags = $payload['value']['exportTags'] ?? [];
|
||||
|
||||
if (!\is_array($exportTags)) {
|
||||
throw new ElixFormsException('Risposta GetExportTags non valida: exportTags deve essere un array.');
|
||||
return $this->error('Risposta GetExportTags non valida: exportTags deve essere un array.');
|
||||
}
|
||||
|
||||
return array_values($exportTags);
|
||||
return $this->success(array_values($exportTags));
|
||||
}
|
||||
|
||||
private function getJsonAsArray(
|
||||
@@ -94,13 +106,9 @@ class ElixFormsApiClient
|
||||
'x-api-username' => $username,
|
||||
]);
|
||||
|
||||
$status = $response['status'] ?? 500;
|
||||
$status = (int) ($response['status'] ?? 500);
|
||||
if ($status !== 200) {
|
||||
throw new ElixFormsException(\sprintf(
|
||||
'Errore durante %s. HTTP Status: %d',
|
||||
$operation,
|
||||
$status
|
||||
));
|
||||
return $this->error(\sprintf('Errore durante %s.', $operation), $status);
|
||||
}
|
||||
|
||||
$payload = $response['json'] ?? null;
|
||||
@@ -111,22 +119,33 @@ class ElixFormsApiClient
|
||||
}
|
||||
|
||||
if (!\is_array($payload) || $jsonError !== JSON_ERROR_NONE) {
|
||||
throw new ElixFormsException(\sprintf(
|
||||
'Risposta non valida da %s: atteso JSON.',
|
||||
$operation
|
||||
));
|
||||
return $this->error(\sprintf('Risposta non valida da %s: atteso JSON.', $operation));
|
||||
}
|
||||
|
||||
$globalStatus = $payload['value']['globalStatus'] ?? null;
|
||||
if ($globalStatus === 'ERROR') {
|
||||
$description = $payload['value']['description'] ?? 'errore non specificato';
|
||||
throw new ElixFormsException(\sprintf(
|
||||
'%s ha restituito un errore: %s',
|
||||
$operation,
|
||||
$description
|
||||
));
|
||||
return $this->fail([
|
||||
'operation' => $operation,
|
||||
'description' => $description,
|
||||
]);
|
||||
}
|
||||
|
||||
return $payload;
|
||||
return $this->success($payload);
|
||||
}
|
||||
|
||||
private function success(array $data): array
|
||||
{
|
||||
return ['status' => 'success', 'data' => $data];
|
||||
}
|
||||
|
||||
private function fail(array $data): array
|
||||
{
|
||||
return ['status' => 'fail', 'data' => $data];
|
||||
}
|
||||
|
||||
private function error(string $message, int $code = 502): array
|
||||
{
|
||||
return ['status' => 'error', 'message' => $message, 'code' => $code];
|
||||
}
|
||||
}
|
||||
+25
-16
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
namespace ElixForms\Auth;
|
||||
namespace ElixForms\Clients;
|
||||
|
||||
use ElixForms\Exceptions\ElixFormsException;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
@@ -19,10 +18,9 @@ class ElixFormsAuthenticationClient {
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return string Il token di autenticazione (authToken)
|
||||
* @throws ElixFormsException Se le credenziali sono errate o c'è un errore server
|
||||
* @return array{status:string,data?:array{authToken:string},message?:string,code?:int}
|
||||
*/
|
||||
public function login(string $username, string $password): string {
|
||||
public function login(string $username, string $password): array {
|
||||
$url = "{$this->baseUrl}/services/api/authentication/login/v1";
|
||||
|
||||
try {
|
||||
@@ -39,23 +37,23 @@ class ElixFormsAuthenticationClient {
|
||||
|
||||
$status = $response->getStatusCode();
|
||||
if ($status !== 200) {
|
||||
throw new ElixFormsException("Errore durante il login elixForms. HTTP Status: " . $status);
|
||||
return $this->error('Errore durante il login elixForms.', $status);
|
||||
}
|
||||
|
||||
$body = $response->getBody()->getContents();
|
||||
$json = json_decode($body, true);
|
||||
|
||||
if (json_last_error() !== JSON_ERROR_NONE || empty($json)) {
|
||||
throw new ElixFormsException("Risposta non valida dal server elixForms: atteso JSON.");
|
||||
return $this->error('Risposta non valida dal server elixForms: atteso JSON.');
|
||||
}
|
||||
|
||||
if (isset($json['value']['authToken'])) {
|
||||
return $json['value']['authToken'];
|
||||
return $this->success(['authToken' => $json['value']['authToken']]);
|
||||
}
|
||||
|
||||
throw new ElixFormsException("authToken non trovato nella risposta del login elixForms.");
|
||||
return $this->fail(['authToken' => 'non trovato nella risposta del login elixForms.']);
|
||||
} catch (GuzzleException $e) {
|
||||
throw new ElixFormsException("Errore di connessione al server elixForms: " . $e->getMessage(), 0, $e);
|
||||
return $this->error('Errore di connessione al server elixForms.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,10 +62,9 @@ class ElixFormsAuthenticationClient {
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $token
|
||||
* @return bool True se il logout ha successo
|
||||
* @throws ElixFormsException Se c'è un errore durante il logout
|
||||
* @return array{status:string,data?:array{loggedOut:bool},message?:string,code?:int}
|
||||
*/
|
||||
public function logout(string $username, string $token): bool {
|
||||
public function logout(string $username, string $token): array {
|
||||
$url = "{$this->baseUrl}/services/api/authentication/" . urlencode($username) . '/logout/v1';
|
||||
|
||||
try {
|
||||
@@ -80,12 +77,24 @@ class ElixFormsAuthenticationClient {
|
||||
|
||||
$status = $response->getStatusCode();
|
||||
if ($status !== 200) {
|
||||
throw new ElixFormsException("Errore durante il logout elixForms. HTTP Status: " . $status);
|
||||
return $this->error('Errore durante il logout elixForms.', $status);
|
||||
}
|
||||
|
||||
return true;
|
||||
return $this->success(['loggedOut' => true]);
|
||||
} catch (GuzzleException $e) {
|
||||
throw new ElixFormsException("Errore di connessione al server elixForms: " . $e->getMessage(), 0, $e);
|
||||
return $this->error('Errore di connessione al server elixForms.');
|
||||
}
|
||||
}
|
||||
|
||||
private function success(array $data): array {
|
||||
return ['status' => 'success', 'data' => $data];
|
||||
}
|
||||
|
||||
private function fail(array $data): array {
|
||||
return ['status' => 'fail', 'data' => $data];
|
||||
}
|
||||
|
||||
private function error(string $message, int $code = 502): array {
|
||||
return ['status' => 'error', 'message' => $message, 'code' => $code];
|
||||
}
|
||||
}
|
||||
+24
-9
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
namespace ElixForms;
|
||||
namespace ElixForms\Clients;
|
||||
|
||||
use ElixForms\Auth\ElixFormsAuthenticationClient as AuthClient;
|
||||
use ElixForms\Exceptions\ElixFormsException;
|
||||
use ElixForms\Clients\ElixFormsAuthenticationClient;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
class ElixFormsClient
|
||||
class ElixFormsGenericClient
|
||||
{
|
||||
private string $baseUrl;
|
||||
private Client $httpClient;
|
||||
@@ -17,9 +16,9 @@ class ElixFormsClient
|
||||
$this->httpClient = $httpClient ?? new Client(['timeout' => 10.0, 'http_errors' => false]);
|
||||
}
|
||||
|
||||
public function auth(): AuthClient
|
||||
public function auth(): ElixFormsAuthenticationClient
|
||||
{
|
||||
return new AuthClient($this->baseUrl, $this->httpClient);
|
||||
return new ElixFormsAuthenticationClient($this->baseUrl, $this->httpClient);
|
||||
}
|
||||
|
||||
public function request(string $method, string $path, ?array $body, array $headers = []): array
|
||||
@@ -38,15 +37,31 @@ class ElixFormsClient
|
||||
$contentType = $response->getHeaderLine('Content-Type');
|
||||
$isJson = stripos($contentType, 'application/json') !== false;
|
||||
|
||||
return [
|
||||
$data = [
|
||||
'status' => $status,
|
||||
'headers' => $response->getHeaders(),
|
||||
'body' => $bodyRaw,
|
||||
'is_json' => $isJson,
|
||||
'json' => $isJson ? json_decode($bodyRaw, true) : null,
|
||||
];
|
||||
} catch (GuzzleException $e) {
|
||||
throw new ElixFormsException('Errore di connessione al server elixForms: ' . $e->getMessage(), 0, $e);
|
||||
|
||||
if ($status < 200 || $status >= 300) {
|
||||
return $this->error('Richiesta a elixForms non riuscita.', $status);
|
||||
}
|
||||
|
||||
return $this->success($data);
|
||||
} catch (GuzzleException $e) {
|
||||
return $this->error('Errore di connessione al server elixForms.');
|
||||
}
|
||||
}
|
||||
|
||||
private function success(array $data): array
|
||||
{
|
||||
return ['status' => 'success', 'data' => $data];
|
||||
}
|
||||
|
||||
private function error(string $message, int $code = 502): array
|
||||
{
|
||||
return ['status' => 'error', 'message' => $message, 'code' => $code];
|
||||
}
|
||||
}
|
||||
+29
-2
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
namespace ElixForms\Auth;
|
||||
namespace ElixForms\Enums;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
@@ -28,7 +28,7 @@ final class ElixFormsRequestStatus
|
||||
/**
|
||||
* @return array<int,string>
|
||||
*/
|
||||
public static function toApiValues(int $status): array
|
||||
public static function toApiValues(?int $status = self::ALL): array
|
||||
{
|
||||
if ($status <= 0 || ($status & ~self::ALL) !== 0) {
|
||||
throw new InvalidArgumentException('La combinazione di stati elixForms non è valida.');
|
||||
@@ -43,4 +43,31 @@ final class ElixFormsRequestStatus
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int,string>
|
||||
*/
|
||||
public static function fromQueryParameter(?string $requestStatuses): array
|
||||
{
|
||||
if ($requestStatuses === null || trim($requestStatuses) === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
$allowedValues = array_values(self::API_VALUES);
|
||||
$statuses = [];
|
||||
foreach (explode(',', $requestStatuses) as $requestStatus) {
|
||||
$requestStatus = trim($requestStatus);
|
||||
if ($requestStatus === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!in_array($requestStatus, $allowedValues, true)) {
|
||||
throw new InvalidArgumentException('Lo stato elixForms richiesto non è valido.');
|
||||
}
|
||||
|
||||
$statuses[] = $requestStatus;
|
||||
}
|
||||
|
||||
return array_values(array_unique($statuses));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
# Sample requests to try out authorization logic
|
||||
|
||||
###
|
||||
# Authorization OK
|
||||
|
||||
@term=MA
|
||||
|
||||
GET http://localhost:8000/api/dipendenti/cerca?term={{term}}
|
||||
Authorization: Basic elixforms_ws:password123
|
||||
X-API-Key: myApiAccessToken
|
||||
|
||||
###
|
||||
# Should return 401 Unauthorized
|
||||
|
||||
@term=MA
|
||||
|
||||
GET http://localhost:8000/api/dipendenti/cerca?term={{term}}
|
||||
@@ -0,0 +1,26 @@
|
||||
# Sample requests to trigger web service
|
||||
|
||||
###
|
||||
# TAG not found
|
||||
|
||||
GET http://localhost:8000/elixforms/instances/search?moduleTag=ANTANI&fieldName=responsabileScientifico.codiceFiscale&fieldValue=MMM
|
||||
|
||||
###
|
||||
# No data found (choose a TAG with very few instances...)
|
||||
|
||||
GET http://localhost:8000/elixforms/instances/search?moduleTag=RequestForm_EDILIZIA_RDA_MANUTENZIONE&fieldName=responsabileScientifico.codiceFiscale&fieldValue=MMM
|
||||
|
||||
###
|
||||
# With one status
|
||||
|
||||
GET http://localhost:8000/elixforms/instances/search?requestStatuses=PROCESSED&moduleTag=RequestForm_EDILIZIA_RDA_MANUTENZIONE&fieldName=responsabileScientifico.codiceFiscale&fieldValue=MMM
|
||||
|
||||
###
|
||||
# With two statuses (comma-separated)
|
||||
|
||||
GET http://localhost:8000/elixforms/instances/search?requestStatuses=PROCESSED,SUBMITTED&moduleTag=RequestForm_EDILIZIA_RDA_MANUTENZIONE&fieldName=responsabileScientifico.codiceFiscale&fieldValue=MMM
|
||||
|
||||
###
|
||||
# With wrong status
|
||||
|
||||
GET http://localhost:8000/elixforms/instances/search?requestStatuses=UNKNOWN&moduleTag=RequestForm_EDILIZIA_RDA_MANUTENZIONE&fieldName=responsabileScientifico.codiceFiscale&fieldValue=MMM
|
||||
@@ -2,8 +2,7 @@
|
||||
namespace Tests\Unit;
|
||||
|
||||
use Api\Core\HttpClient;
|
||||
use ElixForms\Auth\ElixFormsApiClient;
|
||||
use ElixForms\Auth\ElixFormsRequestStatus;
|
||||
use ElixForms\Clients\ElixFormsApiClient;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class ElixFormsApiClientTest extends TestCase
|
||||
@@ -32,16 +31,17 @@ final class ElixFormsApiClientTest extends TestCase
|
||||
};
|
||||
$client = new ElixFormsApiClient('https://example.test', $httpClient);
|
||||
|
||||
$requests = $client->lookupByStatus('MODULO TEST', 'token', 'user');
|
||||
$response = $client->lookupByStatus('MODULO TEST', 'token', 'user');
|
||||
|
||||
self::assertSame([['requestId' => 123]], $requests);
|
||||
self::assertSame('success', $response['status']);
|
||||
self::assertSame([['requestId' => 123]], $response['data']);
|
||||
self::assertStringNotContainsString('requestStatus=', $httpClient->url);
|
||||
self::assertStringContainsString('moduleTag=MODULO%20TEST', $httpClient->url);
|
||||
self::assertSame('Bearer token', $httpClient->headers['Authorization']);
|
||||
self::assertSame('user', $httpClient->headers['x-api-username']);
|
||||
}
|
||||
|
||||
public function testLookupByStatusExpandsCombinedFlags(): void
|
||||
public function testLookupByStatusExpandsCommaSeparatedStatuses(): void
|
||||
{
|
||||
$httpClient = new class extends HttpClient {
|
||||
public string $url = '';
|
||||
@@ -67,7 +67,7 @@ final class ElixFormsApiClientTest extends TestCase
|
||||
'MODULO',
|
||||
'token',
|
||||
'user',
|
||||
ElixFormsRequestStatus::IN_PROGRESS | ElixFormsRequestStatus::PROCESSED
|
||||
'IN_PROGRESS, PROCESSED'
|
||||
);
|
||||
|
||||
self::assertStringContainsString('requestStatus=IN_PROGRESS', $httpClient->url);
|
||||
@@ -75,11 +75,39 @@ final class ElixFormsApiClientTest extends TestCase
|
||||
self::assertStringContainsString('requestStatus=PROCESSED', $httpClient->url);
|
||||
}
|
||||
|
||||
public function testRequestStatusRejectsUnknownFlags(): void
|
||||
public function testLookupByStatusOmitsStatusesWhenTheValueIsEmpty(): void
|
||||
{
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$httpClient = new class extends HttpClient {
|
||||
public string $url = '';
|
||||
|
||||
ElixFormsRequestStatus::toApiValues(8);
|
||||
public function get(string $url, array $headers = [])
|
||||
{
|
||||
$this->url = $url;
|
||||
|
||||
return [
|
||||
'status' => 200,
|
||||
'json' => ['value' => ['globalStatus' => 'OK', 'requests' => []]],
|
||||
];
|
||||
}
|
||||
};
|
||||
$client = new ElixFormsApiClient('https://example.test', $httpClient);
|
||||
|
||||
$client->lookupByStatus('MODULO', 'token', 'user', ' ');
|
||||
|
||||
self::assertStringNotContainsString('requestStatus=', $httpClient->url);
|
||||
}
|
||||
|
||||
public function testLookupByStatusReturnsFailForAnUnknownStatus(): void
|
||||
{
|
||||
$httpClient = new HttpClient();
|
||||
$client = new ElixFormsApiClient('https://example.test', $httpClient);
|
||||
|
||||
$response = $client->lookupByStatus('MODULO', 'token', 'user', 'UNKNOWN');
|
||||
|
||||
self::assertSame([
|
||||
'status' => 'fail',
|
||||
'data' => ['requestStatuses' => 'Lo stato elixForms richiesto non è valido.'],
|
||||
], $response);
|
||||
}
|
||||
|
||||
public function testGetExportTagsSupportsVendorJsonContentTypeResponses(): void
|
||||
@@ -107,14 +135,15 @@ final class ElixFormsApiClientTest extends TestCase
|
||||
};
|
||||
$client = new ElixFormsApiClient('https://example.test/', $httpClient);
|
||||
|
||||
$tags = $client->getExportTags(42, 'MODULO', 'token', 'user');
|
||||
$response = $client->getExportTags(42, 'MODULO', 'token', 'user');
|
||||
|
||||
self::assertSame('success', $response['status']);
|
||||
self::assertSame(
|
||||
[['name' => 'contratto.id', 'value' => 'ABC-123']],
|
||||
$tags
|
||||
$response['data']
|
||||
);
|
||||
self::assertSame(
|
||||
'https://example.test/eF/services/api/request/42/view/_DEFAULT/exportTags/get/v1?moduleTag=MODULO&exportGroup=API',
|
||||
'https://example.test/services/api/request/42/view/_DEFAULT/exportTags/get/v1?moduleTag=MODULO&exportGroup=API',
|
||||
$httpClient->url
|
||||
);
|
||||
}
|
||||
@@ -146,12 +175,34 @@ final class ElixFormsApiClientTest extends TestCase
|
||||
self::assertStringContainsString('exportGroup=REPORT%20ORE', $httpClient->url);
|
||||
}
|
||||
|
||||
public function testGetExportTagsRejectsAnEmptyExportGroup(): void
|
||||
public function testGetExportTagsReturnsFailForAnEmptyExportGroup(): void
|
||||
{
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
|
||||
$httpClient = new HttpClient();
|
||||
$client = new ElixFormsApiClient('https://example.test', $httpClient);
|
||||
$client->getExportTags(42, 'MODULO', 'token', 'user', ' ');
|
||||
$response = $client->getExportTags(42, 'MODULO', 'token', 'user', ' ');
|
||||
|
||||
self::assertSame([
|
||||
'status' => 'fail',
|
||||
'data' => ['exportGroup' => 'deve essere una stringa non vuota.'],
|
||||
], $response);
|
||||
}
|
||||
|
||||
public function testLookupByStatusReturnsErrorForAnUnsuccessfulHttpResponse(): void
|
||||
{
|
||||
$httpClient = new class extends HttpClient {
|
||||
public function get(string $url, array $headers = [])
|
||||
{
|
||||
return ['status' => 503];
|
||||
}
|
||||
};
|
||||
$client = new ElixFormsApiClient('https://example.test', $httpClient);
|
||||
|
||||
$response = $client->lookupByStatus('MODULO', 'token', 'user');
|
||||
|
||||
self::assertSame([
|
||||
'status' => 'error',
|
||||
'message' => 'Errore durante LookupByStatus.',
|
||||
'code' => 503,
|
||||
], $response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ use Api\Controllers\V1\ElixFormsController;
|
||||
use Api\Core\Config;
|
||||
use Api\Core\Request;
|
||||
use Api\Core\Response;
|
||||
use ElixForms\Auth\ElixFormsApiClient;
|
||||
use ElixForms\Auth\ElixFormsAuthenticationClient;
|
||||
use ElixForms\Clients\ElixFormsApiClient;
|
||||
use ElixForms\Clients\ElixFormsAuthenticationClient;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class ElixFormsControllerTest extends TestCase
|
||||
@@ -18,9 +18,9 @@ final class ElixFormsControllerTest extends TestCase
|
||||
{
|
||||
}
|
||||
|
||||
public function login(string $username, string $password): string
|
||||
public function login(string $username, string $password): array
|
||||
{
|
||||
return 'token';
|
||||
return ['status' => 'success', 'data' => ['authToken' => 'token']];
|
||||
}
|
||||
};
|
||||
$apiClient = new class extends ElixFormsApiClient {
|
||||
@@ -32,14 +32,18 @@ final class ElixFormsControllerTest extends TestCase
|
||||
string $moduleTag,
|
||||
string $authToken,
|
||||
string $username,
|
||||
?int $status = null
|
||||
?string $requestStatuses = null
|
||||
): array
|
||||
{
|
||||
return [
|
||||
if ($requestStatuses !== 'IN_PROGRESS,PROCESSED') {
|
||||
throw new \RuntimeException('requestStatuses non inoltrato al client.');
|
||||
}
|
||||
|
||||
return ['status' => 'success', 'data' => [
|
||||
['idDomanda' => 10],
|
||||
['requestId' => 20],
|
||||
['idRequest' => 30],
|
||||
];
|
||||
]];
|
||||
}
|
||||
|
||||
public function getExportTags(
|
||||
@@ -69,7 +73,7 @@ final class ElixFormsControllerTest extends TestCase
|
||||
],
|
||||
];
|
||||
|
||||
return [$tags[$requestId]];
|
||||
return ['status' => 'success', 'data' => [$tags[$requestId]]];
|
||||
}
|
||||
};
|
||||
$config = new class extends Config {
|
||||
@@ -85,6 +89,7 @@ final class ElixFormsControllerTest extends TestCase
|
||||
'moduleTag' => 'MODULO',
|
||||
'fieldName' => 'contratto.id',
|
||||
'fieldValue' => 'abc-123',
|
||||
'requestStatuses' => 'IN_PROGRESS,PROCESSED',
|
||||
'exportGroup' => ' CUSTOM ',
|
||||
];
|
||||
}
|
||||
@@ -97,7 +102,10 @@ final class ElixFormsControllerTest extends TestCase
|
||||
self::fail('La risposta avrebbe dovuto interrompere il flusso del test.');
|
||||
} catch (CapturedResponseException $exception) {
|
||||
self::assertSame(200, $exception->status);
|
||||
self::assertSame([['requestId' => 20]], $exception->payload);
|
||||
self::assertSame([
|
||||
'status' => 'success',
|
||||
'data' => [['requestId' => 20]],
|
||||
], $exception->payload);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user