'superlevel'], ['body' => '100']); } /** * 方法功能:验证普通用户不能发送礼包。 */ public function test_normal_user_cannot_send_red_packet(): void { $user = User::factory()->create(['user_level' => 10]); $response = $this->actingAs($user)->postJson(route('command.red_packet.send'), [ 'room_id' => 1, 'type' => 'gold', ]); $response->assertStatus(403); $response->assertJson(['status' => 'error']); } /** * 方法功能:验证高等级但无职务权限的用户仍不能发送礼包。 */ public function test_high_level_user_without_red_packet_permission_cannot_send_red_packet(): void { $user = User::factory()->create(['user_level' => 100]); $response = $this->actingAs($user)->postJson(route('command.red_packet.send'), [ 'room_id' => 1, 'type' => 'gold', ]); $response->assertStatus(403); } /** * 方法功能:验证站长可以成功发出礼包并写入 Redis 拆包结果。 */ public function test_superadmin_can_send_red_packet(): void { $admin = $this->createSiteOwner(); $response = $this->actingAs($admin)->postJson(route('command.red_packet.send'), [ 'room_id' => 1, 'type' => 'gold', ]); $response->assertStatus(200); $response->assertJson(['status' => 'success']); $this->assertDatabaseHas('red_packet_envelopes', [ 'sender_id' => $admin->id, 'room_id' => 1, 'type' => 'gold', 'status' => 'active', ]); $envelope = RedPacketEnvelope::first(); // Check Redis for parts $this->assertEquals(10, Redis::llen("red_packet:{$envelope->id}:amounts")); } /** * 方法功能:验证拥有礼包权限的职务用户可以发礼包。 */ public function test_position_user_with_red_packet_permission_can_send_red_packet(): void { $user = $this->createUserWithPermissions([ PositionPermissionRegistry::ROOM_RED_PACKET, ]); $response = $this->actingAs($user)->postJson(route('command.red_packet.send'), [ 'room_id' => 1, 'type' => 'exp', ]); $response->assertOk()->assertJson([ 'status' => 'success', ]); } /** * 方法功能:验证同一房间内不可重复发送未结束的礼包。 */ public function test_cannot_send_multiple_active_packets_in_same_room(): void { $admin = $this->createSiteOwner(); $this->actingAs($admin)->postJson(route('command.red_packet.send'), [ 'room_id' => 1, 'type' => 'gold', ]); $response = $this->actingAs($admin)->postJson(route('command.red_packet.send'), [ 'room_id' => 1, 'type' => 'gold', ]); $response->assertStatus(422); } /** * 方法功能:验证用户可以领取礼包并增加金币余额。 */ public function test_user_can_claim_red_packet(): void { $admin = $this->createSiteOwner(); $user = User::factory()->create(['jjb' => 100]); // Send packet $this->actingAs($admin)->postJson(route('command.red_packet.send'), [ 'room_id' => 1, 'type' => 'gold', ]); $envelope = RedPacketEnvelope::first(); // Claim packet $response = $this->actingAs($user)->postJson(route('red_packet.claim', ['envelopeId' => $envelope->id]), [ 'room_id' => 1, ]); $response->assertStatus(200); $response->assertJson(['status' => 'success']); $this->assertDatabaseHas('red_packet_claims', [ 'envelope_id' => $envelope->id, 'user_id' => $user->id, ]); // Verify currency incremented $this->assertGreaterThan(100, $user->fresh()->jjb); } /** * 方法功能:验证领取成功后会返回并广播最新剩余份数。 */ public function test_claim_red_packet_returns_and_broadcasts_remaining_count(): void { Event::fake([RedPacketClaimed::class]); $admin = $this->createSiteOwner(); $user = User::factory()->create(['jjb' => 100]); $this->actingAs($admin)->postJson(route('command.red_packet.send'), [ 'room_id' => 1, 'type' => 'gold', ]); $envelope = RedPacketEnvelope::query()->firstOrFail(); $response = $this->actingAs($user)->postJson(route('red_packet.claim', ['envelopeId' => $envelope->id]), [ 'room_id' => 1, ]); $response->assertOk(); $response->assertJson([ 'status' => 'success', 'remaining_count' => 9, ]); Event::assertDispatched(RedPacketClaimed::class, function (RedPacketClaimed $event) use ($user, $envelope): bool { return $event->claimer->is($user) && $event->envelopeId === $envelope->id && $event->roomId === 1 && $event->remainingCount === 9 && $event->type === 'gold'; }); } /** * 方法功能:验证同一用户不能重复领取同一个礼包。 */ public function test_user_cannot_claim_same_packet_twice(): void { $admin = $this->createSiteOwner(); $user = User::factory()->create(); $this->actingAs($admin)->postJson(route('command.red_packet.send'), [ 'room_id' => 1, 'type' => 'gold', ]); $envelope = RedPacketEnvelope::first(); // First claim $this->actingAs($user)->postJson(route('red_packet.claim', ['envelopeId' => $envelope->id]), [ 'room_id' => 1, ]); // Second claim $response = $this->actingAs($user)->postJson(route('red_packet.claim', ['envelopeId' => $envelope->id]), [ 'room_id' => 1, ]); $response->assertStatus(422); $response->assertJson(['message' => '您已经领过这个礼包了']); } /** * 方法功能:验证可以查询礼包状态并识别当前用户是否已领取。 */ public function test_can_check_packet_status(): void { $admin = $this->createSiteOwner(); $user = User::factory()->create(); $this->actingAs($admin)->postJson(route('command.red_packet.send'), [ 'room_id' => 1, 'type' => 'gold', ]); $envelope = RedPacketEnvelope::first(); $response = $this->actingAs($user)->getJson(route('red_packet.status', ['envelopeId' => $envelope->id])); $response->assertStatus(200); $response->assertJson([ 'status' => 'success', 'has_claimed' => false, 'is_expired' => false, ]); // Claim it $this->actingAs($user)->postJson(route('red_packet.claim', ['envelopeId' => $envelope->id]), [ 'room_id' => 1, ]); $response2 = $this->actingAs($user)->getJson(route('red_packet.status', ['envelopeId' => $envelope->id])); $response2->assertJson([ 'status' => 'success', 'has_claimed' => true, ]); } /** * 创建站长账号。 */ private function createSiteOwner(): User { return User::factory()->create([ 'id' => 1, 'user_level' => 100, ]); } /** * 创建带指定聊天室权限的在职职务用户。 * * @param list $permissions */ private function createUserWithPermissions(array $permissions): User { $user = User::factory()->create([ 'user_level' => 80, ]); $department = Department::create([ 'name' => '红包权限部'.$user->id, 'rank' => 80, 'color' => '#dc2626', 'sort_order' => 1, 'description' => '红包权限测试', ]); $position = Position::create([ 'department_id' => $department->id, 'name' => '红包权限职务'.$user->id, 'icon' => '🧧', 'rank' => 80, 'level' => 80, 'sort_order' => 1, 'permissions' => $permissions, ]); UserPosition::create([ 'user_id' => $user->id, 'position_id' => $position->id, 'appointed_by_user_id' => null, 'appointed_at' => now(), 'remark' => '红包权限测试', 'is_active' => true, ]); return $user->fresh(); } }