Files
usher-manage-stack/tests/Feature/MemberRegistrationTest.php
2025-11-20 23:21:05 +08:00

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);
}
}