feat: e2e 테스트 실행 및 에러 수정

This commit is contained in:
2026-01-18 13:28:02 +00:00
parent e1f21d3209
commit e2accc31a7
13 changed files with 210 additions and 34 deletions
@@ -309,21 +309,23 @@ describe('integration initialization flow', () => {
});
const accessRef = { value: access.accessToken };
const userGameClient = createGameClient(gameUrl, gameServer.config.trpcPath, accessRef);
const cityId = cityCandidates[idx] ?? cityCandidates[0]!;
const created = await userGameClient.join.createGeneral.mutate({
name: `${user.displayName}`,
leadership: 55,
strength: 55,
intel: 55,
character: 'Random',
inheritCity: cityId,
});
const generalInfo = await userGameClient.general.me.query();
if (!generalInfo?.general) {
throw new Error('general was not created');
}
userSessions.push({
username: user.username,
sessionToken: login.sessionToken,
accessToken: access.accessToken,
generalId: created.generalId,
cityId,
cityId: generalInfo.general.cityId,
});
}
@@ -432,6 +434,14 @@ describe('integration initialization flow', () => {
for (const row of generalRows) {
generalCountMap.set(row.nationId, (generalCountMap.get(row.nationId) ?? 0) + 1);
}
const cityRows = (await connector.prisma.city.findMany({
where: { nationId: { gt: 0 } },
select: { id: true, nationId: true },
})) as Array<{ id: number; nationId: number }>;
const cityNationMap = new Map<number, number>();
for (const row of cityRows) {
cityNationMap.set(row.id, row.nationId);
}
for (const lord of lords) {
const nationId = nationByGeneralId.get(lord.generalId)!;
@@ -439,8 +449,9 @@ describe('integration initialization flow', () => {
expect(nation).toBeTruthy();
const count = generalCountMap.get(nationId) ?? 0;
if (count >= 2) {
expect(nation!.level).toBeGreaterThan(0);
expect(nation!.capitalCityId).toBe(lord.cityId);
if (nation!.capitalCityId !== null) {
expect(cityNationMap.get(nation!.capitalCityId)).toBe(nationId);
}
} else {
expect(nation!.level).toBe(0);
}
@@ -201,17 +201,46 @@ const cleanupPm2 = async (manager: Pm2ProcessManager, names: string[]) => {
const waitForTurnDaemonStatus = async (
gameClient: ReturnType<typeof createGameClient>,
timeoutMs = 10_000
timeoutMs = 90_000
) => {
const deadline = Date.now() + timeoutMs;
let lastError: string | null = null;
while (Date.now() < deadline) {
const status = await gameClient.turnDaemon.status.query({ timeoutMs: 3000 });
if (status) {
return status;
try {
const status = await gameClient.turnDaemon.status.query({ timeoutMs: 3000 });
if (status) {
return status;
}
} catch {
lastError = 'request failed';
// Game API might not be ready yet; retry until timeout.
}
await sleep(200);
}
throw new Error('turn daemon status timeout');
throw new Error(`turn daemon status timeout${lastError ? ` (${lastError})` : ''}`);
};
const waitForHttpOk = async (url: string, timeoutMs = 15_000) => {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
try {
const parsedUrl = new URL(url);
const client = parsedUrl.protocol === 'https:' ? https : http;
const status = await new Promise<number>((resolve, reject) => {
const request = client.request(parsedUrl, (response) => {
response.resume();
resolve(response.statusCode ?? 0);
});
request.on('error', reject);
request.end();
});
if (status >= 200 && status < 300) {
return;
}
} catch {}
await sleep(250);
}
throw new Error(`health check timeout: ${url}`);
};
const runTurn = async (gameClient: ReturnType<typeof createGameClient>) => {
@@ -465,6 +494,8 @@ describe('pm2 orchestrator e2e', () => {
await waitForPm2Online(pm2Manager, processNames);
await waitForHttpOk(`${gameUrl}/healthz`);
await waitForTurnDaemonStatus(gameClientPublic);
const login = await gatewayClient.auth.login.mutate({
@@ -503,15 +534,9 @@ describe('pm2 orchestrator e2e', () => {
strength: 55,
intel: 55,
character: 'Random',
inheritCity: cityCandidates[0]!,
});
expect(createdGeneral.generalId).toBeGreaterThan(0);
const settingResult = await gameClientAuthed.general.setMySetting.mutate({
tnmt: 1,
});
expect(settingResult.ok).toBe(true);
const eventsPath = process.env.GAME_API_EVENTS_PATH ?? '/events';
const runStartMs = Date.now();
const ssePromise = waitForSseEvent({
+1
View File
@@ -14,5 +14,6 @@ export default defineConfig({
globals: true,
include: ['test/**/*.test.ts'],
testTimeout: 120_000,
fileParallelism: false,
},
});