Files
Leantime/tests/Unit/app/Domain/Tickets/Events/TicketsEventsBcTest.php

96 lines
5.5 KiB
PHP

<?php
namespace Unit\app\Domain\Tickets\Events;
use Codeception\Test\Unit;
use Leantime\Domain\Tickets\Events\MilestoneCreated;
use Leantime\Domain\Tickets\Events\MilestoneDeleted;
use Leantime\Domain\Tickets\Events\MilestoneUpdated;
use Leantime\Domain\Tickets\Events\StatusLabelsUpdated;
use Leantime\Domain\Tickets\Events\TicketCreated;
use Leantime\Domain\Tickets\Events\TicketDeleted;
use Leantime\Domain\Tickets\Events\TicketListFilter;
use Leantime\Domain\Tickets\Events\TicketStatusUpdated;
use Leantime\Domain\Tickets\Events\TicketUpdated;
use Leantime\Domain\Tickets\Events\TodoWidgetTasksFilter;
/**
* Backwards-compatibility contract for the Tickets pilot: every migrated emit site must
* keep producing the EXACT historical string name it fired under before the class-based
* migration (audited 2026-06). Plugins (Copilot, Llamadorian, Reactions, RecurringTasks,
* observability wildcards) subscribe to these strings — a mismatch silently orphans them.
*
* The expected names are frozen from the pre-migration audit. If this test fails, fix the
* event class or call site — do NOT update the expected name unless the corresponding
* legacy hook is being intentionally retired at the end of the migration window.
*/
class TicketsEventsBcTest extends Unit
{
public function test_every_migrated_emit_site_produces_its_audited_historical_name(): void
{
$prefix = 'leantime.domain.tickets.services.tickets.';
$repoPrefix = 'leantime.domain.tickets.repositories.tickets.';
$expectations = [
// events — services
[new TicketCreated(ticketId: 1, legacyHook: 'quickAddTicket'), $prefix.'quickAddTicket.ticket_created'],
[new TicketCreated(ticketId: 1, legacyHook: 'addTicket'), $prefix.'addTicket.ticket_created'],
[new TicketCreated(legacyHook: 'upsertSubtask'), $prefix.'upsertSubtask.ticket_created'],
[new TicketUpdated(ticketId: 1, legacyHook: 'updateTicket'), $prefix.'updateTicket.ticket_updated'],
[new TicketUpdated(ticketId: 1, legacyHook: 'patch'), $prefix.'patch.ticket_updated'],
[new TicketUpdated(ticketId: 1, legacyHook: 'upsertSubtask'), $prefix.'upsertSubtask.ticket_updated'],
[new TicketUpdated(legacyHook: 'updateTicketSorting'), $prefix.'updateTicketSorting.ticket_updated'],
[new TicketUpdated(legacyHook: 'updateTicketStatusAndSorting'), $prefix.'updateTicketStatusAndSorting.ticket_updated'],
[new TicketDeleted(ticketId: 1, legacyHook: 'delete'), $prefix.'delete.ticket_deleted'],
[new MilestoneCreated(legacyHook: 'quickAddMilestone'), $prefix.'quickAddMilestone.milestone_created'],
[new MilestoneUpdated(milestoneId: 1, legacyHook: 'quickUpdateMilestone'), $prefix.'quickUpdateMilestone.milestone_updated'],
[new MilestoneDeleted(milestoneId: 1, legacyHook: 'deleteMilestone'), $prefix.'deleteMilestone.milestone_deleted'],
[new StatusLabelsUpdated(projectId: 1, legacyHook: 'saveStatusLabels'), $prefix.'saveStatusLabels.statusLabels_updated'],
// events — repository
[new TicketStatusUpdated(ticketId: 1, status: 3, legacyHook: 'patchTicket'), $repoPrefix.'patchTicket.ticketStatusUpdate'],
[new TicketStatusUpdated(ticketId: 1, status: 3, legacyHook: 'updateTicketStatus'), $repoPrefix.'updateTicketStatus.ticketStatusUpdate'],
// filters
[new TicketListFilter(tickets: [], legacyHook: 'getTicketTemplateAssignments'), $prefix.'getTicketTemplateAssignments.filterTickets'],
[new TodoWidgetTasksFilter(tickets: [], legacyHook: 'getToDoWidgetAssignments'), $prefix.'getToDoWidgetAssignments.myTodoWidgetTasks'],
[new TodoWidgetTasksFilter(tickets: [], hierarchical: true, legacyHook: 'getToDoWidgetHierarchicalAssignments'), $prefix.'getToDoWidgetHierarchicalAssignments.myTodoWidgetTasks'],
];
foreach ($expectations as [$event, $expectedName]) {
$this->assertSame(
[$expectedName],
$event->legacyHooks(),
get_class($event).' must keep firing its audited historical name'
);
}
}
/**
* Each emit site passes __FUNCTION__ as the legacy hook, so the method names baked
* into the expectations above must actually exist on the emitting classes — guards
* against renames silently orphaning the legacy names.
*/
public function test_legacy_hook_method_names_still_exist_on_emitters(): void
{
$serviceMethods = [
'saveStatusLabels', 'quickAddTicket', 'quickAddMilestone', 'addTicket',
'updateTicket', 'patch', 'quickUpdateMilestone', 'upsertSubtask',
'updateTicketSorting', 'updateTicketStatusAndSorting', 'delete', 'deleteMilestone',
'getTicketTemplateAssignments', 'getToDoWidgetAssignments', 'getToDoWidgetHierarchicalAssignments',
];
foreach ($serviceMethods as $method) {
$this->assertTrue(
method_exists(\Leantime\Domain\Tickets\Services\Tickets::class, $method),
"Tickets service method {$method} was renamed — its legacy event name is now orphaned"
);
}
foreach (['patchTicket', 'updateTicketStatus'] as $method) {
$this->assertTrue(
method_exists(\Leantime\Domain\Tickets\Repositories\Tickets::class, $method),
"Tickets repository method {$method} was renamed — its legacy event name is now orphaned"
);
}
}
}