diff --git a/.github/workflows/pull_request_unit_tests.yml b/.github/workflows/pull_request_unit_tests.yml index 462317c3..9b21c15e 100644 --- a/.github/workflows/pull_request_unit_tests.yml +++ b/.github/workflows/pull_request_unit_tests.yml @@ -37,6 +37,8 @@ jobs: PHP_VERSION: 8.3 OTEL_SDK_DISABLED: true OTEL_SERVICE_ENABLED: false + MAIL_FROM_EMAIL: noreply@tipit.net + MAIL_FROM_NAME: noreply@tipit.net services: mysql: image: mysql:8.0 diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index ad2ede65..cfaf33c5 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -33,6 +33,8 @@ jobs: PHP_VERSION: 8.3 OTEL_SDK_DISABLED: true OTEL_SERVICE_ENABLED: false + MAIL_FROM_EMAIL: noreply@tipit.net + MAIL_FROM_NAME: noreply@tipit.net services: mysql: image: mysql:8.0 diff --git a/resources/views/emails/welcome_new_user_email_fn.blade.php b/resources/views/emails/welcome_new_user_email_fn.blade.php index 3e332ead..b8554298 100644 --- a/resources/views/emails/welcome_new_user_email_fn.blade.php +++ b/resources/views/emails/welcome_new_user_email_fn.blade.php @@ -1,37 +1,71 @@ @extends('emails.email_layout') @section('content') - +
- - - - @if(!empty($reset_password_link)) - - - - @endif - @if(!$user_is_complete) - - - - @endif - - - - - - + + + + + + + @if(!empty($reset_password_link)) + + + + @endif + @if(!$user_is_complete) + + + + @endif + + + + + +
-
Your {!! Config::get('app.app_name') !!} is: {!!$user_email!!}
-
-
If you did not set a password you can do so now (this link expires in {!! $reset_password_link_lifetime !!} min).
-
-
If you have not entered your first name, last name, company, and country please do so in your profile now. You may also update your photo, add a bio, and provide other information you wish to share.
-
-
Your {!! Config::get('app.app_name') !!} can be used to access all {!! Config::get('app.tenant_name') !!} apps necessary to interact with the event. In order for the apps to operate, each one will ask for permission to access your information and/or request the authority to use your {!! Config::get('app.app_name') !!}.
-
-
Should you have any questions, please email {!! Config::get('app.help_email') !!} for assistance.
-
+

Your FNid is ready.

+

One identity, every FNTECH app — for this event and the next.

+
+
+ {{ $user_email }} +
+
+ + + + + + + +
+
1
+
+
Set your password
+

Link expires in {!! $reset_password_link_lifetime !!} minutes.

+ Set password → +
+
+ + + + + + + +
+
{{ !empty($reset_password_link) ? '2' : '1' }}
+
+
Complete your profile
+

Add your name, company, and country. Photo and bio optional.

+ Open profile → +
+
+

You stay in control. Each {!! Config::get('app.tenant_name') !!} app will ask before accessing your information or acting on your behalf.

+
+ Questions? {!! Config::get('app.help_email') !!} +
@stop \ No newline at end of file diff --git a/tests/unit/WelcomeNewUserEmailFnViewTest.php b/tests/unit/WelcomeNewUserEmailFnViewTest.php new file mode 100644 index 00000000..6aef4a48 --- /dev/null +++ b/tests/unit/WelcomeNewUserEmailFnViewTest.php @@ -0,0 +1,106 @@ +createMock(User::class); + $user->method('getEmail')->willReturn($email); + $user->method('getFullName')->willReturn('Preview User'); + $user->method('getFirstName')->willReturn($complete ? 'Preview' : null); + $user->method('getLastName')->willReturn($complete ? 'User' : null); + $user->method('getCompany')->willReturn($complete ? 'ACME Inc.' : null); + $user->method('getCountry')->willReturn($complete ? 'US' : null); + $user->method('createdByOTP')->willReturn(false); + return $user; + } + + public function testWelcomeEmailWithPasswordLinkAndIncompleteProfile(): void + { + $email = 'preview+welcome@example.com'; + $resetLink = 'https://id.fntech.com/reset/abc123deadbeef'; + + $mailable = new WelcomeNewUserEmail($this->makeUser($email, false), $resetLink); + + $mailable->assertHasSubject( + sprintf('[%1$s] You now have an %1$s', Config::get('app.app_name')) + ); + $mailable->assertTo($email); + + $html = $mailable->render(); + + $this->assertStringContainsString('Your FNid is ready.', $html); + $this->assertStringContainsString($email, $html); + // Step 1 — password + $this->assertStringContainsString('Set your password', $html); + $this->assertStringContainsString($resetLink, $html); + // Step 2 — profile + $this->assertStringContainsString('Complete your profile', $html); + $this->assertStringContainsString('Open profile', $html); + // Disclaimer and footer + $this->assertStringContainsString('You stay in control', $html); + $this->assertStringContainsString(Config::get('app.help_email'), $html); + + } + + public function testWelcomeEmailWithoutPasswordLinkAndCompleteProfile(): void + { + $email = 'preview+welcome-complete@example.com'; + + $mailable = new WelcomeNewUserEmail($this->makeUser($email, true), null); + + $mailable->assertHasSubject( + sprintf('[%1$s] You now have an %1$s', Config::get('app.app_name')) + ); + $mailable->assertTo($email); + + $html = $mailable->render(); + + $this->assertStringContainsString('Your FNid is ready.', $html); + $this->assertStringContainsString($email, $html); + // Neither step should appear + $this->assertStringNotContainsString('Set your password', $html); + $this->assertStringNotContainsString('Complete your profile', $html); + // Disclaimer and footer always present + $this->assertStringContainsString('You stay in control', $html); + $this->assertStringContainsString(Config::get('app.help_email'), $html); + + } +}