from)->toBe($from); expect($message->subject)->toBe($subject); expect($message->body)->toBe($body); expect($message->to)->toBe($to); expect($message->priority)->toBe(Priority::NORMAL); expect($message->cc->isEmpty())->toBeTrue(); expect($message->bcc->isEmpty())->toBeTrue(); expect($message->attachments)->toBeEmpty(); expect($message->headers)->toBeEmpty(); expect($message->replyTo)->toBeNull(); }); it('creates a message with HTML body', function () { $message = new Message( from: new Email('sender@example.com'), subject: 'Test', htmlBody: '

HTML Content

', to: new EmailList(new Email('recipient@example.com')) ); expect($message->htmlBody)->toBe('

HTML Content

'); expect($message->body)->toBe(''); expect($message->hasHtmlBody())->toBeTrue(); }); it('creates a message with both text and HTML body', function () { $message = new Message( from: new Email('sender@example.com'), subject: 'Test', body: 'Plain text', htmlBody: '

HTML content

', to: new EmailList(new Email('recipient@example.com')) ); expect($message->body)->toBe('Plain text'); expect($message->htmlBody)->toBe('

HTML content

'); expect($message->hasHtmlBody())->toBeTrue(); }); it('throws exception when both body and HTML body are empty', function () { expect(fn () => new Message( from: new Email('sender@example.com'), subject: 'Test', to: new EmailList(new Email('recipient@example.com')) ))->toThrow(InvalidArgumentException::class, 'Either body or HTML body is required'); }); it('throws exception when to list is empty', function () { expect(fn () => new Message( from: new Email('sender@example.com'), subject: 'Test', body: 'Test body', to: new EmailList() ))->toThrow(InvalidArgumentException::class, 'At least one recipient is required'); }); it('creates message with CC and BCC recipients', function () { $cc = new EmailList(new Email('cc@example.com')); $bcc = new EmailList(new Email('bcc@example.com')); $message = new Message( from: new Email('sender@example.com'), subject: 'Test', body: 'Test body', to: new EmailList(new Email('recipient@example.com')), cc: $cc, bcc: $bcc ); expect($message->cc)->toBe($cc); expect($message->bcc)->toBe($bcc); }); it('creates message with high priority', function () { $message = new Message( from: new Email('sender@example.com'), subject: 'Urgent', body: 'Urgent message', to: new EmailList(new Email('recipient@example.com')), priority: Priority::HIGH ); expect($message->priority)->toBe(Priority::HIGH); }); it('creates message with custom headers', function () { $headers = ['X-Custom-Header' => 'custom-value']; $message = new Message( from: new Email('sender@example.com'), subject: 'Test', body: 'Test body', to: new EmailList(new Email('recipient@example.com')), headers: $headers ); expect($message->headers)->toBe($headers); }); it('creates message with reply-to address', function () { $replyTo = new Email('noreply@example.com'); $message = new Message( from: new Email('sender@example.com'), subject: 'Test', body: 'Test body', to: new EmailList(new Email('recipient@example.com')), replyTo: $replyTo ); expect($message->replyTo)->toBe($replyTo); }); it('provides fluent withTo method', function () { $message = new Message( from: new Email('sender@example.com'), subject: 'Test', body: 'Test body', to: new EmailList(new Email('original@example.com')) ); $newMessage = $message->withTo(new Email('new@example.com')); expect($newMessage)->not->toBe($message); expect($newMessage->to->toString())->toBe('new@example.com'); expect($message->to->toString())->toBe('original@example.com'); }); it('provides fluent withCc method', function () { $message = new Message( from: new Email('sender@example.com'), subject: 'Test', body: 'Test body', to: new EmailList(new Email('recipient@example.com')) ); $newMessage = $message->withCc(new Email('cc@example.com')); expect($newMessage)->not->toBe($message); expect($newMessage->cc->toString())->toBe('cc@example.com'); expect($message->cc->isEmpty())->toBeTrue(); }); it('provides fluent withBcc method', function () { $message = new Message( from: new Email('sender@example.com'), subject: 'Test', body: 'Test body', to: new EmailList(new Email('recipient@example.com')) ); $newMessage = $message->withBcc(new Email('bcc@example.com')); expect($newMessage)->not->toBe($message); expect($newMessage->bcc->toString())->toBe('bcc@example.com'); expect($message->bcc->isEmpty())->toBeTrue(); }); it('provides fluent withSubject method', function () { $message = new Message( from: new Email('sender@example.com'), subject: 'Original Subject', body: 'Test body', to: new EmailList(new Email('recipient@example.com')) ); $newMessage = $message->withSubject('New Subject'); expect($newMessage)->not->toBe($message); expect($newMessage->subject)->toBe('New Subject'); expect($message->subject)->toBe('Original Subject'); }); it('gets all recipients (to, cc, bcc)', function () { $to = EmailList::fromArray([new Email('to@example.com')]); $cc = new EmailList(new Email('cc@example.com')); $bcc = new EmailList(new Email('bcc@example.com')); $message = new Message( from: new Email('sender@example.com'), subject: 'Test', body: 'Test body', to: $to, cc: $cc, bcc: $bcc ); $allRecipients = $message->getAllRecipients(); expect($allRecipients->count())->toBe(3); expect($allRecipients->contains(new Email('to@example.com')))->toBeTrue(); expect($allRecipients->contains(new Email('cc@example.com')))->toBeTrue(); expect($allRecipients->contains(new Email('bcc@example.com')))->toBeTrue(); }); it('detects if message has attachments', function () { $messageWithoutAttachments = new Message( from: new Email('sender@example.com'), subject: 'Test', body: 'Test body', to: new EmailList(new Email('recipient@example.com')) ); expect($messageWithoutAttachments->hasAttachments())->toBeFalse(); // Note: We can't easily test with real attachments without mocking the Storage and file system // This would be covered in integration tests }); });