Now that we have an edit form, let's test that the validation works correctly.
Again, first, the working code.
php artisan make:request UpdateProductRequest
app/Http/Requests/UpdateProductRequest.php:
use Illuminate\Foundation\Http\FormRequest; class UpdateProductRequest extends FormRequest{ public function authorize(): bool { return true; } public function rules(): array { return [ 'name' => 'required', 'price' => 'required', ]; }}
app/Http/Controllers/ProductController.php:
use Illuminate\Http\RedirectResponse;use App\Http\Requests\UpdateProductRequest; class ProductController extends Controller{ // ... public function update(UpdateProductRequest $request, Product $product): RedirectResponse { $product->update($request->validated()); return redirect()->route('products.index'); }}
The PUT request is used for updating, so in the test, again acting as an admin, we send a PUT request with empty values.
tests/Feature/ProductsTest.php:
// ... test('product update validation error redirects back to form', function () { $product = Product::factory()->create(); asAdmin()->put('products/' . $product->id, [ 'name' => '', 'price' => '' ]);});
And now, we need to assert. We can first assert that the response is a redirect. And then Laravel has an assertion just for validating errors: assertInvalid
.
tests/Feature/ProductsTest.php:
// ... test('product update validation error redirects back to form', function () { $product = Product::factory()->create(); asAdmin()->put('products/' . $product->id, [ 'name' => '', 'price' => '' ]) ->assertStatus(302) ->assertInvalid(['name', 'price']); });
Another validation assertion that we can use is assertSessionHasErrors
. In the same way as in assertInvalid()
, we need to provide keys.
tests/Feature/ProductsTest.php:
// ... test('product update validation error redirects back to form', function () { $product = Product::factory()->create(); asAdmin()->put('products/' . $product->id, [ 'name' => '', 'price' => '' ]) ->assertStatus(302) ->assertInvalid(['name', 'price']) ->assertSessionHasErrors(['name', 'price']); });
Here, we have the same test for PHPUnit.
tests/Feature/ProductsTest.php:
class ProductsTest extends TestCase{ // ... public function test_product_update_validation_error_redirects_back_to_form() { $product = Product::factory()->create(); $response = $this->actingAs($this->admin)->put('products/' . $product->id, [ 'name' => '', 'price' => '' ]); $response->assertStatus(302); $response->assertInvalid(['name', 'price']); $response->assertSessionHasErrors(['name', 'price']); } private function createUser(bool $isAdmin = false): User { return User::factory()->create([ 'is_admin' => $isAdmin, ]); }}