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,