artisan('db:seed', ['--class' => 'RoleSeeder']); } public function test_member_registration_welcome_mail_content(): void { $member = Member::factory()->create([ 'full_name' => 'John Doe', 'email' => 'john@example.com', ]); $mailable = new MemberRegistrationWelcomeMail($member); $mailable->assertSeeInHtml('John Doe'); $mailable->assertSeeInHtml('Welcome'); } public function test_payment_submitted_mail_member_variant(): void { $member = Member::factory()->create(['email' => 'member@example.com']); $payment = MembershipPayment::factory()->create([ 'member_id' => $member->id, 'amount' => 1000, ]); $mailable = new PaymentSubmittedMail($payment, 'member'); $mailable->assertSeeInHtml('1,000'); $mailable->assertSeeInHtml('submitted'); } public function test_payment_submitted_mail_cashier_variant(): void { $member = Member::factory()->create(); $payment = MembershipPayment::factory()->create([ 'member_id' => $member->id, 'amount' => 1000, ]); $mailable = new PaymentSubmittedMail($payment, 'cashier'); $mailable->assertSeeInHtml('review'); $mailable->assertSeeInHtml('1,000'); } public function test_payment_approved_by_cashier_mail(): void { $member = Member::factory()->create(); $payment = MembershipPayment::factory()->create([ 'member_id' => $member->id, 'status' => MembershipPayment::STATUS_APPROVED_CASHIER, 'amount' => 1000, ]); $mailable = new PaymentApprovedByCashierMail($payment); $mailable->assertSeeInHtml('Cashier'); $mailable->assertSeeInHtml('approved'); } public function test_payment_approved_by_accountant_mail(): void { $member = Member::factory()->create(); $payment = MembershipPayment::factory()->create([ 'member_id' => $member->id, 'status' => MembershipPayment::STATUS_APPROVED_ACCOUNTANT, 'amount' => 1000, ]); $mailable = new PaymentApprovedByAccountantMail($payment); $mailable->assertSeeInHtml('Accountant'); $mailable->assertSeeInHtml('approved'); } public function test_payment_fully_approved_mail(): void { $member = Member::factory()->create(); $payment = MembershipPayment::factory()->create([ 'member_id' => $member->id, 'status' => MembershipPayment::STATUS_APPROVED_CHAIR, 'amount' => 1000, ]); $mailable = new PaymentFullyApprovedMail($payment); $mailable->assertSeeInHtml('approved'); $mailable->assertSeeInHtml('1,000'); } public function test_payment_rejected_mail(): void { $member = Member::factory()->create(); $payment = MembershipPayment::factory()->create([ 'member_id' => $member->id, 'status' => MembershipPayment::STATUS_REJECTED, 'rejection_reason' => 'Invalid receipt format', 'amount' => 1000, ]); $mailable = new PaymentRejectedMail($payment); $mailable->assertSeeInHtml('Invalid receipt format'); $mailable->assertSeeInHtml('rejected'); } public function test_membership_activated_mail(): void { $member = Member::factory()->create([ 'full_name' => 'John Doe', 'membership_status' => Member::STATUS_ACTIVE, 'membership_started_at' => now(), 'membership_expires_at' => now()->addYear(), ]); $mailable = new MembershipActivatedMail($member); $mailable->assertSeeInHtml('activated'); $mailable->assertSeeInHtml('John Doe'); } public function test_all_emails_implement_should_queue(): void { $member = Member::factory()->create(); $payment = MembershipPayment::factory()->create(['member_id' => $member->id]); $mailables = [ new MemberRegistrationWelcomeMail($member), new PaymentSubmittedMail($payment, 'member'), new PaymentApprovedByCashierMail($payment), new PaymentApprovedByAccountantMail($payment), new PaymentFullyApprovedMail($payment), new PaymentRejectedMail($payment), new MembershipActivatedMail($member), ]; foreach ($mailables as $mailable) { $this->assertInstanceOf(\Illuminate\Contracts\Queue\ShouldQueue::class, $mailable); } } public function test_emails_queued_correctly(): void { Mail::fake(); $member = Member::factory()->create(); $payment = MembershipPayment::factory()->create(['member_id' => $member->id]); Mail::to($member->email)->queue(new PaymentSubmittedMail($payment, 'member')); Mail::assertQueued(PaymentSubmittedMail::class); } public function test_email_recipients_correct(): void { Mail::fake(); $member = Member::factory()->create(['email' => 'member@example.com']); $payment = MembershipPayment::factory()->create(['member_id' => $member->id]); Mail::to($member->email)->queue(new PaymentSubmittedMail($payment, 'member')); Mail::assertQueued(PaymentSubmittedMail::class, function ($mail) { return $mail->hasTo('member@example.com'); }); } public function test_payment_submitted_mail_has_correct_subject(): void { $member = Member::factory()->create(); $payment = MembershipPayment::factory()->create(['member_id' => $member->id]); $mailable = new PaymentSubmittedMail($payment, 'member'); $this->assertStringContainsString('Payment', $mailable->subject ?? ''); } public function test_rejection_mail_includes_next_steps(): void { $member = Member::factory()->create(); $payment = MembershipPayment::factory()->create([ 'member_id' => $member->id, 'status' => MembershipPayment::STATUS_REJECTED, 'rejection_reason' => 'Test reason', ]); $mailable = new PaymentRejectedMail($payment); $mailable->assertSeeInHtml('Submit New Payment'); } public function test_activation_mail_includes_expiry_date(): void { $member = Member::factory()->create([ 'membership_status' => Member::STATUS_ACTIVE, 'membership_expires_at' => now()->addYear(), ]); $mailable = new MembershipActivatedMail($member); $expiryDate = $member->membership_expires_at->format('Y-m-d'); $mailable->assertSeeInHtml($expiryDate); } public function test_welcome_mail_includes_dashboard_link(): void { $member = Member::factory()->create(); $mailable = new MemberRegistrationWelcomeMail($member); $mailable->assertSeeInHtml(route('member.dashboard')); } public function test_payment_fully_approved_mail_mentions_activation(): void { $member = Member::factory()->create(); $payment = MembershipPayment::factory()->create([ 'member_id' => $member->id, 'status' => MembershipPayment::STATUS_APPROVED_CHAIR, ]); $mailable = new PaymentFullyApprovedMail($payment); $mailable->assertSeeInHtml('activated'); } public function test_mail_facades_work_correctly(): void { Mail::fake(); $member = Member::factory()->create(); $payment = MembershipPayment::factory()->create(['member_id' => $member->id]); // Send various emails Mail::to($member->email)->queue(new MemberRegistrationWelcomeMail($member)); Mail::to($member->email)->queue(new PaymentSubmittedMail($payment, 'member')); Mail::to($member->email)->queue(new MembershipActivatedMail($member)); Mail::assertQueued(MemberRegistrationWelcomeMail::class); Mail::assertQueued(PaymentSubmittedMail::class); Mail::assertQueued(MembershipActivatedMail::class); } public function test_emails_not_sent_when_not_queued(): void { Mail::fake(); // Don't queue any emails Mail::assertNothingQueued(); Mail::assertNothingSent(); } public function test_multiple_recipients_can_receive_same_email(): void { Mail::fake(); $member = Member::factory()->create(); $payment = MembershipPayment::factory()->create(['member_id' => $member->id]); // Send to multiple recipients Mail::to(['admin1@example.com', 'admin2@example.com'])->queue(new PaymentSubmittedMail($payment, 'cashier')); Mail::assertQueued(PaymentSubmittedMail::class, 1); } public function test_email_content_is_html_formatted(): void { $member = Member::factory()->create(); $mailable = new MemberRegistrationWelcomeMail($member); $mailable->assertSeeInHtml('<'); $mailable->assertSeeInHtml('>'); } }