forked from fa/breadcrumb-the-shire
test(helpdesk): add tests for assign, submitForReview, resendNotification and HandoverNotificationService
HandoverServiceTest: 30 new cases covering: - assign(): happy path, draft→in_progress transition, permission check, zero assignedTo, not found, email sent, due date passed to repo - submitForReview(): assignee and manager paths, non-assignee denied, wrong status (under_review/completed), revision created, email sent - resendNotification(): happy path, permission denied, no assignee - statusLabel/Variant for under_review HandoverNotificationServiceTest: 9 new cases covering: - notifyAssigned: sends correct template+vars, skips on empty/null email, fallback dash for empty debitor and due_date - notifyReviewRequested: sends to manager, skips on no email, fallback dash for empty assignee name 48 tests total, all passing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,153 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MintyPHP\Tests\Module\Helpdesk\Service;
|
||||||
|
|
||||||
|
use MintyPHP\Module\Helpdesk\Service\HandoverNotificationService;
|
||||||
|
use MintyPHP\Service\Mail\MailService;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class HandoverNotificationServiceTest extends TestCase
|
||||||
|
{
|
||||||
|
private function createNotificationService(?MailService $mailService = null): HandoverNotificationService
|
||||||
|
{
|
||||||
|
return new HandoverNotificationService(
|
||||||
|
$mailService ?? $this->createMock(MailService::class)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function assignedHandover(array $overrides = []): array
|
||||||
|
{
|
||||||
|
return array_merge([
|
||||||
|
'id' => 1,
|
||||||
|
'debitor_name' => 'Acme Corp',
|
||||||
|
'domain_url' => 'example.com',
|
||||||
|
'due_date' => '2026-12-31',
|
||||||
|
'assigned_to_email' => 'employee@example.com',
|
||||||
|
'assigned_to_label' => 'John Doe',
|
||||||
|
'assigned_by_label' => 'Manager',
|
||||||
|
'assigned_by_email' => 'manager@example.com',
|
||||||
|
], $overrides);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── notifyAssigned ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
public function testNotifyAssignedSendsEmailToAssignee(): void
|
||||||
|
{
|
||||||
|
$mailService = $this->createMock(MailService::class);
|
||||||
|
$mailService->expects($this->once())
|
||||||
|
->method('sendTemplate')
|
||||||
|
->with(
|
||||||
|
'handover_assigned',
|
||||||
|
$this->callback(fn (array $vars): bool => $vars['assignee_name'] === 'John Doe'
|
||||||
|
&& $vars['assigned_by_name'] === 'Manager'
|
||||||
|
&& $vars['debitor_name'] === 'Acme Corp'
|
||||||
|
&& $vars['due_date'] === '2026-12-31'
|
||||||
|
),
|
||||||
|
'employee@example.com',
|
||||||
|
$this->isType('string')
|
||||||
|
);
|
||||||
|
|
||||||
|
$service = $this->createNotificationService($mailService);
|
||||||
|
$service->notifyAssigned($this->assignedHandover());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNotifyAssignedSkipsWhenNoEmail(): void
|
||||||
|
{
|
||||||
|
$mailService = $this->createMock(MailService::class);
|
||||||
|
$mailService->expects($this->never())->method('sendTemplate');
|
||||||
|
|
||||||
|
$service = $this->createNotificationService($mailService);
|
||||||
|
$service->notifyAssigned($this->assignedHandover(['assigned_to_email' => '']));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNotifyAssignedSkipsWhenEmailIsNull(): void
|
||||||
|
{
|
||||||
|
$mailService = $this->createMock(MailService::class);
|
||||||
|
$mailService->expects($this->never())->method('sendTemplate');
|
||||||
|
|
||||||
|
$service = $this->createNotificationService($mailService);
|
||||||
|
$service->notifyAssigned($this->assignedHandover(['assigned_to_email' => null]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNotifyAssignedFallsBackToDashForEmptyDebitor(): void
|
||||||
|
{
|
||||||
|
$mailService = $this->createMock(MailService::class);
|
||||||
|
$mailService->expects($this->once())
|
||||||
|
->method('sendTemplate')
|
||||||
|
->with(
|
||||||
|
'handover_assigned',
|
||||||
|
$this->callback(fn (array $vars): bool => $vars['debitor_name'] === '—'),
|
||||||
|
$this->anything(),
|
||||||
|
$this->anything()
|
||||||
|
);
|
||||||
|
|
||||||
|
$service = $this->createNotificationService($mailService);
|
||||||
|
$service->notifyAssigned($this->assignedHandover(['debitor_name' => '']));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNotifyAssignedFallsBackToDashForEmptyDueDate(): void
|
||||||
|
{
|
||||||
|
$mailService = $this->createMock(MailService::class);
|
||||||
|
$mailService->expects($this->once())
|
||||||
|
->method('sendTemplate')
|
||||||
|
->with(
|
||||||
|
'handover_assigned',
|
||||||
|
$this->callback(fn (array $vars): bool => $vars['due_date'] === '—'),
|
||||||
|
$this->anything(),
|
||||||
|
$this->anything()
|
||||||
|
);
|
||||||
|
|
||||||
|
$service = $this->createNotificationService($mailService);
|
||||||
|
$service->notifyAssigned($this->assignedHandover(['due_date' => '']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── notifyReviewRequested ─────────────────────────────────────────
|
||||||
|
|
||||||
|
public function testNotifyReviewRequestedSendsEmailToManager(): void
|
||||||
|
{
|
||||||
|
$mailService = $this->createMock(MailService::class);
|
||||||
|
$mailService->expects($this->once())
|
||||||
|
->method('sendTemplate')
|
||||||
|
->with(
|
||||||
|
'handover_review_requested',
|
||||||
|
$this->callback(fn (array $vars): bool => $vars['manager_name'] === 'Manager'
|
||||||
|
&& $vars['assignee_name'] === 'John Doe'
|
||||||
|
&& $vars['debitor_name'] === 'Acme Corp'
|
||||||
|
),
|
||||||
|
'manager@example.com',
|
||||||
|
$this->isType('string')
|
||||||
|
);
|
||||||
|
|
||||||
|
$service = $this->createNotificationService($mailService);
|
||||||
|
$service->notifyReviewRequested($this->assignedHandover([
|
||||||
|
'assigned_to_label' => 'John Doe',
|
||||||
|
'assigned_by_label' => 'Manager',
|
||||||
|
'assigned_by_email' => 'manager@example.com',
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNotifyReviewRequestedSkipsWhenNoManagerEmail(): void
|
||||||
|
{
|
||||||
|
$mailService = $this->createMock(MailService::class);
|
||||||
|
$mailService->expects($this->never())->method('sendTemplate');
|
||||||
|
|
||||||
|
$service = $this->createNotificationService($mailService);
|
||||||
|
$service->notifyReviewRequested($this->assignedHandover(['assigned_by_email' => '']));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNotifyReviewRequestedFallsBackToDashForEmptyAssigneeName(): void
|
||||||
|
{
|
||||||
|
$mailService = $this->createMock(MailService::class);
|
||||||
|
$mailService->expects($this->once())
|
||||||
|
->method('sendTemplate')
|
||||||
|
->with(
|
||||||
|
'handover_review_requested',
|
||||||
|
$this->callback(fn (array $vars): bool => $vars['assignee_name'] === '—'),
|
||||||
|
$this->anything(),
|
||||||
|
$this->anything()
|
||||||
|
);
|
||||||
|
|
||||||
|
$service = $this->createNotificationService($mailService);
|
||||||
|
$service->notifyReviewRequested($this->assignedHandover(['assigned_to_label' => '']));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace MintyPHP\Tests\Module\Helpdesk\Service;
|
namespace MintyPHP\Tests\Module\Helpdesk\Service;
|
||||||
|
|
||||||
use MintyPHP\Module\Helpdesk\Repository\HandoverRepository;
|
use MintyPHP\Module\Helpdesk\Repository\HandoverRepository;
|
||||||
|
use MintyPHP\Module\Helpdesk\Service\HandoverNotificationService;
|
||||||
use MintyPHP\Module\Helpdesk\Service\HandoverRevisionService;
|
use MintyPHP\Module\Helpdesk\Service\HandoverRevisionService;
|
||||||
use MintyPHP\Module\Helpdesk\Service\HandoverService;
|
use MintyPHP\Module\Helpdesk\Service\HandoverService;
|
||||||
use MintyPHP\Module\Helpdesk\Service\SoftwareProductService;
|
use MintyPHP\Module\Helpdesk\Service\SoftwareProductService;
|
||||||
@@ -19,11 +20,30 @@ class HandoverServiceTest extends TestCase
|
|||||||
?HandoverRepository $repository = null,
|
?HandoverRepository $repository = null,
|
||||||
?SoftwareProductService $productService = null,
|
?SoftwareProductService $productService = null,
|
||||||
?HandoverRevisionService $revisionService = null,
|
?HandoverRevisionService $revisionService = null,
|
||||||
|
?HandoverNotificationService $notificationService = null,
|
||||||
): HandoverService {
|
): HandoverService {
|
||||||
$repository = $repository ?? $this->createMock(HandoverRepository::class);
|
$repository = $repository ?? $this->createMock(HandoverRepository::class);
|
||||||
$productService = $productService ?? $this->createMock(SoftwareProductService::class);
|
$productService = $productService ?? $this->createMock(SoftwareProductService::class);
|
||||||
|
|
||||||
return new HandoverService($repository, $productService, $revisionService);
|
return new HandoverService($repository, $productService, $revisionService, $notificationService);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handoverRow(array $overrides = []): array
|
||||||
|
{
|
||||||
|
return array_merge([
|
||||||
|
'id' => 1,
|
||||||
|
'tenant_id' => self::TENANT_ID,
|
||||||
|
'status' => HandoverService::STATUS_IN_PROGRESS,
|
||||||
|
'assigned_to' => 0,
|
||||||
|
'assigned_by' => 0,
|
||||||
|
'debitor_name' => 'Acme Corp',
|
||||||
|
'domain_url' => 'example.com',
|
||||||
|
'due_date' => null,
|
||||||
|
'assigned_to_label' => null,
|
||||||
|
'assigned_to_email' => null,
|
||||||
|
'assigned_by_label' => null,
|
||||||
|
'assigned_by_email' => null,
|
||||||
|
], $overrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function mockProductService(bool $exists = true, bool $hasSchema = true): SoftwareProductService
|
private function mockProductService(bool $exists = true, bool $hasSchema = true): SoftwareProductService
|
||||||
@@ -332,6 +352,288 @@ class HandoverServiceTest extends TestCase
|
|||||||
$service->createRevisionAfterSave(self::TENANT_ID, 1, ['name' => 'Test'], 'draft', false, false, 1, self::USER_ID);
|
$service->createRevisionAfterSave(self::TENANT_ID, 1, ['name' => 'Test'], 'draft', false, false, 1, self::USER_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Assign tests ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
public function testAssignHappyPath(): void
|
||||||
|
{
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn($this->handoverRow(['status' => HandoverService::STATUS_IN_PROGRESS]));
|
||||||
|
$repo->expects($this->once())->method('assign')->willReturn(true);
|
||||||
|
$repo->expects($this->never())->method('updateStatus');
|
||||||
|
|
||||||
|
$service = $this->createService($repo);
|
||||||
|
$result = $service->assign(self::TENANT_ID, 1, 99, self::USER_ID, null, HandoverService::PERMISSION_MANAGE);
|
||||||
|
|
||||||
|
$this->assertTrue($result['ok']);
|
||||||
|
$this->assertEmpty($result['errors']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAssignDraftHandoverTransitionsToInProgress(): void
|
||||||
|
{
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn($this->handoverRow(['status' => HandoverService::STATUS_DRAFT]));
|
||||||
|
$repo->method('assign')->willReturn(true);
|
||||||
|
$repo->expects($this->once())
|
||||||
|
->method('updateStatus')
|
||||||
|
->with(self::TENANT_ID, 1, HandoverService::STATUS_IN_PROGRESS, self::USER_ID);
|
||||||
|
|
||||||
|
$service = $this->createService($repo);
|
||||||
|
$result = $service->assign(self::TENANT_ID, 1, 99, self::USER_ID, null, HandoverService::PERMISSION_MANAGE);
|
||||||
|
|
||||||
|
$this->assertTrue($result['ok']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAssignDeniedForCreatePermission(): void
|
||||||
|
{
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->expects($this->never())->method('assign');
|
||||||
|
|
||||||
|
$service = $this->createService($repo);
|
||||||
|
$result = $service->assign(self::TENANT_ID, 1, 99, self::USER_ID, null, HandoverService::PERMISSION_CREATE);
|
||||||
|
|
||||||
|
$this->assertFalse($result['ok']);
|
||||||
|
$this->assertArrayHasKey('general', $result['errors']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAssignFailsWhenAssignedToIsZero(): void
|
||||||
|
{
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn($this->handoverRow());
|
||||||
|
$repo->expects($this->never())->method('assign');
|
||||||
|
|
||||||
|
$service = $this->createService($repo);
|
||||||
|
$result = $service->assign(self::TENANT_ID, 1, 0, self::USER_ID, null, HandoverService::PERMISSION_MANAGE);
|
||||||
|
|
||||||
|
$this->assertFalse($result['ok']);
|
||||||
|
$this->assertArrayHasKey('assigned_to', $result['errors']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAssignFailsWhenHandoverNotFound(): void
|
||||||
|
{
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn(null);
|
||||||
|
|
||||||
|
$service = $this->createService($repo);
|
||||||
|
$result = $service->assign(self::TENANT_ID, 1, 99, self::USER_ID, null, HandoverService::PERMISSION_MANAGE);
|
||||||
|
|
||||||
|
$this->assertFalse($result['ok']);
|
||||||
|
$this->assertArrayHasKey('general', $result['errors']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAssignSendsNotificationEmail(): void
|
||||||
|
{
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn($this->handoverRow([
|
||||||
|
'assigned_to_email' => 'employee@example.com',
|
||||||
|
'assigned_to_label' => 'John Doe',
|
||||||
|
]));
|
||||||
|
$repo->method('assign')->willReturn(true);
|
||||||
|
|
||||||
|
$notificationService = $this->createMock(HandoverNotificationService::class);
|
||||||
|
$notificationService->expects($this->once())->method('notifyAssigned');
|
||||||
|
|
||||||
|
$service = $this->createService($repo, notificationService: $notificationService);
|
||||||
|
$service->assign(self::TENANT_ID, 1, 99, self::USER_ID, null, HandoverService::PERMISSION_MANAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAssignWithDueDatePassesItToRepository(): void
|
||||||
|
{
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn($this->handoverRow());
|
||||||
|
$repo->expects($this->once())
|
||||||
|
->method('assign')
|
||||||
|
->with(self::TENANT_ID, 1, 99, self::USER_ID, '2026-12-31', self::USER_ID)
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
|
$service = $this->createService($repo);
|
||||||
|
$result = $service->assign(self::TENANT_ID, 1, 99, self::USER_ID, '2026-12-31', HandoverService::PERMISSION_MANAGE);
|
||||||
|
|
||||||
|
$this->assertTrue($result['ok']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Submit for review tests ───────────────────────────────────────
|
||||||
|
|
||||||
|
public function testSubmitForReviewHappyPathByAssignee(): void
|
||||||
|
{
|
||||||
|
$assigneeId = 99;
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn($this->handoverRow([
|
||||||
|
'assigned_to' => $assigneeId,
|
||||||
|
'status' => HandoverService::STATUS_IN_PROGRESS,
|
||||||
|
]));
|
||||||
|
$repo->expects($this->once())
|
||||||
|
->method('updateStatus')
|
||||||
|
->with(self::TENANT_ID, 1, HandoverService::STATUS_UNDER_REVIEW, $assigneeId)
|
||||||
|
->willReturn(true);
|
||||||
|
|
||||||
|
$service = $this->createService($repo);
|
||||||
|
$result = $service->submitForReview(self::TENANT_ID, 1, $assigneeId, HandoverService::PERMISSION_CREATE);
|
||||||
|
|
||||||
|
$this->assertTrue($result['ok']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSubmitForReviewAllowedForManager(): void
|
||||||
|
{
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn($this->handoverRow([
|
||||||
|
'assigned_to' => 99,
|
||||||
|
'status' => HandoverService::STATUS_DRAFT,
|
||||||
|
]));
|
||||||
|
$repo->method('updateStatus')->willReturn(true);
|
||||||
|
|
||||||
|
$service = $this->createService($repo);
|
||||||
|
$result = $service->submitForReview(self::TENANT_ID, 1, self::USER_ID, HandoverService::PERMISSION_MANAGE);
|
||||||
|
|
||||||
|
$this->assertTrue($result['ok']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSubmitForReviewDeniedForNonAssignee(): void
|
||||||
|
{
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn($this->handoverRow([
|
||||||
|
'assigned_to' => 99,
|
||||||
|
'status' => HandoverService::STATUS_IN_PROGRESS,
|
||||||
|
]));
|
||||||
|
|
||||||
|
$service = $this->createService($repo);
|
||||||
|
$result = $service->submitForReview(self::TENANT_ID, 1, self::USER_ID, HandoverService::PERMISSION_CREATE);
|
||||||
|
|
||||||
|
$this->assertFalse($result['ok']);
|
||||||
|
$this->assertArrayHasKey('general', $result['errors']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSubmitForReviewDeniedWhenStatusIsUnderReview(): void
|
||||||
|
{
|
||||||
|
$assigneeId = 99;
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn($this->handoverRow([
|
||||||
|
'assigned_to' => $assigneeId,
|
||||||
|
'status' => HandoverService::STATUS_UNDER_REVIEW,
|
||||||
|
]));
|
||||||
|
|
||||||
|
$service = $this->createService($repo);
|
||||||
|
$result = $service->submitForReview(self::TENANT_ID, 1, $assigneeId, HandoverService::PERMISSION_CREATE);
|
||||||
|
|
||||||
|
$this->assertFalse($result['ok']);
|
||||||
|
$this->assertArrayHasKey('status', $result['errors']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSubmitForReviewDeniedWhenStatusIsCompleted(): void
|
||||||
|
{
|
||||||
|
$assigneeId = 99;
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn($this->handoverRow([
|
||||||
|
'assigned_to' => $assigneeId,
|
||||||
|
'status' => HandoverService::STATUS_COMPLETED,
|
||||||
|
]));
|
||||||
|
|
||||||
|
$service = $this->createService($repo);
|
||||||
|
$result = $service->submitForReview(self::TENANT_ID, 1, $assigneeId, HandoverService::PERMISSION_CREATE);
|
||||||
|
|
||||||
|
$this->assertFalse($result['ok']);
|
||||||
|
$this->assertArrayHasKey('status', $result['errors']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSubmitForReviewSendsReviewRequestedEmail(): void
|
||||||
|
{
|
||||||
|
$assigneeId = 99;
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn($this->handoverRow([
|
||||||
|
'assigned_to' => $assigneeId,
|
||||||
|
'status' => HandoverService::STATUS_IN_PROGRESS,
|
||||||
|
'assigned_by_email' => 'manager@example.com',
|
||||||
|
]));
|
||||||
|
$repo->method('updateStatus')->willReturn(true);
|
||||||
|
|
||||||
|
$notificationService = $this->createMock(HandoverNotificationService::class);
|
||||||
|
$notificationService->expects($this->once())->method('notifyReviewRequested');
|
||||||
|
|
||||||
|
$service = $this->createService($repo, notificationService: $notificationService);
|
||||||
|
$service->submitForReview(self::TENANT_ID, 1, $assigneeId, HandoverService::PERMISSION_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSubmitForReviewCreatesRevision(): void
|
||||||
|
{
|
||||||
|
$assigneeId = 99;
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn($this->handoverRow([
|
||||||
|
'assigned_to' => $assigneeId,
|
||||||
|
'status' => HandoverService::STATUS_IN_PROGRESS,
|
||||||
|
]));
|
||||||
|
$repo->method('updateStatus')->willReturn(true);
|
||||||
|
|
||||||
|
$revisionService = $this->createMock(HandoverRevisionService::class);
|
||||||
|
$revisionService->expects($this->once())
|
||||||
|
->method('createRevision')
|
||||||
|
->with(
|
||||||
|
self::TENANT_ID,
|
||||||
|
1,
|
||||||
|
[],
|
||||||
|
HandoverService::STATUS_UNDER_REVIEW,
|
||||||
|
1,
|
||||||
|
$assigneeId,
|
||||||
|
HandoverRevisionService::CHANGE_TYPE_STATUS
|
||||||
|
);
|
||||||
|
|
||||||
|
$service = $this->createService($repo, revisionService: $revisionService);
|
||||||
|
$service->submitForReview(self::TENANT_ID, 1, $assigneeId, HandoverService::PERMISSION_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Resend notification tests ─────────────────────────────────────
|
||||||
|
|
||||||
|
public function testResendNotificationHappyPath(): void
|
||||||
|
{
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn($this->handoverRow(['assigned_to' => 99]));
|
||||||
|
|
||||||
|
$notificationService = $this->createMock(HandoverNotificationService::class);
|
||||||
|
$notificationService->expects($this->once())->method('notifyAssigned');
|
||||||
|
|
||||||
|
$service = $this->createService($repo, notificationService: $notificationService);
|
||||||
|
$result = $service->resendNotification(self::TENANT_ID, 1, HandoverService::PERMISSION_MANAGE);
|
||||||
|
|
||||||
|
$this->assertTrue($result['ok']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testResendNotificationDeniedForCreatePermission(): void
|
||||||
|
{
|
||||||
|
$notificationService = $this->createMock(HandoverNotificationService::class);
|
||||||
|
$notificationService->expects($this->never())->method('notifyAssigned');
|
||||||
|
|
||||||
|
$service = $this->createService(notificationService: $notificationService);
|
||||||
|
$result = $service->resendNotification(self::TENANT_ID, 1, HandoverService::PERMISSION_CREATE);
|
||||||
|
|
||||||
|
$this->assertFalse($result['ok']);
|
||||||
|
$this->assertArrayHasKey('general', $result['errors']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testResendNotificationFailsWhenNoAssignee(): void
|
||||||
|
{
|
||||||
|
$repo = $this->createMock(HandoverRepository::class);
|
||||||
|
$repo->method('findById')->willReturn($this->handoverRow(['assigned_to' => 0]));
|
||||||
|
|
||||||
|
$notificationService = $this->createMock(HandoverNotificationService::class);
|
||||||
|
$notificationService->expects($this->never())->method('notifyAssigned');
|
||||||
|
|
||||||
|
$service = $this->createService($repo, notificationService: $notificationService);
|
||||||
|
$result = $service->resendNotification(self::TENANT_ID, 1, HandoverService::PERMISSION_MANAGE);
|
||||||
|
|
||||||
|
$this->assertFalse($result['ok']);
|
||||||
|
$this->assertArrayHasKey('general', $result['errors']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Status label / variant tests ─────────────────────────────────
|
||||||
|
|
||||||
|
public function testStatusLabelUnderReview(): void
|
||||||
|
{
|
||||||
|
$this->assertNotEmpty(HandoverService::statusLabel(HandoverService::STATUS_UNDER_REVIEW));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testStatusVariantUnderReview(): void
|
||||||
|
{
|
||||||
|
$this->assertSame('info', HandoverService::statusVariant(HandoverService::STATUS_UNDER_REVIEW));
|
||||||
|
}
|
||||||
|
|
||||||
// ── Delete tests ─────────────────────────────────────────────────
|
// ── Delete tests ─────────────────────────────────────────────────
|
||||||
|
|
||||||
public function testDeleteByIdsHappyPath(): void
|
public function testDeleteByIdsHappyPath(): void
|
||||||
|
|||||||
Reference in New Issue
Block a user