262 lines
8.3 KiB
PHP
262 lines
8.3 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Mail\MemberRegistrationWelcomeMail;
|
|
use App\Models\Member;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use Tests\TestCase;
|
|
|
|
class MemberRegistrationTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
$this->artisan('db:seed', ['--class' => 'RoleSeeder']);
|
|
}
|
|
|
|
public function test_public_registration_form_is_accessible(): void
|
|
{
|
|
$response = $this->get(route('register.member'));
|
|
|
|
$response->assertStatus(200);
|
|
$response->assertSee('Register');
|
|
$response->assertSee('Full Name');
|
|
$response->assertSee('Email');
|
|
$response->assertSee('Password');
|
|
}
|
|
|
|
public function test_can_register_with_valid_data(): void
|
|
{
|
|
Mail::fake();
|
|
|
|
$response = $this->post(route('register.member.store'), [
|
|
'full_name' => 'John Doe',
|
|
'email' => 'john@example.com',
|
|
'password' => 'Password123!',
|
|
'password_confirmation' => 'Password123!',
|
|
'phone' => '0912345678',
|
|
'address_line_1' => '123 Test St',
|
|
'city' => 'Taipei',
|
|
'postal_code' => '100',
|
|
'emergency_contact_name' => 'Jane Doe',
|
|
'emergency_contact_phone' => '0987654321',
|
|
'terms_accepted' => true,
|
|
]);
|
|
|
|
$response->assertRedirect(route('member.dashboard'));
|
|
$response->assertSessionHas('status');
|
|
|
|
// Verify user created
|
|
$this->assertDatabaseHas('users', [
|
|
'email' => 'john@example.com',
|
|
]);
|
|
|
|
// Verify member created
|
|
$this->assertDatabaseHas('members', [
|
|
'full_name' => 'John Doe',
|
|
'email' => 'john@example.com',
|
|
'phone' => '0912345678',
|
|
'membership_status' => Member::STATUS_PENDING,
|
|
]);
|
|
}
|
|
|
|
public function test_user_and_member_records_created(): void
|
|
{
|
|
Mail::fake();
|
|
|
|
$this->post(route('register.member.store'), [
|
|
'full_name' => 'John Doe',
|
|
'email' => 'john@example.com',
|
|
'password' => 'Password123!',
|
|
'password_confirmation' => 'Password123!',
|
|
'phone' => '0912345678',
|
|
'terms_accepted' => true,
|
|
]);
|
|
|
|
$user = User::where('email', 'john@example.com')->first();
|
|
$member = Member::where('email', 'john@example.com')->first();
|
|
|
|
$this->assertNotNull($user);
|
|
$this->assertNotNull($member);
|
|
$this->assertEquals($user->id, $member->user_id);
|
|
$this->assertTrue(Hash::check('Password123!', $user->password));
|
|
}
|
|
|
|
public function test_user_is_auto_logged_in_after_registration(): void
|
|
{
|
|
Mail::fake();
|
|
|
|
$response = $this->post(route('register.member.store'), [
|
|
'full_name' => 'John Doe',
|
|
'email' => 'john@example.com',
|
|
'password' => 'Password123!',
|
|
'password_confirmation' => 'Password123!',
|
|
'terms_accepted' => true,
|
|
]);
|
|
|
|
$this->assertAuthenticated();
|
|
|
|
$user = User::where('email', 'john@example.com')->first();
|
|
$this->assertEquals($user->id, auth()->id());
|
|
}
|
|
|
|
public function test_welcome_email_is_sent(): void
|
|
{
|
|
Mail::fake();
|
|
|
|
$this->post(route('register.member.store'), [
|
|
'full_name' => 'John Doe',
|
|
'email' => 'john@example.com',
|
|
'password' => 'Password123!',
|
|
'password_confirmation' => 'Password123!',
|
|
'terms_accepted' => true,
|
|
]);
|
|
|
|
Mail::assertQueued(MemberRegistrationWelcomeMail::class, function ($mail) {
|
|
return $mail->hasTo('john@example.com');
|
|
});
|
|
}
|
|
|
|
public function test_validation_fails_with_invalid_email(): void
|
|
{
|
|
$response = $this->post(route('register.member.store'), [
|
|
'full_name' => 'John Doe',
|
|
'email' => 'invalid-email',
|
|
'password' => 'Password123!',
|
|
'password_confirmation' => 'Password123!',
|
|
'terms_accepted' => true,
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('email');
|
|
$this->assertDatabaseCount('users', 0);
|
|
$this->assertDatabaseCount('members', 0);
|
|
}
|
|
|
|
public function test_validation_fails_with_duplicate_email(): void
|
|
{
|
|
// Create existing user
|
|
User::factory()->create(['email' => 'existing@example.com']);
|
|
|
|
$response = $this->post(route('register.member.store'), [
|
|
'full_name' => 'John Doe',
|
|
'email' => 'existing@example.com',
|
|
'password' => 'Password123!',
|
|
'password_confirmation' => 'Password123!',
|
|
'terms_accepted' => true,
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('email');
|
|
}
|
|
|
|
public function test_validation_fails_with_duplicate_email_in_members(): void
|
|
{
|
|
// Create existing member without user
|
|
Member::factory()->create(['email' => 'existing@example.com', 'user_id' => null]);
|
|
|
|
$response = $this->post(route('register.member.store'), [
|
|
'full_name' => 'John Doe',
|
|
'email' => 'existing@example.com',
|
|
'password' => 'Password123!',
|
|
'password_confirmation' => 'Password123!',
|
|
'terms_accepted' => true,
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('email');
|
|
}
|
|
|
|
public function test_password_confirmation_required(): void
|
|
{
|
|
$response = $this->post(route('register.member.store'), [
|
|
'full_name' => 'John Doe',
|
|
'email' => 'john@example.com',
|
|
'password' => 'Password123!',
|
|
'password_confirmation' => 'DifferentPassword',
|
|
'terms_accepted' => true,
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('password');
|
|
$this->assertDatabaseCount('users', 0);
|
|
}
|
|
|
|
public function test_terms_acceptance_required(): void
|
|
{
|
|
$response = $this->post(route('register.member.store'), [
|
|
'full_name' => 'John Doe',
|
|
'email' => 'john@example.com',
|
|
'password' => 'Password123!',
|
|
'password_confirmation' => 'Password123!',
|
|
'terms_accepted' => false,
|
|
]);
|
|
|
|
$response->assertSessionHasErrors('terms_accepted');
|
|
$this->assertDatabaseCount('users', 0);
|
|
}
|
|
|
|
public function test_registration_creates_audit_log(): void
|
|
{
|
|
Mail::fake();
|
|
|
|
$this->post(route('register.member.store'), [
|
|
'full_name' => 'John Doe',
|
|
'email' => 'john@example.com',
|
|
'password' => 'Password123!',
|
|
'password_confirmation' => 'Password123!',
|
|
'terms_accepted' => true,
|
|
]);
|
|
|
|
$this->assertDatabaseHas('audit_logs', [
|
|
'action' => 'member.self_registered',
|
|
]);
|
|
}
|
|
|
|
public function test_member_status_is_pending_after_registration(): void
|
|
{
|
|
Mail::fake();
|
|
|
|
$this->post(route('register.member.store'), [
|
|
'full_name' => 'John Doe',
|
|
'email' => 'john@example.com',
|
|
'password' => 'Password123!',
|
|
'password_confirmation' => 'Password123!',
|
|
'terms_accepted' => true,
|
|
]);
|
|
|
|
$member = Member::where('email', 'john@example.com')->first();
|
|
$this->assertEquals(Member::STATUS_PENDING, $member->membership_status);
|
|
$this->assertEquals(Member::TYPE_REGULAR, $member->membership_type);
|
|
}
|
|
|
|
public function test_required_fields_validation(): void
|
|
{
|
|
$response = $this->post(route('register.member.store'), []);
|
|
|
|
$response->assertSessionHasErrors(['full_name', 'email', 'password', 'terms_accepted']);
|
|
}
|
|
|
|
public function test_optional_fields_can_be_null(): void
|
|
{
|
|
Mail::fake();
|
|
|
|
$response = $this->post(route('register.member.store'), [
|
|
'full_name' => 'John Doe',
|
|
'email' => 'john@example.com',
|
|
'password' => 'Password123!',
|
|
'password_confirmation' => 'Password123!',
|
|
'terms_accepted' => true,
|
|
// Optional fields omitted
|
|
]);
|
|
|
|
$response->assertRedirect(route('member.dashboard'));
|
|
|
|
$member = Member::where('email', 'john@example.com')->first();
|
|
$this->assertNull($member->phone);
|
|
$this->assertNull($member->address_line_1);
|
|
}
|
|
}
|