diff --git a/Application/Model/ExportBase.php b/Application/Model/ExportBase.php index 480bab2..02c0eab 100644 --- a/Application/Model/ExportBase.php +++ b/Application/Model/ExportBase.php @@ -69,23 +69,7 @@ abstract class ExportBase implements QueryBase } } - [ $rows, $fieldNames ] = $this->getExportData( $this->getQuery() ); - - $content = $this->renderContent($rows, $fieldNames, $format); - - /** @var $oFS d3filesystem */ - $oFS = oxNew( d3filesystem::class ); - if (is_null($path)) { - $oFS->startDirectDownload( $oFS->filterFilename( $this->getExportFileName( $format ) ), $content ); - } else { - $filePath = $oFS->trailingslashit($path).$oFS->filterFilename( $this->getExportFileName( $format ) ); - if (false === $oFS->createFile($filePath, $content,true)) { - throw oxNew(ExportFileException::class, $filePath); - } - return $filePath; - } - - return ''; + return $this->executeExport($format, $path); } /** @@ -180,7 +164,7 @@ abstract class ExportBase implements QueryBase ); } - $rows = DatabaseProvider::getDb( DatabaseProvider::FETCH_MODE_ASSOC )->getAll( $queryString, $parameters ); + $rows = $this->d3GetDb()->getAll( $queryString, $parameters ); if ( count( $rows ) <= 0 ) { throw oxNew( @@ -200,15 +184,12 @@ abstract class ExportBase implements QueryBase */ public function registerFormElement(Input $input) { - switch (get_class($input)) { - case Radio::class: - case Checkbox::class: - $input->setTemplate('

{{ input }} {{ label }}

'); - $input->setAttribute('class', 'form-check-input'); - break; - default: - $input->setTemplate('

{{ label }} {{ input }}

'); - $input->setAttribute('class', 'form-control'); + if ($input instanceof Radio || $input instanceof Checkbox) { + $input->setTemplate('

{{ input }} {{ label }}

'); + $input->setAttribute('class', 'form-check-input'); + } else { + $input->setTemplate('

{{ label }} {{ input }}

'); + $input->setAttribute('class', 'form-control'); } $this->formElements[] = $input; } @@ -228,4 +209,54 @@ abstract class ExportBase implements QueryBase { return $this->formElements; } + + /** + * @param string $format + * @param $path + * @return string + * @throws DBALException + * @throws DatabaseConnectionException + * @throws DatabaseErrorException + * @throws Exceptions\NoSuitableRendererException + * @throws StandardException + * @throws d3ShopCompatibilityAdapterException + * @throws d3_cfg_mod_exception + */ + protected function executeExport(string $format, $path): string + { + [$rows, $fieldNames] = $this->getExportData($this->getQuery()); + + $content = $this->renderContent($rows, $fieldNames, $format); + + /** @var $oFS d3filesystem */ + $oFS = $this->getFileSystem(); + if (is_null($path)) { + $oFS->startDirectDownload($oFS->filterFilename($this->getExportFileName($format)), $content); + } else { + $filePath = $oFS->trailingslashit($path) . $oFS->filterFilename($this->getExportFileName($format)); + if (false === $oFS->createFile($filePath, $content, true)) { + throw oxNew(ExportFileException::class, $filePath); + } + return $filePath; + } + + return ''; + } + + /** + * @return \OxidEsales\Eshop\Core\Database\Adapter\DatabaseInterface|null + * @throws DatabaseConnectionException + */ + protected function d3GetDb(): ?\OxidEsales\Eshop\Core\Database\Adapter\DatabaseInterface + { + return DatabaseProvider::getDb(DatabaseProvider::FETCH_MODE_ASSOC); + } + + /** + * @return d3filesystem|mixed + */ + protected function getFileSystem() + { + return oxNew(d3filesystem::class); + } } \ No newline at end of file diff --git a/tests/unit/Application/Controller/Admin/d3ExportWizardTest.php b/tests/unit/Application/Controller/Admin/d3ExportWizardTest.php index 907634a..e5cccf3 100644 --- a/tests/unit/Application/Controller/Admin/d3ExportWizardTest.php +++ b/tests/unit/Application/Controller/Admin/d3ExportWizardTest.php @@ -15,7 +15,6 @@ declare(strict_types=1); namespace D3\DataWizard\tests\unit\Application\Controller\Admin; -use D3\DataWizard\Application\Controller\Admin\d3ActionWizard; use D3\DataWizard\Application\Controller\Admin\d3ExportWizard; use D3\DataWizard\Application\Model\Configuration; use D3\DataWizard\Application\Model\Exceptions\DebugException; diff --git a/tests/unit/Application/Model/Exceptions/DebugExceptionTest.php b/tests/unit/Application/Model/Exceptions/DebugExceptionTest.php new file mode 100644 index 0000000..779db2f --- /dev/null +++ b/tests/unit/Application/Model/Exceptions/DebugExceptionTest.php @@ -0,0 +1,76 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DataWizard\tests\unit\Application\Model\Exceptions; + +use D3\DataWizard\Application\Model\Exceptions\DebugException; +use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase; +use PHPUnit\Framework\MockObject\MockObject; + +class DebugExceptionTest extends d3ModCfgUnitTestCase +{ + /** @var DebugException */ + protected $_oModel; + + /** + * @covers \D3\DataWizard\Application\Model\Exceptions\DebugException::__construct + * @test + * @throws \ReflectionException + */ + public function canConstruct() + { + $code = '500'; + + $exception = oxNew(\Exception::class); + + /** @var DebugException|MockObject $modelMock */ + $modelMock = $this->getMockBuilder(DebugException::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->_oModel = $modelMock; + + $this->callMethod( + $this->_oModel, + '__construct', + ['testMessage', $code, $exception] + ); + + $this->assertStringContainsString( + 'DEBUG', + $this->callMethod( + $this->_oModel, + 'getMessage' + ) + ); + + $this->assertEquals( + $code, + $this->callMethod( + $this->_oModel, + 'getCode' + ) + ); + + $this->assertSame( + $exception, + $this->callMethod( + $this->_oModel, + 'getPrevious' + ) + ); + } + +} \ No newline at end of file diff --git a/tests/unit/Application/Model/Exceptions/ExportFileExceptionTest.php b/tests/unit/Application/Model/Exceptions/ExportFileExceptionTest.php new file mode 100644 index 0000000..be6d83e --- /dev/null +++ b/tests/unit/Application/Model/Exceptions/ExportFileExceptionTest.php @@ -0,0 +1,76 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DataWizard\tests\unit\Application\Model\Exceptions; + +use D3\DataWizard\Application\Model\Exceptions\ExportFileException; +use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase; +use PHPUnit\Framework\MockObject\MockObject; + +class ExportFileExceptionTest extends d3ModCfgUnitTestCase +{ + /** @var ExportFileException */ + protected $_oModel; + + /** + * @covers \D3\DataWizard\Application\Model\Exceptions\ExportFileException::__construct + * @test + * @throws \ReflectionException + */ + public function canConstruct() + { + $code = '500'; + + $exception = oxNew(\Exception::class); + + /** @var ExportFileException|MockObject $modelMock */ + $modelMock = $this->getMockBuilder(ExportFileException::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->_oModel = $modelMock; + + $this->callMethod( + $this->_oModel, + '__construct', + ['testMessage', $code, $exception] + ); + + $this->assertStringContainsString( + 'EXPORTFILEERROR', + $this->callMethod( + $this->_oModel, + 'getMessage' + ) + ); + + $this->assertEquals( + $code, + $this->callMethod( + $this->_oModel, + 'getCode' + ) + ); + + $this->assertSame( + $exception, + $this->callMethod( + $this->_oModel, + 'getPrevious' + ) + ); + } + +} \ No newline at end of file diff --git a/tests/unit/Application/Model/Exceptions/InputUnvalidExceptionTest.php b/tests/unit/Application/Model/Exceptions/InputUnvalidExceptionTest.php new file mode 100644 index 0000000..2dfe869 --- /dev/null +++ b/tests/unit/Application/Model/Exceptions/InputUnvalidExceptionTest.php @@ -0,0 +1,96 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DataWizard\tests\unit\Application\Model\Exceptions; + +use D3\DataWizard\Application\Model\Exceptions\InputUnvalidException; +use D3\DataWizard\Application\Model\ExportBase; +use D3\DataWizard\tests\tools\d3TestExport; +use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase; +use FormManager\Inputs\Number; +use PHPUnit\Framework\MockObject\MockObject; + +class InputUnvalidExceptionTest extends d3ModCfgUnitTestCase +{ + /** @var InputUnvalidException */ + protected $_oModel; + + /** + * @covers \D3\DataWizard\Application\Model\Exceptions\InputUnvalidException::__construct + * @test + * @throws \ReflectionException + */ + public function canConstruct() + { + $code = '500'; + + $exception = oxNew(\Exception::class); + + /** @var Number $invalidField */ + $invalidField = new Number(null, [ + 'required' => true, + 'min' => 1, + 'max' => 10, + 'step' => 5, + ]); + $invalidField + ->setValue(20) + ->setErrorMessages(['errorMsgs']); + + /** @var ExportBase|MockObject $taskMock */ + $taskMock = $this->getMockBuilder(d3TestExport::class) + ->onlyMethods(['getTitle']) + ->getMock(); + $taskMock->expects($this->atLeastOnce())->method('getTitle')->willReturn('testTitle'); + + /** @var InputUnvalidException|MockObject $modelMock */ + $modelMock = $this->getMockBuilder(InputUnvalidException::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->_oModel = $modelMock; + + $this->callMethod( + $this->_oModel, + '__construct', + [$taskMock, $invalidField, $code, $exception] + ); + + $this->assertRegExp( + '/^testTitle\s-\s*->\s.*\sless\s/m', + $this->callMethod( + $this->_oModel, + 'getMessage' + ) + ); + + $this->assertEquals( + $code, + $this->callMethod( + $this->_oModel, + 'getCode' + ) + ); + + $this->assertSame( + $exception, + $this->callMethod( + $this->_oModel, + 'getPrevious' + ) + ); + } + +} \ No newline at end of file diff --git a/tests/unit/Application/Model/Exceptions/NoSuitableRendererExceptionTest.php b/tests/unit/Application/Model/Exceptions/NoSuitableRendererExceptionTest.php new file mode 100644 index 0000000..49e34b0 --- /dev/null +++ b/tests/unit/Application/Model/Exceptions/NoSuitableRendererExceptionTest.php @@ -0,0 +1,76 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DataWizard\tests\unit\Application\Model\Exceptions; + +use D3\DataWizard\Application\Model\Exceptions\NoSuitableRendererException; +use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase; +use PHPUnit\Framework\MockObject\MockObject; + +class NoSuitableRendererExceptionTest extends d3ModCfgUnitTestCase +{ + /** @var NoSuitableRendererException */ + protected $_oModel; + + /** + * @covers \D3\DataWizard\Application\Model\Exceptions\NoSuitableRendererException::__construct + * @test + * @throws \ReflectionException + */ + public function canConstruct() + { + $code = '500'; + + $exception = oxNew(\Exception::class); + + /** @var NoSuitableRendererException|MockObject $modelMock */ + $modelMock = $this->getMockBuilder(NoSuitableRendererException::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->_oModel = $modelMock; + + $this->callMethod( + $this->_oModel, + '__construct', + ['testMessage', $code, $exception] + ); + + $this->assertStringContainsString( + 'NOSUITABLERENDERER', + $this->callMethod( + $this->_oModel, + 'getMessage' + ) + ); + + $this->assertEquals( + $code, + $this->callMethod( + $this->_oModel, + 'getCode' + ) + ); + + $this->assertSame( + $exception, + $this->callMethod( + $this->_oModel, + 'getPrevious' + ) + ); + } + +} \ No newline at end of file diff --git a/tests/unit/Application/Model/Exceptions/TaskExceptionTest.php b/tests/unit/Application/Model/Exceptions/TaskExceptionTest.php new file mode 100644 index 0000000..f9d5cd4 --- /dev/null +++ b/tests/unit/Application/Model/Exceptions/TaskExceptionTest.php @@ -0,0 +1,84 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DataWizard\tests\unit\Application\Model\Exceptions; + +use D3\DataWizard\Application\Model\Exceptions\TaskException; +use D3\DataWizard\Application\Model\ExportBase; +use D3\DataWizard\tests\tools\d3TestExport; +use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase; +use PHPUnit\Framework\MockObject\MockObject; + +class TaskExceptionTest extends d3ModCfgUnitTestCase +{ + /** @var TaskException */ + protected $_oModel; + + /** + * @covers \D3\DataWizard\Application\Model\Exceptions\TaskException::__construct + * @test + * @throws \ReflectionException + */ + public function canConstruct() + { + $code = '500'; + + $exception = oxNew(\Exception::class); + + /** @var ExportBase|MockObject $taskMock */ + $taskMock = $this->getMockBuilder(d3TestExport::class) + ->onlyMethods(['getTitle']) + ->getMock(); + $taskMock->expects($this->atLeastOnce())->method('getTitle')->willReturn('testTitle'); + + /** @var TaskException|MockObject $modelMock */ + $modelMock = $this->getMockBuilder(TaskException::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->_oModel = $modelMock; + + $this->callMethod( + $this->_oModel, + '__construct', + [$taskMock, 'testMessage', $code, $exception] + ); + + $this->assertSame( + 'testTitle - testMessage', + $this->callMethod( + $this->_oModel, + 'getMessage' + ) + ); + + $this->assertEquals( + $code, + $this->callMethod( + $this->_oModel, + 'getCode' + ) + ); + + $this->assertSame( + $exception, + $this->callMethod( + $this->_oModel, + 'getPrevious' + ) + ); + } + +} \ No newline at end of file diff --git a/tests/unit/Application/Model/ExportBaseTest.php b/tests/unit/Application/Model/ExportBaseTest.php new file mode 100644 index 0000000..e486956 --- /dev/null +++ b/tests/unit/Application/Model/ExportBaseTest.php @@ -0,0 +1,607 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DataWizard\tests\unit\Application\Model; + +use D3\DataWizard\Application\Model\Exceptions\ExportFileException; +use D3\DataWizard\Application\Model\Exceptions\TaskException; +use D3\DataWizard\Application\Model\ExportRenderer\Csv; +use D3\DataWizard\Application\Model\ExportRenderer\RendererBridge; +use D3\DataWizard\Application\Model\ExportRenderer\RendererInterface; +use D3\DataWizard\tests\tools\d3TestExport; +use D3\ModCfg\Application\Model\d3filesystem; +use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase; +use FormManager\Inputs\Hidden; +use FormManager\Inputs\Number; +use FormManager\Inputs\Radio; +use OxidEsales\Eshop\Core\Database\Adapter\Doctrine\Database; +use OxidEsales\Eshop\Core\Exception\StandardException; +use PHPUnit\Framework\MockObject\MockObject; +use ReflectionException; + +class ExportBaseTest extends d3ModCfgUnitTestCase +{ + /** @var d3TestExport */ + protected $_oModel; + + public function setUp() : void + { + parent::setUp(); + + $this->_oModel = oxNew(d3TestExport::class); + } + + public function tearDown() : void + { + parent::tearDown(); + + unset($this->_oModel); + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::getDescription + * @test + * @throws ReflectionException + */ + public function canGetDescription() + { + $this->assertIsString( + $this->callMethod( + $this->_oModel, + 'getDescription' + ) + ); + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::getButtonText + * @test + * @throws ReflectionException + */ + public function canGetButtonText() + { + $this->assertIsString( + $this->callMethod( + $this->_oModel, + 'getButtonText' + ) + ); + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::hasFormElements + * @test + * @throws ReflectionException + * @dataProvider canGetHasFormElementsDataProvider + */ + public function canGetHasFormElements($formElements, $expected) + { + $this->setValue($this->_oModel, 'formElements', $formElements); + + $this->assertSame( + $expected, + $this->callMethod( + $this->_oModel, + 'hasFormElements' + ) + ); + } + + public function canGetHasFormElementsDataProvider() + { + return [ + 'hasFormElements' => [['abc', 'def'], true], + 'hasNoFormElements' => [[], false], + ]; + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::getFormElements + * @test + * @throws ReflectionException + * @dataProvider canGetHasFormElementsDataProvider + */ + public function canGetFormElements($formElements) + { + $this->setValue($this->_oModel, 'formElements', $formElements); + + $this->assertSame( + $formElements, + $this->callMethod( + $this->_oModel, + 'getFormElements' + ) + ); + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::registerFormElement + * @test + * @throws ReflectionException + * @dataProvider canRegisterFormElementDataProvider + */ + public function canRegisterFormElement($inputClass) + { + $oldCount = count($this->getValue($this->_oModel, 'formElements')); + + /** @var Radio|MockObject $inputMock */ + $inputMock = $this->getMockBuilder($inputClass) + ->onlyMethods([ + 'setTemplate', + 'setAttribute' + ]) + ->getMock(); + $inputMock->expects($this->atLeastOnce())->method('setTemplate'); + $inputMock->expects($this->atLeastOnce())->method('setAttribute'); + + $this->callMethod( + $this->_oModel, + 'registerFormElement', + [$inputMock] + ); + + $newCount = count($this->getValue($this->_oModel, 'formElements')); + + $this->assertGreaterThan($oldCount, $newCount); + } + + /** + * @return \string[][] + */ + public function canRegisterFormElementDataProvider(): array + { + return [ + 'Radio' => [Radio::class], + 'Checkbox' => [Radio::class], + 'Hidden' => [Hidden::class] + ]; + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::run + * @test + * @throws ReflectionException + */ + public function canRunWithoutFormElements() + { + $format = 'myFormat'; + $path = 'myPath'; + + /** @var d3TestExport|MockObject $modelMock */ + $modelMock = $this->getMockBuilder(d3TestExport::class) + ->onlyMethods([ + 'hasFormElements', + 'executeExport' + ]) + ->getMock(); + $modelMock->expects($this->atLeastOnce())->method('hasFormElements')->willReturn(false); + $modelMock->expects($this->atLeastOnce())->method('executeExport')->with($format, $path)->willReturn('some content'); + $this->_oModel = $modelMock; + + $this->callMethod( + $this->_oModel, + 'run', + [$format, $path] + ); + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::run + * @test + * @throws ReflectionException + * @dataProvider canRunWithFormElementsDataProvider + */ + public function canRunWithFormElements($elements, $blThrowException) + { + $format = 'myFormat'; + $path = 'myPath'; + + $expectedException = oxNew(StandardException::class); + + $modelMock = $this->getMockBuilder(d3TestExport::class) + ->onlyMethods([ + 'hasFormElements', + 'executeExport', + 'getFormElements' + ]) + ->getMock(); + $modelMock->expects($this->atLeastOnce())->method('hasFormElements')->willReturn(true); + $modelMock->expects($this->exactly((int) !$blThrowException))->method('executeExport')->with($format, $path)->willReturn('some content'); + $modelMock->expects($this->atLeastOnce())->method('getFormElements')->willReturn($elements); + $this->_oModel = $modelMock; + + if ($blThrowException) { + $this->expectException(get_class($expectedException)); + } + + $this->callMethod( + $this->_oModel, + 'run', + [$format, $path] + ); + } + + /** + * @return array[] + */ + public function canRunWithFormElementsDataProvider(): array + { + /** @var Radio|MockObject $validMock */ + $validMock = $this->getMockBuilder(Radio::class) + ->onlyMethods(['isValid']) + ->getMock(); + $validMock->expects($this->atLeastOnce())->method('isValid')->willReturn(true); + + $invalidField = new Number(null, [ + 'required' => true, + 'min' => 1, + 'max' => 10, + 'step' => 5, + ]); + $invalidField + ->setValue(20) + ->setErrorMessages(['errorMsgs']); + + return [ + 'validElements' => [[$validMock, $validMock], false], + 'invalidElements' => [[$validMock, $invalidField], true] + ]; + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::executeExport + * @test + * @throws ReflectionException + * @dataProvider canExecuteExportDataProvider + */ + public function canExecuteExport($path, $throwsException) + { + /** @var d3filesystem|MockObject $fsMock */ + $fsMock = $this->getMockBuilder(d3filesystem::class) + ->onlyMethods([ + 'startDirectDownload', + 'filterFilename', + 'trailingslashit', + 'createFile' + ]) + ->getMock(); + $fsMock->expects($this->exactly((int) !isset($path)))->method('startDirectDownload')->willReturn(true); + $fsMock->method('filterFilename')->willReturnArgument(0); + $fsMock->expects($this->exactly((int) isset($path)))->method('trailingslashit')->willReturnArgument(0); + $fsMock->expects($this->exactly((int) isset($path)))->method('createFile')->willReturn((bool) !$throwsException); + + /** @var d3TestExport|MockObject $modelMock */ + $modelMock = $this->getMockBuilder(d3TestExport::class) + ->onlyMethods([ + 'getQuery', + 'getExportData', + 'renderContent', + 'getFileSystem', + 'getExportFileName' + ]) + ->getMock(); + $modelMock->expects($this->atLeastOnce())->method('getQuery')->willReturn(['SELECT 1', ['arg1', 'arg2']]); + $modelMock->expects($this->atLeastOnce())->method('getExportData')->willReturn([[1, 2], ['field1', 'field2']]); + $modelMock->expects($this->atLeastOnce())->method('renderContent')->willReturn('some content'); + $modelMock->expects($this->atLeastOnce())->method('getFileSystem')->willReturn($fsMock); + $modelMock->expects($this->atLeastOnce())->method('getExportFileName')->willReturn('exportFileName'); + + $this->_oModel = $modelMock; + + if ($path && $throwsException) { + $this->expectException(ExportFileException::class); + } + + $this->callMethod( + $this->_oModel, + 'executeExport', + ['CSV', $path] + ); + } + + /** + * @return array[] + */ + public function canExecuteExportDataProvider(): array + { + return [ + 'unable to create path for saving file' => ['myPath', true], + 'can create path for saving file' => ['myPath', false], + 'no path for download' => [null, false], + ]; + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::d3GetDb + * @test + * @throws ReflectionException + */ + public function canGetDb() + { + $this->assertInstanceOf( + Database::class, + $this->callMethod( + $this->_oModel, + 'd3GetDb' + ) + ); + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::getFileSystem + * @test + * @throws ReflectionException + */ + public function canGetFileSystem() + { + $this->assertInstanceOf( + d3filesystem::class, + $this->callMethod( + $this->_oModel, + 'getFileSystem' + ) + ); + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::getRenderer + * @test + * @throws ReflectionException + */ + public function canGetRenderer() + { + /** @var RendererInterface|MockObject $rendererMock */ + $rendererMock = $this->getMockBuilder(Csv::class) + ->getMock(); + + /** @var RendererBridge|MockObject $rendererBridgeMock */ + $rendererBridgeMock = $this->getMockBuilder(RendererBridge::class) + ->onlyMethods(['getRenderer']) + ->getMock(); + $rendererBridgeMock->expects($this->atLeastOnce())->method('getRenderer')->willReturn($rendererMock); + + /** @var d3TestExport|MockObject $modelMock */ + $modelMock = $this->getMockBuilder(d3TestExport::class) + ->onlyMethods([ + 'getRendererBridge' + ]) + ->getMock(); + $modelMock->expects($this->atLeastOnce())->method('getRendererBridge')->willReturn($rendererBridgeMock); + + $this->_oModel = $modelMock; + + $this->assertSame( + $rendererMock, + $this->callMethod( + $this->_oModel, + 'getRenderer', + [RendererBridge::FORMAT_CSV] + ) + ); + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::getRendererBridge + * @test + * @throws ReflectionException + */ + public function canGetRendererBridge() + { + $this->assertInstanceOf( + RendererBridge::class, + $this->callMethod( + $this->_oModel, + 'getRendererBridge' + ) + ); + } + + + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::getFileExtension + * @test + * @throws ReflectionException + */ + public function canGetFileExtension() + { + $format = RendererBridge::FORMAT_CSV; + $expected = 'myFileExtension'; + + /** @var RendererInterface|MockObject $rendererMock */ + $rendererMock = $this->getMockBuilder(Csv::class) + ->onlyMethods(['getFileExtension']) + ->getMock(); + $rendererMock->expects($this->atLeastOnce())->method('getFileExtension')->willReturn($expected); + + /** @var d3TestExport|MockObject $modelMock */ + $modelMock = $this->getMockBuilder(d3TestExport::class) + ->onlyMethods([ + 'getRenderer' + ]) + ->getMock(); + $modelMock->expects($this->atLeastOnce())->method('getRenderer')->with($format)->willReturn($rendererMock); + + $this->_oModel = $modelMock; + + $this->assertSame( + $expected, + $this->callMethod( + $this->_oModel, + 'getFileExtension', + [$format] + ) + ); + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::renderContent + * @test + * @throws ReflectionException + */ + public function canRenderContent() + { + $rows = ['row1', 'row2']; + $fieldnames = ['fieldname1', 'fieldname2']; + $format = RendererBridge::FORMAT_CSV; + $expected = 'myContent'; + + /** @var RendererInterface|MockObject $rendererMock */ + $rendererMock = $this->getMockBuilder(Csv::class) + ->onlyMethods(['getContent']) + ->getMock(); + $rendererMock->expects($this->atLeastOnce())->method('getContent')->with($rows, $fieldnames)->willReturn($expected); + + /** @var d3TestExport|MockObject $modelMock */ + $modelMock = $this->getMockBuilder(d3TestExport::class) + ->onlyMethods([ + 'getRenderer' + ]) + ->getMock(); + $modelMock->expects($this->atLeastOnce())->method('getRenderer')->with($format)->willReturn($rendererMock); + + $this->_oModel = $modelMock; + + $this->assertSame( + $expected, + $this->callMethod( + $this->_oModel, + 'renderContent', + [$rows, $fieldnames, $format] + ) + ); + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::getExportFilenameBase + * @test + * @throws ReflectionException + */ + public function canGetExportFilenameBase() + { + /** @var d3TestExport|MockObject $modelMock */ + $modelMock = $this->getMockBuilder(d3TestExport::class) + ->onlyMethods([ + 'getTitle' + ]) + ->getMock(); + $modelMock->expects($this->atLeastOnce())->method('getTitle')->willReturn('someTitle'); + + $this->_oModel = $modelMock; + + $this->callMethod( + $this->_oModel, + 'getExportFilenameBase' + ); + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::getExportFileName + * @test + * @throws ReflectionException + */ + public function canGetExportFileName() + { + $format = RendererBridge::FORMAT_CSV; + + /** @var d3TestExport|MockObject $modelMock */ + $modelMock = $this->getMockBuilder(d3TestExport::class) + ->onlyMethods([ + 'getExportFilenameBase', + 'getFileExtension' + ]) + ->getMock(); + $modelMock->expects($this->atLeastOnce())->method('getExportFilenameBase')->willReturn('base'); + $modelMock->expects($this->atLeastOnce())->method('getFileExtension')->with($format)->willReturn('extension'); + + $this->_oModel = $modelMock; + + $this->assertRegExp( + '/^base_(\d{4})-(\d{2})-(\d{2})_(\d{2})-(\d{2})-(\d{2})\.extension$/m', + $this->callMethod( + $this->_oModel, + 'getExportFileName', + [$format] + ) + ); + } + + /** + * @covers \D3\DataWizard\Application\Model\ExportBase::getExportData + * @test + * @throws ReflectionException + * @dataProvider canGetExportDataDataProvider + */ + public function canGetExportData($query, $throwsException, $dbResult) + { + /** @var Database|MockObject $dbMock */ + $dbMock = $this->getMockBuilder(Database::class) + ->onlyMethods(['getAll']) + ->getMock(); + $dbMock->expects($this->exactly((int) !$throwsException))->method('getAll')->willReturn($dbResult); + + /** @var d3TestExport|MockObject $modelMock */ + $modelMock = $this->getMockBuilder(d3TestExport::class) + ->onlyMethods([ + 'd3GetDb' + ]) + ->getMock(); + $modelMock->expects($this->exactly((int) !$throwsException))->method('d3GetDb')->willReturn($dbMock); + + $this->_oModel = $modelMock; + + try { + $result = $this->callMethod( + $this->_oModel, + 'getExportData', + [[$query], ['param1', 'param2']] + ); + + $this->assertSame( + [ + [ + [ + 'field1' => 'content1', + 'field2' => 'content2' + ] + ], + [ + 'field1', + 'field2' + ] + ], + $result + ); + } catch (TaskException $e) { + if ($throwsException) { + $this->assertStringContainsString('NOEXPORTSELECT', $e->getMessage()); + } elseif (!count($dbResult)) { + $this->assertStringContainsString('kein Inhalt', $e->getMessage()); + } + } + } + + /** + * @return array[] + */ + public function canGetExportDataDataProvider(): array + { + return [ + 'not SELECT throws exception' => [' UPDATE 1', true, []], + 'empty SELECT' => [' SELECT 1', false, []], + 'fulfilled SELECT' => [' SELECT 1', false, [['field1' => 'content1', 'field2' => 'content2']]], + ]; + } +} \ No newline at end of file