test(refactor): Extract duplicated code

Signed-off-by: Rubén D <nuxsmin@syspass.org>
This commit is contained in:
Rubén D
2024-09-01 17:39:02 +02:00
parent 419915a866
commit 4d1708ed90
20 changed files with 441 additions and 606 deletions

View File

@@ -24,89 +24,74 @@
namespace SP\Modules\Web\Controllers\ConfigEncryption;
use Exception;
use JsonException;
use SP\Core\Application;
use SP\Core\Crypt\Hash;
use SP\Core\Crypt\Session as CryptSession;
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\Core\Acl\AclActionsInterface;
use SP\Domain\Core\Acl\UnauthorizedPageException;
use SP\Domain\Core\Exceptions\ConstraintException;
use SP\Domain\Core\Exceptions\CryptException;
use SP\Domain\Core\Exceptions\QueryException;
use SP\Domain\Core\Exceptions\SessionTimeout;
use SP\Domain\Core\Exceptions\SPException;
use SP\Domain\Crypt\Ports\MasterPassService;
use SP\Domain\Http\Dtos\JsonMessage;
use SP\Modules\Web\Controllers\SimpleControllerBase;
use SP\Modules\Web\Controllers\Traits\JsonTrait;
use SP\Mvc\Controller\SimpleControllerHelper;
use function SP\__u;
/**
* Class RefreshController
*/
final class RefreshController extends SimpleControllerBase
{
use JsonTrait;
private MasterPassService $masterPassService;
public function __construct(
Application $application,
SimpleControllerHelper $simpleControllerHelper,
MasterPassService $masterPassService
Application $application,
SimpleControllerHelper $simpleControllerHelper,
private readonly MasterPassService $masterPassService
) {
parent::__construct($application, $simpleControllerHelper);
$this->masterPassService = $masterPassService;
}
/**
* Refresh master password hash
*
* @return bool
* @throws JsonException
* @return ActionResponse
* @throws ConstraintException
* @throws CryptException
* @throws QueryException
*/
public function refreshAction(): bool
#[Action(ResponseType::JSON)]
public function refreshAction(): ActionResponse
{
try {
if ($this->config->getConfigData()->isDemoEnabled()) {
return $this->returnJsonResponse(JsonMessage::JSON_WARNING, __u('Ey, this is a DEMO!!'));
}
$this->masterPassService->updateConfig(Hash::hashKey(CryptSession::getSessionKey($this->session)));
$this->eventDispatcher->notify(
'refresh.masterPassword.hash',
new Event($this, EventMessage::build()->addDescription(__u('Master password hash updated')))
);
return $this->returnJsonResponse(JsonMessage::JSON_SUCCESS, __u('Master password hash updated'));
} catch (Exception $e) {
processException($e);
$this->eventDispatcher->notify('exception', new Event($e));
return $this->returnJsonResponse(
JsonMessage::JSON_ERROR,
__u('Error while updating the master password hash')
);
if ($this->config->getConfigData()->isDemoEnabled()) {
return ActionResponse::warning(__u('Ey, this is a DEMO!!'));
}
$this->masterPassService->updateConfig(Hash::hashKey(CryptSession::getSessionKey($this->session)));
$this->eventDispatcher->notify(
'refresh.masterPassword.hash',
new Event($this, EventMessage::build()->addDescription(__u('Master password hash updated')))
);
return ActionResponse::ok(__u('Master password hash updated'));
}
/**
* @return void
* @throws JsonException
* @throws SessionTimeout
* @throws UnauthorizedPageException
* @throws SPException
*/
protected function initialize(): void
{
try {
$this->checks();
$this->checkAccess(AclActionsInterface::CONFIG_CRYPT);
} catch (UnauthorizedPageException $e) {
$this->eventDispatcher->notify('exception', new Event($e));
$this->returnJsonResponseException($e);
}
$this->checks();
$this->checkAccess(AclActionsInterface::CONFIG_CRYPT);
}
}

View File

@@ -24,30 +24,31 @@
namespace SP\Modules\Web\Controllers\ConfigEncryption;
use Exception;
use JsonException;
use SP\Core\Application;
use SP\Core\Crypt\Hash;
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\Config\Ports\ConfigService;
use SP\Domain\Core\Acl\AclActionsInterface;
use SP\Domain\Core\Acl\UnauthorizedPageException;
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\Crypt\Dtos\UpdateMasterPassRequest;
use SP\Domain\Crypt\Ports\MasterPassService;
use SP\Domain\Crypt\Services\MasterPass;
use SP\Domain\Http\Dtos\JsonMessage;
use SP\Domain\Task\Ports\TaskInterface;
use SP\Domain\Task\Services\Task;
use SP\Domain\Task\Services\TaskFactory;
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
use SP\Infrastructure\File\FileException;
use SP\Modules\Web\Controllers\SimpleControllerBase;
use SP\Modules\Web\Controllers\Traits\JsonTrait;
use SP\Mvc\Controller\SimpleControllerHelper;
use function SP\__u;
/**
* Class SaveController
*/
@@ -55,28 +56,25 @@ final class SaveController extends SimpleControllerBase
{
use JsonTrait;
private MasterPassService $masterPassService;
private ConfigService $configService;
public function __construct(
Application $application,
SimpleControllerHelper $simpleControllerHelper,
MasterPassService $masterPassService,
ConfigService $configService
Application $application,
SimpleControllerHelper $simpleControllerHelper,
private readonly MasterPassService $masterPassService,
private readonly ConfigService $configService
) {
parent::__construct($application, $simpleControllerHelper);
$this->masterPassService = $masterPassService;
$this->configService = $configService;
}
/**
* @return bool
* @throws JsonException
* @return ActionResponse
* @throws NoSuchItemException
* @throws ServiceException
* @throws ConstraintException
* @throws QueryException
* @throws Exception
*/
public function saveAction(): bool
#[Action(ResponseType::JSON)]
public function saveAction(): ActionResponse
{
$currentMasterPass = $this->request->analyzeEncrypted('current_masterpass');
$newMasterPass = $this->request->analyzeEncrypted('new_masterpass');
@@ -85,134 +83,71 @@ final class SaveController extends SimpleControllerBase
$noAccountPassChange = $this->request->analyzeBool('no_account_change', false);
if (!$this->masterPassService->checkUserUpdateMPass($this->session->getUserData()->getLastUpdateMPass())) {
return $this->returnJsonResponse(
JsonMessage::JSON_SUCCESS_STICKY,
__u('Master password updated'),
[__u('Please, restart the session for update it')]
);
if (!$this->masterPassService->checkUserUpdateMPass($this->session->getUserData()->lastUpdateMPass)) {
return ActionResponse::ok(__u('Master password updated'), __u('Please, restart the session for update it'));
}
if (empty($newMasterPass) || empty($currentMasterPass)) {
return $this->returnJsonResponse(
JsonMessage::JSON_ERROR,
__u('Master password not entered')
);
return ActionResponse::error(__u('Master password not entered'));
}
if ($confirmPassChange === false) {
return $this->returnJsonResponse(
JsonMessage::JSON_ERROR,
__u('The password update must be confirmed')
);
return ActionResponse::ok(__u('The password update must be confirmed'));
}
if ($newMasterPass === $currentMasterPass) {
return $this->returnJsonResponse(
JsonMessage::JSON_ERROR,
__u('Passwords are the same')
);
return ActionResponse::ok(__u('Passwords are the same'));
}
if ($newMasterPass !== $newMasterPassR) {
return $this->returnJsonResponse(
JsonMessage::JSON_ERROR,
__u('Master passwords do not match')
);
return ActionResponse::ok(__u('Master passwords do not match'));
}
if (!$this->masterPassService->checkMasterPassword($currentMasterPass)) {
return $this->returnJsonResponse(
JsonMessage::JSON_ERROR,
__u('The current master password does not match')
);
return ActionResponse::ok(__u('The current master password does not match'));
}
if (!$this->config->getConfigData()->isMaintenance()) {
return $this->returnJsonResponse(
JsonMessage::JSON_WARNING,
return ActionResponse::warning(
__u('Maintenance mode not enabled'),
[__u('Please, enable it to avoid unwanted behavior from other sessions')]
__u('Please, enable it to avoid unwanted behavior from other sessions')
);
}
if ($this->config->getConfigData()->isDemoEnabled()) {
return $this->returnJsonResponse(
JsonMessage::JSON_WARNING,
__u('Ey, this is a DEMO!!')
);
return ActionResponse::warning(__u('Ey, this is a DEMO!!'));
}
if (!$noAccountPassChange) {
try {
$request = new UpdateMasterPassRequest(
$currentMasterPass,
$newMasterPass,
$this->configService->getByParam(MasterPass::PARAM_MASTER_PASS_HASH),
);
$request = new UpdateMasterPassRequest(
$currentMasterPass,
$newMasterPass,
$this->configService->getByParam(MasterPass::PARAM_MASTER_PASS_HASH),
);
$this->eventDispatcher->notify('update.masterPassword.start', new Event($this));
$this->eventDispatcher->notify('update.masterPassword.start', new Event($this));
$this->masterPassService->changeMasterPassword($request);
$this->masterPassService->changeMasterPassword($request);
$this->eventDispatcher->notify('update.masterPassword.end', new Event($this));
} catch (Exception $e) {
processException($e);
$this->eventDispatcher->notify('exception', new Event($e));
return $this->returnJsonResponseException($e);
}
$this->eventDispatcher->notify('update.masterPassword.end', new Event($this));
} else {
try {
$this->eventDispatcher->notify('update.masterPassword.hash', new Event($this));
$this->eventDispatcher->notify('update.masterPassword.hash', new Event($this));
$this->masterPassService->updateConfig(Hash::hashKey($newMasterPass));
} catch (Exception $e) {
processException($e);
$this->eventDispatcher->notify('exception', new Event($e));
return $this->returnJsonResponse(
JsonMessage::JSON_ERROR,
__u('Error while saving the Master Password\'s hash')
);
}
$this->masterPassService->updateConfig(Hash::hashKey($newMasterPass));
}
return $this->returnJsonResponse(
JsonMessage::JSON_SUCCESS_STICKY,
__u('Master password updated'),
[__u('Please, restart the session to update it')]
);
return ActionResponse::ok(__u('Master password updated'), __u('Please, restart the session to update it'));
}
/**
* @return void
* @throws JsonException
* @throws SessionTimeout
* @throws UnauthorizedPageException
* @throws SPException
*/
protected function initialize(): void
{
try {
$this->checks();
$this->checkAccess(AclActionsInterface::CONFIG_CRYPT);
} catch (UnauthorizedPageException $e) {
$this->eventDispatcher->notify('exception', new Event($e));
$this->returnJsonResponseException($e);
}
}
/**
* @throws FileException
*/
private function getTask(): ?TaskInterface
{
$taskId = $this->request->analyzeString('taskId');
return $taskId !== null
? TaskFactory::register(new Task(__FUNCTION__, $taskId))
: null;
$this->checks();
$this->checkAccess(AclActionsInterface::CONFIG_CRYPT);
}
}

View File

@@ -24,108 +24,81 @@
namespace SP\Modules\Web\Controllers\ConfigEncryption;
use Exception;
use JsonException;
use PHPMailer\PHPMailer\Exception;
use SP\Core\Application;
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\Core\Acl\UnauthorizedPageException;
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\Crypt\Ports\TemporaryMasterPassService;
use SP\Domain\Http\Dtos\JsonMessage;
use SP\Modules\Web\Controllers\SimpleControllerBase;
use SP\Modules\Web\Controllers\Traits\JsonTrait;
use SP\Mvc\Controller\SimpleControllerHelper;
use function SP\__u;
/**
* Class ConfigEncryptionController
*
* @package SP\Modules\Web\Controllers
* Class SaveTempController
*/
final class SaveTempController extends SimpleControllerBase
{
use JsonTrait;
private TemporaryMasterPassService $temporaryMasterPassService;
public function __construct(
Application $application,
SimpleControllerHelper $simpleControllerHelper,
TemporaryMasterPassService $temporaryMasterPassService
Application $application,
SimpleControllerHelper $simpleControllerHelper,
private readonly TemporaryMasterPassService $temporaryMasterPassService
) {
parent::__construct($application, $simpleControllerHelper);
$this->temporaryMasterPassService = $temporaryMasterPassService;
}
/**
* Create a temporary master pass
*
* @return bool
* @throws JsonException
* @return ActionResponse
* @throws Exception
* @throws ServiceException
* @throws ConstraintException
* @throws QueryException
*/
public function saveTempAction(): bool
#[Action(ResponseType::JSON)]
public function saveTempAction(): ActionResponse
{
try {
$key =
$this->temporaryMasterPassService->create(
$this->request->analyzeInt('temporary_masterpass_maxtime', 3600)
);
$key =
$this->temporaryMasterPassService->create(
$this->request->analyzeInt('temporary_masterpass_maxtime', 3600)
);
$groupId = $this->request->analyzeInt('temporary_masterpass_group', 0);
$sendEmail = $this->configData->isMailEnabled()
&& $this->request->analyzeBool('temporary_masterpass_email');
$groupId = $this->request->analyzeInt('temporary_masterpass_group', 0);
$sendEmail = $this->configData->isMailEnabled()
&& $this->request->analyzeBool('temporary_masterpass_email');
if ($sendEmail) {
try {
if ($groupId > 0) {
$this->temporaryMasterPassService->sendByEmailForGroup($groupId, $key);
} else {
$this->temporaryMasterPassService->sendByEmailForAllUsers($key);
}
return $this->returnJsonResponse(
JsonMessage::JSON_SUCCESS,
__u('Temporary password generated'),
[__u('Email sent')]
);
} catch (Exception $e) {
processException($e);
$this->eventDispatcher->notify('exception', new Event($e));
return $this->returnJsonResponse(
JsonMessage::JSON_WARNING,
__u('Temporary password generated'),
[__u('Error while sending the email')]
);
}
if ($sendEmail) {
if ($groupId > 0) {
$this->temporaryMasterPassService->sendByEmailForGroup($groupId, $key);
} else {
$this->temporaryMasterPassService->sendByEmailForAllUsers($key);
}
return $this->returnJsonResponse(JsonMessage::JSON_SUCCESS, __u('Temporary password generated'));
} catch (Exception $e) {
processException($e);
$this->eventDispatcher->notify('exception', new Event($e));
return $this->returnJsonResponseException($e);
return ActionResponse::ok(__u('Temporary password generated'), __u('Email sent'));
}
return ActionResponse::ok(__u('Temporary password generated'));
}
/**
* @return void
* @throws JsonException
* @throws SessionTimeout
* @throws UnauthorizedPageException
* @throws SPException
*/
protected function initialize(): void
{
try {
$this->checks();
$this->checkAccess(AclActionsInterface::CONFIG_CRYPT);
} catch (UnauthorizedPageException $e) {
$this->eventDispatcher->notify('exception', new Event($e));
$this->returnJsonResponseException($e);
}
$this->checks();
$this->checkAccess(AclActionsInterface::CONFIG_CRYPT);
}
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace SP\Tests;
use Attribute;
/**
* Class InjectConfigParam
*/
#[Attribute(Attribute::TARGET_METHOD)]
final readonly class InjectConfigParam
{
public function __construct(public ?string $returnValue = null)
{
}
}

40
tests/SP/InjectCrypt.php Normal file
View File

@@ -0,0 +1,40 @@
<?php
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace SP\Tests;
use Attribute;
/**
* Class InjectCrypt
*/
#[Attribute(Attribute::TARGET_METHOD)]
final readonly class InjectCrypt
{
public function __construct(public string $returnValue = 'some_data')
{
}
}

38
tests/SP/InjectVault.php Normal file
View File

@@ -0,0 +1,38 @@
<?php
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace SP\Tests;
use Attribute;
/**
* Class InjectVault
*/
#[Attribute(Attribute::TARGET_CLASS)]
final class InjectVault
{
}

View File

@@ -39,7 +39,6 @@ use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use ReflectionAttribute;
use ReflectionException;
use ReflectionMethod;
use ReflectionObject;
use SP\Core\Bootstrap\Path;
@@ -52,12 +51,15 @@ use SP\Domain\Account\Ports\AccountAclService;
use SP\Domain\Auth\Ports\LdapConnectionInterface;
use SP\Domain\Config\Ports\ConfigDataInterface;
use SP\Domain\Config\Ports\ConfigFileService;
use SP\Domain\Config\Ports\ConfigService;
use SP\Domain\Core\Acl\AclInterface;
use SP\Domain\Core\Bootstrap\BootstrapInterface;
use SP\Domain\Core\Bootstrap\ModuleInterface;
use SP\Domain\Core\Bootstrap\UriContextInterface;
use SP\Domain\Core\Context\Context;
use SP\Domain\Core\Context\SessionContext;
use SP\Domain\Core\Crypt\CryptInterface;
use SP\Domain\Core\Crypt\VaultInterface;
use SP\Domain\Core\Exceptions\InvalidClassException;
use SP\Domain\Core\Exceptions\SPException;
use SP\Domain\Core\UI\ThemeContextInterface;
@@ -73,10 +75,8 @@ use SP\Infrastructure\File\ArchiveHandler;
use SP\Infrastructure\File\FileException;
use SP\Infrastructure\File\FileSystem;
use SP\Modules\Web\Bootstrap;
use SP\Mvc\View\OutputHandlerInterface;
use SP\Tests\Generators\UserDataGenerator;
use SP\Tests\Generators\UserProfileDataGenerator;
use SP\Tests\Stubs\OutputHandlerStub;
use function DI\autowire;
use function DI\factory;
@@ -87,8 +87,10 @@ use function DI\factory;
abstract class IntegrationTestCase extends TestCase
{
protected static Generator $faker;
private static array $definitionsCache;
protected readonly string $passwordSalt;
protected Closure|null $databaseQueryResolver = null;
protected Closure|null $databaseQueryResolver = null;
protected array $definitions;
/**
* @var array<string, QueryResult> $databaseMapperResolvers
*/
@@ -99,13 +101,39 @@ abstract class IntegrationTestCase extends TestCase
parent::setUpBeforeClass();
self::$faker = Factory::create();
self::$definitionsCache = array_merge(
DomainDefinitions::getDefinitions(),
CoreDefinitions::getDefinitions(REAL_APP_ROOT, 'web')
);
}
/**
* @throws Exception
* @throws \Exception
*/
protected function buildContainer(array $definitions = [], Request $request = null): ContainerInterface
protected function buildContainer(Request $request): ContainerInterface
{
$this->definitions[Request::class] = $request;
$testDefinitions = array_merge($this->definitions, $this->getMockedDefinitions());
$this->processAttributes(
$this->getClassAttributesMap($testDefinitions),
$this->getMethodAttributesMap($testDefinitions)
);
$containerBuilder = new ContainerBuilder();
$containerBuilder->addDefinitions(self::$definitionsCache, $testDefinitions);
return $containerBuilder->build();
}
/**
* @return array
* @throws Exception
* @throws SPException
*/
private function getMockedDefinitions(): array
{
$configData = $this->getConfigData();
@@ -122,7 +150,7 @@ abstract class IntegrationTestCase extends TestCase
$database->method('endTransaction')->willReturn(true);
$database->method('rollbackTransaction')->willReturn(true);
$acl = self::createMock(AclInterface::class);
$acl = $this->createMock(AclInterface::class);
$acl->method('checkUserAccess')->willReturn(true);
$acl->method('getRouteFor')->willReturnCallback(static fn(int $actionId) => (string)$actionId);
@@ -138,7 +166,7 @@ abstract class IntegrationTestCase extends TestCase
return $accountPermission;
});
$mockedDefinitions = [
return [
ConfigFileService::class => $configFileService,
LdapConnectionInterface::class => self::createStub(LdapConnectionInterface::class),
'backup.dbArchiveHandler' => self::createStub(ArchiveHandler::class),
@@ -159,44 +187,6 @@ abstract class IntegrationTestCase extends TestCase
AclInterface::class => $acl,
AccountAclService::class => $accountAcl,
];
$outputChecker = $this->getOutputChecker();
if ($outputChecker !== null) {
$definitions[OutputHandlerInterface::class] = new OutputHandlerStub($outputChecker->bindTo($this));
}
$bodyChecker = $this->getBodyChecker();
if ($bodyChecker !== null) {
$response = $this->getMockBuilder(Response::class)->onlyMethods(['body'])->getMock();
$response->method('body')
->with(
self::callback(static function (string $output) use ($bodyChecker) {
self::assertNotEmpty($output);
$bodyChecker($output);
return true;
})
);
$definitions[Response::class] = $response;
}
if ($request) {
$definitions += [Request::class => $request];
}
$containerBuilder = new ContainerBuilder();
$containerBuilder->addDefinitions(
DomainDefinitions::getDefinitions(),
CoreDefinitions::getDefinitions(REAL_APP_ROOT, 'web'),
$definitions,
$mockedDefinitions
);
return $containerBuilder->build();
}
/**
@@ -271,44 +261,103 @@ abstract class IntegrationTestCase extends TestCase
return UserProfileDataGenerator::factory()->buildProfileData();
}
/**
* @throws ReflectionException
*/
private function getOutputChecker(): ?Closure
private function processAttributes(array $classAtrributes, array $methodAttributes): void
{
$reflection = new ReflectionObject($this);
foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
if ($this->name() === $method->name) {
/** @var array<ReflectionAttribute<OutputChecker>> $attributes */
$attributes = $method->getAttributes(OutputChecker::class);
$object = new ReflectionObject($this);
if (count($attributes) === 1) {
return (new ReflectionMethod($this, $attributes[0]->newInstance()->target))->getClosure($this);
}
}
if (!empty($classAtrributes)) {
$this->invokeAttributes($object, $classAtrributes);
}
return null;
if (!empty($methodAttributes)) {
$methods = array_filter(
$object->getMethods(),
fn(ReflectionMethod $method) => $method->name === $this->name()
);
foreach ($methods as $method) {
$this->invokeAttributes($method, $methodAttributes);
}
}
}
private function invokeAttributes(ReflectionObject|ReflectionMethod $reflection, array $attributeMap): void
{
foreach ($reflection->getAttributes() as $attribute) {
$callable = $attributeMap[$attribute->getName()] ?? null;
if (is_callable($callable)) {
$callable($attribute);
}
}
}
private function getClassAttributesMap(array &$definitions): array
{
return [
InjectVault::class => function () use (&$definitions): void {
$vault = self::createStub(VaultInterface::class);
$vault->method('getData')->willReturn('some_data');
/** @var Context|Stub $context */
$context = $definitions[Context::class];
$context->method('getVault')->willReturn($vault);
}
];
}
/**
* @throws ReflectionException
* @param array $definitions
* @return Closure[]
*/
private function getBodyChecker(): ?Closure
private function getMethodAttributesMap(array &$definitions): array
{
$reflection = new ReflectionObject($this);
foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
if ($this->name() === $method->name) {
/** @var array<ReflectionAttribute<BodyChecker>> $attributes */
$attributes = $method->getAttributes(BodyChecker::class);
return [
BodyChecker::class =>
function (ReflectionAttribute $attribute) use (&$definitions): void {
/** @var ReflectionAttribute<BodyChecker> $attribute */
$bodyChecker = (new ReflectionMethod($this, $attribute->newInstance()->target))
->getClosure($this);
if (count($attributes) === 1) {
return (new ReflectionMethod($this, $attributes[0]->newInstance()->target))->getClosure($this);
$response = $this->getMockBuilder(Response::class)->onlyMethods(['body'])->getMock();
$response->method('body')
->with(
self::callback(static function (string $output) use ($bodyChecker) {
self::assertNotEmpty($output);
$bodyChecker($output);
return true;
})
);
$definitions[Response::class] = $response;
},
InjectCrypt::class => function (ReflectionAttribute $attribute) use (&$definitions): void {
/** @var ReflectionAttribute<InjectCrypt> $attribute */
$value = $attribute->newInstance()->returnValue;
$crypt = $this->createStub(CryptInterface::class);
$crypt->method('decrypt')->willReturn($value);
$crypt->method('encrypt')->willReturn($value);
$definitions[CryptInterface::class] = $crypt;
},
InjectConfigParam::class => function (ReflectionAttribute $attribute) use (&$definitions): void {
/** @var ReflectionAttribute<InjectConfigParam> $attribute */
$value = $attribute->newInstance()->returnValue;
$configService = self::createStub(ConfigService::class);
if ($value) {
$configService->method('getByParam')->willReturn($value);
} else {
$configService->method('getByParam')->willReturnArgument(0);
}
}
}
return null;
$definitions[ConfigService::class] = $configService;
}
];
}
final protected function addDatabaseMapperResolver(string $className, QueryResult $queryResult): void
@@ -344,15 +393,6 @@ abstract class IntegrationTestCase extends TestCase
);
}
/**
* @param callable $outputChecker
* @return OutputHandlerInterface
*/
protected function setupOutputHandler(callable $outputChecker): OutputHandlerInterface
{
return new OutputHandlerStub($outputChecker(...)->bindTo($this));
}
/**
* @param ContainerInterface $container
* @return void
@@ -368,15 +408,13 @@ abstract class IntegrationTestCase extends TestCase
* @throws FileException
* @throws InvalidClassException
*/
protected function getModuleDefinitions(): array
{
return FileSystem::require(FileSystem::buildPath(REAL_APP_ROOT, 'app', 'modules', 'web', 'module.php'));
}
protected function setUp(): void
{
parent::setUp();
$this->passwordSalt = self::$faker->sha1();
$this->definitions = FileSystem::require(
FileSystem::buildPath(REAL_APP_ROOT, 'app', 'modules', 'web', 'module.php')
);
}
}

View File

@@ -33,9 +33,7 @@ use PHPUnit\Framework\MockObject\Stub;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use SP\Domain\Config\Ports\ConfigDataInterface;
use SP\Domain\Core\Exceptions\InvalidClassException;
use SP\Domain\User\Models\ProfileData;
use SP\Infrastructure\File\FileException;
use SP\Tests\BodyChecker;
use SP\Tests\IntegrationTestCase;
use Symfony\Component\DomCrawler\Crawler;
@@ -47,10 +45,8 @@ use Symfony\Component\DomCrawler\Crawler;
class IndexControllerTest extends IntegrationTestCase
{
/**
* @throws Exception
* @throws FileException
* @throws InvalidClassException
* @throws ContainerExceptionInterface
* @throws Exception
* @throws NotFoundExceptionInterface
*/
#[Test]
@@ -58,7 +54,6 @@ class IndexControllerTest extends IntegrationTestCase
public function index()
{
$container = $this->buildContainer(
$this->getModuleDefinitions(),
$this->buildRequest('get', 'index.php', ['r' => 'accessManager/index'])
);

View File

@@ -30,7 +30,6 @@ use Defuse\Crypto\Exception\EnvironmentIsBrokenException;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\MockObject\Exception;
use PHPUnit\Framework\MockObject\Stub;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use SP\Core\Crypt\Crypt;
@@ -44,20 +43,17 @@ use SP\Domain\Account\Models\AccountView;
use SP\Domain\Account\Models\PublicLink;
use SP\Domain\Common\Models\Item;
use SP\Domain\Common\Models\Simple;
use SP\Domain\Config\Ports\ConfigService;
use SP\Domain\Core\Context\SessionContext;
use SP\Domain\Core\Crypt\CryptInterface;
use SP\Domain\Core\Crypt\VaultInterface;
use SP\Domain\Core\Exceptions\CryptException;
use SP\Domain\Core\Exceptions\InvalidClassException;
use SP\Domain\User\Dtos\UserDto;
use SP\Domain\User\Models\ProfileData;
use SP\Infrastructure\Database\QueryResult;
use SP\Infrastructure\File\FileException;
use SP\Tests\BodyChecker;
use SP\Tests\Generators\AccountDataGenerator;
use SP\Tests\Generators\PublicLinkDataGenerator;
use SP\Tests\Generators\UserDataGenerator;
use SP\Tests\InjectConfigParam;
use SP\Tests\InjectCrypt;
use SP\Tests\InjectVault;
use SP\Tests\IntegrationTestCase;
use Symfony\Component\DomCrawler\Crawler;
@@ -65,10 +61,9 @@ use Symfony\Component\DomCrawler\Crawler;
* Class AccountTest
*/
#[Group('integration')]
#[InjectVault]
class AccountTest extends IntegrationTestCase
{
private array $definitions;
/**
* @throws ContainerExceptionInterface
* @throws Exception
@@ -76,6 +71,7 @@ class AccountTest extends IntegrationTestCase
*/
#[Test]
#[BodyChecker('outputCheckerViewPassHistory')]
#[InjectCrypt]
public function viewPassHistory()
{
$this->addDatabaseMapperResolver(
@@ -86,14 +82,8 @@ class AccountTest extends IntegrationTestCase
)
])
);
$crypt = $this->createStub(CryptInterface::class);
$crypt->method('decrypt')->willReturn('some_data');
$crypt->method('encrypt')->willReturn('some_data');
$this->definitions[CryptInterface::class] = $crypt;
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest(
'get',
'index.php',
@@ -116,6 +106,7 @@ class AccountTest extends IntegrationTestCase
*/
#[Test]
#[BodyChecker('outputCheckerViewPass')]
#[InjectCrypt]
public function viewPass()
{
$this->addDatabaseMapperResolver(
@@ -126,14 +117,8 @@ class AccountTest extends IntegrationTestCase
)
])
);
$crypt = $this->createStub(CryptInterface::class);
$crypt->method('decrypt')->willReturn('some_data');
$crypt->method('encrypt')->willReturn('some_data');
$this->definitions[CryptInterface::class] = $crypt;
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest(
'get',
'index.php',
@@ -179,7 +164,6 @@ class AccountTest extends IntegrationTestCase
$this->addDatabaseMapperResolver(PublicLink::class, new QueryResult([$publicLink]));
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'account/viewLink/' . self::$faker->sha1()])
);
@@ -220,7 +204,6 @@ class AccountTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'account/viewHistory/id/' . self::$faker->randomNumber(3)])
);
@@ -253,7 +236,6 @@ class AccountTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'account/view/id/' . self::$faker->randomNumber(3)])
);
@@ -277,7 +259,6 @@ class AccountTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest(
'post',
'index.php',
@@ -295,6 +276,7 @@ class AccountTest extends IntegrationTestCase
* @throws NotFoundExceptionInterface
*/
#[Test]
#[InjectConfigParam]
public function saveRequest()
{
$accountDataGenerator = AccountDataGenerator::factory();
@@ -304,13 +286,7 @@ class AccountTest extends IntegrationTestCase
new QueryResult([$accountDataGenerator->buildAccountDataView()])
);
$configService = self::createStub(ConfigService::class);
$configService->method('getByParam')->willReturnArgument(0);
$this->definitions[ConfigService::class] = $configService;
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest(
'post',
'index.php',
@@ -332,6 +308,7 @@ class AccountTest extends IntegrationTestCase
* @throws NotFoundExceptionInterface
*/
#[Test]
#[InjectConfigParam]
public function saveEditRestore()
{
$accountDataGenerator = AccountDataGenerator::factory();
@@ -351,11 +328,6 @@ class AccountTest extends IntegrationTestCase
new QueryResult([$accountDataGenerator->buildAccountDataView()])
);
$configService = self::createStub(ConfigService::class);
$configService->method('getByParam')->willReturnArgument(0);
$this->definitions[ConfigService::class] = $configService;
$account = $accountDataGenerator->buildAccount();
$paramsPost = [
@@ -367,7 +339,6 @@ class AccountTest extends IntegrationTestCase
$accountId = self::$faker->randomNumber(3);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest(
'post',
'index.php',
@@ -391,6 +362,7 @@ class AccountTest extends IntegrationTestCase
* @throws NotFoundExceptionInterface
*/
#[Test]
#[InjectConfigParam]
public function saveEditPass()
{
$accountDataGenerator = AccountDataGenerator::factory();
@@ -405,11 +377,6 @@ class AccountTest extends IntegrationTestCase
new QueryResult([$accountDataGenerator->buildAccountDataView()])
);
$configService = self::createStub(ConfigService::class);
$configService->method('getByParam')->willReturnArgument(0);
$this->definitions[ConfigService::class] = $configService;
$account = $accountDataGenerator->buildAccount();
$paramsPost = [
@@ -420,7 +387,6 @@ class AccountTest extends IntegrationTestCase
$accountId = self::$faker->randomNumber(3);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('post', 'index.php', ['r' => 'account/saveEditPass/' . $accountId], $paramsPost)
);
@@ -438,6 +404,7 @@ class AccountTest extends IntegrationTestCase
* @throws NotFoundExceptionInterface
*/
#[Test]
#[InjectConfigParam]
public function saveEdit()
{
$accountDataGenerator = AccountDataGenerator::factory();
@@ -452,11 +419,6 @@ class AccountTest extends IntegrationTestCase
new QueryResult([$accountDataGenerator->buildAccountDataView()])
);
$configService = self::createStub(ConfigService::class);
$configService->method('getByParam')->willReturnArgument(0);
$this->definitions[ConfigService::class] = $configService;
$account = $accountDataGenerator->buildAccount();
$paramsPost = [
@@ -488,7 +450,6 @@ class AccountTest extends IntegrationTestCase
$accountId = self::$faker->randomNumber(3);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest(
'post',
'index.php',
@@ -511,6 +472,7 @@ class AccountTest extends IntegrationTestCase
* @throws NotFoundExceptionInterface
*/
#[Test]
#[InjectConfigParam]
public function saveDelete()
{
$accountDataGenerator = AccountDataGenerator::factory();
@@ -525,13 +487,7 @@ class AccountTest extends IntegrationTestCase
new QueryResult([$accountDataGenerator->buildAccount()])
);
$configService = self::createStub(ConfigService::class);
$configService->method('getByParam')->willReturnArgument(0);
$this->definitions[ConfigService::class] = $configService;
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('post', 'index.php', ['r' => 'account/saveDelete/1'])
);
@@ -568,7 +524,6 @@ class AccountTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'account/copy/id/' . self::$faker->randomNumber(3)])
);
@@ -581,6 +536,7 @@ class AccountTest extends IntegrationTestCase
* @throws NotFoundExceptionInterface
*/
#[Test]
#[InjectCrypt]
public function copyPass()
{
$this->addDatabaseMapperResolver(
@@ -591,14 +547,8 @@ class AccountTest extends IntegrationTestCase
)
])
);
$crypt = $this->createStub(CryptInterface::class);
$crypt->method('decrypt')->willReturn('some_data');
$crypt->method('encrypt')->willReturn('some_data');
$this->definitions[CryptInterface::class] = $crypt;
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'account/copyPass/id/' . self::$faker->randomNumber(3)])
);
@@ -613,6 +563,7 @@ class AccountTest extends IntegrationTestCase
* @throws NotFoundExceptionInterface
*/
#[Test]
#[InjectCrypt]
public function copyPassHistory()
{
$this->addDatabaseMapperResolver(
@@ -624,14 +575,7 @@ class AccountTest extends IntegrationTestCase
])
);
$crypt = $this->createStub(CryptInterface::class);
$crypt->method('decrypt')->willReturn('some_data');
$crypt->method('encrypt')->willReturn('some_data');
$this->definitions[CryptInterface::class] = $crypt;
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest(
'get',
'index.php',
@@ -654,7 +598,6 @@ class AccountTest extends IntegrationTestCase
public function create()
{
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'account/create'])
);
@@ -676,7 +619,6 @@ class AccountTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'account/delete/100'])
);
@@ -698,7 +640,6 @@ class AccountTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'account/edit/' . self::$faker->randomNumber(3)])
);
@@ -715,7 +656,6 @@ class AccountTest extends IntegrationTestCase
public function index()
{
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'account'])
);
@@ -737,7 +677,6 @@ class AccountTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'account/requestAccess/' . self::$faker->randomNumber(3)])
);
@@ -750,6 +689,7 @@ class AccountTest extends IntegrationTestCase
* @throws NotFoundExceptionInterface
*/
#[Test]
#[InjectCrypt]
public function saveCopy()
{
$accountDataGenerator = AccountDataGenerator::factory();
@@ -759,12 +699,6 @@ class AccountTest extends IntegrationTestCase
new QueryResult([$accountDataGenerator->buildAccountDataView()])
);
$crypt = $this->createStub(CryptInterface::class);
$crypt->method('decrypt')->willReturn('some_data');
$crypt->method('encrypt')->willReturn('some_data');
$this->definitions[CryptInterface::class] = $crypt;
$account = $accountDataGenerator->buildAccount();
$paramsPost = [
@@ -794,7 +728,6 @@ class AccountTest extends IntegrationTestCase
];
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('post', 'index.php', ['r' => 'account/saveCopy'], $paramsPost)
);
@@ -811,6 +744,7 @@ class AccountTest extends IntegrationTestCase
* @throws NotFoundExceptionInterface
*/
#[Test]
#[InjectCrypt]
public function saveCreate()
{
$accountDataGenerator = AccountDataGenerator::factory();
@@ -820,12 +754,6 @@ class AccountTest extends IntegrationTestCase
new QueryResult([$accountDataGenerator->buildAccountDataView()])
);
$crypt = $this->createStub(CryptInterface::class);
$crypt->method('decrypt')->willReturn('some_data');
$crypt->method('encrypt')->willReturn('some_data');
$this->definitions[CryptInterface::class] = $crypt;
$account = $accountDataGenerator->buildAccount();
$paramsPost = [
@@ -855,7 +783,6 @@ class AccountTest extends IntegrationTestCase
];
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('post', 'index.php', ['r' => 'account/saveCreate'], $paramsPost)
);
@@ -866,34 +793,12 @@ class AccountTest extends IntegrationTestCase
);
}
/**
* @throws FileException
* @throws InvalidClassException
*/
protected function setUp(): void
{
parent::setUp();
$this->definitions = $this->getModuleDefinitions();
}
protected function getUserDataDto(): UserDto
{
$userPreferences = UserDataGenerator::factory()->buildUserPreferencesData()->mutate(['topNavbar' => true]);
return parent::getUserDataDto()->mutate(['preferences' => $userPreferences]);
}
protected function getContext(): SessionContext|Stub
{
$vault = self::createStub(VaultInterface::class);
$vault->method('getData')->willReturn('some_data');
$context = parent::getContext();
$context->method('getVault')->willReturn($vault);
return $context;
}
protected function getUserProfile(): ProfileData
{
return new ProfileData(

View File

@@ -30,8 +30,6 @@ use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\MockObject\Exception;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use SP\Domain\Core\Exceptions\InvalidClassException;
use SP\Infrastructure\File\FileException;
use SP\Tests\IntegrationTestCase;
/**
@@ -41,18 +39,13 @@ use SP\Tests\IntegrationTestCase;
class AccountFavoriteTest extends IntegrationTestCase
{
/**
* @throws NotFoundExceptionInterface
* @throws Exception
* @throws FileException
* @throws InvalidClassException
* @throws ContainerExceptionInterface
* @throws Exception
* @throws NotFoundExceptionInterface
*/
public function testMarkAction()
{
$definitions = $this->getModuleDefinitions();
$container = $this->buildContainer(
$definitions,
$this->buildRequest('post', 'index.php', ['r' => 'accountFavorite/mark/100'])
);
@@ -62,18 +55,13 @@ class AccountFavoriteTest extends IntegrationTestCase
}
/**
* @throws NotFoundExceptionInterface
* @throws Exception
* @throws FileException
* @throws InvalidClassException
* @throws ContainerExceptionInterface
* @throws Exception
* @throws NotFoundExceptionInterface
*/
public function testUnmarkAction()
{
$definitions = $this->getModuleDefinitions();
$container = $this->buildContainer(
$definitions,
$this->buildRequest('post', 'index.php', ['r' => 'accountFavorite/unmark/100'])
);

View File

@@ -34,10 +34,8 @@ use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use SP\Domain\Account\Models\File;
use SP\Domain\Config\Ports\ConfigDataInterface;
use SP\Domain\Core\Exceptions\InvalidClassException;
use SP\Infrastructure\Database\QueryData;
use SP\Infrastructure\Database\QueryResult;
use SP\Infrastructure\File\FileException;
use SP\Tests\BodyChecker;
use SP\Tests\Generators\FileDataGenerator;
use SP\Tests\IntegrationTestCase;
@@ -49,8 +47,6 @@ use Symfony\Component\DomCrawler\Crawler;
#[Group('integration')]
class AccountFileTest extends IntegrationTestCase
{
private array $moduleDefinitions;
/**
* @throws ContainerExceptionInterface
* @throws Exception
@@ -60,7 +56,6 @@ class AccountFileTest extends IntegrationTestCase
public function deleteSingleFile()
{
$container = $this->buildContainer(
$this->moduleDefinitions,
$this->buildRequest('post', 'index.php', ['r' => 'accountFile/delete/100'])
);
@@ -87,7 +82,6 @@ class AccountFileTest extends IntegrationTestCase
};
$container = $this->buildContainer(
$this->moduleDefinitions,
$this->buildRequest('post', 'index.php', ['r' => 'accountFile/delete'], ['items' => [100, 200, 300]])
);
@@ -115,7 +109,6 @@ class AccountFileTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->moduleDefinitions,
$this->buildRequest('get', 'index.php', ['r' => 'accountFile/download/100'])
);
@@ -147,7 +140,6 @@ class AccountFileTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->moduleDefinitions,
$this->buildRequest('get', 'index.php', ['r' => 'accountFile/list/100'])
);
@@ -178,7 +170,6 @@ class AccountFileTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->moduleDefinitions,
$this->buildRequest('get', 'index.php', ['r' => 'accountFile/search'])
);
@@ -209,7 +200,6 @@ class AccountFileTest extends IntegrationTestCase
];
$container = $this->buildContainer(
$this->moduleDefinitions,
$this->buildRequest('post', 'index.php', ['r' => 'accountFile/upload/100'], [], $files)
);
@@ -234,7 +224,6 @@ class AccountFileTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->moduleDefinitions,
$this->buildRequest('get', 'index.php', ['r' => 'accountFile/view/100'])
);
@@ -251,17 +240,6 @@ class AccountFileTest extends IntegrationTestCase
return $configData;
}
/**
* @throws FileException
* @throws InvalidClassException
*/
protected function setUp(): void
{
parent::setUp();
$this->moduleDefinitions = $this->getModuleDefinitions();
}
/**
* @param string $output
* @return void

View File

@@ -35,10 +35,8 @@ use SP\Domain\Account\Models\Account;
use SP\Domain\Account\Models\AccountHistory;
use SP\Domain\Common\Models\Simple;
use SP\Domain\Config\Models\Config;
use SP\Domain\Core\Exceptions\InvalidClassException;
use SP\Infrastructure\Database\QueryData;
use SP\Infrastructure\Database\QueryResult;
use SP\Infrastructure\File\FileException;
use SP\Tests\BodyChecker;
use SP\Tests\Generators\AccountDataGenerator;
use SP\Tests\IntegrationTestCase;
@@ -50,8 +48,6 @@ use Symfony\Component\DomCrawler\Crawler;
#[Group('integration')]
class AccountHistoryManagerTest extends IntegrationTestCase
{
private array $definitions;
/**
* @throws ContainerExceptionInterface
* @throws Exception
@@ -66,7 +62,6 @@ class AccountHistoryManagerTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'accountHistoryManager/delete/100'])
);
@@ -89,7 +84,6 @@ class AccountHistoryManagerTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest(
'post',
'index.php',
@@ -138,7 +132,6 @@ class AccountHistoryManagerTest extends IntegrationTestCase
};
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'accountHistoryManager/restore/100'])
);
@@ -182,7 +175,6 @@ class AccountHistoryManagerTest extends IntegrationTestCase
};
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'accountHistoryManager/restore/100'])
);
@@ -214,24 +206,12 @@ class AccountHistoryManagerTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'accountHistoryManager/search'])
);
$this->runApp($container);
}
/**
* @throws FileException
* @throws InvalidClassException
*/
protected function setUp(): void
{
parent::setUp();
$this->definitions = $this->getModuleDefinitions();
}
/**
* @param string $output
* @return void

View File

@@ -38,13 +38,11 @@ use SP\Domain\Category\Models\Category;
use SP\Domain\Client\Models\Client;
use SP\Domain\Config\Models\Config;
use SP\Domain\Config\Ports\ConfigService;
use SP\Domain\Core\Exceptions\InvalidClassException;
use SP\Domain\Tag\Models\Tag;
use SP\Domain\User\Models\User;
use SP\Domain\User\Models\UserGroup;
use SP\Infrastructure\Database\QueryData;
use SP\Infrastructure\Database\QueryResult;
use SP\Infrastructure\File\FileException;
use SP\Tests\BodyChecker;
use SP\Tests\Generators\AccountDataGenerator;
use SP\Tests\Generators\CategoryGenerator;
@@ -52,6 +50,7 @@ use SP\Tests\Generators\ClientGenerator;
use SP\Tests\Generators\TagGenerator;
use SP\Tests\Generators\UserDataGenerator;
use SP\Tests\Generators\UserGroupGenerator;
use SP\Tests\InjectConfigParam;
use SP\Tests\IntegrationTestCase;
use Symfony\Component\DomCrawler\Crawler;
@@ -61,8 +60,6 @@ use Symfony\Component\DomCrawler\Crawler;
#[Group('integration')]
class AccountManagerTest extends IntegrationTestCase
{
private array $definitions;
/**
* @throws ContainerExceptionInterface
* @throws Exception
@@ -98,7 +95,6 @@ class AccountManagerTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('post', 'index.php', ['r' => 'accountManager/bulkEdit'], ['items' => [100, 200, 300]])
);
@@ -111,6 +107,7 @@ class AccountManagerTest extends IntegrationTestCase
* @throws NotFoundExceptionInterface
*/
#[Test]
#[InjectConfigParam]
public function deleteSingle()
{
$accountDataGenerator = AccountDataGenerator::factory();
@@ -125,13 +122,7 @@ class AccountManagerTest extends IntegrationTestCase
new QueryResult([$accountDataGenerator->buildAccount()])
);
$configService = self::createStub(ConfigService::class);
$configService->method('getByParam')->willReturnArgument(0);
$this->definitions[ConfigService::class] = $configService;
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'accountManager/delete/100'])
);
@@ -172,7 +163,6 @@ class AccountManagerTest extends IntegrationTestCase
};
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('post', 'index.php', ['r' => 'accountManager/delete'], ['items' => [100, 200, 300]])
);
@@ -222,7 +212,6 @@ class AccountManagerTest extends IntegrationTestCase
];
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest(
'post',
'index.php',
@@ -259,24 +248,12 @@ class AccountManagerTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'accountManager/search', 'search' => 'test'])
);
$this->runApp($container);
}
/**
* @throws InvalidClassException
* @throws FileException
*/
protected function setUp(): void
{
parent::setUp();
$this->definitions = $this->getModuleDefinitions();
}
private function outputCheckerBulkEdit(string $output): void
{
$json = json_decode($output);

View File

@@ -32,9 +32,7 @@ use PHPUnit\Framework\MockObject\Exception;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use SP\Domain\Auth\Models\AuthToken;
use SP\Domain\Core\Exceptions\InvalidClassException;
use SP\Infrastructure\Database\QueryResult;
use SP\Infrastructure\File\FileException;
use SP\Tests\BodyChecker;
use SP\Tests\Generators\AuthTokenGenerator;
use SP\Tests\IntegrationTestCase;
@@ -46,8 +44,6 @@ use Symfony\Component\DomCrawler\Crawler;
#[Group('integration')]
class AuthTokenTest extends IntegrationTestCase
{
private array $definitions;
/**
* @throws ContainerExceptionInterface
* @throws Exception
@@ -58,7 +54,6 @@ class AuthTokenTest extends IntegrationTestCase
public function create()
{
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'authToken/create'])
);
@@ -74,7 +69,6 @@ class AuthTokenTest extends IntegrationTestCase
public function deleteMultiple()
{
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'authToken/delete', 'items' => [100, 200, 300]])
);
@@ -92,7 +86,6 @@ class AuthTokenTest extends IntegrationTestCase
public function deleteSingle()
{
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'authToken/delete/100'])
);
@@ -116,7 +109,6 @@ class AuthTokenTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'authToken/edit/100'])
);
@@ -138,7 +130,6 @@ class AuthTokenTest extends IntegrationTestCase
];
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('post', 'index.php', ['r' => 'authToken/saveCreate'], $data)
);
@@ -162,7 +153,6 @@ class AuthTokenTest extends IntegrationTestCase
];
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('post', 'index.php', ['r' => 'authToken/saveEdit/100'], $data)
);
@@ -194,7 +184,6 @@ class AuthTokenTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'authToken/search', 'search' => 'test'])
);
@@ -216,24 +205,12 @@ class AuthTokenTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'authToken/view/100'])
);
$this->runApp($container);
}
/**
* @throws FileException
* @throws InvalidClassException
*/
protected function setUp(): void
{
parent::setUp();
$this->definitions = $this->getModuleDefinitions();
}
/**
* @param string $output
* @return void

View File

@@ -31,8 +31,6 @@ use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\MockObject\Exception;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use SP\Domain\Core\Exceptions\InvalidClassException;
use SP\Infrastructure\File\FileException;
use SP\Tests\BodyChecker;
use SP\Tests\IntegrationTestCase;
@@ -47,15 +45,12 @@ class BootstrapTest extends IntegrationTestCase
* @throws ContainerExceptionInterface
* @throws Exception
* @throws NotFoundExceptionInterface
* @throws InvalidClassException
* @throws FileException
*/
#[Test]
#[BodyChecker('getEnvironmentOutputChecker')]
public function getEnvironment()
{
$container = $this->buildContainer(
$this->getModuleDefinitions(),
$this->buildRequest('get', 'index.php', ['r' => 'bootstrap/getEnvironment'])
);

View File

@@ -32,9 +32,7 @@ use PHPUnit\Framework\MockObject\Exception;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use SP\Domain\Category\Models\Category;
use SP\Domain\Core\Exceptions\InvalidClassException;
use SP\Infrastructure\Database\QueryResult;
use SP\Infrastructure\File\FileException;
use SP\Tests\BodyChecker;
use SP\Tests\Generators\CategoryGenerator;
use SP\Tests\IntegrationTestCase;
@@ -46,8 +44,6 @@ use Symfony\Component\DomCrawler\Crawler;
#[Group('integration')]
class CategoryTest extends IntegrationTestCase
{
private array $definitions;
/**
* @throws ContainerExceptionInterface
* @throws Exception
@@ -58,7 +54,6 @@ class CategoryTest extends IntegrationTestCase
public function create()
{
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'category/create'])
);
@@ -74,7 +69,6 @@ class CategoryTest extends IntegrationTestCase
public function deleteMultiple()
{
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'category/delete', 'items' => [100, 200, 300]])
);
@@ -92,7 +86,6 @@ class CategoryTest extends IntegrationTestCase
public function deleteSingle()
{
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'category/delete/100'])
);
@@ -116,7 +109,6 @@ class CategoryTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'category/edit/100'])
);
@@ -137,7 +129,6 @@ class CategoryTest extends IntegrationTestCase
];
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('post', 'index.php', ['r' => 'category/saveCreate'], $data)
);
@@ -160,7 +151,6 @@ class CategoryTest extends IntegrationTestCase
];
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('post', 'index.php', ['r' => 'category/saveEdit/100'], $data)
);
@@ -192,7 +182,6 @@ class CategoryTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'category/search', 'search' => 'test'])
);
@@ -214,24 +203,12 @@ class CategoryTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'category/view/100'])
);
$this->runApp($container);
}
/**
* @throws FileException
* @throws InvalidClassException
*/
protected function setUp(): void
{
parent::setUp();
$this->definitions = $this->getModuleDefinitions();
}
/**
* @param string $output
* @return void

View File

@@ -32,9 +32,7 @@ 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;
@@ -46,8 +44,6 @@ use Symfony\Component\DomCrawler\Crawler;
#[Group('integration')]
class ClientTest extends IntegrationTestCase
{
private array $definitions;
/**
* @throws ContainerExceptionInterface
* @throws Exception
@@ -58,7 +54,6 @@ class ClientTest extends IntegrationTestCase
public function create()
{
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'client/create'])
);
@@ -74,7 +69,6 @@ class ClientTest extends IntegrationTestCase
public function deleteMultiple()
{
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'client/delete', 'items' => [100, 200, 300]])
);
@@ -92,7 +86,6 @@ class ClientTest extends IntegrationTestCase
public function deleteSingle()
{
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'client/delete/100'])
);
@@ -116,7 +109,6 @@ class ClientTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'client/edit/100'])
);
@@ -138,7 +130,6 @@ class ClientTest extends IntegrationTestCase
];
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('post', 'index.php', ['r' => 'client/saveCreate'], $data)
);
@@ -162,7 +153,6 @@ class ClientTest extends IntegrationTestCase
];
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('post', 'index.php', ['r' => 'client/saveEdit/100'], $data)
);
@@ -194,7 +184,6 @@ class ClientTest extends IntegrationTestCase
);
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'client/search', 'search' => 'test'])
);
@@ -216,24 +205,12 @@ class ClientTest extends IntegrationTestCase
);
$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

View File

@@ -31,8 +31,6 @@ use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\MockObject\Exception;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use SP\Domain\Core\Exceptions\InvalidClassException;
use SP\Infrastructure\File\FileException;
use SP\Tests\IntegrationTestCase;
/**
@@ -46,8 +44,6 @@ class ConfigAccountControllerTest extends IntegrationTestCase
* @throws ContainerExceptionInterface
* @throws Exception
* @throws NotFoundExceptionInterface
* @throws InvalidClassException
* @throws FileException
*/
#[Test]
public function save()
@@ -71,7 +67,6 @@ class ConfigAccountControllerTest extends IntegrationTestCase
];
$container = $this->buildContainer(
$this->getModuleDefinitions(),
$this->buildRequest('post', 'index.php', ['r' => 'configAccount/save'], $data)
);

View File

@@ -33,8 +33,6 @@ use PHPUnit\Framework\MockObject\Stub;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use SP\Domain\Config\Ports\ConfigDataInterface;
use SP\Domain\Core\Exceptions\InvalidClassException;
use SP\Infrastructure\File\FileException;
use SP\Tests\IntegrationTestCase;
/**
@@ -43,8 +41,6 @@ use SP\Tests\IntegrationTestCase;
#[Group('integration')]
class ConfigBackupControllerTest extends IntegrationTestCase
{
private array $definitions;
/**
* @throws ContainerExceptionInterface
* @throws Exception
@@ -66,7 +62,6 @@ class ConfigBackupControllerTest extends IntegrationTestCase
file_put_contents($filename, 'test_data_app');
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'configBackup/downloadBackupApp'])
);
@@ -98,7 +93,6 @@ class ConfigBackupControllerTest extends IntegrationTestCase
file_put_contents($filename, 'test_data_db');
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'configBackup/downloadBackupDb'])
);
@@ -130,7 +124,6 @@ class ConfigBackupControllerTest extends IntegrationTestCase
file_put_contents($filename, 'test_data_export');
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'configBackup/downloadExport'])
);
@@ -150,7 +143,6 @@ class ConfigBackupControllerTest extends IntegrationTestCase
public function fileBackup()
{
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'configBackup/fileBackup'])
);
@@ -168,7 +160,6 @@ class ConfigBackupControllerTest extends IntegrationTestCase
public function xmlExport()
{
$container = $this->buildContainer(
$this->definitions,
$this->buildRequest('get', 'index.php', ['r' => 'configBackup/xmlExport'])
);
@@ -177,17 +168,6 @@ class ConfigBackupControllerTest extends IntegrationTestCase
$this->runApp($container);
}
/**
* @throws InvalidClassException
* @throws FileException
*/
protected function setUp(): void
{
parent::setUp();
$this->definitions = $this->getModuleDefinitions();
}
protected function getConfigData(): ConfigDataInterface|Stub
{
$configData = parent::getConfigData();

View File

@@ -0,0 +1,61 @@
<?php
/**
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace SP\Tests\Modules\Web\Controllers\ConfigEncryption;
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\Tests\InjectVault;
use SP\Tests\IntegrationTestCase;
/**
* Class RefreshControllerTest
*/
#[Group('integration')]
#[InjectVault]
class RefreshControllerTest extends IntegrationTestCase
{
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws Exception
*/
#[Test]
public function refresh()
{
$container = $this->buildContainer(
$this->buildRequest('get', 'index.php', ['r' => 'configEncryption/refresh'])
);
$this->runApp($container);
$this->expectOutputString('{"status":"OK","description":"Master password hash updated","data":null}');
}
}