added project importer and grandtotal converter (#1468)
This commit is contained in:
@@ -10,16 +10,12 @@
|
||||
namespace App\Tests\Command;
|
||||
|
||||
use App\Command\ImportCustomerCommand;
|
||||
use App\Configuration\FormConfiguration;
|
||||
use App\Repository\CustomerRepository;
|
||||
use App\Repository\ProjectRepository;
|
||||
use App\Repository\TeamRepository;
|
||||
use App\Repository\UserRepository;
|
||||
use App\Importer\ImporterService;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
/**
|
||||
* @covers \App\Command\ImportCustomerCommand
|
||||
* @group integration
|
||||
*/
|
||||
class ImportCustomerCommandTest extends KernelTestCase
|
||||
@@ -33,14 +29,11 @@ class ImportCustomerCommandTest extends KernelTestCase
|
||||
{
|
||||
$kernel = self::bootKernel();
|
||||
$this->application = new Application($kernel);
|
||||
$container = self::$kernel->getContainer();
|
||||
|
||||
$customers = $this->createMock(CustomerRepository::class);
|
||||
$projects = $this->createMock(ProjectRepository::class);
|
||||
$teams = $this->createMock(TeamRepository::class);
|
||||
$users = $this->createMock(UserRepository::class);
|
||||
$configuration = $this->createMock(FormConfiguration::class);
|
||||
$importer = $container->get(ImporterService::class);
|
||||
|
||||
$this->application->add(new ImportCustomerCommand($customers, $projects, $teams, $users, $configuration));
|
||||
$this->application->add(new ImportCustomerCommand($importer));
|
||||
}
|
||||
|
||||
public function testCommandName()
|
||||
@@ -48,4 +41,184 @@ class ImportCustomerCommandTest extends KernelTestCase
|
||||
$command = $this->application->find('kimai:import:customer');
|
||||
self::assertInstanceOf(ImportCustomerCommand::class, $command);
|
||||
}
|
||||
|
||||
public function testImportWithMissingFile()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:customer');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/foo_bar.csv1'
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Kimai importer: Customers', $result);
|
||||
self::assertStringContainsString('[ERROR] File not existing or not readable', $result);
|
||||
self::assertStringContainsString('_data/foo_bar', $result);
|
||||
|
||||
self::assertEquals(2, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testDefaultImportWithUnknownReader()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:customer');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/customers2.csv',
|
||||
'--reader' => 'fooo',
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('[ERROR] Unknown import reader: fooo', $result);
|
||||
|
||||
self::assertEquals(1, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testImportWithUnknownImporter()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:customer');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/customers2.csv',
|
||||
'--importer' => 'fooo',
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('[ERROR] Unknown customer importer: fooo', $result);
|
||||
|
||||
self::assertEquals(1, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testDefaultImport()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:customer');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/customers.csv'
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Found 10 rows to process, converting now ...', $result);
|
||||
self::assertStringContainsString('Converted 10 customers, importing into Kimai now ...', $result);
|
||||
self::assertStringContainsString('[OK] Imported 9 customer', $result);
|
||||
self::assertStringContainsString('[OK] Updated 1 customer', $result);
|
||||
|
||||
self::assertEquals(0, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testDefaultImportSkipUpdate()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:customer');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/customers.csv',
|
||||
'--no-update' => true,
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Found 10 rows to process, converting now ...', $result);
|
||||
self::assertStringContainsString('Converted 10 customers, importing into Kimai now ...', $result);
|
||||
self::assertStringContainsString('[OK] Imported 9 customer', $result);
|
||||
self::assertStringContainsString('[OK] Skipped 1 existing customer', $result);
|
||||
|
||||
self::assertEquals(0, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testDefaultImportWithSemicolon()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:customer');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/customers2.csv',
|
||||
'--importer' => 'default',
|
||||
'--reader' => 'csv-semicolon',
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Found 10 rows to process, converting now ...', $result);
|
||||
self::assertStringContainsString('Converted 10 customers, importing into Kimai now ...', $result);
|
||||
self::assertStringContainsString('[OK] Imported 10 customer', $result);
|
||||
|
||||
self::assertEquals(0, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testGrandtotalImportWithInvalidCsvFile()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:customer');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/customers2.csv',
|
||||
'--importer' => 'grandtotal',
|
||||
'--reader' => 'csv-semicolon',
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Invalid row 1: Missing customer name', $result);
|
||||
self::assertStringContainsString('! [CAUTION] Not importing, previous 10 errors need to be fixed first.', $result);
|
||||
|
||||
self::assertEquals(3, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testGrandtotalImport()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:customer');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/grandtotal_en.csv',
|
||||
'--importer' => 'grandtotal',
|
||||
'--reader' => 'csv-semicolon',
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Found 1 rows to process, converting now ...', $result);
|
||||
self::assertStringContainsString('Converted 1 customers, importing into Kimai now ...', $result);
|
||||
self::assertStringContainsString('[OK] Imported 1 customer', $result);
|
||||
|
||||
self::assertEquals(0, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testGrandtotalImportGerman()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:customer');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/grandtotal_de.csv',
|
||||
'--importer' => 'grandtotal',
|
||||
'--reader' => 'csv-semicolon',
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Found 2 rows to process, converting now ...', $result);
|
||||
self::assertStringContainsString('Converted 2 customers, importing into Kimai now ...', $result);
|
||||
self::assertStringContainsString('[OK] Imported 1 customer', $result);
|
||||
self::assertStringContainsString('[OK] Updated 1 customer', $result);
|
||||
|
||||
self::assertEquals(0, $commandTester->getStatusCode());
|
||||
}
|
||||
}
|
||||
|
||||
250
tests/Command/ImportProjectCommandTest.php
Normal file
250
tests/Command/ImportProjectCommandTest.php
Normal file
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Command;
|
||||
|
||||
use App\Command\ImportProjectCommand;
|
||||
use App\Importer\ImporterService;
|
||||
use App\Repository\TeamRepository;
|
||||
use App\Repository\UserRepository;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
/**
|
||||
* @group integration
|
||||
*/
|
||||
class ImportProjectCommandTest extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
* @var Application
|
||||
*/
|
||||
protected $application;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$kernel = self::bootKernel();
|
||||
$this->application = new Application($kernel);
|
||||
$container = self::$kernel->getContainer();
|
||||
|
||||
$importer = $container->get(ImporterService::class);
|
||||
$teams = $this->createMock(TeamRepository::class);
|
||||
/** @var UserRepository $users */
|
||||
$users = $container->get(UserRepository::class);
|
||||
|
||||
$this->application->add(new ImportProjectCommand($importer, $teams, $users));
|
||||
}
|
||||
|
||||
public function testCommandName()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:project');
|
||||
self::assertInstanceOf(ImportProjectCommand::class, $command);
|
||||
}
|
||||
|
||||
public function testImportWithMissingFile()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:project');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/foo_bar.csv1'
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Kimai importer: Projects', $result);
|
||||
self::assertStringContainsString('[ERROR] File not existing or not readable', $result);
|
||||
self::assertStringContainsString('_data/foo_bar', $result);
|
||||
|
||||
self::assertEquals(2, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testDefaultImportWithUnknownReader()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:project');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/customers2.csv',
|
||||
'--reader' => 'fooo',
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('[ERROR] Unknown import reader: fooo', $result);
|
||||
|
||||
self::assertEquals(1, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testImportWithUnknownImporter()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:project');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/customers2.csv',
|
||||
'--importer' => 'grandtotal',
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('[ERROR] Unknown project importer: grandtotal', $result);
|
||||
|
||||
self::assertEquals(1, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testDefaultImport()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:project');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/projects.csv',
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Found 3 rows to process, converting now ...', $result);
|
||||
self::assertStringContainsString('Converted 3 projects, importing into Kimai now ...', $result);
|
||||
self::assertStringContainsString('[OK] Imported 2 projects', $result);
|
||||
self::assertStringContainsString('[OK] Updated 1 projects', $result);
|
||||
|
||||
self::assertEquals(0, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testDefaultImportSkipUpdate()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:project');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/projects.csv',
|
||||
'--no-update' => true,
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Found 3 rows to process, converting now ...', $result);
|
||||
self::assertStringContainsString('Converted 3 projects, importing into Kimai now ...', $result);
|
||||
self::assertStringContainsString('[OK] Imported 2 projects', $result);
|
||||
self::assertStringContainsString('[OK] Skipped 1 existing projects', $result);
|
||||
|
||||
self::assertEquals(0, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testDefaultImportWithInvalidCustomerMapping()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:project');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/projects_invalid.csv',
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Found 3 rows to process, converting now ...', $result);
|
||||
self::assertStringContainsString('[ERROR] Invalid row 2: Customer mismatch for project', $result);
|
||||
self::assertStringContainsString('[CAUTION] Not importing, previous 1 errors need to be fixed first.', $result);
|
||||
|
||||
self::assertEquals(3, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testDefaultImportWithSemicolon()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:project');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/projects2.csv',
|
||||
'--importer' => 'default',
|
||||
'--reader' => 'csv-semicolon',
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Found 39 rows to process, converting now ...', $result);
|
||||
self::assertStringContainsString('Converted 39 projects, importing into Kimai now ...', $result);
|
||||
self::assertStringContainsString('[OK] Imported 39 projects', $result);
|
||||
self::assertStringContainsString('[OK] Imported 10 customers', $result);
|
||||
|
||||
self::assertEquals(0, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testGrandtotalImportWithInvalidCsvFile()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:project');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/projects.csv',
|
||||
'--reader' => 'csv-semicolon',
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Invalid row 1: Missing customer name', $result);
|
||||
self::assertStringContainsString('! [CAUTION] Not importing, previous 3 errors need to be fixed first.', $result);
|
||||
|
||||
self::assertEquals(3, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testDefaultImportWithSemicolonAndTeamlead()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:project');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/projects2.csv',
|
||||
'--importer' => 'default',
|
||||
'--reader' => 'csv-semicolon',
|
||||
'--teamlead' => 'clara_customer',
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Found 39 rows to process, converting now ...', $result);
|
||||
self::assertStringContainsString('Converted 39 projects, importing into Kimai now ...', $result);
|
||||
self::assertStringContainsString('[OK] Imported 39 projects', $result);
|
||||
self::assertStringContainsString('[OK] Imported 10 customers', $result);
|
||||
self::assertStringContainsString('[OK] Created 39 teams', $result);
|
||||
|
||||
self::assertEquals(0, $commandTester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testDefaultImportWithSemicolonAndMissingTeamlead()
|
||||
{
|
||||
$command = $this->application->find('kimai:import:project');
|
||||
$commandTester = new CommandTester($command);
|
||||
$commandTester->setInputs(['no']);
|
||||
$commandTester->execute([
|
||||
'command' => $command->getName(),
|
||||
'file' => __DIR__ . '/../Importer/_data/projects2.csv',
|
||||
'--importer' => 'default',
|
||||
'--reader' => 'csv-semicolon',
|
||||
'--teamlead' => 'foobar',
|
||||
]);
|
||||
|
||||
$result = $commandTester->getDisplay();
|
||||
|
||||
self::assertStringContainsString('You requested to create empty teams for each project', $result);
|
||||
self::assertStringContainsString('Please create a user with the name (or email) foobar', $result);
|
||||
|
||||
self::assertEquals(3, $commandTester->getStatusCode());
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Tests\Command;
|
||||
|
||||
use App\Command\ImportTimesheetCommand;
|
||||
use App\Configuration\FormConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Repository\ActivityRepository;
|
||||
use App\Repository\CustomerRepository;
|
||||
use App\Repository\ProjectRepository;
|
||||
@@ -42,7 +42,7 @@ class ImportTimesheetCommandTest extends KernelTestCase
|
||||
$users = $this->createMock(UserRepository::class);
|
||||
$tagRepository = $this->createMock(TagRepository::class);
|
||||
$timesheets = $this->createMock(TimesheetRepository::class);
|
||||
$configuration = $this->createMock(FormConfiguration::class);
|
||||
$configuration = $this->createMock(SystemConfiguration::class);
|
||||
|
||||
$this->application->add(new ImportTimesheetCommand($customers, $projects, $activities, $users, $tagRepository, $timesheets, $configuration));
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ use PHPUnit\Framework\TestCase;
|
||||
/**
|
||||
* @covers \App\Configuration\FormConfiguration
|
||||
* @covers \App\Configuration\StringAccessibleConfigTrait
|
||||
* @group legacy
|
||||
*/
|
||||
class FormConfigurationTest extends TestCase
|
||||
{
|
||||
@@ -34,6 +35,13 @@ class FormConfigurationTest extends TestCase
|
||||
'currency' => 'GBP',
|
||||
'country' => 'FR',
|
||||
],
|
||||
'user' => [
|
||||
'timezone' => 'Europe/London',
|
||||
'currency' => 'GBP',
|
||||
'country' => 'FR',
|
||||
'language' => 'it',
|
||||
'theme' => 'blue',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -43,6 +51,11 @@ class FormConfigurationTest extends TestCase
|
||||
(new Configuration())->setName('defaults.customer.timezone')->setValue('Russia/Moscov'),
|
||||
(new Configuration())->setName('defaults.customer.currency')->setValue('USD'),
|
||||
(new Configuration())->setName('defaults.customer.country')->setValue('RU'),
|
||||
(new Configuration())->setName('defaults.user.timezone')->setValue('Russia/Moscov'),
|
||||
(new Configuration())->setName('defaults.user.currency')->setValue('USD'),
|
||||
(new Configuration())->setName('defaults.user.language')->setValue('RU'),
|
||||
(new Configuration())->setName('defaults.user.country')->setValue('RU'),
|
||||
(new Configuration())->setName('defaults.user.theme')->setValue('black'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -66,6 +79,11 @@ class FormConfigurationTest extends TestCase
|
||||
$this->assertEquals('Russia/Moscov', $sut->getCustomerDefaultTimezone());
|
||||
$this->assertEquals('USD', $sut->getCustomerDefaultCurrency());
|
||||
$this->assertEquals('RU', $sut->getCustomerDefaultCountry());
|
||||
$this->assertEquals('USD', $sut->getUserDefaultCurrency());
|
||||
$this->assertEquals('RU', $sut->getUserDefaultLanguage());
|
||||
$this->assertEquals('black', $sut->getUserDefaultTheme());
|
||||
$this->assertEquals('Russia/Moscov', $sut->getUserDefaultTimezone());
|
||||
$this->assertEquals('Russia/Moscov', $sut->offsetGet('defaults.user.timezone'));
|
||||
}
|
||||
|
||||
public function testDefaultWithMixedConfigs()
|
||||
|
||||
@@ -51,6 +51,12 @@ class SystemConfigurationTest extends TestCase
|
||||
'currency' => 'GBP',
|
||||
'country' => 'FR',
|
||||
],
|
||||
'user' => [
|
||||
'timezone' => 'foo/bar',
|
||||
'theme' => 'blue',
|
||||
'language' => 'IT',
|
||||
'currency' => 'USD',
|
||||
],
|
||||
],
|
||||
'calendar' => [
|
||||
'businessHours' => [
|
||||
@@ -164,4 +170,28 @@ class SystemConfigurationTest extends TestCase
|
||||
$sources = $sut->getCalendarGoogleSources();
|
||||
$this->assertEquals(2, \count($sources));
|
||||
}
|
||||
|
||||
public function testFormDefaultWithoutLoader()
|
||||
{
|
||||
$sut = $this->getSut($this->getDefaultSettings(), []);
|
||||
$this->assertEquals('Europe/London', $sut->getCustomerDefaultTimezone());
|
||||
$this->assertEquals('GBP', $sut->getCustomerDefaultCurrency());
|
||||
$this->assertEquals('FR', $sut->getCustomerDefaultCountry());
|
||||
$this->assertEquals('foo/bar', $sut->getUserDefaultTimezone());
|
||||
$this->assertEquals('blue', $sut->getUserDefaultTheme());
|
||||
$this->assertEquals('IT', $sut->getUserDefaultLanguage());
|
||||
$this->assertEquals('USD', $sut->getUserDefaultCurrency());
|
||||
}
|
||||
|
||||
public function testFormDefaultWithLoader()
|
||||
{
|
||||
$sut = $this->getSut($this->getDefaultSettings(), $this->getDefaultLoaderSettings());
|
||||
$this->assertEquals('Russia/Moscov', $sut->getCustomerDefaultTimezone());
|
||||
$this->assertEquals('RUB', $sut->getCustomerDefaultCurrency());
|
||||
$this->assertEquals('FR', $sut->getCustomerDefaultCountry());
|
||||
$this->assertEquals('foo/bar', $sut->getUserDefaultTimezone());
|
||||
$this->assertEquals('blue', $sut->getUserDefaultTheme());
|
||||
$this->assertEquals('IT', $sut->getUserDefaultLanguage());
|
||||
$this->assertEquals('USD', $sut->getUserDefaultCurrency());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ use App\Configuration\ConfigLoaderInterface;
|
||||
use App\Entity\Configuration;
|
||||
|
||||
/**
|
||||
* @covers \App\Configuration\FormConfiguration
|
||||
* @covers \App\Configuration\SystemConfiguration
|
||||
*/
|
||||
class TestConfigLoader implements ConfigLoaderInterface
|
||||
{
|
||||
|
||||
@@ -64,6 +64,11 @@ class CalendarControllerTest extends ControllerBaseTest
|
||||
protected function getDefaultSettings()
|
||||
{
|
||||
return [
|
||||
'defaults' => [
|
||||
'user' => [
|
||||
'language' => 'en'
|
||||
],
|
||||
],
|
||||
'timesheet' => [
|
||||
'default_begin' => '08:30:00',
|
||||
],
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace App\Tests\Controller;
|
||||
|
||||
use App\DataFixtures\UserFixtures;
|
||||
use App\Entity\User;
|
||||
use App\Repository\ConfigurationRepository;
|
||||
use App\Tests\KernelTestTrait;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
@@ -26,6 +27,15 @@ abstract class ControllerBaseTest extends WebTestCase
|
||||
|
||||
public const DEFAULT_LANGUAGE = 'en';
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
/** @var ConfigurationRepository $repository */
|
||||
$repository = static::$kernel->getContainer()->get(ConfigurationRepository::class);
|
||||
$repository->clearCache();
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
protected function getClientForAuthenticatedUser(string $role = User::ROLE_USER): HttpKernelBrowser
|
||||
{
|
||||
switch ($role) {
|
||||
|
||||
@@ -9,12 +9,10 @@
|
||||
|
||||
namespace App\Tests\Controller;
|
||||
|
||||
use App\Entity\Configuration;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Entity\TimesheetMeta;
|
||||
use App\Entity\User;
|
||||
use App\Form\Type\DateRangeType;
|
||||
use App\Repository\ConfigurationRepository;
|
||||
use App\Tests\DataFixtures\TimesheetFixtures;
|
||||
use App\Tests\Mocks\TimesheetTestMetaFieldSubscriberMock;
|
||||
|
||||
@@ -53,7 +51,6 @@ class TimesheetControllerTest extends ControllerBaseTest
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$start = new \DateTime('first day of this month');
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
$fixture = new TimesheetFixtures();
|
||||
$fixture->setAmount(5);
|
||||
$fixture->setAmountRunning(2);
|
||||
@@ -90,7 +87,6 @@ class TimesheetControllerTest extends ControllerBaseTest
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$start = new \DateTime('first day of this month');
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
$fixture = new TimesheetFixtures();
|
||||
$fixture->setAmount(5);
|
||||
$fixture->setUser($this->getUserByRole(User::ROLE_USER));
|
||||
@@ -127,7 +123,6 @@ class TimesheetControllerTest extends ControllerBaseTest
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser();
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
$fixture = new TimesheetFixtures();
|
||||
$fixture->setAmount(5);
|
||||
$fixture->setUser($this->getUserByRole(User::ROLE_USER));
|
||||
@@ -305,60 +300,54 @@ class TimesheetControllerTest extends ControllerBaseTest
|
||||
|
||||
public function testCreateActionWithFromAndToValuesTwiceFailsOnOverlappingRecord()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$this->request($client, '/timesheet/create?from=2018-08-02T20%3A00%3A00&to=2018-08-02T20%3A30%3A00');
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
|
||||
$this->assertAccessIsGranted($client, '/admin/system-config/');
|
||||
|
||||
$form = $client->getCrawler()->filter('form[name=timesheet_edit_form]')->form();
|
||||
$form = $client->getCrawler()->filter('form[name=system_configuration_form_timesheet]')->form();
|
||||
$client->submit($form, [
|
||||
'timesheet_edit_form' => [
|
||||
'hourlyRate' => 100,
|
||||
'project' => 1,
|
||||
'activity' => 1,
|
||||
'system_configuration_form_timesheet' => [
|
||||
'configuration' => [
|
||||
['name' => 'timesheet.mode', 'value' => 'default'],
|
||||
['name' => 'timesheet.active_entries.default_begin', 'value' => '08:00'],
|
||||
['name' => 'timesheet.rules.allow_future_times', 'value' => true],
|
||||
['name' => 'timesheet.rules.allow_overlapping_records', 'value' => false],
|
||||
['name' => 'timesheet.rules.lockdown_period_start', 'value' => null],
|
||||
['name' => 'timesheet.rules.lockdown_period_end', 'value' => null],
|
||||
['name' => 'timesheet.rules.lockdown_grace_period', 'value' => null],
|
||||
['name' => 'timesheet.active_entries.hard_limit', 'value' => 1],
|
||||
['name' => 'timesheet.active_entries.soft_limit', 'value' => 1],
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertIsRedirect($client, $this->createUrl('/timesheet/'));
|
||||
$client->followRedirect();
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
$this->assertHasFlashSuccess($client);
|
||||
$client = $this->getClientForAuthenticatedUser();
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
/** @var Timesheet $timesheet */
|
||||
$timesheet = $em->getRepository(Timesheet::class)->find(1);
|
||||
$this->assertInstanceOf(\DateTime::class, $timesheet->getBegin());
|
||||
$this->assertInstanceOf(\DateTime::class, $timesheet->getEnd());
|
||||
$this->assertEquals(50, $timesheet->getRate());
|
||||
$begin = new \DateTime('2018-08-02T20:00:00');
|
||||
$end = new \DateTime('2018-08-02T20:30:00');
|
||||
|
||||
$expected = new \DateTime('2018-08-02T20:00:00');
|
||||
$this->assertEquals($expected->format(\DateTime::ATOM), $timesheet->getBegin()->format(\DateTime::ATOM));
|
||||
$fixture = new TimesheetFixtures();
|
||||
$fixture->setCallback(function (Timesheet $timesheet) use ($begin, $end) {
|
||||
$timesheet->setBegin($begin);
|
||||
$timesheet->setEnd($end);
|
||||
});
|
||||
$fixture->setAmount(1);
|
||||
$fixture->setUser($this->getUserByRole(User::ROLE_USER));
|
||||
$this->importFixture($fixture);
|
||||
|
||||
$expected = new \DateTime('2018-08-02T20:30:00');
|
||||
$this->assertEquals($expected->format(\DateTime::ATOM), $timesheet->getEnd()->format(\DateTime::ATOM));
|
||||
|
||||
/** @var ConfigurationRepository $configurations */
|
||||
$configurations = $em->getRepository(Configuration::class);
|
||||
$config = new Configuration();
|
||||
$config->setName('timesheet.rules.allow_overlapping_records');
|
||||
$config->setValue(false);
|
||||
$configurations->saveConfiguration($config);
|
||||
|
||||
// create a second entry that is overlapping fails due to the changed config above
|
||||
// create a second entry that is overlapping - should fail due to the changed config above
|
||||
$this->assertHasValidationError(
|
||||
$client,
|
||||
'/timesheet/create?from=2018-08-02T20%3A02%3A00&to=2018-08-02T20%3A20%3A00',
|
||||
'form[name=timesheet_edit_form]',
|
||||
[
|
||||
'timesheet_edit_form' => [
|
||||
'hourlyRate' => 100,
|
||||
//'hourlyRate' => 100,
|
||||
'project' => 1,
|
||||
'activity' => 1,
|
||||
]
|
||||
],
|
||||
['#timesheet_edit_form_begin']
|
||||
);
|
||||
|
||||
$configurations->clearCache();
|
||||
}
|
||||
|
||||
public function testCreateActionWithBeginAndEndAndTagValues()
|
||||
@@ -401,7 +390,6 @@ class TimesheetControllerTest extends ControllerBaseTest
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser();
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
$fixture = new TimesheetFixtures();
|
||||
$fixture->setAmount(10);
|
||||
$fixture->setUser($this->getUserByRole(User::ROLE_USER));
|
||||
@@ -442,7 +430,6 @@ class TimesheetControllerTest extends ControllerBaseTest
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
$user = $this->getUserByRole(User::ROLE_USER);
|
||||
$fixture = new TimesheetFixtures();
|
||||
$fixture->setAmount(10);
|
||||
@@ -481,7 +468,6 @@ class TimesheetControllerTest extends ControllerBaseTest
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
$user = $this->getUserByRole(User::ROLE_SUPER_ADMIN);
|
||||
$fixture = new TimesheetFixtures();
|
||||
$fixture->setAmount(10);
|
||||
|
||||
156
tests/Customer/CustomerServiceTest.php
Normal file
156
tests/Customer/CustomerServiceTest.php
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Customer;
|
||||
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Customer\CustomerService;
|
||||
use App\Entity\Customer;
|
||||
use App\Event\CustomerCreateEvent;
|
||||
use App\Event\CustomerCreatePostEvent;
|
||||
use App\Event\CustomerCreatePreEvent;
|
||||
use App\Event\CustomerMetaDefinitionEvent;
|
||||
use App\Event\CustomerUpdatePostEvent;
|
||||
use App\Event\CustomerUpdatePreEvent;
|
||||
use App\Repository\CustomerRepository;
|
||||
use App\Validator\ValidationFailedException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Validator\ConstraintViolation;
|
||||
use Symfony\Component\Validator\ConstraintViolationList;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
/**
|
||||
* @covers \App\Customer\CustomerService
|
||||
*/
|
||||
class CustomerServiceTest extends TestCase
|
||||
{
|
||||
private function getSut(
|
||||
?EventDispatcherInterface $dispatcher = null,
|
||||
?ValidatorInterface $validator = null,
|
||||
?CustomerRepository $repository = null,
|
||||
?SystemConfiguration $configuration = null
|
||||
): CustomerService {
|
||||
if ($repository === null) {
|
||||
$repository = $this->createMock(CustomerRepository::class);
|
||||
}
|
||||
|
||||
if ($dispatcher === null) {
|
||||
$dispatcher = $this->createMock(EventDispatcherInterface::class);
|
||||
}
|
||||
|
||||
if ($validator === null) {
|
||||
$validator = $this->createMock(ValidatorInterface::class);
|
||||
$validator->method('validate')->willReturn(new ConstraintViolationList());
|
||||
}
|
||||
|
||||
if ($configuration === null) {
|
||||
$configuration = $this->createMock(SystemConfiguration::class);
|
||||
$configuration->method('getCustomerDefaultTimezone')->willReturn('Europe/Vienna');
|
||||
$configuration->method('getCustomerDefaultCountry')->willReturn('IN');
|
||||
$configuration->method('getCustomerDefaultCurrency')->willReturn('RUB');
|
||||
}
|
||||
|
||||
$service = new CustomerService($repository, $configuration, $validator, $dispatcher);
|
||||
|
||||
return $service;
|
||||
}
|
||||
|
||||
public function testCannotSavePersistedCustomerAsNew()
|
||||
{
|
||||
$Customer = $this->createMock(Customer::class);
|
||||
$Customer->expects($this->once())->method('getId')->willReturn(1);
|
||||
|
||||
$sut = $this->getSut();
|
||||
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Cannot create customer, already persisted');
|
||||
|
||||
$sut->saveNewCustomer($Customer);
|
||||
}
|
||||
|
||||
public function testSaveNewCustomerHasValidationError()
|
||||
{
|
||||
$constraints = new ConstraintViolationList();
|
||||
$constraints->add(new ConstraintViolation('toooo many tests', 'abc.def', [], '$root', 'begin', 4, null, null, null, '$cause'));
|
||||
|
||||
$validator = $this->createMock(ValidatorInterface::class);
|
||||
$validator->method('validate')->willReturn($constraints);
|
||||
|
||||
$sut = $this->getSut(null, $validator);
|
||||
|
||||
$this->expectException(ValidationFailedException::class);
|
||||
$this->expectExceptionMessage('Validation Failed');
|
||||
|
||||
$sut->saveNewCustomer(new Customer());
|
||||
}
|
||||
|
||||
public function testUpdateDispatchesEvents()
|
||||
{
|
||||
$Customer = $this->createMock(Customer::class);
|
||||
$Customer->method('getId')->willReturn(1);
|
||||
|
||||
$dispatcher = $this->createMock(EventDispatcherInterface::class);
|
||||
$dispatcher->expects($this->exactly(2))->method('dispatch')->willReturnCallback(function ($event) use ($Customer) {
|
||||
if ($event instanceof CustomerUpdatePostEvent) {
|
||||
self::assertSame($Customer, $event->getCustomer());
|
||||
} elseif ($event instanceof CustomerUpdatePreEvent) {
|
||||
self::assertSame($Customer, $event->getCustomer());
|
||||
} else {
|
||||
$this->fail('Invalid event received');
|
||||
}
|
||||
});
|
||||
|
||||
$sut = $this->getSut($dispatcher);
|
||||
|
||||
$sut->updateCustomer($Customer);
|
||||
}
|
||||
|
||||
public function testCreateNewCustomerDispatchesEvents()
|
||||
{
|
||||
$dispatcher = $this->createMock(EventDispatcherInterface::class);
|
||||
$dispatcher->expects($this->exactly(2))->method('dispatch')->willReturnCallback(function ($event) {
|
||||
if ($event instanceof CustomerMetaDefinitionEvent) {
|
||||
self::assertInstanceOf(Customer::class, $event->getEntity());
|
||||
} elseif ($event instanceof CustomerCreateEvent) {
|
||||
self::assertInstanceOf(Customer::class, $event->getCustomer());
|
||||
} else {
|
||||
$this->fail('Invalid event received');
|
||||
}
|
||||
});
|
||||
|
||||
$sut = $this->getSut($dispatcher);
|
||||
|
||||
$customer = $sut->createNewCustomer();
|
||||
|
||||
self::assertInstanceOf(Customer::class, $customer);
|
||||
self::assertEquals('Europe/Vienna', $customer->getTimezone());
|
||||
self::assertEquals('IN', $customer->getCountry());
|
||||
self::assertEquals('RUB', $customer->getCurrency());
|
||||
}
|
||||
|
||||
public function testSaveNewCustomerDispatchesEvents()
|
||||
{
|
||||
$dispatcher = $this->createMock(EventDispatcherInterface::class);
|
||||
$dispatcher->expects($this->exactly(2))->method('dispatch')->willReturnCallback(function ($event) {
|
||||
if ($event instanceof CustomerCreatePreEvent) {
|
||||
self::assertInstanceOf(Customer::class, $event->getCustomer());
|
||||
} elseif ($event instanceof CustomerCreatePostEvent) {
|
||||
self::assertInstanceOf(Customer::class, $event->getCustomer());
|
||||
} else {
|
||||
$this->fail('Invalid event received');
|
||||
}
|
||||
});
|
||||
|
||||
$sut = $this->getSut($dispatcher);
|
||||
|
||||
$Customer = new Customer();
|
||||
$sut->saveNewCustomer($Customer);
|
||||
}
|
||||
}
|
||||
@@ -253,7 +253,6 @@ class AppExtensionTest extends TestCase
|
||||
'kimai.i18n_domains' => []
|
||||
];
|
||||
|
||||
// nasty parameter, should be removed!!!
|
||||
$this->assertTrue($container->hasParameter('kimai.config'));
|
||||
|
||||
foreach ($expected as $key => $value) {
|
||||
|
||||
29
tests/Event/AbstractCustomerEventTest.php
Normal file
29
tests/Event/AbstractCustomerEventTest.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Event;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Event\AbstractCustomerEvent;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
abstract class AbstractCustomerEventTest extends TestCase
|
||||
{
|
||||
abstract protected function createCustomerEvent(Customer $customer): AbstractCustomerEvent;
|
||||
|
||||
public function testGetterAndSetter()
|
||||
{
|
||||
$customer = new Customer();
|
||||
$sut = $this->createCustomerEvent($customer);
|
||||
|
||||
self::assertInstanceOf(Event::class, $sut);
|
||||
self::assertSame($customer, $sut->getCustomer());
|
||||
}
|
||||
}
|
||||
26
tests/Event/CustomerCreateEventTest.php
Normal file
26
tests/Event/CustomerCreateEventTest.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Event;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Event\AbstractCustomerEvent;
|
||||
use App\Event\CustomerCreateEvent;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\AbstractCustomerEvent
|
||||
* @covers \App\Event\CustomerCreateEvent
|
||||
*/
|
||||
class CustomerCreateEventTest extends AbstractCustomerEventTest
|
||||
{
|
||||
protected function createCustomerEvent(Customer $customer): AbstractCustomerEvent
|
||||
{
|
||||
return new CustomerCreateEvent($customer);
|
||||
}
|
||||
}
|
||||
26
tests/Event/CustomerCreatePostEventTest.php
Normal file
26
tests/Event/CustomerCreatePostEventTest.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Event;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Event\AbstractCustomerEvent;
|
||||
use App\Event\CustomerCreatePostEvent;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\AbstractCustomerEvent
|
||||
* @covers \App\Event\CustomerCreatePostEvent
|
||||
*/
|
||||
class CustomerCreatePostEventTest extends AbstractCustomerEventTest
|
||||
{
|
||||
protected function createCustomerEvent(Customer $customer): AbstractCustomerEvent
|
||||
{
|
||||
return new CustomerCreatePostEvent($customer);
|
||||
}
|
||||
}
|
||||
26
tests/Event/CustomerCreatePreEventTest.php
Normal file
26
tests/Event/CustomerCreatePreEventTest.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Event;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Event\AbstractCustomerEvent;
|
||||
use App\Event\CustomerCreatePreEvent;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\AbstractCustomerEvent
|
||||
* @covers \App\Event\CustomerCreatePreEvent
|
||||
*/
|
||||
class CustomerCreatePreEventTest extends AbstractCustomerEventTest
|
||||
{
|
||||
protected function createCustomerEvent(Customer $customer): AbstractCustomerEvent
|
||||
{
|
||||
return new CustomerCreatePreEvent($customer);
|
||||
}
|
||||
}
|
||||
26
tests/Event/CustomerUpdatePostEventTest.php
Normal file
26
tests/Event/CustomerUpdatePostEventTest.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Event;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Event\AbstractCustomerEvent;
|
||||
use App\Event\CustomerUpdatePostEvent;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\AbstractCustomerEvent
|
||||
* @covers \App\Event\CustomerUpdatePostEvent
|
||||
*/
|
||||
class CustomerUpdatePostEventTest extends AbstractCustomerEventTest
|
||||
{
|
||||
protected function createCustomerEvent(Customer $customer): AbstractCustomerEvent
|
||||
{
|
||||
return new CustomerUpdatePostEvent($customer);
|
||||
}
|
||||
}
|
||||
26
tests/Event/CustomerUpdatePreEventTest.php
Normal file
26
tests/Event/CustomerUpdatePreEventTest.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Event;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Event\AbstractCustomerEvent;
|
||||
use App\Event\CustomerUpdatePreEvent;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\AbstractCustomerEvent
|
||||
* @covers \App\Event\CustomerUpdatePreEvent
|
||||
*/
|
||||
class CustomerUpdatePreEventTest extends AbstractCustomerEventTest
|
||||
{
|
||||
protected function createCustomerEvent(Customer $customer): AbstractCustomerEvent
|
||||
{
|
||||
return new CustomerUpdatePreEvent($customer);
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace App\Tests\EventSubscriber;
|
||||
|
||||
use App\Configuration\FormConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Entity\User;
|
||||
use App\Entity\UserPreference;
|
||||
use App\Event\PrepareUserEvent;
|
||||
@@ -91,7 +91,7 @@ class UserPreferenceSubscriberTest extends TestCase
|
||||
$authMock->expects($this->once())->method('isGranted')->willReturn($seeHourlyRate);
|
||||
|
||||
$eventMock = $this->createMock(EventDispatcherInterface::class);
|
||||
$formConfigMock = $this->createMock(FormConfiguration::class);
|
||||
$formConfigMock = $this->createMock(SystemConfiguration::class);
|
||||
|
||||
return new UserPreferenceSubscriber($eventMock, $authMock, $formConfigMock);
|
||||
}
|
||||
|
||||
62
tests/Importer/CsvReaderTest.php
Normal file
62
tests/Importer/CsvReaderTest.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Importer;
|
||||
|
||||
use App\Importer\CsvReader;
|
||||
use App\Importer\ImportNotFoundException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Importer\CsvReader
|
||||
*/
|
||||
class CsvReaderTest extends TestCase
|
||||
{
|
||||
public function testRead()
|
||||
{
|
||||
$sut = new CsvReader(';');
|
||||
$result = $sut->read(__DIR__ . '/_data/grandtotal_en.csv');
|
||||
$result = iterator_to_array($result);
|
||||
self::assertEquals([1 => [
|
||||
'Organization' => 'Keleo',
|
||||
'Department' => 'IT Abteilung',
|
||||
'Title' => 'Bc',
|
||||
'First name' => 'Kevin',
|
||||
'Middle name' => '',
|
||||
'Last name' => 'Papst',
|
||||
'E-Mail' => 'unknown@kimai.org',
|
||||
'Street' => 'Acme Street
|
||||
Downtown',
|
||||
'ZIP' => '1022',
|
||||
'City' => 'Vienna',
|
||||
'State' => '',
|
||||
'Salutation' => 'Sehr geehrter Herr',
|
||||
'Country' => 'DE',
|
||||
'Customer number' => '00001',
|
||||
'Tax-ID' => 'DE1234567890',
|
||||
'Note' => 'sakdjhfg laksjhdfasd f#asd<br>
|
||||
fas<br>
|
||||
dfasdfasdf<br>
|
||||
asdfasdfasdf',
|
||||
'IBAN' => '0987654321',
|
||||
'BIC' => '12345678',
|
||||
'SEPA Mandate ID' => '',
|
||||
'zusatz 1' => 'blub',
|
||||
'zusatz 2' => 'foo',
|
||||
]], $result);
|
||||
}
|
||||
|
||||
public function testReadNotFound()
|
||||
{
|
||||
$this->expectException(ImportNotFoundException::class);
|
||||
|
||||
$sut = new CsvReader(';');
|
||||
$sut->read(__DIR__ . '/_data/fffffoooooooooooo');
|
||||
}
|
||||
}
|
||||
90
tests/Importer/DefaultCustomerImporterTest.php
Normal file
90
tests/Importer/DefaultCustomerImporterTest.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Importer;
|
||||
|
||||
use App\Customer\CustomerService;
|
||||
use App\Entity\Customer;
|
||||
use App\Importer\DefaultCustomerImporter;
|
||||
use App\Importer\UnsupportedFormatException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Importer\DefaultCustomerImporter
|
||||
*/
|
||||
class DefaultCustomerImporterTest extends TestCase
|
||||
{
|
||||
private function getSut(int $count = 1): DefaultCustomerImporter
|
||||
{
|
||||
$customerService = $this->createMock(CustomerService::class);
|
||||
$customerService->expects($this->exactly($count))->method('createNewCustomer')->willReturnCallback(
|
||||
function () {
|
||||
return new Customer();
|
||||
}
|
||||
);
|
||||
|
||||
$sut = new DefaultCustomerImporter($customerService);
|
||||
|
||||
return $sut;
|
||||
}
|
||||
|
||||
private function getDefaultImport(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'Test customer',
|
||||
];
|
||||
}
|
||||
|
||||
private function prepareCustomer(array $values = []): Customer
|
||||
{
|
||||
$sut = $this->getSut();
|
||||
|
||||
$import = array_merge($this->getDefaultImport(), $values);
|
||||
|
||||
return $sut->convertEntryToCustomer($import);
|
||||
}
|
||||
|
||||
public function testImportMissingName()
|
||||
{
|
||||
$this->expectException(UnsupportedFormatException::class);
|
||||
$this->expectExceptionMessage('Missing customer name, expected in column: "Name"');
|
||||
|
||||
return $this->getSut(0)->convertEntryToCustomer(['sdfgsdfgsdfg' => 'sdfgsdfg']);
|
||||
}
|
||||
|
||||
public function testImport()
|
||||
{
|
||||
$customer = $this->prepareCustomer([]);
|
||||
self::assertEquals('Test customer', $customer->getName());
|
||||
}
|
||||
|
||||
public function testImportWithMultipleValues()
|
||||
{
|
||||
$customer = $this->prepareCustomer([
|
||||
'e mail' => 'test@example.com',
|
||||
'contact' => 'Foo Bar',
|
||||
'phone' => '0123 4567890',
|
||||
'mobile' => '111 354687',
|
||||
'fax' => '999 112233445566778899',
|
||||
'homepage' => 'www.example.com',
|
||||
'budget' => 1000.17,
|
||||
'time budget' => 3600,
|
||||
'meta.qwertz' => 'uztiuzgubhöklji7gl',
|
||||
]);
|
||||
self::assertEquals('Test customer', $customer->getName());
|
||||
self::assertEquals(1000.17, $customer->getBudget());
|
||||
self::assertEquals(3600, $customer->getTimeBudget());
|
||||
self::assertEquals('0123 4567890', $customer->getPhone());
|
||||
self::assertEquals('111 354687', $customer->getMobile());
|
||||
self::assertEquals('999 112233445566778899', $customer->getFax());
|
||||
self::assertEquals('www.example.com', $customer->getHomepage());
|
||||
self::assertEquals('www.example.com', $customer->getHomepage());
|
||||
self::assertEquals('uztiuzgubhöklji7gl', $customer->getMetaField('qwertz')->getValue());
|
||||
}
|
||||
}
|
||||
92
tests/Importer/DefaultProjectImporterTest.php
Normal file
92
tests/Importer/DefaultProjectImporterTest.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Importer;
|
||||
|
||||
use App\Customer\CustomerService;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Importer\DefaultProjectImporter;
|
||||
use App\Importer\UnsupportedFormatException;
|
||||
use App\Project\ProjectService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Importer\DefaultProjectImporter
|
||||
*/
|
||||
class DefaultProjectImporterTest extends TestCase
|
||||
{
|
||||
private function getSut(int $count = 1): DefaultProjectImporter
|
||||
{
|
||||
$projectService = $this->createMock(ProjectService::class);
|
||||
$projectService->expects($this->exactly($count))->method('createNewProject')->willReturnCallback(
|
||||
function (Customer $customer) {
|
||||
$customer->setTimezone('Europe/Paris');
|
||||
$project = new Project();
|
||||
$project->setCustomer($customer);
|
||||
|
||||
return $project;
|
||||
}
|
||||
);
|
||||
$customerService = $this->createMock(CustomerService::class);
|
||||
$customerService->expects($this->once())->method('createNewCustomer')->willReturn(new Customer());
|
||||
|
||||
$sut = new DefaultProjectImporter($projectService, $customerService);
|
||||
|
||||
return $sut;
|
||||
}
|
||||
|
||||
private function getDefaultImport(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'Test project',
|
||||
];
|
||||
}
|
||||
|
||||
private function prepareProject(array $values = []): Project
|
||||
{
|
||||
$sut = $this->getSut();
|
||||
|
||||
$import = array_merge($this->getDefaultImport(), $values);
|
||||
|
||||
return $sut->convertEntryToProject($import);
|
||||
}
|
||||
|
||||
public function testImportMissingName()
|
||||
{
|
||||
$this->expectException(UnsupportedFormatException::class);
|
||||
$this->expectExceptionMessage('Missing project name, expected in one of the columns: "Name", "Project , "Project Name", "Project-Name", "ProjectName"');
|
||||
|
||||
return $this->getSut(0)->convertEntryToProject(['CuStOMer-name' => 'Test CUSTOMER!']);
|
||||
}
|
||||
|
||||
public function testImport()
|
||||
{
|
||||
$project = $this->prepareProject(['CuStOMer-name' => 'Test CUSTOMER!']);
|
||||
self::assertEquals('Test project', $project->getName());
|
||||
self::assertEquals('Test CUSTOMER!', $project->getCustomer()->getName());
|
||||
}
|
||||
|
||||
public function testImportWithMultipleValues()
|
||||
{
|
||||
$project = $this->prepareProject([
|
||||
'CuStOMer-name' => 'Test CUSTOMER!',
|
||||
'order date' => '2020-07-21 17:28:54',
|
||||
'budget' => 1000.17,
|
||||
'time budget' => 3600,
|
||||
'meta.abcd' => 'uztiuzgubhöklji7gl',
|
||||
]);
|
||||
self::assertEquals('Test project', $project->getName());
|
||||
self::assertEquals('Test CUSTOMER!', $project->getCustomer()->getName());
|
||||
self::assertEquals(1000.17, $project->getBudget());
|
||||
self::assertEquals(3600, $project->getTimeBudget());
|
||||
self::assertEquals('2020-07-21T17:28:54+0200', $project->getOrderDate()->format(DATE_ISO8601));
|
||||
self::assertEquals('uztiuzgubhöklji7gl', $project->getMetaField('abcd')->getValue());
|
||||
}
|
||||
}
|
||||
26
tests/Importer/UnsupportedFormatExceptionTest.php
Normal file
26
tests/Importer/UnsupportedFormatExceptionTest.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Importer;
|
||||
|
||||
use App\Importer\UnsupportedFormatException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Importer\UnsupportedFormatException
|
||||
*/
|
||||
class UnsupportedFormatExceptionTest extends TestCase
|
||||
{
|
||||
public function testException()
|
||||
{
|
||||
$sut = new UnsupportedFormatException('test');
|
||||
self::assertEquals('test', $sut->getMessage());
|
||||
self::assertEquals(0, $sut->getCode());
|
||||
}
|
||||
}
|
||||
21
tests/Importer/_data/customers.csv
Normal file
21
tests/Importer/_data/customers.csv
Normal file
@@ -0,0 +1,21 @@
|
||||
ID,Name,Company name,Account,VAT-ID,Address,Contact,Email,Phone,Mobile,Fax,Homepage,Country,Currency,Timezone,Color,Visible,Comment,meta.some-id,meta.aaaaa
|
||||
8,Cassin LLC,Cassin Limited,C-63671629,AT U33445071,"7170 Scottie Motorway Suite 828
|
||||
Bridgettestad, MO 04855-1492",,,,,,,YE,EUR,Pacific/Pitcairn,#0d0403,1,Et placeat error esse rerum. Vitae optio sed et consequuntur est molestias. Sunt accusantium error qui deleniti nisi esse ab.,4,
|
||||
12,Gaylord-Kling,,C-81069873,AT U41003217,"999 Stracke Underpass Apt. 278
|
||||
West Celestine, NC 28716",,,,,,,HN,NPR,Europe/Kiev,#17dd05,1,Quam itaque illo aut omnis et. Explicabo molestias ut consequatur ad voluptatem illum ut. Voluptas enim ut vitae explicabo quis.,5,
|
||||
7,"Kub, Lowe and Daugherty",,C-08406910,AT U34327342,"3410 Ferry Ferry
|
||||
New Raphaelstad, MA 86907-3325",,,,,,,AS,HRK,America/Indiana/Knox,,1,"Architecto explicabo in iure debitis sunt sed. Eum animi ducimus adipisci quod voluptas reprehenderit molestias laudantium. Eos voluptatem non est officia molestias minus.",,
|
||||
6,"Nitzsche, Pfeffer and Dickens",,C-73111252,AT U92452965,"563 Alvis Plains Apt. 816
|
||||
Schowalterberg, MT 54542",,,,,,,MU,JMD,America/Port_of_Spain,#d14add,1,Itaque ipsa et expedita. Porro aut ab quo. Cumque quia blanditiis aut et vero in neque.,,
|
||||
2,"Smitham, Balistreri and Ondricka",,C-29186648,AT U94223297,"685 Waelchi Mountains
|
||||
Vanceport, AK 24274",,,,,,,BR,RUB,Atlantic/Faroe,#dd0c08,0,Architecto eum quaerat minus in sed quia impedit. Amet qui aliquam rerum provident optio. Voluptatem pariatur qui ad vitae corporis.,,
|
||||
13,Stanton PLC,,C-65852132,AT U66535044,"1927 O'Keefe Island
|
||||
North Carmella, MI 02061-1971",,,,,,,GD,GNF,America/Denver,#dd8a11,1,Iusto dignissimos quibusdam neque fuga ut et quam nobis. Non atque natus esse consequatur quod et est.,,
|
||||
4,"Toy, Larson and Schaefer",,C-07787515,AT U10587666,"760 Dare Highway Suite 023
|
||||
Port Vernice, IA 78379-6315",,,,,,,GL,USD,America/Grand_Turk,#191add,1,Perferendis enim nihil fugiat explicabo animi. Molestiae odit nemo enim quo id. Odio dolores aperiam repudiandae accusantium. Consequuntur illo doloremque veritatis minima animi maiores impedit.,,
|
||||
14,"Ullrich, Cruickshank and Emard",,C-89509630,AT U88402013,"4532 Hahn Squares Suite 090
|
||||
Port Eliezer, MI 45157",,,,,,,HT,GHS,Australia/Perth,#d2d6de,1,Culpa debitis repellendus quisquam dolor non consequuntur. Omnis doloribus dolore recusandae dolorem quia quidem. Odio veniam expedita quam. Et ut aut voluptatem veniam et necessitatibus.,1,
|
||||
11,"Ullrich, Satterfield and Homenick",,C-91464415,AT U72675057,"46915 Hartmann Crossroad Suite 125
|
||||
Antoniahaven, VT 39060-5021",,,,,,,MU,ZMW,Asia/Taipei,#00dddd,1,Temporibus aut numquam et fugiat. Laboriosam itaque quibusdam dolore sunt delectus est. Iusto reprehenderit mollitia iure tempora blanditiis praesentium quia quisquam.,3,
|
||||
9,"Test",,C-76507878,AT U18747846,"95027 Murray Walks Apt. 283
|
||||
New Kendrick, UT 09361-3329",,,,,,,SZ,LKR,Asia/Riyadh,,1,Nulla velit voluptatem atque molestias consequuntur sed. Ut et sunt quia quidem ea.,,
|
||||
|
21
tests/Importer/_data/customers2.csv
Normal file
21
tests/Importer/_data/customers2.csv
Normal file
@@ -0,0 +1,21 @@
|
||||
ID;Name;Company name;Account;VAT-ID;Address;Contact;Email;Phone;Mobile;Fax;Homepage;Country;Currency;Timezone;Color;Visible;Comment;meta.some-id;meta.aaaaa
|
||||
8;Cassin LLC;Cassin Limited;C-63671629;AT U33445071;"7170 Scottie Motorway Suite 828
|
||||
Bridgettestad, MO 04855-1492";;;;;;;YE;EUR;Pacific/Pitcairn;#0d0403;1;Et placeat error esse rerum. Vitae optio sed et consequuntur est molestias. Sunt accusantium error qui deleniti nisi esse ab.;4;
|
||||
12;Gaylord-Kling;;C-81069873;AT U41003217;"999 Stracke Underpass Apt. 278
|
||||
West Celestine, NC 28716";;;;;;;HN;NPR;Europe/Kiev;#17dd05;1;Quam itaque illo aut omnis et. Explicabo molestias ut consequatur ad voluptatem illum ut. Voluptas enim ut vitae explicabo quis.;5;
|
||||
7;Kub, Lowe and Daugherty;;C-08406910;AT U34327342;"3410 Ferry Ferry
|
||||
New Raphaelstad, MA 86907-3325";;;;;;;AS;HRK;America/Indiana/Knox;;1;Architecto explicabo in iure debitis sunt sed. Eum animi ducimus adipisci quod voluptas reprehenderit molestias laudantium. Eos voluptatem non est officia molestias minus.;;
|
||||
6;Nitzsche, Pfeffer and Dickens;;C-73111252;AT U92452965;"563 Alvis Plains Apt. 816
|
||||
Schowalterberg, MT 54542";;;;;;;MU;JMD;America/Port_of_Spain;#d14add;1;Itaque ipsa et expedita. Porro aut ab quo. Cumque quia blanditiis aut et vero in neque.;;
|
||||
2;Smitham, Balistreri and Ondricka;;C-29186648;AT U94223297;"685 Waelchi Mountains
|
||||
Vanceport, AK 24274";;;;;;;BR;RUB;Atlantic/Faroe;#dd0c08;0;Architecto eum quaerat minus in sed quia impedit. Amet qui aliquam rerum provident optio. Voluptatem pariatur qui ad vitae corporis.;;
|
||||
13;Stanton PLC;;C-65852132;AT U66535044;"1927 O'Keefe Island
|
||||
North Carmella, MI 02061-1971";;;;;;;GD;GNF;America/Denver;#dd8a11;1;Iusto dignissimos quibusdam neque fuga ut et quam nobis. Non atque natus esse consequatur quod et est.;;
|
||||
4;Toy, Larson and Schaefer;;C-07787515;AT U10587666;"760 Dare Highway Suite 023
|
||||
Port Vernice, IA 78379-6315";;;;;;;GL;USD;America/Grand_Turk;#191add;1;Perferendis enim nihil fugiat explicabo animi. Molestiae odit nemo enim quo id. Odio dolores aperiam repudiandae accusantium. Consequuntur illo doloremque veritatis minima animi maiores impedit.;;
|
||||
14;Ullrich, Cruickshank and Emard;;C-89509630;AT U88402013;"4532 Hahn Squares Suite 090
|
||||
Port Eliezer, MI 45157";;;;;;;HT;GHS;Australia/Perth;#d2d6de;1;Culpa debitis repellendus quisquam dolor non consequuntur. Omnis doloribus dolore recusandae dolorem quia quidem. Odio veniam expedita quam. Et ut aut voluptatem veniam et necessitatibus.;1;
|
||||
11;Ullrich, Satterfield and Homenick;;C-91464415;AT U72675057;"46915 Hartmann Crossroad Suite 125
|
||||
Antoniahaven, VT 39060-5021";;;;;;;MU;ZMW;Asia/Taipei;#00dddd;1;Temporibus aut numquam et fugiat. Laboriosam itaque quibusdam dolore sunt delectus est. Iusto reprehenderit mollitia iure tempora blanditiis praesentium quia quisquam.;3;
|
||||
9;Weber, Weber and Mosciski;;C-76507878;AT U18747846;"95027 Murray Walks Apt. 283
|
||||
New Kendrick, UT 09361-3329";;;;;;;SZ;LKR;Asia/Riyadh;;1;Nulla velit voluptatem atque molestias consequuntur sed. Ut et sunt quia quidem ea.;;
|
||||
|
11
tests/Importer/_data/grandtotal_de.csv
Normal file
11
tests/Importer/_data/grandtotal_de.csv
Normal file
@@ -0,0 +1,11 @@
|
||||
Firma;Abteilung;Titel;Vorname;Zweiter Vorname;Nachname;E-Mail;Straße;PLZ;Ort;Bundesland;Briefanrede;Land;Kundennummer;Umsatzsteuer-ID;Notiz;IBAN;BIC;SEPA Mandat ID;zusatz 1;zusatz 2
|
||||
Keleo;IT Abteilung;Bc;Kevin;;Papst;unknown@kimai.org;"Acme Street
|
||||
Downtown";1022;Vienna;;Sehr geehrter Herr;DE;00001;DE1234567890;"sakdjhfg laksjhdfasd f#asd<br>
|
||||
fas<br>
|
||||
dfasdfasdf<br>
|
||||
asdfasdfasdf";0987654321;12345678;;blub;foo
|
||||
Test;IT Abteilung;Bc;Kevin;;Tspap;unknown@kimai.org;"Acme Street 2
|
||||
Downtown";1022;Vienna;;Sehr geehrter Herr;DE;1;DE0987654321;"sakdjhfg laksjhdfasd f#asd<br>
|
||||
fas<br>
|
||||
dfasdfasdf<br>
|
||||
asdfasdfasdf";0987654321;12345678;;blub;foo
|
||||
|
6
tests/Importer/_data/grandtotal_en.csv
Normal file
6
tests/Importer/_data/grandtotal_en.csv
Normal file
@@ -0,0 +1,6 @@
|
||||
Organization;Department;Title;First name;Middle name;Last name;E-Mail;Street;ZIP;City;State;Salutation;Country;Customer number;Tax-ID;Note;IBAN;BIC;SEPA Mandate ID;zusatz 1;zusatz 2
|
||||
Keleo;IT Abteilung;Bc;Kevin;;Papst;unknown@kimai.org;"Acme Street
|
||||
Downtown";1022;Vienna;;Sehr geehrter Herr;DE;00001;DE1234567890;"sakdjhfg laksjhdfasd f#asd<br>
|
||||
fas<br>
|
||||
dfasdfasdf<br>
|
||||
asdfasdfasdf";0987654321;12345678;;blub;foo
|
||||
|
4
tests/Importer/_data/projects.csv
Normal file
4
tests/Importer/_data/projects.csv
Normal file
@@ -0,0 +1,4 @@
|
||||
ID,Name,Customer,Order number,Order date,Project Start,Project End,Color,Visible,Comment,Meta.zzzzz
|
||||
147,Multi-channelled 4thgeneration strategy,"Ullrich, Satterfield and Homenick",P-53400468,,,,,1,Amet non magni est. Cupiditate in magni adipisci nisi voluptatem sequi id. Accusamus sed alias enim et perferendis quo ut. Veniam voluptatem dicta dolores ut tenetur.,
|
||||
188,Test,Test,P-58944387,,,,,1,Facere architecto doloremque quae. Exercitationem ut velit molestiae alias dolore provident. Unde facere iste harum doloribus odio.,
|
||||
177,Multi-channelled transitional data-warehouse,Gaylord-Kling,P-17219648,,,,,1,Voluptatibus ipsa eos et maiores. Autem dolorem quia sit dolores. Qui adipisci aut aut eligendi voluptatibus. Libero voluptatem dignissimos rerum dignissimos aliquid consectetur.,
|
||||
|
40
tests/Importer/_data/projects2.csv
Normal file
40
tests/Importer/_data/projects2.csv
Normal file
@@ -0,0 +1,40 @@
|
||||
ID;Name;Customer;Order number;Order date;Project Start;Project End;Color;Visible;Comment;Meta.zzzzz
|
||||
147;Multi-channelled 4thgeneration strategy;Ullrich, Satterfield and Homenick;P-53400468;;;;;1;Amet non magni est. Cupiditate in magni adipisci nisi voluptatem sequi id. Accusamus sed alias enim et perferendis quo ut. Veniam voluptatem dicta dolores ut tenetur.;
|
||||
188;Multi-channelled background workforce;Stanton PLC;P-58944387;;;;;1;Facere architecto doloremque quae. Exercitationem ut velit molestiae alias dolore provident. Unde facere iste harum doloribus odio.;
|
||||
177;Multi-channelled transitional data-warehouse;Gaylord-Kling;P-17219648;;;;;1;Voluptatibus ipsa eos et maiores. Autem dolorem quia sit dolores. Qui adipisci aut aut eligendi voluptatibus. Libero voluptatem dignissimos rerum dignissimos aliquid consectetur.;
|
||||
154;Multi-channelled uniform focusgroup;Ullrich, Satterfield and Homenick;P-36133086;;;;;0;Similique eaque ea aut provident. Explicabo maiores consectetur est voluptatum expedita. Fugit cumque non iusto recusandae aspernatur.;
|
||||
165;Multi-channelled web-enabled adapter;Gaylord-Kling;P-27569344;;;;;1;Odit beatae nostrum quia laboriosam nam dolores. Rem similique voluptate facilis rerum omnis quia. Officiis a culpa vel aliquam sunt perspiciatis.;
|
||||
201;Multi-layered empowering neural-net;Ullrich, Cruickshank and Emard;P-96679708;;;;;1;Minus vero praesentium mollitia earum repellat quas eveniet eius. Et velit aut quia. Placeat non aperiam in iure eligendi harum porro.;
|
||||
27;Multi-layered uniform project;Smitham, Balistreri and Ondricka;P-86389174;;;;;1;Id placeat ut ut eius fugiat voluptate qui. Unde deleniti velit voluptatem quia. Neque harum eum est.;#d2d6de
|
||||
181;Multi-tiered impactful paradigm;Stanton PLC;P-78069558;;;;;1;Cupiditate nemo ut omnis consectetur est ipsam voluptates. A minus quod sit vel adipisci rerum. Voluptatum ut nihil et rerum. Recusandae voluptatem porro sed omnis fuga ut ea.;
|
||||
115;Networked contextually-based blockchain;Weber, Weber and Mosciski;P-14827181;;;;;1;Animi maiores dolorem impedit molestias. Et est quia et aut. Eligendi et quis quia occaecati exercitationem. Autem vel voluptas maxime modi reprehenderit earum.;
|
||||
18;Networked mission-critical functionalities;A customer name;P-06598815;;;;;1;Et illo labore sit sint. Similique quis natus voluptates aut ut. Ipsum distinctio laboriosam veritatis nesciunt consequatur laborum odit autem. Recusandae impedit veritatis sunt quasi.;
|
||||
138;Open-architected human-resource instructionset;Ullrich, Satterfield and Homenick;P-87900477;;;;;0;At commodi quis non eveniet recusandae voluptas. Assumenda earum esse et est odio ut dolorem. Enim nihil ipsa quo et. Rerum provident facilis non deleniti dolore aut. Culpa sed rerum sequi.;
|
||||
183;Open-source web-enabled projection;Stanton PLC;P-44548292;;;;;1;Distinctio eum earum debitis facere velit numquam exercitationem ipsum. Et et iusto possimus facere. Unde autem et recusandae sed quae. Sed vero eligendi nihil corporis harum fugiat.;
|
||||
37;Optimized content-based array;Smitham, Balistreri and Ondricka;P-74951659;;;;;1;Est aperiam est similique sit velit et. Rerum commodi veniam ullam et consequuntur.;
|
||||
178;Optional bandwidth-monitored moratorium;Stanton PLC;P-72979020;;;;;1;Voluptas suscipit voluptatibus dolorum ullam eos consequuntur aut. Nam voluptatem magni enim quas ad tempore voluptatum. Cum incidunt est qui sit.;Sdfgsdf
|
||||
53;Organic context-sensitive neural-net;Toy, Larson and Schaefer;P-53133083;;;;#d2d6de;1;Vitae sint sed ea nulla facere qui cum. Eligendi velit repellat non sit sit atque aut. Est minus nobis id accusamus repellat et. Quo in et tempora expedita.;
|
||||
83;Organic incremental interface;Nitzsche, Pfeffer and Dickens;P-10570715;;;;;1;Iure est impedit explicabo dolores qui. Quo amet est iste nulla et voluptatum. Sed magni id aliquam aut velit voluptas omnis dolores.;
|
||||
84;Organic needs-based methodology;Nitzsche, Pfeffer and Dickens;P-16957282;;;;;1;Dignissimos dolores et nam ipsa. Aut ipsam fugiat vel. Neque vel consequatur corporis quibusdam eaque.;
|
||||
26;Organic nextgeneration array;Smitham, Balistreri and Ondricka;P-90074059;;;;;1;Rerum at animi sint ipsum. Expedita earum omnis in voluptatem voluptatem porro libero. Perspiciatis possimus ratione voluptatem nobis.;Sfgh0zu90
|
||||
100;Organic responsive artificialintelligence;Cassin LLC;P-47808997;;;;#d2d6de;1;Enim molestias molestiae error ab quisquam qui. Nihil tempore voluptatum vel id et. Sint nisi consequatur iste ipsa vitae veniam neque.;
|
||||
99;Organized composite capability;Cassin LLC;P-88143507;;;;;1;Ut quia recusandae occaecati voluptates dolores. Consectetur quasi et et. Nostrum error modi quam ea a quam eveniet.;
|
||||
167;Organized interactive hardware;Gaylord-Kling;P-80225447;;;;;1;Doloribus eveniet repellendus ut. Dolor quaerat vel eos velit et aspernatur. Consequatur rerum provident quia voluptatem.;
|
||||
119;Organized reciprocal groupware;Weber, Weber and Mosciski;P-96414873;;;;;1;Et reprehenderit reiciendis magnam corrupti. Laudantium fugit fugit nobis unde quod magnam. Sit rerum earum nostrum repellendus.;
|
||||
150;Persistent asynchronous migration;Ullrich, Satterfield and Homenick;P-72771556;;;;;0;Dolores quia nisi aliquam vitae rem. Dolorem ipsum velit culpa quo. Voluptatem iste aliquam maiores consequatur. Et quisquam quae cupiditate ea labore dolor qui.;
|
||||
193;Persistent dedicated extranet;Stanton PLC;P-83020315;;;;;1;Eligendi harum in consequatur enim aut quidem. Debitis est autem et amet quia. Recusandae enim cumque quidem sequi suscipit sunt.;#d2d6de
|
||||
96;Phased assymetric contingency;Cassin LLC;P-63450040;;;;;1;Earum odit non ad cum nihil voluptas et. Totam ea corrupti dicta est. Odit minima est repudiandae sed aperiam sed dolores.;
|
||||
44;Polarised regional capacity;Toy, Larson and Schaefer;P-86899055;;;;;1;Accusamus a sit nisi voluptatem doloremque ipsa totam. Autem sit laudantium magnam perferendis sapiente. Assumenda aperiam quos nobis qui cumque accusantium.;
|
||||
55;Pre-emptive client-driven neural-net;Toy, Larson and Schaefer;P-93689915;;;;;1;Eos labore exercitationem rerum modi tenetur. Occaecati labore sit in rerum quas. Ullam quos illum iure.;
|
||||
51;Pre-emptive directional application;Toy, Larson and Schaefer;P-82374365;;;;;1;Voluptas consequatur consequuntur deserunt dolores placeat. Velit dolores accusamus commodi quae sit. Ut optio in ipsam rerum doloribus.;
|
||||
45;Pre-emptive grid-enabled migration;Toy, Larson and Schaefer;P-44070519;;;;;1;Et nihil alias occaecati nostrum. Doloribus neque nemo repellat nihil. Nihil voluptas est non fugit. Hic nulla omnis alias incidunt asperiores asperiores aut.;
|
||||
90;Pre-emptive homogeneous migration;Cassin LLC;P-37388904;;;;;1;Voluptate quo ipsa et natus. Eum impedit dignissimos et consequatur rerum magnam in provident. Quis qui nesciunt voluptatem minus ut distinctio illum. Consequatur rem et quia quis cupiditate animi.;
|
||||
142;Pre-emptive mission-critical extranet;Ullrich, Satterfield and Homenick;P-36044153;;;;;1;Reiciendis ullam voluptas quia corrupti quod est ut. Qui mollitia dolorem possimus asperiores. Non assumenda qui dolor odio et nihil. Accusantium sint laboriosam veniam quia.;2314
|
||||
125;Pre-emptive optimal extranet;Weber, Weber and Mosciski;P-44924478;;;;;1;Sed aut cumque aut id. Ea qui dignissimos natus inventore praesentium dolorem nihil. Aut sint doloremque minima consequuntur ut ut et. Magnam vel distinctio aperiam laudantium.;
|
||||
24;Proactive explicit info-mediaries;A customer name;P-19018812;;;;;1;Modi dignissimos numquam et quia magni. Magnam impedit ab natus quo.;
|
||||
174;Proactive solution-oriented groupware;Gaylord-Kling;P-42846727;;;;;1;Expedita error voluptatem occaecati. Architecto nobis et perferendis et ipsum soluta. Repudiandae occaecati iure et.;
|
||||
192;Proactive uniform internetsolution;Stanton PLC;P-75026981;;;;;0;Ipsum perferendis amet non sed non perferendis voluptates. Ut quasi quia vitae rerum eos quod. Nihil cum odit provident expedita.;#d2d6de
|
||||
135;Profit-focused contextually-based moratorium;Ullrich, Satterfield and Homenick;P-46607140;;;;;1;Et nisi placeat aut modi. Atque reprehenderit dolorum ducimus non in. Dolor id repudiandae dicta fugit ratione perspiciatis.;
|
||||
160;Profound didactic artificialintelligence;Gaylord-Kling;P-61821699;;;;;1;Repudiandae omnis labore sed vel. Sed vel aperiam nobis id sed mollitia. Sunt impedit ipsum reiciendis ut nobis at provident.;
|
||||
162;Profound fault-tolerant data-warehouse;Gaylord-Kling;P-04359890;;;;;1;Ut esse blanditiis totam consequatur illo quibusdam nostrum rerum. Aspernatur dolores est tempora incidunt voluptas facere vero quod. In autem sint iste architecto inventore itaque blanditiis eum.;
|
||||
12;Profound homogeneous instructionset;A customer name;P-87850895;;;;;1;Dignissimos a commodi cum et et incidunt molestias. Similique odio labore molestias ipsam velit nihil. Et excepturi fuga animi inventore consequatur minus.;
|
||||
|
4
tests/Importer/_data/projects_invalid.csv
Normal file
4
tests/Importer/_data/projects_invalid.csv
Normal file
@@ -0,0 +1,4 @@
|
||||
ID,Name,Customer,Order number,Order date,Project Start,Project End,Color,Visible,Comment,Meta.zzzzz
|
||||
147,Multi-channelled 4thgeneration strategy,"Ullrich, Satterfield and Homenick",P-53400468,,,,,1,Amet non magni est. Cupiditate in magni adipisci nisi voluptatem sequi id. Accusamus sed alias enim et perferendis quo ut. Veniam voluptatem dicta dolores ut tenetur.,
|
||||
188,Test,Stanton PLC,P-58944387,,,,,1,Facere architecto doloremque quae. Exercitationem ut velit molestiae alias dolore provident. Unde facere iste harum doloribus odio.,
|
||||
177,Multi-channelled transitional data-warehouse,Gaylord-Kling,P-17219648,,,,,1,Voluptatibus ipsa eos et maiores. Autem dolorem quia sit dolores. Qui adipisci aut aut eligendi voluptatibus. Libero voluptatem dignissimos rerum dignissimos aliquid consectetur.,
|
||||
|
Reference in New Issue
Block a user