Next major version 2 with PHP 8.1, Symfony 6, Tabler UI, 2FA ... (#2902)

This commit is contained in:
Kevin Papst
2022-12-31 21:19:55 +01:00
committed by GitHub
parent 95e06746bd
commit 90a0fd8a22
2164 changed files with 83700 additions and 86426 deletions

View File

@@ -10,6 +10,7 @@
namespace App\Tests\DependencyInjection;
use App\DependencyInjection\AppExtension;
use App\Tests\Mocks\SystemConfigurationFactory;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -18,10 +19,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
*/
class AppExtensionTest extends TestCase
{
/**
* @var AppExtension
*/
private $extension;
private ?AppExtension $extension = null;
protected function setUp(): void
{
@@ -29,31 +27,27 @@ class AppExtensionTest extends TestCase
$this->extension = new AppExtension();
}
/**
* @return ContainerBuilder
*/
private function getContainer()
private function getContainer(): ContainerBuilder
{
$container = new ContainerBuilder();
$container->setParameter('app_locales', 'de|en|tr|zh_CN');
$container->setParameter('app_locales', 'de|en|he|tr|zh_CN');
$container->setParameter('kernel.project_dir', realpath(__DIR__ . '/../../'));
$container->setParameter('security.role_hierarchy.roles', [
'ROLE_TEAMLEAD' => ['ROLE_USER'],
'ROLE_ADMIN' => ['ROLE_TEAMLEAD'],
'ROLE_SUPER_ADMIN' => ['ROLE_ADMIN'],
]);
return $container;
}
protected function getMinConfig()
/**
* @return array<string, array<string, mixed>>
*/
protected function getMinConfig(): array
{
return [
'kimai' => [
'languages' => [
'en' => [
'date_type' => 'dd. MM. yyyy',
'date' => 'A-m-d'
],
'tr' => [
'date' => 'X-m-d'
],
],
'data_dir' => '/tmp/',
'timesheet' => [],
'saml' => [
@@ -63,169 +57,55 @@ class AppExtensionTest extends TestCase
];
}
public function testDefaultValues()
public function testDefaultValues(): void
{
$minConfig = $this->getMinConfig();
$this->extension->load($minConfig, $container = $this->getContainer());
// these value list represents the default values with unmerged kimai.yaml
$expected = [
'kimai.data_dir' => '/tmp/',
'kimai.plugin_dir' => realpath(__DIR__ . '/../../') . '/var/plugins',
'kimai.languages' => [
'en' => [
'date_time_type' => 'yyyy-MM-dd HH:mm',
'date_type' => 'dd. MM. yyyy',
'date' => 'A-m-d',
'date_time' => 'm-d H:i',
'duration' => '%%h:%%m h',
'time' => 'H:i',
'24_hours' => true,
'date' => 'M/d/yy',
'time' => 'h:mm a',
'rtl' => false,
],
'de' => [
'date_time_type' => 'yyyy-MM-dd HH:mm',
'date_type' => 'dd. MM. yyyy',
'date' => 'A-m-d',
'date_time' => 'm-d H:i',
'duration' => '%%h:%%m h',
'time' => 'H:i',
'24_hours' => true,
'date' => 'dd.MM.yy',
'time' => 'HH:mm',
'rtl' => false,
],
'he' => [
'date' => 'd.M.y',
'time' => 'H:mm',
'rtl' => true,
],
'tr' => [
'date_time_type' => 'yyyy-MM-dd HH:mm',
// this value if pre-filled by the Configuration object, as "tr" is defined in the min config
// and the other languages (not defined in min config) are "only" copied during runtime from "en"
'date_type' => 'yyyy-MM-dd',
'date' => 'X-m-d',
'date_time' => 'm-d H:i',
'duration' => '%%h:%%m h',
'time' => 'H:i',
'24_hours' => true,
'date' => 'd.MM.y',
'time' => 'HH:mm',
'rtl' => false,
],
'zh_CN' => [
'date_time_type' => 'yyyy-MM-dd HH:mm',
'date_type' => 'dd. MM. yyyy',
'date' => 'A-m-d',
'date_time' => 'm-d H:i',
'duration' => '%%h:%%m h',
'time' => 'H:i',
'24_hours' => true,
'date' => 'y/M/d',
'time' => 'HH:mm',
'rtl' => false,
],
],
'kimai.calendar' => [
'week_numbers' => true,
'day_limit' => 4,
'slot_duration' => '00:30:00',
'businessHours' => [
'days' => [1, 2, 3, 4, 5],
'begin' => '08:00',
'end' => '20:00',
],
'visibleHours' => [
'begin' => '00:00',
'end' => '23:59',
],
'google' => [
'api_key' => null,
'sources' => [],
],
'weekends' => true,
'dragdrop_amount' => 10,
'dragdrop_data' => false,
'title_pattern' => '{activity}',
],
'kimai.dashboard' => [],
'kimai.widgets' => [],
'kimai.invoice.documents' => [
'var/invoices/',
'templates/invoice/renderer/',
],
'kimai.defaults' => [
'timesheet' => [
'billable' => true,
],
'customer' => [
'timezone' => null,
'country' => 'DE',
'currency' => 'EUR',
],
'user' => [
'timezone' => null,
'language' => 'en',
'theme' => null,
'currency' => 'EUR',
]
],
'kimai.theme' => [
'active_warning' => 3,
'box_color' => 'blue',
'select_type' => 'selectpicker',
'show_about' => true,
'chart' => [
'background_color' => '#3c8dbc',
'border_color' => '#3b8bba',
'grid_color' => 'rgba(0,0,0,.05)',
'height' => '200'
],
'branding' => [
'logo' => null,
'mini' => null,
'company' => null,
'title' => null,
'translation' => null,
],
'autocomplete_chars' => 3,
'tags_create' => true,
'calendar' => [
'background_color' => '#d2d6de',
],
'colors_limited' => true,
'color_choices' => 'Silver|#c0c0c0,Gray|#808080,Black|#000000,Maroon|#800000,Brown|#a52a2a,Red|#ff0000,Orange|#ffa500,Gold|#ffd700,Yellow|#ffff00,Peach|#ffdab9,Khaki|#f0e68c,Olive|#808000,Lime|#00ff00,Jelly|#9acd32,Green|#008000,Teal|#008080,Aqua|#00ffff,LightBlue|#add8e6,DeepSky|#00bfff,Dodger|#1e90ff,Blue|#0000ff,Navy|#000080,Purple|#800080,Fuchsia|#ff00ff,Violet|#ee82ee,Rose|#ffe4e1,Lavender|#E6E6FA',
'random_colors' => true,
'avatar_url' => false,
],
'kimai.timesheet' => [
'mode' => 'default',
'markdown_content' => false,
'rounding' => [
'default' => [
'begin' => 1,
'end' => 1,
'duration' => 0,
'mode' => 'default',
'days' => 'monday,tuesday,wednesday,thursday,friday,saturday,sunday'
]
],
'rates' => [],
'active_entries' => [
'soft_limit' => 1,
'hard_limit' => 1,
],
'rules' => [
'allow_future_times' => true,
'allow_zero_duration' => true,
'allow_overlapping_records' => true,
'lockdown_period_start' => null,
'lockdown_period_end' => null,
'lockdown_grace_period' => null,
'allow_overbooking_budget' => true,
'lockdown_period_timezone' => null,
'break_warning_duration' => 0,
'long_running_duration' => 0,
],
'default_begin' => 'now',
'duration_increment' => null,
'time_increment' => null,
],
'kimai.timesheet.rates' => [],
'kimai.timesheet.rounding' => [
'default' => [
'begin' => 1,
'end' => 1,
'duration' => 0,
'mode' => 'default',
'days' => 'monday,tuesday,wednesday,thursday,friday,saturday,sunday'
]
'default' => [
'begin' => 1,
'end' => 1,
'duration' => 0,
'mode' => 'default',
'days' => 'monday,tuesday,wednesday,thursday,friday,saturday,sunday'
]
],
'kimai.permissions' => [
'ROLE_USER' => [],
@@ -233,41 +113,46 @@ class AppExtensionTest extends TestCase
'ROLE_ADMIN' => [],
'ROLE_SUPER_ADMIN' => [],
],
'kimai.i18n_domains' => []
];
$kimaiLdap = [
'activate' => false,
'user' => [
'baseDn' => null,
'filter' => '',
'usernameAttribute' => 'uid',
'attributesFilter' => '(objectClass=*)',
'attributes' => [],
],
'role' => [
'baseDn' => null,
'nameAttribute' => 'cn',
'userDnAttribute' => 'member',
'groups' => [],
'usernameAttribute' => 'dn',
],
'connection' => [
'baseDn' => null,
'host' => null,
'port' => 389,
'useStartTls' => false,
'useSsl' => false,
'bindRequiresDn' => true,
'accountFilterFormat' => '(&(uid=%s))',
'ldap' => [
'activate' => false,
'user' => [
'baseDn' => null,
'filter' => '',
'usernameAttribute' => 'uid',
'attributesFilter' => '(objectClass=*)',
'attributes' => [],
],
'role' => [
'baseDn' => null,
'nameAttribute' => 'cn',
'userDnAttribute' => 'member',
'groups' => [],
'usernameAttribute' => 'dn',
],
'connection' => [
'baseDn' => null,
'host' => null,
'port' => 389,
'useStartTls' => false,
'useSsl' => false,
'bindRequiresDn' => true,
'accountFilterFormat' => '(&(uid=%s))',
],
],
];
$this->assertTrue($container->hasParameter('kimai.config'));
/** @var array<string, mixed> $config */
$config = $container->getParameter('kimai.config');
$this->assertArrayHasKey('ldap', $config);
$this->assertEquals($kimaiLdap, $config['ldap']);
foreach (SystemConfigurationFactory::flatten($kimaiLdap) as $key => $value) {
$this->assertArrayHasKey($key, $config);
$this->assertEquals($value, $config[$key]);
}
foreach ($expected as $key => $value) {
$this->assertTrue($container->hasParameter($key), 'Could not find config: ' . $key);
@@ -275,60 +160,7 @@ class AppExtensionTest extends TestCase
}
}
public function testAdditionalAuthenticationRoutes()
{
$minConfig = $this->getMinConfig();
$adminLte = [
'adminlte_registration' => 'foo',
'adminlte_password_reset' => 'bar',
];
$container = $this->getContainer();
$container->setParameter('admin_lte_theme.routes', $adminLte);
$this->extension->load($minConfig, $container);
$this->assertEquals(
[
'adminlte_registration' => 'foo',
'adminlte_password_reset' => 'bar',
],
$container->getParameter('admin_lte_theme.routes')
);
}
/**
* @expectedDeprecation Configuration "kimai.timesheet.duration_only" is deprecated, please remove it
* @group legacy
*/
public function testDurationOnlyDeprecationIsTriggered()
{
$this->expectNotice();
$this->expectExceptionMessage('Found ambiguous configuration: remove "kimai.timesheet.duration_only" and set "kimai.timesheet.mode" instead.');
$minConfig = $this->getMinConfig();
$minConfig['kimai']['timesheet']['duration_only'] = true;
$minConfig['kimai']['timesheet']['mode'] = 'punch';
$this->extension->load($minConfig, $container = $this->getContainer());
}
/**
* @expectedDeprecation Changing the plugin directory via "kimai.plugin_dir" is not supported since 1.9
* @group legacy
*/
public function testChangingPluginsIsIgnoredAndTriggersDeprecation()
{
$minConfig = $this->getMinConfig();
$minConfig['kimai']['plugin_dir'] = '/tmp/';
$expected = realpath(__DIR__ . '/../../') . '/var/plugins';
$this->extension->load($minConfig, $container = $this->getContainer());
$this->assertEquals($expected, $container->getParameter('kimai.plugin_dir'), 'Invalid config: kimai.plugin_dir');
}
public function testLdapDefaultValues()
public function testLdapDefaultValues(): void
{
$minConfig = $this->getMinConfig();
$minConfig['kimai']['ldap'] = [
@@ -347,16 +179,15 @@ class AppExtensionTest extends TestCase
$this->extension->load($minConfig, $container = $this->getContainer());
$config = $container->getParameter('kimai.config');
$ldapConfig = $config['ldap'];
$this->assertEquals('123123123', $ldapConfig['user']['baseDn']);
$this->assertEquals('(..........)', $ldapConfig['user']['filter']);
$this->assertEquals('xxx', $ldapConfig['user']['usernameAttribute']);
$this->assertEquals('lkhiuzhkj', $ldapConfig['connection']['baseDn']);
$this->assertEquals('(uid=%s)', $ldapConfig['connection']['accountFilterFormat']);
$this->assertEquals('123123123', $config['ldap.user.baseDn']);
$this->assertEquals('(..........)', $config['ldap.user.filter']);
$this->assertEquals('xxx', $config['ldap.user.usernameAttribute']);
$this->assertEquals('lkhiuzhkj', $config['ldap.connection.baseDn']);
$this->assertEquals('(uid=%s)', $config['ldap.connection.accountFilterFormat']);
}
public function testLdapFallbackValue()
public function testLdapFallbackValue(): void
{
$minConfig = $this->getMinConfig();
$minConfig['kimai']['ldap'] = [
@@ -372,16 +203,15 @@ class AppExtensionTest extends TestCase
$this->extension->load($minConfig, $container = $this->getContainer());
$config = $container->getParameter('kimai.config');
$ldapConfig = $config['ldap'];
$this->assertEquals('123123123', $ldapConfig['user']['baseDn']);
$this->assertEquals('xxx', $ldapConfig['user']['usernameAttribute']);
$this->assertEquals('123123123', $ldapConfig['connection']['baseDn']);
$this->assertEquals('(&(xxx=%s))', $ldapConfig['connection']['accountFilterFormat']);
$this->assertEquals('', $ldapConfig['user']['filter']);
$this->assertEquals('123123123', $config['ldap.user.baseDn']);
$this->assertEquals('xxx', $config['ldap.user.usernameAttribute']);
$this->assertEquals('123123123', $config['ldap.connection.baseDn']);
$this->assertEquals('(&(xxx=%s))', $config['ldap.connection.accountFilterFormat']);
$this->assertEquals('', $config['ldap.user.filter']);
}
public function testLdapMoreFallbackValue()
public function testLdapMoreFallbackValue(): void
{
$minConfig = $this->getMinConfig();
$minConfig['kimai']['ldap'] = [
@@ -399,57 +229,30 @@ class AppExtensionTest extends TestCase
$this->extension->load($minConfig, $container = $this->getContainer());
$config = $container->getParameter('kimai.config');
$ldapConfig = $config['ldap'];
$this->assertEquals('123123123', $ldapConfig['user']['baseDn']);
$this->assertEquals('zzzz', $ldapConfig['user']['usernameAttribute']);
$this->assertEquals('7658765', $ldapConfig['connection']['baseDn']);
$this->assertEquals('(&(&(objectClass=inetOrgPerson))(zzzz=%s))', $ldapConfig['connection']['accountFilterFormat']);
$this->assertEquals('(&(objectClass=inetOrgPerson))', $ldapConfig['user']['filter']);
$this->assertEquals('123123123', $config['ldap.user.baseDn']);
$this->assertEquals('zzzz', $config['ldap.user.usernameAttribute']);
$this->assertEquals('7658765', $config['ldap.connection.baseDn']);
$this->assertEquals('(&(&(objectClass=inetOrgPerson))(zzzz=%s))', $config['ldap.connection.accountFilterFormat']);
$this->assertEquals('(&(objectClass=inetOrgPerson))', $config['ldap.user.filter']);
}
public function testTranslationOverwritesEmpty()
{
$minConfig = $this->getMinConfig();
$this->extension->load($minConfig, $container = $this->getContainer());
$config = $container->getParameter('kimai.i18n_domains');
$this->assertEquals([], $config);
}
public function testTranslationOverwrites()
{
$minConfig = $this->getMinConfig();
$minConfig['kimai']['industry'] = [
'translation' => 'xxxx',
];
$minConfig['kimai']['theme'] = [
'branding' => [
'translation' => 'yyyy',
]
];
$this->extension->load($minConfig, $container = $this->getContainer());
$config = $container->getParameter('kimai.i18n_domains');
// oder is important, theme/installation specific translations win
$this->assertEquals(['yyyy', 'xxxx'], $config);
}
public function testWithBundleConfiguration()
public function testWithBundleConfiguration(): void
{
$bundleConfig = [
'foo-bundle' => ['test'],
'foo-bundle' => [
'bar' => 'test'
],
];
$container = $this->getContainer();
$container->setParameter('kimai.bundles.config', $bundleConfig);
$this->extension->load($this->getMinConfig(), $container);
$config = $container->getParameter('kimai.config');
self::assertEquals(['test'], $config['foo-bundle']);
self::assertEquals('test', $config['foo-bundle.bar']);
}
public function testWithBundleConfigurationFailsOnDuplicatedKey()
public function testWithBundleConfigurationFailsOnDuplicatedKey(): void
{
$this->expectNotice();
$this->expectExceptionMessage('Invalid bundle configuration "timesheet" found, skipping');
@@ -463,7 +266,7 @@ class AppExtensionTest extends TestCase
$this->extension->load($this->getMinConfig(), $container);
}
public function testWithBundleConfigurationFailsOnNonArray()
public function testWithBundleConfigurationFailsOnNonArray(): void
{
$this->expectNotice();
$this->expectExceptionMessage('Invalid bundle configuration found, skipping all bundle configuration');

View File

@@ -51,21 +51,6 @@ class ConfigurationTest extends TestCase
$this->assertConfig($this->getMinConfig('sdfsdfsdfds'), []);
}
/**
* @expectedDeprecation Changing the plugin directory via "kimai.plugin_dir" is not supported since 1.9
* @group legacy
*/
public function testValidatePluginDir()
{
$config = $this->getMinConfig();
$config['plugin_dir'] = '/tmp/';
$finalizedConfig = $this->getCompiledConfig($config);
$finalizedConfig['plugin_dir'] = '/tmp/';
$this->assertConfig($config, $finalizedConfig);
}
public function testValidateLdapConfigUserBaseDn()
{
$this->expectException(InvalidConfigurationException::class);
@@ -291,7 +276,6 @@ class ConfigurationTest extends TestCase
],
'rates' => [],
'active_entries' => [
'soft_limit' => 1,
'hard_limit' => 1,
],
'rules' => [
@@ -304,10 +288,11 @@ class ConfigurationTest extends TestCase
'allow_overbooking_budget' => true,
'lockdown_period_timezone' => null,
'break_warning_duration' => 0,
'long_running_duration' => 0,
'long_running_duration' => 480,
'require_activity' => true,
],
'duration_increment' => null,
'time_increment' => null,
'duration_increment' => 15,
'time_increment' => 15,
],
'user' => [
'registration' => false,
@@ -323,7 +308,6 @@ class ConfigurationTest extends TestCase
0 => 'var/invoices/',
1 => 'templates/invoice/renderer/',
],
'simple_form' => false,
'number_format' => '{Y}/{cy,3}',
],
'export' => [
@@ -334,19 +318,11 @@ class ConfigurationTest extends TestCase
1 => 'templates/export/renderer/',
],
],
'languages' => [],
'calendar' => [
'week_numbers' => true,
'day_limit' => 4,
'slot_duration' => '00:30:00',
'businessHours' => [
'days' => [
0 => 1,
1 => 2,
2 => 3,
3 => 4,
4 => 5,
],
'begin' => '08:00',
'end' => '20:00',
],
@@ -360,47 +336,23 @@ class ConfigurationTest extends TestCase
],
],
'weekends' => true,
'dragdrop_amount' => 10,
'dragdrop_amount' => 5,
'dragdrop_data' => false,
'title_pattern' => '{activity}',
],
'theme' => [
'active_warning' => 3,
'box_color' => 'blue',
'select_type' => 'selectpicker',
'show_about' => true,
'chart' => [
'background_color' => '#3c8dbc',
'border_color' => '#3b8bba',
'grid_color' => 'rgba(0,0,0,.05)',
'height' => '200',
],
'branding' => [
'logo' => null,
'mini' => null,
'company' => null,
'title' => null,
'translation' => null,
],
'autocomplete_chars' => 3,
'tags_create' => true,
'calendar' => [
'background_color' => '#d2d6de'
],
'colors_limited' => true,
'color_choices' => 'Silver|#c0c0c0,Gray|#808080,Black|#000000,Maroon|#800000,Brown|#a52a2a,Red|#ff0000,Orange|#ffa500,Gold|#ffd700,Yellow|#ffff00,Peach|#ffdab9,Khaki|#f0e68c,Olive|#808000,Lime|#00ff00,Jelly|#9acd32,Green|#008000,Teal|#008080,Aqua|#00ffff,LightBlue|#add8e6,DeepSky|#00bfff,Dodger|#1e90ff,Blue|#0000ff,Navy|#000080,Purple|#800080,Fuchsia|#ff00ff,Violet|#ee82ee,Rose|#ffe4e1,Lavender|#E6E6FA',
'random_colors' => true,
'avatar_url' => false,
],
'industry' => [
'translation' => null,
],
'dashboard' => [],
'widgets' => [],
'defaults' => [
'timesheet' => [
'billable' => true,
],
'customer' => [
'timezone' => null,
'country' => 'DE',
@@ -409,7 +361,7 @@ class ConfigurationTest extends TestCase
'user' => [
'timezone' => null,
'language' => 'en',
'theme' => null,
'theme' => 'default',
'currency' => 'EUR',
],
],
@@ -460,6 +412,7 @@ class ConfigurationTest extends TestCase
'connection' => [
'organization' => []
],
'provider' => null,
],
'company' => [
'financial_year' => null,
@@ -472,6 +425,12 @@ class ConfigurationTest extends TestCase
'project' => [
'copy_teams_on_create' => false,
],
'activity' => [
'allow_inline_create' => false,
],
'customer' => [
'number_format' => '{cc,4}',
],
];
$this->assertConfig($this->getMinConfig(), $fullDefaultConfig);