fix(game-ui): 사령부 실제 지도 조회를 복구
This commit is contained in:
@@ -0,0 +1,68 @@
|
|||||||
|
import { dirname, resolve } from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import { defineConfig, devices } from '@playwright/test';
|
||||||
|
|
||||||
|
const repositoryRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../../..');
|
||||||
|
const frontendPort = Number(process.env.PLAYWRIGHT_FRONTEND_PORT ?? 15161);
|
||||||
|
const apiPort = Number(process.env.PLAYWRIGHT_GAME_API_PORT ?? 15162);
|
||||||
|
const basePath = '/che';
|
||||||
|
const profileId = 'chief_command_map_live_integration';
|
||||||
|
const scenario = '2';
|
||||||
|
const gameProfile = `${profileId}:${scenario}`;
|
||||||
|
const databaseUrl = process.env.CHIEF_COMMAND_MAP_LIVE_DATABASE_URL ?? '';
|
||||||
|
const redisUrl = process.env.CHIEF_COMMAND_MAP_LIVE_REDIS_URL ?? '';
|
||||||
|
const gameSecret = process.env.CHIEF_COMMAND_MAP_LIVE_GAME_SECRET ?? '';
|
||||||
|
const imageUploadSecretFile = resolve(repositoryRoot, 'app/game-frontend/e2e/fixtures/image-upload-secret.example');
|
||||||
|
|
||||||
|
if (databaseUrl && new URL(databaseUrl).searchParams.get('schema') !== profileId) {
|
||||||
|
throw new Error('Chief command map live database must use its dedicated schema.');
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: '.',
|
||||||
|
testMatch: ['chiefCommandMapLive.spec.ts'],
|
||||||
|
fullyParallel: false,
|
||||||
|
workers: 1,
|
||||||
|
timeout: 90_000,
|
||||||
|
expect: { timeout: 15_000 },
|
||||||
|
reporter: [['list']],
|
||||||
|
outputDir: resolve(repositoryRoot, 'test-results/chief-command-map-live'),
|
||||||
|
use: {
|
||||||
|
baseURL: `http://127.0.0.1:${frontendPort}${basePath}/`,
|
||||||
|
...devices['Desktop Chrome'],
|
||||||
|
deviceScaleFactor: 1,
|
||||||
|
locale: 'ko-KR',
|
||||||
|
timezoneId: 'Asia/Seoul',
|
||||||
|
trace: 'retain-on-failure',
|
||||||
|
screenshot: 'only-on-failure',
|
||||||
|
},
|
||||||
|
webServer: [
|
||||||
|
{
|
||||||
|
command: 'node app/game-api/dist/index.js',
|
||||||
|
cwd: repositoryRoot,
|
||||||
|
url: `http://127.0.0.1:${apiPort}/healthz`,
|
||||||
|
reuseExistingServer: false,
|
||||||
|
timeout: 120_000,
|
||||||
|
env: {
|
||||||
|
DATABASE_URL: databaseUrl,
|
||||||
|
REDIS_URL: redisUrl,
|
||||||
|
GAME_TOKEN_SECRET: gameSecret,
|
||||||
|
GAME_IMAGE_UPLOAD_SECRET_FILE: imageUploadSecretFile,
|
||||||
|
GAME_API_ROLE: 'server',
|
||||||
|
GAME_API_HOST: '127.0.0.1',
|
||||||
|
GAME_API_PORT: String(apiPort),
|
||||||
|
PROFILE: profileId,
|
||||||
|
SCENARIO: scenario,
|
||||||
|
GAME_PROFILE_NAME: gameProfile,
|
||||||
|
DAEMON_REQUEST_TIMEOUT_MS: '15000',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
command: `VITE_APP_BASE_PATH=${basePath} VITE_GAME_API_URL=http://127.0.0.1:${apiPort}/trpc VITE_GAME_PROFILE=${gameProfile} VITE_GATEWAY_WEB_URL=/gateway/ pnpm --filter @sammo-ts/game-frontend build && VITE_APP_BASE_PATH=${basePath} pnpm --filter @sammo-ts/game-frontend preview --host 127.0.0.1 --port ${frontendPort}`,
|
||||||
|
cwd: repositoryRoot,
|
||||||
|
url: `http://127.0.0.1:${frontendPort}${basePath}/`,
|
||||||
|
reuseExistingServer: false,
|
||||||
|
timeout: 120_000,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
@@ -0,0 +1,296 @@
|
|||||||
|
import { randomUUID } from 'node:crypto';
|
||||||
|
import { readFile } from 'node:fs/promises';
|
||||||
|
import { dirname, resolve } from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
|
import { expect, test, type Page } from '@playwright/test';
|
||||||
|
import { encryptGameSessionToken } from '../../../packages/common/dist/auth/gameToken.js';
|
||||||
|
import { createGamePostgresConnector } from '../../../packages/infra/dist/index.js';
|
||||||
|
import { seedScenarioToDatabase } from '../../game-engine/dist/index.js';
|
||||||
|
|
||||||
|
const databaseUrl = process.env.CHIEF_COMMAND_MAP_LIVE_DATABASE_URL;
|
||||||
|
const redisUrl = process.env.CHIEF_COMMAND_MAP_LIVE_REDIS_URL;
|
||||||
|
const gameTokenSecret = process.env.CHIEF_COMMAND_MAP_LIVE_GAME_SECRET;
|
||||||
|
const profile = 'chief_command_map_live_integration:2';
|
||||||
|
const profileId = profile.split(':', 1)[0]!;
|
||||||
|
const hasLiveFixture = Boolean(databaseUrl && redisUrl && gameTokenSecret);
|
||||||
|
const actorId = 7_761;
|
||||||
|
const actorUserId = 'chief-command-map-live-user';
|
||||||
|
const ownNationId = 9_918;
|
||||||
|
const targetNationId = 9_919;
|
||||||
|
const repositoryRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../../..');
|
||||||
|
const imageRoots = [
|
||||||
|
resolve(repositoryRoot, '../image'),
|
||||||
|
resolve(repositoryRoot, '../../image'),
|
||||||
|
resolve(repositoryRoot, '../sam_rebuild/image'),
|
||||||
|
resolve(repositoryRoot, '../../sam_rebuild/image'),
|
||||||
|
];
|
||||||
|
|
||||||
|
const readImage = async (relativePath: string): Promise<Buffer> => {
|
||||||
|
if (relativePath.includes('..')) throw new Error(`Unsafe fixture image path: ${relativePath}`);
|
||||||
|
for (const root of imageRoots) {
|
||||||
|
try {
|
||||||
|
return await readFile(resolve(root, relativePath));
|
||||||
|
} catch {
|
||||||
|
// Product checkout and worktrees have different image-root parents.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`Fixture image not found: ${relativePath}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const imageContentType = (relativePath: string): string => {
|
||||||
|
if (relativePath.endsWith('.png')) return 'image/png';
|
||||||
|
if (relativePath.endsWith('.gif')) return 'image/gif';
|
||||||
|
return 'image/jpeg';
|
||||||
|
};
|
||||||
|
|
||||||
|
const installSession = async (page: Page): Promise<void> => {
|
||||||
|
const issuedAt = new Date();
|
||||||
|
const gameToken = encryptGameSessionToken(
|
||||||
|
{
|
||||||
|
version: 1,
|
||||||
|
profile,
|
||||||
|
issuedAt: issuedAt.toISOString(),
|
||||||
|
expiresAt: new Date(issuedAt.getTime() + 3_600_000).toISOString(),
|
||||||
|
sessionId: `chief-command-map-live-${randomUUID()}`,
|
||||||
|
user: {
|
||||||
|
id: actorUserId,
|
||||||
|
username: actorUserId,
|
||||||
|
displayName: '사령부지도검증',
|
||||||
|
roles: ['user'],
|
||||||
|
canUseGeneralPicture: false,
|
||||||
|
},
|
||||||
|
sanctions: {},
|
||||||
|
identity: {
|
||||||
|
kakaoVerified: true,
|
||||||
|
canCreateGeneral: true,
|
||||||
|
requiresKakaoVerification: false,
|
||||||
|
graceEndsAt: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
gameTokenSecret!
|
||||||
|
);
|
||||||
|
await page.addInitScript(
|
||||||
|
({ token, gameProfile }) => {
|
||||||
|
localStorage.setItem('sammo-game-token', token);
|
||||||
|
localStorage.setItem('sammo-game-profile', gameProfile);
|
||||||
|
},
|
||||||
|
{ token: gameToken, gameProfile: profile }
|
||||||
|
);
|
||||||
|
await page.route('**/image/**', async (route) => {
|
||||||
|
const relativePath = decodeURIComponent(new URL(route.request().url()).pathname.split('/image/')[1] ?? '');
|
||||||
|
try {
|
||||||
|
await route.fulfill({
|
||||||
|
status: 200,
|
||||||
|
contentType: imageContentType(relativePath),
|
||||||
|
body: await readImage(relativePath),
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
await route.fulfill({ status: 404, body: '' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await page.route('**/game/**', async (route) => {
|
||||||
|
const relativePath = decodeURIComponent(new URL(route.request().url()).pathname.split('/game/')[1] ?? '');
|
||||||
|
try {
|
||||||
|
await route.fulfill({
|
||||||
|
status: 200,
|
||||||
|
contentType: imageContentType(relativePath),
|
||||||
|
body: await readImage(`game/${relativePath}`),
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
await route.fulfill({ status: 404, body: '' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
test('shows and operates a city target map through live PostgreSQL, Game API, and production Chromium', async ({
|
||||||
|
browser,
|
||||||
|
page,
|
||||||
|
}, testInfo) => {
|
||||||
|
test.skip(!hasLiveFixture, 'dedicated PostgreSQL, Redis, and game token secret are required');
|
||||||
|
page.setDefaultTimeout(15_000);
|
||||||
|
|
||||||
|
const schema = new URL(databaseUrl!).searchParams.get('schema');
|
||||||
|
if (schema !== profileId || !schema.endsWith('chief_command_map_live_integration')) {
|
||||||
|
throw new Error('Refusing a non-dedicated chief command map schema.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const previousSeed = process.env.INTEGRATION_WORLD_SEED;
|
||||||
|
process.env.INTEGRATION_WORLD_SEED = 'chief-command-map-live-seed';
|
||||||
|
try {
|
||||||
|
await seedScenarioToDatabase({
|
||||||
|
scenarioId: 2,
|
||||||
|
databaseUrl: databaseUrl!,
|
||||||
|
now: new Date('2099-08-01T00:00:00.000Z'),
|
||||||
|
gameClockMode: 'manual',
|
||||||
|
installOptions: {
|
||||||
|
turnTermMinutes: 5,
|
||||||
|
joinMode: 'full',
|
||||||
|
npcMode: 0,
|
||||||
|
showImgLevel: 3,
|
||||||
|
serverId: profile,
|
||||||
|
season: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
if (previousSeed === undefined) delete process.env.INTEGRATION_WORLD_SEED;
|
||||||
|
else process.env.INTEGRATION_WORLD_SEED = previousSeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
const connector = createGamePostgresConnector({ url: databaseUrl! });
|
||||||
|
await connector.connect();
|
||||||
|
try {
|
||||||
|
const db = connector.prisma;
|
||||||
|
const [ownCity, targetCity] = await db.city.findMany({ orderBy: { id: 'asc' }, take: 2 });
|
||||||
|
if (!ownCity || !targetCity) throw new Error('The seeded scenario needs at least two cities.');
|
||||||
|
|
||||||
|
await db.general.deleteMany({ where: { userId: actorUserId } });
|
||||||
|
await db.nation.upsert({
|
||||||
|
where: { id: ownNationId },
|
||||||
|
create: {
|
||||||
|
id: ownNationId,
|
||||||
|
name: '지도아국',
|
||||||
|
color: '#225500',
|
||||||
|
capitalCityId: ownCity.id,
|
||||||
|
level: 7,
|
||||||
|
meta: { gennum: 1, scout: 0 },
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
name: '지도아국',
|
||||||
|
color: '#225500',
|
||||||
|
capitalCityId: ownCity.id,
|
||||||
|
level: 7,
|
||||||
|
meta: { gennum: 1, scout: 0 },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await db.nation.upsert({
|
||||||
|
where: { id: targetNationId },
|
||||||
|
create: {
|
||||||
|
id: targetNationId,
|
||||||
|
name: '지도적국',
|
||||||
|
color: '#772222',
|
||||||
|
capitalCityId: targetCity.id,
|
||||||
|
level: 1,
|
||||||
|
meta: { gennum: 0, scout: 0 },
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
name: '지도적국',
|
||||||
|
color: '#772222',
|
||||||
|
capitalCityId: targetCity.id,
|
||||||
|
level: 1,
|
||||||
|
meta: { gennum: 0, scout: 0 },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await db.city.update({ where: { id: ownCity.id }, data: { nationId: ownNationId, supplyState: 1 } });
|
||||||
|
await db.city.update({ where: { id: targetCity.id }, data: { nationId: targetNationId, supplyState: 1 } });
|
||||||
|
await db.general.create({
|
||||||
|
data: {
|
||||||
|
id: actorId,
|
||||||
|
userId: actorUserId,
|
||||||
|
name: '지도군주',
|
||||||
|
nationId: ownNationId,
|
||||||
|
cityId: ownCity.id,
|
||||||
|
troopId: 0,
|
||||||
|
npcState: 0,
|
||||||
|
leadership: 80,
|
||||||
|
strength: 70,
|
||||||
|
intel: 60,
|
||||||
|
officerLevel: 12,
|
||||||
|
experience: 100,
|
||||||
|
dedication: 100,
|
||||||
|
gold: 100_000,
|
||||||
|
rice: 100_000,
|
||||||
|
turnTime: new Date('2099-08-01T00:05:00.000Z'),
|
||||||
|
turnTick: null,
|
||||||
|
meta: { killturn: 960, belong: 1 },
|
||||||
|
penalty: {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await installSession(page);
|
||||||
|
const mapResponses: number[] = [];
|
||||||
|
page.on('response', (response) => {
|
||||||
|
if (response.url().includes('world.getMap')) mapResponses.push(response.status());
|
||||||
|
});
|
||||||
|
await page.goto('chief-center');
|
||||||
|
await expect(page.getByRole('heading', { name: '사령부', exact: true })).toBeVisible();
|
||||||
|
await page.getByRole('button', { name: '1턴 명령 입력', exact: true }).click();
|
||||||
|
const picker = page.getByTestId('command-picker');
|
||||||
|
await picker.getByRole('button', { name: /^(?:국가:)?특수$/, exact: true }).click();
|
||||||
|
await picker.getByRole('button', { name: '천도', exact: true }).click();
|
||||||
|
|
||||||
|
const form = picker.getByTestId('command-argument-form');
|
||||||
|
const map = form.getByTestId('command-argument-map');
|
||||||
|
await expect(map).toBeVisible();
|
||||||
|
await expect.poll(() => mapResponses.length).toBeGreaterThan(0);
|
||||||
|
expect(mapResponses.every((status) => status >= 200 && status < 300)).toBe(true);
|
||||||
|
|
||||||
|
const target = map.locator('.city-base').nth(1);
|
||||||
|
await expect(target).toBeVisible();
|
||||||
|
await target.click();
|
||||||
|
await expect(form.getByRole('combobox', { name: '대상 도시' })).toHaveValue(String(targetCity.id));
|
||||||
|
await expect(form.getByTestId('command-map-selection-status')).toContainText(`선택 도시${targetCity.name}`);
|
||||||
|
await expect(form.getByTestId('command-map-target-summary')).toContainText(targetCity.name);
|
||||||
|
|
||||||
|
const geometry = await map.evaluate((element) => {
|
||||||
|
const rect = element.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
width: rect.width,
|
||||||
|
height: rect.height,
|
||||||
|
display: getComputedStyle(element).display,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
expect(geometry.width).toBeGreaterThan(400);
|
||||||
|
expect(geometry.height).toBeGreaterThan(250);
|
||||||
|
expect(geometry.display).not.toBe('none');
|
||||||
|
await page.screenshot({ path: testInfo.outputPath('chief-command-city-map-live.png'), fullPage: true });
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: '명령 입력 닫기', exact: true }).click();
|
||||||
|
await page.getByRole('button', { name: '2턴 명령 입력', exact: true }).click();
|
||||||
|
const nationPicker = page.getByTestId('command-picker');
|
||||||
|
await nationPicker.getByRole('button', { name: /^(?:국가:)?외교$/, exact: true }).click();
|
||||||
|
await nationPicker.getByRole('button', { name: '선전포고', exact: true }).click();
|
||||||
|
const nationForm = nationPicker.getByTestId('command-argument-form');
|
||||||
|
const nationMap = nationForm.getByTestId('command-argument-map');
|
||||||
|
await expect(nationMap).toBeVisible();
|
||||||
|
await nationMap.locator('.city-base').nth(1).click();
|
||||||
|
await expect(nationForm.getByRole('combobox', { name: '대상 국가' })).toHaveValue(String(targetNationId));
|
||||||
|
await expect(nationForm.getByTestId('command-map-selection-status')).toContainText('선택 국가지도적국');
|
||||||
|
await expect(nationForm.getByTestId('command-map-target-summary')).toContainText(
|
||||||
|
`지도적국 · 수도 ${targetCity.name} · 도시 1개`
|
||||||
|
);
|
||||||
|
await page.screenshot({ path: testInfo.outputPath('chief-command-nation-map-live.png'), fullPage: true });
|
||||||
|
|
||||||
|
const mobileContext = await browser.newContext({
|
||||||
|
viewport: { width: 500, height: 900 },
|
||||||
|
deviceScaleFactor: 1,
|
||||||
|
locale: 'ko-KR',
|
||||||
|
timezoneId: 'Asia/Seoul',
|
||||||
|
});
|
||||||
|
const mobilePage = await mobileContext.newPage();
|
||||||
|
mobilePage.setDefaultTimeout(15_000);
|
||||||
|
await installSession(mobilePage);
|
||||||
|
const configuredBaseUrl = testInfo.project.use.baseURL;
|
||||||
|
if (typeof configuredBaseUrl !== 'string') throw new Error('The live Chromium baseURL is required.');
|
||||||
|
await mobilePage.goto(new URL('chief-center', configuredBaseUrl).href);
|
||||||
|
await mobilePage.getByRole('button', { name: '1턴 명령 입력', exact: true }).click();
|
||||||
|
const mobilePicker = mobilePage.getByTestId('command-picker');
|
||||||
|
await mobilePicker.getByRole('button', { name: /^(?:국가:)?특수$/, exact: true }).click();
|
||||||
|
await mobilePicker.getByRole('button', { name: '천도', exact: true }).click();
|
||||||
|
const mobileMap = mobilePicker.getByTestId('command-argument-map');
|
||||||
|
await expect(mobileMap).toBeVisible();
|
||||||
|
const mobileGeometry = await mobilePicker.evaluate((element) => ({
|
||||||
|
pickerWidth: element.getBoundingClientRect().width,
|
||||||
|
pickerOverflow: element.scrollWidth - element.clientWidth,
|
||||||
|
documentOverflow: document.documentElement.scrollWidth - document.documentElement.clientWidth,
|
||||||
|
}));
|
||||||
|
expect(mobileGeometry).toEqual({ pickerWidth: 500, pickerOverflow: 0, documentOverflow: 0 });
|
||||||
|
await mobilePage.screenshot({
|
||||||
|
path: testInfo.outputPath('chief-command-city-map-live-mobile.png'),
|
||||||
|
fullPage: true,
|
||||||
|
});
|
||||||
|
await mobileContext.close();
|
||||||
|
} finally {
|
||||||
|
await connector.disconnect();
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -846,7 +846,8 @@ const install = async (page: Page, rejectGeneral = false, commandTableResponse:
|
|||||||
nationCnt: 2,
|
nationCnt: 2,
|
||||||
});
|
});
|
||||||
if (name === 'join.getConfig') return response({});
|
if (name === 'join.getConfig') return response({});
|
||||||
if (name === 'world.getMap')
|
if (name === 'world.getMap') {
|
||||||
|
requests.push({ operation: name, body });
|
||||||
return response({
|
return response({
|
||||||
result: true,
|
result: true,
|
||||||
version: 0,
|
version: 0,
|
||||||
@@ -866,6 +867,7 @@ const install = async (page: Page, rejectGeneral = false, commandTableResponse:
|
|||||||
myCity: 1,
|
myCity: 1,
|
||||||
myNation: 1,
|
myNation: 1,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
if (name === 'turns.getCommandTable') return response(commandTableResponse);
|
if (name === 'turns.getCommandTable') return response(commandTableResponse);
|
||||||
if (name === 'nation.getChiefCenter') return response(chiefCenter);
|
if (name === 'nation.getChiefCenter') return response(chiefCenter);
|
||||||
if (name === 'turns.reserved.getGeneral')
|
if (name === 'turns.reserved.getGeneral')
|
||||||
@@ -1775,7 +1777,7 @@ test('keeps arbitrary direct recruitment and mercenary amounts for all four arms
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('uses the map to choose a nation target in the chief command window', async ({ page }) => {
|
test('uses the map to choose a nation target in the chief command window', async ({ page }) => {
|
||||||
await install(page);
|
const requests = await install(page);
|
||||||
await page.setViewportSize({ width: 1200, height: 900 });
|
await page.setViewportSize({ width: 1200, height: 900 });
|
||||||
await page.goto('/che/chief-center');
|
await page.goto('/che/chief-center');
|
||||||
await page.getByRole('button', { name: '1턴 명령 입력', exact: true }).click();
|
await page.getByRole('button', { name: '1턴 명령 입력', exact: true }).click();
|
||||||
@@ -1791,6 +1793,7 @@ test('uses the map to choose a nation target in the chief command window', async
|
|||||||
await expect(form.getByTestId('current-city-marker')).toHaveAttribute('aria-label', '현재 도시 업');
|
await expect(form.getByTestId('current-city-marker')).toHaveAttribute('aria-label', '현재 도시 업');
|
||||||
await expect(form.getByTestId('command-map-target-summary')).toContainText('수도 허창 · 도시 1개');
|
await expect(form.getByTestId('command-map-target-summary')).toContainText('수도 허창 · 도시 1개');
|
||||||
await expect(page).toHaveURL(/\/che\/chief-center$/);
|
await expect(page).toHaveURL(/\/che\/chief-center$/);
|
||||||
|
expect(JSON.stringify(requests)).toContain('"generalId":1');
|
||||||
await page.screenshot({ path: test.info().outputPath('chief-nation-map-option.png'), fullPage: true });
|
await page.screenshot({ path: test.info().outputPath('chief-nation-map-option.png'), fullPage: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
chief-command-map-live-test-placeholder
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
"test:e2e:join-live": "playwright test --config e2e/joinGeneral.live.playwright.config.mjs --tsconfig e2e/playwright.live.tsconfig.json",
|
"test:e2e:join-live": "playwright test --config e2e/joinGeneral.live.playwright.config.mjs --tsconfig e2e/playwright.live.tsconfig.json",
|
||||||
"test:e2e:npc-possession": "playwright test npcPossession.spec.ts --config e2e/playwright.config.mjs",
|
"test:e2e:npc-possession": "playwright test npcPossession.spec.ts --config e2e/playwright.config.mjs",
|
||||||
"test:e2e:join-layout": "playwright test joinLayout.spec.ts --config e2e/playwright.config.mjs",
|
"test:e2e:join-layout": "playwright test joinLayout.spec.ts --config e2e/playwright.config.mjs",
|
||||||
|
"test:e2e:chief-command-map-live": "playwright test --config e2e/chiefCommandMap.live.playwright.config.mjs --tsconfig e2e/playwright.live.tsconfig.json",
|
||||||
"test:e2e:npc-possession-live": "pnpm --filter @sammo-ts/infra prisma:generate && pnpm --filter @sammo-ts/common build && pnpm --filter @sammo-ts/logic build && pnpm --filter @sammo-ts/infra build && pnpm --filter @sammo-ts/game-engine build && pnpm --filter @sammo-ts/game-api build && playwright test --config e2e/npcPossession.live.playwright.config.mjs --tsconfig e2e/playwright.live.tsconfig.json",
|
"test:e2e:npc-possession-live": "pnpm --filter @sammo-ts/infra prisma:generate && pnpm --filter @sammo-ts/common build && pnpm --filter @sammo-ts/logic build && pnpm --filter @sammo-ts/infra build && pnpm --filter @sammo-ts/game-engine build && pnpm --filter @sammo-ts/game-api build && playwright test --config e2e/npcPossession.live.playwright.config.mjs --tsconfig e2e/playwright.live.tsconfig.json",
|
||||||
"test:e2e:die-on-prestart-live": "pnpm --filter @sammo-ts/infra prisma:generate && pnpm --filter @sammo-ts/common build && pnpm --filter @sammo-ts/logic build && pnpm --filter @sammo-ts/infra build && pnpm --filter @sammo-ts/game-engine build && pnpm --filter @sammo-ts/game-api build && playwright test --config e2e/dieOnPrestart.live.playwright.config.mjs --tsconfig e2e/playwright.live.tsconfig.json",
|
"test:e2e:die-on-prestart-live": "pnpm --filter @sammo-ts/infra prisma:generate && pnpm --filter @sammo-ts/common build && pnpm --filter @sammo-ts/logic build && pnpm --filter @sammo-ts/infra build && pnpm --filter @sammo-ts/game-engine build && pnpm --filter @sammo-ts/game-api build && playwright test --config e2e/dieOnPrestart.live.playwright.config.mjs --tsconfig e2e/playwright.live.tsconfig.json",
|
||||||
"test:e2e:default-recruit-commands-live": "pnpm --filter @sammo-ts/infra prisma:generate && pnpm --filter @sammo-ts/common build && pnpm --filter @sammo-ts/logic build && pnpm --filter @sammo-ts/infra build && pnpm --filter @sammo-ts/game-engine build && pnpm --filter @sammo-ts/game-api build && playwright test --config e2e/defaultRecruitCommands.live.playwright.config.mjs --tsconfig e2e/playwright.live.tsconfig.json",
|
"test:e2e:default-recruit-commands-live": "pnpm --filter @sammo-ts/infra prisma:generate && pnpm --filter @sammo-ts/common build && pnpm --filter @sammo-ts/logic build && pnpm --filter @sammo-ts/infra build && pnpm --filter @sammo-ts/game-engine build && pnpm --filter @sammo-ts/game-api build && playwright test --config e2e/defaultRecruitCommands.live.playwright.config.mjs --tsconfig e2e/playwright.live.tsconfig.json",
|
||||||
|
|||||||
@@ -55,7 +55,14 @@ const chiefApi = trpc as unknown as {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
world: {
|
world: {
|
||||||
getMap: { query: () => Promise<CommandMapData> };
|
getMap: {
|
||||||
|
query: (input: {
|
||||||
|
generalId: number;
|
||||||
|
neutralView?: boolean;
|
||||||
|
showMe?: boolean;
|
||||||
|
useCache?: boolean;
|
||||||
|
}) => Promise<CommandMapData>;
|
||||||
|
};
|
||||||
getMapLayout: { query: () => Promise<CommandMapLayout> };
|
getMapLayout: { query: () => Promise<CommandMapLayout> };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -117,7 +124,7 @@ const loadCommandTable = async (generalId: number) => {
|
|||||||
try {
|
try {
|
||||||
const [nextCommandTable, nextWorldMap, nextMapLayout] = await Promise.all([
|
const [nextCommandTable, nextWorldMap, nextMapLayout] = await Promise.all([
|
||||||
chiefApi.turns.getCommandTable.query({ generalId }),
|
chiefApi.turns.getCommandTable.query({ generalId }),
|
||||||
chiefApi.world.getMap.query().catch(() => null),
|
chiefApi.world.getMap.query({ generalId, showMe: true, useCache: true }).catch(() => null),
|
||||||
chiefApi.world.getMapLayout.query().catch(() => null),
|
chiefApi.world.getMapLayout.query().catch(() => null),
|
||||||
]);
|
]);
|
||||||
commandTable.value = nextCommandTable;
|
commandTable.value = nextCommandTable;
|
||||||
|
|||||||
Reference in New Issue
Block a user