add api tests

This commit is contained in:
root
2026-06-08 02:08:04 -04:00
parent 8ca24ef03f
commit 79024235ef
28 changed files with 1446 additions and 130 deletions
@@ -0,0 +1,249 @@
<?php
namespace Tests\Feature\Api\V1\PrintRequests;
use App\Models\PrintRequest;
use App\Models\Role;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
class PrintRequestsWorkflowTest extends TestCase
{
use RefreshDatabase;
public function test_teacher_can_create_hand_copy_request_and_admin_can_advance_statuses(): void
{
$teacher = $this->createUserWithRole('teacher');
$admin = $this->createUserWithRole('administrator');
$classSectionId = $this->seedClassSection();
$this->actingAs($teacher, 'api');
$createResponse = $this->postJson('/api/v1/print-requests/hand-copy', [
'class_id' => $classSectionId,
'num_copies' => 3,
'required_by' => '2026-09-13 11:00:00',
'pickup_method' => 'Self Pickup',
]);
$createResponse
->assertCreated()
->assertJsonPath('status', true)
->assertJsonPath('data.print_request.status', 'not_assigned');
$requestId = (int) $createResponse->json('data.print_request.id');
$this->assertDatabaseHas('print_requests', [
'id' => $requestId,
'teacher_id' => $teacher->id,
'class_id' => $classSectionId,
'file_path' => '',
'num_copies' => 3,
'status' => 'not_assigned',
]);
$this->actingAs($admin, 'api');
foreach (['assigned', 'done', 'delivered'] as $status) {
$this->patchJson("/api/v1/print-requests/{$requestId}/status", [
'status' => $status,
])
->assertOk()
->assertJsonPath('status', true)
->assertJsonPath('data.print_request.status', $status);
}
$this->assertDatabaseHas('print_requests', [
'id' => $requestId,
'admin_id' => $admin->id,
'status' => 'delivered',
]);
}
public function test_admin_status_rejects_invalid_transition(): void
{
$teacher = $this->createUserWithRole('teacher');
$admin = $this->createUserWithRole('administrator');
$request = $this->seedPrintRequest($teacher, ['status' => 'delivered']);
$this->actingAs($admin, 'api');
$this->patchJson("/api/v1/print-requests/{$request->id}/status", [
'status' => 'assigned',
])
->assertUnprocessable()
->assertJsonPath('status', false);
$this->assertDatabaseHas('print_requests', [
'id' => $request->id,
'status' => 'delivered',
]);
}
public function test_teacher_routes_reject_non_teacher_roles_and_admin_routes_reject_teacher_roles(): void
{
$parent = $this->createUserWithRole('parent');
$teacher = $this->createUserWithRole('teacher');
$this->actingAs($parent, 'api');
$this->getJson('/api/v1/print-requests/teacher')
->assertForbidden();
$this->actingAs($teacher, 'api');
$this->getJson('/api/v1/print-requests/admin')
->assertForbidden();
}
public function test_teacher_cannot_update_delete_or_download_another_teachers_request(): void
{
$owner = $this->createUserWithRole('teacher');
$intruder = $this->createUserWithRole('teacher');
$request = $this->seedPrintRequest($owner, [
'status' => 'not_assigned',
'file_path' => 'missing-file.pdf',
]);
$this->actingAs($intruder, 'api');
$this->patchJson("/api/v1/print-requests/{$request->id}", [
'num_copies' => 8,
'required_by' => '2026-09-20 11:00:00',
'pickup_method' => 'Self Pickup',
])->assertForbidden();
$this->deleteJson("/api/v1/print-requests/{$request->id}")
->assertForbidden();
$this->getJson("/api/v1/print-requests/{$request->id}/file")
->assertForbidden();
$this->assertDatabaseHas('print_requests', [
'id' => $request->id,
'teacher_id' => $owner->id,
'num_copies' => 1,
]);
}
public function test_teacher_cannot_delete_request_after_processing_has_started(): void
{
$teacher = $this->createUserWithRole('teacher');
$request = $this->seedPrintRequest($teacher, ['status' => 'done']);
$this->actingAs($teacher, 'api');
$this->deleteJson("/api/v1/print-requests/{$request->id}")
->assertBadRequest()
->assertJsonPath('status', false);
$this->assertDatabaseHas('print_requests', [
'id' => $request->id,
'status' => 'done',
]);
}
public function test_upload_requires_valid_file_and_page_selection_format(): void
{
$teacher = $this->createUserWithRole('teacher');
$classSectionId = $this->seedClassSection();
$this->actingAs($teacher, 'api');
$response = $this->post('/api/v1/print-requests', [
'file' => UploadedFile::fake()->create('lesson.pdf', 12, 'application/pdf'),
'class_id' => $classSectionId,
'num_copies' => 1,
'required_by' => '2026-09-13 11:00:00',
'pickup_method' => 'Self Pickup',
'page_selection' => 'one through five',
]);
$response
->assertUnprocessable()
->assertJsonPath('status', false)
->assertJsonStructure(['errors' => ['page_selection']]);
}
public function test_teacher_can_upload_and_download_own_file_and_admin_can_download_any_request_file(): void
{
$teacher = $this->createUserWithRole('teacher');
$admin = $this->createUserWithRole('administrator');
$classSectionId = $this->seedClassSection();
$this->actingAs($teacher, 'api');
$createResponse = $this->post('/api/v1/print-requests', [
'file' => UploadedFile::fake()->create('lesson.pdf', 12, 'application/pdf'),
'class_id' => $classSectionId,
'num_copies' => 2,
'required_by' => '2026-09-13 11:00:00',
'pickup_method' => 'Self Pickup',
'page_selection' => '1-3,5',
]);
$createResponse
->assertCreated()
->assertJsonPath('status', true);
$requestId = (int) $createResponse->json('data.print_request.id');
$this->actingAs($teacher, 'api');
$this->get("/api/v1/print-requests/{$requestId}/file")
->assertOk();
$this->actingAs($admin, 'api');
$this->get("/api/v1/print-requests/{$requestId}/file")
->assertOk();
}
private function createUserWithRole(string $roleName): User
{
$role = Role::query()->firstOrCreate(
['name' => $roleName],
[
'slug' => $roleName,
'description' => ucfirst(str_replace('_', ' ', $roleName)),
'dashboard_route' => $roleName === 'teacher' ? 'teacher/classes' : 'administrator/administratordashboard',
'priority' => 1,
'is_active' => 1,
]
);
$user = User::factory()->create([
'status' => 'Active',
'is_verified' => 1,
'is_suspended' => 0,
'email' => $roleName . '-print-request-' . str_replace('.', '', uniqid('', true)) . '@example.test',
]);
$user->roles()->syncWithoutDetaching([$role->id]);
return $user->fresh() ?? $user;
}
private function seedClassSection(): int
{
DB::table('classSection')->insert([
'class_id' => 1,
'class_section_id' => 9901,
'class_section_name' => 'Print Request Test Class',
'semester' => 'Fall',
'school_year' => '2026-2027',
]);
return 9901;
}
/**
* @param array<string, mixed> $overrides
*/
private function seedPrintRequest(User $teacher, array $overrides = []): PrintRequest
{
return PrintRequest::query()->create(array_merge([
'teacher_id' => $teacher->id,
'admin_id' => null,
'class_id' => $this->seedClassSection(),
'file_path' => '',
'page_selection' => null,
'num_copies' => 1,
'required_by' => '2026-09-13 11:00:00',
'pickup_method' => 'Self Pickup',
'status' => 'not_assigned',
], $overrides));
}
}
@@ -33,7 +33,13 @@ class RoleSwitcherControllerTest extends TestCase
public function test_switch_sets_role(): void
{
$user = $this->seedUser();
$this->seedRole();
$roleId = $this->seedRole();
DB::table('user_roles')->insert([
'user_id' => $user->id,
'role_id' => $roleId,
]);
Sanctum::actingAs($user);
$response = $this->postJson('/api/v1/role-switcher/switch', [
@@ -52,6 +58,55 @@ class RoleSwitcherControllerTest extends TestCase
$response->assertStatus(401);
}
public function test_switch_rejects_role_that_user_does_not_have(): void
{
$user = $this->seedUser();
$this->seedRole();
$teacherRoleId = DB::table('roles')->insertGetId([
'name' => 'teacher',
'slug' => 'teacher',
'description' => 'Teacher',
'dashboard_route' => 'teacher/classes',
'priority' => 2,
'is_active' => 1,
'created_at' => now(),
'updated_at' => now(),
]);
DB::table('user_roles')->insert([
'user_id' => $user->id,
'role_id' => $teacherRoleId,
]);
Sanctum::actingAs($user);
$this->postJson('/api/v1/role-switcher/switch', [
'role' => 'admin',
])
->assertForbidden()
->assertJsonPath('status', false);
}
public function test_switch_validates_empty_role_payload(): void
{
$user = $this->seedUser();
$this->seedRole();
Sanctum::actingAs($user);
$this->postJson('/api/v1/role-switcher/switch', [])
->assertUnprocessable();
}
public function test_index_returns_not_found_when_authenticated_user_has_no_roles(): void
{
$user = $this->seedUser();
Sanctum::actingAs($user);
$this->getJson('/api/v1/role-switcher')
->assertNotFound()
->assertJsonPath('status', false);
}
private function seedUser(): User
{
$userId = DB::table('users')->insertGetId([