Skip to content

Commit

Permalink
[FEATURE] Add command controller to create test data (#1297)
Browse files Browse the repository at this point in the history
Fixes #1120
  • Loading branch information
kanow authored Dec 21, 2024
1 parent 68eb2e1 commit 565666b
Show file tree
Hide file tree
Showing 12 changed files with 279 additions and 0 deletions.
83 changes: 83 additions & 0 deletions Classes/Command/CreateTestDataCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

declare(strict_types=1);

namespace TTN\Tea\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\ReferenceIndex;
use TYPO3\CMS\Core\Utility\GeneralUtility;

/*
* Command to create test data for the tea extension.
*/
final class CreateTestDataCommand extends Command
{
/**
* @var list<array{title: non-empty-string, description: non-empty-string, sys_language_uid: int<0, max>}>
*/
protected array $teaData = [
[
'title' => 'Darjeeling',
'description' => 'I love that tea!',
'sys_language_uid' => 0,
],
[
'title' => 'Earl Grey',
'description' => 'A nice tea!',
'sys_language_uid' => 0,
],
];

protected function configure(): void
{
$this
->setHelp('Create test data for the tea extension in an already existing page (sysfolder).')
->addArgument(
'pageUid',
InputArgument::REQUIRED,
'Existing sysfolder page id.'
)
->addOption(
'delete-data-before',
'd',
InputOption::VALUE_NONE,
'Delete all tea data in the defined pid before creating new data.'
);
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$pageUid = $input->getArgument('pageUid') ?? 0;
\assert(\is_int($pageUid));
$deleteDataBefore = $input->getOption('delete-data-before') ?? false;
\assert(\is_bool($deleteDataBefore));
$table = 'tx_tea_domain_model_tea';
$connectionForTable = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);

if ($deleteDataBefore) {
$query = $connectionForTable;
$query->delete($table, ['pid' => $pageUid], [Connection::PARAM_INT]);
$output->writeln(sprintf('Existing data in page %s deleted.', $pageUid));
}

$query = $connectionForTable;
foreach ($this->teaData as $item) {
$item = ['pid' => $pageUid, 'title' => $item['title'], 'description' => $item['description']];
$query->insert($table, $item);
}
$output->writeln(\sprintf('Test data in page %s created.', $pageUid));

$referenceIndex = GeneralUtility::makeInstance(ReferenceIndex::class);
$referenceIndex->updateIndex(false);
$output->writeln('Reference index updated.');

return Command::SUCCESS;
}
}
11 changes: 11 additions & 0 deletions Configuration/Services.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use TTN\Tea\Command\CreateTestDataCommand;

return static function (ContainerConfigurator $containerConfigurator) {
$services = $containerConfigurator->services()
->defaults()
Expand All @@ -12,4 +14,13 @@

$services->load('TTN\\Tea\\', '../Classes/*')
->exclude('../Classes/Domain/Model/*');

$services->set(CreateTestDataCommand::class)
->tag(
'console.command',
[
'command' => 'tea:create-test-data',
'description' => 'Create test data in existing sysfolder',
]
);
};
28 changes: 28 additions & 0 deletions Documentation/CommandController.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.. include:: /Includes.rst.txt

.. _command-controller:

==================
Command Controller
==================

The "tea" extension comes with a CommandController that can be used for the
automatic creation of test data. It also serves to illustrate how data can be
created in the database using a command controller.

You must set a page id as argument. Therefore it's necessary to create an
sysfolder before.

You can add option `-d` to delete already existing data.


.. code-block:: bash
vendor/bin/typo3 tea:create-test-data 3
.. seealso::

For further details to Console Commands read the
:ref:`Creating a basic command <t3coreapi:console-command-tutorial-create>`
tutorial.
1 change: 1 addition & 0 deletions Documentation/Index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ continuous integration.
ReleaseBranchingStrategy
Environment
DependencyManager
CommandController
Running
ContinuousIntegration
Documentation
Expand Down
124 changes: 124 additions & 0 deletions Tests/Functional/Command/CreateTestDataCommandTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<?php

declare(strict_types=1);

namespace TTN\Tea\Tests\Functional\Command;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Tester\CommandTester;
use TTN\Tea\Command\CreateTestDataCommand;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;

