From 0a2b3240414a5f0961fb718db46e066b6d8a7962 Mon Sep 17 00:00:00 2001 From: joddyabott Date: Sat, 10 May 2025 17:24:11 +0330 Subject: [PATCH 1/5] write test for this project for example login ana call --- database/factories/ProvinceFactory.php | 4 +- resources/lang/fa/validation.php | 4 +- tests/Feature/Auth/LoginTest.php | 99 ++++++++++++ tests/Feature/Call/ListTest.php | 129 +++++++++++++++ tests/Feature/Call/StoreTest.php | 120 ++++++++++++++ tests/Feature/Call/UpdateTest.php | 208 +++++++++++++++++++++++++ tests/TestCase.php | 10 +- 7 files changed, 571 insertions(+), 3 deletions(-) create mode 100644 tests/Feature/Auth/LoginTest.php create mode 100644 tests/Feature/Call/ListTest.php create mode 100644 tests/Feature/Call/StoreTest.php create mode 100644 tests/Feature/Call/UpdateTest.php diff --git a/database/factories/ProvinceFactory.php b/database/factories/ProvinceFactory.php index 767b375..891ea6e 100644 --- a/database/factories/ProvinceFactory.php +++ b/database/factories/ProvinceFactory.php @@ -17,7 +17,9 @@ class ProvinceFactory extends Factory public function definition(): array { return [ - // + 'name' => $this->faker->state, + 'lat' => $this->faker->latitude, + 'lon' => $this->faker->longitude, ]; } } diff --git a/resources/lang/fa/validation.php b/resources/lang/fa/validation.php index b92f5eb..903e525 100644 --- a/resources/lang/fa/validation.php +++ b/resources/lang/fa/validation.php @@ -204,7 +204,9 @@ return [ 'category_id' => 'موضوع', 'subcategory_id' => 'زیر موضوع', 'description' => 'توضیحات', - 'size' => 'حداکثر تعداد' + 'size' => 'حداکثر تعداد', + 'extension' => 'کد تلفن', + 'caller_id' => 'شماره تماس‌گیرنده', ], ]; diff --git a/tests/Feature/Auth/LoginTest.php b/tests/Feature/Auth/LoginTest.php new file mode 100644 index 0000000..5649fae --- /dev/null +++ b/tests/Feature/Auth/LoginTest.php @@ -0,0 +1,99 @@ +withoutExceptionHandling(); +// +// $this->artisan('passport:install'); +// +// $user = User::factory()->create(); +// +// $response = $this->postJson('/api/auth/login', [ +// 'username' => $user->username, +// 'password' => 'password', +// ]); +// +// $token = Token::where('user_id', $user->id)->first(); +// +// $response->assertStatus(200) +// ->assertJson([ +// 'message' => __('messages.successful') +// ]); +// +// $this->assertDatabaseHas('oauth_access_tokens' , [ +// 'user_id' => $user->id, +// ]); +// +// $this->assertInstanceOf(Token::class, $token); +// } + + public function test_user_can_login() + { + $user = User::factory() + ->create([ + 'password' => bcrypt('password'), + 'province_id' => Province::factory() + ]); + + $response = $this->postJson('/server/auth/login', [ + 'username' => $user->username, + 'password' => 'password', + 'telephone_id' => $this->faker->numerify('TID####') + ]); + + $response->assertOk() + ->assertJson([ + 'message' => __('messages.successful'), + ]); + + $this->assertAuthenticatedAs($user); + } + + public function test_username_is_required() + { + $response = $this->postJson('/server/auth/login', [ + 'password' => 'password', + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'username' => __('validation.required', ['attribute' => 'نام کاربری']), + ]); + } + + + public function test_password_is_required() + { + $response = $this->postJson('/server/auth/login', [ + 'username' => $this->faker->lexify('?????'), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'password' => __('validation.required', ['attribute' => 'رمز عبور']) + ]); + } + public function test_telephone_id_is_required() + { + $response = $this->postJson('/server/auth/login', [ + 'username' => $this->faker->lexify('?????'), + 'password' => 'password', + ]); + $response->assertUnprocessable() + ->assertInvalid([ + 'telephone_id' => __('validation.required', ['attribute' => 'کد تلفن']) + ]); + } +} diff --git a/tests/Feature/Call/ListTest.php b/tests/Feature/Call/ListTest.php new file mode 100644 index 0000000..907842a --- /dev/null +++ b/tests/Feature/Call/ListTest.php @@ -0,0 +1,129 @@ +getJson(route('calls.list')); +// $response->assertStatus(401); +// } +// +// public function test_user_without_permission_cannot_access(): void +// { +// $user = User::factory()->create(); +// $this->actingAs($user); +// +// $response = $this->getJson(route('calls.list')); +// $response->assertForbidden(); +// } +// +// public function test_phone_number_must_be_string(): void +// { +// $user = User::factory() +// ->has(Permission::factory([ +// 'name' => 'manage_calls', +// 'name_fa' => 'مدیریت تماس‌ها', +// ])) +// ->create(); +// +// // 🟢 احراز هویت کاربر قبل از ارسال درخواست +// $this->actingAs($user); +// +// $response = $this->getJson(route('calls.list', [ +// 'phone_number' => $this->faker->in, +// ])); +// +// $response->assertUnprocessable() +// ->assertInvalid([ +// 'phone_number' => __('validation.string', ['attribute' => 'شماره تلفن']), +// ]); +// } +// +// +// public function test_size_must_be_integer(): void +// { +// $user = $this->createUserWithPermission(); +// $this->actingAs($user); +// +// $response = $this->getJson(route('calls.list', [ +// 'size' => 'not-an-integer', +// ])); +// +// $response->assertUnprocessable() +// ->assertInvalid([ +// 'size' => __('validation.integer', ['attribute' => 'حداکثر تعداد']), +// ]); +// } +// +// public function test_calls_are_returned_with_limit(): void +// { +// $user = $this->createUserWithPermission(); +// $this->actingAs($user); +// +// Call::factory()->count(8)->create(); +// +// $response = $this->getJson(route('calls.list', ['size' => 5])); +// +// $response->assertOk() +// ->assertJsonCount(5, 'data') +// ->assertJson(fn (AssertableJson $json) => +// $json->has('message') +// ->has('data') +// ->has('data.0', fn (AssertableJson $json) => +// $json->hasAll([ +// 'id', +// 'operator_id', +// 'operator_full_name', +// 'operator_username', +// 'telephone_id', +// 'caller_phone_number', +// 'description', +// 'category_id', +// 'category_name', +// 'subcategory_id', +// 'subcategory_name', +// 'created_at', +// ]) +// ) +// ); +// } +// +// public function test_calls_are_filtered_by_phone_number(): void +// { +// $user = $this->createUserWithPermission(); +// $this->actingAs($user); +// +// $targetPhone = '09' . $this->faker->numberBetween(100000000, 999999999); +// Call::factory()->count(4)->create(['caller_phone_number' => $targetPhone]); +// Call::factory()->count(2)->create(); // other numbers +// +// $response = $this->getJson(route('calls.list', ['phone_number' => $targetPhone])); +// +// $response->assertOk() +// ->assertJsonCount(4, 'data') +// ->assertJsonFragment(['caller_phone_number' => $targetPhone]); +// } +// +// private function createUserWithPermission(): User +// { +// return User::factory() +// ->has(Permission::factory([ +// 'name' => 'manage_calls', +// 'name_fa' => 'مدیریت تماس‌ها', +// ])) +// ->create(); +// } +//} diff --git a/tests/Feature/Call/StoreTest.php b/tests/Feature/Call/StoreTest.php new file mode 100644 index 0000000..03b2ed7 --- /dev/null +++ b/tests/Feature/Call/StoreTest.php @@ -0,0 +1,120 @@ +create(); + + $response = $this->actingAs($user)->postJson(route('calls.store')); + + $response->assertUnprocessable() + ->assertInvalid([ + 'extension' => __('validation.required', ['attribute' => 'کد تلفن']), + 'caller_id' => __('validation.required', ['attribute' => 'شماره تماس‌گیرنده']), + ]); + } + + public function test_extension_must_be_string(): void + { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->postJson(route('calls.store'), [ + 'extension' => $this->faker->numberBetween(1000, 9999), + 'caller_id' => $this->faker->numerify('09#########'), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'extension' => __('validation.string', ['attribute' => 'کد تلفن']), + ]); + } + + public function test_extension_must_exist_in_users_table(): void + { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->postJson(route('calls.store'), [ + 'extension' => 'invalid-ext-' . $this->faker->uuid, + 'caller_id' => $this->faker->numerify('09#########'), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'extension' => __('validation.exists', ['attribute' => 'کد تلفن']), + ]); + } + + public function test_caller_id_must_be_numeric(): void + { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->postJson(route('calls.store'), [ + 'extension' => $user->telephone_id, + 'caller_id' => $this->faker->word(), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'caller_id' => __('validation.numeric', ['attribute' => 'شماره تماس‌گیرنده']), + ]); + } + + public function test_can_create_a_call(): void + { + $operator = User::factory()->make(); // bypass fillable + $operator->telephone_id = 'tel-' . $this->faker->unique()->numerify('###'); + $operator->save(); + + $this->artisan('db:seed --class=EventSeeder'); + + $this->mock(NotificationService::class, function (MockInterface $mock) { + $mock->shouldReceive('deliverDataToNotificationServer'); + }); + + $callerId = $this->faker->numerify('09#########'); + + $response = $this->postJson(route('calls.store'), [ + 'extension' => $operator->telephone_id, + 'caller_id' => $callerId, + ]); + + $response->assertStatus(200) + ->assertExactJson([ + 'message' => __('messages.successful'), + ]); + + $this->assertDatabaseHas('calls', [ + 'caller_phone_number' => $callerId, + 'telephone_id' => $operator->telephone_id, + 'operator_id' => $operator->id, + 'operator_username' => $operator->username, + 'operator_full_name' => $operator->full_name, + ]); + + $event = Event::query()->where('id', CallEvents::CALL_CREATED)->first(); + + $this->assertDatabaseHas('call_histories', [ + 'event_name' => $event->name, + 'event_id' => $event->id, + 'caller_phone_number' => $callerId, + 'telephone_id' => $operator->telephone_id, + ]); + } + +} diff --git a/tests/Feature/Call/UpdateTest.php b/tests/Feature/Call/UpdateTest.php new file mode 100644 index 0000000..9dc555f --- /dev/null +++ b/tests/Feature/Call/UpdateTest.php @@ -0,0 +1,208 @@ +create([ + 'telephone_id' => 'tel-' . $this->faker->unique()->numerify('###'), + ]); + + $call = Call::factory()->create([ + 'telephone_id' => $callOwner->telephone_id, + ]); + + $unauthorizedUser = User::factory()->create(); // no permission + + $this->actingAs($unauthorizedUser); + + $response = $this->postJson(route('calls.update', $call->id), [ + 'category_id' => 1, + 'subcategory_id' => 2, + 'description' => '...', + ]); + + $response->assertForbidden(); + } + + public function test_validation_fails_when_required_fields_are_missing(): void + { + $telephoneId = 'tel-' . $this->faker->unique()->numerify('###'); + + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_calls', + 'name_fa' => 'مدیریت تماس‌ها', + ])) + ->create([ + 'telephone_id' => $telephoneId, + ]); + + $call = Call::factory()->create([ + 'telephone_id' => $telephoneId, + ]); + + $this->actingAs($user); + + $response = $this->postJson(route('calls.update', $call->id), []); + + $response->assertUnprocessable() + ->assertInvalid([ + 'category_id' => __('validation.required', ['attribute' => 'موضوع']), + 'subcategory_id' => __('validation.required', ['attribute' => 'زیر موضوع']), + ]); + } + + public function test_category_id_and_subcategory_id_must_be_integers(): void + { + $telephoneId = 'tel-' . $this->faker->unique()->numerify('###'); + + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_calls', + 'name_fa' => 'مدیریت تماس‌ها', + ])) + ->create([ + 'telephone_id' => $telephoneId, + ]); + + $call = Call::factory()->create([ + 'telephone_id' => $telephoneId, + ]); + + $this->actingAs($user); + + $response = $this->postJson(route('calls.update', $call->id), [ + 'category_id' => 'not-an-int', + 'subcategory_id' => 'also-string', + 'description' => 'توضیح', + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'category_id' => __('validation.integer', ['attribute' => 'موضوع']), + 'subcategory_id' => __('validation.integer', ['attribute' => 'زیر موضوع']), + ]); + } + + public function test_description_field_must_be_string(): void + { + $telephoneId = 'tel-' . $this->faker->unique()->numerify('###'); + + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_calls', + 'name_fa' => 'مدیریت تماس‌ها', + ])) + ->create([ + 'telephone_id' => $telephoneId, + ]); + + $call = Call::factory()->create([ + 'telephone_id' => $telephoneId, + ]); + + $this->actingAs($user); + + $response = $this->postJson(route('calls.update', $call->id), [ + 'category_id' => 1, + 'subcategory_id' => 2, + 'description' => ['not', 'a', 'string'], + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'description' => __('validation.string', ['attribute' => 'توضیحات']), + ]); + } + + public function test_combination_of_category_and_subcategory_must_exist(): void + { + $telephoneId = 'tel-' . $this->faker->unique()->numerify('###'); + + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_calls', + 'name_fa' => 'مدیریت تماس‌ها', + ])) + ->create([ + 'telephone_id' => $telephoneId, + ]); + + $call = Call::factory()->create([ + 'telephone_id' => $telephoneId, + ]); + + $this->actingAs($user); + + $response = $this->postJson(route('calls.update', $call->id), [ + 'category_id' => 12345, + 'subcategory_id' => 67890, + 'description' => '...', + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'category' => __('messages.combination_of_category_and_subcategory_does_not_exist'), + ]); + } + + public function test_operator_can_update_call_successfully(): void + { + $telephoneId = 'tel-' . $this->faker->unique()->numerify('###'); + + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_calls', + 'name_fa' => 'مدیریت تماس‌ها', + ])) + ->create([ + 'telephone_id' => $telephoneId, + ]); + + $call = Call::factory()->create([ + 'telephone_id' => $telephoneId, + ]); + + $category = Category::factory()->create(); + + $this->actingAs($user); + + $response = $this->postJson(route('calls.update', $call->id), [ + 'category_id' => $category->category_id, + 'subcategory_id' => $category->subcategory_id, + 'description' => 'توضیحات تستی', + ]); + + $response->assertOk() + ->assertJson([ + 'message' => __('messages.successful'), + ]); + + $this->assertDatabaseHas('calls', [ + 'id' => $call->id, + 'category_id' => $category->category_id, + 'subcategory_id' => $category->subcategory_id, + 'description' => 'توضیحات تستی', + ]); + + $this->assertDatabaseHas('call_histories', [ + 'call_id' => $call->id, + 'event_id' => CallEvents::OPERATOR_STORED_CALL_DATA, + ]); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index fe1ffc2..1b5fd39 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,9 +2,17 @@ namespace Tests; +use Database\Seeders\EventSeeder; use Illuminate\Foundation\Testing\TestCase as BaseTestCase; abstract class TestCase extends BaseTestCase { - // + + protected function setUp(): void + { + parent::setUp(); + app()->setLocale('fa'); + config(['logging.default' => 'null']); + $this->seed(EventSeeder::class); + } } From f2fda290412dfa2e8df85ea6c0d4f37aeb6bbcf5 Mon Sep 17 00:00:00 2001 From: joddyabott Date: Sun, 11 May 2025 11:10:40 +0330 Subject: [PATCH 2/5] improve 4 test --- tests/Feature/Auth/LoginTest.php | 28 +--- tests/Feature/Call/ListTest.php | 241 ++++++++++++++---------------- tests/Feature/Call/StoreTest.php | 12 +- tests/Feature/Call/UpdateTest.php | 112 +++++++++----- 4 files changed, 196 insertions(+), 197 deletions(-) diff --git a/tests/Feature/Auth/LoginTest.php b/tests/Feature/Auth/LoginTest.php index 5649fae..cdc9e28 100644 --- a/tests/Feature/Auth/LoginTest.php +++ b/tests/Feature/Auth/LoginTest.php @@ -12,33 +12,6 @@ class LoginTest extends TestCase { use RefreshDatabase, WithFaker; -// public function test_user_can_login() -// { -// $this->withoutExceptionHandling(); -// -// $this->artisan('passport:install'); -// -// $user = User::factory()->create(); -// -// $response = $this->postJson('/api/auth/login', [ -// 'username' => $user->username, -// 'password' => 'password', -// ]); -// -// $token = Token::where('user_id', $user->id)->first(); -// -// $response->assertStatus(200) -// ->assertJson([ -// 'message' => __('messages.successful') -// ]); -// -// $this->assertDatabaseHas('oauth_access_tokens' , [ -// 'user_id' => $user->id, -// ]); -// -// $this->assertInstanceOf(Token::class, $token); -// } - public function test_user_can_login() { $user = User::factory() @@ -85,6 +58,7 @@ class LoginTest extends TestCase 'password' => __('validation.required', ['attribute' => 'رمز عبور']) ]); } + public function test_telephone_id_is_required() { $response = $this->postJson('/server/auth/login', [ diff --git a/tests/Feature/Call/ListTest.php b/tests/Feature/Call/ListTest.php index 907842a..eba7d04 100644 --- a/tests/Feature/Call/ListTest.php +++ b/tests/Feature/Call/ListTest.php @@ -1,129 +1,114 @@ getJson(route('calls.list')); -// $response->assertStatus(401); -// } -// -// public function test_user_without_permission_cannot_access(): void -// { -// $user = User::factory()->create(); -// $this->actingAs($user); -// -// $response = $this->getJson(route('calls.list')); -// $response->assertForbidden(); -// } -// -// public function test_phone_number_must_be_string(): void -// { -// $user = User::factory() -// ->has(Permission::factory([ -// 'name' => 'manage_calls', -// 'name_fa' => 'مدیریت تماس‌ها', -// ])) -// ->create(); -// -// // 🟢 احراز هویت کاربر قبل از ارسال درخواست -// $this->actingAs($user); -// -// $response = $this->getJson(route('calls.list', [ -// 'phone_number' => $this->faker->in, -// ])); -// -// $response->assertUnprocessable() -// ->assertInvalid([ -// 'phone_number' => __('validation.string', ['attribute' => 'شماره تلفن']), -// ]); -// } -// -// -// public function test_size_must_be_integer(): void -// { -// $user = $this->createUserWithPermission(); -// $this->actingAs($user); -// -// $response = $this->getJson(route('calls.list', [ -// 'size' => 'not-an-integer', -// ])); -// -// $response->assertUnprocessable() -// ->assertInvalid([ -// 'size' => __('validation.integer', ['attribute' => 'حداکثر تعداد']), -// ]); -// } -// -// public function test_calls_are_returned_with_limit(): void -// { -// $user = $this->createUserWithPermission(); -// $this->actingAs($user); -// -// Call::factory()->count(8)->create(); -// -// $response = $this->getJson(route('calls.list', ['size' => 5])); -// -// $response->assertOk() -// ->assertJsonCount(5, 'data') -// ->assertJson(fn (AssertableJson $json) => -// $json->has('message') -// ->has('data') -// ->has('data.0', fn (AssertableJson $json) => -// $json->hasAll([ -// 'id', -// 'operator_id', -// 'operator_full_name', -// 'operator_username', -// 'telephone_id', -// 'caller_phone_number', -// 'description', -// 'category_id', -// 'category_name', -// 'subcategory_id', -// 'subcategory_name', -// 'created_at', -// ]) -// ) -// ); -// } -// -// public function test_calls_are_filtered_by_phone_number(): void -// { -// $user = $this->createUserWithPermission(); -// $this->actingAs($user); -// -// $targetPhone = '09' . $this->faker->numberBetween(100000000, 999999999); -// Call::factory()->count(4)->create(['caller_phone_number' => $targetPhone]); -// Call::factory()->count(2)->create(); // other numbers -// -// $response = $this->getJson(route('calls.list', ['phone_number' => $targetPhone])); -// -// $response->assertOk() -// ->assertJsonCount(4, 'data') -// ->assertJsonFragment(['caller_phone_number' => $targetPhone]); -// } -// -// private function createUserWithPermission(): User -// { -// return User::factory() -// ->has(Permission::factory([ -// 'name' => 'manage_calls', -// 'name_fa' => 'مدیریت تماس‌ها', -// ])) -// ->create(); -// } -//} + +namespace Tests\Feature\Call; + +use App\Models\Call; +use App\Models\Permission; +use App\Models\User; +use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Testing\Fluent\AssertableJson; +use Tests\TestCase; + +class ListTest extends TestCase +{ + use RefreshDatabase, WithFaker; + + public function test_unauthenticated_user_cannot_access(): void + { + $response = $this->getJson(route('calls.list')); + $response->assertStatus(401); + } + + public function test_user_without_permission_cannot_access(): void + { + $user = User::factory()->create(); + $this->actingAs($user); + + $response = $this->getJson(route('calls.list')); + $response->assertForbidden(); + } + + public function test_size_must_be_integer(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_calls', + 'name_fa' => 'مدیریت تماس‌ها', + ]))->create(); + $this->actingAs($user); + + $response = $this->getJson(route('calls.list', [ + 'size' => $this->faker->word, + ])); + + $response->assertUnprocessable() + ->assertInvalid([ + 'size' => __('validation.integer', ['attribute' => 'حداکثر تعداد']), + ]); + } + + public function test_calls_are_limited_by_size_parameter(): void + { + + $user = User::factory() + ->has(Permission::factory()->state([ + 'id' => 3, + 'name' => 'manage_calls', + 'name_fa' => 'مدیریت تماس‌ها', + ])) + ->create(); + Call::factory()->count(5)->create(); + + + $response = $this->actingAs($user)->getJson(route('calls.list', [ + 'size' => $this->faker->numberBetween(1, 4), + ])); + + $response->assertOk() + ->assertJson(fn (AssertableJson $json) => + $json->has('data') + ->has('data.0', fn (AssertableJson $json) => $json->hasAll([ + 'id', + 'operator_id', + 'operator_full_name', + 'operator_username', + 'telephone_id', + 'caller_phone_number', + 'description', + 'category_id', + 'category_name', + 'subcategory_id', + 'subcategory_name', + 'created_at', + ])) + ); + + } + + + public function test_calls_are_filtered_by_phone_number(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_calls', + 'name_fa' => 'مدیریت تماس‌ها', + ]))->create(); + + $targetPhone = '09' . $this->faker->numberBetween(100000000, 999999999); + + Call::factory()->count(4)->create([ + 'caller_phone_number' => $targetPhone, + ]); + + Call::factory()->count(2)->create(); + + + $response = $this->actingAs($user)->getJson(route('calls.list', ['phone_number' => $targetPhone])); + + $response->assertOk() + ->assertJsonCount(4, 'data') + ->assertJsonFragment(['caller_phone_number' => $targetPhone]); + } + +} diff --git a/tests/Feature/Call/StoreTest.php b/tests/Feature/Call/StoreTest.php index 03b2ed7..c4b6466 100644 --- a/tests/Feature/Call/StoreTest.php +++ b/tests/Feature/Call/StoreTest.php @@ -2,14 +2,13 @@ namespace Tests\Feature\Call; -use App\Models\Call; -use App\Models\CallHistory; use App\Models\Event; use App\Models\User; use App\Enums\CallEvents; use App\Services\Notification\NotificationService; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithFaker; +use Illuminate\Support\Facades\DB; use Mockery\MockInterface; use Tests\TestCase; @@ -36,7 +35,7 @@ class StoreTest extends TestCase $response = $this->actingAs($user)->postJson(route('calls.store'), [ 'extension' => $this->faker->numberBetween(1000, 9999), - 'caller_id' => $this->faker->numerify('09#########'), + 'caller_id' => $this->faker->randomNumber(), ]); $response->assertUnprocessable() @@ -50,8 +49,8 @@ class StoreTest extends TestCase $user = User::factory()->create(); $response = $this->actingAs($user)->postJson(route('calls.store'), [ - 'extension' => 'invalid-ext-' . $this->faker->uuid, - 'caller_id' => $this->faker->numerify('09#########'), + 'extension' => $this->faker->uuid, + 'caller_id' => $this->faker->randomNumber(), ]); $response->assertUnprocessable() @@ -77,10 +76,11 @@ class StoreTest extends TestCase public function test_can_create_a_call(): void { - $operator = User::factory()->make(); // bypass fillable + $operator = User::factory()->create(); $operator->telephone_id = 'tel-' . $this->faker->unique()->numerify('###'); $operator->save(); + DB::table('events')->truncate(); $this->artisan('db:seed --class=EventSeeder'); $this->mock(NotificationService::class, function (MockInterface $mock) { diff --git a/tests/Feature/Call/UpdateTest.php b/tests/Feature/Call/UpdateTest.php index 9dc555f..f399a7e 100644 --- a/tests/Feature/Call/UpdateTest.php +++ b/tests/Feature/Call/UpdateTest.php @@ -5,7 +5,6 @@ namespace Tests\Feature\Call; use App\Enums\CallEvents; use App\Models\Call; use App\Models\Category; -use App\Models\Event; use App\Models\Permission; use App\Models\User; use Illuminate\Foundation\Testing\RefreshDatabase; @@ -16,6 +15,55 @@ class UpdateTest extends TestCase { use RefreshDatabase, WithFaker; + public function test_operator_is_not_authenticated(): void + { + $response = $this->postJson(route('calls.update', ['call' => 1])); + + $response->assertUnauthorized(); + } + + public function test_operator_without_unappropriated_permission_is_forbidden_to_access_calls_data(): void + { + $telephoneId = 'tel-' . $this->faker->unique()->numerify('###'); + + $user = User::factory() + ->create([ + 'telephone_id' => $telephoneId, + ]); + + $call = Call::factory()->create([ + 'telephone_id' => $telephoneId, + ]); + + $response = $this->actingAs($user)->postJson(route('calls.update', ['call' => $call->id])); + + $response->assertForbidden(); + } + + public function test_operator_can_not_access_to_other_operators_calls(): void + { + + $telephoneId = 'tel-' . $this->faker->unique()->numerify('###'); + + $user = User::factory() + ->create([ + 'telephone_id' => $telephoneId, + ]); + + $another_operator = User::factory([ + 'id' => $this->faker->randomNumber(2, true) + ])->create(); + + $call = Call::factory([ + 'telephone_id' => $another_operator->telephone_id + ])->create(); + + $response = $this->actingAs($user)->postJson(route('calls.update', ['call' => $call->id])); + + $response->assertForbidden(); + } + + public function test_non_owner_user_cannot_update_call(): void { $callOwner = User::factory()->create([ @@ -26,14 +74,12 @@ class UpdateTest extends TestCase 'telephone_id' => $callOwner->telephone_id, ]); - $unauthorizedUser = User::factory()->create(); // no permission + $user = User::factory()->create(); - $this->actingAs($unauthorizedUser); - - $response = $this->postJson(route('calls.update', $call->id), [ - 'category_id' => 1, - 'subcategory_id' => 2, - 'description' => '...', + $response = $this->actingAs($user)->postJson(route('calls.update', $call->id), [ + 'category_id' => $this->faker->randomNumber(), + 'subcategory_id' => $this->faker->randomNumber(), + 'description' => $this->faker->sentence ]); $response->assertForbidden(); @@ -56,9 +102,7 @@ class UpdateTest extends TestCase 'telephone_id' => $telephoneId, ]); - $this->actingAs($user); - - $response = $this->postJson(route('calls.update', $call->id), []); + $response = $this->actingAs($user)->postJson(route('calls.update', $call->id), []); $response->assertUnprocessable() ->assertInvalid([ @@ -81,15 +125,13 @@ class UpdateTest extends TestCase ]); $call = Call::factory()->create([ - 'telephone_id' => $telephoneId, + 'telephone_id' =>$user->telephone_id, ]); - $this->actingAs($user); - - $response = $this->postJson(route('calls.update', $call->id), [ - 'category_id' => 'not-an-int', - 'subcategory_id' => 'also-string', - 'description' => 'توضیح', + $response = $this->actingAs($user)->postJson(route('calls.update', $call->id), [ + 'category_id' =>$this->faker->sentence(3), + 'subcategory_id' => $this->faker->sentence(3), + 'description' => $this->faker->sentence, ]); $response->assertUnprocessable() @@ -116,12 +158,12 @@ class UpdateTest extends TestCase 'telephone_id' => $telephoneId, ]); - $this->actingAs($user); - $response = $this->postJson(route('calls.update', $call->id), [ - 'category_id' => 1, - 'subcategory_id' => 2, - 'description' => ['not', 'a', 'string'], + + $response = $this->actingAs($user)->postJson(route('calls.update', $call->id), [ + 'category_id' => $this->faker->randomNumber(), + 'subcategory_id' => $this->faker->randomNumber(), + 'description' => $this->faker->randomNumber(), ]); $response->assertUnprocessable() @@ -147,12 +189,12 @@ class UpdateTest extends TestCase 'telephone_id' => $telephoneId, ]); - $this->actingAs($user); - $response = $this->postJson(route('calls.update', $call->id), [ - 'category_id' => 12345, - 'subcategory_id' => 67890, - 'description' => '...', + + $response = $this->actingAs($user)->postJson(route('calls.update', $call->id), [ + 'category_id' => $this->faker->randomNumber(), + 'subcategory_id' => $this->faker->randomNumber(), + 'description' => $this->faker->sentence, ]); $response->assertUnprocessable() @@ -179,14 +221,12 @@ class UpdateTest extends TestCase ]); $category = Category::factory()->create(); - - $this->actingAs($user); - - $response = $this->postJson(route('calls.update', $call->id), [ + $description = $this->faker->sentence; + $response = $this->actingAs($user)->postJson(route('calls.update', $call->id), [ 'category_id' => $category->category_id, 'subcategory_id' => $category->subcategory_id, - 'description' => 'توضیحات تستی', - ]); + 'description' => $description, + ]); $response->assertOk() ->assertJson([ @@ -197,8 +237,8 @@ class UpdateTest extends TestCase 'id' => $call->id, 'category_id' => $category->category_id, 'subcategory_id' => $category->subcategory_id, - 'description' => 'توضیحات تستی', - ]); + 'description' => $description, + ]); $this->assertDatabaseHas('call_histories', [ 'call_id' => $call->id, From 70f3c36f588c61aae629ba0d42afad3696f26a61 Mon Sep 17 00:00:00 2001 From: joddyabott Date: Sun, 11 May 2025 16:19:50 +0330 Subject: [PATCH 3/5] write test for all of permission api --- database/factories/PermissionFactory.php | 4 +- routes/web.php | 1 + tests/Feature/Permission/DeleteTest.php | 41 ++++++++ tests/Feature/Permission/IndexTest.php | 50 ++++++++++ tests/Feature/Permission/ListTest.php | 57 +++++++++++ tests/Feature/Permission/SHowTest.php | 53 ++++++++++ tests/Feature/Permission/StoreTest.php | 117 +++++++++++++++++++++++ tests/Feature/Permission/UpdateTest.php | 114 ++++++++++++++++++++++ 8 files changed, 436 insertions(+), 1 deletion(-) create mode 100644 tests/Feature/Permission/DeleteTest.php create mode 100644 tests/Feature/Permission/IndexTest.php create mode 100644 tests/Feature/Permission/ListTest.php create mode 100644 tests/Feature/Permission/SHowTest.php create mode 100644 tests/Feature/Permission/StoreTest.php create mode 100644 tests/Feature/Permission/UpdateTest.php diff --git a/database/factories/PermissionFactory.php b/database/factories/PermissionFactory.php index d2cec7f..365446d 100644 --- a/database/factories/PermissionFactory.php +++ b/database/factories/PermissionFactory.php @@ -17,7 +17,9 @@ class PermissionFactory extends Factory public function definition(): array { return [ - // + 'name' => $this->faker->unique()->slug, + 'name_fa' => $this->faker->word, + 'guard_name' => 'web', ]; } } diff --git a/routes/web.php b/routes/web.php index 5714891..5da8281 100644 --- a/routes/web.php +++ b/routes/web.php @@ -60,6 +60,7 @@ Route::prefix('server')->group(function () { Route::middleware('auth') ->prefix('permissions') + ->name('permissions.') ->controller(PermissionManagementController::class) ->group(function () { Route::get('/', 'index')->name('index'); diff --git a/tests/Feature/Permission/DeleteTest.php b/tests/Feature/Permission/DeleteTest.php new file mode 100644 index 0000000..d0b1d4c --- /dev/null +++ b/tests/Feature/Permission/DeleteTest.php @@ -0,0 +1,41 @@ +create(); + $permission = Permission::factory()->create(); + + $response = $this->actingAs($user)->deleteJson(route('permissions.destroy', $permission)); + + $response->assertOk() + ->assertJson([ + 'message' => __('messages.successful'), + ]); + + $this->assertDatabaseMissing('permissions', [ + 'id' => $permission->id, + ]); + } + + public function test_guest_cannot_delete_permission(): void + { + $permission = Permission::factory()->create(); + + $response = $this->deleteJson(route('permissions.destroy', $permission)); + + $response->assertUnauthorized(); + } + +} diff --git a/tests/Feature/Permission/IndexTest.php b/tests/Feature/Permission/IndexTest.php new file mode 100644 index 0000000..be3ebd4 --- /dev/null +++ b/tests/Feature/Permission/IndexTest.php @@ -0,0 +1,50 @@ +getJson(route('permissions.list')); + + $response->assertStatus(401); + } + + public function test_all_permissions_returned_successfully(): void + { + $user = User::factory() + ->has(Permission::factory()->state([ + 'name' => 'permissions', + 'name_fa' => 'مدیریت دسترسی', + 'guard_name' => 'web', + ])) + ->create(); + + $response = $this->actingAs($user)->getJson(route('permissions.index')); + + $response->assertOk(); + + $response->assertJsonStructure([ + 'data' => [ + '*' => [ + 'id', + 'name', + 'name_fa', + 'guard_name', + 'created_at', + 'updated_at', + ], + ] + ]); + + } +} diff --git a/tests/Feature/Permission/ListTest.php b/tests/Feature/Permission/ListTest.php new file mode 100644 index 0000000..036ee3d --- /dev/null +++ b/tests/Feature/Permission/ListTest.php @@ -0,0 +1,57 @@ +getJson(route('permissions.list')); + + $response->assertStatus(401); + } + + + public function test_guest_user_cannot_access_list(): void + { + $response = $this->getJson(route('permissions.list')); + + $response->assertUnauthorized(); + } + + public function test_permissions_list_returns_correct_structure(): void + { + $user = User::factory() + ->has(Permission::factory()->state([ + 'name' => 'manage-permissions', + 'name_fa' => 'مدیریت دسترسی‌ها', + 'guard_name' => 'web', + ])) + ->create(); + + Permission::factory()->count(3)->create(); + + $response = $this->actingAs($user)->getJson(route('permissions.list')); + + $response->assertOk() + ->assertJsonStructure([ + 'data' => [ + '*' => [ + 'id', + 'name', + 'name_fa', + ] + ] + ]); + } + +} diff --git a/tests/Feature/Permission/SHowTest.php b/tests/Feature/Permission/SHowTest.php new file mode 100644 index 0000000..4d8997c --- /dev/null +++ b/tests/Feature/Permission/SHowTest.php @@ -0,0 +1,53 @@ +create(); + + $response = $this->getJson(route('permissions.show', $permission)); + + $response->assertUnauthorized(); + } + public function test_permission_show_returns_correct_structure_and_data(): void + { + $user = User::factory() + ->has(Permission::factory()->state([ + 'name' => 'manage-permissions', + 'name_fa' => 'مدیریت دسترسی‌ها', + 'guard_name' => 'web', + ])) + ->create(); + + $permission = Permission::factory()->create([ + 'name' => 'edit-posts', + 'name_fa' => 'ویرایش پست‌ها', + 'guard_name' => 'web', + ]); + + $response = $this->actingAs($user)->getJson(route('permissions.show', $permission)); + + $response->assertOk() + ->assertJson([ + 'data' => [ + 'id' => $permission->id, + 'name' => 'edit-posts', + 'name_fa' => 'ویرایش پست‌ها', + 'guard_name' => 'web', + ] + ]); + } + + +} diff --git a/tests/Feature/Permission/StoreTest.php b/tests/Feature/Permission/StoreTest.php new file mode 100644 index 0000000..2517eaa --- /dev/null +++ b/tests/Feature/Permission/StoreTest.php @@ -0,0 +1,117 @@ +postJson(route('permissions.store'), []); + $response->assertUnauthorized(); + } + + public function test_name_and_name_fa_fields_are_required(): void + { + $user = User::factory()->create(); + + + $response = $this->actingAs($user)->postJson(route('permissions.store')); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.required', ['attribute' => 'نام']), + 'name_fa' => __('validation.required', ['attribute' => 'نام فارسی']), + ]); + } + public function test_name_and_name_fa_fields_must_be_unique(): void + { + $user = User::factory()->create(); + + $duplicateName = $this->faker->unique()->slug; + $duplicateNameFa = $this->faker->unique()->word; + + Permission::create([ + 'name' => $duplicateName, + 'name_fa' => $duplicateNameFa, + 'guard_name' => 'web', + ]); + + $response = $this->actingAs($user)->postJson(route('permissions.store'), [ + 'name' => $duplicateName, // حالا واقعا تکراری هستند + 'name_fa' => $duplicateNameFa, + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.unique', ['attribute' => 'نام']), + 'name_fa' => __('validation.unique', ['attribute' => 'نام فارسی']), + ]); + } + + + public function test_name_and_name_fa_must_be_strings(): void + { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->postJson(route('permissions.store'), [ + 'name' =>$this->faker->randomDigit(), + 'name_fa' => $this->faker->randomDigit(), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.string', ['attribute' => 'نام']), + 'name_fa' => __('validation.string', ['attribute' => 'نام فارسی']), + ]); + } + + public function test_name_and_name_fa_must_not_exceed_max_length(): void + { + $user = User::factory()->create(); + + $longString = $this->faker->regexify('[a-zA-Z0-9]{256}'); + + $response = $this->actingAs($user)->postJson(route('permissions.store'), [ + 'name' => $longString, + 'name_fa' => $longString, + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.max.string', ['attribute' => 'نام', 'max' => 255]), + 'name_fa' => __('validation.max.string', ['attribute' => 'نام فارسی', 'max' => 255]), + ]); + } + + public function test_valid_permission_is_stored_successfully(): void + { + $user = User::factory()->create(); + + $payload = [ + 'name' => $this->faker->unique()->slug, + 'name_fa' => $this->faker->unique()->words(2, true), + ]; + + $response = $this->actingAs($user)->postJson(route('permissions.store'), $payload); + + $response->assertOk() + ->assertJson([ + 'message' => __('messages.successful'), + ]); + + $this->assertDatabaseHas('permissions', [ + 'name' => $payload['name'], + 'name_fa' => $payload['name_fa'], + ]); + } + + +} diff --git a/tests/Feature/Permission/UpdateTest.php b/tests/Feature/Permission/UpdateTest.php new file mode 100644 index 0000000..855832e --- /dev/null +++ b/tests/Feature/Permission/UpdateTest.php @@ -0,0 +1,114 @@ +postJson(route('permissions.store'), []); + $response->assertUnauthorized(); + } + + + public function test_name_and_name_fa_fields_are_required(): void + { + $user = User::factory()->create(); + $permission = Permission::factory()->create(); + + $response = $this->actingAs($user)->postJson(route('permissions.update', $permission)); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.required', ['attribute' => 'نام']), + 'name_fa' => __('validation.required', ['attribute' => 'نام فارسی']), + ]); + } + + public function test_name_and_name_fa_fields_must_be_strings(): void + { + $user = User::factory()->create(); + $permission = Permission::factory()->create(); + + $response = $this->actingAs($user)->postJson(route('permissions.update', $permission), [ + 'name' =>$this->faker->randomDigit(), + 'name_fa' => $this->faker->randomDigit(), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.string', ['attribute' => 'نام']), + 'name_fa' => __('validation.string', ['attribute' => 'نام فارسی']), + ]); + } + + public function test_name_and_name_fa_fields_must_be_unique_except_current(): void + { + $user = User::factory()->create(); + + $permission1 = Permission::factory()->create(); + $permission2 = Permission::factory()->create(); + + $response = $this->actingAs($user)->postJson(route('permissions.update', $permission1), [ + 'name' => $permission2->name, + 'name_fa' => $permission2->name_fa, + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.unique', ['attribute' => 'نام']), + 'name_fa' => __('validation.unique', ['attribute' => 'نام فارسی']), + ]); + } + + public function test_name_and_name_fa_must_not_exceed_max_length(): void + { + $user = User::factory()->create(); + $permission = Permission::factory()->create(); + + $longString = $this->faker->regexify('[a-zA-Z0-9]{256}'); + + $response = $this->actingAs($user)->postJson(route('permissions.update', $permission), [ + 'name' => $longString, + 'name_fa' => $longString, + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.max.string', ['attribute' => 'نام', 'max' => 255]), + 'name_fa' => __('validation.max.string', ['attribute' => 'نام فارسی', 'max' => 255]), + ]); + } + + public function test_valid_permission_is_updated_successfully(): void + { + $user = User::factory()->create(); + $permission = Permission::factory()->create(); + + $payload = [ + 'name' => $this->faker->unique()->slug, + 'name_fa' => $this->faker->unique()->words(2, true), + ]; + + $response = $this->actingAs($user)->postJson(route('permissions.update', $permission), $payload); + + $response->assertOk() + ->assertJson([ + 'message' => __('messages.successful'), + ]); + + $this->assertDatabaseHas('permissions', [ + 'id' => $permission->id, + 'name' => $payload['name'], + 'name_fa' => $payload['name_fa'], + ]); + } +} From db8cda55dfb99f8996cf9ae0eb86877688dc3c6b Mon Sep 17 00:00:00 2001 From: joddyabott Date: Mon, 12 May 2025 17:05:42 +0330 Subject: [PATCH 4/5] write new tests --- database/factories/RoleFactory.php | 4 +- routes/web.php | 7 +- tests/Feature/Call/StoreTest.php | 7 +- tests/Feature/Call/UpdateTest.php | 4 + tests/Feature/Permission/IndexTest.php | 2 +- tests/Feature/Permission/UpdateTest.php | 6 +- tests/Feature/Role/DeleteTest.php | 65 ++++++++++ tests/Feature/Role/IndexTest.php | 47 +++++++ tests/Feature/Role/ListTest.php | 41 +++++++ tests/Feature/Role/ShowTest.php | 51 ++++++++ tests/Feature/Role/StoreTest.php | 125 +++++++++++++++++++ tests/Feature/Role/UpdateTest.php | 157 ++++++++++++++++++++++++ tests/TestCase.php | 9 +- 13 files changed, 507 insertions(+), 18 deletions(-) create mode 100644 tests/Feature/Role/DeleteTest.php create mode 100644 tests/Feature/Role/IndexTest.php create mode 100644 tests/Feature/Role/ListTest.php create mode 100644 tests/Feature/Role/ShowTest.php create mode 100644 tests/Feature/Role/StoreTest.php create mode 100644 tests/Feature/Role/UpdateTest.php diff --git a/database/factories/RoleFactory.php b/database/factories/RoleFactory.php index b825646..5dbe458 100644 --- a/database/factories/RoleFactory.php +++ b/database/factories/RoleFactory.php @@ -17,7 +17,9 @@ class RoleFactory extends Factory public function definition(): array { return [ - // + 'name' => $this->faker->unique()->slug, + 'name_fa' => $this->faker->unique()->word, + 'guard_name' => 'web', ]; } } diff --git a/routes/web.php b/routes/web.php index 5da8281..7784c91 100644 --- a/routes/web.php +++ b/routes/web.php @@ -79,13 +79,14 @@ Route::prefix('server')->group(function () { Route::middleware('auth') ->prefix('roles') + ->name('roles.') ->controller(RoleManagementController::class) ->group(function () { Route::get('/', 'index')->name('index'); Route::get('list', 'list')->name('list'); Route::post('/', 'store')->name('store'); - Route::get('/{roll}', 'show')->name('show'); - Route::post('/{roll}', 'update')->name('update'); - Route::delete('/{roll}', 'destroy')->name('destroy'); + Route::get('/{role}', 'show')->name('show'); + Route::post('/{role}', 'update')->name('update'); + Route::delete('/{role}', 'destroy')->name('destroy'); }); }); diff --git a/tests/Feature/Call/StoreTest.php b/tests/Feature/Call/StoreTest.php index c4b6466..71018f3 100644 --- a/tests/Feature/Call/StoreTest.php +++ b/tests/Feature/Call/StoreTest.php @@ -76,11 +76,10 @@ class StoreTest extends TestCase public function test_can_create_a_call(): void { - $operator = User::factory()->create(); - $operator->telephone_id = 'tel-' . $this->faker->unique()->numerify('###'); - $operator->save(); + $operator = User::factory()->create([ + 'telephone_id' => $this->faker->unique()->numerify('###'), + ]); - DB::table('events')->truncate(); $this->artisan('db:seed --class=EventSeeder'); $this->mock(NotificationService::class, function (MockInterface $mock) { diff --git a/tests/Feature/Call/UpdateTest.php b/tests/Feature/Call/UpdateTest.php index f399a7e..a60db06 100644 --- a/tests/Feature/Call/UpdateTest.php +++ b/tests/Feature/Call/UpdateTest.php @@ -7,6 +7,7 @@ use App\Models\Call; use App\Models\Category; use App\Models\Permission; use App\Models\User; +use Database\Seeders\EventSeeder; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithFaker; use Tests\TestCase; @@ -220,8 +221,11 @@ class UpdateTest extends TestCase 'telephone_id' => $telephoneId, ]); + $this->seed(EventSeeder::class); + $category = Category::factory()->create(); $description = $this->faker->sentence; + $response = $this->actingAs($user)->postJson(route('calls.update', $call->id), [ 'category_id' => $category->category_id, 'subcategory_id' => $category->subcategory_id, diff --git a/tests/Feature/Permission/IndexTest.php b/tests/Feature/Permission/IndexTest.php index be3ebd4..ea798bd 100644 --- a/tests/Feature/Permission/IndexTest.php +++ b/tests/Feature/Permission/IndexTest.php @@ -14,7 +14,7 @@ class IndexTest extends TestCase public function test_unauthenticated_user_cannot_access_permission_index(): void { - $response = $this->getJson(route('permissions.list')); + $response = $this->getJson(route('permissions.index')); $response->assertStatus(401); } diff --git a/tests/Feature/Permission/UpdateTest.php b/tests/Feature/Permission/UpdateTest.php index 855832e..b9f8653 100644 --- a/tests/Feature/Permission/UpdateTest.php +++ b/tests/Feature/Permission/UpdateTest.php @@ -14,11 +14,15 @@ class UpdateTest extends TestCase public function test_user_must_be_authenticated(): void { - $response = $this->postJson(route('permissions.store'), []); + $permission = Permission::factory()->create(); + + $response = $this->postJson(route('permissions.update', $permission)); + $response->assertUnauthorized(); } + public function test_name_and_name_fa_fields_are_required(): void { $user = User::factory()->create(); diff --git a/tests/Feature/Role/DeleteTest.php b/tests/Feature/Role/DeleteTest.php new file mode 100644 index 0000000..ddaf5aa --- /dev/null +++ b/tests/Feature/Role/DeleteTest.php @@ -0,0 +1,65 @@ +create(); + $response = $this->postJson(route('roles.destroy', [$role->id])); + + $response->assertUnauthorized(); + } + + public function test_a_role_can_be_deleted() + { + $user = User::factory()->create(); + $role = Role::factory()->create(); + + $permission = Permission::factory([ + 'id' => 2, + 'name' => $this->faker->name + ])->create(); + + $role->syncPermissions($permission); + + $this->assertDatabaseHas('roles', [ + 'id' => $role->id, + 'name' => $role->name, + 'name_fa' => $role->name_fa, + ]); + + $this->assertDatabaseHas('role_has_permissions', [ + 'permission_id' => $permission->id, + 'role_id' => $role->id + ]); + + $response = $this->actingAs($user)->deleteJson(route('roles.destroy', [$role->id])); + + $response->assertOk() + ->assertExactJson([ + 'message' => __('messages.successful') + ]); + + $this->assertDatabaseMissing('roles', [ + 'id' => $role->id, + 'name' => $role->name, + 'name_fa' => $role->name_fa, + ]); + + $this->assertDatabaseMissing('role_has_permissions', [ + 'permission_id' => $permission->id, + 'role_id' => $role->id + ]); + } +} diff --git a/tests/Feature/Role/IndexTest.php b/tests/Feature/Role/IndexTest.php new file mode 100644 index 0000000..95de2e6 --- /dev/null +++ b/tests/Feature/Role/IndexTest.php @@ -0,0 +1,47 @@ +getJson(route('roles.index')); + + $response->assertStatus(401); + } + + public function test_authenticated_user_can_see_roles_index(): void + { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->getJson(route('roles.index',[ + 'filters' => json_encode([]), + 'sorting' => json_encode([]), + ])); + + $response->assertOk(); + + $response->assertJsonStructure([ + 'data' => [ + '*' => [ + 'id', + 'name', + 'name_fa', + ], + ], + 'meta' => [ + 'totalRowCount' + ] + ]); + } + +} diff --git a/tests/Feature/Role/ListTest.php b/tests/Feature/Role/ListTest.php new file mode 100644 index 0000000..d38d271 --- /dev/null +++ b/tests/Feature/Role/ListTest.php @@ -0,0 +1,41 @@ +getJson(route('roles.list')); + $response->assertUnauthorized(); + } + + public function test_roles_list_returns_correct_structure(): void + { + $user = User::factory()->create(); + + Role::factory()->count(3)->create(); + + $response = $this->actingAs($user)->getJson(route('roles.list')); + + $response->assertOk() + ->assertJsonStructure([ + 'data' => [ + '*' => [ + 'id', + 'name', + 'name_fa', + ] + ] + ]); + } +} diff --git a/tests/Feature/Role/ShowTest.php b/tests/Feature/Role/ShowTest.php new file mode 100644 index 0000000..fbffde3 --- /dev/null +++ b/tests/Feature/Role/ShowTest.php @@ -0,0 +1,51 @@ +create(); + $response = $this->postJson(route('roles.show',[$role->id])); + + $response->assertUnauthorized(); + } + + public function test_a_role_can_be_returned_properly():void + { + $user = User::factory()->create(); + + $role = Role::factory()->create(); + + + $permission = Permission::factory()->create([ + 'id' => 2, + 'name' => $this->faker->name, + 'name_fa' => $this->faker->name + ]); + + $role->syncPermissions($permission); + + $role = Role::factory()->create(); + $response = $this->actingAs($user)->getJson(route('roles.show', [$role->id])); + + $response->assertOk() + ->assertJson([ + 'data' => [ + 'id' => $role->id, + 'name' => $role->name, + 'name_fa' => $role->name_fa, + 'permissions' => $role->permissions->pluck('name')->toArray(), + ] + ]); + } +} diff --git a/tests/Feature/Role/StoreTest.php b/tests/Feature/Role/StoreTest.php new file mode 100644 index 0000000..806a175 --- /dev/null +++ b/tests/Feature/Role/StoreTest.php @@ -0,0 +1,125 @@ +postJson(route('roles.store')); + + $response->assertUnauthorized(); + } + + public function test_name_and_name_fa_fields_are_required(): void + { + $user = User::factory()->create(); + + + $response = $this->actingAs($user)->postJson(route('roles.store')); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.required', ['attribute' => 'نام']), + 'name_fa' => __('validation.required', ['attribute' => 'نام فارسی']), + ]); + } + public function test_name_and_name_fa_fields_must_be_unique(): void + { + $user = User::factory()->create(); + + $duplicateName = $this->faker->unique()->slug; + $duplicateNameFa = $this->faker->unique()->word; + + Role::create([ + 'name' => $duplicateName, + 'name_fa' => $duplicateNameFa, + 'guard_name' => 'web', + ]); + + $response = $this->actingAs($user)->postJson(route('roles.store'), [ + 'name' => $duplicateName, + 'name_fa' => $duplicateNameFa, + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.unique', ['attribute' => 'نام']), + 'name_fa' => __('validation.unique', ['attribute' => 'نام فارسی']), + ]); + } + + + public function test_name_and_name_fa_must_be_strings(): void + { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->postJson(route('roles.store'), [ + 'name' =>$this->faker->randomDigit(), + 'name_fa' => $this->faker->randomDigit(), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.string', ['attribute' => 'نام']), + 'name_fa' => __('validation.string', ['attribute' => 'نام فارسی']), + ]); + } + + public function test_name_and_name_fa_must_not_exceed_max_length(): void + { + $user = User::factory()->create(); + + $longString = $this->faker->regexify('[a-zA-Z0-9]{256}'); + + $response = $this->actingAs($user)->postJson(route('roles.store'), [ + 'name' => $longString, + 'name_fa' => $longString, + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.max.string', ['attribute' => 'نام', 'max' => 255]), + 'name_fa' => __('validation.max.string', ['attribute' => 'نام فارسی', 'max' => 255]), + ]); + } + + public function test_valid_role_is_stored_successfully(): void + { + $user = User::factory()->create(); + + $permission = Permission::factory()->create(); + + $payload = [ + 'name' => $this->faker->unique()->slug, + 'name_fa' => $this->faker->unique()->words(2, true), + 'permissions' => [$permission->id], + ]; + + $response = $this->actingAs($user)->postJson(route('roles.store'), $payload); + + $response->assertOk() + ->assertExactJson([ + 'message' => __('messages.successful') + ]); + + $this->assertDatabaseHas('roles', [ + 'name' => $payload['name'], + 'name_fa' => $payload['name_fa'], + ]); + + $this->assertDatabaseHas('role_has_permissions', [ + 'permission_id' => $permission->id, + ]); + } + +} diff --git a/tests/Feature/Role/UpdateTest.php b/tests/Feature/Role/UpdateTest.php new file mode 100644 index 0000000..21c01a7 --- /dev/null +++ b/tests/Feature/Role/UpdateTest.php @@ -0,0 +1,157 @@ +create(); + $response = $this->postJson(route('roles.update',$role)); + + $response->assertUnauthorized(); + } + + public function test_fields_are_required(): void + { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->postJson(route('roles.store')); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.required', ['attribute' => 'نام']), + 'name_fa' => __('validation.required', ['attribute' => 'نام فارسی']), + 'permissions' => __('validation.required', ['attribute' => 'دسترسی ها']), + ]); + } + + public function test_fields_must_be_unique(): void + { + $user = User::factory()->create(); + + $duplicateName = $this->faker->unique()->slug; + $duplicateNameFa = $this->faker->unique()->word; + + Role::create([ + 'name' => $duplicateName, + 'name_fa' => $duplicateNameFa, + 'guard_name' => 'web', + ]); + + $response = $this->actingAs($user)->postJson(route('roles.store'), [ + 'name' => $duplicateName, + 'name_fa' => $duplicateNameFa, + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.unique', ['attribute' => 'نام']), + 'name_fa' => __('validation.unique', ['attribute' => 'نام فارسی']), + ]); + } + + public function test_name_and_name_fa_must_be_strings(): void + { + $user = User::factory()->create(); + $permission = Permission::factory()->create(); + + $response = $this->actingAs($user)->postJson(route('roles.store'), [ + 'name' => 123, + 'name_fa' => 456, + 'permissions' => [$permission->id], + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.string', ['attribute' => 'نام']), + 'name_fa' => __('validation.string', ['attribute' => 'نام فارسی']), + ]); + } + + public function test_name_and_name_fa_must_not_exceed_max_length(): void + { + $user = User::factory()->create(); + $longString = str_repeat('a', 256); + $permission = Permission::factory()->create(); + + $response = $this->actingAs($user)->postJson(route('roles.store'), [ + 'name' => $longString, + 'name_fa' => $longString, + 'permissions' => [$permission->id], + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'name' => __('validation.max.string', ['attribute' => 'نام', 'max' => 255]), + 'name_fa' => __('validation.max.string', ['attribute' => 'نام فارسی', 'max' => 255]), + ]); + } + + public function test_permissions_must_be_array(): void + { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->postJson(route('roles.store'), [ + 'name' => $this->faker->slug, + 'name_fa' => $this->faker->word, + 'permissions' => 1, + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'permissions' => __('validation.array', ['attribute' => 'دسترسی ها']), + ]); + } + + public function test_permissions_values_must_exist(): void + { + $user = User::factory()->create(); + $role = Role::factory()->create(); + + $response = $this->actingAs($user)->postJson(route('roles.update', [$role->id]), [ + 'permissions' => $this->faker->name(), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'permissions' => __('validation.exists', ['attribute' => 'دسترسی ها']), + ]); + } + + public function test_valid_role_is_update_successfully(): void + { + $user = User::factory()->create(); + $permission = Permission::factory()->create(); + + $payload = [ + 'name' => $this->faker->unique()->slug, + 'name_fa' => $this->faker->unique()->words(2, true), + 'permissions' => [$permission->id], + ]; + + $response = $this->actingAs($user)->postJson(route('roles.store'), $payload); + + $response->assertOk() + ->assertExactJson([ + 'message' => __('messages.successful'), + ]); + + $this->assertDatabaseHas('roles', [ + 'name' => $payload['name'], + 'name_fa' => $payload['name_fa'], + ]); + + $this->assertDatabaseHas('role_has_permissions', [ + 'permission_id' => $permission->id, + ]); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index 1b5fd39..8f98a4a 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -7,12 +7,5 @@ use Illuminate\Foundation\Testing\TestCase as BaseTestCase; abstract class TestCase extends BaseTestCase { - - protected function setUp(): void - { - parent::setUp(); - app()->setLocale('fa'); - config(['logging.default' => 'null']); - $this->seed(EventSeeder::class); - } + // } From 16fe0be5553b161cb1803f68bd1ca5d19e4fbdc5 Mon Sep 17 00:00:00 2001 From: joddyabott Date: Wed, 14 May 2025 15:38:33 +0330 Subject: [PATCH 5/5] write test for another items and change some part of the code --- resources/lang/fa/validation.php | 1 + routes/web.php | 4 +- tests/Feature/Call/StoreTest.php | 1 - tests/Feature/Category/ListTest.php | 41 ++ tests/Feature/Permission/DeleteTest.php | 12 +- tests/Feature/Permission/IndexTest.php | 11 +- tests/Feature/Permission/ListTest.php | 10 +- tests/Feature/Permission/SHowTest.php | 9 +- tests/Feature/Permission/StoreTest.php | 2 +- tests/Feature/Permission/UpdateTest.php | 12 +- tests/Feature/Province/ListTest.php | 32 ++ tests/Feature/Role/IndexTest.php | 4 +- tests/Feature/Role/ShowTest.php | 2 +- tests/Feature/Role/StoreTest.php | 2 +- tests/Feature/Role/UpdateTest.php | 26 +- tests/Feature/User/DeleteTest.php | 61 +++ tests/Feature/User/IndexTest.php | 59 +++ tests/Feature/User/ShowTest.php | 76 ++++ tests/Feature/User/StoreTest.php | 508 ++++++++++++++++++++++++ tests/Feature/User/UpdateTest.php | 430 ++++++++++++++++++++ 20 files changed, 1258 insertions(+), 45 deletions(-) create mode 100644 tests/Feature/Category/ListTest.php create mode 100644 tests/Feature/Province/ListTest.php create mode 100644 tests/Feature/User/DeleteTest.php create mode 100644 tests/Feature/User/IndexTest.php create mode 100644 tests/Feature/User/ShowTest.php create mode 100644 tests/Feature/User/StoreTest.php create mode 100644 tests/Feature/User/UpdateTest.php diff --git a/resources/lang/fa/validation.php b/resources/lang/fa/validation.php index 903e525..4eb1325 100644 --- a/resources/lang/fa/validation.php +++ b/resources/lang/fa/validation.php @@ -207,6 +207,7 @@ return [ 'size' => 'حداکثر تعداد', 'extension' => 'کد تلفن', 'caller_id' => 'شماره تماس‌گیرنده', + 'role_id' => 'شناسه نقش ', ], ]; diff --git a/routes/web.php b/routes/web.php index 7784c91..c95f079 100644 --- a/routes/web.php +++ b/routes/web.php @@ -54,8 +54,9 @@ Route::prefix('server')->group(function () { Route::prefix('categories') ->middleware('auth') ->controller(CategoryController::class) + ->name('categories.') ->group(function () { - Route::get('/list', 'list'); + Route::get('/list', 'list')->name('list'); }); Route::middleware('auth') @@ -73,6 +74,7 @@ Route::prefix('server')->group(function () { Route::prefix('provinces') ->controller(ProvinceController::class) + ->name('provinces.') ->group(function () { Route::get('/list', 'list')->name('list'); }); diff --git a/tests/Feature/Call/StoreTest.php b/tests/Feature/Call/StoreTest.php index 71018f3..a1b372c 100644 --- a/tests/Feature/Call/StoreTest.php +++ b/tests/Feature/Call/StoreTest.php @@ -8,7 +8,6 @@ use App\Enums\CallEvents; use App\Services\Notification\NotificationService; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithFaker; -use Illuminate\Support\Facades\DB; use Mockery\MockInterface; use Tests\TestCase; diff --git a/tests/Feature/Category/ListTest.php b/tests/Feature/Category/ListTest.php new file mode 100644 index 0000000..f02aa60 --- /dev/null +++ b/tests/Feature/Category/ListTest.php @@ -0,0 +1,41 @@ +getJson(route('categories.list')); + $response->assertUnauthorized(); + } + public function test_user_can_see_list(): void + { + $user = User::factory()->create(); + $response = $this->actingAs($user)->getJson(route('categories.list')); + + Category::factory()->count(3)->create(); + + $response->assertOk(); + $response->assertJsonStructure([ + 'data' => [ + '*' => [ + 'id', + 'category_id', + 'category_name', + 'subcategory_id', + 'subcategory_name' + ], + ] + ]); + + } +} diff --git a/tests/Feature/Permission/DeleteTest.php b/tests/Feature/Permission/DeleteTest.php index d0b1d4c..d390457 100644 --- a/tests/Feature/Permission/DeleteTest.php +++ b/tests/Feature/Permission/DeleteTest.php @@ -12,12 +12,20 @@ class DeleteTest extends TestCase { use RefreshDatabase, WithFaker; + + public function test_unauthenticated_user_cannot_access(): void + { + $permission = Permission::factory()->create(); + $response = $this->getJson(route('permissions.destroy',[$permission->id])); + $response->assertUnauthorized(); + } + public function test_authenticated_user_can_delete_permission(): void { $user = User::factory()->create(); $permission = Permission::factory()->create(); - $response = $this->actingAs($user)->deleteJson(route('permissions.destroy', $permission)); + $response = $this->actingAs($user)->deleteJson(route('permissions.destroy', [$permission->id])); $response->assertOk() ->assertJson([ @@ -33,7 +41,7 @@ class DeleteTest extends TestCase { $permission = Permission::factory()->create(); - $response = $this->deleteJson(route('permissions.destroy', $permission)); + $response = $this->deleteJson(route('permissions.destroy', [$permission->id])); $response->assertUnauthorized(); } diff --git a/tests/Feature/Permission/IndexTest.php b/tests/Feature/Permission/IndexTest.php index ea798bd..b0971e1 100644 --- a/tests/Feature/Permission/IndexTest.php +++ b/tests/Feature/Permission/IndexTest.php @@ -12,21 +12,16 @@ class IndexTest extends TestCase { use RefreshDatabase, WithFaker; - public function test_unauthenticated_user_cannot_access_permission_index(): void + + public function test_unauthenticated_user_cannot_access(): void { $response = $this->getJson(route('permissions.index')); - - $response->assertStatus(401); + $response->assertUnauthorized(); } public function test_all_permissions_returned_successfully(): void { $user = User::factory() - ->has(Permission::factory()->state([ - 'name' => 'permissions', - 'name_fa' => 'مدیریت دسترسی', - 'guard_name' => 'web', - ])) ->create(); $response = $this->actingAs($user)->getJson(route('permissions.index')); diff --git a/tests/Feature/Permission/ListTest.php b/tests/Feature/Permission/ListTest.php index 036ee3d..79ad422 100644 --- a/tests/Feature/Permission/ListTest.php +++ b/tests/Feature/Permission/ListTest.php @@ -13,11 +13,10 @@ class ListTest extends TestCase { use RefreshDatabase, WithFaker; - public function test_unauthenticated_user_cannot_access_permission_list(): void + public function test_unauthenticated_user_cannot_access(): void { $response = $this->getJson(route('permissions.list')); - - $response->assertStatus(401); + $response->assertUnauthorized(); } @@ -31,11 +30,6 @@ class ListTest extends TestCase public function test_permissions_list_returns_correct_structure(): void { $user = User::factory() - ->has(Permission::factory()->state([ - 'name' => 'manage-permissions', - 'name_fa' => 'مدیریت دسترسی‌ها', - 'guard_name' => 'web', - ])) ->create(); Permission::factory()->count(3)->create(); diff --git a/tests/Feature/Permission/SHowTest.php b/tests/Feature/Permission/SHowTest.php index 4d8997c..d7a4a90 100644 --- a/tests/Feature/Permission/SHowTest.php +++ b/tests/Feature/Permission/SHowTest.php @@ -16,18 +16,13 @@ class SHowTest extends TestCase { $permission = Permission::factory()->create(); - $response = $this->getJson(route('permissions.show', $permission)); + $response = $this->getJson(route('permissions.show', [$permission->id])); $response->assertUnauthorized(); } public function test_permission_show_returns_correct_structure_and_data(): void { $user = User::factory() - ->has(Permission::factory()->state([ - 'name' => 'manage-permissions', - 'name_fa' => 'مدیریت دسترسی‌ها', - 'guard_name' => 'web', - ])) ->create(); $permission = Permission::factory()->create([ @@ -36,7 +31,7 @@ class SHowTest extends TestCase 'guard_name' => 'web', ]); - $response = $this->actingAs($user)->getJson(route('permissions.show', $permission)); + $response = $this->actingAs($user)->getJson(route('permissions.show', [$permission->id])); $response->assertOk() ->assertJson([ diff --git a/tests/Feature/Permission/StoreTest.php b/tests/Feature/Permission/StoreTest.php index 2517eaa..cbd4942 100644 --- a/tests/Feature/Permission/StoreTest.php +++ b/tests/Feature/Permission/StoreTest.php @@ -45,7 +45,7 @@ class StoreTest extends TestCase ]); $response = $this->actingAs($user)->postJson(route('permissions.store'), [ - 'name' => $duplicateName, // حالا واقعا تکراری هستند + 'name' => $duplicateName, 'name_fa' => $duplicateNameFa, ]); diff --git a/tests/Feature/Permission/UpdateTest.php b/tests/Feature/Permission/UpdateTest.php index b9f8653..42b65a7 100644 --- a/tests/Feature/Permission/UpdateTest.php +++ b/tests/Feature/Permission/UpdateTest.php @@ -16,7 +16,7 @@ class UpdateTest extends TestCase { $permission = Permission::factory()->create(); - $response = $this->postJson(route('permissions.update', $permission)); + $response = $this->postJson(route('permissions.update', [$permission->id])); $response->assertUnauthorized(); } @@ -28,7 +28,7 @@ class UpdateTest extends TestCase $user = User::factory()->create(); $permission = Permission::factory()->create(); - $response = $this->actingAs($user)->postJson(route('permissions.update', $permission)); + $response = $this->actingAs($user)->postJson(route('permissions.update', [$permission->id])); $response->assertUnprocessable() ->assertInvalid([ @@ -42,7 +42,7 @@ class UpdateTest extends TestCase $user = User::factory()->create(); $permission = Permission::factory()->create(); - $response = $this->actingAs($user)->postJson(route('permissions.update', $permission), [ + $response = $this->actingAs($user)->postJson(route('permissions.update', [$permission->id]), [ 'name' =>$this->faker->randomDigit(), 'name_fa' => $this->faker->randomDigit(), ]); @@ -61,7 +61,7 @@ class UpdateTest extends TestCase $permission1 = Permission::factory()->create(); $permission2 = Permission::factory()->create(); - $response = $this->actingAs($user)->postJson(route('permissions.update', $permission1), [ + $response = $this->actingAs($user)->postJson(route('permissions.update', [$permission1->id]), [ 'name' => $permission2->name, 'name_fa' => $permission2->name_fa, ]); @@ -80,7 +80,7 @@ class UpdateTest extends TestCase $longString = $this->faker->regexify('[a-zA-Z0-9]{256}'); - $response = $this->actingAs($user)->postJson(route('permissions.update', $permission), [ + $response = $this->actingAs($user)->postJson(route('permissions.update', [$permission->id]), [ 'name' => $longString, 'name_fa' => $longString, ]); @@ -102,7 +102,7 @@ class UpdateTest extends TestCase 'name_fa' => $this->faker->unique()->words(2, true), ]; - $response = $this->actingAs($user)->postJson(route('permissions.update', $permission), $payload); + $response = $this->actingAs($user)->postJson(route('permissions.update', [$permission->id]), $payload); $response->assertOk() ->assertJson([ diff --git a/tests/Feature/Province/ListTest.php b/tests/Feature/Province/ListTest.php new file mode 100644 index 0000000..0f8151d --- /dev/null +++ b/tests/Feature/Province/ListTest.php @@ -0,0 +1,32 @@ +create(); + $response = $this->actingAs($user)->getJson(route('provinces.list')); + + Province::factory()->count(3)->create(); + $response->assertOk(); + $response->assertJsonStructure([ + 'data' => [ + '*' => [ + 'id', + 'name' + ], + ] + ]); + + } +} diff --git a/tests/Feature/Role/IndexTest.php b/tests/Feature/Role/IndexTest.php index 95de2e6..13fdc70 100644 --- a/tests/Feature/Role/IndexTest.php +++ b/tests/Feature/Role/IndexTest.php @@ -12,11 +12,11 @@ class IndexTest extends TestCase { use RefreshDatabase, WithFaker; - public function test_the_user_is_not_authenticated(): void + public function test_unauthenticated_user_cannot_access(): void { $response = $this->getJson(route('roles.index')); - $response->assertStatus(401); + $response->assertUnauthorized(); } public function test_authenticated_user_can_see_roles_index(): void diff --git a/tests/Feature/Role/ShowTest.php b/tests/Feature/Role/ShowTest.php index fbffde3..4edc4b9 100644 --- a/tests/Feature/Role/ShowTest.php +++ b/tests/Feature/Role/ShowTest.php @@ -12,7 +12,7 @@ use Tests\TestCase; class ShowTest extends TestCase { use RefreshDatabase, WithFaker; - public function test_guest_cannot_view_role(): void + public function test_unauthenticated_user_cannot_access(): void { $role = Role::factory()->create(); $response = $this->postJson(route('roles.show',[$role->id])); diff --git a/tests/Feature/Role/StoreTest.php b/tests/Feature/Role/StoreTest.php index 806a175..9d2633f 100644 --- a/tests/Feature/Role/StoreTest.php +++ b/tests/Feature/Role/StoreTest.php @@ -13,7 +13,7 @@ class StoreTest extends TestCase { use RefreshDatabase, WithFaker; - public function test_the_user_is_not_authenticated() + public function test_unauthenticated_user_cannot_access() { $response = $this->postJson(route('roles.store')); diff --git a/tests/Feature/Role/UpdateTest.php b/tests/Feature/Role/UpdateTest.php index 21c01a7..18b68eb 100644 --- a/tests/Feature/Role/UpdateTest.php +++ b/tests/Feature/Role/UpdateTest.php @@ -15,7 +15,7 @@ class UpdateTest extends TestCase public function test_the_user_is_not_authenticated() { $role = Role::factory()->create(); - $response = $this->postJson(route('roles.update',$role)); + $response = $this->postJson(route('roles.update',[$role->id])); $response->assertUnauthorized(); } @@ -23,8 +23,10 @@ class UpdateTest extends TestCase public function test_fields_are_required(): void { $user = User::factory()->create(); + $role = Role::factory()->create(); - $response = $this->actingAs($user)->postJson(route('roles.store')); + + $response = $this->actingAs($user)->postJson(route('roles.update',[$role->id])); $response->assertUnprocessable() ->assertInvalid([ @@ -37,6 +39,8 @@ class UpdateTest extends TestCase public function test_fields_must_be_unique(): void { $user = User::factory()->create(); + $role = Role::factory()->create(); + $duplicateName = $this->faker->unique()->slug; $duplicateNameFa = $this->faker->unique()->word; @@ -47,7 +51,7 @@ class UpdateTest extends TestCase 'guard_name' => 'web', ]); - $response = $this->actingAs($user)->postJson(route('roles.store'), [ + $response = $this->actingAs($user)->postJson(route('roles.update',[$role->id]), [ 'name' => $duplicateName, 'name_fa' => $duplicateNameFa, ]); @@ -61,10 +65,12 @@ class UpdateTest extends TestCase public function test_name_and_name_fa_must_be_strings(): void { + $role = Role::factory()->create(); + $user = User::factory()->create(); $permission = Permission::factory()->create(); - $response = $this->actingAs($user)->postJson(route('roles.store'), [ + $response = $this->actingAs($user)->postJson(route('roles.update',[$role->id]), [ 'name' => 123, 'name_fa' => 456, 'permissions' => [$permission->id], @@ -79,11 +85,13 @@ class UpdateTest extends TestCase public function test_name_and_name_fa_must_not_exceed_max_length(): void { + $role = Role::factory()->create(); + $user = User::factory()->create(); $longString = str_repeat('a', 256); $permission = Permission::factory()->create(); - $response = $this->actingAs($user)->postJson(route('roles.store'), [ + $response = $this->actingAs($user)->postJson(route('roles.update',[$role->id]), [ 'name' => $longString, 'name_fa' => $longString, 'permissions' => [$permission->id], @@ -99,8 +107,10 @@ class UpdateTest extends TestCase public function test_permissions_must_be_array(): void { $user = User::factory()->create(); + $role = Role::factory()->create(); - $response = $this->actingAs($user)->postJson(route('roles.store'), [ + + $response = $this->actingAs($user)->postJson(route('roles.update',[$role->id]), [ 'name' => $this->faker->slug, 'name_fa' => $this->faker->word, 'permissions' => 1, @@ -130,6 +140,8 @@ class UpdateTest extends TestCase public function test_valid_role_is_update_successfully(): void { $user = User::factory()->create(); + $role = Role::factory()->create(); + $permission = Permission::factory()->create(); $payload = [ @@ -138,7 +150,7 @@ class UpdateTest extends TestCase 'permissions' => [$permission->id], ]; - $response = $this->actingAs($user)->postJson(route('roles.store'), $payload); + $response = $this->actingAs($user)->postJson(route('roles.update',[$role->id]), $payload); $response->assertOk() ->assertExactJson([ diff --git a/tests/Feature/User/DeleteTest.php b/tests/Feature/User/DeleteTest.php new file mode 100644 index 0000000..ec3f07b --- /dev/null +++ b/tests/Feature/User/DeleteTest.php @@ -0,0 +1,61 @@ +create(); + $response = $this->getJson(route('users.destroy',[$user->id])); + + $response->assertUnauthorized(); + } + public function test_user_without_permission_cannot_destroy_users(): void + { + $user = User::factory() + ->create(); + + $response = $this->actingAs($user)->getJson(route('users.destroy',[$user->id])); + $response->assertForbidden(); + } + public function test_superAdmin_cant_updated() + { + + $user = User::factory()->create([ + 'username' => "witel", + ]); + + $response = $this->actingAs($user)->getJson(route('users.destroy',[$user->id])); + + $response->assertForbidden(); + + } + public function test_can_delete_a_user() + { + $user = User::factory() + ->has(permission::factory([ + 'name'=> 'manage_users', + "name_fa" => 'مدیریت کاربران', + ])) + ->create(); + + $response = $this->actingAs($user)->deleteJson(route('users.destroy', [$user->id])); + + $response->assertStatus(200) + ->assertExactJson([ + 'message' => __('messages.successful') + ]); + + $this->assertDatabaseMissing('users', [ + 'username' => $user->username + ]); + } +} diff --git a/tests/Feature/User/IndexTest.php b/tests/Feature/User/IndexTest.php new file mode 100644 index 0000000..f4f249d --- /dev/null +++ b/tests/Feature/User/IndexTest.php @@ -0,0 +1,59 @@ +getJson(route('users.index')); + + $response->assertUnauthorized(); + } + public function test_user_without_permission_cannot_see_index(): void + { + $user = User::factory()->create(); + $response = $this->actingAs($user)->getJson(route('users.index')); + $response->assertForbidden(); + } + public function test_all_users_returned_successfully_for_index_user(): void + { + $user = User::factory() + ->has(permission::factory([ + 'name'=> 'manage_users', + "name_fa" => 'مدیریت کاربران', + ])) + ->create(); + User::factory()->count(2)->create(); + $response = $this->actingAs($user)->getJson(route('users.index',[ + 'filters'=> json_encode([]), + 'sortings'=> json_encode([]), + 'relations'=> ['roles:id,name_fa'] + ])); + $response->assertOk(); + $response->assertJsonStructure([ + 'data' => [ + '*' => ['id', + 'full_name', + 'username', + 'province_id', + 'phone_number', + 'national_id', + 'telephone_id', + ], + ], + 'meta' => [ + 'totalRowCount' + ] + ]); + } + +} diff --git a/tests/Feature/User/ShowTest.php b/tests/Feature/User/ShowTest.php new file mode 100644 index 0000000..b531479 --- /dev/null +++ b/tests/Feature/User/ShowTest.php @@ -0,0 +1,76 @@ +create(); + $response = $this->getJson(route('users.show',[$user->id])); + + $response->assertUnauthorized(); + } + public function test_user_without_permission_cannot_show_users(): void + { + $user = User::factory() + ->create(); + + $response = $this->actingAs($user)->getJson(route('users.show',[$user->id])); + $response->assertForbidden(); + } + public function test_superAdmin_cant_updated() + { + + $user = User::factory()->create([ + 'username' => "witel", + ]); + + $response = $this->actingAs($user)->getJson(route('users.show',[$user->id])); + + $response->assertForbidden(); + + } + public function test_user_with_permission_can_show_users(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + $role = Role::factory() + ->has(Permission::factory([ + 'name' => 'test' + ]))->create(); + + $user->assignRole($role->id); + + $response = $this->actingAs($user)->getJson(route('users.show',[$user->id])); + $response->assertJsonStructure([ + 'data' => [ + 'username', + 'full_name', + 'id', + 'gender', + 'email', + 'phone_number', + 'avatar', + 'national_id', + 'position', + 'province_id', + 'province_name', + 'role', + 'telephone_id' + ] + ]); + } +} diff --git a/tests/Feature/User/StoreTest.php b/tests/Feature/User/StoreTest.php new file mode 100644 index 0000000..6d9e9bc --- /dev/null +++ b/tests/Feature/User/StoreTest.php @@ -0,0 +1,508 @@ +getJson(route('users.store')); + + $response->assertUnauthorized(); + } + public function test_user_without_permission_cannot_see_index(): void + { + $user = User::factory()->create(); + $response = $this->actingAs($user)->getJson(route('users.store')); + $response->assertForbidden(); + } + + public function test_fields_are_required() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.store'),[]); + $response->assertUnprocessable() + ->assertInValid([ + 'full_name' => __('validation.required', ['attribute' => 'نام کامل']), + 'username' => __('validation.required', ['attribute' => 'نام کاربری']), + 'position' => __('validation.required', ['attribute' => 'سمت']), + 'gender' => __('validation.required', ['attribute' => 'جنسیت']), + 'national_id' => __('validation.required', ['attribute' => 'کدملی']), + 'phone_number' => __('validation.required', ['attribute' => 'شماره تلفن']), + 'province_id' => __('validation.required', ['attribute' => 'استان']), + 'password' => __('validation.required', ['attribute' => 'رمز عبور']), + 'role_id' => __('validation.required', ['attribute' => 'شناسه نقش ']), + ]); + + } + public function test_gender_should_be_male_or_female() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->name, + 'username' => $this->faker->unique()->userName, + 'position' => $this->faker->jobTitle, + 'gender' => 'other', + 'national_id' => $this->faker->numerify('##########'), + 'phone_number' => $this->faker->numerify('09#########'), + 'province_id' => Province::factory()->create()->id, + 'role_id' => Role::factory()->create()->id, + 'password' => $this->faker->regexify('[A-Za-z]{4}[0-9]{4}') + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'gender' => __('validation.in', ['attribute' => 'جنسیت']) + ]); + } + + public function test_phone_number_should_match_regex() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->text, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '01' . $this->faker->numberBetween(100000000, 999999999), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'phone_number' => __('validation.regex', ['attribute' => 'شماره تلفن']) + ]); + } + + public function test_password_should_match_the_regex() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->text, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '09' . $this->faker->numberBetween(100000000, 999999999), + 'province_id' => Province::factory()->create()->id, + 'password' => $this->faker->lexify('?????'), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'password' => __('validation.regex', ['attribute' => 'رمز عبور']) + ]); + } + public function test_fields_should_be_string() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->numberBetween(10, 20), + 'username' => $this->faker->numberBetween(10, 20), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'full_name' => __('validation.string', ['attribute' => 'نام کامل']), + 'username' => __('validation.string', ['attribute' => 'نام کاربری']), + ]); + } + public function test_avatar_should_be_less_than_2048() + { + $avatar = UploadedFile::fake()->image('file.png')->size('3000'); + + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->text, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '09' . $this->faker->numberBetween(100000000, 999999999), + 'province_id' => Province::factory()->create()->id, + 'password' => $this->faker->numberBetween(1000, 9999) . $this->faker->lexify('?????'), + 'roles' => Role::factory()->create()->id, + 'avatar' => $avatar + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'avatar' => __('validation.max.file', ['attribute' => 'آواتار', 'max' => 2048]) + ]); + } + + public function test_full_name_must_not_exceed_max_length():void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + $longString = $this->faker->regexify('[a-zA-Z0-9]{256}'); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $longString, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '09' . $this->faker->numberBetween(100000000, 999999999), + 'province_id' => Province::factory()->create()->id, + 'password' => $this->faker->numberBetween(1000, 9999) . $this->faker->lexify('?????'), + 'role_id' => Role::factory()->create()->id, + + ]); + $response->assertUnprocessable() + ->assertInvalid([ + 'full_name' => __('validation.max.string', ['attribute' => 'نام کامل', 'max' => 255]), + ]); + } + + public function test_fields_id_should_be_unique() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + $existingPhone = '09' .$this->faker->numberBetween(100000000, 999999999); + $existingEmail = $this->faker->email; + $existingUser = $this->faker->name; + $existingNational = $this->faker->numberBetween(1000000000, 9999999999); + + User::factory()->create([ + 'phone_number' => $existingPhone, + 'national_id' => $existingNational, + 'username' => $existingUser, + 'email' => $existingEmail, + ]); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->text, + 'username' =>$existingUser, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' =>$existingNational, + 'phone_number' => $existingPhone, + 'province_id' => Province::factory()->create()->id, + 'password' => $this->faker->numberBetween(1000, 9999) . $this->faker->lexify('?????'), + 'role_id' => Role::factory()->create()->id, + 'email' =>$existingEmail, + ]); + + $response->assertJsonValidationErrors([ + 'phone_number' => __('validation.unique', ['attribute' => 'شماره تلفن']), + 'email' => __('validation.unique', ['attribute' => 'ایمیل']), + 'username' => __('validation.unique', ['attribute' => 'نام کاربری']), + 'national_id' => __('validation.unique', ['attribute' => 'کدملی']), + ]); + } + + public function test_password_should_have_minimum_8_characters(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->name, + 'username' => $this->faker->unique()->userName, + 'position' => $this->faker->jobTitle, + 'gender' => $this->faker->randomElement(['male', 'female']), + 'national_id' => $this->faker->numerify('##########'), + 'phone_number' => $this->faker->numerify('09#########'), + 'province_id' => Province::factory()->create()->id, + 'password' => 'abc123', + 'role_id' => Role::factory()->create()->id, + 'email' => $this->faker->unique()->safeEmail, + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'password' => __('validation.min.string', ['attribute' => 'رمز عبور', 'min' => 8]), + ]); + } + public function test_national_id_should_be_10_digits() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->text, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(10000, 99999), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'national_id' => __('validation.digits', [ + 'attribute' => 'کدملی', + 'digits' => 10, + ]) + ]); + } + public function test_phone_number_should_be_11_digits() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->text, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '09' . $this->faker->numberBetween(1000000, 9999999), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'phone_number' => __('validation.digits', [ + 'attribute' => 'شماره تلفن', + 'digits' => 11 + ]) + ]); + } + + public function test_role_should_exist_in_roles_table() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + $invalidRoleId = 9999; + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->text, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '09' . $this->faker->numberBetween(100000000, 999999999), + 'province_id' => Province::factory()->create()->id, + 'password' => $this->faker->numberBetween(1000, 9999) . $this->faker->lexify('?????'), + 'role_id' => $invalidRoleId , + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'role_id' => __('validation.exists', ['attribute' => 'شناسه نقش ']) + ]); + } + public function test_province_id_should_be_exist_in_province_table() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + $invalidProvince = $this->faker->numberBetween(100000000, 999999999); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ 'full_name' => $this->faker->text, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '09' . $this->faker->numberBetween(100000000, 999999999), + 'province_id' => $invalidProvince, + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'province_id' => __('validation.exists', ['attribute' => 'استان']) + ]); + } + + public function test_email_should_have_valid_format(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->name, + 'username' => $this->faker->unique()->userName, + 'position' => $this->faker->jobTitle, + 'gender' => $this->faker->randomElement(['male', 'female']), + 'national_id' => $this->faker->numerify('##########'), + 'phone_number' => $this->faker->numerify('09#########'), + 'province_id' => Province::factory()->create()->id, + 'password' => 'abc12345', + 'role_id' => Role::factory()->create()->id, + 'email' => 'not-an-email', + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'email' => __('validation.email', ['attribute' => 'ایمیل']), + ]); + } + public function test_avatar_should_be_valid_mime_type(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $invalidFile = UploadedFile::fake()->create('avatar.txt', 100, 'text/plain'); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->name, + 'username' => $this->faker->unique()->userName, + 'position' => $this->faker->jobTitle, + 'gender' => $this->faker->randomElement(['male', 'female']), + 'national_id' => $this->faker->numerify('##########'), + 'phone_number' => $this->faker->numerify('09#########'), + 'province_id' => Province::factory()->create()->id, + 'password' => $this->faker->regexify('[A-Za-z]{4}[0-9]{4}'), + 'role_id' => Role::factory()->create()->id, + 'email' => $this->faker->unique()->safeEmail, + 'avatar' => $invalidFile, + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'avatar' => __('validation.mimes', ['attribute' => 'آواتار', 'values' => 'png, jpg, pdf']), + ]); + } + public function test_phone_number_must_be_numeric(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + $invalidPhone = $this->faker->word(); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->name, + 'username' => $this->faker->unique()->userName, + 'position' => $this->faker->jobTitle, + 'gender' => $this->faker->randomElement(['male', 'female']), + 'national_id' => $this->faker->numerify('##########'), + 'phone_number' =>$invalidPhone , + 'province_id' => Province::factory()->create()->id, + 'password' => 'abc12345', + 'role_id' => Role::factory()->create()->id, + 'email' => 'not-an-email', + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'phone_number' => __('validation.numeric', ['attribute' => 'شماره تلفن']), + ]); + + } + + + public function test_can_store_an_user() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + $username = $this->faker->userName; + + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->name, + 'username' => $username, + 'position' => $this->faker->lexify('?????'), + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '09' . $this->faker->numberBetween(100000000, 999999999), + 'province_id' => Province::factory()->create()->id, + 'password' => $this->faker->numberBetween(1000, 9999) . $this->faker->lexify('?????'), + 'role_id' => Role::factory()->create()->id, + 'telephone_id' => '01-1' + ]); + + $response->assertStatus(200) + ->assertExactJson([ + 'message' => __('messages.successful') + ]); + + $this->assertDatabaseHas('users', [ + 'username' => $username + ]); + } + + + + + + +} diff --git a/tests/Feature/User/UpdateTest.php b/tests/Feature/User/UpdateTest.php new file mode 100644 index 0000000..58baedd --- /dev/null +++ b/tests/Feature/User/UpdateTest.php @@ -0,0 +1,430 @@ +create(); + $response = $this->getJson(route('users.update',[$user->id])); + + $response->assertUnauthorized(); + } + public function test_user_without_permission_cannot_see_index(): void + { + $user = User::factory()->create(); + $response = $this->actingAs($user)->getJson(route('users.update',[$user->id])); + $response->assertForbidden(); + } + public function test_superAdmin_cant_updated() + { + + $user = User::factory()->create([ + 'username' => "witel", + ]); + + $response = $this->actingAs($user)->getJson(route('users.update',[$user->id])); + + $response->assertForbidden(); + + } + public function test_fields_are_required() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.update',[$user->id]),[]); + $response->assertUnprocessable() + ->assertInValid([ + 'full_name' => __('validation.required', ['attribute' => 'نام کامل']), + 'username' => __('validation.required', ['attribute' => 'نام کاربری']), + 'position' => __('validation.required', ['attribute' => 'سمت']), + 'gender' => __('validation.required', ['attribute' => 'جنسیت']), + 'national_id' => __('validation.required', ['attribute' => 'کدملی']), + 'phone_number' => __('validation.required', ['attribute' => 'شماره تلفن']), + 'province_id' => __('validation.required', ['attribute' => 'استان']), + 'role_id' => __('validation.required', ['attribute' => 'شناسه نقش ']), + ]); + + } + public function test_gender_should_be_male_or_female() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.update',[$user->id]), [ + 'full_name' => $this->faker->name, + 'username' => $this->faker->unique()->userName, + 'position' => $this->faker->jobTitle, + 'gender' => 'other', + 'national_id' => $this->faker->numerify('##########'), + 'phone_number' => $this->faker->numerify('09#########'), + 'province_id' => Province::factory()->create()->id, + 'role_id' => Role::factory()->create()->id, + 'password' => $this->faker->regexify('[A-Za-z]{4}[0-9]{4}') + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'gender' => __('validation.in', ['attribute' => 'جنسیت']) + ]); + } + + public function test_phone_number_should_match_regex() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.update',[$user->id]), [ + 'full_name' => $this->faker->text, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '01' . $this->faker->numberBetween(100000000, 999999999), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'phone_number' => __('validation.regex', ['attribute' => 'شماره تلفن']) + ]); + } + + public function test_fields_should_be_string() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.update',[$user->id]), [ + 'full_name' => $this->faker->numberBetween(10, 20), + 'username' => $this->faker->numberBetween(10, 20), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'full_name' => __('validation.string', ['attribute' => 'نام کامل']), + 'username' => __('validation.string', ['attribute' => 'نام کاربری']), + ]); + } + public function test_avatar_should_be_less_than_2048() + { + $avatar = UploadedFile::fake()->image('file.png')->size('3000'); + + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.update',[$user->id]), [ + 'full_name' => $this->faker->text, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '09' . $this->faker->numberBetween(100000000, 999999999), + 'province_id' => Province::factory()->create()->id, + 'password' => $this->faker->numberBetween(1000, 9999) . $this->faker->lexify('?????'), + 'roles' => Role::factory()->create()->id, + 'avatar' => $avatar + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'avatar' => __('validation.max.file', ['attribute' => 'آواتار', 'max' => 2048]) + ]); + } + + public function test_full_name_must_not_exceed_max_length():void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + $longString = $this->faker->regexify('[a-zA-Z0-9]{256}'); + + $response = $this->actingAs($user)->postJson(route('users.update',[$user->id]), [ + 'full_name' => $longString, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '09' . $this->faker->numberBetween(100000000, 999999999), + 'province_id' => Province::factory()->create()->id, + 'password' => $this->faker->numberBetween(1000, 9999) . $this->faker->lexify('?????'), + 'role_id' => Role::factory()->create()->id, + + ]); + $response->assertUnprocessable() + ->assertInvalid([ + 'full_name' => __('validation.max.string', ['attribute' => 'نام کامل', 'max' => 255]), + ]); + } + public function test_national_id_should_be_10_digits() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.update',[$user->id]), [ + 'full_name' => $this->faker->text, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(10000, 99999), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'national_id' => __('validation.digits', [ + 'attribute' => 'کدملی', + 'digits' => 10, + ]) + ]); + } + public function test_phone_number_should_be_11_digits() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.update',[$user->id]), [ + 'full_name' => $this->faker->text, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '09' . $this->faker->numberBetween(1000000, 9999999), + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'phone_number' => __('validation.digits', [ + 'attribute' => 'شماره تلفن', + 'digits' => 11 + ]) + ]); + } + + public function test_role_should_exist_in_roles_table() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + $invalidRoleId = 9999; + + $response = $this->actingAs($user)->postJson(route('users.update',[$user->id]), [ + 'full_name' => $this->faker->text, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '09' . $this->faker->numberBetween(100000000, 999999999), + 'province_id' => Province::factory()->create()->id, + 'password' => $this->faker->numberBetween(1000, 9999) . $this->faker->lexify('?????'), + 'role_id' => $invalidRoleId , + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'role_id' => __('validation.exists', ['attribute' => 'شناسه نقش ']) + ]); + } + public function test_province_id_should_be_exist_in_province_table() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + $invalidProvince = $this->faker->numberBetween(100000000, 999999999); + + $response = $this->actingAs($user)->postJson(route('users.update',[$user->id]), [ 'full_name' => $this->faker->text, + 'username' => $this->faker->text, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '09' . $this->faker->numberBetween(100000000, 999999999), + 'province_id' => $invalidProvince, + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'province_id' => __('validation.exists', ['attribute' => 'استان']) + ]); + } + + public function test_email_should_have_valid_format(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $response = $this->actingAs($user)->postJson(route('users.update',[$user->id]), [ + 'full_name' => $this->faker->name, + 'username' => $this->faker->unique()->userName, + 'position' => $this->faker->jobTitle, + 'gender' => $this->faker->randomElement(['male', 'female']), + 'national_id' => $this->faker->numerify('##########'), + 'phone_number' => $this->faker->numerify('09#########'), + 'province_id' => Province::factory()->create()->id, + 'password' => 'abc12345', + 'role_id' => Role::factory()->create()->id, + 'email' => 'not-an-email', + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'email' => __('validation.email', ['attribute' => 'ایمیل']), + ]); + } + public function test_avatar_should_be_valid_mime_type(): void + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $invalidFile = UploadedFile::fake()->create('avatar.txt', 100, 'text/plain'); + + $response = $this->actingAs($user)->postJson(route('users.update',[$user->id]), [ + 'full_name' => $this->faker->name, + 'username' => $this->faker->unique()->userName, + 'position' => $this->faker->jobTitle, + 'gender' => $this->faker->randomElement(['male', 'female']), + 'national_id' => $this->faker->numerify('##########'), + 'phone_number' => $this->faker->numerify('09#########'), + 'province_id' => Province::factory()->create()->id, + 'password' => $this->faker->regexify('[A-Za-z]{4}[0-9]{4}'), + 'role_id' => Role::factory()->create()->id, + 'email' => $this->faker->unique()->safeEmail, + 'avatar' => $invalidFile, + ]); + + $response->assertUnprocessable() + ->assertInvalid([ + 'avatar' => __('validation.mimes', ['attribute' => 'آواتار', 'values' => 'png, jpg, pdf']), + ]); + } + public function test_fields_id_should_be_unique() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + $existingPhone = '09' .$this->faker->numberBetween(100000000, 999999999); + $existingEmail = $this->faker->email; + $existingUser = $this->faker->name; + $existingNational = $this->faker->numberBetween(1000000000, 9999999999); + + User::factory()->create([ + 'phone_number' => $existingPhone, + 'national_id' => $existingNational, + 'username' => $existingUser, + 'email' => $existingEmail, + ]); + + $response = $this->actingAs($user)->postJson(route('users.store'), [ + 'full_name' => $this->faker->text, + 'username' =>$existingUser, + 'position' => $this->faker->text, + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' =>$existingNational, + 'phone_number' => $existingPhone, + 'province_id' => Province::factory()->create()->id, + 'password' => $this->faker->numberBetween(1000, 9999) . $this->faker->lexify('?????'), + 'role_id' => Role::factory()->create()->id, + 'email' =>$existingEmail, + ]); + + $response->assertJsonValidationErrors([ + 'phone_number' => __('validation.unique', ['attribute' => 'شماره تلفن']), + 'email' => __('validation.unique', ['attribute' => 'ایمیل']), + 'username' => __('validation.unique', ['attribute' => 'نام کاربری']), + 'national_id' => __('validation.unique', ['attribute' => 'کدملی']), + ]); + } + public function test_can_update_an_user() + { + $user = User::factory() + ->has(Permission::factory([ + 'name' => 'manage_users', + 'name_fa' => 'مدیریت کاربران' + ])) + ->create(); + + $username = $this->faker->userName; + + $response = $this->actingAs($user)->postJson(route('users.update',[$user->id]), [ + 'full_name' => $this->faker->name, + 'username' => $username, + 'position' => $this->faker->lexify('?????'), + 'gender' => $this->faker->randomElement(['female', 'male']), + 'national_id' => $this->faker->numberBetween(1000000000, 9999999999), + 'phone_number' => '09' . $this->faker->numberBetween(100000000, 999999999), + 'province_id' => Province::factory()->create()->id, + 'role_id' => Role::factory()->create()->id, + 'telephone_id' => '01-1' + ]); + + $response->assertStatus(200) + ->assertExactJson([ + 'message' => __('messages.successful') + ]); + + $this->assertDatabaseHas('users', [ + 'username' => $username + ]); + } + + +}