Spaces:
Sleeping
Sleeping
| 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.']); | |
| }); | |