diff --git a/resources/views/components/layouts/app.blade.php b/resources/views/components/layouts/app.blade.php
index a2dbce2..791b25b 100644
--- a/resources/views/components/layouts/app.blade.php
+++ b/resources/views/components/layouts/app.blade.php
@@ -26,7 +26,7 @@
@if(config('devdojo.auth.settings.enable_branding') && !app()->isLocal())
-
+
Secured by DevDojo
diff --git a/resources/views/pages/auth/password/[token].blade.php b/resources/views/pages/auth/password/[token].blade.php
index 5d50612..45e76ff 100644
--- a/resources/views/pages/auth/password/[token].blade.php
+++ b/resources/views/pages/auth/password/[token].blade.php
@@ -6,9 +6,7 @@
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Auth\Events\PasswordReset;
-
-use function Laravel\Folio\name;
-
+use function Laravel\Folio\{middleware, name};
use Livewire\Volt\Component;
use Livewire\Attributes\Validate;
@@ -78,10 +76,10 @@ function ($user, $password) {
/>
@endvolt
diff --git a/resources/views/pages/auth/password/confirm.blade.php b/resources/views/pages/auth/password/confirm.blade.php
index 3e961ab..62c0b65 100644
--- a/resources/views/pages/auth/password/confirm.blade.php
+++ b/resources/views/pages/auth/password/confirm.blade.php
@@ -1,10 +1,14 @@
isLocal()){
+ middleware('auth');
+}
+
name('password.confirm');
new class extends Component
@@ -40,8 +44,8 @@ public function confirm()
:show_subheadline="($language->passwordConfirm->show_subheadline ?? false)"
/>
@endvolt
diff --git a/resources/views/pages/auth/password/reset.blade.php b/resources/views/pages/auth/password/reset.blade.php
index 37647f3..33273ff 100644
--- a/resources/views/pages/auth/password/reset.blade.php
+++ b/resources/views/pages/auth/password/reset.blade.php
@@ -2,7 +2,7 @@
use Devdojo\Auth\Traits\HasConfigs;
use Illuminate\Support\Facades\Password;
-use function Laravel\Folio\name;
+use function Laravel\Folio\{middleware, name};
use Livewire\Volt\Component;
use Livewire\Attributes\Validate;
@@ -68,13 +68,13 @@ public function sendResetPasswordLink()
@else
@endif
Or
- return to login
+ return to login
@endvolt
diff --git a/resources/views/pages/user/two-factor-authentication/index.blade.php b/resources/views/pages/user/two-factor-authentication/index.blade.php
index e5e0ddd..a95d08b 100644
--- a/resources/views/pages/user/two-factor-authentication/index.blade.php
+++ b/resources/views/pages/user/two-factor-authentication/index.blade.php
@@ -128,7 +128,7 @@ public function disable(){
Two factor authentication disabled.
When you enabled 2FA, you will be prompted for a secure code during authentication. This code can be retrieved from your phone's Google Authenticator application.
- Enable
+ Enable
@else
diff --git a/routes/web.php b/routes/web.php
index f77adf1..a383fc9 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -28,15 +28,6 @@
// Add social routes
Route::get('auth/{driver}/redirect', [SocialController::class, 'redirect']);
Route::get('auth/{driver}/callback', [SocialController::class, 'callback']);
-});
-
-Route::get('hey', function () {
- $rowsArray = [];
- $socialProviders = config('devdojo.auth.providers', []);
- foreach ($socialProviders as $key => $provider) {
- $provider['slug'] = $key;
- array_push($rowsArray, $provider);
- }
- dd($rowsArray);
});
+
diff --git a/src/AuthServiceProvider.php b/src/AuthServiceProvider.php
index fe8d988..fc74f24 100644
--- a/src/AuthServiceProvider.php
+++ b/src/AuthServiceProvider.php
@@ -80,6 +80,7 @@ public function boot(): void
}
$this->handleStarterKitFunctionality();
+ $this->loadDynamicRoutesForTesting();
}
private function registerAuthFolioDirectory(): void
@@ -150,4 +151,13 @@ public function register()
$this->app->register(\Devdojo\Auth\Providers\DuskServiceProvider::class);
}
}
+
+ private function loadDynamicRoutesForTesting()
+ {
+ if (app()->environment('testing') || app()->environment('local')) {
+ Route::get('/auth/password_confirmation_test', function () {
+ return 'Test Confirmed';
+ })->middleware('web', 'auth', 'password.confirm');
+ }
+ }
}
diff --git a/src/Providers/DuskServiceProvider.php b/src/Providers/DuskServiceProvider.php
index 367ab45..a27f63a 100644
--- a/src/Providers/DuskServiceProvider.php
+++ b/src/Providers/DuskServiceProvider.php
@@ -45,6 +45,18 @@ public function boot(): void
return $this;
});
+ Browser::macro('loginAsJohnDoe', function(){
+ $this->loginAs(\Devdojo\Auth\Models\User::where('email', 'johndoe@gmail.com')->first());
+ return $this;
+ });
+
+ Browser::macro('enable2FAforJohnDoe', function(){
+ $johnDoe = \Devdojo\Auth\Models\User::where('email', 'johndoe@gmail.com')->first();
+ $johnDoe->two_factor_confirmed_at = now();
+ $johnDoe->save();
+ return $this;
+ });
+
Browser::macro('assertRedirectAfterAuthUrlIsCorrect', function () {
$redirectExpectedToBe = '/';
if (class_exists(\Devdojo\Genesis\Genesis::class)) {
@@ -67,5 +79,18 @@ public function boot(): void
return $this;
});
+
+ Browser::macro('typeAndSubmit', function (?string $selector, string $value) {
+ $this->type($selector, $value)
+ ->click('@submit-button');
+
+ return $this;
+ });
+
+ Browser::macro('visitPasswordConfirmTestPage', function () {
+ $this->visit('/auth/password_confirmation_test');
+ return $this;
+ });
+
}
}
diff --git a/tests/Browser/ConfirmPasswordTest.php b/tests/Browser/ConfirmPasswordTest.php
new file mode 100644
index 0000000..ac6aee3
--- /dev/null
+++ b/tests/Browser/ConfirmPasswordTest.php
@@ -0,0 +1,55 @@
+browse(function (Browser $browser) {
+ $browser
+ ->visit(new ConfirmPassword)
+ ->assertPathIs('/auth/login');
+ });
+});
+
+test('Password Confirm Protected Page Redirects', function () {
+ $browser = $this->browse(function (Browser $browser) {
+ $browser
+ ->visitPasswordConfirmTestPage()
+ ->assertPathIs('/auth/login')
+ ->createJohnDoe()
+ ->loginAsJohnDoe()
+ ->visitPasswordConfirmTestPage()
+ ->assertPathIs('/auth/password/confirm');
+ });
+});
+
+test('Password Confirm Works', function(){
+ $browser = $this->browse(function (Browser $browser) {
+ $browser
+ ->createJohnDoe()
+ ->loginAsJohnDoe()
+ ->visit(new ConfirmPassword)
+ ->type('@password-input', 'password')
+ ->clickAndWaitForReload('@submit-button')
+ ->assertRedirectAfterAuthUrlIsCorrect();
+ });
+});
+
+test('Password Confirm Works and redirect to password protected page', function(){
+ $browser = $this->browse(function (Browser $browser) {
+ $browser
+ ->createJohnDoe()
+ ->loginAsJohnDoe()
+ ->visitPasswordConfirmTestPage()
+ ->type('@password-input', 'password')
+ ->clickAndWaitForReload('@submit-button')
+ ->assertSee('Test Confirmed');
+ });
+});
\ No newline at end of file
diff --git a/tests/Browser/ForgotPasswordTest.php b/tests/Browser/ForgotPasswordTest.php
new file mode 100644
index 0000000..67682bc
--- /dev/null
+++ b/tests/Browser/ForgotPasswordTest.php
@@ -0,0 +1,73 @@
+browse(function (Browser $browser) {
+ $browser
+ ->visit(new PasswordResetRequest)
+ ->authAttributeRemove('#email', 'required')
+ ->testValidationErrorOnSubmit('The email field is required');
+ });
+});
+
+test('Invalid Email Validation', function () {
+ $browser = $this->browse(function (Browser $browser) {
+ $browser
+ ->visit(new PasswordResetRequest)
+ ->authAttributeChange('#email', 'type', 'text')
+ ->type('@email-input', 'johndoe')
+ ->testValidationErrorOnSubmit('The email field must be a valid email address');
+ });
+});
+
+test('Email Does Not Exist', function () {
+ $browser = $this->browse(function (Browser $browser) {
+ $browser
+ ->visit(new PasswordResetRequest)
+ ->type('@email-input', 'jimmycrackcorn@gmail.com')
+ ->testValidationErrorOnSubmit('We can\'t find a user with that email address');
+ });
+});
+
+test('Email reset functionality', function () {
+ $browser = $this->browse(function (Browser $browser) {
+
+ $browser
+ ->visit(new PasswordResetRequest)
+ ->createJohnDoe()
+ ->clearLogFile()
+ ->typeAndSubmit('@email-input', 'johndoe@gmail.com')
+ ->waitForText('We have emailed your password reset link')
+ ->getLogFile(function ($content) use ($browser) {
+
+ $foundLine = $this->findLineContainingSubstring($content, 'Reset Password:');
+ $url = str_replace('Reset Password: ', '', $foundLine);
+ $browser
+ ->visit($url)
+ ->assertSeeIn('#auth-heading-title', 'Reset Password')
+ ->type('@password-input', 'password123')
+ ->type('@password-confirm-input', 'password123')
+ ->clickAndWaitForReload('@submit-button')
+ ->assertRedirectAfterAuthUrlIsCorrect();
+ });
+ });
+});
+
+test('Link to Login Page', function () {
+ $browser = $this->browse(function (Browser $browser) {
+ $browser
+ ->visit(new PasswordResetRequest)
+ ->click('@login-link')
+ ->waitFor('@auth-login')
+ ->assertPathIs('/auth/login');
+ });
+});
\ No newline at end of file
diff --git a/tests/Browser/LoginTest.php b/tests/Browser/LoginTest.php
index 0d2ac63..40f0dbf 100644
--- a/tests/Browser/LoginTest.php
+++ b/tests/Browser/LoginTest.php
@@ -10,7 +10,8 @@
$this->browse(function (Browser $browser) {
$browser->visit(new Login)
->createJohnDoe()
- ->loginAsJohnDoe();
+ ->formLoginAsJohnDoe()
+ ->assertRedirectAfterAuthUrlIsCorrect();
});
});
diff --git a/tests/Browser/LogoutTest.php b/tests/Browser/LogoutTest.php
new file mode 100644
index 0000000..e69de29
diff --git a/tests/Browser/Pages/ConfirmPassword.php b/tests/Browser/Pages/ConfirmPassword.php
new file mode 100644
index 0000000..7b1a8e9
--- /dev/null
+++ b/tests/Browser/Pages/ConfirmPassword.php
@@ -0,0 +1,16 @@
+visit('/auth/login')
@@ -23,17 +23,9 @@ public function loginAsJohnDoe(Browser $browser)
->click('@submit-button')
->waitFor('@password-input')
->type('@password-input', 'password')
- ->clickAndWaitForReload('@submit-button')
- ->assertRedirectAfterAuthUrlIsCorrect();
+ ->clickAndWaitForReload('@submit-button');
return $this;
}
- public function typeAndSubmit(Browser $browser, $selector, $value)
- {
- $browser->type($selector, $value)
- ->click('@submit-button');
-
- return $this;
- }
}
diff --git a/tests/Browser/Pages/PasswordResetRequest.php b/tests/Browser/Pages/PasswordResetRequest.php
new file mode 100644
index 0000000..3aa986f
--- /dev/null
+++ b/tests/Browser/Pages/PasswordResetRequest.php
@@ -0,0 +1,16 @@
+browse(function (Browser $browser) {
+ $browser->visit(new TwoFactorAuth)
+ ->assertPathIs('/auth/login');
+ });
+});
+
+test('Successfully View 2FA Setup Page', function () {
+
+ $this->browse(function (Browser $browser) {
+ $browser
+ ->createJohnDoe()
+ ->loginAsJohnDoe()
+ ->visit(new TwoFactorAuth)
+ ->assertSee('Two factor authentication disabled')
+ ->click('@enable-button')
+ ->waitForText('Finish enabling two factor authentication')
+ ->assertSee('Finish enabling two factor authentication');
+ });
+});
+
diff --git a/tests/Browser/TwoFactorChallengeTest.php b/tests/Browser/TwoFactorChallengeTest.php
new file mode 100644
index 0000000..f2ead27
--- /dev/null
+++ b/tests/Browser/TwoFactorChallengeTest.php
@@ -0,0 +1,29 @@
+browse(function (Browser $browser) {
+ $browser->visit(new TwoFactorChallenge)
+ ->assertPathIs('/auth/login');
+ });
+});
+
+test('User logs in with 2fa enabled and redirected to challenge', function () {
+ // Turn on 2FA site-wide
+ $this->setConfig('devdojo.auth.settings.enable_2fa', true);
+ $this->browse(function (Browser $browser) {
+ $browser->visit(new Login)
+ ->createJohnDoe()
+ ->enable2FAforJohnDoe()
+ ->formLoginAsJohnDoe()
+ ->assertPathIs('/auth/two-factor-challenge');
+
+ $browser->pause(2000);
+ });
+});
\ No newline at end of file