toBe('canceled') ->and(DhlShipment::normalizeStatus('canceled'))->toBe('canceled'); }); it('translates canceled and legacy cancelled shipments consistently', function () { app()->setLocale('de'); $canceledShipment = new DhlShipment(['status' => 'canceled']); $legacyShipment = new DhlShipment(['status' => 'cancelled']); expect($canceledShipment->getStatusTranslation())->toBe('Storniert') ->and($legacyShipment->getStatusTranslation())->toBe('Storniert') ->and($canceledShipment->getStatusBadgeClass())->toBe('warning') ->and($legacyShipment->getStatusBadgeClass())->toBe('warning'); }); it('returns tracking email history with latest entries first', function () { $shipment = new DhlShipment([ 'api_response_data' => [ 'tracking_email_history' => [ [ 'sent_at' => '2026-05-27T08:00:00+00:00', 'type' => 'auto', 'status' => 'in_transit', 'recipient_email' => 'first@example.test', ], [ 'sent_at' => '2026-05-27T09:00:00+00:00', 'type' => 'manual', 'status' => 'out_for_delivery', 'recipient_email' => 'second@example.test', ], ], ], ]); $history = $shipment->getTrackingEmailHistory(); expect($history)->toHaveCount(2) ->and($history[0]['recipient_email'])->toBe('second@example.test') ->and($history[0]['status'])->toBe('out_for_delivery') ->and(DhlShipment::getStatusBadgeClassFor($history[0]['status']))->toBe('primary'); }); it('returns empty tracking email history for legacy shipments without history', function () { $shipment = new DhlShipment(['api_response_data' => ['items' => []]]); expect($shipment->getTrackingEmailHistory())->toBe([]); }); it('triggers tracking emails for relevant status changes only once', function () { $order = new ShoppingOrder; $shipment = new DhlShipment([ 'status' => 'out_for_delivery', 'dhl_shipment_no' => '00340435065133', 'email' => 'customer@example.test', ]); $shipment->setRelation('shoppingOrder', $order); expect($shipment->shouldTriggerTrackingEmail('created'))->toBeTrue() ->and($shipment->shouldTriggerTrackingEmail('out_for_delivery'))->toBeFalse(); $shipment->tracking_email_sent_at = now(); expect($shipment->shouldTriggerTrackingEmail('created'))->toBeFalse(); }); it('does not trigger tracking emails for terminal delivered status', function () { $order = new ShoppingOrder; $shipment = new DhlShipment([ 'status' => 'delivered', 'dhl_shipment_no' => '00340435065133', 'email' => 'customer@example.test', ]); $shipment->setRelation('shoppingOrder', $order); expect($shipment->shouldTriggerTrackingEmail('in_transit'))->toBeFalse(); }); it('maps DHL status variants to internal tracking statuses', function (string $dhlStatus, string $internalStatus) { expect(DhlTrackingService::mapDhlStatusToInternal($dhlStatus))->toBe($internalStatus); })->with([ 'transit' => ['transit', 'in_transit'], 'in-transit' => ['in-transit', 'in_transit'], 'out-for-delivery' => ['out-for-delivery', 'out_for_delivery'], 'out_for_delivery' => ['out_for_delivery', 'out_for_delivery'], ]);