phase 6 added helpdesk

This commit is contained in:
Mark Gregory
2026-07-24 11:28:06 +01:00
parent 5ecf20fe97
commit 8c74abfbc6
212 changed files with 23064 additions and 0 deletions
@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace Modules\Helpdesk\Tests\Unit;
use Modules\Helpdesk\Support\Color;
use Tests\TestCase;
final class ColorPaletteTest extends TestCase
{
/** @test */
public function palette_colours_resolve_to_standard_hex_values(): void
{
self::assertSame('#dc2626', Color::css('red'));
self::assertSame('#16a34a', Color::css('green'));
self::assertSame('#2563eb', Color::css('blue'));
self::assertSame('#6b7280', Color::css('gray'));
}
/** @test */
public function legacy_colour_aliases_are_normalised(): void
{
self::assertSame('red', Color::normalise('rose'));
self::assertSame('green', Color::normalise('emerald'));
self::assertSame('blue', Color::normalise('cyan'));
self::assertSame('gray', Color::normalise('zinc'));
}
/** @test */
public function custom_hex_colours_are_supported_and_validated(): void
{
self::assertSame('#ffffff', Color::css('#ffffff'));
self::assertSame('#000000', Color::css('#000000'));
self::assertTrue(Color::isAllowed('#ffffff'));
self::assertFalse(Color::isAllowed('#fff'));
self::assertFalse(Color::isAllowed('brown'));
}
/** @test */
public function readable_text_colour_is_calculated_for_badge_backgrounds(): void
{
self::assertSame('#111827', Color::text('#ffffff'));
self::assertSame('#ffffff', Color::text('#000000'));
self::assertSame('#ffffff', Color::text('red'));
}
}
@@ -0,0 +1,74 @@
<?php
declare(strict_types=1);
namespace Modules\Helpdesk\Tests\Unit;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Modules\Helpdesk\Models\Comment;
use Modules\Helpdesk\Models\GitCommit;
use Modules\Helpdesk\Tests\Concerns\BuildsHelpdeskFixtures;
use Tests\TestCase;
final class ModelRelationshipTest extends TestCase
{
use BuildsHelpdeskFixtures;
use RefreshDatabase;
public function test_ticket_loads_company_project_team_category_priority_status_and_git_commits(): void
{
$fixtures = $this->seedLookupData();
$repository = $this->repository(['project_id' => $fixtures['project']->id]);
$ticket = $this->ticket([
'status_id' => $fixtures['open']->id,
'priority_id' => $fixtures['high']->id,
'category_id' => $fixtures['category']->id,
'team_id' => $fixtures['team']->id,
'project_id' => $fixtures['project']->id,
]);
GitCommit::query()->create([
'repository_id' => $repository->id,
'ticket_id' => $ticket->id,
'hash' => str_repeat('a', 40),
'short_hash' => 'aaaaaaa',
'branch' => 'develop',
'author_name' => 'Developer',
'author_email' => 'dev@example.com',
'message' => 'Fix HD reference handling',
'url' => 'https://example.com/commit/a',
'committed_at' => now(),
]);
$ticket->refresh()->load(['status', 'priority', 'category', 'team', 'project', 'gitCommits']);
self::assertSame('Open', $ticket->status?->name);
self::assertSame('High', $ticket->priority?->name);
self::assertSame('Support', $ticket->category?->name);
self::assertSame('Support Team', $ticket->team?->name);
self::assertSame('WMS Core', $ticket->project?->title);
self::assertCount(1, $ticket->gitCommits);
}
public function test_comments_support_nested_replies(): void
{
$ticket = $this->ticket();
$user = $this->user();
$comment = Comment::query()->create([
'ticket_id' => $ticket->id,
'user_id' => $user->id,
'body' => '<p>Parent response</p>',
'is_internal' => false,
]);
Comment::query()->create([
'ticket_id' => $ticket->id,
'parent_id' => $comment->id,
'user_id' => $user->id,
'body' => '<p>Nested response</p>',
'is_internal' => false,
]);
self::assertSame('Nested response', strip_tags((string) $comment->replies()->firstOrFail()->body));
self::assertCount(1, $ticket->comments()->with('replies')->get());
}
}
@@ -0,0 +1,56 @@
<?php
declare(strict_types=1);
namespace Modules\Helpdesk\Tests\Unit;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Modules\Helpdesk\Services\TicketReferenceService;
use Modules\Helpdesk\Tests\Concerns\BuildsHelpdeskFixtures;
use Tests\TestCase;
final class TicketReferenceServiceTest extends TestCase
{
use BuildsHelpdeskFixtures;
use RefreshDatabase;
public function test_it_generates_the_first_reference_for_the_current_year(): void
{
$reference = app(TicketReferenceService::class)->next();
self::assertSame('HD-' . now()->format('Y') . '-00001', $reference);
}
public function test_it_generates_the_next_reference_after_existing_tickets(): void
{
$this->ticket(['reference' => 'HD-' . now()->format('Y') . '-00041']);
$reference = app(TicketReferenceService::class)->next();
self::assertSame('HD-' . now()->format('Y') . '-00042', $reference);
}
public function test_it_does_not_reuse_soft_deleted_ticket_references(): void
{
$year = now()->format('Y');
$ticket = $this->ticket(['reference' => 'HD-' . $year . '-00002']);
$ticket->delete();
$reference = app(TicketReferenceService::class)->next();
self::assertSame('HD-' . $year . '-00003', $reference);
}
public function test_it_uses_the_highest_reference_suffix_instead_of_latest_database_id(): void
{
$year = now()->format('Y');
$this->ticket(['reference' => 'HD-' . $year . '-00042']);
$this->ticket(['reference' => 'HD-' . $year . '-00002']);
$reference = app(TicketReferenceService::class)->next();
self::assertSame('HD-' . $year . '-00043', $reference);
}
}