From 8f6bd547d383532f8eec1184923f8b2ce30485a2 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Sat, 13 Apr 2024 18:02:40 +0200 Subject: [PATCH] Move shifts event handler to right location --- config/app.php | 6 +- includes/includes.php | 1 - .../Events/Listener/Shifts.php | 21 +- tests/Unit/Events/Listener/ShiftsTest.php | 258 ++++++++++++++++++ 4 files changed, 273 insertions(+), 13 deletions(-) rename includes/helper/shift_helper.php => src/Events/Listener/Shifts.php (88%) create mode 100644 tests/Unit/Events/Listener/ShiftsTest.php diff --git a/config/app.php b/config/app.php index 70165359..50059765 100644 --- a/config/app.php +++ b/config/app.php @@ -81,10 +81,10 @@ return [ 'oauth2.login' => \Engelsystem\Events\Listener\OAuth2::class . '@login', 'shift.deleting' => [ - \Engelsystem\Events\Listener\Shift::class . '@shiftDeletingCreateWorklogs', - \Engelsystem\Events\Listener\Shift::class . '@shiftDeletingSendEmails', + \Engelsystem\Events\Listener\Shifts::class . '@deletingCreateWorklogs', + \Engelsystem\Events\Listener\Shifts::class . '@deletingSendEmails', ], - 'shift.updating' => \Engelsystem\Events\Listener\Shift::class . '@updatedShiftSendEmail', + 'shift.updating' => \Engelsystem\Events\Listener\Shifts::class . '@updatedSendEmail', ], ]; diff --git a/includes/includes.php b/includes/includes.php index 36a05271..aa8f3539 100644 --- a/includes/includes.php +++ b/includes/includes.php @@ -46,7 +46,6 @@ $includeFiles = [ __DIR__ . '/../includes/helper/legacy_helper.php', __DIR__ . '/../includes/helper/message_helper.php', __DIR__ . '/../includes/helper/email_helper.php', - __DIR__ . '/../includes/helper/shift_helper.php', __DIR__ . '/../includes/mailer/shifts_mailer.php', __DIR__ . '/../includes/mailer/users_mailer.php', diff --git a/includes/helper/shift_helper.php b/src/Events/Listener/Shifts.php similarity index 88% rename from includes/helper/shift_helper.php rename to src/Events/Listener/Shifts.php index dc0a2a1c..3896750b 100644 --- a/includes/helper/shift_helper.php +++ b/src/Events/Listener/Shifts.php @@ -1,16 +1,18 @@ shiftEntries as $entry) { if ($entry->freeloaded || $shift->start > Carbon::now()) { @@ -50,7 +52,7 @@ class Shift } } - public function shiftDeletingSendEmails(ShiftModel $shift): void + public function deletingSendEmails(Shift $shift): void { foreach ($shift->shiftEntries as $entry) { if (!$entry->user->settings->email_shiftinfo) { @@ -70,10 +72,8 @@ class Shift } } - public function updatedShiftSendEmail( - ShiftModel $shift, - ShiftModel $oldShift - ): void { + public function updatedSendEmail(Shift $shift, Shift $oldShift): void + { // Only send e-mail on relevant changes if ( $oldShift->shift_type_id == $shift->shift_type_id @@ -96,7 +96,10 @@ class Shift $user = $shiftEntry->user; $angelType = $shiftEntry->angelType; - if (!$user->settings->email_shiftinfo || $shift->end < Carbon::now()) { + if ( + !$user->settings->email_shiftinfo + || $shift->end < Carbon::now() && $oldShift->end < Carbon::now() + ) { continue; } diff --git a/tests/Unit/Events/Listener/ShiftsTest.php b/tests/Unit/Events/Listener/ShiftsTest.php new file mode 100644 index 00000000..49d043c7 --- /dev/null +++ b/tests/Unit/Events/Listener/ShiftsTest.php @@ -0,0 +1,258 @@ +setExpects($this->auth, 'user', null, $this->user); + $this->setExpects($this->translator, 'translate', null, 'Text', $this->atLeastOnce()); + + /** @var Shifts $listener */ + $listener = $this->app->make(Shifts::class); + $listener->deletingCreateWorklogs($this->shift); + + $this->assertCount(1, $this->user->worklogs); + $this->assertEquals($this->shift->isNightShift() ? 4 : 2, $this->user->worklogs[0]->hours); + $this->assertEquals('Text', $this->user->worklogs[0]->comment); + + $this->assertTrue($this->log->hasInfoThatContains('Created worklog entry')); + } + + /** + * @covers \Engelsystem\Events\Listener\Shifts::deletingCreateWorklogs + */ + public function testDeletingCreateWorklogsIgnoreFreeload(): void + { + $this->entry->freeloaded = true; + $this->entry->save(); + + /** @var Shifts $listener */ + $listener = $this->app->make(Shifts::class); + $listener->deletingCreateWorklogs($this->shift); + + $this->assertCount(0, $this->user->worklogs); + } + + /** + * @covers \Engelsystem\Events\Listener\Shifts::deletingCreateWorklogs + */ + public function testDeletingCreateWorklogsIgnoreNotStarted(): void + { + $this->shift->start = Carbon::now()->addMinutes(42); + $this->shift->save(); + + /** @var Shifts $listener */ + $listener = $this->app->make(Shifts::class); + $listener->deletingCreateWorklogs($this->shift); + + $this->assertCount(0, $this->user->worklogs); + } + + /** + * @covers \Engelsystem\Events\Listener\Shifts::deletingSendEmails + */ + public function testDeletingSendEmailsNoNotification(): void + { + $this->setExpects($this->mailer, 'sendViewTranslated', null, null, $this->never()); + + $this->user->settings->email_shiftinfo = false; + $this->user->settings->save(); + + /** @var Shifts $listener */ + $listener = $this->app->make(Shifts::class); + $listener->deletingSendEmails($this->shift); + } + + /** + * @covers \Engelsystem\Events\Listener\Shifts::deletingSendEmails + */ + public function testDeletingSendEmails(): void + { + $this->mailer->expects($this->once()) + ->method('sendViewTranslated') + ->willReturnCallback(function (User $user, string $subject, string $template, array $data): bool { + $this->assertEquals($this->user->id, $user->id); + $this->assertEquals('notification.shift.deleted', $subject); + $this->assertEquals('emails/worklog-from-shift', $template); + $this->assertArrayHasKey('shift', $data); + $this->assertEquals($this->shift, $data['shift']); + $this->assertArrayHasKey('entry', $data); + $this->assertEquals($this->entry->id, $data['entry']->id); + + return true; + }); + + /** @var Shifts $listener */ + $listener = $this->app->make(Shifts::class); + $listener->deletingSendEmails($this->shift); + } + + /** + * @covers \Engelsystem\Events\Listener\Shifts::updatedSendEmail + */ + public function testUpdatedSendEmailNoRelevantChange(): void + { + $this->setExpects($this->mailer, 'sendViewTranslated', null, null, $this->never()); + + $oldShift = Shift::find($this->shift->id); + $this->shift->description = 'Foo'; + + /** @var Shifts $listener */ + $listener = $this->app->make(Shifts::class); + $listener->updatedSendEmail($this->shift, $oldShift); + } + + /** + * @covers \Engelsystem\Events\Listener\Shifts::updatedSendEmail + */ + public function testUpdatedSendEmailNoNotification(): void + { + $this->setExpects($this->mailer, 'sendViewTranslated', null, null, $this->never()); + + $oldShift = Shift::find($this->shift->id); + $this->shift->title = 'Bar'; + + $this->user->settings->email_shiftinfo = false; + $this->user->settings->save(); + + /** @var Shifts $listener */ + $listener = $this->app->make(Shifts::class); + $listener->updatedSendEmail($this->shift, $oldShift); + } + + /** + * @covers \Engelsystem\Events\Listener\Shifts::updatedSendEmail + */ + public function testUpdatedSendEmailAlreadyEnded(): void + { + $this->setExpects($this->mailer, 'sendViewTranslated', null, null, $this->never()); + + $oldShift = Shift::find($this->shift->id); + $oldShift->end = Carbon::now()->subMinutes(42); + $this->shift->end = Carbon::now()->subMinutes(42); + + /** @var Shifts $listener */ + $listener = $this->app->make(Shifts::class); + $listener->updatedSendEmail($this->shift, $oldShift); + } + + /** + * @covers \Engelsystem\Events\Listener\Shifts::updatedSendEmail + */ + public function testUpdatedSendEmail(): void + { + $oldShift = Shift::find($this->shift->id); + $this->shift->title = 'Bar'; + + $this->mailer->expects($this->once()) + ->method('sendViewTranslated') + ->willReturnCallback(function ( + User $user, + string $subject, + string $template, + array $data + ) use ($oldShift): bool { + $this->assertEquals($this->user->id, $user->id); + $this->assertEquals('notification.shift.updated', $subject); + $this->assertEquals('emails/updated-shift', $template); + $this->assertArrayHasKey('shift', $data); + $this->assertEquals($this->shift, $data['shift']); + $this->assertArrayHasKey('oldShift', $data); + $this->assertEquals($oldShift, $data['oldShift']); + + return true; + }); + + /** @var Shifts $listener */ + $listener = $this->app->make(Shifts::class); + $listener->updatedSendEmail($this->shift, $oldShift); + } + + protected function setUp(): void + { + parent::setUp(); + $this->initDatabase(); + + $this->log = new TestLogger(); + $this->app->instance(LoggerInterface::class, $this->log); + + $this->mailer = $this->createMock(EngelsystemMailer::class); + $this->app->instance(EngelsystemMailer::class, $this->mailer); + + $config = new Config([ + 'night_shifts' => [ + 'enabled' => true, + 'start' => 2, + 'end' => 8, + 'multiplier' => 2, + ], + ]); + $this->app->instance('config', $config); + + $this->translator = $this->createMock(Translator::class); + $this->app->instance('translator', $this->translator); + + $this->user = User::factory() + ->has(Settings::factory([ + 'language' => '', + 'theme' => 1, + 'email_shiftinfo' => true, + ])) + ->create(); + + $start = Carbon::now()->subHour(); + $this->shift = Shift::factory([ + 'title' => 'Foo', + 'start' => $start, + 'end' => $start->copy()->addHours(2), + ])->create(); + $this->entry = ShiftEntry::factory([ + 'shift_id' => $this->shift->id, + 'user_id' => $this->user->id, + 'freeloaded' => false, + ])->create(); + + $this->auth = $this->createMock(Authenticator::class); + $this->app->instance('authenticator', $this->auth); + } +}