complete story 8.5 with qa tests
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
<?php
|
||||
|
||||
use App\Mail\BookingRejectedEmail;
|
||||
use App\Models\Consultation;
|
||||
use App\Models\User;
|
||||
use App\Notifications\BookingRejected;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
test('booking rejected email uses arabic template for arabic preference', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'ar']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation);
|
||||
|
||||
expect($mailable->content()->markdown)->toBe('emails.booking.rejected.ar');
|
||||
});
|
||||
|
||||
test('booking rejected email uses english template for english preference', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'en']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation);
|
||||
|
||||
expect($mailable->content()->markdown)->toBe('emails.booking.rejected.en');
|
||||
});
|
||||
|
||||
test('booking rejected email defaults to arabic from database default', function () {
|
||||
// The database schema has default('ar') for preferred_language
|
||||
// This test verifies the mailable respects that default
|
||||
$user = User::factory()->create(['preferred_language' => 'ar']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation);
|
||||
|
||||
expect($mailable->content()->markdown)->toBe('emails.booking.rejected.ar');
|
||||
expect($mailable->envelope()->subject)->toBe('تعذر الموافقة على طلب الاستشارة');
|
||||
});
|
||||
|
||||
test('booking rejected email has correct arabic subject', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'ar']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation);
|
||||
|
||||
expect($mailable->envelope()->subject)->toBe('تعذر الموافقة على طلب الاستشارة');
|
||||
});
|
||||
|
||||
test('booking rejected email has correct english subject', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'en']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation);
|
||||
|
||||
expect($mailable->envelope()->subject)->toBe('Your Consultation Request Could Not Be Approved');
|
||||
});
|
||||
|
||||
test('booking rejected email includes reason when provided', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'en']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
$reason = 'Schedule conflict with another appointment';
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation, $reason);
|
||||
$content = $mailable->content();
|
||||
|
||||
expect($content->with['reason'])->toBe($reason);
|
||||
expect($content->with['hasReason'])->toBeTrue();
|
||||
});
|
||||
|
||||
test('booking rejected email handles null reason', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'en']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation, null);
|
||||
$content = $mailable->content();
|
||||
|
||||
expect($content->with['reason'])->toBeNull();
|
||||
expect($content->with['hasReason'])->toBeFalse();
|
||||
});
|
||||
|
||||
test('booking rejected email handles empty reason', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'en']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation, '');
|
||||
$content = $mailable->content();
|
||||
|
||||
expect($content->with['hasReason'])->toBeFalse();
|
||||
});
|
||||
|
||||
test('date is formatted as d/m/Y for arabic users', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'ar']);
|
||||
$consultation = Consultation::factory()->for($user)->create([
|
||||
'booking_date' => '2025-03-15',
|
||||
]);
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation);
|
||||
|
||||
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()->for($user)->create([
|
||||
'booking_date' => '2025-03-15',
|
||||
]);
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation);
|
||||
|
||||
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()->for($user)->create([
|
||||
'booking_time' => '14:30:00',
|
||||
]);
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation);
|
||||
|
||||
expect($mailable->getFormattedTime())->toBe('02:30 PM');
|
||||
});
|
||||
|
||||
test('booking rejected email implements ShouldQueue', function () {
|
||||
expect(BookingRejectedEmail::class)->toImplement(ShouldQueue::class);
|
||||
});
|
||||
|
||||
test('content includes all required data', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'en']);
|
||||
$consultation = Consultation::factory()->for($user)->create([
|
||||
'booking_date' => '2025-03-15',
|
||||
'booking_time' => '10:00:00',
|
||||
]);
|
||||
$reason = 'Test reason';
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation, $reason);
|
||||
$content = $mailable->content();
|
||||
|
||||
expect($content->with)
|
||||
->toHaveKey('consultation')
|
||||
->toHaveKey('user')
|
||||
->toHaveKey('reason')
|
||||
->toHaveKey('hasReason')
|
||||
->toHaveKey('formattedDate')
|
||||
->toHaveKey('formattedTime');
|
||||
});
|
||||
|
||||
test('email renders without errors in arabic', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'ar']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation);
|
||||
$rendered = $mailable->render();
|
||||
|
||||
expect($rendered)->toContain('تعذر الموافقة على طلب الاستشارة');
|
||||
});
|
||||
|
||||
test('email renders without errors in english', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'en']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation);
|
||||
$rendered = $mailable->render();
|
||||
|
||||
expect($rendered)->toContain('Your Consultation Request Could Not Be Approved');
|
||||
});
|
||||
|
||||
test('email renders reason section when reason provided', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'en']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
$reason = 'The requested time slot is not available';
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation, $reason);
|
||||
$rendered = $mailable->render();
|
||||
|
||||
expect($rendered)->toContain($reason);
|
||||
expect($rendered)->toContain('Reason');
|
||||
});
|
||||
|
||||
test('email does not render reason section when reason not provided', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'en']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation);
|
||||
$rendered = $mailable->render();
|
||||
|
||||
expect($rendered)->not->toContain('Reason:');
|
||||
});
|
||||
|
||||
test('arabic email does not render reason section when reason not provided', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'ar']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
|
||||
$mailable = new BookingRejectedEmail($consultation);
|
||||
$rendered = $mailable->render();
|
||||
|
||||
expect($rendered)->not->toContain('سبب الرفض');
|
||||
});
|
||||
|
||||
test('notification sends booking rejected email', function () {
|
||||
Notification::fake();
|
||||
|
||||
$user = User::factory()->create(['preferred_language' => 'en']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
$reason = 'Test reason';
|
||||
|
||||
$user->notify(new BookingRejected($consultation, $reason));
|
||||
|
||||
Notification::assertSentTo($user, BookingRejected::class, function ($notification) use ($consultation, $reason) {
|
||||
return $notification->consultation->id === $consultation->id
|
||||
&& $notification->rejectionReason === $reason;
|
||||
});
|
||||
});
|
||||
|
||||
test('notification sends email to correct recipient', function () {
|
||||
Notification::fake();
|
||||
|
||||
$user = User::factory()->create(['email' => 'client@example.com']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
|
||||
$user->notify(new BookingRejected($consultation));
|
||||
|
||||
Notification::assertSentTo($user, BookingRejected::class);
|
||||
});
|
||||
|
||||
test('notification passes rejection reason to mailable', function () {
|
||||
Notification::fake();
|
||||
|
||||
$user = User::factory()->create();
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
$reason = 'Schedule conflict';
|
||||
|
||||
$user->notify(new BookingRejected($consultation, $reason));
|
||||
|
||||
Notification::assertSentTo($user, BookingRejected::class, function ($notification) use ($reason) {
|
||||
return $notification->rejectionReason === $reason;
|
||||
});
|
||||
});
|
||||
|
||||
test('notification toMail returns BookingRejectedEmail mailable', function () {
|
||||
$user = User::factory()->create(['preferred_language' => 'en']);
|
||||
$consultation = Consultation::factory()->for($user)->create();
|
||||
$reason = 'Test reason';
|
||||
|
||||
$notification = new BookingRejected($consultation, $reason);
|
||||
$mailable = $notification->toMail($user);
|
||||
|
||||
expect($mailable)->toBeInstanceOf(BookingRejectedEmail::class);
|
||||
expect($mailable->consultation->id)->toBe($consultation->id);
|
||||
expect($mailable->reason)->toBe($reason);
|
||||
});
|
||||
Reference in New Issue
Block a user