scenario = Scenario::factory()->create(); } public function test_can_update_starting_amount_only(): void { $bucket = Bucket::factory()->need()->fixedLimit(1000)->create([ 'scenario_id' => $this->scenario->id, 'starting_amount' => 0, 'priority' => 1, ]); $response = $this->patchJson("/buckets/{$bucket->uuid}", [ 'starting_amount' => 500, ]); $response->assertOk(); $this->assertDatabaseHas('buckets', [ 'id' => $bucket->id, 'starting_amount' => 500, 'name' => $bucket->name, 'type' => $bucket->type->value, ]); } public function test_can_update_type_only(): void { $bucket = Bucket::factory()->need()->fixedLimit(1000)->create([ 'scenario_id' => $this->scenario->id, 'priority' => 1, ]); $response = $this->patchJson("/buckets/{$bucket->uuid}", [ 'type' => 'want', ]); $response->assertOk(); $this->assertDatabaseHas('buckets', [ 'id' => $bucket->id, 'type' => BucketTypeEnum::WANT->value, 'name' => $bucket->name, ]); } public function test_can_update_buffer_multiplier_only(): void { $bucket = Bucket::factory()->need()->fixedLimit(1000)->create([ 'scenario_id' => $this->scenario->id, 'buffer_multiplier' => 0, 'priority' => 1, ]); $response = $this->patchJson("/buckets/{$bucket->uuid}", [ 'buffer_multiplier' => 1.5, ]); $response->assertOk(); $this->assertDatabaseHas('buckets', [ 'id' => $bucket->id, 'buffer_multiplier' => 1.5, ]); } public function test_cannot_change_overflow_type(): void { $bucket = Bucket::factory()->overflow()->create([ 'scenario_id' => $this->scenario->id, 'priority' => 1, ]); $response = $this->patchJson("/buckets/{$bucket->uuid}", [ 'type' => 'need', ]); $response->assertUnprocessable(); $response->assertJsonValidationErrors('type'); } public function test_starting_amount_rejects_negative(): void { $bucket = Bucket::factory()->need()->fixedLimit(1000)->create([ 'scenario_id' => $this->scenario->id, 'priority' => 1, ]); $response = $this->patchJson("/buckets/{$bucket->uuid}", [ 'starting_amount' => -100, ]); $response->assertUnprocessable(); $response->assertJsonValidationErrors('starting_amount'); } public function test_buffer_multiplier_forced_to_zero_for_non_fixed_limit(): void { $bucket = Bucket::factory()->need()->fixedLimit(1000)->create([ 'scenario_id' => $this->scenario->id, 'buffer_multiplier' => 1.5, 'priority' => 1, ]); $response = $this->patchJson("/buckets/{$bucket->uuid}", [ 'allocation_type' => 'percentage', 'allocation_value' => 25, ]); $response->assertOk(); $this->assertDatabaseHas('buckets', [ 'id' => $bucket->id, 'allocation_type' => BucketAllocationTypeEnum::PERCENTAGE->value, 'buffer_multiplier' => 0, ]); } public function test_response_includes_starting_amount(): void { $bucket = Bucket::factory()->need()->fixedLimit(1000)->create([ 'scenario_id' => $this->scenario->id, 'starting_amount' => 500, 'priority' => 1, ]); $response = $this->patchJson("/buckets/{$bucket->uuid}", [ 'starting_amount' => 750, ]); $response->assertOk(); $response->assertJsonPath('bucket.starting_amount', 750); $response->assertJsonPath('bucket.current_balance', 750); } public function test_can_update_name_only(): void { $bucket = Bucket::factory()->need()->fixedLimit(1000)->create([ 'scenario_id' => $this->scenario->id, 'name' => 'Old Name', 'priority' => 1, ]); $response = $this->patchJson("/buckets/{$bucket->uuid}", [ 'name' => 'New Name', ]); $response->assertOk(); $this->assertDatabaseHas('buckets', [ 'id' => $bucket->id, 'name' => 'New Name', ]); } public function test_partial_update_does_not_null_other_fields(): void { $bucket = Bucket::factory()->need()->fixedLimit(1000)->create([ 'scenario_id' => $this->scenario->id, 'starting_amount' => 500, 'buffer_multiplier' => 1.5, 'priority' => 1, ]); $response = $this->patchJson("/buckets/{$bucket->uuid}", [ 'starting_amount' => 750, ]); $response->assertOk(); $bucket->refresh(); $this->assertEquals(750, $bucket->starting_amount); $this->assertEquals(1000, (float) $bucket->allocation_value); $this->assertEquals(1.5, (float) $bucket->buffer_multiplier); } }