From 8fb81f982317dfd8965d5809f5d501b9c64598ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D?= Date: Sun, 10 Mar 2024 16:08:38 +0100 Subject: [PATCH] chore(tests): UT for PluginData repository MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rubén D --- .../Plugin/Ports/PluginDataRepository.php | 43 ++- lib/SP/Domain/Plugin/Services/PluginData.php | 2 +- .../Plugin/Repositories/PluginData.php | 244 ++++++-------- tests/SPT/Generators/PluginDataGenerator.php | 49 +++ .../Plugin/Repositories/PluginDataTest.php | 308 ++++++++++++++++++ 5 files changed, 485 insertions(+), 161 deletions(-) create mode 100644 tests/SPT/Generators/PluginDataGenerator.php create mode 100644 tests/SPT/Infrastructure/Plugin/Repositories/PluginDataTest.php diff --git a/lib/SP/Domain/Plugin/Ports/PluginDataRepository.php b/lib/SP/Domain/Plugin/Ports/PluginDataRepository.php index 56b690e8..1af22a31 100644 --- a/lib/SP/Domain/Plugin/Ports/PluginDataRepository.php +++ b/lib/SP/Domain/Plugin/Ports/PluginDataRepository.php @@ -39,35 +39,35 @@ interface PluginDataRepository /** * Creates an item * - * @param PluginDataModel $itemData + * @param PluginDataModel $pluginData * * @return QueryResult * @throws ConstraintException * @throws QueryException */ - public function create(PluginDataModel $itemData): QueryResult; + public function create(PluginDataModel $pluginData): QueryResult; /** * Updates an item * - * @param PluginDataModel $itemData + * @param PluginDataModel $pluginData * * @return int * @throws ConstraintException * @throws QueryException */ - public function update(PluginDataModel $itemData): int; + public function update(PluginDataModel $pluginData): int; /** * Deletes an item * - * @param string $id + * @param string $name * - * @return int + * @return QueryResult * @throws ConstraintException * @throws QueryException */ - public function delete(string $id): int; + public function delete(string $name): QueryResult; /** * Deletes an item @@ -75,22 +75,19 @@ interface PluginDataRepository * @param string $name * @param int $itemId * - * @return int + * @return QueryResult * @throws ConstraintException * @throws QueryException */ - public function deleteByItemId(string $name, int $itemId): int; + public function deleteByItemId(string $name, int $itemId): QueryResult; /** - * Returns the item for given id - * - * @param string $id + * Returns the item for given name * + * @param string $name * @return QueryResult - * @throws ConstraintException - * @throws QueryException */ - public function getById(string $id): QueryResult; + public function getByName(string $name): QueryResult; /** * Returns all the items @@ -102,26 +99,24 @@ interface PluginDataRepository public function getAll(): QueryResult; /** - * Returns all the items for given ids + * Returns all the items for given names * - * @param string[] $ids + * @param string[] $names * * @return QueryResult - * @throws ConstraintException - * @throws QueryException */ - public function getByIdBatch(array $ids): QueryResult; + public function getByNameBatch(array $names): QueryResult; /** - * Deletes all the items for given ids + * Deletes all the items for given names * - * @param string[] $ids + * @param string[] $names * - * @return int + * @return QueryResult * @throws ConstraintException * @throws QueryException */ - public function deleteByIdBatch(array $ids): int; + public function deleteByNameBatch(array $names): QueryResult; /** * Devuelve los datos de un plugin por su nombre diff --git a/lib/SP/Domain/Plugin/Services/PluginData.php b/lib/SP/Domain/Plugin/Services/PluginData.php index 6e8f56d3..c9df8929 100644 --- a/lib/SP/Domain/Plugin/Services/PluginData.php +++ b/lib/SP/Domain/Plugin/Services/PluginData.php @@ -121,7 +121,7 @@ final class PluginData extends Service implements PluginDataService */ public function getById(string $id): array { - $result = $this->pluginDataRepository->getById($id); + $result = $this->pluginDataRepository->getByName($id); if ($result->getNumRows() === 0) { throw new NoSuchItemException(__u('Plugin\'s data not found'), SPException::INFO); diff --git a/lib/SP/Infrastructure/Plugin/Repositories/PluginData.php b/lib/SP/Infrastructure/Plugin/Repositories/PluginData.php index 8e91404e..c6ad1c67 100644 --- a/lib/SP/Infrastructure/Plugin/Repositories/PluginData.php +++ b/lib/SP/Infrastructure/Plugin/Repositories/PluginData.php @@ -33,6 +33,8 @@ use SP\Infrastructure\Common\Repositories\RepositoryItemTrait; use SP\Infrastructure\Database\QueryData; use SP\Infrastructure\Database\QueryResult; +use function SP\__u; + /** * Class PluginData * @@ -42,29 +44,25 @@ final class PluginData extends BaseRepository implements PluginDataRepository { use RepositoryItemTrait; + public const TABLE = 'PluginData'; + /** * Creates an item * - * @param PluginDataModel $itemData + * @param PluginDataModel $pluginData * * @return QueryResult * @throws ConstraintException * @throws QueryException */ - public function create(PluginDataModel $itemData): QueryResult + public function create(PluginDataModel $pluginData): QueryResult { - $query = /** @lang SQL */ - 'INSERT INTO PluginData SET `name` = ?, itemId = ?, `data` = ?, `key` = ?'; + $query = $this->queryFactory + ->newInsert() + ->into(self::TABLE) + ->cols($pluginData->toArray(null, ['id'])); - $queryData = new QueryData(); - $queryData->setQuery($query); - $queryData->setParams([ - $itemData->getName(), - $itemData->getItemId(), - $itemData->getData(), - $itemData->getKey(), - ]); - $queryData->setOnErrorMessage(__u('Error while adding plugin\'s data')); + $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while adding plugin\'s data')); return $this->db->doQuery($queryData); } @@ -72,47 +70,25 @@ final class PluginData extends BaseRepository implements PluginDataRepository /** * Updates an item * - * @param PluginDataModel $itemData + * @param PluginDataModel $pluginData * * @return int * @throws ConstraintException * @throws QueryException */ - public function update(PluginDataModel $itemData): int + public function update(PluginDataModel $pluginData): int { - $query = /** @lang SQL */ - 'UPDATE PluginData - SET `data` = ?, `key` = ? - WHERE `name` = ? AND itemId = ? LIMIT 1'; + $query = $this->queryFactory + ->newUpdate() + ->table(self::TABLE) + ->cols($pluginData->toArray(null, ['name', 'itemId'])) + ->where( + 'name = :name AND itemId = :itemId', + ['name' => $pluginData->getName(), 'itemId' => $pluginData->getItemId()] + ) + ->limit(1); - $queryData = new QueryData(); - $queryData->setQuery($query); - $queryData->setParams([ - $itemData->getData(), - $itemData->getKey(), - $itemData->getName(), - $itemData->getItemId(), - ]); - $queryData->setOnErrorMessage(__u('Error while updating plugin\'s data')); - - return $this->db->doQuery($queryData)->getAffectedNumRows(); - } - - /** - * Deletes an item - * - * @param string $id - * - * @return int - * @throws ConstraintException - * @throws QueryException - */ - public function delete(string $id): int - { - $queryData = new QueryData(); - $queryData->setQuery('DELETE FROM PluginData WHERE `name` = ?'); - $queryData->addParam($id); - $queryData->setOnErrorMessage(__u('Error while deleting plugin\'s data')); + $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while updating plugin\'s data')); return $this->db->doQuery($queryData)->getAffectedNumRows(); } @@ -121,45 +97,64 @@ final class PluginData extends BaseRepository implements PluginDataRepository * Deletes an item * * @param string $name - * @param int $itemId * - * @return int + * @return QueryResult * @throws ConstraintException * @throws QueryException */ - public function deleteByItemId(string $name, int $itemId): int + public function delete(string $name): QueryResult { - $queryData = new QueryData(); - $queryData->setQuery('DELETE FROM PluginData WHERE `name` = ? AND itemId = ? LIMIT 1'); - $queryData->setParams([$name, $itemId]); - $queryData->setOnErrorMessage(__u('Error while deleting plugin\'s data')); + $query = $this->queryFactory + ->newDelete() + ->from(self::TABLE) + ->where('name = :name', ['name' => $name]) + ->limit(1); - return $this->db->doQuery($queryData)->getAffectedNumRows(); + $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while deleting plugin\'s data')); + + return $this->db->doQuery($queryData); } /** - * Returns the item for given id + * Deletes an item * - * @param string $id + * @param string $name + * @param int $itemId * - * @return QueryResult + * @return QueryResult * @throws ConstraintException * @throws QueryException */ - public function getById(string $id): QueryResult + public function deleteByItemId(string $name, int $itemId): QueryResult { - $query = /** @lang SQL */ - 'SELECT itemId, - `name`, - `data`, - `key` - FROM PluginData - WHERE `name` = ?'; + $query = $this->queryFactory + ->newDelete() + ->from(self::TABLE) + ->where('name = :name AND itemId = :itemId', ['name' => $name, 'itemId' => $itemId]) + ->limit(1); - $queryData = new QueryData(); - $queryData->setMapClassName(PluginDataModel::class); - $queryData->setQuery($query); - $queryData->addParam($id); + $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while deleting plugin\'s data')); + + return $this->db->doQuery($queryData); + } + + /** + * Returns the item for given name + * + * @param string $name + * @return QueryResult + */ + public function getByName(string $name): QueryResult + { + $query = $this->queryFactory + ->newSelect() + ->from(self::TABLE) + ->cols(PluginDataModel::getCols()) + ->where('name = :name') + ->bindValues(['name' => $name]) + ->limit(1); + + $queryData = QueryData::buildWithMapper($query, PluginDataModel::class); return $this->db->doSelect($queryData); } @@ -168,79 +163,62 @@ final class PluginData extends BaseRepository implements PluginDataRepository * Returns all the items * * @return QueryResult - * @throws ConstraintException - * @throws QueryException */ public function getAll(): QueryResult { - $query = /** @lang SQL */ - 'SELECT itemId, - `name`, - `data`, - `key` - FROM PluginData - ORDER BY `name`'; + $query = $this->queryFactory + ->newSelect() + ->from(self::TABLE) + ->cols(PluginDataModel::getCols()) + ->orderBy(['name']); - $queryData = new QueryData(); - $queryData->setMapClassName(PluginDataModel::class); - $queryData->setQuery($query); + return $this->db->doSelect(QueryData::buildWithMapper($query, PluginDataModel::class)); + } + + /** + * Returns all the items for given names + * + * @param string[] $names + * + * @return QueryResult + */ + public function getByNameBatch(array $names): QueryResult + { + $query = $this->queryFactory + ->newSelect() + ->from(self::TABLE) + ->cols(PluginDataModel::getCols()) + ->where('name IN (:name)', ['name' => $names]) + ->orderBy(['name']); + + $queryData = QueryData::buildWithMapper($query, PluginDataModel::class); return $this->db->doSelect($queryData); } /** - * Returns all the items for given ids + * Deletes all the items for given names * - * @param string[] $ids + * @param string[] $names * - * @return QueryResult + * @return QueryResult * @throws ConstraintException * @throws QueryException */ - public function getByIdBatch(array $ids): QueryResult + public function deleteByNameBatch(array $names): QueryResult { - if (count($ids) === 0) { + if (count($names) === 0) { return new QueryResult(); } - $query = /** @lang SQL */ - 'SELECT itemId, - `name`, - `data`, - `key` - FROM PluginData - WHERE `name` IN (' . $this->buildParamsFromArray($ids) . ') - ORDER BY `name`'; + $query = $this->queryFactory + ->newDelete() + ->from(self::TABLE) + ->where('name IN (:name)', ['name' => $names]); - $queryData = new QueryData(); - $queryData->setMapClassName(PluginDataModel::class); - $queryData->setQuery($query); - $queryData->setParams($ids); + $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while deleting plugin\'s data')); - return $this->db->doSelect($queryData); - } - - /** - * Deletes all the items for given ids - * - * @param string[] $ids - * - * @return int - * @throws ConstraintException - * @throws QueryException - */ - public function deleteByIdBatch(array $ids): int - { - if (count($ids) === 0) { - return 0; - } - - $queryData = new QueryData(); - $queryData->setQuery('DELETE FROM PluginData WHERE `name` IN (' . $this->buildParamsFromArray($ids) . ')'); - $queryData->setParams($ids); - $queryData->setOnErrorMessage(__u('Error while deleting plugin\'s data')); - - return $this->db->doQuery($queryData)->getAffectedNumRows(); + return $this->db->doQuery($queryData); } /** @@ -250,23 +228,17 @@ final class PluginData extends BaseRepository implements PluginDataRepository * @param int $itemId * * @return QueryResult - * @throws ConstraintException - * @throws QueryException */ public function getByItemId(string $name, int $itemId): QueryResult { - $query = /** @lang SQL */ - 'SELECT itemId, - `name`, - `data`, - `key` - FROM PluginData - WHERE `name` = ? AND itemId = ? LIMIT 1'; + $query = $this->queryFactory + ->newSelect() + ->from(self::TABLE) + ->cols(PluginDataModel::getCols()) + ->where('name = :name AND itemId = :itemId', ['name' => $name, 'itemId' => $itemId]) + ->limit(1); - $queryData = new QueryData(); - $queryData->setMapClassName(PluginDataModel::class); - $queryData->setQuery($query); - $queryData->setParams([$name, $itemId]); + $queryData = QueryData::buildWithMapper($query, PluginDataModel::class); return $this->db->doSelect($queryData); } diff --git a/tests/SPT/Generators/PluginDataGenerator.php b/tests/SPT/Generators/PluginDataGenerator.php new file mode 100644 index 00000000..5f065bc8 --- /dev/null +++ b/tests/SPT/Generators/PluginDataGenerator.php @@ -0,0 +1,49 @@ +. + */ + +namespace SPT\Generators; + +use SP\Domain\Plugin\Models\PluginData; + +/** + * Class PluginGenerator + */ +final class PluginDataGenerator extends DataGenerator +{ + + public function buildPluginData(): PluginData + { + return new PluginData($this->pluginDataProperties()); + } + + private function pluginDataProperties(): array + { + return [ + 'itemId' => $this->faker->randomNumber(3), + 'name' => $this->faker->colorName(), + 'data' => serialize((object)['test' => 1]), + 'key' => $this->faker->sha1() + ]; + } +} diff --git a/tests/SPT/Infrastructure/Plugin/Repositories/PluginDataTest.php b/tests/SPT/Infrastructure/Plugin/Repositories/PluginDataTest.php new file mode 100644 index 00000000..a1eb1eb0 --- /dev/null +++ b/tests/SPT/Infrastructure/Plugin/Repositories/PluginDataTest.php @@ -0,0 +1,308 @@ +. + */ + +namespace SPT\Infrastructure\Plugin\Repositories; + +use Aura\SqlQuery\Common\DeleteInterface; +use Aura\SqlQuery\Common\InsertInterface; +use Aura\SqlQuery\Common\SelectInterface; +use Aura\SqlQuery\Common\UpdateInterface; +use Aura\SqlQuery\QueryFactory; +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\Constraint\Callback; +use SP\Domain\Common\Models\Simple; +use SP\Domain\Core\Exceptions\ConstraintException; +use SP\Domain\Core\Exceptions\QueryException; +use SP\Domain\Plugin\Models\PluginData as PluginDataModel; +use SP\Infrastructure\Database\DatabaseInterface; +use SP\Infrastructure\Database\QueryData; +use SP\Infrastructure\Database\QueryResult; +use SP\Infrastructure\Plugin\Repositories\PluginData; +use SPT\Generators\PluginDataGenerator; +use SPT\UnitaryTestCase; + +/** + * Class PluginDataTest + */ +#[Group('unitary')] +class PluginDataTest extends UnitaryTestCase +{ + + private PluginData $pluginData; + + public function testGetAll() + { + $callback = new Callback( + static function (QueryData $arg) { + $query = $arg->getQuery(); + + return $arg->getMapClassName() === PluginDataModel::class + && is_a($query, SelectInterface::class) + && !empty($query->getStatement()); + } + ); + + $this->database + ->expects(self::once()) + ->method('doSelect') + ->with($callback); + + $this->pluginData->getAll(); + } + + /** + * @throws ConstraintException + * @throws QueryException + */ + public function testDeleteByItemId() + { + $callback = new Callback( + static function (QueryData $arg) { + $query = $arg->getQuery(); + $params = $query->getBindValues(); + + return count($params) === 2 + && $params['name'] === 'test_name' + && $params['itemId'] === 200 + && is_a($query, DeleteInterface::class) + && !empty($query->getStatement()); + } + ); + + $this->database->expects(self::once())->method('doQuery')->with($callback); + + $this->pluginData->deleteByItemId('test_name', 200); + } + + /** + * @throws ConstraintException + * @throws QueryException + */ + public function testDelete() + { + $callback = new Callback( + static function (QueryData $arg) { + $query = $arg->getQuery(); + $params = $query->getBindValues(); + + return count($params) === 1 + && $params['name'] === 'test_name' + && is_a($query, DeleteInterface::class) + && !empty($query->getStatement()); + } + ); + + $this->database->expects(self::once())->method('doQuery')->with($callback); + + $this->pluginData->delete('test_name'); + } + + /** + * @throws ConstraintException + * @throws QueryException + */ + public function testCreate() + { + $pluginData = PluginDataGenerator::factory()->buildPluginData(); + + $callbackCreate = new Callback( + static function (QueryData $arg) use ($pluginData) { + $query = $arg->getQuery(); + $params = $query->getBindValues(); + + return count($params) === 4 + && $params['name'] === $pluginData->getName() + && $params['data'] === $pluginData->getData() + && $params['key'] === $pluginData->getKey() + && $params['itemId'] === $pluginData->getItemId() + && is_a($query, InsertInterface::class) + && !empty($query->getStatement()); + } + ); + + $this->database + ->expects(self::exactly(1)) + ->method('doQuery') + ->with($callbackCreate) + ->willReturn(new QueryResult([])); + + $this->pluginData->create($pluginData); + } + + /** + * @throws ConstraintException + * @throws QueryException + */ + public function testUpdate() + { + $pluginData = PluginDataGenerator::factory()->buildPluginData(); + + $callbackCreate = new Callback( + static function (QueryData $arg) use ($pluginData) { + $query = $arg->getQuery(); + $params = $query->getBindValues(); + + return count($params) === 4 + && $params['name'] === $pluginData->getName() + && $params['itemId'] === $pluginData->getItemId() + && $params['key'] === $pluginData->getKey() + && $params['data'] === $pluginData->getData() + && is_a($query, UpdateInterface::class) + && !empty($query->getStatement()); + } + ); + + $queryResult = new QueryResult([]); + + $this->database + ->expects(self::exactly(1)) + ->method('doQuery') + ->with($callbackCreate) + ->willReturn($queryResult->setAffectedNumRows(1)); + + $out = $this->pluginData->update($pluginData); + + $this->assertEquals(1, $out); + } + + public function testGetByNameBatch() + { + $names = [self::$faker->colorName(), self::$faker->colorName(), self::$faker->colorName()]; + + $callback = new Callback( + static function (QueryData $arg) use ($names) { + $query = $arg->getQuery(); + $values = $query->getBindValues(); + + return count($values) === 3 + && array_shift($values) === array_shift($names) + && array_shift($values) === array_shift($names) + && array_shift($values) === array_shift($names) + && $arg->getMapClassName() === PluginDataModel::class + && is_a($query, SelectInterface::class) + && !empty($query->getStatement()); + } + ); + + $this->database + ->expects(self::once()) + ->method('doSelect') + ->with($callback); + + $this->pluginData->getByNameBatch($names); + } + + /** + * @throws ConstraintException + * @throws QueryException + */ + public function testDeleteByNameBatch() + { + $names = [self::$faker->colorName(), self::$faker->colorName(), self::$faker->colorName()]; + + $callback = new Callback( + static function (QueryData $arg) use ($names) { + $query = $arg->getQuery(); + $values = $query->getBindValues(); + + return count($values) === 3 + && array_shift($values) === array_shift($names) + && array_shift($values) === array_shift($names) + && array_shift($values) === array_shift($names) + && $arg->getMapClassName() === Simple::class + && is_a($query, DeleteInterface::class) + && !empty($query->getStatement()); + } + ); + + $this->database + ->expects(self::once()) + ->method('doQuery') + ->with($callback); + + $this->pluginData->deleteByNameBatch($names); + } + + public function testGetByItemId() + { + $callback = new Callback( + static function (QueryData $arg) { + $query = $arg->getQuery(); + $params = $query->getBindValues(); + + return count($params) === 2 + && $params['name'] === 'test_name' + && $params['itemId'] === 100 + && $arg->getMapClassName() === PluginDataModel::class + && is_a($query, SelectInterface::class) + && !empty($query->getStatement()); + } + ); + + $this->database + ->expects(self::once()) + ->method('doSelect') + ->with($callback); + + $this->pluginData->getByItemId('test_name', 100); + } + + public function testGetByName() + { + $callback = new Callback( + static function (QueryData $arg) { + $query = $arg->getQuery(); + $params = $query->getBindValues(); + + return count($params) === 1 + && $params['name'] === 'test_name' + && $arg->getMapClassName() === PluginDataModel::class + && is_a($query, SelectInterface::class) + && !empty($query->getStatement()); + } + ); + + $this->database + ->expects(self::once()) + ->method('doSelect') + ->with($callback); + + $this->pluginData->getByName('test_name'); + } + + protected function setUp(): void + { + parent::setUp(); + + $this->database = $this->createMock(DatabaseInterface::class); + $queryFactory = new QueryFactory('mysql'); + + $this->pluginData = new PluginData( + $this->database, + $this->context, + $this->application->getEventDispatcher(), + $queryFactory, + ); + } +}