| <?php |
|
|
| use Illuminate\Http\Client\Request as HttpRequest; |
| use Illuminate\Http\UploadedFile; |
| use Illuminate\Support\Facades\Http; |
| use Inertia\Testing\AssertableInertia as Assert; |
|
|
| function lecturerAuthUserCookie(): string |
| { |
| return json_encode([ |
| 'email' => 'lecturer@example.com', |
| 'id' => 10, |
| 'identity_number' => 'D12345', |
| 'name' => 'Dosen', |
| 'role' => 'lecturer', |
| 'status' => 'active', |
| ], JSON_THROW_ON_ERROR); |
| } |
|
|
| test('dosen routes redirect guests to login', function () { |
| $this->get(route('dosen')) |
| ->assertRedirect(route('login')); |
| }); |
|
|
| test('dosen dashboard page can be rendered', function () { |
| config(['services.rag.base_url' => 'https://rag.test/api/v1']); |
|
|
| Http::fake([ |
| 'https://rag.test/api/v1/courses/101/documents' => Http::response([ |
| 'data' => [ |
| [ |
| 'course_id' => '101', |
| 'created_at' => '2026-05-01T10:00:00Z', |
| 'file_size' => 1200, |
| 'file_type' => 'pdf', |
| 'filename' => 'materi.pdf', |
| 'id' => 'doc-1', |
| 'status' => 'ready', |
| 'updated_at' => '2026-05-02T10:00:00Z', |
| 'uploaded_by' => 'dosen-1', |
| ], |
| ], |
| ]), |
| 'https://rag.test/api/v1/courses*' => Http::response([ |
| 'data' => [ |
| [ |
| 'description' => 'Materi dasar algoritma', |
| 'id' => 101, |
| 'title' => 'Algoritma & Pemrograman', |
| ], |
| ], |
| 'limit' => 100, |
| 'page' => 1, |
| 'total' => 1, |
| ]), |
| ]); |
|
|
| $this->withCookie('sevima_raghub_auth_token', 'token') |
| ->withCookie('sevima_raghub_auth_user', lecturerAuthUserCookie()) |
| ->get(route('dosen')) |
| ->assertOk() |
| ->assertInertia(fn (Assert $page) => $page |
| ->component('dosen') |
| ->where('backendMessage', null) |
| ->has('knowledgeBases', 1) |
| ->where('knowledgeBases.0.id', '101') |
| ->where('knowledgeBases.0.name', 'Algoritma & Pemrograman') |
| ->where('knowledgeBases.0.documentCount', 1) |
| ->where('knowledgeBases.0.failedDocumentCount', 0) |
| ->where('knowledgeBases.0.updatedAt', '2026-05-02')); |
|
|
| Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'GET' |
| && str_starts_with($request->url(), 'https://rag.test/api/v1/courses?') |
| && $request->hasHeader('Authorization', 'Bearer token')); |
| }); |
|
|
| test('dosen settings page can be rendered', function () { |
| $this->withCookie('sevima_raghub_auth_token', 'token') |
| ->withCookie('sevima_raghub_auth_user', lecturerAuthUserCookie()) |
| ->get(route('dosen.pengaturan')) |
| ->assertOk() |
| ->assertInertia(fn (Assert $page) => $page->component('dosen/pengaturan')); |
| }); |
|
|
| test('dosen course detail page can be rendered', function () { |
| config(['services.rag.base_url' => 'https://rag.test/api/v1']); |
|
|
| Http::fake([ |
| 'https://rag.test/api/v1/courses/101/documents' => Http::response([ |
| 'data' => [ |
| [ |
| 'course_id' => '101', |
| 'created_at' => '2026-05-01T10:00:00Z', |
| 'file_size' => 1200, |
| 'file_type' => 'pdf', |
| 'filename' => 'materi.pdf', |
| 'id' => 'doc-1', |
| 'status' => 'ready', |
| 'updated_at' => '2026-05-02T10:00:00Z', |
| 'uploaded_by' => 'dosen-1', |
| ], |
| ], |
| ]), |
| 'https://rag.test/api/v1/courses/101' => Http::response([ |
| 'description' => 'Materi dasar algoritma', |
| 'id' => 101, |
| 'title' => 'Algoritma & Pemrograman', |
| ]), |
| ]); |
|
|
| $this->withCookie('sevima_raghub_auth_token', 'token') |
| ->withCookie('sevima_raghub_auth_user', lecturerAuthUserCookie()) |
| ->get(route('dosen.show', ['courseId' => '101'])) |
| ->assertOk() |
| ->assertInertia(fn (Assert $page) => $page |
| ->component('dosen-detail') |
| ->where('backendMessage', null) |
| ->where('courseId', '101') |
| ->where('course.id', 101) |
| ->where('course.title', 'Algoritma & Pemrograman') |
| ->has('documents', 1) |
| ->where('documents.0.id', 'doc-1') |
| ->where('documents.0.filename', 'materi.pdf')); |
|
|
| Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'GET' |
| && $request->url() === 'https://rag.test/api/v1/courses/101' |
| && $request->hasHeader('Authorization', 'Bearer token')); |
|
|
| Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'GET' |
| && $request->url() === 'https://rag.test/api/v1/courses/101/documents' |
| && $request->hasHeader('Authorization', 'Bearer token')); |
| }); |
|
|
| test('dosen course can be created through laravel proxy', function () { |
| config(['services.rag.base_url' => 'https://rag.test/api/v1']); |
|
|
| Http::fake([ |
| 'https://rag.test/api/v1/courses' => Http::response([ |
| 'description' => 'Materi dasar algoritma', |
| 'id' => 101, |
| 'title' => 'Algoritma & Pemrograman', |
| ], 201), |
| ]); |
|
|
| $this->withCookie('sevima_raghub_auth_token', 'token') |
| ->withCookie('sevima_raghub_auth_user', lecturerAuthUserCookie()) |
| ->from(route('dosen')) |
| ->post(route('dosen.courses.store'), [ |
| 'description' => 'Materi dasar algoritma', |
| 'title' => 'Algoritma & Pemrograman', |
| ]) |
| ->assertRedirect(route('dosen')) |
| ->assertSessionHasNoErrors(); |
|
|
| Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'POST' |
| && $request->url() === 'https://rag.test/api/v1/courses' |
| && $request->hasHeader('Authorization', 'Bearer token') |
| && $request['title'] === 'Algoritma & Pemrograman' |
| && $request['description'] === 'Materi dasar algoritma'); |
| }); |
|
|
| test('dosen course create uses backend error message', function () { |
| config(['services.rag.base_url' => 'https://rag.test/api/v1']); |
|
|
| Http::fake([ |
| 'https://rag.test/api/v1/courses' => Http::response([ |
| 'message' => 'Course already exists.', |
| ], 422), |
| ]); |
|
|
| $this->withCookie('sevima_raghub_auth_token', 'token') |
| ->withCookie('sevima_raghub_auth_user', lecturerAuthUserCookie()) |
| ->from(route('dosen')) |
| ->post(route('dosen.courses.store'), [ |
| 'title' => 'Algoritma & Pemrograman', |
| ]) |
| ->assertRedirect(route('dosen')) |
| ->assertSessionHasErrors(['course' => 'Course already exists.']); |
| }); |
|
|
| test('dosen course can be updated through laravel proxy', function () { |
| config(['services.rag.base_url' => 'https://rag.test/api/v1']); |
|
|
| Http::fake([ |
| 'https://rag.test/api/v1/courses/101' => Http::response([ |
| 'description' => 'Materi semester awal', |
| 'id' => 101, |
| 'title' => 'Algoritma Lanjut', |
| ]), |
| ]); |
|
|
| $this->withCookie('sevima_raghub_auth_token', 'token') |
| ->withCookie('sevima_raghub_auth_user', lecturerAuthUserCookie()) |
| ->from(route('dosen.show', ['courseId' => '101'])) |
| ->put(route('dosen.update', ['courseId' => '101']), [ |
| 'description' => 'Materi semester awal', |
| 'title' => 'Algoritma Lanjut', |
| ]) |
| ->assertRedirect(route('dosen.show', ['courseId' => '101'])) |
| ->assertSessionHasNoErrors(); |
|
|
| Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'PUT' |
| && $request->url() === 'https://rag.test/api/v1/courses/101' |
| && $request->hasHeader('Authorization', 'Bearer token') |
| && $request['title'] === 'Algoritma Lanjut' |
| && $request['description'] === 'Materi semester awal'); |
| }); |
|
|
| test('dosen course update uses backend error message', function () { |
| config(['services.rag.base_url' => 'https://rag.test/api/v1']); |
|
|
| Http::fake([ |
| 'https://rag.test/api/v1/courses/101' => Http::response([ |
| 'message' => 'Course title already exists.', |
| ], 422), |
| ]); |
|
|
| $this->withCookie('sevima_raghub_auth_token', 'token') |
| ->withCookie('sevima_raghub_auth_user', lecturerAuthUserCookie()) |
| ->from(route('dosen.show', ['courseId' => '101'])) |
| ->put(route('dosen.update', ['courseId' => '101']), [ |
| 'title' => 'Algoritma Lanjut', |
| ]) |
| ->assertRedirect(route('dosen.show', ['courseId' => '101'])) |
| ->assertSessionHasErrors(['course' => 'Course title already exists.']); |
| }); |
|
|
| test('dosen course can be deleted through laravel proxy', function () { |
| config(['services.rag.base_url' => 'https://rag.test/api/v1']); |
|
|
| Http::fake([ |
| 'https://rag.test/api/v1/courses/101' => Http::response([]), |
| ]); |
|
|
| $this->withCookie('sevima_raghub_auth_token', 'token') |
| ->withCookie('sevima_raghub_auth_user', lecturerAuthUserCookie()) |
| ->from(route('dosen.show', ['courseId' => '101'])) |
| ->delete(route('dosen.destroy', ['courseId' => '101'])) |
| ->assertRedirect(route('dosen')) |
| ->assertSessionHasNoErrors(); |
|
|
| Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'DELETE' |
| && $request->url() === 'https://rag.test/api/v1/courses/101' |
| && $request->hasHeader('Authorization', 'Bearer token')); |
| }); |
|
|
| test('dosen course delete uses backend error message', function () { |
| config(['services.rag.base_url' => 'https://rag.test/api/v1']); |
|
|
| Http::fake([ |
| 'https://rag.test/api/v1/courses/101' => Http::response([ |
| 'message' => 'Course still has active documents.', |
| ], 422), |
| ]); |
|
|
| $this->withCookie('sevima_raghub_auth_token', 'token') |
| ->withCookie('sevima_raghub_auth_user', lecturerAuthUserCookie()) |
| ->from(route('dosen.show', ['courseId' => '101'])) |
| ->delete(route('dosen.destroy', ['courseId' => '101'])) |
| ->assertRedirect(route('dosen.show', ['courseId' => '101'])) |
| ->assertSessionHasErrors(['course' => 'Course still has active documents.']); |
| }); |
|
|
| test('dosen document can be uploaded through laravel proxy', function () { |
| config(['services.rag.base_url' => 'https://rag.test/api/v1']); |
|
|
| Http::fake([ |
| 'https://rag.test/api/v1/documents/upload' => Http::response([ |
| 'document_id' => 'doc-1', |
| 'filename' => 'materi.pdf', |
| 'message' => 'File accepted.', |
| 'status' => 'processing', |
| ], 202), |
| ]); |
|
|
| $file = UploadedFile::fake()->create('materi.pdf', 100, 'application/pdf'); |
|
|
| $this->withCookie('sevima_raghub_auth_token', 'token') |
| ->withCookie('sevima_raghub_auth_user', lecturerAuthUserCookie()) |
| ->from(route('dosen.show', ['courseId' => '101'])) |
| ->post(route('dosen.documents.store', ['courseId' => '101']), [ |
| 'file' => $file, |
| ]) |
| ->assertRedirect(route('dosen.show', ['courseId' => '101'])) |
| ->assertSessionHasNoErrors(); |
|
|
| Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'POST' |
| && $request->url() === 'https://rag.test/api/v1/documents/upload' |
| && $request->hasHeader('Authorization', 'Bearer token') |
| && $request->isMultipart() |
| && $request->hasFile('file', filename: 'materi.pdf') |
| && collect($request->data())->contains( |
| fn (array $part): bool => ($part['name'] ?? null) === 'course_id' |
| && ($part['contents'] ?? null) === '101', |
| )); |
| }); |
|
|
| test('dosen document upload uses backend error message', function () { |
| config(['services.rag.base_url' => 'https://rag.test/api/v1']); |
|
|
| Http::fake([ |
| 'https://rag.test/api/v1/documents/upload' => Http::response([ |
| 'detail' => [ |
| ['msg' => 'Unsupported file type.'], |
| ], |
| ], 422), |
| ]); |
|
|
| $file = UploadedFile::fake()->create('materi.pdf', 100, 'application/pdf'); |
|
|
| $this->withCookie('sevima_raghub_auth_token', 'token') |
| ->withCookie('sevima_raghub_auth_user', lecturerAuthUserCookie()) |
| ->from(route('dosen.show', ['courseId' => '101'])) |
| ->post(route('dosen.documents.store', ['courseId' => '101']), [ |
| 'file' => $file, |
| ]) |
| ->assertRedirect(route('dosen.show', ['courseId' => '101'])) |
| ->assertSessionHasErrors(['file' => 'Unsupported file type.']); |
| }); |
|
|