Files
usher-manage-stack/tests/Feature/BatchOperations/BatchOperationsTest.php
Gbanyan 642b879dd4 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>
2025-12-01 09:56:01 +08:00

271 lines
7.1 KiB
PHP

<?php
namespace Tests\Feature\BatchOperations;
use App\Models\FinanceDocument;
use App\Models\Issue;
use App\Models\Member;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
use Tests\Traits\CreatesFinanceData;
use Tests\Traits\CreatesMemberData;
use Tests\Traits\SeedsRolesAndPermissions;
/**
* Batch Operations Tests
*
* Tests bulk operations on records.
*/
class BatchOperationsTest extends TestCase
{
use RefreshDatabase, SeedsRolesAndPermissions, CreatesMemberData, CreatesFinanceData;
protected User $admin;
protected function setUp(): void
{
parent::setUp();
Storage::fake('private');
Storage::fake('local');
$this->seedRolesAndPermissions();
$this->admin = $this->createAdmin();
}
/**
* Test batch member status update
*/
public function test_batch_member_status_update(): void
{
$members = [];
for ($i = 0; $i < 5; $i++) {
$members[] = $this->createPendingMember();
}
$memberIds = array_map(fn ($m) => $m->id, $members);
$response = $this->actingAs($this->admin)->post(
route('admin.members.batch-update'),
[
'member_ids' => $memberIds,
'action' => 'activate',
]
);
foreach ($members as $member) {
$member->refresh();
$this->assertEquals(Member::STATUS_ACTIVE, $member->membership_status);
}
}
/**
* Test batch member suspend
*/
public function test_batch_member_suspend(): void
{
$members = [];
for ($i = 0; $i < 3; $i++) {
$members[] = $this->createActiveMember();
}
$memberIds = array_map(fn ($m) => $m->id, $members);
$response = $this->actingAs($this->admin)->post(
route('admin.members.batch-update'),
[
'member_ids' => $memberIds,
'action' => 'suspend',
]
);
foreach ($members as $member) {
$member->refresh();
$this->assertEquals(Member::STATUS_SUSPENDED, $member->membership_status);
}
}
/**
* Test batch issue status update
*/
public function test_batch_issue_status_update(): void
{
$issues = [];
for ($i = 0; $i < 5; $i++) {
$issues[] = Issue::factory()->create([
'created_by_user_id' => $this->admin->id,
'status' => Issue::STATUS_NEW,
]);
}
$issueIds = array_map(fn ($i) => $i->id, $issues);
$response = $this->actingAs($this->admin)->post(
route('admin.issues.batch-update'),
[
'issue_ids' => $issueIds,
'status' => Issue::STATUS_IN_PROGRESS,
]
);
foreach ($issues as $issue) {
$issue->refresh();
$this->assertEquals(Issue::STATUS_IN_PROGRESS, $issue->status);
}
}
/**
* Test batch issue assign
*/
public function test_batch_issue_assign(): void
{
$assignee = User::factory()->create();
$issues = [];
for ($i = 0; $i < 3; $i++) {
$issues[] = Issue::factory()->create([
'created_by_user_id' => $this->admin->id,
'assignee_id' => null,
]);
}
$issueIds = array_map(fn ($i) => $i->id, $issues);
$response = $this->actingAs($this->admin)->post(
route('admin.issues.batch-assign'),
[
'issue_ids' => $issueIds,
'assignee_id' => $assignee->id,
]
);
foreach ($issues as $issue) {
$issue->refresh();
$this->assertEquals($assignee->id, $issue->assignee_id);
}
}
/**
* Test batch issue close
*/
public function test_batch_issue_close(): void
{
$issues = [];
for ($i = 0; $i < 3; $i++) {
$issues[] = Issue::factory()->create([
'created_by_user_id' => $this->admin->id,
'status' => Issue::STATUS_REVIEW,
]);
}
$issueIds = array_map(fn ($i) => $i->id, $issues);
$response = $this->actingAs($this->admin)->post(
route('admin.issues.batch-update'),
[
'issue_ids' => $issueIds,
'status' => Issue::STATUS_CLOSED,
]
);
foreach ($issues as $issue) {
$issue->refresh();
$this->assertEquals(Issue::STATUS_CLOSED, $issue->status);
}
}
/**
* Test batch operation with empty selection
*/
public function test_batch_operation_with_empty_selection(): void
{
$response = $this->actingAs($this->admin)->post(
route('admin.members.batch-update'),
[
'member_ids' => [],
'action' => 'activate',
]
);
$response->assertSessionHasErrors('member_ids');
}
/**
* Test batch operation with invalid IDs
*/
public function test_batch_operation_with_invalid_ids(): void
{
$response = $this->actingAs($this->admin)->post(
route('admin.members.batch-update'),
[
'member_ids' => [99999, 99998],
'action' => 'activate',
]
);
// Should handle gracefully
$response->assertRedirect();
}
/**
* Test batch export members
*/
public function test_batch_export_members(): void
{
for ($i = 0; $i < 5; $i++) {
$this->createActiveMember();
}
$response = $this->actingAs($this->admin)->get(
route('admin.members.export', ['format' => 'csv'])
);
$response->assertStatus(200);
$response->assertHeader('content-type', 'text/csv; charset=UTF-8');
}
/**
* Test batch operation requires permission
*/
public function test_batch_operation_requires_permission(): void
{
$regularUser = User::factory()->create();
$member = $this->createPendingMember();
$response = $this->actingAs($regularUser)->post(
route('admin.members.batch-update'),
[
'member_ids' => [$member->id],
'action' => 'activate',
]
);
$response->assertForbidden();
}
/**
* Test batch operation limit
*/
public function test_batch_operation_limit(): void
{
// Create many members
$members = [];
for ($i = 0; $i < 100; $i++) {
$members[] = $this->createPendingMember();
}
$memberIds = array_map(fn ($m) => $m->id, $members);
$response = $this->actingAs($this->admin)->post(
route('admin.members.batch-update'),
[
'member_ids' => $memberIds,
'action' => 'activate',
]
);
// Should handle large batch
$this->assertTrue($response->isRedirect() || $response->isSuccessful());
}
}