CAPS04-FE-REFACTOR / tests /Feature /AdminDashboardTest.php
wepee's picture
change: move api to controller
1e5ae4b
Raw
History Blame
11.5 kB
<?php
use Illuminate\Http\Client\Request as HttpRequest;
use Illuminate\Support\Facades\Http;
use Inertia\Testing\AssertableInertia as Assert;
function adminAuthUserCookie(): string
{
return json_encode([
'email' => 'admin@example.com',
'id' => 99,
'identity_number' => 'ADM001',
'name' => 'Admin',
'role' => 'admin',
'status' => 'active',
], JSON_THROW_ON_ERROR);
}
test('admin dashboard fetches rag config and users from backend', function () {
config(['services.rag.base_url' => 'https://rag.test/api/v1']);
Http::fake([
'https://rag.test/api/v1/admin/rag/config' => Http::response([
'llm' => [],
'path' => 'config/rag.yaml',
'retrieval' => [],
'vector_db' => [],
]),
'https://rag.test/api/v1/admin/rag/config/llm' => Http::response([
'max_tokens' => 2048,
'model' => 'gpt-test',
'request_timeout' => 30,
'temperature' => 0.2,
]),
'https://rag.test/api/v1/admin/rag/config/retrieval' => Http::response([
'bm25_weight' => 0.2,
'candidate_pool_size' => 20,
'dense_weight' => 0.6,
'enable_reranker' => true,
'history_turns' => 3,
'lexical_weight' => 0.2,
'max_context_chars' => 6000,
'neighbor_window' => 1,
'reranker_model' => 'rerank-test',
'similarity_threshold' => 0.1,
'top_k' => 4,
]),
'https://rag.test/api/v1/admin/rag/config/vector_db' => Http::response([
'chunk_overlap' => 100,
'chunk_size' => 800,
'embedding_model' => 'embed-test',
]),
'https://rag.test/api/v1/user*' => Http::response([
'founds' => [
[
'created_at' => '2026-05-01T10:00:00Z',
'email' => 'admin@example.com',
'id' => 99,
'identity_number' => 'ADM001',
'is_active' => true,
'is_superuser' => true,
'name' => 'Admin',
'role' => 'admin',
'updated_at' => '2026-05-01T10:00:00Z',
],
],
'search_options' => [],
]),
]);
$this->withCookie('sevima_raghub_auth_token', 'token')
->withCookie('sevima_raghub_auth_user', adminAuthUserCookie())
->get(route('admin.dashboard', ['name' => 'Admin']))
->assertOk()
->assertInertia(fn (Assert $page) => $page
->component('admin/dashboard')
->where('backendMessage', null)
->where('ragConfig.path', 'config/rag.yaml')
->where('ragConfig.llm.model', 'gpt-test')
->has('users', 1)
->where('users.0.email', 'admin@example.com')
->where('userFilters.name', 'Admin'));
Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'GET'
&& $request->url() === 'https://rag.test/api/v1/admin/rag/config'
&& $request->hasHeader('Authorization', 'Bearer token'));
Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'GET'
&& $request->url() === 'https://rag.test/api/v1/admin/rag/config/llm'
&& $request->hasHeader('Authorization', 'Bearer token'));
Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'GET'
&& $request->url() === 'https://rag.test/api/v1/admin/rag/config/vector_db'
&& $request->hasHeader('Authorization', 'Bearer token'));
Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'GET'
&& $request->url() === 'https://rag.test/api/v1/admin/rag/config/retrieval'
&& $request->hasHeader('Authorization', 'Bearer token'));
Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'GET'
&& str_starts_with($request->url(), 'https://rag.test/api/v1/user?')
&& $request['name'] === 'Admin'
&& $request->hasHeader('Authorization', 'Bearer token'));
});
test('admin config pages render separate inertia components', function (string $routeName, string $component) {
config(['services.rag.base_url' => 'https://rag.test/api/v1']);
Http::fake([
'https://rag.test/api/v1/admin/rag/config' => Http::response([
'llm' => [],
'path' => 'config/rag.yaml',
'retrieval' => [],
'vector_db' => [],
]),
'https://rag.test/api/v1/admin/rag/config/llm' => Http::response([
'model' => 'gpt-test',
]),
'https://rag.test/api/v1/admin/rag/config/retrieval' => Http::response([
'top_k' => 4,
]),
'https://rag.test/api/v1/admin/rag/config/vector_db' => Http::response([
'chunk_size' => 800,
]),
]);
$this->withCookie('sevima_raghub_auth_token', 'token')
->withCookie('sevima_raghub_auth_user', adminAuthUserCookie())
->get(route($routeName))
->assertOk()
->assertInertia(fn (Assert $page) => $page
->component($component)
->where('backendMessage', null)
->where('ragConfig.path', 'config/rag.yaml'));
})->with([
'rag config' => ['admin.rag-config', 'admin/rag-config'],
'llm config' => ['admin.llm-config', 'admin/llm-config'],
'vector retrieval config' => ['admin.vector-retrieval-config', 'admin/vector-retrieval-config'],
]);
test('admin config update endpoints are proxied to backend', function (string $routeName, string $redirectRouteName, string $url, array $payload, string $assertKey) {
config(['services.rag.base_url' => 'https://rag.test/api/v1']);
Http::fake([
$url => Http::response($payload),
]);
$this->withCookie('sevima_raghub_auth_token', 'token')
->withCookie('sevima_raghub_auth_user', adminAuthUserCookie())
->from(route('admin.dashboard'))
->patch(route($routeName), $payload)
->assertRedirect(route($redirectRouteName))
->assertSessionHasNoErrors();
Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'PATCH'
&& $request->url() === $url
&& $request[$assertKey] === $payload[$assertKey]
&& $request->hasHeader('Authorization', 'Bearer token'));
})->with([
'llm' => [
'admin.rag.llm.update',
'admin.llm-config',
'https://rag.test/api/v1/admin/rag/config/llm',
['model' => 'gpt-test', 'temperature' => 0.1],
'model',
],
'vector db' => [
'admin.rag.vector-db.update',
'admin.vector-retrieval-config',
'https://rag.test/api/v1/admin/rag/config/vector_db',
['chunk_size' => 900, 'embedding_model' => 'embed-test'],
'chunk_size',
],
'retrieval' => [
'admin.rag.retrieval.update',
'admin.vector-retrieval-config',
'https://rag.test/api/v1/admin/rag/config/retrieval',
['enable_reranker' => true, 'top_k' => 5],
'top_k',
],
]);
test('admin api key generation is proxied and flashes generated key', function () {
config(['services.rag.base_url' => 'https://rag.test/api/v1']);
Http::fake([
'https://rag.test/api/v1/auth/api-keys' => Http::response([
'api_key' => 'rag_sk_test',
'expires_at' => null,
], 201),
]);
$this->withCookie('sevima_raghub_auth_token', 'token')
->withCookie('sevima_raghub_auth_user', adminAuthUserCookie())
->from(route('admin.dashboard'))
->post(route('admin.api-keys.store'))
->assertRedirect(route('admin.dashboard'))
->assertSessionHas('generatedApiKey.api_key', 'rag_sk_test')
->assertSessionHasNoErrors();
Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'POST'
&& $request->url() === 'https://rag.test/api/v1/auth/api-keys'
&& $request->hasHeader('Authorization', 'Bearer token'));
});
test('admin user crud actions are proxied to backend', function () {
config(['services.rag.base_url' => 'https://rag.test/api/v1']);
Http::fake([
'https://rag.test/api/v1/user' => Http::response([
'email' => 'student@example.com',
'id' => 10,
'role' => 'student',
]),
'https://rag.test/api/v1/user/10' => Http::response([
'email' => 'student@example.com',
'id' => 10,
'role' => 'student',
]),
]);
$this->withCookie('sevima_raghub_auth_token', 'token')
->withCookie('sevima_raghub_auth_user', adminAuthUserCookie())
->from(route('admin.dashboard'))
->post(route('admin.users.store'), [
'email' => 'student@example.com',
'identity_number' => 'M001',
'is_active' => true,
'is_superuser' => false,
'name' => 'Student',
'role' => 'student',
])
->assertRedirect(route('admin.dashboard'))
->assertSessionHasNoErrors();
$this->withCookie('sevima_raghub_auth_token', 'token')
->withCookie('sevima_raghub_auth_user', adminAuthUserCookie())
->from(route('admin.dashboard'))
->patch(route('admin.users.update', ['userId' => 10]), [
'email' => 'student@example.com',
'identity_number' => 'M001',
'is_active' => false,
'is_superuser' => false,
'name' => 'Student Updated',
'role' => 'student',
])
->assertRedirect(route('admin.dashboard'))
->assertSessionHasNoErrors();
$this->withCookie('sevima_raghub_auth_token', 'token')
->withCookie('sevima_raghub_auth_user', adminAuthUserCookie())
->from(route('admin.dashboard'))
->delete(route('admin.users.destroy', ['userId' => 10]))
->assertRedirect(route('admin.dashboard'))
->assertSessionHasNoErrors();
Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'POST'
&& $request->url() === 'https://rag.test/api/v1/user'
&& $request['email'] === 'student@example.com'
&& $request->hasHeader('Authorization', 'Bearer token'));
Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'PATCH'
&& $request->url() === 'https://rag.test/api/v1/user/10'
&& $request['name'] === 'Student Updated'
&& $request->hasHeader('Authorization', 'Bearer token'));
Http::assertSent(fn (HttpRequest $request): bool => $request->method() === 'DELETE'
&& $request->url() === 'https://rag.test/api/v1/user/10'
&& $request->hasHeader('Authorization', 'Bearer token'));
});
test('admin actions use backend error messages', function () {
config(['services.rag.base_url' => 'https://rag.test/api/v1']);
Http::fake([
'https://rag.test/api/v1/user' => Http::response([
'detail' => [
['msg' => 'Email already exists.'],
],
], 422),
]);
$this->withCookie('sevima_raghub_auth_token', 'token')
->withCookie('sevima_raghub_auth_user', adminAuthUserCookie())
->from(route('admin.dashboard'))
->post(route('admin.users.store'), [
'email' => 'admin@example.com',
'role' => 'admin',
])
->assertRedirect(route('admin.dashboard'))
->assertSessionHasErrors(['user' => 'Email already exists.']);
});