. */ namespace SP\Tests\Domain\Config\Services; use Defuse\Crypto\Exception\EnvironmentIsBrokenException; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\MockObject\Exception; use PHPUnit\Framework\MockObject\MockObject; use SP\Core\Context\ContextException; use SP\Domain\Config\Adapters\ConfigData; use SP\Domain\Config\Ports\ConfigDataInterface; use SP\Domain\Config\Services\ConfigFile; use SP\Domain\Core\Exceptions\ConfigException; use SP\Domain\Storage\Ports\FileCacheService; use SP\Domain\Storage\Ports\XmlFileStorageService; use SP\Infrastructure\File\FileException; use SP\Tests\UnitaryTestCase; /** * Class ConfigFileTest * */ #[Group('unitary')] class ConfigFileTest extends UnitaryTestCase { private XmlFileStorageService|MockObject $fileStorageService; private FileCacheService|MockObject $fileCacheService; /** * @throws ConfigException * @throws Exception */ public function testInitializeWithProvided() { $this->fileCacheService ->expects(self::never()) ->method('exists'); $this->fileStorageService ->expects(self::never()) ->method('getFileTime'); $this->fileStorageService ->expects(self::never()) ->method('save'); $this->fileCacheService ->expects(self::never()) ->method('save'); $attributes = [ ConfigDataInterface::CONFIG_HASH => self::$faker->sha1(), ConfigDataInterface::LOG_EVENTS => self::$faker->boolean(), ConfigDataInterface::CONFIG_DATE => self::$faker->unixTime() ]; new ConfigFile( $this->fileStorageService, $this->fileCacheService, $this->context, new ConfigData($attributes) ); } /** * @throws ConfigException * @throws Exception */ public function testInitializeWithCache() { $this->fileCacheService ->expects(self::once()) ->method('exists') ->willReturn(true); $time = time(); $this->fileStorageService ->expects(self::once()) ->method('getFileTime') ->willReturn($time); $this->fileCacheService ->expects(self::once()) ->method('isExpiredDate') ->with($time) ->willReturn(false); $this->fileCacheService ->expects(self::once()) ->method('loadWith') ->with(ConfigData::class) ->willReturn($this->config->getConfigData()); new ConfigFile( $this->fileStorageService, $this->fileCacheService, $this->context ); } /** * @throws ConfigException * @throws Exception */ public function testInitializeWithCacheAndNoAttributes() { $this->fileCacheService ->expects(self::once()) ->method('exists') ->willReturn(true); $time = time(); $this->fileStorageService ->expects(self::once()) ->method('getFileTime') ->willReturn($time); $this->fileCacheService ->expects(self::once()) ->method('isExpiredDate') ->with($time) ->willReturn(false); $this->fileCacheService ->expects(self::once()) ->method('loadWith') ->with(ConfigData::class) ->willReturn(new ConfigData()); $this->fileCacheService ->expects(self::once()) ->method('delete'); $this->ensureConfigFileIsUsed(); new ConfigFile( $this->fileStorageService, $this->fileCacheService, $this->context ); } /** * @return void */ private function ensureConfigFileIsUsed(): void { $configData = new ConfigData(); $this->fileStorageService ->expects(self::once()) ->method('load') ->with('config') ->willReturn($configData->getAttributes()); $this->fileCacheService ->expects(self::once()) ->method('save') ->with($configData); } /** * @throws ConfigException * @throws Exception */ public function testInitializeWithExistingFile() { $this->fileCacheService ->expects(self::once()) ->method('exists') ->willReturn(false); $this->ensureConfigFileIsUsed(); new ConfigFile( $this->fileStorageService, $this->fileCacheService, $this->context ); } /** * @throws ConfigException * @throws Exception */ public function testInitializeWithGenerateNewConfig() { $this->fileCacheService ->expects(self::once()) ->method('exists') ->willReturn(false); $this->fileStorageService ->expects(self::never()) ->method('getFileTime'); $this->fileStorageService ->expects(self::once()) ->method('load') ->with('config') ->willThrowException(FileException::error('test')); $this->fileStorageService ->expects(self::once()) ->method('save') ->with(self::isType('array'), 'config'); $this->fileCacheService ->expects(self::once()) ->method('save') ->with(self::anything()); new ConfigFile( $this->fileStorageService, $this->fileCacheService, $this->context ); } /** * @throws ConfigException * @throws Exception */ public function testInitializeWithExceptionFromCache() { $this->fileCacheService ->expects(self::once()) ->method('exists') ->willReturn(true); $time = time(); $this->fileStorageService ->expects(self::once()) ->method('getFileTime') ->willReturn($time); $this->fileCacheService ->expects(self::once()) ->method('isExpiredDate') ->with($time) ->willReturn(false); $this->fileCacheService ->expects(self::once()) ->method('loadWith') ->with(ConfigData::class) ->willThrowException(FileException::error('test')); $this->expectException(ConfigException::class); $this->expectExceptionMessage('test'); new ConfigFile( $this->fileStorageService, $this->fileCacheService, $this->context ); } /** * @throws ConfigException * @throws Exception */ public function testInitializeWithExceptionFromCacheExpired() { $this->fileCacheService ->expects(self::once()) ->method('exists') ->willReturn(true); $time = time(); $this->fileStorageService ->expects(self::exactly(1)) ->method('getFileTime') ->willReturn($time); $this->fileCacheService ->expects(self::once()) ->method('isExpiredDate') ->with($time) ->willThrowException(FileException::error('test')); $this->fileCacheService ->expects(self::never()) ->method('loadWith'); $this->ensureConfigFileIsUsed(); new ConfigFile( $this->fileStorageService, $this->fileCacheService, $this->context ); } /** * @throws ConfigException * @throws Exception */ public function testInitializeWithExceptionCacheDelete() { $this->fileCacheService ->expects(self::once()) ->method('exists') ->willReturn(true); $time = time(); $this->fileStorageService ->expects(self::once()) ->method('getFileTime') ->willReturn($time); $this->fileCacheService ->expects(self::once()) ->method('isExpiredDate') ->with($time) ->willReturn(false); $this->fileCacheService ->expects(self::once()) ->method('loadWith') ->with(ConfigData::class) ->willReturn(new ConfigData()); $this->fileCacheService ->expects(self::once()) ->method('delete') ->willThrowException(FileException::error('test')); $this->expectException(ConfigException::class); $this->expectExceptionMessage('test'); new ConfigFile( $this->fileStorageService, $this->fileCacheService, $this->context ); } /** * @throws ConfigException * @throws Exception * @throws FileException */ public function testSave() { $this->fileCacheService ->expects(self::once()) ->method('exists') ->willReturn(false); $this->fileStorageService ->expects(self::never()) ->method('getFileTime'); $this->fileStorageService ->expects(self::once()) ->method('load') ->willThrowException(FileException::error('test')); $configData = $this->createMock(ConfigDataInterface::class); $this->fileStorageService ->expects(self::exactly(2)) ->method('save') ->with(self::isType('array'), 'config'); $this->fileCacheService ->expects(self::exactly(2)) ->method('save') ->with(self::anything()); $configFile = new ConfigFile( $this->fileStorageService, $this->fileCacheService, $this->context ); $configData->expects(self::once()) ->method('setConfigDate'); $configData->expects(self::once()) ->method('setConfigSaver'); $configData->expects(self::once()) ->method('setConfigHash'); $configData->expects(self::once()) ->method('getAttributes') ->willReturn([]); $configFile->save($configData); $this->assertEquals($configData, $configFile->getConfigData()); } /** * @throws ConfigException * @throws Exception * @throws FileException */ public function testSaveWithoutCommit() { $this->fileCacheService ->expects(self::once()) ->method('exists') ->willReturn(false); $this->fileStorageService ->expects(self::once()) ->method('load') ->willThrowException(FileException::error('test')); $configData = $this->createMock(ConfigDataInterface::class); $this->fileStorageService ->expects(self::exactly(1)) ->method('save') ->with(self::isType('array'), 'config'); $this->fileCacheService ->expects(self::exactly(1)) ->method('save') ->with(self::anything()); $configFile = new ConfigFile( $this->fileStorageService, $this->fileCacheService, $this->context ); $configData->expects(self::once()) ->method('setConfigDate'); $configData->expects(self::once()) ->method('setConfigSaver'); $configData->expects(self::once()) ->method('setConfigHash'); $configData->expects(self::never()) ->method('getAttributes'); $configFile->save($configData, false); $this->assertEquals($configData, $configFile->getConfigData()); } /** * @throws ConfigException * @throws Exception * @throws FileException * @throws EnvironmentIsBrokenException */ public function testGenerateUpgradeKey() { $this->fileCacheService ->expects(self::once()) ->method('exists') ->willReturn(false); $this->fileStorageService ->expects(self::once()) ->method('load') ->willThrowException(FileException::error('test')); $this->fileStorageService ->expects(self::exactly(2)) ->method('save') ->with(self::isType('array'), 'config'); $this->fileCacheService ->expects(self::exactly(2)) ->method('save') ->with(self::anything()); $configFile = new ConfigFile( $this->fileStorageService, $this->fileCacheService, $this->context ); $configFile->generateUpgradeKey(); $this->assertNotEmpty($configFile->getConfigData()->getUpgradeKey()); } /** * @throws ConfigException * @throws Exception * @throws FileException * @throws EnvironmentIsBrokenException */ public function testGenerateUpgradeKeyWithExistingKey() { $configData = $this->createMock(ConfigDataInterface::class); $configData->expects(self::once()) ->method('getUpgradeKey') ->willReturn(self::$faker->sha1()); $configData->expects(self::never()) ->method('setUpgradeKey'); $configFile = new ConfigFile( $this->fileStorageService, $this->fileCacheService, $this->context, $configData ); $configFile->generateUpgradeKey(); } /** * @throws ConfigException * @throws Exception */ public function testReload() { $this->fileCacheService ->expects(self::exactly(2)) ->method('exists') ->willReturn(false); $this->fileStorageService ->expects(self::never()) ->method('getFileTime'); $attributes = [ ConfigDataInterface::CONFIG_VERSION => self::$faker->colorName(), ConfigDataInterface::INSTALLED => self::$faker->boolean(), ConfigDataInterface::CONFIG_DATE => self::$faker->unixTime() ]; $configData = new ConfigData($attributes); $this->fileStorageService ->expects(self::exactly(2)) ->method('load') ->with('config') ->willReturn($attributes); $this->fileCacheService ->expects(self::exactly(2)) ->method('save') ->with($configData); $configFile = new ConfigFile( $this->fileStorageService, $this->fileCacheService, $this->context ); $configFile->reload(); } /** * @throws Exception * @throws ContextException */ protected function setUp(): void { parent::setUp(); $this->fileStorageService = $this->createMock(XmlFileStorageService::class); $this->fileCacheService = $this->createMock(FileCacheService::class); } }