Testovanie
Tickets::fake() vymení manažéra za TicketsFake a vráti ho:
use RoundlyConsulting\Tickets\Facades\Tickets;
$fake = Tickets::fake();
// … exercise your app …
$fake->assertCreated(fn (Ticket $ticket) => $ticket->subject === 'Printer jammed');
$fake->assertReplied('TCK-1', role: 'agent');
$fake->assertTransitioned('TCK-1', 'resolve');
$fake->assertNothingMerged();
// …or straight on the facade — every assertion is documented there, so the IDE completes it
Tickets::assertAssigned('TCK-1', $agent);- Je to nahrávací fake, ktorý volania aj vykoná: každé volanie beží naozaj — riadky, udalosti, lifecycle, policy, notifikácie — a každá úspešná operácia sa zaznamená. Volanie, ktoré vyhodí výnimku, nezaznamená nič.
- Vymení sa za fasádou aj v kontajneri, takže sa podvrhne aj injektovaný TicketsManager. Zaznamená fasádu, injektovaného manažéra, handle, pod-prístup, builder aj metódu modelu ($ticket->assignTo(), $user->openTicket()); priame volanie triedy akcie sa nezaznamená.
- Keďže volania vykonáva, test s fake potrebuje databázu (publikované migrácie) ako každý iný.
- Udalosti ani notifikácie Laravelu nepodvrhuje — vedľa neho použite Event::fake() / Notification::fake().
Zaznamenané operácie
$fake->recorded(?TicketOperation $operation = null) — alebo Tickets::recorded() — vráti surové záznamy RecordedTicketOperation: operation, context a result. Kontext nesie aktéra handlu a príznak system plus vlastné argumenty volania (data, priority, transition, assignee, tags, …). Každý záznam má ticket(), concerns(Ticket|string|null $ticket) a model(string $key):
use RoundlyConsulting\Tickets\Enums\TicketOperation;
$replies = Tickets::recorded(TicketOperation::Reply);
expect($replies)->toHaveCount(1)
->and($replies[0]->concerns('TCK-1'))->toBeTrue()
->and($replies[0]->context['data']->body)->toContain('technician');Pomenovanie
- assert<Verb>() má dvojičku assertNothing<Verb>() — assertCreated() / assertNothingCreated().
- assert<Noun…><Verb>() (dve a viac slov) má dvojičku assertNo<Noun…><Verb>() — assertTagsSynced() / assertNoTagsSynced(), assertDueSet() / assertNoDueSet().
- assertNothingHappened() stojí samostatne.
Prechody cez odpoveď
assertTransitioned() ráta explicitný prechod (transition(), resolve(), …) aj transition: zverejnenej odpovede. transition: zadržanej odpovede neuplatnil nič, takže sa neráta; nerátajú sa ani automatizácie, ktoré nie sú vaším volaním:
Tickets::for($ticket)->by($agent)->reply('Please send a photo.', transition: 'wait');
$fake->assertTransitioned($ticket, 'wait'); // passes — unless the reply was heldAsercie
Argument $ticket prijme model alebo číslo tiketu; null znamená akýkoľvek. Každá asercia je zdokumentovaná aj na fasáde, takže funguje aj Tickets::assertAssigned(…):
| Operácia | Asercia | Negatívna |
|---|---|---|
| čokoľvek | — | assertNothingHappened() |
| založenie | assertCreated(?Closure $callback) | assertNothingCreated() |
| úprava | assertUpdated($ticket) | assertNothingUpdated() |
| priorita | assertPrioritized($ticket, $priority) | assertNothingPrioritized() |
| kategória | assertCategorized($ticket, $category) | assertNothingCategorized() |
| termín | assertDueSet($ticket) | assertNoDueSet() |
| žiadateľ | assertRequesterChanged($ticket) | assertNoRequesterChanged() |
| zmazanie / obnovenie | assertDeleted($ticket), assertRestored($ticket) | assertNothingDeleted(), assertNothingRestored() |
| prechod (aj transition: zverejnenej odpovede) | assertTransitioned($ticket, ?string $transition) | assertNothingTransitioned() |
| odpoveď / poznámka | assertReplied($ticket, AuthorRole|string|null $role), assertNoted($ticket) | assertNothingReplied(), assertNothingNoted() |
| úprava / zmazanie správy | assertCommentUpdated(?Comment), assertCommentDeleted(?Comment) | assertNoCommentUpdated(), assertNoCommentDeleted() |
| priradenie / odobratie / prevzatie | assertAssigned($ticket, ?Model $assignee), assertUnassigned($ticket), assertClaimed($ticket) | assertNothingAssigned(), assertNothingUnassigned(), assertNothingClaimed() |
| sledujúci pridaný / odobratý | assertWatched($ticket, ?Model $watcher), assertUnwatched($ticket, ?Model $watcher) | assertNothingWatched(), assertNothingUnwatched() |
| štítky pripojené / odpojené / synchronizované | assertTagged($ticket, ?string $tag), assertUntagged(…), assertTagsSynced(…) | assertNothingTagged(), assertNothingUntagged(), assertNoTagsSynced() |
| prepojenie / zrušenie | assertLinked($ticket, ?LinkType $type), assertUnlinked(…) | assertNothingLinked(), assertNothingUnlinked() |
| zlúčenie | assertMerged($source, $target) | assertNothingMerged() |
| príloha pridaná / odobratá | assertAttached($ticket), assertAttachmentRemoved($ticket) | assertNothingAttached(), assertNoAttachmentRemoved() |
| hodnoty polí nastavené / zabudnuté | assertFieldsSet($ticket, ?string $key), assertFieldsForgotten($ticket, ?string $key) | assertNoFieldsSet(), assertNoFieldsForgotten() |
| kategória vytvorená / upravená / presunutá / zmazaná / obnovená | assertCategoryCreated(?Closure), assertCategoryUpdated(?TicketCategory), assertCategoryMoved(…), assertCategoryDeleted(…), assertCategoryRestored(…) | assertNoCategoryCreated(), assertNoCategoryUpdated(), assertNoCategoryMoved(), assertNoCategoryDeleted(), assertNoCategoryRestored() |
| pole definované / upravené / zmazané / obnovené | assertFieldDefined(?string $key), assertFieldUpdated(…), assertFieldDeleted(…), assertFieldRestored(…) | assertNoFieldDefined(), assertNoFieldUpdated(), assertNoFieldDeleted(), assertNoFieldRestored() |
| čistenie | assertFieldsPruned(?bool $dryRun, ?int $chunk) | assertNoFieldsPruned() |
| štítok vytvorený (aj findOrCreate) / upravený / zmazaný | assertTagCreated(?string $name), assertTagUpdated(?TicketTag), assertTagDeleted(?TicketTag) | assertNoTagCreated(), assertNoTagUpdated(), assertNoTagDeleted() |
| hosť vyhodnotený / upravený / konvertovaný | assertGuestResolved(?Closure), assertGuestUpdated(?TicketGuest), assertGuestConverted(?TicketGuest) | assertNoGuestResolved(), assertNoGuestUpdated(), assertNoGuestConverted() |
| odkaz pre hosťa / zneplatnenie prístupu | assertGuestLinkIssued($ticket, ?TicketGuest $guest), assertGuestAccessRevoked($ticket) | assertNoGuestLinkIssued(), assertNoGuestAccessRevoked() |
| kontrola termínov | assertSwept(?Closure $callback) | assertNothingSwept() |
$fake->assertFieldsPruned(dryRun: true); // a dry run happened, any chunk
$fake->assertFieldsPruned(dryRun: false, chunk: 500);
$fake->assertSwept(fn (SweepResult $result) => $result->overdue === 2);
$fake->assertGuestLinkIssued('TCK-3');Odkazy, ktoré balík vytvára pre vlastné notifikácie hostí, sa nezaznamenávajú — assertGuestLinkIssued vidí len odkazy, o ktoré požiadal váš kód. Čítania sa nikdy nezaznamenávajú: find(), for(), Tickets::guests()->find() a ostatné vyhľadávania nechajú assertNothingHappened() prejsť.
Factory
Každý model má factory v RoundlyConsulting\Tickets\Database\Factories a päť vymeniteľných vytvára nakonfigurovanú triedu. TicketFactory čísluje riadky mimo všetkých skutočných postupností (rozsah factory, čísla FAC-n), predvolene nastaví žiadateľa na nového TicketGuest bez polí, kanál na api a prioritu na normal a má stavy requestedBy(), assignedTo(), inProject() a inStatus(); TicketCategoryFactory má inactive(), under() a inProject():
use RoundlyConsulting\Tickets\Models\Ticket;
// Numbered outside every real sequence (FAC-n); no activity, events, notifications or defaults
$ticket = Ticket::factory()->requestedBy($customer)->assignedTo($agent)->inStatus('pending')->create();Riadky z factory obchádzajú akcie balíka, takže tam, kde test potrebuje aktivity, udalosti, notifikácie alebo predvolené hodnoty, zakladajte cez fasádu. Hosťa s poliami získajte cez Tickets::guests()->resolve().
Testovanie aplikácie
- Žiadna špeciálna výbava: publikované migrácie sú bežné migrácie aplikácie, takže RefreshDatabase / LazilyRefreshDatabase fungujú so SQLite v pamäti aj s MySQL či PostgreSQL.
- Definujte Gate oprávnenia, na ktorých testy stoja (tickets.agent, …) — nedefinované oprávnenia zamietajú.
- Notifikácie idú do fronty po potvrdení: s frontou sync sa odošlú v rámci požiadavky; na ich overenie použite Notification::fake().
- Súbory udržíte mimo úložiska cez Storage::fake('local') pre disk príloh.
- API je vypnuté, pokiaľ pred štartom aplikácie nie je nastavené TICKETS_ROUTES=on — v phpunit.xml používajte hodnoty on / off, pretože PHPUnit mení false na prázdny reťazec, čo znamená predvolenú hodnotu.
<!-- phpunit.xml -->
<env name="TICKETS_ROUTES" value="on"/>Prejavte lásku k open source
Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.
Ďalšie spôsoby podpory vrátane kryptomienOdoslaním daru súhlasíte s našimi podmienkami prijímania darov.
Chcete to zabudovať do svojho produktu?
Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.