Add form request validation tests for various client and admin requests
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Admin;
|
||||
|
||||
use App\Enums\DocumentPriorityEnum;
|
||||
use App\Enums\DocumentStatusEnum;
|
||||
use App\Http\Requests\Admin\DocumentRequest;
|
||||
use App\Models\Pet;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class DocumentRequestTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase, ValidatesFormRequests;
|
||||
|
||||
public function test_passes_with_existing_pet_only(): void
|
||||
{
|
||||
$this->assertPasses(DocumentRequest::class, ['pet_id' => Pet::factory()->create()->id]);
|
||||
}
|
||||
|
||||
public function test_passes_with_all_optional_fields(): void
|
||||
{
|
||||
$this->assertPasses(DocumentRequest::class, [
|
||||
'pet_id' => Pet::factory()->create()->id,
|
||||
'modality' => 'mri',
|
||||
'status' => DocumentStatusEnum::Registered->name,
|
||||
'priority' => DocumentPriorityEnum::High->name,
|
||||
'note' => 'n',
|
||||
'submitted_at' => '2026-09-21',
|
||||
'scan_date' => '2026-09-21 10:00:00',
|
||||
'processing_deadline' => '2026-09-22',
|
||||
'primary_files' => [],
|
||||
'history_files' => [],
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_fails_without_pet_or_with_unknown_pet(): void
|
||||
{
|
||||
$this->assertFailsOn('pet_id', DocumentRequest::class, []);
|
||||
$this->assertFailsOn('pet_id', DocumentRequest::class, ['pet_id' => 999]);
|
||||
}
|
||||
|
||||
public function test_fails_when_status_or_priority_is_a_value_instead_of_key(): void
|
||||
{
|
||||
$petId = Pet::factory()->create()->id;
|
||||
|
||||
$this->assertFailsOn('status', DocumentRequest::class, ['pet_id' => $petId, 'status' => DocumentStatusEnum::Registered->value]);
|
||||
$this->assertFailsOn('priority', DocumentRequest::class, ['pet_id' => $petId, 'priority' => DocumentPriorityEnum::High->value]);
|
||||
}
|
||||
|
||||
public function test_fails_with_invalid_dates_or_non_array_files(): void
|
||||
{
|
||||
$petId = Pet::factory()->create()->id;
|
||||
|
||||
$this->assertFailsOn('submitted_at', DocumentRequest::class, ['pet_id' => $petId, 'submitted_at' => 'x']);
|
||||
$this->assertFailsOn('primary_files', DocumentRequest::class, ['pet_id' => $petId, 'primary_files' => 'x']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Admin;
|
||||
|
||||
use App\Enums\PetGenderEnum;
|
||||
use App\Enums\PetTypeEnum;
|
||||
use App\Http\Requests\Admin\PetRequest;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class PetRequestTest extends TestCase
|
||||
{
|
||||
use ValidatesFormRequests;
|
||||
|
||||
protected function valid(array $overrides = []): array
|
||||
{
|
||||
return array_merge([
|
||||
'name' => 'Rex',
|
||||
'type' => PetTypeEnum::Dog->value,
|
||||
'gender' => PetGenderEnum::Male->value,
|
||||
'breed' => 'ژرمن',
|
||||
'weight' => '20',
|
||||
'sterilized' => true,
|
||||
'birthday' => '2020-01-01',
|
||||
], $overrides);
|
||||
}
|
||||
|
||||
public function test_passes_with_valid_payload(): void
|
||||
{
|
||||
$this->assertPasses(PetRequest::class, $this->valid());
|
||||
}
|
||||
|
||||
public function test_converts_persian_digits_in_weight(): void
|
||||
{
|
||||
$this->assertPasses(PetRequest::class, $this->valid(['weight' => '۲۰']));
|
||||
}
|
||||
|
||||
public function test_fails_without_required_fields(): void
|
||||
{
|
||||
$errors = $this->formRequestErrors(PetRequest::class, ['weight' => '1']);
|
||||
|
||||
foreach (['name', 'type', 'gender', 'breed', 'sterilized', 'birthday'] as $field) {
|
||||
$this->assertArrayHasKey($field, $errors);
|
||||
}
|
||||
}
|
||||
|
||||
public function test_fails_without_weight(): void
|
||||
{
|
||||
$this->assertFailsOn('weight', PetRequest::class, $this->valid(['weight' => null]));
|
||||
}
|
||||
|
||||
public function test_fails_when_type_or_gender_is_a_key_instead_of_value(): void
|
||||
{
|
||||
$this->assertFailsOn('type', PetRequest::class, $this->valid(['type' => PetTypeEnum::Dog->name]));
|
||||
$this->assertFailsOn('gender', PetRequest::class, $this->valid(['gender' => PetGenderEnum::Male->name]));
|
||||
}
|
||||
|
||||
public function test_fails_with_non_integer_weight_or_invalid_birthday(): void
|
||||
{
|
||||
$this->assertFailsOn('weight', PetRequest::class, $this->valid(['weight' => 'heavy']));
|
||||
$this->assertFailsOn('birthday', PetRequest::class, $this->valid(['birthday' => 'x']));
|
||||
}
|
||||
|
||||
public function test_fails_with_non_boolean_sterilized(): void
|
||||
{
|
||||
$this->assertFailsOn('sterilized', PetRequest::class, $this->valid(['sterilized' => 'yes']));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Admin;
|
||||
|
||||
use App\Enums\ReportStatusEnum;
|
||||
use App\Http\Requests\Admin\ReportRequest;
|
||||
use App\Models\Document;
|
||||
use App\Models\Medium;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ReportRequestTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase, ValidatesFormRequests;
|
||||
|
||||
protected function valid(array $overrides = []): array
|
||||
{
|
||||
return array_merge([
|
||||
'document_id' => Document::factory()->create()->id,
|
||||
'doctor_id' => User::factory()->create()->id,
|
||||
'status' => ReportStatusEnum::Approved->name,
|
||||
'body' => 'متن گزارش',
|
||||
'submitted_at' => '2026-09-21 10:00:00',
|
||||
], $overrides);
|
||||
}
|
||||
|
||||
public function test_passes_with_valid_payload(): void
|
||||
{
|
||||
$this->assertPasses(ReportRequest::class, $this->valid());
|
||||
}
|
||||
|
||||
public function test_passes_with_existing_medium(): void
|
||||
{
|
||||
$this->assertPasses(ReportRequest::class, $this->valid(['medium_id' => Medium::factory()->create()->id]));
|
||||
}
|
||||
|
||||
public function test_fails_without_required_fields(): void
|
||||
{
|
||||
$errors = $this->formRequestErrors(ReportRequest::class, []);
|
||||
|
||||
foreach (['document_id', 'doctor_id', 'status', 'body', 'submitted_at'] as $field) {
|
||||
$this->assertArrayHasKey($field, $errors);
|
||||
}
|
||||
}
|
||||
|
||||
public function test_fails_with_unknown_document_doctor_or_medium(): void
|
||||
{
|
||||
$this->assertFailsOn('document_id', ReportRequest::class, $this->valid(['document_id' => 999]));
|
||||
$this->assertFailsOn('doctor_id', ReportRequest::class, $this->valid(['doctor_id' => 999]));
|
||||
$this->assertFailsOn('medium_id', ReportRequest::class, $this->valid(['medium_id' => 999]));
|
||||
}
|
||||
|
||||
public function test_fails_when_status_is_a_value_instead_of_key(): void
|
||||
{
|
||||
$this->assertFailsOn('status', ReportRequest::class, $this->valid(['status' => ReportStatusEnum::Approved->value]));
|
||||
}
|
||||
|
||||
public function test_fails_with_invalid_submitted_at(): void
|
||||
{
|
||||
$this->assertFailsOn('submitted_at', ReportRequest::class, $this->valid(['submitted_at' => 'x']));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Admin;
|
||||
|
||||
use App\Http\Requests\Admin\SettingProfileRequest;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class SettingProfileRequestTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase, ValidatesFormRequests;
|
||||
|
||||
public function test_passes_with_name_for_edited_user(): void
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->assertPasses(SettingProfileRequest::class, ['name' => 'new-name'], [], null, ['user' => $user]);
|
||||
}
|
||||
|
||||
public function test_fails_without_name(): void
|
||||
{
|
||||
$this->assertFailsOn('name', SettingProfileRequest::class, [], [], null, ['user' => User::factory()->create()]);
|
||||
}
|
||||
|
||||
public function test_fails_when_fields_exceed_limit(): void
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->assertFailsOn('name', SettingProfileRequest::class, ['name' => str_repeat('a', 256)], [], null, ['user' => $user]);
|
||||
$this->assertFailsOn('first_name', SettingProfileRequest::class, ['name' => 'n', 'first_name' => str_repeat('a', 256)], [], null, ['user' => $user]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Admin;
|
||||
|
||||
use App\Enums\ShiftDayEnum;
|
||||
use App\Enums\UserEnum;
|
||||
use App\Http\Requests\Admin\ShiftRequest;
|
||||
use App\Models\Shift;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ShiftRequestTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase, ValidatesFormRequests;
|
||||
|
||||
protected function valid(array $overrides = []): array
|
||||
{
|
||||
return array_merge([
|
||||
'day_of_week' => ShiftDayEnum::Monday->value,
|
||||
'start_time' => '08:00',
|
||||
'end_time' => '16:00',
|
||||
'is_active' => true,
|
||||
], $overrides);
|
||||
}
|
||||
|
||||
public function test_passes_with_weekly_shift(): void
|
||||
{
|
||||
$this->assertPasses(ShiftRequest::class, $this->valid());
|
||||
}
|
||||
|
||||
public function test_passes_with_dated_shift_and_doctor(): void
|
||||
{
|
||||
$doctor = User::factory()->create(['level' => UserEnum::Doctor->value]);
|
||||
|
||||
$this->assertPasses(ShiftRequest::class, $this->valid(['day_of_week' => null, 'date' => '2026-09-21', 'user_id' => $doctor->id]));
|
||||
}
|
||||
|
||||
public function test_passes_with_overnight_shift(): void
|
||||
{
|
||||
$this->assertPasses(ShiftRequest::class, $this->valid(['start_time' => '22:00', 'end_time' => '02:00']));
|
||||
}
|
||||
|
||||
public function test_fails_without_day_of_week_or_date(): void
|
||||
{
|
||||
$errors = $this->formRequestErrors(ShiftRequest::class, $this->valid(['day_of_week' => null]));
|
||||
|
||||
$this->assertArrayHasKey('day_of_week', $errors);
|
||||
$this->assertArrayHasKey('date', $errors);
|
||||
}
|
||||
|
||||
public function test_fails_without_times_or_is_active(): void
|
||||
{
|
||||
$errors = $this->formRequestErrors(ShiftRequest::class, ['day_of_week' => ShiftDayEnum::Monday->value]);
|
||||
|
||||
$this->assertArrayHasKey('start_time', $errors);
|
||||
$this->assertArrayHasKey('end_time', $errors);
|
||||
$this->assertArrayHasKey('is_active', $errors);
|
||||
}
|
||||
|
||||
public function test_fails_with_invalid_day_time_format_or_equal_times(): void
|
||||
{
|
||||
$this->assertFailsOn('day_of_week', ShiftRequest::class, $this->valid(['day_of_week' => 'Monday']));
|
||||
$this->assertFailsOn('start_time', ShiftRequest::class, $this->valid(['start_time' => '8am']));
|
||||
$this->assertFailsOn('end_time', ShiftRequest::class, $this->valid(['end_time' => '08:00']));
|
||||
}
|
||||
|
||||
public function test_fails_when_user_is_not_a_doctor(): void
|
||||
{
|
||||
$vet = User::factory()->create(['level' => UserEnum::Vet->value]);
|
||||
|
||||
$this->assertFailsOn('user_id', ShiftRequest::class, $this->valid(['user_id' => $vet->id]));
|
||||
}
|
||||
|
||||
public function test_fails_when_shift_conflicts_with_doctors_existing_shift(): void
|
||||
{
|
||||
$doctor = User::factory()->create(['level' => UserEnum::Doctor->value]);
|
||||
Shift::factory()->weekly(ShiftDayEnum::Monday)->between('08:00', '12:00')->forDoctor($doctor)->create();
|
||||
|
||||
$this->assertFailsOn('start_time', ShiftRequest::class, $this->valid(['user_id' => $doctor->id, 'start_time' => '10:00', 'end_time' => '14:00']));
|
||||
}
|
||||
|
||||
public function test_conflict_check_ignores_shift_being_edited(): void
|
||||
{
|
||||
$doctor = User::factory()->create(['level' => UserEnum::Doctor->value]);
|
||||
$shift = Shift::factory()->weekly(ShiftDayEnum::Monday)->between('08:00', '12:00')->forDoctor($doctor)->create();
|
||||
|
||||
$this->assertPasses(ShiftRequest::class, $this->valid(['user_id' => $doctor->id, 'start_time' => '09:00', 'end_time' => '13:00']), [], null, ['shift' => $shift]);
|
||||
}
|
||||
|
||||
public function test_date_takes_precedence_and_clears_day_of_week(): void
|
||||
{
|
||||
$this->assertPasses(ShiftRequest::class, $this->valid(['day_of_week' => 'invalid-day', 'date' => '2026-09-21']));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Admin;
|
||||
|
||||
use App\Enums\UserEnum;
|
||||
use App\Http\Requests\Admin\UserRequest;
|
||||
use App\Models\Medium;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Spatie\Permission\Models\Role;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UserRequestTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase, ValidatesFormRequests;
|
||||
|
||||
protected function valid(array $overrides = []): array
|
||||
{
|
||||
return array_merge([
|
||||
'phone' => '09120000000',
|
||||
'password' => 'secret123',
|
||||
'password_confirmation' => 'secret123',
|
||||
'level' => UserEnum::Doctor->value,
|
||||
], $overrides);
|
||||
}
|
||||
|
||||
public function test_passes_with_required_fields_on_create(): void
|
||||
{
|
||||
$this->assertPasses(UserRequest::class, $this->valid());
|
||||
}
|
||||
|
||||
public function test_passes_with_optional_fields_and_roles(): void
|
||||
{
|
||||
$role = Role::create(['name' => 'editor']);
|
||||
|
||||
$this->assertPasses(UserRequest::class, $this->valid([
|
||||
'username' => 'ali',
|
||||
'fullname' => 'علی',
|
||||
'email' => 'ali@example.com',
|
||||
'role' => [$role->id],
|
||||
]));
|
||||
}
|
||||
|
||||
public function test_fails_without_phone_password_or_level(): void
|
||||
{
|
||||
$errors = $this->formRequestErrors(UserRequest::class, []);
|
||||
|
||||
$this->assertArrayHasKey('phone', $errors);
|
||||
$this->assertArrayHasKey('password', $errors);
|
||||
$this->assertArrayHasKey('level', $errors);
|
||||
}
|
||||
|
||||
public function test_fails_with_short_or_unconfirmed_password(): void
|
||||
{
|
||||
$this->assertFailsOn('password', UserRequest::class, $this->valid(['password' => 'short', 'password_confirmation' => 'short']));
|
||||
$this->assertFailsOn('password', UserRequest::class, $this->valid(['password_confirmation' => 'different']));
|
||||
}
|
||||
|
||||
public function test_fails_with_level_outside_admin_list(): void
|
||||
{
|
||||
$this->assertFailsOn('level', UserRequest::class, $this->valid(['level' => UserEnum::Vet->value]));
|
||||
}
|
||||
|
||||
public function test_fails_with_duplicate_username_or_email(): void
|
||||
{
|
||||
User::factory()->create(['username' => 'taken', 'email' => 'taken@example.com']);
|
||||
|
||||
$this->assertFailsOn('username', UserRequest::class, $this->valid(['username' => 'taken']));
|
||||
$this->assertFailsOn('email', UserRequest::class, $this->valid(['email' => 'taken@example.com']));
|
||||
}
|
||||
|
||||
public function test_profile_url_must_match_existing_medium(): void
|
||||
{
|
||||
$medium = Medium::factory()->create(['url' => 'http://example.test/a.png']);
|
||||
|
||||
$this->assertPasses(UserRequest::class, $this->valid(['profile_url' => $medium->url]));
|
||||
$this->assertFailsOn('profile_url', UserRequest::class, $this->valid(['profile_url' => 'http://example.test/missing.png']));
|
||||
}
|
||||
|
||||
public function test_fails_with_invalid_phone_or_unknown_role(): void
|
||||
{
|
||||
$this->assertFailsOn('phone', UserRequest::class, $this->valid(['phone' => 'abc']));
|
||||
$this->assertFailsOn('role', UserRequest::class, $this->valid(['role' => [999]]));
|
||||
}
|
||||
|
||||
public function test_update_allows_own_username_and_email_and_optional_password(): void
|
||||
{
|
||||
$user = User::factory()->create(['username' => 'me', 'email' => 'me@example.com']);
|
||||
|
||||
$this->assertPasses(UserRequest::class, [
|
||||
'username' => 'me',
|
||||
'email' => 'me@example.com',
|
||||
'phone' => '09120000000',
|
||||
'level' => UserEnum::Doctor->value,
|
||||
], [], null, ['user' => $user]);
|
||||
}
|
||||
|
||||
public function test_update_still_rejects_another_users_username(): void
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
User::factory()->create(['username' => 'other']);
|
||||
|
||||
$this->assertFailsOn('username', UserRequest::class, $this->valid(['username' => 'other']), [], null, ['user' => $user]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Admin;
|
||||
|
||||
use App\Http\Requests\Admin\WithdrawRejectRequest;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class WithdrawRejectRequestTest extends TestCase
|
||||
{
|
||||
use ValidatesFormRequests;
|
||||
|
||||
public function test_passes_without_note(): void
|
||||
{
|
||||
$this->assertPasses(WithdrawRejectRequest::class, []);
|
||||
$this->assertPasses(WithdrawRejectRequest::class, ['note' => null]);
|
||||
}
|
||||
|
||||
public function test_passes_with_note(): void
|
||||
{
|
||||
$this->assertPasses(WithdrawRejectRequest::class, ['note' => 'اطلاعات کارت ناقص است']);
|
||||
}
|
||||
|
||||
public function test_fails_when_note_exceeds_limit(): void
|
||||
{
|
||||
$this->assertFailsOn('note', WithdrawRejectRequest::class, ['note' => str_repeat('a', 1001)]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user