diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..165765a --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +.phpunit.result.cache diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..2e8a767 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,52 @@ +# D3 Datawizard Tests + +## Requirements + +Both unit and acceptance tests require OXID Testing Library installed. +See https://github.com/OXID-eSales/testing_library. + +### Configuration + +Please install the packages listed in the composer.json in "require-dev". Unfortunately Composer does not provide an automatic installation. + +Here is an example of Testing Library configuration file `oxideshop/test_config.yml` + +``` +# This file is auto-generated during the composer install +mandatory_parameters: + shop_path: /var/www/oxideshop/source + shop_tests_path: /var/www/oxideshop/tests + partial_module_paths: d3/datawizard +optional_parameters: + shop_url: null + shop_serial: '' + enable_varnish: false + is_subshop: false + install_shop: false + remote_server_dir: null + shop_setup_path: null + restore_shop_after_tests_suite: false + test_database_name: null + restore_after_acceptance_tests: false + restore_after_unit_tests: false + tmp_path: /tmp/oxid_test_library/ + database_restoration_class: DatabaseRestorer + activate_all_modules: false + run_tests_for_shop: false + run_tests_for_modules: true + screen_shots_path: null + screen_shots_url: null + browser_name: firefox + selenium_server_ip: 127.0.0.1 + selenium_server_port: '4444' + additional_test_paths: null +``` + +## Unit Tests + +To execute unit tests run the following: + +``` +cd /var/www/oxideshop/ +vendor/bin/runtests +``` diff --git a/tests/additional.inc.php b/tests/additional.inc.php new file mode 100755 index 0000000..84c8ac5 --- /dev/null +++ b/tests/additional.inc.php @@ -0,0 +1,39 @@ + + * @link https://www.oxidmodule.com + */ + +// Include datawizard test config +namespace D3\DataWizard\tests; + +use D3\ModCfg\Tests\additional_abstract; +use Exception; +use OxidEsales\Eshop\Core\Exception\StandardException; + +include(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'd3datawizard_config.php'); + +class additional extends additional_abstract +{ + /** + * additional constructor. + * @throws StandardException + */ + public function __construct() + { + if (D3DATAWIZARD_REQUIRE_MODCFG) { + $this->reactivateModCfg(); + } + } +} + +try { + d3GetModCfgDIC()->get(additional::class); +} catch (Exception $e) {} \ No newline at end of file diff --git a/tests/d3datawizard_config.php b/tests/d3datawizard_config.php new file mode 100755 index 0000000..e4e6aab --- /dev/null +++ b/tests/d3datawizard_config.php @@ -0,0 +1,15 @@ + + * @link https://www.oxidmodule.com + */ + +define('D3DATAWIZARD_REQUIRE_MODCFG', true); + diff --git a/tests/phpunit.xml b/tests/phpunit.xml new file mode 100644 index 0000000..6c09de6 --- /dev/null +++ b/tests/phpunit.xml @@ -0,0 +1,27 @@ + + + + ../Application + ../Modules + ../public + ../Setup + + + + + + diff --git a/tests/reports/logfile.xml b/tests/reports/logfile.xml new file mode 100644 index 0000000..c7f9b6c --- /dev/null +++ b/tests/reports/logfile.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/tools/d3TestAction.php b/tests/tools/d3TestAction.php new file mode 100644 index 0000000..18fd56f --- /dev/null +++ b/tests/tools/d3TestAction.php @@ -0,0 +1,18 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DataWizard\tests\unit\Application\Controller\Admin; + +use D3\DataWizard\Application\Controller\Admin\d3ActionWizard; +use D3\DataWizard\Application\Model\Configuration; +use D3\DataWizard\Application\Model\Exceptions\DebugException; +use D3\DataWizard\tests\tools\d3TestAction; +use OxidEsales\Eshop\Core\Config; +use OxidEsales\Eshop\Core\Registry; +use OxidEsales\Eshop\Core\Request; +use PHPUnit\Framework\MockObject\MockObject; +use ReflectionException; + +class d3ActionWizardTest extends d3AdminControllerTest +{ + /** @var d3ActionWizard */ + protected $_oController; + + public function setUp() : void + { + parent::setUp(); + + $this->_oController = oxNew(d3ActionWizard::class); + } + + /** + * @covers d3ActionWizard::getGroups() + * @test + * @throws ReflectionException + */ + public function canGetGroups() + { + $expected = ['expected' => 'array']; + /** @var Configuration|MockObject $configurationMock */ + $configurationMock = $this->getMockBuilder(Configuration::class) + ->onlyMethods(['getActionGroups']) + ->getMock(); + $configurationMock->expects($this->atLeastOnce())->method('getActionGroups')->willReturn($expected); + + $this->setValue($this->_oController, 'configuration', $configurationMock); + + $this->assertSame( + $expected, + $this->callMethod( + $this->_oController, + 'getGroups' + ) + ); + } + + /** + * @covers d3ActionWizard::getGroupTasks() + * @test + * @throws ReflectionException + * @dataProvider canGetGroupTasksDataProvider + */ + public function canGetGroupTasks($argument) + { + $expected = ['expected' => 'array']; + /** @var Configuration|MockObject $configurationMock */ + $configurationMock = $this->getMockBuilder(Configuration::class) + ->onlyMethods(['getActionsByGroup']) + ->getMock(); + $configurationMock->expects($this->atLeastOnce())->method('getActionsByGroup')->with($argument)->willReturn($expected); + + $this->setValue($this->_oController, 'configuration', $configurationMock); + + $this->assertSame( + $expected, + $this->callMethod( + $this->_oController, + 'getGroupTasks', + [$argument] + ) + ); + } + + /** + * @return array + */ + public function canGetGroupTasksDataProvider(): array + { + return [ + ['test1'], + ['test2'] + ]; + } + + /** + * @covers d3ActionWizard::execute() + * @test + * @throws ReflectionException + * @dataProvider executePassDataProvider + */ + public function executePass($blDebug) + { + /** @var Request|MockObject $requestMock */ + $requestMock = $this->getMockBuilder(get_class(Registry::getRequest())) + ->onlyMethods(['getRequestEscapedParameter']) + ->getMock(); + $requestMock->expects($this->atLeastOnce())->method('getRequestEscapedParameter')->with('taskid')->willReturn('testTaskId'); + Registry::set(Request::class, $requestMock); + + /** @var d3TestAction|MockObject $actionMock */ + $actionMock = $this->getMockBuilder(d3TestAction::class) + ->onlyMethods([ + 'getQuery', + 'run' + ]) + ->getMock(); + $actionMock->expects($this->atLeastOnce())->method('getQuery')->willReturn(['SELECT 1', ['1']]); + $actionMock->expects($this->exactly((int) !$blDebug))->method('run')->willReturn(true); + + /** @var Configuration|MockObject $configurationMock */ + $configurationMock = $this->getMockBuilder(Configuration::class) + ->onlyMethods(['getActionById']) + ->disableOriginalConstructor() + ->getMock(); + $configurationMock->expects($this->atLeastOnce())->method('getActionById')->with('testTaskId')->willReturn($actionMock); + $this->setValue($this->_oController, 'configuration', $configurationMock); + + /** @var Config|MockObject $configMock */ + $configMock = $this->getMockBuilder(Config::class) + ->onlyMethods(['getConfigParam']) + ->getMock(); + $configMock->expects($this->atLeastOnce())->method('getConfigParam')->willReturn($blDebug); + Registry::set(Config::class, $configMock); + + if ($blDebug) { + $this->expectException(DebugException::class); + } + + $this->callMethod( + $this->_oController, + 'execute' + ); + } + + /** + * @return array + */ + public function executePassDataProvider(): array + { + return [ + 'no debug' => [false], + 'debug' => [true], + ]; + } +} \ No newline at end of file diff --git a/tests/unit/Application/Controller/Admin/d3AdminControllerTest.php b/tests/unit/Application/Controller/Admin/d3AdminControllerTest.php new file mode 100644 index 0000000..7be5e8e --- /dev/null +++ b/tests/unit/Application/Controller/Admin/d3AdminControllerTest.php @@ -0,0 +1,238 @@ + + * @link https://www.oxidmodule.com + */ + +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\DataWizardException; +use D3\DataWizard\Application\Model\Exceptions\DebugException; +use D3\DataWizard\tests\tools\d3TestAction; +use D3\ModCfg\Tests\unit\d3ModCfgUnitTestCase; +use Doctrine\DBAL\DBALException; +use OxidEsales\Eshop\Core\Config; +use OxidEsales\Eshop\Core\Exception\DatabaseErrorException; +use OxidEsales\Eshop\Core\Registry; +use OxidEsales\Eshop\Core\Request; +use OxidEsales\Eshop\Core\UtilsView; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; +use ReflectionException; + +abstract class d3AdminControllerTest extends d3ModCfgUnitTestCase +{ + /** @var d3ActionWizard|d3ExportWizard */ + protected $_oController; + + public function tearDown() : void + { + parent::tearDown(); + + unset($this->_oController); + } + + /** + * @covers \D3\DataWizard\Application\Controller\Admin\d3ActionWizard::__construct + * @covers \D3\DataWizard\Application\Controller\Admin\d3ExportWizard::__construct + * @test + * @throws ReflectionException + */ + public function testConstructor() + { + $this->setValue($this->_oController, 'configuration', null); + + $this->callMethod( + $this->_oController, + '__construct' + ); + + $this->assertInstanceOf( + Configuration::class, + $this->getValue( + $this->_oController, + 'configuration' + ) + ); + } + + /** + * @covers d3ActionWizard::runTask() + * @test + * @throws ReflectionException + */ + public function runTaskPass() + { + /** @var d3ActionWizard|MockObject $controllerMock */ + $controllerMock = $this->getMockBuilder(d3ActionWizard::class) + ->onlyMethods(['execute']) + ->getMock(); + $controllerMock->expects($this->once())->method('execute')->willReturn(true); + + $this->_oController = $controllerMock; + + $this->callMethod( + $this->_oController, + 'runTask' + ); + } + + /** + * @covers d3ActionWizard::runTask() + * @test + * @param $exceptionClass + * @throws ReflectionException + * @dataProvider runTaskFailedDataProvider + */ + public function runTaskFailed($exceptionClass) + { + /** @var DataWizardException|DBALException|DatabaseErrorException|MockObject $exceptionMock */ + $exceptionMock = $this->getMockBuilder($exceptionClass) + ->disableOriginalConstructor() + ->getMock(); + $this->setValue($exceptionMock, 'message', 'exc_msg'); + + /** @var d3ActionWizard|MockObject $controllerMock */ + $controllerMock = $this->getMockBuilder(d3ActionWizard::class) + ->onlyMethods(['execute']) + ->getMock(); + $controllerMock->expects($this->once())->method('execute')->willThrowException($exceptionMock); + + /** @var LoggerInterface|MockObject $loggerMock */ + $loggerMock = $this->getMockBuilder(get_class(Registry::getLogger())) + ->onlyMethods(['error']) + ->disableOriginalConstructor() + ->getMock(); + $loggerMock->expects($this->atLeastOnce())->method('error')->with('exc_msg')->willReturn(true); + Registry::set('logger', $loggerMock); + + /** @var UtilsView|MockObject $utilsViewMock */ + $utilsViewMock = $this->getMockBuilder(get_class(Registry::getUtilsView())) + ->onlyMethods(['addErrorToDisplay']) + ->getMock(); + $utilsViewMock->expects($this->atLeastOnce())->method('addErrorToDisplay')->with($exceptionMock)->willReturn(true); + Registry::set(UtilsView::class, $utilsViewMock); + + $this->_oController = $controllerMock; + + $this->callMethod( + $this->_oController, + 'runTask' + ); + } + + /** + * @return \string[][] + */ + public function runTaskFailedDataProvider(): array + { + return [ + [DataWizardException::class], + [DBALException::class], + [DatabaseErrorException::class], + ]; + } + + /** + * @covers d3ActionWizard::execute() + * @test + * @throws ReflectionException + * @dataProvider executePassDataProvider + */ + public function executePass($blDebug) + { + /** @var Request|MockObject $requestMock */ + $requestMock = $this->getMockBuilder(get_class(Registry::getRequest())) + ->onlyMethods(['getRequestEscapedParameter']) + ->getMock(); + $requestMock->expects($this->atLeastOnce())->method('getRequestEscapedParameter')->with('taskid')->willReturn('testTaskId'); + Registry::set(Request::class, $requestMock); + + /** @var d3TestAction|MockObject $actionMock */ + $actionMock = $this->getMockBuilder(d3TestAction::class) + ->onlyMethods([ + 'getQuery', + 'run' + ]) + ->getMock(); + $actionMock->expects($this->atLeastOnce())->method('getQuery')->willReturn(['SELECT 1', ['1']]); + $actionMock->expects($this->exactly((int) !$blDebug))->method('run')->willReturn(true); + + /** @var Configuration|MockObject $configurationMock */ + $configurationMock = $this->getMockBuilder(Configuration::class) + ->onlyMethods(['getActionById']) + ->disableOriginalConstructor() + ->getMock(); + $configurationMock->expects($this->atLeastOnce())->method('getActionById')->with('testTaskId')->willReturn($actionMock); + $this->setValue($this->_oController, 'configuration', $configurationMock); + + /** @var Config|MockObject $configMock */ + $configMock = $this->getMockBuilder(Config::class) + ->onlyMethods(['getConfigParam']) + ->getMock(); + $configMock->expects($this->atLeastOnce())->method('getConfigParam')->willReturn($blDebug); + Registry::set(Config::class, $configMock); + + if ($blDebug) { + $this->expectException(DebugException::class); + } + + $this->callMethod( + $this->_oController, + 'execute' + ); + } + + /** + * @return array + */ + public function executePassDataProvider(): array + { + return [ + 'no debug' => [false], + 'debug' => [true], + ]; + } + + /** + * @covers d3ActionWizard::getUserMessages() + * @test + * @throws ReflectionException + */ + public function canGetUserMessages() + { + $this->assertNull( + $this->callMethod( + $this->_oController, + 'getUserMessages' + ) + ); + } + + /** + * @covers d3ActionWizard::getHelpURL() + * @test + * @throws ReflectionException + */ + public function canGetHelpUrl() + { + $this->assertNull( + $this->callMethod( + $this->_oController, + 'getHelpURL' + ) + ); + } +} \ No newline at end of file diff --git a/tests/unit/Application/Controller/Admin/d3ExportWizardTest.php b/tests/unit/Application/Controller/Admin/d3ExportWizardTest.php new file mode 100644 index 0000000..678ef39 --- /dev/null +++ b/tests/unit/Application/Controller/Admin/d3ExportWizardTest.php @@ -0,0 +1,168 @@ + + * @link https://www.oxidmodule.com + */ + +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; +use D3\DataWizard\tests\tools\d3TestAction; +use D3\DataWizard\tests\tools\d3TestExport; +use OxidEsales\Eshop\Core\Config; +use OxidEsales\Eshop\Core\Registry; +use OxidEsales\Eshop\Core\Request; +use PHPUnit\Framework\MockObject\MockObject; +use ReflectionException; + +class d3ExportWizardTest extends d3AdminControllerTest +{ + /** @var d3ExportWizard */ + protected $_oController; + + public function setUp() : void + { + parent::setUp(); + + $this->_oController = oxNew(d3ExportWizard::class); + } + + /** + * @covers d3ActionWizard::getGroups() + * @test + * @throws ReflectionException + */ + public function canGetGroups() + { + $expected = ['expected' => 'array']; + /** @var Configuration|MockObject $configurationMock */ + $configurationMock = $this->getMockBuilder(Configuration::class) + ->onlyMethods(['getExportGroups']) + ->getMock(); + $configurationMock->expects($this->atLeastOnce())->method('getExportGroups')->willReturn($expected); + + $this->setValue($this->_oController, 'configuration', $configurationMock); + + $this->assertSame( + $expected, + $this->callMethod( + $this->_oController, + 'getGroups' + ) + ); + } + + /** + * @covers d3ActionWizard::getGroupTasks() + * @test + * @throws ReflectionException + * @dataProvider canGetGroupTasksDataProvider + */ + public function canGetGroupTasks($argument) + { + $expected = ['expected' => 'array']; + /** @var Configuration|MockObject $configurationMock */ + $configurationMock = $this->getMockBuilder(Configuration::class) + ->onlyMethods(['getExportsByGroup']) + ->getMock(); + $configurationMock->expects($this->atLeastOnce())->method('getExportsByGroup')->with($argument)->willReturn($expected); + + $this->setValue($this->_oController, 'configuration', $configurationMock); + + $this->assertSame( + $expected, + $this->callMethod( + $this->_oController, + 'getGroupTasks', + [$argument] + ) + ); + } + + /** + * @return array + */ + public function canGetGroupTasksDataProvider(): array + { + return [ + ['test1'], + ['test2'] + ]; + } + + /** + * @covers d3ActionWizard::execute() + * @test + * @throws ReflectionException + * @dataProvider executePassDataProvider + */ + public function executePass($blDebug) + { + /** @var Request|MockObject $requestMock */ + $requestMock = $this->getMockBuilder(get_class(Registry::getRequest())) + ->onlyMethods(['getRequestEscapedParameter']) + ->getMock(); + + $requestMock->expects($this->exactly($blDebug ? 1 : 2))->method('getRequestEscapedParameter')->withConsecutive( + ['taskid'], ['format'] + )->willReturnOnConsecutiveCalls('testTaskId', 'CSV'); + Registry::set(Request::class, $requestMock); + + /** @var d3TestAction|MockObject $exportMock */ + $exportMock = $this->getMockBuilder(d3TestExport::class) + ->onlyMethods([ + 'getQuery', + 'run' + ]) + ->getMock(); + $exportMock->expects($this->atLeastOnce())->method('getQuery')->willReturn(['SELECT 1', ['1']]); + $exportMock->expects($this->exactly((int) !$blDebug))->method('run')->willReturn(''); + + /** @var Configuration|MockObject $configurationMock */ + $configurationMock = $this->getMockBuilder(Configuration::class) + ->onlyMethods(['getExportById']) + ->disableOriginalConstructor() + ->getMock(); + $configurationMock->expects($this->atLeastOnce())->method('getExportById')->with('testTaskId')->willReturn($exportMock); + $this->setValue($this->_oController, 'configuration', $configurationMock); + + /** @var Config|MockObject $configMock */ + $configMock = $this->getMockBuilder(Config::class) + ->onlyMethods(['getConfigParam']) + ->getMock(); + $configMock->expects($this->atLeastOnce())->method('getConfigParam')->willReturn($blDebug); + Registry::set(Config::class, $configMock); + + if ($blDebug) { + $this->expectException(DebugException::class); + } + + $this->callMethod( + $this->_oController, + 'execute' + ); + } + + /** + * @return array + */ + public function executePassDataProvider(): array + { + return [ + 'no debug' => [false], + 'debug' => [true], + ]; + } +} \ No newline at end of file