/**
* @covers \TTN\Tea\Command\CreateTestDataCommand
*/
final class CreateTestDataCommandTest extends FunctionalTestCase
{
/**
* @var non-empty-string
*/
private const COMMAND_NAME = 'tea:create-test-data';

protected array $testExtensionsToLoad = ['ttn/tea'];

private CreateTestDataCommand $subject;

private CommandTester $commandTester;

protected function setUp(): void
{
parent::setUp();
$this->importCSVDataSet(__DIR__ . '/Fixtures/Database/Pages.csv');
$this->subject = new CreateTestDataCommand(self::COMMAND_NAME);
$application = new Application();
$application->add($this->subject);

$command = $application->find('tea:create-test-data');
$this->commandTester = new CommandTester($command);
}

/**
* @test
*/
public function isConsoleCommand(): void
{
self::assertInstanceOf(Command::class, $this->subject);
}

/**
* @test
*/
public function hasDescription(): void
{
$expected = 'Create test data for the tea extension in an already existing page (sysfolder).';
self::assertSame($expected, $this->subject->getHelp());
}

/**
* @test
*/
public function hasHelpText(): void
{
$expected = 'Create test data for the tea extension in an already existing page (sysfolder).';
self::assertSame($expected, $this->subject->getHelp());
}

/**
* @test
*/
public function runReturnsSuccessStatus(): void
{
$result = $this->commandTester->execute(
[
'pageUid' => 1,
],
);

self::assertSame(Command::SUCCESS, $result);
}

/**
* @test
*/
public function createsTestData(): void
{
$this->commandTester->execute([
'pageUid' => 1,
]);

$this->assertCSVDataSet(__DIR__ . '/Fixtures/Database/Teas.csv');
}

/**
* @test
*/
public function deletesExistingDataOnGivenPidBeforeCreatingNewData(): void
{
$this->importCSVDataSet(__DIR__ . '/Fixtures/Database/ExistingTeas.csv');
$this->commandTester->execute(
[
'pageUid' => 1,
'--delete-data-before' => true,
]
);

$this->assertCSVDataSet(__DIR__ . '/Fixtures/Database/TeasAfterDelete.csv');
}

/**
* @test
*/
public function doesNotDeleteDataOnOtherPid(): void
{
$this->importCSVDataSet(__DIR__ . '/Fixtures/Database/OtherExistingTeas.csv');
$this->commandTester->execute(
[
'pageUid' => 1,
'--delete-data-before' => true,
]
);

$this->assertCSVDataSet(__DIR__ . '/Fixtures/Database/TeasAfterDeleteOtherExistingTeas.csv');
}
}
4 changes: 4 additions & 0 deletions Tests/Functional/Command/Fixtures/Database/ExistingTeas.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"tx_tea_domain_model_tea"
,"uid","pid","title","description","deleted"
,1,1,"Darjeeling","Which already existed in the system",0
,2,1,"Earl Grey","Which already existed in the system",0
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"tx_tea_domain_model_tea"
,"uid","pid","title","description","deleted"
,3,1,"Darjeeling","Exists and should be deleted","0"
,4,1,"Earl Grey","Exists and should be deleted","0"
,1,2,"Darjeeling","Which already existed in the system",0
,2,2,"Earl Grey","Which already existed in the system",0
4 changes: 4 additions & 0 deletions Tests/Functional/Command/Fixtures/Database/Pages.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"pages",,,,,,,,,
,"uid","pid","sorting","deleted","t3_origuid","title",,,
,1,0,256,0,0,"Tea data",,,
,2,0,512,0,0,"Other tea data",,,
4 changes: 4 additions & 0 deletions Tests/Functional/Command/Fixtures/Database/Teas.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"tx_tea_domain_model_tea"
,"uid","pid","title","description","deleted"
,1,1,"Darjeeling","I love that tea!",0
,2,1,"Earl Grey","A nice tea!",0
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"tx_tea_domain_model_tea"
,"pid","title","description","deleted"
,1,"Darjeeling","I love that tea!",0
,1,"Earl Grey","A nice tea!",0
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"tx_tea_domain_model_tea"
,"pid","title","description","deleted"
,1,"Darjeeling","I love that tea!",0
,1,"Earl Grey","A nice tea!",0
,2,"Darjeeling","Which already existed in the system",0
,2,"Earl Grey","Which already existed in the system",0
4 changes: 4 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,7 @@ parameters:
- '$_FILES'
- '$_SERVER'
message: 'Use PSR-7 API instead'
ignoreErrors:
-
message: '#Out of 1 possible constant types#'
path: Tests/Functional/Command/CreateTestDataCommandTest.php

0 comments on commit 565666b

Please sign in to comment.