Add form request validation tests for various client and admin requests
This commit is contained in:
@@ -38,8 +38,10 @@ class PetRequest extends FormRequest
|
||||
|
||||
public function prepareForValidation()
|
||||
{
|
||||
if ($this->filled('weight')) {
|
||||
$this->merge([
|
||||
'weight' => PersianToEnglish::toEnglish($this->weight),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class UserRequest extends FormRequest
|
||||
'phone' => ['required', 'max:255', new PhoneNumber],
|
||||
'fullname' => 'nullable | max:255',
|
||||
'role' => ['nullable', 'array', 'exists:roles,id'],
|
||||
'profile_url' => ['nullable', 'exists:medium,url'],
|
||||
'profile_url' => ['nullable', 'exists:media,url'],
|
||||
'email' => ['nullable', 'email', 'max:255',
|
||||
isset($toBeEditedUser)
|
||||
? Rule::unique('users')->ignore($toBeEditedUser->id)
|
||||
|
||||
+20
-19
@@ -65,8 +65,9 @@ app/Models/Shift.php → tests/Feature/Models/ShiftTes
|
||||
**Service** — happy path; every guard / exception branch; every side effect (DB rows, dispatched
|
||||
jobs, transactions written); for money code, balance invariants before and after.
|
||||
|
||||
**Form Request** — `authorize()` when it is not `return true`; each rule with an invalid input →
|
||||
`assertSessionHasErrors('field')` / 422; one fully valid payload passes.
|
||||
**Form Request** — use the `Tests\Concerns\ValidatesFormRequests` trait (`assertPasses`, `assertFailsOn`,
|
||||
`formRequestErrors`); it runs `prepareForValidation`, `rules`, `withValidator` and route/user resolvers without HTTP.
|
||||
Cover `authorize()` when it is not `return true`; each rule with an invalid input; one fully valid payload.
|
||||
|
||||
**HTTP** — guest is redirected to login; wrong role or non-owner gets 403/404; happy path returns
|
||||
the expected status and persisted state; Inertia page tests assert the component name and key props.
|
||||
@@ -120,23 +121,23 @@ Legend: `☐` not written · `☑` written · `—` intentionally not tested
|
||||
|
||||
| Priority | Source | Test | Status |
|
||||
|----------|--------|------|--------|
|
||||
| P1 | `app/Http/Requests/Client/Auth/UserRegistrationRequest.php` | `tests/Feature/Requests/Client/Auth/UserRegistrationRequestTest.php` | ☐ |
|
||||
| P1 | `app/Http/Requests/Client/Auth/VerifyOtpRequest.php` | `tests/Feature/Requests/Client/Auth/VerifyOtpRequestTest.php` | ☐ |
|
||||
| P1 | `app/Http/Requests/Client/PaymentRequest.php` | `tests/Feature/Requests/Client/PaymentRequestTest.php` | ☐ |
|
||||
| P1 | `app/Http/Requests/Client/WalletDepositRequest.php` | `tests/Feature/Requests/Client/WalletDepositRequestTest.php` | ☐ |
|
||||
| P1 | `app/Http/Requests/Client/WithdrawRequestStoreRequest.php` | `tests/Feature/Requests/Client/WithdrawRequestStoreRequestTest.php` | ☐ |
|
||||
| P1 | `app/Http/Requests/Client/BankCardStoreRequest.php` | `tests/Feature/Requests/Client/BankCardStoreRequestTest.php` | ☐ |
|
||||
| P1 | `app/Http/Requests/Client/FastRequestRequest.php` | `tests/Feature/Requests/Client/FastRequestRequestTest.php` | ☐ |
|
||||
| P2 | `app/Http/Requests/Client/CaseRejectRequest.php` | `tests/Feature/Requests/Client/CaseRejectRequestTest.php` | ☐ |
|
||||
| P2 | `app/Http/Requests/Client/ReportSubmitRequest.php` | `tests/Feature/Requests/Client/ReportSubmitRequestTest.php` | ☐ |
|
||||
| P2 | `app/Http/Requests/Client/ProfileUpdateRequest.php` | `tests/Feature/Requests/Client/ProfileUpdateRequestTest.php` | ☐ |
|
||||
| P2 | `app/Http/Requests/Admin/WithdrawRejectRequest.php` | `tests/Feature/Requests/Admin/WithdrawRejectRequestTest.php` | ☐ |
|
||||
| P2 | `app/Http/Requests/Admin/DocumentRequest.php` | `tests/Feature/Requests/Admin/DocumentRequestTest.php` | ☐ |
|
||||
| P2 | `app/Http/Requests/Admin/ShiftRequest.php` | `tests/Feature/Requests/Admin/ShiftRequestTest.php` | ☐ |
|
||||
| P2 | `app/Http/Requests/Admin/UserRequest.php` | `tests/Feature/Requests/Admin/UserRequestTest.php` | ☐ |
|
||||
| P2 | `app/Http/Requests/Admin/PetRequest.php` | `tests/Feature/Requests/Admin/PetRequestTest.php` | ☐ |
|
||||
| P2 | `app/Http/Requests/Admin/ReportRequest.php` | `tests/Feature/Requests/Admin/ReportRequestTest.php` | ☐ |
|
||||
| P2 | `app/Http/Requests/Admin/SettingProfileRequest.php` | `tests/Feature/Requests/Admin/SettingProfileRequestTest.php` | ☐ |
|
||||
| P1 | `app/Http/Requests/Client/Auth/UserRegistrationRequest.php` | `tests/Feature/Requests/Client/Auth/UserRegistrationRequestTest.php` | ☑ |
|
||||
| P1 | `app/Http/Requests/Client/Auth/VerifyOtpRequest.php` | `tests/Feature/Requests/Client/Auth/VerifyOtpRequestTest.php` | ☑ |
|
||||
| P1 | `app/Http/Requests/Client/PaymentRequest.php` | `tests/Feature/Requests/Client/PaymentRequestTest.php` | ☑ |
|
||||
| P1 | `app/Http/Requests/Client/WalletDepositRequest.php` | `tests/Feature/Requests/Client/WalletDepositRequestTest.php` | ☑ |
|
||||
| P1 | `app/Http/Requests/Client/WithdrawRequestStoreRequest.php` | `tests/Feature/Requests/Client/WithdrawRequestStoreRequestTest.php` | ☑ |
|
||||
| P1 | `app/Http/Requests/Client/BankCardStoreRequest.php` | `tests/Feature/Requests/Client/BankCardStoreRequestTest.php` | ☑ |
|
||||
| P1 | `app/Http/Requests/Client/FastRequestRequest.php` | `tests/Feature/Requests/Client/FastRequestRequestTest.php` | ☑ |
|
||||
| P2 | `app/Http/Requests/Client/CaseRejectRequest.php` | `tests/Feature/Requests/Client/CaseRejectRequestTest.php` | ☑ |
|
||||
| P2 | `app/Http/Requests/Client/ReportSubmitRequest.php` | `tests/Feature/Requests/Client/ReportSubmitRequestTest.php` | ☑ |
|
||||
| P2 | `app/Http/Requests/Client/ProfileUpdateRequest.php` | `tests/Feature/Requests/Client/ProfileUpdateRequestTest.php` | ☑ |
|
||||
| P2 | `app/Http/Requests/Admin/WithdrawRejectRequest.php` | `tests/Feature/Requests/Admin/WithdrawRejectRequestTest.php` | ☑ |
|
||||
| P2 | `app/Http/Requests/Admin/DocumentRequest.php` | `tests/Feature/Requests/Admin/DocumentRequestTest.php` | ☑ |
|
||||
| P2 | `app/Http/Requests/Admin/ShiftRequest.php` | `tests/Feature/Requests/Admin/ShiftRequestTest.php` | ☑ |
|
||||
| P2 | `app/Http/Requests/Admin/UserRequest.php` | `tests/Feature/Requests/Admin/UserRequestTest.php` | ☑ |
|
||||
| P2 | `app/Http/Requests/Admin/PetRequest.php` | `tests/Feature/Requests/Admin/PetRequestTest.php` | ☑ |
|
||||
| P2 | `app/Http/Requests/Admin/ReportRequest.php` | `tests/Feature/Requests/Admin/ReportRequestTest.php` | ☑ |
|
||||
| P2 | `app/Http/Requests/Admin/SettingProfileRequest.php` | `tests/Feature/Requests/Admin/SettingProfileRequestTest.php` | ☑ (known bug: validates `users.name`, `first_name`, `last_name` which do not exist; passes on sqlite only because of literal quoting) |
|
||||
|
||||
### HTTP
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Concerns;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Routing\Route;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
trait ValidatesFormRequests
|
||||
{
|
||||
protected function formRequestErrors(string $requestClass, array $data, array $files = [], ?User $user = null, array $routeParameters = []): array
|
||||
{
|
||||
$request = $requestClass::create('/', 'POST', $data, [], $files);
|
||||
$request->setContainer(app())->setRedirector(app(Redirector::class));
|
||||
$request->setUserResolver(fn () => $user);
|
||||
|
||||
$route = new Route('POST', '/', []);
|
||||
$route->parameters = $routeParameters;
|
||||
$request->setRouteResolver(fn () => $route);
|
||||
|
||||
try {
|
||||
$request->validateResolved();
|
||||
} catch (ValidationException $e) {
|
||||
return $e->errors();
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function assertPasses(string $requestClass, array $data, array $files = [], ?User $user = null, array $routeParameters = []): void
|
||||
{
|
||||
$this->assertSame([], $this->formRequestErrors($requestClass, $data, $files, $user, $routeParameters));
|
||||
}
|
||||
|
||||
protected function assertFailsOn(string $field, string $requestClass, array $data, array $files = [], ?User $user = null, array $routeParameters = []): void
|
||||
{
|
||||
$this->assertArrayHasKey($field, $this->formRequestErrors($requestClass, $data, $files, $user, $routeParameters));
|
||||
}
|
||||
}
|
||||
@@ -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)]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Client\Auth;
|
||||
|
||||
use App\Http\Requests\Client\Auth\UserRegistrationRequest;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UserRegistrationRequestTest extends TestCase
|
||||
{
|
||||
use ValidatesFormRequests;
|
||||
|
||||
protected function valid(array $overrides = []): array
|
||||
{
|
||||
return array_merge(['phone' => '09120000000', 'national_code' => '0012345678'], $overrides);
|
||||
}
|
||||
|
||||
public function test_passes_with_phone_and_national_code(): void
|
||||
{
|
||||
$this->assertPasses(UserRegistrationRequest::class, $this->valid());
|
||||
}
|
||||
|
||||
public function test_passes_with_all_optional_fields(): void
|
||||
{
|
||||
$this->assertPasses(UserRegistrationRequest::class, $this->valid([
|
||||
'fullname' => 'f', 'specialty' => 's', 'clinic_name' => 'c', 'clinic_phone' => '021', 'province' => 'p', 'city' => 'c', 'address' => 'a', 'level' => 'دانپزشک',
|
||||
]));
|
||||
}
|
||||
|
||||
public function test_accepts_international_and_persian_digit_phones(): void
|
||||
{
|
||||
$this->assertPasses(UserRegistrationRequest::class, $this->valid(['phone' => '+989120000000']));
|
||||
$this->assertPasses(UserRegistrationRequest::class, $this->valid(['phone' => '۰۹۱۲۰۰۰۰۰۰۰']));
|
||||
}
|
||||
|
||||
public function test_fails_without_phone_or_national_code(): void
|
||||
{
|
||||
$errors = $this->formRequestErrors(UserRegistrationRequest::class, []);
|
||||
|
||||
$this->assertArrayHasKey('phone', $errors);
|
||||
$this->assertArrayHasKey('national_code', $errors);
|
||||
}
|
||||
|
||||
public function test_fails_with_invalid_phone(): void
|
||||
{
|
||||
$this->assertFailsOn('phone', UserRegistrationRequest::class, $this->valid(['phone' => 'abc']));
|
||||
$this->assertFailsOn('phone', UserRegistrationRequest::class, $this->valid(['phone' => '123']));
|
||||
$this->assertFailsOn('phone', UserRegistrationRequest::class, $this->valid(['phone' => '+9999120000000']));
|
||||
}
|
||||
|
||||
public function test_fails_when_level_exceeds_limit(): void
|
||||
{
|
||||
$this->assertFailsOn('level', UserRegistrationRequest::class, $this->valid(['level' => str_repeat('a', 51)]));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Client\Auth;
|
||||
|
||||
use App\Http\Requests\Client\Auth\VerifyOtpRequest;
|
||||
use App\Models\OtpCode;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class VerifyOtpRequestTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase, ValidatesFormRequests;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
session(['login_phone' => '09120000000']);
|
||||
}
|
||||
|
||||
public function test_passes_with_valid_code_for_session_phone(): void
|
||||
{
|
||||
OtpCode::factory()->create(['phone' => '09120000000', 'code' => '1234']);
|
||||
|
||||
$this->assertPasses(VerifyOtpRequest::class, ['otp_code' => '1234']);
|
||||
}
|
||||
|
||||
public function test_fails_without_code(): void
|
||||
{
|
||||
$this->assertFailsOn('otp_code', VerifyOtpRequest::class, []);
|
||||
}
|
||||
|
||||
public function test_fails_when_code_is_not_four_digits(): void
|
||||
{
|
||||
OtpCode::factory()->create(['phone' => '09120000000', 'code' => '123']);
|
||||
|
||||
$this->assertFailsOn('otp_code', VerifyOtpRequest::class, ['otp_code' => '123']);
|
||||
$this->assertFailsOn('otp_code', VerifyOtpRequest::class, ['otp_code' => 'abcd']);
|
||||
}
|
||||
|
||||
public function test_fails_with_wrong_code(): void
|
||||
{
|
||||
OtpCode::factory()->create(['phone' => '09120000000', 'code' => '1234']);
|
||||
|
||||
$this->assertFailsOn('otp_code', VerifyOtpRequest::class, ['otp_code' => '0000']);
|
||||
}
|
||||
|
||||
public function test_fails_with_expired_code(): void
|
||||
{
|
||||
OtpCode::factory()->expired()->create(['phone' => '09120000000', 'code' => '1234']);
|
||||
|
||||
$this->assertFailsOn('otp_code', VerifyOtpRequest::class, ['otp_code' => '1234']);
|
||||
}
|
||||
|
||||
public function test_fails_when_code_belongs_to_another_phone(): void
|
||||
{
|
||||
OtpCode::factory()->create(['phone' => '09130000000', 'code' => '1234']);
|
||||
|
||||
$this->assertFailsOn('otp_code', VerifyOtpRequest::class, ['otp_code' => '1234']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Client;
|
||||
|
||||
use App\Http\Requests\Client\BankCardStoreRequest;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class BankCardStoreRequestTest extends TestCase
|
||||
{
|
||||
use ValidatesFormRequests;
|
||||
|
||||
public function test_passes_with_sixteen_digit_card_and_holder_name(): void
|
||||
{
|
||||
$this->assertPasses(BankCardStoreRequest::class, ['card_number' => '6037991234567890', 'holder_name' => 'علی رضایی']);
|
||||
}
|
||||
|
||||
public function test_fails_without_required_fields(): void
|
||||
{
|
||||
$errors = $this->formRequestErrors(BankCardStoreRequest::class, []);
|
||||
|
||||
$this->assertArrayHasKey('card_number', $errors);
|
||||
$this->assertArrayHasKey('holder_name', $errors);
|
||||
}
|
||||
|
||||
public function test_fails_when_card_number_is_not_sixteen_digits(): void
|
||||
{
|
||||
$this->assertFailsOn('card_number', BankCardStoreRequest::class, ['card_number' => '603799123456789', 'holder_name' => 'x']);
|
||||
$this->assertFailsOn('card_number', BankCardStoreRequest::class, ['card_number' => '60379912345678901', 'holder_name' => 'x']);
|
||||
$this->assertFailsOn('card_number', BankCardStoreRequest::class, ['card_number' => '6037-9912-3456-7890', 'holder_name' => 'x']);
|
||||
}
|
||||
|
||||
public function test_fails_when_holder_name_is_too_long(): void
|
||||
{
|
||||
$this->assertFailsOn('holder_name', BankCardStoreRequest::class, ['card_number' => '6037991234567890', 'holder_name' => str_repeat('a', 256)]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Client;
|
||||
|
||||
use App\Http\Requests\Client\CaseRejectRequest;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class CaseRejectRequestTest extends TestCase
|
||||
{
|
||||
use ValidatesFormRequests;
|
||||
|
||||
public function test_passes_with_reason(): void
|
||||
{
|
||||
$this->assertPasses(CaseRejectRequest::class, ['reason' => 'تصاویر ناخوانا هستند']);
|
||||
}
|
||||
|
||||
public function test_fails_without_reason(): void
|
||||
{
|
||||
$this->assertFailsOn('reason', CaseRejectRequest::class, []);
|
||||
$this->assertFailsOn('reason', CaseRejectRequest::class, ['reason' => '']);
|
||||
}
|
||||
|
||||
public function test_fails_when_reason_exceeds_limit(): void
|
||||
{
|
||||
$this->assertFailsOn('reason', CaseRejectRequest::class, ['reason' => str_repeat('a', 1001)]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Client;
|
||||
|
||||
use App\Enums\DocumentModalityEnum;
|
||||
use App\Enums\DocumentPriorityEnum;
|
||||
use App\Enums\PetGenderEnum;
|
||||
use App\Enums\PetTypeEnum;
|
||||
use App\Enums\UserEnum;
|
||||
use App\Http\Requests\Client\FastRequestRequest;
|
||||
use App\Models\Pet;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class FastRequestRequestTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase, ValidatesFormRequests;
|
||||
|
||||
protected User $user;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->user = User::factory()->create();
|
||||
}
|
||||
|
||||
protected function valid(array $overrides = []): array
|
||||
{
|
||||
return array_merge([
|
||||
'modality' => DocumentModalityEnum::Mri->value,
|
||||
'priority' => DocumentPriorityEnum::High->name,
|
||||
'pet' => ['name' => 'Rex', 'type' => PetTypeEnum::Dog->name],
|
||||
], $overrides);
|
||||
}
|
||||
|
||||
public function test_passes_with_new_pet(): void
|
||||
{
|
||||
$this->assertPasses(FastRequestRequest::class, $this->valid([
|
||||
'note' => 'n',
|
||||
'pet' => ['name' => 'Rex', 'type' => PetTypeEnum::Dog->name, 'gender' => PetGenderEnum::Male->name, 'breed' => 'b', 'age' => 3, 'weight' => 20, 'sterilized' => true],
|
||||
]), [], $this->user);
|
||||
}
|
||||
|
||||
public function test_passes_with_own_existing_pet_and_no_pet_payload(): void
|
||||
{
|
||||
$pet = Pet::factory()->create(['owner_id' => $this->user->id]);
|
||||
|
||||
$this->assertPasses(FastRequestRequest::class, ['modality' => DocumentModalityEnum::Mri->value, 'priority' => DocumentPriorityEnum::Medium->name, 'pet_id' => $pet->id], [], $this->user);
|
||||
}
|
||||
|
||||
public function test_passes_with_doctor_and_image_files(): void
|
||||
{
|
||||
$doctor = User::factory()->create(['level' => UserEnum::Doctor->value]);
|
||||
|
||||
$this->assertPasses(FastRequestRequest::class, $this->valid(['doctor_id' => $doctor->id]), [
|
||||
'history_files' => [UploadedFile::fake()->image('h.jpg')],
|
||||
'scan_files' => [UploadedFile::fake()->image('s.png')],
|
||||
], $this->user);
|
||||
}
|
||||
|
||||
public function test_fails_without_modality_priority_or_pet(): void
|
||||
{
|
||||
$errors = $this->formRequestErrors(FastRequestRequest::class, [], [], $this->user);
|
||||
|
||||
$this->assertArrayHasKey('modality', $errors);
|
||||
$this->assertArrayHasKey('priority', $errors);
|
||||
$this->assertArrayHasKey('pet', $errors);
|
||||
$this->assertArrayHasKey('pet.name', $errors);
|
||||
$this->assertArrayHasKey('pet.type', $errors);
|
||||
}
|
||||
|
||||
public function test_fails_with_invalid_modality_or_priority(): void
|
||||
{
|
||||
$this->assertFailsOn('modality', FastRequestRequest::class, $this->valid(['modality' => 'xray']), [], $this->user);
|
||||
$this->assertFailsOn('priority', FastRequestRequest::class, $this->valid(['priority' => DocumentPriorityEnum::High->value]), [], $this->user);
|
||||
}
|
||||
|
||||
public function test_fails_with_pet_of_another_user(): void
|
||||
{
|
||||
$pet = Pet::factory()->create();
|
||||
|
||||
$this->assertFailsOn('pet_id', FastRequestRequest::class, $this->valid(['pet_id' => $pet->id]), [], $this->user);
|
||||
}
|
||||
|
||||
public function test_fails_with_invalid_pet_type_gender_age_or_weight(): void
|
||||
{
|
||||
$this->assertFailsOn('pet.type', FastRequestRequest::class, $this->valid(['pet' => ['name' => 'x', 'type' => PetTypeEnum::Dog->value]]), [], $this->user);
|
||||
$this->assertFailsOn('pet.gender', FastRequestRequest::class, $this->valid(['pet' => ['name' => 'x', 'type' => 'Dog', 'gender' => 'Alien']]), [], $this->user);
|
||||
$this->assertFailsOn('pet.age', FastRequestRequest::class, $this->valid(['pet' => ['name' => 'x', 'type' => 'Dog', 'age' => 101]]), [], $this->user);
|
||||
$this->assertFailsOn('pet.weight', FastRequestRequest::class, $this->valid(['pet' => ['name' => 'x', 'type' => 'Dog', 'weight' => -1]]), [], $this->user);
|
||||
}
|
||||
|
||||
public function test_fails_with_non_doctor_as_doctor_id(): void
|
||||
{
|
||||
$vet = User::factory()->create(['level' => UserEnum::Vet->value]);
|
||||
|
||||
$this->assertFailsOn('doctor_id', FastRequestRequest::class, $this->valid(['doctor_id' => $vet->id]), [], $this->user);
|
||||
}
|
||||
|
||||
public function test_fails_with_non_image_or_oversized_files(): void
|
||||
{
|
||||
$this->assertFailsOn('history_files.0', FastRequestRequest::class, $this->valid(), ['history_files' => [UploadedFile::fake()->create('a.pdf', 10, 'application/pdf')]], $this->user);
|
||||
$this->assertFailsOn('scan_files.0', FastRequestRequest::class, $this->valid(), ['scan_files' => [UploadedFile::fake()->image('a.jpg')->size(10241)]], $this->user);
|
||||
}
|
||||
|
||||
public function test_fails_when_note_exceeds_limit(): void
|
||||
{
|
||||
$this->assertFailsOn('note', FastRequestRequest::class, $this->valid(['note' => str_repeat('a', 1001)]), [], $this->user);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Client;
|
||||
|
||||
use App\Http\Requests\Client\PaymentRequest;
|
||||
use App\Models\Invoice;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class PaymentRequestTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase, ValidatesFormRequests;
|
||||
|
||||
public function test_passes_with_existing_invoice_id(): void
|
||||
{
|
||||
$invoice = Invoice::factory()->create();
|
||||
|
||||
$this->assertPasses(PaymentRequest::class, ['invoice_id' => $invoice->id]);
|
||||
}
|
||||
|
||||
public function test_fails_without_invoice_id(): void
|
||||
{
|
||||
$this->assertFailsOn('invoice_id', PaymentRequest::class, []);
|
||||
}
|
||||
|
||||
public function test_fails_with_non_integer_invoice_id(): void
|
||||
{
|
||||
$this->assertFailsOn('invoice_id', PaymentRequest::class, ['invoice_id' => 'abc']);
|
||||
}
|
||||
|
||||
public function test_fails_with_unknown_invoice_id(): void
|
||||
{
|
||||
$this->assertFailsOn('invoice_id', PaymentRequest::class, ['invoice_id' => 999]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Client;
|
||||
|
||||
use App\Http\Requests\Client\ProfileUpdateRequest;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ProfileUpdateRequestTest extends TestCase
|
||||
{
|
||||
use ValidatesFormRequests;
|
||||
|
||||
protected function valid(array $overrides = []): array
|
||||
{
|
||||
return array_merge(['fullname' => 'علی رضایی', 'national_code' => '0012345678'], $overrides);
|
||||
}
|
||||
|
||||
public function test_passes_with_required_fields_only(): void
|
||||
{
|
||||
$this->assertPasses(ProfileUpdateRequest::class, $this->valid());
|
||||
}
|
||||
|
||||
public function test_passes_with_all_optional_fields_and_png_avatar(): void
|
||||
{
|
||||
$this->assertPasses(ProfileUpdateRequest::class, $this->valid([
|
||||
'birthdate' => '1990-01-01',
|
||||
'email' => 'a@b.com',
|
||||
'province' => 'تهران',
|
||||
'city' => 'تهران',
|
||||
'address' => 'خیابان',
|
||||
]), ['avatar' => UploadedFile::fake()->image('a.png')]);
|
||||
}
|
||||
|
||||
public function test_fails_without_fullname_or_national_code(): void
|
||||
{
|
||||
$errors = $this->formRequestErrors(ProfileUpdateRequest::class, []);
|
||||
|
||||
$this->assertArrayHasKey('fullname', $errors);
|
||||
$this->assertArrayHasKey('national_code', $errors);
|
||||
}
|
||||
|
||||
public function test_fails_with_invalid_birthdate_or_email(): void
|
||||
{
|
||||
$this->assertFailsOn('birthdate', ProfileUpdateRequest::class, $this->valid(['birthdate' => 'not-a-date']));
|
||||
$this->assertFailsOn('email', ProfileUpdateRequest::class, $this->valid(['email' => 'not-an-email']));
|
||||
}
|
||||
|
||||
public function test_fails_when_national_code_or_address_too_long(): void
|
||||
{
|
||||
$this->assertFailsOn('national_code', ProfileUpdateRequest::class, $this->valid(['national_code' => str_repeat('1', 21)]));
|
||||
$this->assertFailsOn('address', ProfileUpdateRequest::class, $this->valid(['address' => str_repeat('a', 501)]));
|
||||
}
|
||||
|
||||
public function test_fails_with_non_image_or_disallowed_avatar_type(): void
|
||||
{
|
||||
$this->assertFailsOn('avatar', ProfileUpdateRequest::class, $this->valid(), ['avatar' => UploadedFile::fake()->create('a.pdf', 10, 'application/pdf')]);
|
||||
$this->assertFailsOn('avatar', ProfileUpdateRequest::class, $this->valid(), ['avatar' => UploadedFile::fake()->image('a.gif')]);
|
||||
}
|
||||
|
||||
public function test_fails_with_avatar_over_ten_megabytes(): void
|
||||
{
|
||||
$this->assertFailsOn('avatar', ProfileUpdateRequest::class, $this->valid(), ['avatar' => UploadedFile::fake()->image('a.jpg')->size(10241)]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Client;
|
||||
|
||||
use App\Http\Requests\Client\ReportSubmitRequest;
|
||||
use App\Models\Document;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ReportSubmitRequestTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase, ValidatesFormRequests;
|
||||
|
||||
protected function valid(array $overrides = []): array
|
||||
{
|
||||
return array_merge(['document_id' => Document::factory()->create()->id, 'finding' => 'یافتهها'], $overrides);
|
||||
}
|
||||
|
||||
public function test_passes_with_document_and_finding(): void
|
||||
{
|
||||
$this->assertPasses(ReportSubmitRequest::class, $this->valid());
|
||||
}
|
||||
|
||||
public function test_passes_with_optional_sections_and_image_files(): void
|
||||
{
|
||||
$this->assertPasses(ReportSubmitRequest::class, $this->valid([
|
||||
'technique' => 't',
|
||||
'diagnose' => 'd',
|
||||
'recommendation' => 'r',
|
||||
]), ['files' => [UploadedFile::fake()->image('a.jpg'), UploadedFile::fake()->image('b.png')]]);
|
||||
}
|
||||
|
||||
public function test_fails_without_document_or_finding(): void
|
||||
{
|
||||
$errors = $this->formRequestErrors(ReportSubmitRequest::class, []);
|
||||
|
||||
$this->assertArrayHasKey('document_id', $errors);
|
||||
$this->assertArrayHasKey('finding', $errors);
|
||||
}
|
||||
|
||||
public function test_fails_with_unknown_document(): void
|
||||
{
|
||||
$this->assertFailsOn('document_id', ReportSubmitRequest::class, $this->valid(['document_id' => 999]));
|
||||
}
|
||||
|
||||
public function test_fails_when_section_exceeds_limit(): void
|
||||
{
|
||||
$this->assertFailsOn('finding', ReportSubmitRequest::class, $this->valid(['finding' => str_repeat('a', 10001)]));
|
||||
}
|
||||
|
||||
public function test_fails_with_non_image_file(): void
|
||||
{
|
||||
$this->assertFailsOn('files.0', ReportSubmitRequest::class, $this->valid(), ['files' => [UploadedFile::fake()->create('a.pdf', 10, 'application/pdf')]]);
|
||||
}
|
||||
|
||||
public function test_fails_with_file_over_ten_megabytes(): void
|
||||
{
|
||||
$this->assertFailsOn('files.0', ReportSubmitRequest::class, $this->valid(), ['files' => [UploadedFile::fake()->image('a.jpg')->size(10241)]]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Client;
|
||||
|
||||
use App\Http\Requests\Client\WalletDepositRequest;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class WalletDepositRequestTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase, ValidatesFormRequests;
|
||||
|
||||
public function test_passes_with_amount_in_range(): void
|
||||
{
|
||||
$this->assertPasses(WalletDepositRequest::class, ['amount' => 10000]);
|
||||
$this->assertPasses(WalletDepositRequest::class, ['amount' => 500000000]);
|
||||
}
|
||||
|
||||
public function test_fails_without_amount(): void
|
||||
{
|
||||
$this->assertFailsOn('amount', WalletDepositRequest::class, []);
|
||||
}
|
||||
|
||||
public function test_fails_with_non_integer_amount(): void
|
||||
{
|
||||
$this->assertFailsOn('amount', WalletDepositRequest::class, ['amount' => '10000.5']);
|
||||
}
|
||||
|
||||
public function test_fails_below_minimum(): void
|
||||
{
|
||||
$this->assertFailsOn('amount', WalletDepositRequest::class, ['amount' => 9999]);
|
||||
}
|
||||
|
||||
public function test_fails_above_maximum(): void
|
||||
{
|
||||
$this->assertFailsOn('amount', WalletDepositRequest::class, ['amount' => 500000001]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Requests\Client;
|
||||
|
||||
use App\Http\Requests\Client\WithdrawRequestStoreRequest;
|
||||
use App\Models\BankCard;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\Concerns\ValidatesFormRequests;
|
||||
use Tests\TestCase;
|
||||
|
||||
class WithdrawRequestStoreRequestTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase, ValidatesFormRequests;
|
||||
|
||||
public function test_passes_with_valid_amount_and_existing_bank_card(): void
|
||||
{
|
||||
$bankCard = BankCard::factory()->create();
|
||||
|
||||
$this->assertPasses(WithdrawRequestStoreRequest::class, ['amount' => 50000, 'bank_card_id' => $bankCard->id]);
|
||||
}
|
||||
|
||||
public function test_fails_without_required_fields(): void
|
||||
{
|
||||
$errors = $this->formRequestErrors(WithdrawRequestStoreRequest::class, []);
|
||||
|
||||
$this->assertArrayHasKey('amount', $errors);
|
||||
$this->assertArrayHasKey('bank_card_id', $errors);
|
||||
}
|
||||
|
||||
public function test_fails_with_amount_out_of_range(): void
|
||||
{
|
||||
$bankCard = BankCard::factory()->create();
|
||||
|
||||
$this->assertFailsOn('amount', WithdrawRequestStoreRequest::class, ['amount' => 9999, 'bank_card_id' => $bankCard->id]);
|
||||
$this->assertFailsOn('amount', WithdrawRequestStoreRequest::class, ['amount' => 500000001, 'bank_card_id' => $bankCard->id]);
|
||||
}
|
||||
|
||||
public function test_fails_with_unknown_bank_card(): void
|
||||
{
|
||||
$this->assertFailsOn('bank_card_id', WithdrawRequestStoreRequest::class, ['amount' => 50000, 'bank_card_id' => 999]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user