Add exception for deleting member
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details

This commit is contained in:
philipp lang 2023-08-16 01:07:48 +02:00
parent aeb926e165
commit 74c5faaebd
5 changed files with 51 additions and 5 deletions

View File

@ -0,0 +1,7 @@
<?php
namespace App\Lib\Events;
class JobFailed extends JobEvent
{
}

View File

@ -2,16 +2,19 @@
namespace App\Lib\JobMiddleware; namespace App\Lib\JobMiddleware;
use App\Lib\Events\JobFailed;
use App\Lib\Events\JobFinished; use App\Lib\Events\JobFinished;
use App\Lib\Events\JobStarted; use App\Lib\Events\JobStarted;
use Closure; use Closure;
use Lorisleiva\Actions\Decorators\JobDecorator; use Lorisleiva\Actions\Decorators\JobDecorator;
use Throwable;
class WithJobState class WithJobState
{ {
public JobStarted $beforeMessage; public JobStarted $beforeMessage;
public JobFinished $afterMessage; public JobFinished $afterMessage;
public JobFailed $failedMessage;
private function __construct(public string $channel) private function __construct(public string $channel)
{ {
@ -36,9 +39,17 @@ class WithJobState
return $this; return $this;
} }
public function failed(string $message): self
{
$this->failedMessage = JobFailed::on($this->channel)->withMessage($message);
return $this;
}
public function shouldReload(): self public function shouldReload(): self
{ {
$this->afterMessage->shouldReload(); $this->afterMessage->shouldReload();
$this->failedMessage->shouldReload();
return $this; return $this;
} }
@ -46,7 +57,14 @@ class WithJobState
public function handle(JobDecorator $job, Closure $next): void public function handle(JobDecorator $job, Closure $next): void
{ {
event($this->beforeMessage); event($this->beforeMessage);
try {
$next($job); $next($job);
} catch (Throwable $e) {
event($this->failedMessage);
throw $e;
}
event($this->afterMessage); event($this->afterMessage);
} }
} }

View File

@ -43,6 +43,7 @@ class MemberDeleteAction
WithJobState::make('member') WithJobState::make('member')
->before('Lösche Mitglied ' . $member->fullname) ->before('Lösche Mitglied ' . $member->fullname)
->after('Mitglied ' . $member->fullname . ' gelöscht') ->after('Mitglied ' . $member->fullname . ' gelöscht')
->failed('Löschen von ' . $member->fullname . ' fehlgeschlagen.')
->shouldReload(), ->shouldReload(),
]; ];
} }

View File

@ -61,9 +61,9 @@ export function useIndex(props, siteName) {
}; };
} }
function handleJobEvent(event) { function handleJobEvent(event, type = 'success') {
if (event.message) { if (event.message) {
toast.success(event.message); toast[type](event.message);
} }
if (event.reload) { if (event.reload) {
reload(false); reload(false);
@ -73,7 +73,8 @@ export function useIndex(props, siteName) {
window.Echo.channel('jobs').listen('\\App\\Lib\\Events\\ClientMessage', (e) => handleJobEvent(e)); window.Echo.channel('jobs').listen('\\App\\Lib\\Events\\ClientMessage', (e) => handleJobEvent(e));
window.Echo.channel(siteName) window.Echo.channel(siteName)
.listen('\\App\\Lib\\Events\\JobStarted', (e) => handleJobEvent(e)) .listen('\\App\\Lib\\Events\\JobStarted', (e) => handleJobEvent(e))
.listen('\\App\\Lib\\Events\\JobFinished', (e) => handleJobEvent(e)); .listen('\\App\\Lib\\Events\\JobFinished', (e) => handleJobEvent(e))
.listen('\\App\\Lib\\Events\\JobFailed', (e) => handleJobEvent(e, 'error'));
onBeforeUnmount(() => window.Echo.leave(siteName)); onBeforeUnmount(() => window.Echo.leave(siteName));
onBeforeUnmount(() => window.Echo.leave('jobs')); onBeforeUnmount(() => window.Echo.leave('jobs'));

View File

@ -4,16 +4,18 @@ namespace Tests\Feature\Member;
use App\Course\Models\Course; use App\Course\Models\Course;
use App\Course\Models\CourseMember; use App\Course\Models\CourseMember;
use App\Lib\Events\ClientMessage; use App\Lib\Events\JobFailed;
use App\Lib\Events\JobFinished; use App\Lib\Events\JobFinished;
use App\Lib\Events\JobStarted; use App\Lib\Events\JobStarted;
use App\Member\Actions\MemberDeleteAction; use App\Member\Actions\MemberDeleteAction;
use App\Member\Actions\NamiDeleteMemberAction; use App\Member\Actions\NamiDeleteMemberAction;
use App\Member\Member; use App\Member\Member;
use Exception;
use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Queue;
use Tests\TestCase; use Tests\TestCase;
use Throwable;
class DeleteTest extends TestCase class DeleteTest extends TestCase
{ {
@ -76,4 +78,21 @@ class DeleteTest extends TestCase
Event::assertDispatched(JobStarted::class, fn ($event) => $event->broadcastOn()->name === 'member' && $event->message === 'Lösche Mitglied Max Muster' && $event->reload === false); Event::assertDispatched(JobStarted::class, fn ($event) => $event->broadcastOn()->name === 'member' && $event->message === 'Lösche Mitglied Max Muster' && $event->reload === false);
Event::assertDispatched(JobFinished::class, fn ($event) => $event->message === 'Mitglied Max Muster gelöscht' && $event->reload === true); Event::assertDispatched(JobFinished::class, fn ($event) => $event->message === 'Mitglied Max Muster gelöscht' && $event->reload === true);
} }
public function testItFiresEventWhenDeletingFailed(): void
{
Event::fake([JobStarted::class, JobFinished::class, JobFailed::class]);
$this->login()->loginNami();
$member = Member::factory()->defaults()->create(['firstname' => 'Max', 'lastname' => 'Muster']);
MemberDeleteAction::partialMock()->shouldReceive('handle')->andThrow(new Exception('sorry'));
try {
MemberDeleteAction::dispatch($member->id);
} catch (Throwable) {
}
Event::assertDispatched(JobStarted::class, fn ($event) => $event->broadcastOn()->name === 'member' && $event->message === 'Lösche Mitglied Max Muster' && $event->reload === false);
Event::assertDispatched(JobFailed::class, fn ($event) => $event->message === 'Löschen von Max Muster fehlgeschlagen.' && $event->reload === true);
Event::assertNotDispatched(JobFinished::class);
}
} }