diff --git a/src/Controller/DashboardController.php b/src/Controller/DashboardController.php index e090dd37..42a728dd 100644 --- a/src/Controller/DashboardController.php +++ b/src/Controller/DashboardController.php @@ -13,6 +13,7 @@ use App\Event\DashboardEvent; use App\Widget\Type\AbstractContainer; use App\Widget\Type\AuthorizedWidget; use App\Widget\Type\CompoundRow; +use App\Widget\Type\UserWidget; use App\Widget\WidgetContainerInterface; use App\Widget\WidgetException; use App\Widget\WidgetService; @@ -31,15 +32,15 @@ class DashboardController extends AbstractController /** * @var EventDispatcherInterface */ - protected $eventDispatcher; + private $eventDispatcher; /** * @var WidgetService */ - protected $widgets; + private $widgets; /** * @var array */ - protected $dashboard; + private $dashboard; /** * @param EventDispatcherInterface $dispatcher @@ -58,8 +59,9 @@ class DashboardController extends AbstractController */ public function indexAction() { - $event = new DashboardEvent($this->getUser()); + $user = $this->getUser(); + $event = new DashboardEvent($user); foreach ($this->dashboard as $widgetRow) { if (empty($widgetRow['widgets'])) { continue; @@ -110,6 +112,10 @@ class DashboardController extends AbstractController $add = $tmp; } + if ($widget instanceof UserWidget) { + $widget->setUser($user); + } + if ($add) { $row->addWidget($widget); } diff --git a/src/Repository/WidgetRepository.php b/src/Repository/WidgetRepository.php index 614450cb..5bb88b10 100644 --- a/src/Repository/WidgetRepository.php +++ b/src/Repository/WidgetRepository.php @@ -9,10 +9,8 @@ namespace App\Repository; -use App\Entity\User; -use App\Security\CurrentUser; -use App\Widget\Type\AbstractWidgetType; use App\Widget\Type\Counter; +use App\Widget\Type\SimpleStatisticChart; use App\Widget\Type\YearChart; use App\Widget\WidgetException; use App\Widget\WidgetInterface; @@ -25,29 +23,19 @@ class WidgetRepository /** * @var TimesheetRepository */ - protected $repository; + private $repository; /** * @var array */ - protected $widgets = []; + private $widgets = []; /** * @var array */ - protected $definitions = []; - /** - * @var User|null - */ - protected $user; + private $definitions = []; - /** - * @param TimesheetRepository $repository - * @param CurrentUser $user - * @param array $widgets - */ - public function __construct(TimesheetRepository $repository, CurrentUser $user, array $widgets) + public function __construct(TimesheetRepository $repository, array $widgets) { $this->repository = $repository; - $this->user = $user->getUser(); $this->definitions = array_merge($this->getDefaultWidgets(), $widgets); } @@ -89,12 +77,6 @@ class WidgetRepository */ protected function create(string $name, array $widget): WidgetInterface { - $user = $this->user; - $timezone = new \DateTimeZone($user->getTimezone()); - $begin = !empty($widget['begin']) ? new \DateTime($widget['begin'], $timezone) : null; - $end = !empty($widget['end']) ? new \DateTime($widget['end'], $timezone) : null; - $theUser = $widget['user'] ? $user : null; - if (!isset($widget['type'])) { @trigger_error('Using a widget definition without a "type" is deprecated', E_USER_DEPRECATED); $widget['type'] = Counter::class; @@ -104,30 +86,25 @@ class WidgetRepository throw new WidgetException(sprintf('Unknown widget type "%s"', $widgetClassName)); } - /** @var AbstractWidgetType $model */ - $model = new $widgetClassName(); - if (!($model instanceof AbstractWidgetType)) { + /** @var SimpleStatisticChart $model */ + $model = new $widgetClassName($this->repository); + if (!($model instanceof SimpleStatisticChart)) { throw new WidgetException( sprintf( 'Widget type "%s" is not an instance of "%s"', $widgetClassName, - AbstractWidgetType::class + SimpleStatisticChart::class ) ); } - try { - $data = $this->repository->getStatistic($widget['query'], $begin, $end, $theUser); - } catch (\Exception $ex) { - throw new WidgetException( - 'Failed loading widget data: ' . $ex->getMessage() - ); - } - $model + ->setQuery($widget['query']) + ->setBegin($widget['begin']) + ->setEnd($widget['end']) ->setId($name) ->setTitle($widget['title']) - ->setData($data); + ; if ($widget['query'] == TimesheetRepository::STATS_QUERY_DURATION) { $model->setOption('dataType', 'duration'); diff --git a/src/Twig/EventExtensions.php b/src/Twig/EventExtensions.php index 1146d1f8..9c04df8d 100644 --- a/src/Twig/EventExtensions.php +++ b/src/Twig/EventExtensions.php @@ -9,75 +9,19 @@ namespace App\Twig; -use App\Entity\User; -use App\Event\ThemeEvent; -use App\Security\CurrentUser; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use App\Twig\Runtime\ThemeEventExtension; use Twig\Extension\AbstractExtension; use Twig\TwigFunction; class EventExtensions extends AbstractExtension { - /** - * @var EventDispatcherInterface - */ - protected $eventDispatcher; - /** - * @var User - */ - protected $user; - - /** - * @param EventDispatcherInterface $dispatcher - * @param CurrentUser $user - */ - public function __construct(EventDispatcherInterface $dispatcher, CurrentUser $user) - { - $this->eventDispatcher = $dispatcher; - $this->user = $user->getUser(); - } - /** * {@inheritdoc} */ public function getFunctions() { return [ - new TwigFunction('trigger', [$this, 'triggerEvent']), + new TwigFunction('trigger', [ThemeEventExtension::class, 'trigger']), ]; } - - /** - * @return EventDispatcherInterface - */ - protected function getDispatcher() - { - return $this->eventDispatcher; - } - - /** - * @param string $eventName - * - * @return bool - */ - protected function hasListener($eventName) - { - return $this->getDispatcher()->hasListeners($eventName); - } - - /** - * @param string $eventName - * @param mixed $payload - * @return ThemeEvent - */ - public function triggerEvent(string $eventName, $payload = null) - { - $themeEvent = new ThemeEvent($this->user, $payload); - - if ($this->hasListener($eventName)) { - $this->getDispatcher()->dispatch($themeEvent, $eventName); - } - - return $themeEvent; - } } diff --git a/src/Twig/MarkdownExtension.php b/src/Twig/MarkdownExtension.php index 05e3790f..e2076cc7 100644 --- a/src/Twig/MarkdownExtension.php +++ b/src/Twig/MarkdownExtension.php @@ -52,7 +52,7 @@ final class MarkdownExtension extends AbstractExtension /** * Transforms the entities comment (customer, project, activity ...) into HTML. * - * @param string $content + * @param string|null $content * @param bool $fullLength * @return string */ diff --git a/src/Twig/Runtime/ThemeEventExtension.php b/src/Twig/Runtime/ThemeEventExtension.php new file mode 100644 index 00000000..e824726d --- /dev/null +++ b/src/Twig/Runtime/ThemeEventExtension.php @@ -0,0 +1,49 @@ +eventDispatcher = $dispatcher; + $this->user = $user; + } + + /** + * @param string $eventName + * @param mixed|null $payload + * @return ThemeEvent + */ + public function trigger(string $eventName, $payload = null): ThemeEvent + { + $themeEvent = new ThemeEvent($this->user->getUser(), $payload); + + if ($this->eventDispatcher->hasListeners($eventName)) { + $this->eventDispatcher->dispatch($themeEvent, $eventName); + } + + return $themeEvent; + } +} diff --git a/src/Widget/Type/AbstractWidgetType.php b/src/Widget/Type/AbstractWidgetType.php index 07970b3f..fd16c4a6 100644 --- a/src/Widget/Type/AbstractWidgetType.php +++ b/src/Widget/Type/AbstractWidgetType.php @@ -30,7 +30,7 @@ abstract class AbstractWidgetType implements WidgetInterface */ protected $data; - public function setId(string $id): AbstractWidgetType + public function setId(string $id): self { $this->id = $id; @@ -42,7 +42,7 @@ abstract class AbstractWidgetType implements WidgetInterface return $this->id; } - public function setData($data): AbstractWidgetType + public function setData($data): self { $this->data = $data; @@ -58,7 +58,7 @@ abstract class AbstractWidgetType implements WidgetInterface return $this->data; } - public function setTitle(string $title): AbstractWidgetType + public function setTitle(string $title): self { $this->title = $title; @@ -70,7 +70,7 @@ abstract class AbstractWidgetType implements WidgetInterface return $this->title; } - public function setOptions(array $options): AbstractWidgetType + public function setOptions(array $options): self { foreach ($options as $key => $value) { $this->options[$key] = $value; diff --git a/src/Widget/Type/Counter.php b/src/Widget/Type/Counter.php index 81ace956..4d8ca532 100644 --- a/src/Widget/Type/Counter.php +++ b/src/Widget/Type/Counter.php @@ -9,10 +9,13 @@ namespace App\Widget\Type; -class Counter extends SimpleWidget +use App\Repository\TimesheetRepository; + +final class Counter extends SimpleStatisticChart { - public function __construct() + public function __construct(TimesheetRepository $repository) { + parent::__construct($repository); $this->setOption('dataType', 'int'); } } diff --git a/src/Widget/Type/DailyWorkingTimeChart.php b/src/Widget/Type/DailyWorkingTimeChart.php index 9e73af88..b33c6c60 100644 --- a/src/Widget/Type/DailyWorkingTimeChart.php +++ b/src/Widget/Type/DailyWorkingTimeChart.php @@ -11,12 +11,11 @@ namespace App\Widget\Type; use App\Entity\Activity; use App\Entity\Project; +use App\Entity\User; use App\Repository\TimesheetRepository; -use App\Security\CurrentUser; -use App\Timesheet\UserDateTimeFactory; use DateTime; -class DailyWorkingTimeChart extends SimpleWidget +class DailyWorkingTimeChart extends SimpleWidget implements UserWidget { public const DEFAULT_CHART = 'bar'; @@ -24,27 +23,26 @@ class DailyWorkingTimeChart extends SimpleWidget * @var TimesheetRepository */ protected $repository; - /** - * @var UserDateTimeFactory - */ - private $dateTimeFactory; - public function __construct(TimesheetRepository $repository, CurrentUser $user, UserDateTimeFactory $dateTime) + public function __construct(TimesheetRepository $repository) { $this->repository = $repository; - $this->dateTimeFactory = $dateTime; $this->setId('DailyWorkingTimeChart'); $this->setTitle('stats.yourWorkingHours'); $this->setOptions([ 'begin' => 'monday this week 00:00:00', 'end' => 'sunday this week 23:59:59', 'color' => '', - 'user' => $user->getUser(), 'type' => self::DEFAULT_CHART, 'id' => '', ]); } + public function setUser(User $user): void + { + $this->setOption('user', $user); + } + public function getOptions(array $options = []): array { $options = parent::getOptions($options); @@ -65,16 +63,20 @@ class DailyWorkingTimeChart extends SimpleWidget $options = $this->getOptions($options); $user = $options['user']; + if (null === $user || !($user instanceof User)) { + throw new \InvalidArgumentException('Widget option "user" must be an instance of ' . User::class); + } + if ($options['begin'] instanceof DateTime) { $begin = $options['begin']; } else { - $begin = new DateTime($options['begin'], $this->dateTimeFactory->getTimezone()); + $begin = new DateTime($options['begin'], new \DateTimeZone($user->getTimezone())); } if ($options['end'] instanceof DateTime) { $end = $options['end']; } else { - $end = new DateTime($options['end'], $this->dateTimeFactory->getTimezone()); + $end = new DateTime($options['end'], new \DateTimeZone($user->getTimezone())); } $activities = []; diff --git a/src/Widget/Type/PaginatedWorkingTimeChart.php b/src/Widget/Type/PaginatedWorkingTimeChart.php index 3ee5c658..f5f931f9 100644 --- a/src/Widget/Type/PaginatedWorkingTimeChart.php +++ b/src/Widget/Type/PaginatedWorkingTimeChart.php @@ -9,37 +9,40 @@ namespace App\Widget\Type; +use App\Entity\User; use App\Repository\TimesheetRepository; -use App\Security\CurrentUser; -use App\Timesheet\UserDateTimeFactory; use DateTime; -final class PaginatedWorkingTimeChart extends SimpleWidget +final class PaginatedWorkingTimeChart extends SimpleWidget implements UserWidget { /** * @var TimesheetRepository */ private $repository; - /** - * @var UserDateTimeFactory - */ - private $dateTimeFactory; - public function __construct(TimesheetRepository $repository, CurrentUser $user, UserDateTimeFactory $dateTime) + public function __construct(TimesheetRepository $repository) { $this->repository = $repository; - $this->dateTimeFactory = $dateTime; $this->setId('PaginatedWorkingTimeChart'); $this->setTitle('stats.yourWorkingHours'); $this->setOptions([ - 'year' => (new DateTime('now', $this->dateTimeFactory->getTimezone()))->format('Y'), - 'week' => (new DateTime('now', $this->dateTimeFactory->getTimezone()))->format('W'), - 'user' => $user->getUser(), + 'year' => (new DateTime('now'))->format('Y'), + 'week' => (new DateTime('now'))->format('W'), 'type' => 'bar', ]); } + public function setUser(User $user): void + { + $this->setOption('user', $user); + $now = new DateTime('now', new \DateTimeZone($user->getTimezone())); + $this->setOptions([ + 'year' => $now->format('Y'), + 'week' => $now->format('W'), + ]); + } + public function getOptions(array $options = []): array { $options = parent::getOptions($options); @@ -51,9 +54,9 @@ final class PaginatedWorkingTimeChart extends SimpleWidget return $options; } - private function getDate($year, $week, $day, $hour, $minute, $second) + private function getDate(\DateTimeZone $timezone, $year, $week, $day, $hour, $minute, $second) { - $now = new DateTime('now', $this->dateTimeFactory->getTimezone()); + $now = new DateTime('now', $timezone); $now->setISODate($year, $week, $day); $now->setTime($hour, $minute, $second); @@ -63,10 +66,16 @@ final class PaginatedWorkingTimeChart extends SimpleWidget public function getData(array $options = []) { $options = $this->getOptions($options); - $user = $options['user']; - $weekBegin = $this->getDate($options['year'], $options['week'], 1, 0, 0, 0); - $weekEnd = $this->getDate($options['year'], $options['week'], 7, 23, 59, 59); + $user = $options['user']; + if (null === $user || !($user instanceof User)) { + throw new \InvalidArgumentException('Widget option "user" must be an instance of ' . User::class); + } + + $timezone = new \DateTimeZone($user->getTimezone()); + + $weekBegin = $this->getDate($timezone, $options['year'], $options['week'], 1, 0, 0, 0); + $weekEnd = $this->getDate($timezone, $options['year'], $options['week'], 7, 23, 59, 59); return [ 'begin' => clone $weekBegin, @@ -74,8 +83,8 @@ final class PaginatedWorkingTimeChart extends SimpleWidget 'stats' => $this->repository->getDailyStats($user, $weekBegin, $weekEnd), 'day' => $this->repository->getStatistic( 'duration', - new DateTime('00:00:00', $this->dateTimeFactory->getTimezone()), - new DateTime('23:59:59', $this->dateTimeFactory->getTimezone()), + new DateTime('00:00:00', $timezone), + new DateTime('23:59:59', $timezone), $user ), 'week' => $this->repository->getStatistic( @@ -92,8 +101,8 @@ final class PaginatedWorkingTimeChart extends SimpleWidget ), 'year' => $this->repository->getStatistic( 'duration', - new DateTime(sprintf('01 january %s 00:00:00', $options['year']), $this->dateTimeFactory->getTimezone()), - new DateTime(sprintf('31 december %s 23:59:59', $options['year']), $this->dateTimeFactory->getTimezone()), + new DateTime(sprintf('01 january %s 00:00:00', $options['year']), $timezone), + new DateTime(sprintf('31 december %s 23:59:59', $options['year']), $timezone), $user ), ]; diff --git a/src/Widget/Type/SimpleStatisticChart.php b/src/Widget/Type/SimpleStatisticChart.php new file mode 100644 index 00000000..0354fdea --- /dev/null +++ b/src/Widget/Type/SimpleStatisticChart.php @@ -0,0 +1,101 @@ +repository = $repository; + } + + public function setQuery(string $query): SimpleStatisticChart + { + $this->query = $query; + + return $this; + } + + public function setBegin(?string $begin): SimpleStatisticChart + { + $this->begin = $begin; + + return $this; + } + + public function setEnd(?string $end): SimpleStatisticChart + { + $this->end = $end; + + return $this; + } + + public function setUser(User $user): SimpleStatisticChart + { + $this->user = $user; + + return $this; + } + + public function setData($data): AbstractWidgetType + { + throw new \InvalidArgumentException('Cannot set data on instances of SimpleStatisticChart'); + } + + /** + * @param array $options + * @return mixed|null + * @throws WidgetException + */ + public function getData(array $options = []) + { + $timezone = date_default_timezone_get(); + if (null !== $this->user) { + $timezone = $this->user->getTimezone(); + } + $timezone = new \DateTimeZone($timezone); + + $begin = !empty($this->begin) ? new \DateTime($this->begin, $timezone) : null; + $end = !empty($this->end) ? new \DateTime($this->end, $timezone) : null; + + try { + return $this->repository->getStatistic($this->query, $begin, $end, $this->user); + } catch (\Exception $ex) { + throw new WidgetException( + 'Failed loading widget data: ' . $ex->getMessage() + ); + } + } +} diff --git a/src/Widget/Type/UserTeamProjects.php b/src/Widget/Type/UserTeamProjects.php index 8e24f665..7c82b080 100644 --- a/src/Widget/Type/UserTeamProjects.php +++ b/src/Widget/Type/UserTeamProjects.php @@ -13,23 +13,19 @@ use App\Entity\Project; use App\Entity\Team; use App\Entity\User; use App\Repository\ProjectRepository; -use App\Security\CurrentUser; -class UserTeamProjects extends SimpleWidget implements AuthorizedWidget +class UserTeamProjects extends SimpleWidget implements AuthorizedWidget, UserWidget { /** * @var ProjectRepository */ private $repository; - public function __construct(CurrentUser $user, ProjectRepository $repository) + public function __construct(ProjectRepository $repository) { $this->setId('UserTeamProjects'); $this->setTitle('label.my_team_projects'); - $this->setOptions([ - 'user' => $user->getUser(), - 'id' => '', - ]); + $this->setOption('id', ''); $this->repository = $repository; } @@ -80,4 +76,9 @@ class UserTeamProjects extends SimpleWidget implements AuthorizedWidget { return ['budget_team_project', 'budget_teamlead_project', 'budget_project']; } + + public function setUser(User $user): void + { + $this->setOption('user', $user); + } } diff --git a/src/Widget/Type/UserTeams.php b/src/Widget/Type/UserTeams.php index 557ac217..2cfd4d19 100644 --- a/src/Widget/Type/UserTeams.php +++ b/src/Widget/Type/UserTeams.php @@ -10,18 +10,14 @@ namespace App\Widget\Type; use App\Entity\User; -use App\Security\CurrentUser; -class UserTeams extends SimpleWidget implements AuthorizedWidget +class UserTeams extends SimpleWidget implements AuthorizedWidget, UserWidget { - public function __construct(CurrentUser $user) + public function __construct() { $this->setId('UserTeams'); $this->setTitle('label.my_teams'); - $this->setOptions([ - 'user' => $user->getUser(), - 'id' => '', - ]); + $this->setOption('id', ''); } public function getOptions(array $options = []): array @@ -51,4 +47,9 @@ class UserTeams extends SimpleWidget implements AuthorizedWidget { return ['view_team_member', 'view_team']; } + + public function setUser(User $user): void + { + $this->setOption('user', $user); + } } diff --git a/src/Widget/Type/UserWidget.php b/src/Widget/Type/UserWidget.php new file mode 100644 index 00000000..742fc3f3 --- /dev/null +++ b/src/Widget/Type/UserWidget.php @@ -0,0 +1,22 @@ +repository = $repository; } - /** - * @param string $widget - * @return bool - */ public function hasWidget(string $widget): bool { return $this->repository->has($widget); diff --git a/templates/widget/paginatedworkingtimechart.html.twig b/templates/widget/paginatedworkingtimechart.html.twig index 83656ec3..801e06f3 100644 --- a/templates/widget/paginatedworkingtimechart.html.twig +++ b/templates/widget/paginatedworkingtimechart.html.twig @@ -1 +1 @@ -{{ render_widget('PaginatedWorkingTimeChart', {'year': year, 'week': week}) }} +{{ render_widget('PaginatedWorkingTimeChart', {'user': user, 'year': year, 'week': week}) }} diff --git a/tests/Controller/WidgetControllerTest.php b/tests/Controller/WidgetControllerTest.php new file mode 100644 index 00000000..a21660f5 --- /dev/null +++ b/tests/Controller/WidgetControllerTest.php @@ -0,0 +1,34 @@ +assertUrlIsSecured('/widgets/working-time/2020/1'); + } + + public function testWorkingtimechartAction() + { + $client = $this->getClientForAuthenticatedUser(User::ROLE_USER); + $this->assertAccessIsGranted($client, '/widgets/working-time/2020/1'); + + $content = $client->getResponse()->getContent(); + self::assertStringContainsString('id="PaginatedWorkingTimeChart"', $content); + self::assertStringContainsString('myChart = new Chart', $content); + self::assertStringContainsString("KimaiPaginatedBoxWidget.create('#PaginatedWorkingTimeChart');", $content); + } +} diff --git a/tests/Repository/WidgetRepositoryTest.php b/tests/Repository/WidgetRepositoryTest.php index 636959c1..70756a5e 100644 --- a/tests/Repository/WidgetRepositoryTest.php +++ b/tests/Repository/WidgetRepositoryTest.php @@ -9,10 +9,8 @@ namespace App\Tests\Repository; -use App\Entity\User; use App\Repository\TimesheetRepository; use App\Repository\WidgetRepository; -use App\Tests\Mocks\Security\CurrentUserFactory; use App\Widget\Type\CompoundChart; use App\Widget\Type\Counter; use App\Widget\WidgetException; @@ -26,9 +24,8 @@ class WidgetRepositoryTest extends TestCase public function testHasWidget() { $repoMock = $this->createMock(TimesheetRepository::class); - $userMock = (new CurrentUserFactory($this))->create(new User()); - $sut = new WidgetRepository($repoMock, $userMock, ['test' => []]); + $sut = new WidgetRepository($repoMock, ['test' => []]); $this->assertFalse($sut->has('foo')); $this->assertTrue($sut->has('test')); @@ -40,9 +37,8 @@ class WidgetRepositoryTest extends TestCase $this->expectExceptionMessage('Cannot find widget "foo".'); $repoMock = $this->createMock(TimesheetRepository::class); - $userMock = (new CurrentUserFactory($this))->create(new User()); - $sut = new WidgetRepository($repoMock, $userMock, ['test' => []]); + $sut = new WidgetRepository($repoMock, ['test' => []]); $sut->get('foo'); } @@ -52,21 +48,19 @@ class WidgetRepositoryTest extends TestCase $this->expectExceptionMessage('Unknown widget type "FooBar"'); $repoMock = $this->createMock(TimesheetRepository::class); - $userMock = (new CurrentUserFactory($this))->create(new User()); - $sut = new WidgetRepository($repoMock, $userMock, ['test' => ['type' => 'FooBar', 'user' => false]]); + $sut = new WidgetRepository($repoMock, ['test' => ['type' => 'FooBar', 'user' => false]]); $sut->get('test'); } public function testGetWidgetTriggersExceptionOnWrongClass() { $this->expectException(WidgetException::class); - $this->expectExceptionMessage('Widget type "App\Widget\Type\CompoundChart" is not an instance of "App\Widget\Type\AbstractWidgetType"'); + $this->expectExceptionMessage('Widget type "App\Widget\Type\CompoundChart" is not an instance of "App\Widget\Type\SimpleStatisticChart"'); $repoMock = $this->createMock(TimesheetRepository::class); - $userMock = (new CurrentUserFactory($this))->create(new User()); - $sut = new WidgetRepository($repoMock, $userMock, ['test' => ['type' => CompoundChart::class, 'user' => false]]); + $sut = new WidgetRepository($repoMock, ['test' => ['type' => CompoundChart::class, 'user' => false]]); $sut->get('test'); } @@ -78,8 +72,6 @@ class WidgetRepositoryTest extends TestCase $repoMock = $this->createMock(TimesheetRepository::class); $repoMock->method('getStatistic')->willReturn($data); - $userMock = (new CurrentUserFactory($this))->create(new User()); - $widget = [ 'color' => 'sunny', 'icon' => 'far fa-test', @@ -91,7 +83,7 @@ class WidgetRepositoryTest extends TestCase 'type' => Counter::class, ]; - $sut = new WidgetRepository($repoMock, $userMock, ['test' => $widget]); + $sut = new WidgetRepository($repoMock, ['test' => $widget]); $widget = $sut->get('test'); $options = $widget->getOptions(); diff --git a/tests/Twig/EventExtensionsTest.php b/tests/Twig/EventExtensionsTest.php new file mode 100644 index 00000000..b45928ae --- /dev/null +++ b/tests/Twig/EventExtensionsTest.php @@ -0,0 +1,39 @@ +getSut(); + $twigFunctions = $sut->getFunctions(); + self::assertCount(\count($functions), $twigFunctions); + $i = 0; + /** @var TwigFunction $filter */ + foreach ($twigFunctions as $filter) { + self::assertInstanceOf(TwigFunction::class, $filter); + self::assertEquals($functions[$i++], $filter->getName()); + } + } +} diff --git a/tests/Twig/Runtime/ThemeEventExtensionTest.php b/tests/Twig/Runtime/ThemeEventExtensionTest.php new file mode 100644 index 00000000..8f8e70df --- /dev/null +++ b/tests/Twig/Runtime/ThemeEventExtensionTest.php @@ -0,0 +1,48 @@ +createMock(EventDispatcherInterface::class); + $dispatcher->expects($this->once())->method('hasListeners')->willReturn($hasListener); + $dispatcher->expects($hasListener ? $this->once() : $this->never())->method('dispatch'); + + $user = (new CurrentUserFactory($this))->create(new User()); + + return new ThemeEventExtension($dispatcher, $user); + } + + public function testTrigger() + { + $sut = $this->getSut(); + $event = $sut->trigger('foo', []); + self::assertInstanceOf(ThemeEvent::class, $event); + } + + public function testTriggerWithoutListener() + { + $sut = $this->getSut(false); + $event = $sut->trigger('foo', []); + self::assertInstanceOf(ThemeEvent::class, $event); + } +} diff --git a/tests/Twig/WidgetExtensionTest.php b/tests/Twig/WidgetExtensionTest.php index c1b7b555..3e20872f 100644 --- a/tests/Twig/WidgetExtensionTest.php +++ b/tests/Twig/WidgetExtensionTest.php @@ -10,7 +10,7 @@ namespace App\Tests\Twig; use App\Twig\WidgetExtension; -use App\Widget\Type\Counter; +use App\Widget\Type\More; use App\Widget\WidgetInterface; use App\Widget\WidgetRendererInterface; use App\Widget\WidgetService; @@ -72,7 +72,7 @@ class WidgetExtensionTest extends TestCase public function testRenderWidgetByString() { - $widget = new Counter(); + $widget = new More(); $sut = $this->getSut(true, $widget, new TestRenderer()); $options = ['foo' => 'bar', 'dataType' => 'blub']; $result = $sut->renderWidget('test', $options); @@ -82,7 +82,7 @@ class WidgetExtensionTest extends TestCase public function testRenderWidgetObject() { - $widget = new Counter(); + $widget = new More(); $sut = $this->getSut(null, null, new TestRenderer()); $options = ['foo' => 'bar', 'dataType' => 'blub']; $result = $sut->renderWidget($widget, $options); diff --git a/tests/Widget/Renderer/CompoundChartRendererTest.php b/tests/Widget/Renderer/CompoundChartRendererTest.php index 3435dd78..6ff9c853 100644 --- a/tests/Widget/Renderer/CompoundChartRendererTest.php +++ b/tests/Widget/Renderer/CompoundChartRendererTest.php @@ -12,7 +12,7 @@ namespace App\Tests\Widget\Renderer; use App\Widget\Renderer\CompoundChartRenderer; use App\Widget\Type\CompoundChart; use App\Widget\Type\CompoundRow; -use App\Widget\Type\Counter; +use App\Widget\Type\More; use PHPUnit\Framework\TestCase; use Twig\Environment; @@ -40,7 +40,7 @@ class CompoundChartRendererTest extends TestCase $sut = new CompoundChartRenderer($twig); $row = new CompoundChart(); $row->setTitle('foo-bar'); - $row->addWidget(new Counter()); + $row->addWidget(new More()); $result = $sut->render($row); $result = json_decode($result, true); diff --git a/tests/Widget/Renderer/CompoundRowRendererTest.php b/tests/Widget/Renderer/CompoundRowRendererTest.php index f24f892f..1a18ddb4 100644 --- a/tests/Widget/Renderer/CompoundRowRendererTest.php +++ b/tests/Widget/Renderer/CompoundRowRendererTest.php @@ -12,7 +12,7 @@ namespace App\Tests\Widget\Renderer; use App\Widget\Renderer\CompoundRowRenderer; use App\Widget\Type\CompoundChart; use App\Widget\Type\CompoundRow; -use App\Widget\Type\Counter; +use App\Widget\Type\More; use PHPUnit\Framework\TestCase; use Twig\Environment; @@ -40,7 +40,7 @@ class CompoundRowRendererTest extends TestCase $sut = new CompoundRowRenderer($twig); $row = new CompoundRow(); $row->setTitle('foo-bar'); - $row->addWidget(new Counter()); + $row->addWidget(new More()); $result = $sut->render($row); $result = json_decode($result, true); diff --git a/tests/Widget/Renderer/SimpleWidgetRendererTest.php b/tests/Widget/Renderer/SimpleWidgetRendererTest.php index c26653c8..7bbb8f59 100644 --- a/tests/Widget/Renderer/SimpleWidgetRendererTest.php +++ b/tests/Widget/Renderer/SimpleWidgetRendererTest.php @@ -10,7 +10,6 @@ namespace App\Tests\Widget\Renderer; use App\Widget\Renderer\SimpleWidgetRenderer; -use App\Widget\Type\Counter; use App\Widget\Type\More; use App\Widget\Type\SimpleWidget; use PHPUnit\Framework\TestCase; @@ -60,7 +59,6 @@ class SimpleWidgetRendererTest extends TestCase { return [ [new SimpleWidget(), 'widget/widget-simplewidget.html.twig', 'yellow'], - [new Counter(), 'widget/widget-counter.html.twig', 'asdfgh'], [new More(), 'widget/widget-more.html.twig', '#123456'], ]; } diff --git a/tests/Widget/Type/AbstractSimpleStatisticsWidgetTypeTest.php b/tests/Widget/Type/AbstractSimpleStatisticsWidgetTypeTest.php new file mode 100644 index 00000000..77890821 --- /dev/null +++ b/tests/Widget/Type/AbstractSimpleStatisticsWidgetTypeTest.php @@ -0,0 +1,26 @@ +createSut(); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Cannot set data on instances of SimpleStatisticChart'); + + $sut->setData(10); + } +} diff --git a/tests/Widget/Type/AbstractWidgetTypeTest.php b/tests/Widget/Type/AbstractWidgetTypeTest.php index cdeed4af..c3fe7a22 100644 --- a/tests/Widget/Type/AbstractWidgetTypeTest.php +++ b/tests/Widget/Type/AbstractWidgetTypeTest.php @@ -38,7 +38,6 @@ abstract class AbstractWidgetTypeTest extends TestCase self::assertInstanceOf(AbstractWidgetType::class, $sut->setOptions([])); self::assertInstanceOf(AbstractWidgetType::class, $sut->setId('')); self::assertInstanceOf(AbstractWidgetType::class, $sut->setTitle('')); - self::assertInstanceOf(AbstractWidgetType::class, $sut->setData('')); } public function testSetter() @@ -57,8 +56,14 @@ abstract class AbstractWidgetTypeTest extends TestCase // id $sut->setId('cvbnmyx'); self::assertEquals('cvbnmyx', $sut->getId()); + } + + public function testData() + { + $sut = $this->createSut(); + + self::assertInstanceOf(AbstractWidgetType::class, $sut->setData('')); - // data $sut->setData('slkudfhalksjdhfkljsahdf'); self::assertEquals('slkudfhalksjdhfkljsahdf', $sut->getData()); diff --git a/tests/Widget/Type/CounterTest.php b/tests/Widget/Type/CounterTest.php index fb8527e8..43ad9d19 100644 --- a/tests/Widget/Type/CounterTest.php +++ b/tests/Widget/Type/CounterTest.php @@ -9,6 +9,7 @@ namespace App\Tests\Widget\Type; +use App\Repository\TimesheetRepository; use App\Widget\Type\AbstractWidgetType; use App\Widget\Type\Counter; use App\Widget\Type\SimpleWidget; @@ -17,11 +18,14 @@ use App\Widget\Type\SimpleWidget; * @covers \App\Widget\Type\Counter * @covers \App\Widget\Type\SimpleWidget */ -class CounterTest extends AbstractWidgetTypeTest +class CounterTest extends AbstractSimpleStatisticsWidgetTypeTest { public function createSut(): AbstractWidgetType { - return new Counter(); + $sut = new Counter($this->createMock(TimesheetRepository::class)); + $sut->setQuery(TimesheetRepository::STATS_QUERY_ACTIVE); + + return $sut; } public function getDefaultOptions(): array @@ -37,7 +41,8 @@ class CounterTest extends AbstractWidgetTypeTest public function testTemplateName() { - $sut = new Counter(); + /** @var Counter $sut */ + $sut = $this->createSut(); self::assertEquals('widget/widget-counter.html.twig', $sut->getTemplateName()); } } diff --git a/tests/Widget/Type/DailyWorkingTimeChartTest.php b/tests/Widget/Type/DailyWorkingTimeChartTest.php index 6989842d..166e7c62 100644 --- a/tests/Widget/Type/DailyWorkingTimeChartTest.php +++ b/tests/Widget/Type/DailyWorkingTimeChartTest.php @@ -12,8 +12,6 @@ namespace App\Tests\Widget\Type; use App\Entity\User; use App\Model\Statistic\Day; use App\Repository\TimesheetRepository; -use App\Tests\Mocks\Security\CurrentUserFactory; -use App\Tests\Mocks\Security\UserDateTimeFactoryFactory; use App\Widget\Type\AbstractWidgetType; use App\Widget\Type\DailyWorkingTimeChart; use App\Widget\Type\SimpleWidget; @@ -30,11 +28,11 @@ class DailyWorkingTimeChartTest extends TestCase public function createSut(): AbstractWidgetType { $repository = $this->createMock(TimesheetRepository::class); - $mockFactory = new UserDateTimeFactoryFactory($this); - $userFactory = new CurrentUserFactory($this); - $user = $userFactory->create(new User(), 'Europe/Berlin'); - return new DailyWorkingTimeChart($repository, $user, $mockFactory->create('Europe/Berlin')); + $sut = new DailyWorkingTimeChart($repository); + $sut->setUser(new User()); + + return $sut; } public function testExtendsSimpleWidget() @@ -107,12 +105,8 @@ class DailyWorkingTimeChartTest extends TestCase ]; }); - $userFactory = new CurrentUserFactory($this); - $user = $userFactory->create(new User(), 'Europe/Berlin'); - - $mockFactory = new UserDateTimeFactoryFactory($this); - - $sut = new DailyWorkingTimeChart($repository, $user, $mockFactory->create('Europe/Berlin')); + $sut = new DailyWorkingTimeChart($repository); + $sut->setUser(new User()); $data = $sut->getData([]); self::assertCount(2, $data); self::assertArrayHasKey('activities', $data); diff --git a/tests/Widget/Type/YearChartTest.php b/tests/Widget/Type/YearChartTest.php index 4b41b865..8c14932e 100644 --- a/tests/Widget/Type/YearChartTest.php +++ b/tests/Widget/Type/YearChartTest.php @@ -9,17 +9,21 @@ namespace App\Tests\Widget\Type; +use App\Repository\TimesheetRepository; use App\Widget\Type\AbstractWidgetType; use App\Widget\Type\YearChart; /** * @covers \App\Widget\Type\YearChart */ -class YearChartTest extends AbstractWidgetTypeTest +class YearChartTest extends AbstractSimpleStatisticsWidgetTypeTest { public function createSut(): AbstractWidgetType { - return new YearChart(); + $sut = new YearChart($this->createMock(TimesheetRepository::class)); + $sut->setQuery(TimesheetRepository::STATS_QUERY_ACTIVE); + + return $sut; } public function getDefaultOptions(): array