fix(gateway): decouple admin navigation loading
This commit is contained in:
@@ -105,6 +105,7 @@ const installFixture = async (page: Page) => {
|
||||
});
|
||||
}
|
||||
if (operation === 'admin.system.getNotice') return response({ notice: '' });
|
||||
if (operation === 'admin.profiles.listNavigation') return response([]);
|
||||
if (operation === 'admin.profiles.list') return response([]);
|
||||
if (operation === 'admin.profiles.listScenarios') return response([]);
|
||||
if (operation === 'admin.users.lookup') {
|
||||
@@ -194,7 +195,12 @@ const installFixture = async (page: Page) => {
|
||||
}
|
||||
throw new Error(`Unhandled tRPC operation: ${operation}`);
|
||||
});
|
||||
await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(results) });
|
||||
const isBatch = new URL(route.request().url()).searchParams.get('batch') === '1';
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(isBatch ? results : results[0]),
|
||||
});
|
||||
});
|
||||
return mutations;
|
||||
};
|
||||
|
||||
@@ -145,6 +145,15 @@ const installFixture = async (
|
||||
},
|
||||
]);
|
||||
}
|
||||
if (operation === 'admin.profiles.listNavigation') {
|
||||
return response([
|
||||
{
|
||||
profileName: 'hwe:default',
|
||||
profile: 'hwe',
|
||||
meta: {},
|
||||
},
|
||||
]);
|
||||
}
|
||||
if (operation === 'admin.profiles.list') {
|
||||
const keepPending = requested && postRequestProfileReads++ < (options.pendingProfileReads ?? 0);
|
||||
return response([
|
||||
@@ -235,7 +244,9 @@ const installFixture = async (
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(results),
|
||||
body: JSON.stringify(
|
||||
new URL(route.request().url()).searchParams.get('batch') === '1' ? results : results[0]
|
||||
),
|
||||
});
|
||||
});
|
||||
return { releaseRequest, releaseInstall, requestBodies };
|
||||
|
||||
@@ -52,6 +52,19 @@ const installGatewayFixture = async (page: Page, roles: string[]) => {
|
||||
: []
|
||||
);
|
||||
}
|
||||
if (operation === 'admin.profiles.listNavigation') {
|
||||
return response(
|
||||
roles.some((role) => role === 'superuser' || role.includes(':hwe:2'))
|
||||
? [
|
||||
{
|
||||
profileName: 'hwe:2',
|
||||
profile: 'hwe',
|
||||
meta: { korName: '환상서버' },
|
||||
},
|
||||
]
|
||||
: []
|
||||
);
|
||||
}
|
||||
if (operation === 'admin.releases.gatewayState') {
|
||||
return response({ id: 'gateway', updatedAt: '2026-08-01T00:00:00.000Z' });
|
||||
}
|
||||
@@ -85,7 +98,9 @@ const installGatewayFixture = async (page: Page, roles: string[]) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(results),
|
||||
body: JSON.stringify(
|
||||
new URL(route.request().url()).searchParams.get('batch') === '1' ? results : results[0]
|
||||
),
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -36,8 +36,9 @@ type FixtureState = {
|
||||
gatewayLogPollCount?: number;
|
||||
capabilities?: Array<{ permission: string; scope: 'GLOBAL' | 'PROFILE'; scopes: string[] }>;
|
||||
profileListDelayMs?: number;
|
||||
profileListRequests?: number;
|
||||
profileListResolved?: boolean;
|
||||
profileNavigationDelayMs?: number;
|
||||
profileNavigationRequests?: number;
|
||||
profileNavigationResolved?: boolean;
|
||||
};
|
||||
|
||||
const profile = (runtimeRunning: boolean) => ({
|
||||
@@ -97,12 +98,16 @@ const installFixture = async (page: Page, state: FixtureState) => {
|
||||
await page.route('**/gateway/api/trpc/**', async (route) => {
|
||||
const names = operationNames(route);
|
||||
const body = route.request().postDataJSON() as unknown;
|
||||
if (names.includes('admin.profiles.list')) {
|
||||
state.profileListRequests = (state.profileListRequests ?? 0) + 1;
|
||||
if (state.profileListDelayMs) {
|
||||
await new Promise((resolve) => setTimeout(resolve, state.profileListDelayMs));
|
||||
if (names.includes('admin.profiles.listNavigation')) {
|
||||
expect(names).toEqual(['admin.profiles.listNavigation']);
|
||||
state.profileNavigationRequests = (state.profileNavigationRequests ?? 0) + 1;
|
||||
if (state.profileNavigationDelayMs) {
|
||||
await new Promise((resolve) => setTimeout(resolve, state.profileNavigationDelayMs));
|
||||
}
|
||||
state.profileListResolved = true;
|
||||
state.profileNavigationResolved = true;
|
||||
}
|
||||
if (names.includes('admin.profiles.list') && state.profileListDelayMs) {
|
||||
await new Promise((resolve) => setTimeout(resolve, state.profileListDelayMs));
|
||||
}
|
||||
const results = names.map((name) => {
|
||||
if (route.request().method() === 'POST') {
|
||||
@@ -111,6 +116,15 @@ const installFixture = async (page: Page, state: FixtureState) => {
|
||||
if (name === 'admin.profiles.list') {
|
||||
return response([profile(state.runtimeRunning)]);
|
||||
}
|
||||
if (name === 'admin.profiles.listNavigation') {
|
||||
return response([
|
||||
{
|
||||
profileName: 'che:2',
|
||||
profile: 'che',
|
||||
meta: { korName: '천하서버' },
|
||||
},
|
||||
]);
|
||||
}
|
||||
if (name === 'admin.capabilities.list') {
|
||||
return response(
|
||||
state.capabilities ?? [
|
||||
@@ -261,7 +275,9 @@ const installFixture = async (page: Page, state: FixtureState) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(results),
|
||||
body: JSON.stringify(
|
||||
new URL(route.request().url()).searchParams.get('batch') === '1' ? results : results[0]
|
||||
),
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -387,16 +403,33 @@ test('renders the fixed-profile version form without waiting for the server list
|
||||
gatewayOperations: [],
|
||||
runtimeRunning: true,
|
||||
requestBodies: [],
|
||||
profileListDelayMs: 1500,
|
||||
profileListResolved: false,
|
||||
profileNavigationDelayMs: 1500,
|
||||
profileNavigationResolved: false,
|
||||
};
|
||||
await installFixture(page, state);
|
||||
|
||||
await page.goto('admin/servers/che%3A2/version');
|
||||
await expect(page.getByTestId('request-deploy')).toBeVisible({ timeout: 900 });
|
||||
expect(state.profileListResolved).toBe(false);
|
||||
await expect.poll(() => state.profileListResolved).toBe(true);
|
||||
expect(state.profileListRequests).toBe(1);
|
||||
expect(state.profileNavigationResolved).toBe(false);
|
||||
await expect.poll(() => state.profileNavigationResolved).toBe(true);
|
||||
expect(state.profileNavigationRequests).toBe(1);
|
||||
});
|
||||
|
||||
test('renders the server navigation before the detailed runtime profile request resolves', async ({ page }) => {
|
||||
const state: FixtureState = {
|
||||
operations: [],
|
||||
gatewayOperations: [],
|
||||
runtimeRunning: true,
|
||||
requestBodies: [],
|
||||
profileListDelayMs: 1500,
|
||||
};
|
||||
await installFixture(page, state);
|
||||
|
||||
await page.goto('admin/servers/che%3A2');
|
||||
const navigation = page.getByRole('navigation', { name: '관리자 메뉴' });
|
||||
await expect(navigation.getByRole('link', { name: '천하서버 (che:2)' })).toBeVisible({ timeout: 900 });
|
||||
await expect(navigation.getByRole('link', { name: 'Gateway 릴리스' })).toBeVisible({ timeout: 900 });
|
||||
expect(state.profileNavigationRequests).toBe(1);
|
||||
});
|
||||
|
||||
test('scenario-only operator resets the current version without Git or Gateway controls', async ({ page }) => {
|
||||
|
||||
Reference in New Issue
Block a user