From e2d67fef14617f8dc9752cb15ffe75edaafa93bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D?= Date: Thu, 29 Aug 2024 18:38:59 +0200 Subject: [PATCH] test(IT): Test Client use cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rubén D --- .../web/Controllers/Client/ClientSaveBase.php | 20 +- .../web/Controllers/Client/ClientViewBase.php | 32 +- .../Controllers/Client/CreateController.php | 67 ++-- .../Controllers/Client/DeleteController.php | 87 +++-- .../web/Controllers/Client/EditController.php | 63 ++-- .../Client/SaveCreateController.php | 86 +++-- .../Controllers/Client/SaveEditController.php | 84 +++-- .../Controllers/Client/SearchController.php | 60 ++-- .../web/Controllers/Client/ViewController.php | 60 ++-- .../Controllers/Helpers/Grid/ClientGrid.php | 17 +- app/modules/web/Forms/ClientForm.php | 4 +- .../Client/Repositories/Client.php | 1 - .../Web/Controllers/Client/ClientTest.php | 303 ++++++++++++++++++ 13 files changed, 574 insertions(+), 310 deletions(-) create mode 100644 tests/SP/Modules/Web/Controllers/Client/ClientTest.php diff --git a/app/modules/web/Controllers/Client/ClientSaveBase.php b/app/modules/web/Controllers/Client/ClientSaveBase.php index a0905ce1..e88dc3e5 100644 --- a/app/modules/web/Controllers/Client/ClientSaveBase.php +++ b/app/modules/web/Controllers/Client/ClientSaveBase.php @@ -26,7 +26,9 @@ namespace SP\Modules\Web\Controllers\Client; use SP\Core\Application; +use SP\Domain\Auth\Services\AuthException; use SP\Domain\Client\Ports\ClientService; +use SP\Domain\Core\Exceptions\SessionTimeout; use SP\Domain\CustomField\Ports\CustomFieldDataService; use SP\Modules\Web\Controllers\ControllerBase; use SP\Modules\Web\Forms\ClientForm; @@ -37,22 +39,22 @@ use SP\Mvc\Controller\WebControllerHelper; */ abstract class ClientSaveBase extends ControllerBase { - protected ClientService $clientService; - protected CustomFieldDataService $customFieldService; - protected ClientForm $form; + protected readonly ClientForm $form; + /** + * @throws AuthException + * @throws SessionTimeout + */ public function __construct( - Application $application, - WebControllerHelper $webControllerHelper, - ClientService $clientService, - CustomFieldDataService $customFieldService + Application $application, + WebControllerHelper $webControllerHelper, + protected readonly ClientService $clientService, + protected readonly CustomFieldDataService $customFieldService ) { parent::__construct($application, $webControllerHelper); $this->checkLoggedIn(); - $this->clientService = $clientService; - $this->customFieldService = $customFieldService; $this->form = new ClientForm($application, $this->request); } } diff --git a/app/modules/web/Controllers/Client/ClientViewBase.php b/app/modules/web/Controllers/Client/ClientViewBase.php index 3f598677..b36a9cac 100644 --- a/app/modules/web/Controllers/Client/ClientViewBase.php +++ b/app/modules/web/Controllers/Client/ClientViewBase.php @@ -24,15 +24,15 @@ namespace SP\Modules\Web\Controllers\Client; - -use SP\Core\Acl\Acl; use SP\Core\Application; +use SP\Domain\Auth\Services\AuthException; use SP\Domain\Client\Models\Client; use SP\Domain\Client\Ports\ClientService; use SP\Domain\Common\Services\ServiceException; use SP\Domain\Core\Acl\AclActionsInterface; use SP\Domain\Core\Exceptions\ConstraintException; use SP\Domain\Core\Exceptions\QueryException; +use SP\Domain\Core\Exceptions\SessionTimeout; use SP\Domain\Core\Exceptions\SPException; use SP\Domain\CustomField\Ports\CustomFieldDataService; use SP\Infrastructure\Common\Repositories\NoSuchItemException; @@ -47,27 +47,25 @@ abstract class ClientViewBase extends ControllerBase { use ItemTrait; - private ClientService $clientService; - private CustomFieldDataService $customFieldService; - + /** + * @throws AuthException + * @throws SessionTimeout + */ public function __construct( - Application $application, - WebControllerHelper $webControllerHelper, - ClientService $clientService, - CustomFieldDataService $customFieldService + Application $application, + WebControllerHelper $webControllerHelper, + private readonly ClientService $clientService, + private readonly CustomFieldDataService $customFieldService ) { parent::__construct($application, $webControllerHelper); $this->checkLoggedIn(); - - $this->clientService = $clientService; - $this->customFieldService = $customFieldService; } /** * Sets view data for displaying client's data * - * @param int|null $clientId + * @param int|null $clientId * * @throws ConstraintException * @throws NoSuchItemException @@ -75,7 +73,7 @@ abstract class ClientViewBase extends ControllerBase * @throws SPException * @throws ServiceException */ - protected function setViewData(?int $clientId = null): void + protected function setViewData(?int $clientId = null, bool $readonly = true): void { $this->view->addTemplate('client', 'itemshow'); @@ -87,10 +85,12 @@ abstract class ClientViewBase extends ControllerBase $this->view->assign( 'nextAction', - Acl::getActionRoute(AclActionsInterface::ITEMS_MANAGE) + $this->acl->getRouteFor(AclActionsInterface::ITEMS_MANAGE) ); - if ($this->view->isView === true) { + $this->view->assign('isView', $readonly); + + if ($readonly) { $this->view->assign('disabled', 'disabled'); $this->view->assign('readonly', 'readonly'); } else { diff --git a/app/modules/web/Controllers/Client/CreateController.php b/app/modules/web/Controllers/Client/CreateController.php index 574cbe97..0505060c 100644 --- a/app/modules/web/Controllers/Client/CreateController.php +++ b/app/modules/web/Controllers/Client/CreateController.php @@ -24,53 +24,48 @@ namespace SP\Modules\Web\Controllers\Client; - -use Exception; -use JsonException; use SP\Core\Events\Event; +use SP\Domain\Common\Attributes\Action; +use SP\Domain\Common\Dtos\ActionResponse; +use SP\Domain\Common\Enums\ResponseType; +use SP\Domain\Common\Services\ServiceException; use SP\Domain\Core\Acl\AclActionsInterface; -use SP\Domain\Http\Dtos\JsonMessage; -use SP\Modules\Web\Controllers\Traits\JsonTrait; +use SP\Domain\Core\Exceptions\ConstraintException; +use SP\Domain\Core\Exceptions\QueryException; +use SP\Domain\Core\Exceptions\SPException; +use SP\Infrastructure\Common\Repositories\NoSuchItemException; + +use function SP\__; +use function SP\__u; /** * Class CreateController */ final class CreateController extends ClientViewBase { - use JsonTrait; - /** - * @return bool - * @throws JsonException + * @return ActionResponse + * @throws ServiceException + * @throws ConstraintException + * @throws QueryException + * @throws SPException + * @throws NoSuchItemException */ - public function createAction(): bool + #[Action(ResponseType::JSON)] + public function createAction(): ActionResponse { - try { - if (!$this->acl->checkUserAccess(AclActionsInterface::CLIENT_CREATE)) { - return $this->returnJsonResponse( - JsonMessage::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - $this->view->assign('header', __('New Client')); - $this->view->assign('isView', false); - $this->view->assign('route', 'client/saveCreate'); - - $this->setViewData(); - - $this->eventDispatcher->notify('show.client.create', new Event($this)); - - return $this->returnJsonResponseData(['html' => $this->render()]); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notify( - 'exception', - new Event($e) - ); - - return $this->returnJsonResponseException($e); + if (!$this->acl->checkUserAccess(AclActionsInterface::CLIENT_CREATE)) { + return ActionResponse::error(__u('You don\'t have permission to do this operation')); } + + $this->view->assign('header', __('New Client')); + $this->view->assign('isView', false); + $this->view->assign('route', 'client/saveCreate'); + + $this->setViewData(); + + $this->eventDispatcher->notify('show.client.create', new Event($this)); + + return ActionResponse::ok('', ['html' => $this->render()]); } } diff --git a/app/modules/web/Controllers/Client/DeleteController.php b/app/modules/web/Controllers/Client/DeleteController.php index e66c589f..1e64753a 100644 --- a/app/modules/web/Controllers/Client/DeleteController.php +++ b/app/modules/web/Controllers/Client/DeleteController.php @@ -24,16 +24,21 @@ namespace SP\Modules\Web\Controllers\Client; - -use Exception; -use JsonException; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; +use SP\Domain\Common\Attributes\Action; +use SP\Domain\Common\Dtos\ActionResponse; +use SP\Domain\Common\Enums\ResponseType; +use SP\Domain\Common\Services\ServiceException; use SP\Domain\Core\Acl\AclActionsInterface; -use SP\Domain\Http\Dtos\JsonMessage; +use SP\Domain\Core\Exceptions\ConstraintException; +use SP\Domain\Core\Exceptions\QueryException; +use SP\Infrastructure\Common\Repositories\NoSuchItemException; use SP\Modules\Web\Controllers\Traits\JsonTrait; use SP\Mvc\Controller\ItemTrait; +use function SP\__u; + /** * Class DeleteController */ @@ -45,60 +50,48 @@ final class DeleteController extends ClientSaveBase /** * Delete action * - * @param int|null $id + * @param int|null $id * - * @return bool - * @throws JsonException + * @return ActionResponse + * @throws ServiceException + * @throws ConstraintException + * @throws QueryException + * @throws NoSuchItemException */ - public function deleteAction(?int $id = null): bool + #[Action(ResponseType::JSON)] + public function deleteAction(?int $id = null): ActionResponse { - try { - if (!$this->acl->checkUserAccess(AclActionsInterface::CLIENT_DELETE)) { - return $this->returnJsonResponse( - JsonMessage::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } + if (!$this->acl->checkUserAccess(AclActionsInterface::CLIENT_DELETE)) { + return ActionResponse::error(__u('You don\'t have permission to do this operation')); + } - if ($id === null) { - $this->clientService->deleteByIdBatch($this->getItemsIdFromRequest($this->request)); - - $this->deleteCustomFieldsForItem(AclActionsInterface::CLIENT, $id, $this->customFieldService); - - $this->eventDispatcher->notify( - 'delete.client.selection', - new Event( - $this, - EventMessage::build()->addDescription(__u('Clients deleted')) - ) - ); - - return $this->returnJsonResponse(JsonMessage::JSON_SUCCESS, __u('Clients deleted')); - } - $this->clientService->delete($id); - - $this->deleteCustomFieldsForItem(AclActionsInterface::CLIENT, $id, $this->customFieldService); + if ($id === null) { + $ids = $this->getItemsIdFromRequest($this->request); + $this->clientService->deleteByIdBatch($ids); + $this->deleteCustomFieldsForItem(AclActionsInterface::CLIENT, $ids, $this->customFieldService); $this->eventDispatcher->notify( - 'delete.client', + 'delete.client.selection', new Event( $this, - EventMessage::build() - ->addDescription(__u('Client deleted')) - ->addDetail(__u('Client'), $id) + EventMessage::build()->addDescription(__u('Clients deleted')) ) ); - return $this->returnJsonResponse( - JsonMessage::JSON_SUCCESS, - __u('Client deleted') - ); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notify('exception', new Event($e)); - - return $this->returnJsonResponseException($e); + return ActionResponse::ok(__u('Clients deleted')); } + $this->clientService->delete($id); + + $this->deleteCustomFieldsForItem(AclActionsInterface::CLIENT, $id, $this->customFieldService); + + $this->eventDispatcher->notify( + 'delete.client', + new Event( + $this, + EventMessage::build(__u('Client deleted'))->addDetail(__u('Client'), $id) + ) + ); + + return ActionResponse::ok(__u('Client deleted')); } } diff --git a/app/modules/web/Controllers/Client/EditController.php b/app/modules/web/Controllers/Client/EditController.php index 099a2919..a253deee 100644 --- a/app/modules/web/Controllers/Client/EditController.php +++ b/app/modules/web/Controllers/Client/EditController.php @@ -24,14 +24,21 @@ namespace SP\Modules\Web\Controllers\Client; - -use Exception; -use JsonException; use SP\Core\Events\Event; +use SP\Domain\Common\Attributes\Action; +use SP\Domain\Common\Dtos\ActionResponse; +use SP\Domain\Common\Enums\ResponseType; +use SP\Domain\Common\Services\ServiceException; use SP\Domain\Core\Acl\AclActionsInterface; -use SP\Domain\Http\Dtos\JsonMessage; +use SP\Domain\Core\Exceptions\ConstraintException; +use SP\Domain\Core\Exceptions\QueryException; +use SP\Domain\Core\Exceptions\SPException; +use SP\Infrastructure\Common\Repositories\NoSuchItemException; use SP\Modules\Web\Controllers\Traits\JsonTrait; +use function SP\__; +use function SP\__u; + /** * Class EditController */ @@ -42,36 +49,30 @@ final class EditController extends ClientViewBase /** * Edit action * - * @param int $id + * @param int $id * - * @return bool - * @throws JsonException + * @return ActionResponse + * @throws ServiceException + * @throws ConstraintException + * @throws QueryException + * @throws SPException + * @throws NoSuchItemException */ - public function editAction(int $id): bool + #[Action(ResponseType::JSON)] + public function editAction(int $id): ActionResponse { - try { - if (!$this->acl->checkUserAccess(AclActionsInterface::CLIENT_EDIT)) { - return $this->returnJsonResponse( - JsonMessage::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - $this->view->assign('header', __('Edit Client')); - $this->view->assign('isView', false); - $this->view->assign('route', 'client/saveEdit/'.$id); - - $this->setViewData($id); - - $this->eventDispatcher->notify('show.client.edit', new Event($this)); - - return $this->returnJsonResponseData(['html' => $this->render()]); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notify('exception', new Event($e)); - - return $this->returnJsonResponseException($e); + if (!$this->acl->checkUserAccess(AclActionsInterface::CLIENT_EDIT)) { + return ActionResponse::error(__u('You don\'t have permission to do this operation')); } + + $this->view->assign('header', __('Edit Client')); + $this->view->assign('isView', false); + $this->view->assign('route', 'client/saveEdit/' . $id); + + $this->setViewData($id, false); + + $this->eventDispatcher->notify('show.client.edit', new Event($this)); + + return ActionResponse::ok('', ['html' => $this->render()]); } } diff --git a/app/modules/web/Controllers/Client/SaveCreateController.php b/app/modules/web/Controllers/Client/SaveCreateController.php index f9bb6a4c..e4231403 100644 --- a/app/modules/web/Controllers/Client/SaveCreateController.php +++ b/app/modules/web/Controllers/Client/SaveCreateController.php @@ -25,16 +25,21 @@ namespace SP\Modules\Web\Controllers\Client; -use Exception; -use JsonException; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; +use SP\Domain\Common\Attributes\Action; +use SP\Domain\Common\Dtos\ActionResponse; +use SP\Domain\Common\Enums\ResponseType; +use SP\Domain\Common\Services\ServiceException; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Domain\Core\Exceptions\ValidationException; -use SP\Domain\Http\Dtos\JsonMessage; +use SP\Infrastructure\Common\Repositories\DuplicatedItemException; use SP\Modules\Web\Controllers\Traits\JsonTrait; use SP\Mvc\Controller\ItemTrait; +use function SP\__u; + /** * Class SaveCreateController */ @@ -44,51 +49,40 @@ final class SaveCreateController extends ClientSaveBase use JsonTrait; /** - * @return bool - * @throws JsonException + * @return ActionResponse + * @throws ValidationException + * @throws ServiceException + * @throws SPException + * @throws DuplicatedItemException */ - public function saveCreateAction(): bool + #[Action(ResponseType::JSON)] + public function saveCreateAction(): ActionResponse { - try { - if (!$this->acl->checkUserAccess(AclActionsInterface::CLIENT_CREATE)) { - return $this->returnJsonResponse( - JsonMessage::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - $this->form->validateFor(AclActionsInterface::CLIENT_CREATE); - - $itemData = $this->form->getItemData(); - - $id = $this->clientService->create($itemData); - - $this->eventDispatcher->notify( - 'create.client', - new Event( - $this, - EventMessage::build() - ->addDescription(__u('Client added')) - ->addDetail(__u('Client'), $itemData->getName()) - ) - ); - - $this->addCustomFieldsForItem( - AclActionsInterface::CLIENT, - $id, - $this->request, - $this->customFieldService - ); - - return $this->returnJsonResponse(JsonMessage::JSON_SUCCESS, __u('Client added')); - } catch (ValidationException $e) { - return $this->returnJsonResponseException($e); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notify('exception', new Event($e)); - - return $this->returnJsonResponseException($e); + if (!$this->acl->checkUserAccess(AclActionsInterface::CLIENT_CREATE)) { + return ActionResponse::error(__u('You don\'t have permission to do this operation')); } + + $this->form->validateFor(AclActionsInterface::CLIENT_CREATE); + + $itemData = $this->form->getItemData(); + + $id = $this->clientService->create($itemData); + + $this->eventDispatcher->notify( + 'create.client', + new Event( + $this, + EventMessage::build(__u('Client added'))->addDetail(__u('Client'), $itemData->getName()) + ) + ); + + $this->addCustomFieldsForItem( + AclActionsInterface::CLIENT, + $id, + $this->request, + $this->customFieldService + ); + + return ActionResponse::ok(__u('Client added')); } } diff --git a/app/modules/web/Controllers/Client/SaveEditController.php b/app/modules/web/Controllers/Client/SaveEditController.php index 8dfd636d..a85aec81 100644 --- a/app/modules/web/Controllers/Client/SaveEditController.php +++ b/app/modules/web/Controllers/Client/SaveEditController.php @@ -25,16 +25,22 @@ namespace SP\Modules\Web\Controllers\Client; -use Exception; -use JsonException; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; +use SP\Domain\Common\Attributes\Action; +use SP\Domain\Common\Dtos\ActionResponse; +use SP\Domain\Common\Enums\ResponseType; +use SP\Domain\Common\Services\ServiceException; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\ConstraintException; +use SP\Domain\Core\Exceptions\QueryException; +use SP\Domain\Core\Exceptions\SPException; use SP\Domain\Core\Exceptions\ValidationException; -use SP\Domain\Http\Dtos\JsonMessage; use SP\Modules\Web\Controllers\Traits\JsonTrait; use SP\Mvc\Controller\ItemTrait; +use function SP\__u; + /** * Class SaveEditController */ @@ -46,49 +52,41 @@ final class SaveEditController extends ClientSaveBase /** * Saves edit action * - * @param int $id + * @param int $id * - * @return bool - * @throws JsonException + * @return ActionResponse + * @throws ValidationException + * @throws ServiceException + * @throws ConstraintException + * @throws QueryException + * @throws SPException */ - public function saveEditAction(int $id): bool + #[Action(ResponseType::JSON)] + public function saveEditAction(int $id): ActionResponse { - try { - if (!$this->acl->checkUserAccess(AclActionsInterface::CLIENT_EDIT)) { - return $this->returnJsonResponse( - JsonMessage::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - $this->form->validateFor(AclActionsInterface::CLIENT_EDIT, $id); - - $this->clientService->update($this->form->getItemData()); - - $this->eventDispatcher->notify( - 'edit.client', - new Event( - $this, - EventMessage::build()->addDescription(__u('Client updated'))->addDetail(__u('Client'), $id) - ) - ); - - $this->updateCustomFieldsForItem( - AclActionsInterface::CLIENT, - $id, - $this->request, - $this->customFieldService - ); - - return $this->returnJsonResponse(JsonMessage::JSON_SUCCESS, __u('Client updated')); - } catch (ValidationException $e) { - return $this->returnJsonResponseException($e); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notify('exception', new Event($e)); - - return $this->returnJsonResponseException($e); + if (!$this->acl->checkUserAccess(AclActionsInterface::CLIENT_EDIT)) { + return ActionResponse::error(__u('You don\'t have permission to do this operation')); } + + $this->form->validateFor(AclActionsInterface::CLIENT_EDIT, $id); + + $this->clientService->update($this->form->getItemData()); + + $this->eventDispatcher->notify( + 'edit.client', + new Event( + $this, + EventMessage::build()->addDescription(__u('Client updated'))->addDetail(__u('Client'), $id) + ) + ); + + $this->updateCustomFieldsForItem( + AclActionsInterface::CLIENT, + $id, + $this->request, + $this->customFieldService + ); + + return ActionResponse::ok(__u('Client updated')); } } diff --git a/app/modules/web/Controllers/Client/SearchController.php b/app/modules/web/Controllers/Client/SearchController.php index fb2344af..e3fe12d2 100644 --- a/app/modules/web/Controllers/Client/SearchController.php +++ b/app/modules/web/Controllers/Client/SearchController.php @@ -25,76 +25,49 @@ namespace SP\Modules\Web\Controllers\Client; -use JsonException; use SP\Core\Application; +use SP\Domain\Auth\Services\AuthException; use SP\Domain\Client\Ports\ClientService; use SP\Domain\Core\Acl\AclActionsInterface; use SP\Domain\Core\Exceptions\ConstraintException; use SP\Domain\Core\Exceptions\QueryException; +use SP\Domain\Core\Exceptions\SessionTimeout; use SP\Domain\Core\Exceptions\SPException; -use SP\Domain\Http\Dtos\JsonMessage; use SP\Html\DataGrid\DataGridInterface; -use SP\Modules\Web\Controllers\ControllerBase; use SP\Modules\Web\Controllers\Helpers\Grid\ClientGrid; -use SP\Modules\Web\Controllers\Traits\JsonTrait; +use SP\Modules\Web\Controllers\SearchGridControllerBase; use SP\Mvc\Controller\ItemTrait; use SP\Mvc\Controller\WebControllerHelper; /** * Class SearchController */ -final class SearchController extends ControllerBase +final class SearchController extends SearchGridControllerBase { use ItemTrait; - use JsonTrait; - - private ClientService $clientService; - private ClientGrid $clientGrid; + /** + * @throws AuthException + * @throws SessionTimeout + */ public function __construct( - Application $application, - WebControllerHelper $webControllerHelper, - ClientService $clientService, - ClientGrid $clientGrid + Application $application, + WebControllerHelper $webControllerHelper, + private readonly ClientService $clientService, + private readonly ClientGrid $clientGrid ) { parent::__construct($application, $webControllerHelper); $this->checkLoggedIn(); - - $this->clientService = $clientService; - $this->clientGrid = $clientGrid; - } - - /** - * Search action - * - * @return bool - * @throws ConstraintException - * @throws QueryException - * @throws SPException - * @throws JsonException - */ - public function searchAction(): bool - { - if (!$this->acl->checkUserAccess(AclActionsInterface::CLIENT_SEARCH)) { - return $this->returnJsonResponse( - JsonMessage::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - $this->view->addTemplate('datagrid-table', 'grid'); - $this->view->assign('index', $this->request->analyzeInt('activetab', 0)); - $this->view->assign('data', $this->getSearchGrid()); - - return $this->returnJsonResponseData(['html' => $this->render()]); } /** * getSearchGrid * + * @return DataGridInterface * @throws ConstraintException * @throws QueryException + * @throws SPException */ protected function getSearchGrid(): DataGridInterface { @@ -105,4 +78,9 @@ final class SearchController extends ControllerBase $itemSearchData ); } + + protected function getAclAction(): int + { + return AclActionsInterface::CLIENT_SEARCH; + } } diff --git a/app/modules/web/Controllers/Client/ViewController.php b/app/modules/web/Controllers/Client/ViewController.php index 27212490..b9513eef 100644 --- a/app/modules/web/Controllers/Client/ViewController.php +++ b/app/modules/web/Controllers/Client/ViewController.php @@ -24,13 +24,21 @@ namespace SP\Modules\Web\Controllers\Client; -use Exception; -use JsonException; use SP\Core\Events\Event; +use SP\Domain\Common\Attributes\Action; +use SP\Domain\Common\Dtos\ActionResponse; +use SP\Domain\Common\Enums\ResponseType; +use SP\Domain\Common\Services\ServiceException; use SP\Domain\Core\Acl\AclActionsInterface; -use SP\Domain\Http\Dtos\JsonMessage; +use SP\Domain\Core\Exceptions\ConstraintException; +use SP\Domain\Core\Exceptions\QueryException; +use SP\Domain\Core\Exceptions\SPException; +use SP\Infrastructure\Common\Repositories\NoSuchItemException; use SP\Modules\Web\Controllers\Traits\JsonTrait; +use function SP\__; +use function SP\__u; + /** * Class ViewController * @@ -43,35 +51,29 @@ final class ViewController extends ClientViewBase /** * View action * - * @param int $id + * @param int $id * - * @return bool - * @throws JsonException + * @return ActionResponse + * @throws ServiceException + * @throws ConstraintException + * @throws QueryException + * @throws SPException + * @throws NoSuchItemException */ - public function viewAction(int $id): bool + #[Action(ResponseType::JSON)] + public function viewAction(int $id): ActionResponse { - try { - if (!$this->acl->checkUserAccess(AclActionsInterface::CLIENT_VIEW)) { - return $this->returnJsonResponse( - JsonMessage::JSON_ERROR, - __u('You don\'t have permission to do this operation') - ); - } - - $this->view->assign('header', __('View Client')); - $this->view->assign('isView', true); - - $this->setViewData($id); - - $this->eventDispatcher->notify('show.client', new Event($this)); - - return $this->returnJsonResponseData(['html' => $this->render()]); - } catch (Exception $e) { - processException($e); - - $this->eventDispatcher->notify('exception', new Event($e)); - - return $this->returnJsonResponseException($e); + if (!$this->acl->checkUserAccess(AclActionsInterface::CLIENT_VIEW)) { + return ActionResponse::error(__u('You don\'t have permission to do this operation')); } + + $this->view->assign('header', __('View Client')); + $this->view->assign('isView', true); + + $this->setViewData($id); + + $this->eventDispatcher->notify('show.client', new Event($this)); + + return ActionResponse::ok('', ['html' => $this->render()]); } } diff --git a/app/modules/web/Controllers/Helpers/Grid/ClientGrid.php b/app/modules/web/Controllers/Helpers/Grid/ClientGrid.php index 4b3b784b..3a409314 100644 --- a/app/modules/web/Controllers/Helpers/Grid/ClientGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/ClientGrid.php @@ -24,7 +24,6 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; -use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; use SP\Domain\Core\Exceptions\SPException; use SP\Html\DataGrid\Action\DataGridAction; @@ -82,7 +81,7 @@ final class ClientGrid extends GridBase } /** - * @throws SPException + * @return DataGridInterface */ protected function getGridLayout(): DataGridInterface { @@ -110,7 +109,7 @@ final class ClientGrid extends GridBase } /** - * @throws SPException + * @return DataGridData */ protected function getData(): DataGridData { @@ -122,9 +121,7 @@ final class ClientGrid extends GridBase $gridData->addDataRowSource( 'isGlobal', false, - function ($value) { - return $value ? __('YES') : __('NO'); - } + fn($value) => $value ? __('YES') : __('NO') ); $gridData->setData($this->queryResult); @@ -142,7 +139,7 @@ final class ClientGrid extends GridBase $gridActionSearch->setOnSubmitFunction('appMgmt/search'); $gridActionSearch->addData( 'action-route', - Acl::getActionRoute(AclActionsInterface::CLIENT_SEARCH) + $this->acl->getRouteFor(AclActionsInterface::CLIENT_SEARCH) ); return $gridActionSearch; @@ -163,7 +160,7 @@ final class ClientGrid extends GridBase $gridAction->setOnClickFunction('appMgmt/show'); $gridAction->addData( 'action-route', - Acl::getActionRoute(AclActionsInterface::CLIENT_CREATE) + $this->acl->getRouteFor(AclActionsInterface::CLIENT_CREATE) ); return $gridAction; @@ -180,7 +177,7 @@ final class ClientGrid extends GridBase $gridAction->setOnClickFunction('appMgmt/show'); $gridAction->addData( 'action-route', - Acl::getActionRoute(AclActionsInterface::CLIENT_EDIT) + $this->acl->getRouteFor(AclActionsInterface::CLIENT_EDIT) ); return $gridAction; @@ -197,7 +194,7 @@ final class ClientGrid extends GridBase $gridAction->setOnClickFunction('appMgmt/delete'); $gridAction->addData( 'action-route', - Acl::getActionRoute(AclActionsInterface::CLIENT_DELETE) + $this->acl->getRouteFor(AclActionsInterface::CLIENT_DELETE) ); return $gridAction; diff --git a/app/modules/web/Forms/ClientForm.php b/app/modules/web/Forms/ClientForm.php index 21f9124a..d95604b6 100644 --- a/app/modules/web/Forms/ClientForm.php +++ b/app/modules/web/Forms/ClientForm.php @@ -28,6 +28,8 @@ use SP\Domain\Client\Models\Client; use SP\Domain\Core\Acl\AclActionsInterface; use SP\Domain\Core\Exceptions\ValidationException; +use function SP\__u; + /** * Class ClientForm * @@ -43,7 +45,7 @@ final class ClientForm extends FormBase implements FormInterface * @param int $action * @param int|null $id * - * @return ClientForm|FormInterface + * @return FormInterface * @throws ValidationException */ public function validateFor(int $action, ?int $id = null): FormInterface diff --git a/lib/SP/Infrastructure/Client/Repositories/Client.php b/lib/SP/Infrastructure/Client/Repositories/Client.php index 40d97b7b..a1870edd 100644 --- a/lib/SP/Infrastructure/Client/Repositories/Client.php +++ b/lib/SP/Infrastructure/Client/Repositories/Client.php @@ -122,7 +122,6 @@ final class Client extends BaseRepository implements ClientRepository ->table(ClientModel::TABLE) ->cols($client->toArray(null, ['id', 'hash'])) ->where('id = :id') - ->limit(1) ->bindValues( [ 'id' => $client->getId(), diff --git a/tests/SP/Modules/Web/Controllers/Client/ClientTest.php b/tests/SP/Modules/Web/Controllers/Client/ClientTest.php new file mode 100644 index 00000000..c405b634 --- /dev/null +++ b/tests/SP/Modules/Web/Controllers/Client/ClientTest.php @@ -0,0 +1,303 @@ +. + */ + +declare(strict_types=1); + +namespace SP\Modules\Web\Controllers\Client; + +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Attributes\Test; +use PHPUnit\Framework\MockObject\Exception; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; +use SP\Domain\Client\Models\Client; +use SP\Domain\Core\Exceptions\InvalidClassException; +use SP\Infrastructure\Database\QueryResult; +use SP\Infrastructure\File\FileException; +use SP\Tests\BodyChecker; +use SP\Tests\Generators\ClientGenerator; +use SP\Tests\IntegrationTestCase; +use Symfony\Component\DomCrawler\Crawler; + +/** + * Class ClientTest + */ +#[Group('integration')] +class ClientTest extends IntegrationTestCase +{ + private array $definitions; + + /** + * @throws ContainerExceptionInterface + * @throws Exception + * @throws NotFoundExceptionInterface + */ + #[Test] + #[BodyChecker('outputCheckerCreate')] + public function create() + { + $container = $this->buildContainer( + $this->definitions, + $this->buildRequest('get', 'index.php', ['r' => 'client/create']) + ); + + $this->runApp($container); + } + + /** + * @throws ContainerExceptionInterface + * @throws Exception + * @throws NotFoundExceptionInterface + */ + #[Test] + public function deleteMultiple() + { + $container = $this->buildContainer( + $this->definitions, + $this->buildRequest('get', 'index.php', ['r' => 'client/delete', 'items' => [100, 200, 300]]) + ); + + $this->runApp($container); + + $this->expectOutputString('{"status":"OK","description":"Clients deleted","data":null}'); + } + + /** + * @throws ContainerExceptionInterface + * @throws Exception + * @throws NotFoundExceptionInterface + */ + #[Test] + public function deleteSingle() + { + $container = $this->buildContainer( + $this->definitions, + $this->buildRequest('get', 'index.php', ['r' => 'client/delete/100']) + ); + + $this->runApp($container); + + $this->expectOutputString('{"status":"OK","description":"Client deleted","data":null}'); + } + + /** + * @throws ContainerExceptionInterface + * @throws Exception + * @throws NotFoundExceptionInterface + */ + #[Test] + #[BodyChecker('outputCheckerEdit')] + public function edit() + { + $this->addDatabaseMapperResolver( + Client::class, + new QueryResult([ClientGenerator::factory()->buildClient()]) + ); + + $container = $this->buildContainer( + $this->definitions, + $this->buildRequest('get', 'index.php', ['r' => 'client/edit/100']) + ); + + $this->runApp($container); + } + + /** + * @throws ContainerExceptionInterface + * @throws Exception + * @throws NotFoundExceptionInterface + */ + #[Test] + public function saveCreate() + { + $data = [ + 'name' => self::$faker->name(), + 'description' => self::$faker->text(), + 'isglobal' => self::$faker->boolean(), + ]; + + $container = $this->buildContainer( + $this->definitions, + $this->buildRequest('post', 'index.php', ['r' => 'client/saveCreate'], $data) + ); + + $this->runApp($container); + + $this->expectOutputString('{"status":"OK","description":"Client added","data":null}'); + } + + /** + * @throws ContainerExceptionInterface + * @throws Exception + * @throws NotFoundExceptionInterface + */ + #[Test] + public function saveEdit() + { + $data = [ + 'name' => self::$faker->name(), + 'description' => self::$faker->text(), + 'isglobal' => self::$faker->boolean(), + ]; + + $container = $this->buildContainer( + $this->definitions, + $this->buildRequest('post', 'index.php', ['r' => 'client/saveEdit/100'], $data) + ); + + $this->runApp($container); + + $this->expectOutputString('{"status":"OK","description":"Client updated","data":null}'); + } + + /** + * @throws ContainerExceptionInterface + * @throws Exception + * @throws NotFoundExceptionInterface + */ + #[Test] + #[BodyChecker('outputCheckerSearch')] + public function search() + { + $clientGenerator = ClientGenerator::factory(); + + $this->addDatabaseMapperResolver( + Client::class, + QueryResult::withTotalNumRows( + [ + $clientGenerator->buildClient(), + $clientGenerator->buildClient() + ], + 2 + ) + ); + + $container = $this->buildContainer( + $this->definitions, + $this->buildRequest('get', 'index.php', ['r' => 'client/search', 'search' => 'test']) + ); + + $this->runApp($container); + } + + /** + * @throws ContainerExceptionInterface + * @throws Exception + * @throws NotFoundExceptionInterface + */ + #[Test] + #[BodyChecker('outputCheckerView')] + public function view() + { + $this->addDatabaseMapperResolver( + Client::class, + new QueryResult([ClientGenerator::factory()->buildClient()]) + ); + + $container = $this->buildContainer( + $this->definitions, + $this->buildRequest('get', 'index.php', ['r' => 'client/view/100']) + ); + + $this->runApp($container); + } + + /** + * @throws FileException + * @throws InvalidClassException + */ + protected function setUp(): void + { + parent::setUp(); + + $this->definitions = $this->getModuleDefinitions(); + } + + /** + * @param string $output + * @return void + */ + private function outputCheckerCreate(string $output): void + { + $json = json_decode($output); + + $crawler = new Crawler($json->data->html); + $filter = $crawler->filterXPath( + '//div[@id="box-popup"]//form[@name="frmClients"]//select|//input' + )->extract(['_name']); + + self::assertCount(4, $filter); + } + + /** + * @param string $output + * @return void + */ + private function outputCheckerEdit(string $output): void + { + $json = json_decode($output); + + $crawler = new Crawler($json->data->html); + $filter = $crawler->filterXPath( + '//div[@id="box-popup"]//form[@name="frmClients"]//select|//input' + )->extract(['_name']); + + self::assertCount(4, $filter); + self::assertEquals('OK', $json->status); + } + + /** + * @param string $output + * @return void + */ + private function outputCheckerSearch(string $output): void + { + $json = json_decode($output); + + $crawler = new Crawler($json->data->html); + $filter = $crawler->filterXPath( + '//table/tbody[@id="data-rows-tblClients"]//tr[string-length(@data-item-id) > 0]' + )->extract(['data-item-id']); + + self::assertCount(2, $filter); + self::assertEquals('OK', $json->status); + } + + /** + * @param string $output + * @return void + */ + private function outputCheckerView(string $output): void + { + $json = json_decode($output); + + $crawler = new Crawler($json->data->html); + $filter = $crawler->filterXPath( + '//div[@id="box-popup"]//form[@name="frmClients"]//select|//input' + )->extract(['_name']); + + self::assertCount(4, $filter); + self::assertEquals('OK', $json->status); + } +}