Add membership fee system with disability discount and fix document permissions
Features: - Implement two fee types: entrance fee and annual fee (both NT$1,000) - Add 50% discount for disability certificate holders - Add disability certificate upload in member profile - Integrate disability verification into cashier approval workflow - Add membership fee settings in system admin Document permissions: - Fix hard-coded role logic in Document model - Use permission-based authorization instead of role checks Additional features: - Add announcements, general ledger, and trial balance modules - Add income management and accounting entries - Add comprehensive test suite with factories - Update UI translations to Traditional Chinese 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
211
tests/Browser/MemberDashboardBrowserTest.php
Normal file
211
tests/Browser/MemberDashboardBrowserTest.php
Normal file
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Browser;
|
||||
|
||||
use App\Models\Member;
|
||||
use App\Models\MembershipPayment;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Laravel\Dusk\Browser;
|
||||
use Tests\DuskTestCase;
|
||||
|
||||
/**
|
||||
* Member Dashboard Browser Tests
|
||||
*
|
||||
* Tests the member dashboard user interface and user experience.
|
||||
*/
|
||||
class MemberDashboardBrowserTest extends DuskTestCase
|
||||
{
|
||||
use DatabaseMigrations;
|
||||
|
||||
protected User $memberUser;
|
||||
|
||||
protected Member $member;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->artisan('db:seed', ['--class' => 'FinancialWorkflowPermissionsSeeder']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a member user for testing
|
||||
*/
|
||||
protected function createMemberUser(): User
|
||||
{
|
||||
$user = User::factory()->create([
|
||||
'email' => 'member@test.com',
|
||||
'password' => Hash::make('password'),
|
||||
]);
|
||||
|
||||
Member::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'membership_status' => Member::STATUS_ACTIVE,
|
||||
]);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test member can view dashboard
|
||||
*/
|
||||
public function test_member_can_view_dashboard(): void
|
||||
{
|
||||
$user = $this->createMemberUser();
|
||||
|
||||
$this->browse(function (Browser $browser) use ($user) {
|
||||
$browser->loginAs($user)
|
||||
->visit(route('member.dashboard'))
|
||||
->assertSee('會員')
|
||||
->assertSee('儀表板');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test member sees membership status
|
||||
*/
|
||||
public function test_member_sees_membership_status(): void
|
||||
{
|
||||
$user = $this->createMemberUser();
|
||||
|
||||
$this->browse(function (Browser $browser) use ($user) {
|
||||
$browser->loginAs($user)
|
||||
->visit(route('member.dashboard'))
|
||||
->assertSee('會員狀態');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test member can navigate to payment page
|
||||
*/
|
||||
public function test_member_can_navigate_to_payment_page(): void
|
||||
{
|
||||
$user = $this->createMemberUser();
|
||||
|
||||
$this->browse(function (Browser $browser) use ($user) {
|
||||
$browser->loginAs($user)
|
||||
->visit(route('member.dashboard'))
|
||||
->clickLink('繳費')
|
||||
->assertPathIs('/member/payments*');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test member can view payment history
|
||||
*/
|
||||
public function test_member_can_view_payment_history(): void
|
||||
{
|
||||
$user = $this->createMemberUser();
|
||||
$member = $user->member;
|
||||
|
||||
MembershipPayment::factory()->count(3)->create([
|
||||
'member_id' => $member->id,
|
||||
'status' => MembershipPayment::STATUS_APPROVED_CHAIR,
|
||||
]);
|
||||
|
||||
$this->browse(function (Browser $browser) use ($user) {
|
||||
$browser->loginAs($user)
|
||||
->visit(route('member.payments.index'))
|
||||
->assertSee('繳費紀錄');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test member can submit new payment
|
||||
*/
|
||||
public function test_member_can_submit_new_payment(): void
|
||||
{
|
||||
$user = $this->createMemberUser();
|
||||
|
||||
$this->browse(function (Browser $browser) use ($user) {
|
||||
$browser->loginAs($user)
|
||||
->visit(route('member.payments.create'))
|
||||
->assertSee('提交繳費')
|
||||
->assertPresent('input[name="amount"]')
|
||||
->assertPresent('input[type="file"]');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test member sees pending payment status
|
||||
*/
|
||||
public function test_member_sees_pending_payment_status(): void
|
||||
{
|
||||
$user = $this->createMemberUser();
|
||||
$member = $user->member;
|
||||
|
||||
MembershipPayment::factory()->create([
|
||||
'member_id' => $member->id,
|
||||
'status' => MembershipPayment::STATUS_PENDING,
|
||||
]);
|
||||
|
||||
$this->browse(function (Browser $browser) use ($user) {
|
||||
$browser->loginAs($user)
|
||||
->visit(route('member.payments.index'))
|
||||
->assertSee('待審核');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test member can update profile
|
||||
*/
|
||||
public function test_member_can_update_profile(): void
|
||||
{
|
||||
$user = $this->createMemberUser();
|
||||
|
||||
$this->browse(function (Browser $browser) use ($user) {
|
||||
$browser->loginAs($user)
|
||||
->visit(route('member.profile.edit'))
|
||||
->assertPresent('input[name="phone"]')
|
||||
->assertPresent('input[name="address"]');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test member dashboard shows expiry date
|
||||
*/
|
||||
public function test_member_dashboard_shows_expiry_date(): void
|
||||
{
|
||||
$user = $this->createMemberUser();
|
||||
$user->member->update([
|
||||
'membership_expires_at' => now()->addYear(),
|
||||
]);
|
||||
|
||||
$this->browse(function (Browser $browser) use ($user) {
|
||||
$browser->loginAs($user)
|
||||
->visit(route('member.dashboard'))
|
||||
->assertSee('到期');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test logout functionality
|
||||
*/
|
||||
public function test_logout_functionality(): void
|
||||
{
|
||||
$user = $this->createMemberUser();
|
||||
|
||||
$this->browse(function (Browser $browser) use ($user) {
|
||||
$browser->loginAs($user)
|
||||
->visit(route('member.dashboard'))
|
||||
->click('@user-menu')
|
||||
->clickLink('登出')
|
||||
->assertPathIs('/');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test member cannot access admin pages
|
||||
*/
|
||||
public function test_member_cannot_access_admin_pages(): void
|
||||
{
|
||||
$user = $this->createMemberUser();
|
||||
|
||||
$this->browse(function (Browser $browser) use ($user) {
|
||||
$browser->loginAs($user)
|
||||
->visit('/admin/dashboard')
|
||||
->assertPathIsNot('/admin/dashboard');
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user