From df9f31ee243e5ad84d666c0cfd58df2855d1e781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D?= Date: Mon, 11 Mar 2024 08:01:20 +0100 Subject: [PATCH] chore(tests): UT for PluginManager service MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rubén D --- .../Plugin/Ports/PluginManagerService.php | 6 +- .../Plugin/Ports/PluginOperationInterface.php | 12 +- .../Domain/Plugin/Services/PluginManager.php | 64 +-- .../Plugin/Services/PluginOperation.php | 18 +- .../Services/NotificationTest.php | 3 + .../Plugin/Services/PluginManagerTest.php | 513 ++++++++++++++++++ 6 files changed, 560 insertions(+), 56 deletions(-) create mode 100644 tests/SPT/Domain/Plugin/Services/PluginManagerTest.php diff --git a/lib/SP/Domain/Plugin/Ports/PluginManagerService.php b/lib/SP/Domain/Plugin/Ports/PluginManagerService.php index 36084126..ff739700 100644 --- a/lib/SP/Domain/Plugin/Ports/PluginManagerService.php +++ b/lib/SP/Domain/Plugin/Ports/PluginManagerService.php @@ -44,7 +44,7 @@ interface PluginManagerService * @throws ConstraintException * @throws QueryException */ - public function create(Plugin $itemData): int; + public function create(Plugin $plugin): int; /** * Updates an item @@ -52,7 +52,7 @@ interface PluginManagerService * @throws ConstraintException * @throws QueryException */ - public function update(Plugin $itemData): int; + public function update(Plugin $plugin): int; /** * Returns the item for given id @@ -164,7 +164,7 @@ interface PluginManagerService * @throws ConstraintException * @throws QueryException */ - public function resetById(int $id): bool; + public function resetById(int $id): void; /** * Devolver los plugins activados diff --git a/lib/SP/Domain/Plugin/Ports/PluginOperationInterface.php b/lib/SP/Domain/Plugin/Ports/PluginOperationInterface.php index 9a757eb1..f25b8409 100644 --- a/lib/SP/Domain/Plugin/Ports/PluginOperationInterface.php +++ b/lib/SP/Domain/Plugin/Ports/PluginOperationInterface.php @@ -4,7 +4,7 @@ * * @author nuxsmin * @link https://syspass.org - * @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org + * @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. * @@ -47,7 +47,7 @@ interface PluginOperationInterface * @throws QueryException * @throws ServiceException */ - public function create(int $itemId, mixed $data): int; + public function create(int $itemId, object $data): int; /** * @param int $itemId @@ -60,7 +60,7 @@ interface PluginOperationInterface * @throws QueryException * @throws ServiceException */ - public function update(int $itemId, mixed $data): int; + public function update(int $itemId, object $data): int; /** * @throws ConstraintException @@ -73,9 +73,9 @@ interface PluginOperationInterface * @template T * * @param int $itemId - * @param class-string|null $class + * @param class-string $class * - * @return T + * @return T|null * * @throws ConstraintException * @throws CryptoException @@ -83,5 +83,5 @@ interface PluginOperationInterface * @throws QueryException * @throws ServiceException */ - public function get(int $itemId, ?string $class = null): mixed; + public function get(int $itemId, string $class): ?object; } diff --git a/lib/SP/Domain/Plugin/Services/PluginManager.php b/lib/SP/Domain/Plugin/Services/PluginManager.php index d0b1e239..58350b2f 100644 --- a/lib/SP/Domain/Plugin/Services/PluginManager.php +++ b/lib/SP/Domain/Plugin/Services/PluginManager.php @@ -25,7 +25,6 @@ namespace SP\Domain\Plugin\Services; use SP\Core\Application; -use SP\DataModel\Item; use SP\DataModel\ItemSearchData; use SP\Domain\Common\Services\Service; use SP\Domain\Common\Services\ServiceException; @@ -54,14 +53,14 @@ final class PluginManager extends Service implements PluginManagerService } /** - * Creates an item + * Creates an item and returns the id * * @throws ConstraintException * @throws QueryException */ - public function create(PluginModel $itemData): int + public function create(PluginModel $plugin): int { - return $this->pluginRepository->create($itemData)->getLastId(); + return $this->pluginRepository->create($plugin)->getLastId(); } /** @@ -70,9 +69,9 @@ final class PluginManager extends Service implements PluginManagerService * @throws ConstraintException * @throws QueryException */ - public function update(PluginModel $itemData): int + public function update(PluginModel $plugin): int { - return $this->pluginRepository->update($itemData); + return $this->pluginRepository->update($plugin); } /** @@ -80,33 +79,27 @@ final class PluginManager extends Service implements PluginManagerService * * @param int $id * @return PluginModel - * @throws ConstraintException * @throws NoSuchItemException - * @throws QueryException - * @throws SPException */ public function getById(int $id): PluginModel { $result = $this->pluginRepository->getById($id); if ($result->getNumRows() === 0) { - throw new NoSuchItemException(__u('Plugin not found'), SPException::INFO); + throw NoSuchItemException::info(__u('Plugin not found')); } - return $result->getData(); + return $result->getData(PluginModel::class); } /** * Returns all the items * * @return array - * @throws ConstraintException - * @throws QueryException - * @throws SPException */ public function getAll(): array { - return $this->pluginRepository->getAll()->getDataAsArray(); + return $this->pluginRepository->getAll()->getDataAsArray(PluginModel::class); } /** @@ -115,13 +108,10 @@ final class PluginManager extends Service implements PluginManagerService * @param int[] $ids * * @return array - * @throws ConstraintException - * @throws QueryException - * @throws SPException */ public function getByIdBatch(array $ids): array { - return $this->pluginRepository->getByIdBatch($ids)->getDataAsArray(); + return $this->pluginRepository->getByIdBatch($ids)->getDataAsArray(PluginModel::class); } /** @@ -136,8 +126,8 @@ final class PluginManager extends Service implements PluginManagerService */ public function deleteByIdBatch(array $ids): void { - if ($this->pluginRepository->deleteByIdBatch($ids) !== count($ids)) { - throw new ServiceException(__u('Error while deleting the plugins')); + if ($this->pluginRepository->deleteByIdBatch($ids)->getAffectedNumRows() !== count($ids)) { + throw ServiceException::error(__u('Error while deleting the plugins')); } } @@ -150,16 +140,16 @@ final class PluginManager extends Service implements PluginManagerService */ public function delete(int $id): void { - if ($this->pluginRepository->delete($id) === 0) { - throw new NoSuchItemException(__u('Plugin not found'), SPException::INFO); + if ($this->pluginRepository->delete($id)->getAffectedNumRows() === 0) { + throw NoSuchItemException::info(__u('Plugin not found')); } } /** * Searches for items by a given filter * - * @throws ConstraintException - * @throws QueryException + * @param ItemSearchData $itemSearchData + * @return QueryResult */ public function search(ItemSearchData $itemSearchData): QueryResult { @@ -181,10 +171,10 @@ final class PluginManager extends Service implements PluginManagerService $result = $this->pluginRepository->getByName($name); if ($result->getNumRows() === 0) { - throw new NoSuchItemException(__u('Plugin not found'), SPException::INFO); + throw NoSuchItemException::info(__u('Plugin not found')); } - return $result->getData(); + return $result->getData(PluginModel::class); } /** @@ -197,7 +187,7 @@ final class PluginManager extends Service implements PluginManagerService public function toggleEnabled(int $id, bool $enabled): void { if ($this->pluginRepository->toggleEnabled($id, $enabled) === 0) { - throw new NoSuchItemException(__u('Plugin not found'), SPException::INFO); + throw NoSuchItemException::info(__u('Plugin not found')); } } @@ -211,7 +201,7 @@ final class PluginManager extends Service implements PluginManagerService public function toggleEnabledByName(string $name, bool $enabled): void { if ($this->pluginRepository->toggleEnabledByName($name, $enabled) === 0) { - throw new NoSuchItemException(__u('Plugin not found'), SPException::INFO); + throw NoSuchItemException::info(__u('Plugin not found')); } } @@ -225,7 +215,7 @@ final class PluginManager extends Service implements PluginManagerService public function toggleAvailable(int $id, bool $available): void { if ($this->pluginRepository->toggleAvailable($id, $available) === 0) { - throw new NoSuchItemException(__u('Plugin not found'), SPException::INFO); + throw NoSuchItemException::info(__u('Plugin not found')); } } @@ -239,7 +229,7 @@ final class PluginManager extends Service implements PluginManagerService public function toggleAvailableByName(string $name, bool $available): void { if ($this->pluginRepository->toggleAvailableByName($name, $available) === 0) { - throw new NoSuchItemException(__u('Plugin not found'), SPException::INFO); + throw NoSuchItemException::info(__u('Plugin not found')); } } @@ -250,25 +240,23 @@ final class PluginManager extends Service implements PluginManagerService * @throws ConstraintException * @throws QueryException */ - public function resetById(int $id): bool + public function resetById(int $id): void { - if (($count = $this->pluginRepository->resetById($id)) === 0) { - throw new NoSuchItemException(__u('Plugin not found'), SPException::INFO); + if ($this->pluginRepository->resetById($id) === 0) { + throw NoSuchItemException::info(__u('Plugin not found')); } - - return $count; } /** * Devolver los plugins activados * - * @return Item[] + * @return array * @throws ConstraintException * @throws QueryException * @throws SPException */ public function getEnabled(): array { - return $this->pluginRepository->getEnabled()->getDataAsArray(); + return $this->pluginRepository->getEnabled()->getDataAsArray(PluginModel::class); } } diff --git a/lib/SP/Domain/Plugin/Services/PluginOperation.php b/lib/SP/Domain/Plugin/Services/PluginOperation.php index 794608e3..ec95af07 100644 --- a/lib/SP/Domain/Plugin/Services/PluginOperation.php +++ b/lib/SP/Domain/Plugin/Services/PluginOperation.php @@ -56,11 +56,11 @@ final class PluginOperation implements PluginOperationInterface * @throws QueryException * @throws ServiceException */ - public function create(int $itemId, mixed $data): int + public function create(int $itemId, object $data): int { - $itemData = new PluginDataModel(['name' => $this->pluginName, 'itemId' => $itemId, 'data' => serialize($data)]); + $itemData = new PluginDataModel(['name' => $this->pluginName, 'itemId' => $itemId]); - return $this->pluginDataService->create($itemData)->getLastId(); + return $this->pluginDataService->create($itemData->dehydrate($data))->getLastId(); } /** @@ -74,11 +74,11 @@ final class PluginOperation implements PluginOperationInterface * @throws QueryException * @throws ServiceException */ - public function update(int $itemId, mixed $data): int + public function update(int $itemId, object $data): int { - $itemData = new PluginDataModel(['name' => $this->pluginName, 'itemId' => $itemId, 'data' => serialize($data)]); + $itemData = new PluginDataModel(['name' => $this->pluginName, 'itemId' => $itemId]); - return $this->pluginDataService->update($itemData); + return $this->pluginDataService->update($itemData->dehydrate($data)); } /** @@ -95,16 +95,16 @@ final class PluginOperation implements PluginOperationInterface * @template T * * @param int $itemId - * @param class-string|null $class + * @param class-string $class * - * @return mixed|null + * @return T|null * @throws ConstraintException * @throws CryptoException * @throws NoSuchPropertyException * @throws QueryException * @throws ServiceException */ - public function get(int $itemId, ?string $class = null): mixed + public function get(int $itemId, string $class): ?object { try { return $this->pluginDataService diff --git a/tests/SPT/Domain/Notification/Services/NotificationTest.php b/tests/SPT/Domain/Notification/Services/NotificationTest.php index 0306c866..8e0bf6c8 100644 --- a/tests/SPT/Domain/Notification/Services/NotificationTest.php +++ b/tests/SPT/Domain/Notification/Services/NotificationTest.php @@ -238,6 +238,9 @@ class NotificationTest extends UnitaryTestCase $this->assertEquals([1], $out); } + /** + * @throws Exception + */ public function testGetByIdBatch() { $queryResult = $this->createMock(QueryResult::class); diff --git a/tests/SPT/Domain/Plugin/Services/PluginManagerTest.php b/tests/SPT/Domain/Plugin/Services/PluginManagerTest.php new file mode 100644 index 00000000..8b6b6296 --- /dev/null +++ b/tests/SPT/Domain/Plugin/Services/PluginManagerTest.php @@ -0,0 +1,513 @@ +. + */ + +namespace SPT\Domain\Plugin\Services; + +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\MockObject\Exception; +use PHPUnit\Framework\MockObject\MockObject; +use SP\Core\Context\ContextException; +use SP\DataModel\ItemSearchData; +use SP\Domain\Common\Services\ServiceException; +use SP\Domain\Core\Exceptions\ConstraintException; +use SP\Domain\Core\Exceptions\QueryException; +use SP\Domain\Core\Exceptions\SPException; +use SP\Domain\Plugin\Models\Plugin as PluginModel; +use SP\Domain\Plugin\Ports\PluginRepository; +use SP\Domain\Plugin\Services\PluginManager; +use SP\Infrastructure\Common\Repositories\NoSuchItemException; +use SP\Infrastructure\Database\QueryResult; +use SPT\Generators\PluginGenerator; +use SPT\UnitaryTestCase; + +/** + * Class PluginManagerTest + */ +#[Group('unitary')] +class PluginManagerTest extends UnitaryTestCase +{ + + private PluginRepository|MockObject $pluginRepository; + private PluginManager $pluginManager; + + /** + * @throws NoSuchItemException + * @throws ContextException + * @throws ConstraintException + * @throws SPException + * @throws QueryException + */ + public function testGetByName() + { + $plugin = PluginGenerator::factory()->buildPlugin(); + + $queryResult = new QueryResult([$plugin]); + + $this->pluginRepository + ->expects($this->once()) + ->method('getByName') + ->with('test_plugin') + ->willReturn($queryResult); + + $out = $this->pluginManager->getByName('test_plugin'); + + $this->assertEquals($plugin, $out); + } + + /** + * @throws NoSuchItemException + * @throws ContextException + * @throws ConstraintException + * @throws SPException + * @throws QueryException + */ + public function testGetByNameWithNotFound() + { + $queryResult = new QueryResult([]); + + $this->pluginRepository + ->expects($this->once()) + ->method('getByName') + ->with('test_plugin') + ->willReturn($queryResult); + + $this->expectException(NoSuchItemException::class); + $this->expectExceptionMessage('Plugin not found'); + + $this->pluginManager->getByName('test_plugin'); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws QueryException + */ + public function testToggleAvailable() + { + $this->pluginRepository + ->expects($this->once()) + ->method('toggleAvailable') + ->with(100, true) + ->willReturn(1); + + $this->pluginManager->toggleAvailable(100, true); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws QueryException + */ + public function testToggleAvailableWithNotFound() + { + $this->pluginRepository + ->expects($this->once()) + ->method('toggleAvailable') + ->with(100, true) + ->willReturn(0); + + $this->expectException(NoSuchItemException::class); + $this->expectExceptionMessage('Plugin not found'); + + $this->pluginManager->toggleAvailable(100, true); + } + + /** + * @throws ConstraintException + * @throws SPException + * @throws QueryException + */ + public function testDelete() + { + $queryResult = new QueryResult(); + $this->pluginRepository + ->expects($this->once()) + ->method('delete') + ->with(100) + ->willReturn($queryResult->setAffectedNumRows(1)); + + $this->pluginManager->delete(100); + } + + /** + * @throws ConstraintException + * @throws SPException + * @throws QueryException + */ + public function testDeleteWithNotFound() + { + $queryResult = new QueryResult(); + $this->pluginRepository + ->expects($this->once()) + ->method('delete') + ->with(100) + ->willReturn($queryResult->setAffectedNumRows(0)); + + $this->expectException(NoSuchItemException::class); + $this->expectExceptionMessage('Plugin not found'); + + $this->pluginManager->delete(100); + } + + public function testGetAll() + { + $plugin = PluginGenerator::factory()->buildPlugin(); + $queryResult = new QueryResult([$plugin]); + + $this->pluginRepository + ->expects($this->once()) + ->method('getAll') + ->willReturn($queryResult); + + $out = $this->pluginManager->getAll(); + + $this->assertEquals($plugin, $out[0]); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws QueryException + */ + public function testToggleAvailableByName() + { + $this->pluginRepository + ->expects($this->once()) + ->method('toggleAvailableByName') + ->with('test_plugin', true) + ->willReturn(1); + + $this->pluginManager->toggleAvailableByName('test_plugin', true); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws QueryException + */ + public function testToggleAvailableByNameWithNotFound() + { + $this->pluginRepository + ->expects($this->once()) + ->method('toggleAvailableByName') + ->with('test_plugin', true) + ->willReturn(0); + + $this->expectException(NoSuchItemException::class); + $this->expectExceptionMessage('Plugin not found'); + + $this->pluginManager->toggleAvailableByName('test_plugin', true); + } + + /** + * @throws Exception + */ + public function testGetByIdBatch() + { + $queryResult = $this->createMock(QueryResult::class); + $queryResult->expects($this->once()) + ->method('getDataAsArray') + ->with(PluginModel::class) + ->willReturn([1]); + + $this->pluginRepository + ->expects($this->once()) + ->method('getByIdBatch') + ->with([100, 200, 300]) + ->willReturn($queryResult); + + $out = $this->pluginManager->getByIdBatch([100, 200, 300]); + + $this->assertEquals([1], $out); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws QueryException + */ + public function testToggleEnabledByName() + { + $this->pluginRepository + ->expects($this->once()) + ->method('toggleEnabledByName') + ->with('test_plugin', true) + ->willReturn(1); + + $this->pluginManager->toggleEnabledByName('test_plugin', true); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws QueryException + */ + public function testToggleEnabledByNameWithNotFound() + { + $this->pluginRepository + ->expects($this->once()) + ->method('toggleEnabledByName') + ->with('test_plugin', true) + ->willReturn(0); + + $this->expectException(NoSuchItemException::class); + $this->expectExceptionMessage('Plugin not found'); + + $this->pluginManager->toggleEnabledByName('test_plugin', true); + } + + /** + * @throws ConstraintException + * @throws Exception + * @throws QueryException + * @throws SPException + */ + public function testGetEnabled() + { + $queryResult = $this->createMock(QueryResult::class); + $queryResult->expects($this->once()) + ->method('getDataAsArray') + ->with(PluginModel::class) + ->willReturn([1]); + + $this->pluginRepository + ->expects($this->once()) + ->method('getEnabled') + ->willReturn($queryResult); + + $out = $this->pluginManager->getEnabled(); + + $this->assertEquals([1], $out); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws QueryException + */ + public function testToggleEnabled() + { + $this->pluginRepository + ->expects($this->once()) + ->method('toggleEnabled') + ->with(100, true) + ->willReturn(1); + + $this->pluginManager->toggleEnabled(100, true); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws QueryException + */ + public function testToggleEnabledWithNotFound() + { + $this->pluginRepository + ->expects($this->once()) + ->method('toggleEnabled') + ->with(100, true) + ->willReturn(0); + + $this->expectException(NoSuchItemException::class); + $this->expectExceptionMessage('Plugin not found'); + + $this->pluginManager->toggleEnabled(100, true); + } + + + /** + * @throws ConstraintException + * @throws QueryException + * @throws SPException + */ + public function testDeleteByIdBatch() + { + $queryResult = new QueryResult([]); + + $this->pluginRepository + ->expects($this->once()) + ->method('deleteByIdBatch') + ->with([100, 200, 300]) + ->willReturn($queryResult->setAffectedNumRows(3)); + + $this->pluginManager->deleteByIdBatch([100, 200, 300]); + } + + /** + * @throws ConstraintException + * @throws QueryException + * @throws SPException + */ + public function testDeleteByIdBatchWithException() + { + $queryResult = new QueryResult([]); + + $this->pluginRepository + ->expects($this->once()) + ->method('deleteByIdBatch') + ->with([100, 200, 300]) + ->willReturn($queryResult->setAffectedNumRows(1)); + + $this->expectException(ServiceException::class); + $this->expectExceptionMessage('Error while deleting the plugins'); + + $this->pluginManager->deleteByIdBatch([100, 200, 300]); + } + + + public function testSearch() + { + $itemSearchData = new ItemSearchData(); + + $queryResult = new QueryResult([1]); + + $this->pluginRepository + ->expects($this->once()) + ->method('search') + ->with($itemSearchData) + ->willReturn($queryResult); + + $out = $this->pluginManager->search($itemSearchData); + + $this->assertEquals($queryResult, $out); + } + + /** + * @throws ConstraintException + * @throws QueryException + */ + public function testUpdate() + { + $plugin = PluginGenerator::factory()->buildPlugin(); + + $this->pluginRepository + ->expects($this->once()) + ->method('update') + ->with($plugin) + ->willReturn(100); + + $out = $this->pluginManager->update($plugin); + + $this->assertEquals(100, $out); + } + + /** + * @throws ConstraintException + * @throws QueryException + */ + public function testCreate() + { + $plugin = PluginGenerator::factory()->buildPlugin(); + + $queryResult = new QueryResult(); + + $this->pluginRepository + ->expects($this->once()) + ->method('create') + ->with($plugin) + ->willReturn($queryResult->setLastId(100)); + + $out = $this->pluginManager->create($plugin); + + $this->assertEquals(100, $out); + } + + /** + * @throws NoSuchItemException + * @throws Exception + */ + public function testGetById() + { + $queryResult = $this->createMock(QueryResult::class); + $queryResult->expects($this->once()) + ->method('getNumRows') + ->willReturn(1); + + $plugin = PluginGenerator::factory()->buildPlugin(); + + $queryResult->expects($this->once()) + ->method('getData') + ->with(PluginModel::class) + ->willReturn($plugin); + + $this->pluginRepository + ->expects($this->once()) + ->method('getById') + ->with(100) + ->willReturn($queryResult); + + $out = $this->pluginManager->getById(100); + + $this->assertEquals($plugin, $out); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws QueryException + */ + public function testResetById() + { + $this->pluginRepository + ->expects($this->once()) + ->method('resetById') + ->with(100) + ->willReturn(1); + + $this->pluginManager->resetById(100); + } + + /** + * @throws ConstraintException + * @throws NoSuchItemException + * @throws QueryException + */ + public function testResetByIdWithNotFound() + { + $this->pluginRepository + ->expects($this->once()) + ->method('resetById') + ->with(100) + ->willReturn(0); + + $this->expectException(NoSuchItemException::class); + $this->expectExceptionMessage('Plugin not found'); + + $this->pluginManager->resetById(100); + } + + + protected function setUp(): void + { + parent::setUp(); + + $this->pluginRepository = $this->createMock(PluginRepository::class); + + $this->pluginManager = new PluginManager( + $this->application, + $this->pluginRepository + ); + } +}