From ac3e6d2ff90874108240e0831684c89d69b176bd Mon Sep 17 00:00:00 2001 From: myrmidex Date: Sun, 22 Mar 2026 00:56:20 +0100 Subject: [PATCH] 17 - Add scenario PATCH route with distribution_mode validation --- app/Http/Controllers/ScenarioController.php | 7 +- app/Http/Requests/UpdateScenarioRequest.php | 10 +-- routes/web.php | 2 +- tests/Feature/ScenarioUpdateTest.php | 74 +++++++++++++++++++++ 4 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 tests/Feature/ScenarioUpdateTest.php diff --git a/app/Http/Controllers/ScenarioController.php b/app/Http/Controllers/ScenarioController.php index 6359db1..0ee5f2e 100644 --- a/app/Http/Controllers/ScenarioController.php +++ b/app/Http/Controllers/ScenarioController.php @@ -14,6 +14,7 @@ use App\Repositories\ScenarioRepository; use App\Repositories\StreamRepository; use App\Services\Streams\StatsService; +use Illuminate\Http\JsonResponse; use Illuminate\Http\RedirectResponse; use Inertia\Inertia; use Inertia\Response; @@ -69,13 +70,11 @@ public function edit(Scenario $scenario): Response ]); } - public function update(UpdateScenarioRequest $request, Scenario $scenario): RedirectResponse + public function update(UpdateScenarioRequest $request, Scenario $scenario): JsonResponse { $this->updateScenarioAction->execute($scenario, $request->validated()); - return redirect() - ->route('scenarios.show', $scenario) - ->with('success', 'Scenario updated successfully'); + return response()->json(['success' => true]); } public function destroy(Scenario $scenario): RedirectResponse diff --git a/app/Http/Requests/UpdateScenarioRequest.php b/app/Http/Requests/UpdateScenarioRequest.php index 81e3108..3e03684 100644 --- a/app/Http/Requests/UpdateScenarioRequest.php +++ b/app/Http/Requests/UpdateScenarioRequest.php @@ -2,29 +2,29 @@ namespace App\Http\Requests; +use App\Enums\DistributionModeEnum; use Illuminate\Foundation\Http\FormRequest; +use Illuminate\Validation\Rule; class UpdateScenarioRequest extends FormRequest { public function authorize(): bool { - // In production, check if user owns the scenario - // For now, allow all requests return true; } public function rules(): array { return [ - 'name' => ['required', 'string', 'max:255', 'min:1'], - 'description' => ['nullable', 'string', 'max:1000'], + 'name' => ['sometimes', 'string', 'max:255', 'min:1'], + 'description' => ['sometimes', 'nullable', 'string', 'max:1000'], + 'distribution_mode' => ['sometimes', 'string', Rule::in(DistributionModeEnum::values())], ]; } public function messages(): array { return [ - 'name.required' => 'A scenario name is required.', 'name.min' => 'The scenario name must be at least 1 character.', 'name.max' => 'The scenario name cannot exceed 255 characters.', 'description.max' => 'The description cannot exceed 1000 characters.', diff --git a/routes/web.php b/routes/web.php index 32ba796..4e98b5c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -19,7 +19,7 @@ // Route::get('/scenarios/create', [ScenarioController::class, 'create'])->name('scenarios.create'); // Route::post('/scenarios', [ScenarioController::class, 'store'])->name('scenarios.store'); // Route::get('/scenarios/{scenario}/edit', [ScenarioController::class, 'edit'])->name('scenarios.edit'); -// Route::patch('/scenarios/{scenario}', [ScenarioController::class, 'update'])->name('scenarios.update'); +Route::patch('/scenarios/{scenario}', [ScenarioController::class, 'update'])->name('scenarios.update'); // Route::delete('/scenarios/{scenario}', [ScenarioController::class, 'destroy'])->name('scenarios.destroy'); // Bucket routes (no auth required for MVP) diff --git a/tests/Feature/ScenarioUpdateTest.php b/tests/Feature/ScenarioUpdateTest.php new file mode 100644 index 0000000..b071154 --- /dev/null +++ b/tests/Feature/ScenarioUpdateTest.php @@ -0,0 +1,74 @@ +scenario = Scenario::factory()->create(); + } + + public function test_can_update_distribution_mode(): void + { + $response = $this->patchJson("/scenarios/{$this->scenario->uuid}", [ + 'distribution_mode' => 'priority', + ]); + + $response->assertOk(); + $this->assertDatabaseHas('scenarios', [ + 'id' => $this->scenario->id, + 'distribution_mode' => DistributionModeEnum::PRIORITY->value, + ]); + } + + public function test_rejects_invalid_distribution_mode(): void + { + $response = $this->patchJson("/scenarios/{$this->scenario->uuid}", [ + 'distribution_mode' => 'invalid', + ]); + + $response->assertUnprocessable(); + $response->assertJsonValidationErrors(['distribution_mode']); + } + + public function test_can_update_distribution_mode_without_name(): void + { + $originalName = $this->scenario->name; + + $response = $this->patchJson("/scenarios/{$this->scenario->uuid}", [ + 'distribution_mode' => 'priority', + ]); + + $response->assertOk(); + $this->assertDatabaseHas('scenarios', [ + 'id' => $this->scenario->id, + 'name' => $originalName, + 'distribution_mode' => DistributionModeEnum::PRIORITY->value, + ]); + } + + public function test_can_update_name_without_distribution_mode(): void + { + $response = $this->patchJson("/scenarios/{$this->scenario->uuid}", [ + 'name' => 'Updated Name', + ]); + + $response->assertOk(); + $this->assertDatabaseHas('scenarios', [ + 'id' => $this->scenario->id, + 'name' => 'Updated Name', + 'distribution_mode' => $this->scenario->distribution_mode->value, + ]); + } +}