create(['preferred_language' => 'ar']); $consultation = Consultation::factory()->pending()->create(['user_id' => $user->id]); $consultation->update(['status' => ConsultationStatus::Approved]); Mail::assertQueued(BookingApprovedMail::class, function ($mail) use ($consultation) { return $mail->consultation->id === $consultation->id; }); }); test('does not send email when status changes to non-approved', function () { Mail::fake(); $user = User::factory()->create(['preferred_language' => 'ar']); $consultation = Consultation::factory()->pending()->create(['user_id' => $user->id]); $consultation->update(['status' => ConsultationStatus::Rejected]); Mail::assertNotQueued(BookingApprovedMail::class); }); test('does not send email when consultation is created as approved', function () { Mail::fake(); $user = User::factory()->create(['preferred_language' => 'ar']); Consultation::factory()->approved()->create(['user_id' => $user->id]); Mail::assertNotQueued(BookingApprovedMail::class); }); test('does not send email when other fields change on approved consultation', function () { Mail::fake(); $user = User::factory()->create(['preferred_language' => 'ar']); $consultation = Consultation::factory()->approved()->create(['user_id' => $user->id]); $consultation->update(['problem_summary' => 'Updated summary']); Mail::assertNotQueued(BookingApprovedMail::class); }); test('includes ics attachment', function () { $user = User::factory()->create(['preferred_language' => 'ar']); $consultation = Consultation::factory()->approved()->create(['user_id' => $user->id]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); $attachments = $mailable->attachments(); expect($attachments)->toHaveCount(1); expect($attachments[0]->as)->toBe('consultation.ics'); }); test('uses Arabic template for Arabic-preferring users', function () { $user = User::factory()->create(['preferred_language' => 'ar']); $consultation = Consultation::factory()->approved()->create(['user_id' => $user->id]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); expect($mailable->content()->markdown)->toBe('emails.booking.approved.ar'); }); test('uses English template for English-preferring users', function () { $user = User::factory()->create(['preferred_language' => 'en']); $consultation = Consultation::factory()->approved()->create(['user_id' => $user->id]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); expect($mailable->content()->markdown)->toBe('emails.booking.approved.en'); }); test('includes payment instructions for paid consultations', function () { $user = User::factory()->create(['preferred_language' => 'en']); $consultation = Consultation::factory()->approved()->create([ 'user_id' => $user->id, 'consultation_type' => ConsultationType::Paid, 'payment_amount' => 150.00, 'payment_status' => PaymentStatus::Pending, ]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $paymentInstructions = 'Please pay 150 ILS before your consultation.'; $mailable = new BookingApprovedMail($consultation, $icsContent, $paymentInstructions); expect($mailable->paymentInstructions)->toBe($paymentInstructions); }); test('excludes payment instructions for free consultations', function () { $user = User::factory()->create(['preferred_language' => 'ar']); $consultation = Consultation::factory()->approved()->free()->create(['user_id' => $user->id]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); expect($mailable->paymentInstructions)->toBeNull(); }); test('has correct Arabic subject', function () { $user = User::factory()->create(['preferred_language' => 'ar']); $consultation = Consultation::factory()->approved()->create(['user_id' => $user->id]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); expect($mailable->envelope()->subject)->toBe('تمت الموافقة على استشارتك'); }); test('has correct English subject', function () { $user = User::factory()->create(['preferred_language' => 'en']); $consultation = Consultation::factory()->approved()->create(['user_id' => $user->id]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); expect($mailable->envelope()->subject)->toBe('Your Consultation Has Been Approved'); }); test('date is formatted as d/m/Y for Arabic users', function () { $user = User::factory()->create(['preferred_language' => 'ar']); $consultation = Consultation::factory()->approved()->create([ 'user_id' => $user->id, 'booking_date' => '2025-03-15', ]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); expect($mailable->getFormattedDate('ar'))->toBe('15/03/2025'); }); test('date is formatted as m/d/Y for English users', function () { $user = User::factory()->create(['preferred_language' => 'en']); $consultation = Consultation::factory()->approved()->create([ 'user_id' => $user->id, 'booking_date' => '2025-03-15', ]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); expect($mailable->getFormattedDate('en'))->toBe('03/15/2025'); }); test('time is formatted as h:i A', function () { $user = User::factory()->create(['preferred_language' => 'ar']); $consultation = Consultation::factory()->approved()->create([ 'user_id' => $user->id, 'booking_time' => '14:30:00', ]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); expect($mailable->getFormattedTime())->toBe('02:30 PM'); }); test('consultation type label is correct in Arabic', function () { $user = User::factory()->create(['preferred_language' => 'ar']); $freeConsultation = Consultation::factory()->approved()->free()->create(['user_id' => $user->id]); $paidConsultation = Consultation::factory()->approved()->paid()->create(['user_id' => $user->id]); $freeIcs = app(CalendarService::class)->generateIcs($freeConsultation); $paidIcs = app(CalendarService::class)->generateIcs($paidConsultation); $freeMailable = new BookingApprovedMail($freeConsultation, $freeIcs); $paidMailable = new BookingApprovedMail($paidConsultation, $paidIcs); expect($freeMailable->getConsultationTypeLabel('ar'))->toBe('مجانية'); expect($paidMailable->getConsultationTypeLabel('ar'))->toBe('مدفوعة'); }); test('consultation type label is correct in English', function () { $user = User::factory()->create(['preferred_language' => 'en']); $freeConsultation = Consultation::factory()->approved()->free()->create(['user_id' => $user->id]); $paidConsultation = Consultation::factory()->approved()->paid()->create(['user_id' => $user->id]); $freeIcs = app(CalendarService::class)->generateIcs($freeConsultation); $paidIcs = app(CalendarService::class)->generateIcs($paidConsultation); $freeMailable = new BookingApprovedMail($freeConsultation, $freeIcs); $paidMailable = new BookingApprovedMail($paidConsultation, $paidIcs); expect($freeMailable->getConsultationTypeLabel('en'))->toBe('Free'); expect($paidMailable->getConsultationTypeLabel('en'))->toBe('Paid'); }); test('booking approved email implements ShouldQueue', function () { expect(BookingApprovedMail::class)->toImplement(ShouldQueue::class); }); test('content includes all required data', function () { $user = User::factory()->create(['preferred_language' => 'en']); $consultation = Consultation::factory()->approved()->create([ 'user_id' => $user->id, 'booking_date' => '2025-03-15', 'booking_time' => '10:00:00', ]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); $content = $mailable->content(); expect($content->with) ->toHaveKey('consultation') ->toHaveKey('user') ->toHaveKey('paymentInstructions') ->toHaveKey('formattedDate') ->toHaveKey('formattedTime') ->toHaveKey('duration') ->toHaveKey('consultationType') ->toHaveKey('isPaid') ->toHaveKey('paymentAmount'); }); test('email has correct recipient when queued via observer', function () { Mail::fake(); $user = User::factory()->create(['preferred_language' => 'en']); $consultation = Consultation::factory()->pending()->create(['user_id' => $user->id]); $consultation->update(['status' => ConsultationStatus::Approved]); Mail::assertQueued(BookingApprovedMail::class, function ($mail) use ($user) { return $mail->hasTo($user->email); }); }); test('email renders without errors in Arabic', function () { $user = User::factory()->create(['preferred_language' => 'ar']); $consultation = Consultation::factory()->approved()->create(['user_id' => $user->id]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); $rendered = $mailable->render(); expect($rendered)->toContain('تمت الموافقة على استشارتك'); }); test('email renders without errors in English', function () { $user = User::factory()->create(['preferred_language' => 'en']); $consultation = Consultation::factory()->approved()->create(['user_id' => $user->id]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); $rendered = $mailable->render(); expect($rendered)->toContain('Your Consultation Has Been Approved'); }); test('paid consultation email includes payment amount', function () { $user = User::factory()->create(['preferred_language' => 'en']); $consultation = Consultation::factory()->approved()->create([ 'user_id' => $user->id, 'consultation_type' => ConsultationType::Paid, 'payment_amount' => 250.00, 'payment_status' => PaymentStatus::Pending, ]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $paymentInstructions = 'Please pay before your appointment.'; $mailable = new BookingApprovedMail($consultation, $icsContent, $paymentInstructions); $rendered = $mailable->render(); expect($rendered)->toContain('250.00'); }); test('free consultation email does not include payment section', function () { $user = User::factory()->create(['preferred_language' => 'en']); $consultation = Consultation::factory()->approved()->free()->create(['user_id' => $user->id]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); $rendered = $mailable->render(); expect($rendered)->not->toContain('Payment Information'); }); test('defaults to Arabic when preferred_language is ar', function () { $user = User::factory()->create(['preferred_language' => 'ar']); $consultation = Consultation::factory()->approved()->create(['user_id' => $user->id]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); expect($mailable->envelope()->subject)->toBe('تمت الموافقة على استشارتك'); expect($mailable->content()->markdown)->toBe('emails.booking.approved.ar'); }); test('duration defaults to 45 minutes', function () { $user = User::factory()->create(['preferred_language' => 'en']); $consultation = Consultation::factory()->approved()->create(['user_id' => $user->id]); $icsContent = app(CalendarService::class)->generateIcs($consultation); $mailable = new BookingApprovedMail($consultation, $icsContent); $content = $mailable->content(); expect($content->with['duration'])->toBe(45); });