testToken); $user = new User(['email' => 'test@example.com', 'name' => 'Test User']); $channels = $notification->via($user); $this->assertContains('mail', $channels); } /** * toMail()이 DbTemplateMail을 반환하는지 확인 */ public function test_to_mail_returns_db_template_mail(): void { MailTemplate::factory()->withType('reset_password')->create(); $notification = new ResetPasswordNotification($this->testToken); $user = User::factory()->create(); $mailable = $notification->toMail($user); $this->assertInstanceOf(DbTemplateMail::class, $mailable); } /** * Mailable의 templateType이 reset_password인지 확인 */ public function test_mailable_template_type_is_reset_password(): void { MailTemplate::factory()->withType('reset_password')->create(); $notification = new ResetPasswordNotification($this->testToken); $user = User::factory()->create(); $mailable = $notification->toMail($user); $this->assertEquals('reset_password', $mailable->getTemplateType()); } /** * Mailable의 module이 core인지 확인 */ public function test_mailable_module_is_core(): void { MailTemplate::factory()->withType('reset_password')->create(); $notification = new ResetPasswordNotification($this->testToken); $user = User::factory()->create(); $mailable = $notification->toMail($user); $this->assertEquals(ExtensionOwnerType::Core, $mailable->getExtensionType()); $this->assertEquals('core', $mailable->getExtensionIdentifier()); } /** * 비활성 템플릿에서 스킵 인스턴스 반환 */ public function test_to_mail_returns_skipped_when_template_inactive(): void { MailTemplate::factory()->withType('reset_password')->inactive()->create(); $notification = new ResetPasswordNotification($this->testToken); $user = User::factory()->create(); $mailable = $notification->toMail($user); $this->assertInstanceOf(DbTemplateMail::class, $mailable); $this->assertTrue($mailable->isSkipped()); } /** * getToken()이 토큰을 반환하는지 확인 */ public function test_get_token_returns_token(): void { $notification = new ResetPasswordNotification($this->testToken); $this->assertEquals($this->testToken, $notification->getToken()); } /** * action_url 변수를 포함하는 비밀번호 재설정 템플릿을 생성합니다. */ private function createResetPasswordTemplate(): void { MailTemplate::factory()->withType('reset_password')->create([ 'subject' => [ 'ko' => '비밀번호 재설정', 'en' => 'Reset Password', ], 'body' => [ 'ko' => '

비밀번호 재설정

', 'en' => '

Reset Password

', ], ]); } /** * redirect_prefix 없이 기본 /reset-password URL 생성 */ public function test_to_mail_generates_default_reset_url(): void { $this->createResetPasswordTemplate(); $notification = new ResetPasswordNotification($this->testToken); $user = User::factory()->create(['email' => 'user@example.com']); $mailable = $notification->toMail($user); // renderedBody는 생성자 파라미터이므로 Reflection으로 접근 $ref = new \ReflectionProperty($mailable, 'renderedBody'); $body = $ref->getValue($mailable); $this->assertStringContainsString('/reset-password?', $body); $this->assertStringNotContainsString('/admin/reset-password?', $body); } /** * redirect_prefix='admin' 시 /admin/reset-password URL 생성 */ public function test_to_mail_generates_admin_reset_url_with_redirect_prefix(): void { $this->createResetPasswordTemplate(); $notification = new ResetPasswordNotification($this->testToken, 'admin'); $user = User::factory()->create(['email' => 'admin@example.com']); $mailable = $notification->toMail($user); $ref = new \ReflectionProperty($mailable, 'renderedBody'); $body = $ref->getValue($mailable); $this->assertStringContainsString('/admin/reset-password?', $body); } /** * redirect_prefix=null 시 기본 URL (하위 호환성) */ public function test_to_mail_null_redirect_prefix_uses_default_url(): void { $this->createResetPasswordTemplate(); $notification = new ResetPasswordNotification($this->testToken, null); $user = User::factory()->create(['email' => 'test@example.com']); $mailable = $notification->toMail($user); $ref = new \ReflectionProperty($mailable, 'renderedBody'); $body = $ref->getValue($mailable); $this->assertStringContainsString('/reset-password?', $body); $this->assertStringNotContainsString('/admin/reset-password?', $body); } }