User registration and corresponding test

This commit is contained in:
Ryan Scherler
2020-10-27 18:05:23 -07:00
parent e6ced901d0
commit bdb84d2ffa
16 changed files with 251 additions and 32 deletions
+3 -2
View File
@@ -15,12 +15,12 @@ return [
*/
'features' => [
Features::users(),
Features::registration(),
],
'models' => [
// 'model' => App\Models\Model::class,
'user' => config('auth.providers.users.model'),
],
@@ -80,6 +80,7 @@ return [
'login' => Filament\Http\Livewire\Auth\Login::class,
'forgot-password' => Filament\Http\Livewire\Auth\ForgotPassword::class,
'reset-password' => Filament\Http\Livewire\Auth\ResetPassword::class,
'register' => Filament\Http\Livewire\Auth\Register::class,
'dashboard' => Filament\Http\Livewire\Dashboard::class,
],
+2
View File
@@ -15,4 +15,6 @@ return [
'signin' => 'Sign in to your account',
'register' => 'Create a new account',
];
@@ -1,6 +1,13 @@
<form wire:submit.prevent="login" class="space-y-4">
<x-filament::input-group-stacked name="email" :label="__('E-Mail Address')" required>
<x-filament::input type="email" name="email" wire:model.defer="email" id="email" required autocomplete="email" autofocus />
@if (Route::has('filament.register'))
<x-slot name="hint">
<a href="{{ route('filament.register') }}" class="text-current hover:text-blue">
{{ __('filament::auth.register') }}
</a>
</x-slot>
@endif
</x-filament::input-group-stacked>
<x-filament::input-group-stacked name="password" :label="__('Password')" required>
@@ -0,0 +1,27 @@
<form wire:submit.prevent="register" class="space-y-4">
<x-filament::input-group-stacked name="name" :label="__('Name')" required>
<x-filament::input name="name" wire:model.defer="name" id="name" required autofocus />
<x-slot name="hint">
<a href="{{ route('filament.login') }}" class="text-current hover:text-blue">
&larr; {{ __('Back to login') }}
</a>
</x-slot>
</x-filament::input-group-stacked>
<x-filament::input-group-stacked name="email" :label="__('E-Mail Address')" required>
<x-filament::input type="email" name="email" wire:model.lazy="email" id="email" required autocomplete="email" />
</x-filament::input-group-stacked>
<x-filament::input-group-stacked name="password" :label="__('New Password')" required>
<x-filament::input type="password" name="password" wire:model.defer="password" id="password" required autocomplete="new-password" />
</x-filament::input-group-stacked>
<x-filament::input-group-stacked name="password_confirmation" :label="__('Confirm New Password')" required>
<x-filament::input type="password" name="password_confirmation" wire:model.defer="password_confirmation" id="password_confirmation" required autocomplete="new-password" />
</x-filament::input-group-stacked>
<x-filament::button type="submit" class="w-full" wire:loading.attr="disabled">
<x-filament::loader class="w-6 h-6 absolute left-0 ml-2 pointer-events-none" wire:loading />
{{ __('Register') }}
</x-filament::button>
</form>
+5 -13
View File
@@ -24,23 +24,15 @@ Route::group([
Route::get('/forgot-password', config('filament.livewire.forgot-password'))->name('password.forgot');
Route::get('/reset-password/{token}', config('filament.livewire.reset-password'))->name('password.reset');
// Registration
if (Features::registersUsers()) {
Route::get('/register', config('filament.livewire.register'))->name('register');
}
// Authenticated routes
Route::group(['middleware' => ['auth', 'verified']], function () {
// Dashboard
Route::get('/', config('filament.livewire.dashboard'))->name('dashboard');
/*
// User profile
Route::get('/profile', config('filament.livewire.profile'))->name('profile');
// Users
if (Features::managesUsers()) {
Route::name('users.')->group(function () {
Route::get('/users', config('filament.livewire.users'))->name('index');
Route::get('/user/{user}', config('filament.livewire.user'))->name('show');
});
}
*/
});
});
+8
View File
@@ -0,0 +1,8 @@
<?php
namespace Filament\Contracts;
interface User
{
//
}
+6 -6
View File
@@ -16,22 +16,22 @@ class Features
}
/**
* Determine if the application manages users.
* Determine if the application allows user registration.
*
* @return bool
*/
public static function managesUsers()
public static function registersUsers()
{
return static::enabled(static::users());
return static::enabled(static::registration());
}
/**
* Enable the users feature.
* Enable the user registration feature.
*
* @return string
*/
public static function users()
public static function registration()
{
return 'users';
return 'registration';
}
}
+4 -3
View File
@@ -10,6 +10,7 @@ use Illuminate\Support\Facades\{
Blade,
};
use Livewire\Livewire;
use Filament\Contracts\User as UserContract;
use Filament\Commands\{
MakeUser,
};
@@ -50,13 +51,13 @@ class FilamentServiceProvider extends ServiceProvider
protected function bootModelBindings(): void
{
$config = $this->app->config['filament.models'];
$models = $this->app->config['filament.models'];
if (! $config) {
if (! $models) {
return;
}
// $this->app->bind(ModelContract::class, $config['model']);
$this->app->bind(UserContract::class, $models['user']);
}
protected function bootPolicies(): void
+47
View File
@@ -0,0 +1,47 @@
<?php
namespace Filament\Http\Livewire\Auth;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Livewire\Component;
use Filament\Contracts\User as UserContract;
class Register extends Component
{
public $name;
public $email;
public $password;
public $password_confirmation;
protected $rules = [
'name' => 'required|min:2',
'email' => 'required|email|unique:users',
'password' => 'required|min:8|confirmed',
'password_confirmation' => 'required|same:password',
];
public function updatedEmail($value)
{
$this->validateOnly('email', ['email' => 'unique:users']);
}
public function register()
{
$this->validate();
$userClass = app(UserContract::class);
$user = $userClass::create([
'name' => $this->name,
'email' => $this->email,
'password' => Hash::make($this->password),
]);
Auth::login($user);
return redirect()->route('filament.dashboard');
}
public function render()
{
return view('filament::livewire.auth.register')
->layout('filament::layouts.auth', ['title' => __('filament::auth.register')]);
}
}
+1 -1
View File
@@ -24,7 +24,7 @@ class ResetPassword extends Component
protected $rules = [
'email' => 'required|email',
'password' => 'required|min:8|confirmed',
'password_confirmation' => 'required',
'password_confirmation' => 'required|same:password',
];
public function mount(Request $request, $token)
+17 -2
View File
@@ -14,10 +14,25 @@ class User extends Authenticatable
use HasFactory, Notifiable, FilamentUser;
/**
* Disable Laravel's mass assignment protection
* The attributes that are mass assignable.
*
* @var array
*/
protected $guarded = [];
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast to native types.
+2 -2
View File
@@ -1,6 +1,6 @@
<?php
namespace Tests\Feature;
namespace Filament\Tests\Feature;
use Illuminate\Auth\Notifications\ResetPassword as ResetPasswordNotification;
use Illuminate\Foundation\Testing\RefreshDatabase;
@@ -9,8 +9,8 @@ use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Password;
use Livewire\Livewire;
use Filament\Tests\TestCase;
use Filament\Http\Livewire\Auth\ForgotPassword;
use Filament\Tests\Database\Models\User;
use Filament\Http\Livewire\Auth\ForgotPassword;
class ForgotPasswordTest extends TestCase
{
+1 -1
View File
@@ -1,6 +1,6 @@
<?php
namespace Tests\Feature;
namespace Filament\Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
+118
View File
@@ -0,0 +1,118 @@
<?php
namespace Filament\Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Filament\Tests\TestCase;
use Filament\Http\Livewire\Auth\Register;
use Filament\Tests\Database\Models\User;
class RegisterTest extends TestCase
{
use RefreshDatabase;
public function test_can_see_register_form()
{
$this->get(route('filament.register'))
->assertSuccessful()
->assertSee(__('filament::auth.register'));
}
public function test_can_register()
{
Livewire::test(Register::class)
->set('name', 'Me')
->set('email', 'me@example.com')
->set('password', 'password')
->set('password_confirmation', 'password')
->call('register')
->assertHasNoErrors(['name', 'email', 'password', 'password_confirmation'])
->assertRedirect(route('filament.dashboard'));
$this->assertDatabaseHas('users', [
'name' => 'Me',
'email' => 'me@example.com',
]);
$this->assertAuthenticated();
}
public function test_name_is_required()
{
Livewire::test(Register::class)
->call('register')
->assertHasErrors(['name' => 'required']);
}
public function test_name_is_minimum_two_characters()
{
Livewire::test(Register::class)
->set('name', 'a')
->call('register')
->assertHasErrors(['name' => 'min']);
}
public function test_email_is_required()
{
Livewire::test(Register::class)
->call('register')
->assertHasErrors(['email' => 'required']);
}
public function test_email_is_valid_email()
{
Livewire::test(Register::class)
->set('email', 'Something')
->call('register')
->assertHasErrors(['email' => 'email']);
}
public function test_email_is_unique()
{
User::factory()->create(['email' => 'test@example.com']);
Livewire::test(Register::class)
->set('email', 'test@example.com')
->assertHasErrors(['email' => 'unique']);
}
public function test_password_is_required()
{
Livewire::test(Register::class)
->call('register')
->assertHasErrors(['password' => 'required']);
}
public function test_password_is_minimum_eight_characters()
{
Livewire::test(Register::class)
->set('password', 'test')
->call('register')
->assertHasErrors(['password' => 'min']);
}
public function test_password_must_be_confirmed()
{
Livewire::test(Register::class)
->set('password', 'test')
->call('register')
->assertHasErrors(['password' => 'confirmed']);
}
public function test_password_confirmation_is_required()
{
Livewire::test(Register::class)
->call('register')
->assertHasErrors(['password_confirmation' => 'required']);
}
public function test_password_confirmation_matches_password()
{
Livewire::test(Register::class)
->set('password', 'test')
->set('password_confirmation', 'test2')
->call('register')
->assertHasErrors(['password_confirmation' => 'same']);
}
}
+2 -2
View File
@@ -1,15 +1,15 @@
<?php
namespace Tests\Feature;
namespace Filament\Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Password;
use Livewire\Livewire;
use Filament\Tests\TestCase;
use Filament\Tests\Database\Models\User;
use Filament\Http\Livewire\Auth\Login;
use Filament\Http\Livewire\Auth\ResetPassword;
use Filament\Tests\Database\Models\User;
class ResetPasswordTest extends TestCase
{
+1
View File
@@ -78,5 +78,6 @@ abstract class TestCase extends OrchestraTestCase
]);
$app['config']->set('auth.providers.users.model', User::class);
$app['config']->set('filament.models.user', User::class);
}
}