Files
core2026/app/gateway-api/test/profileSeedCli.integration.test.ts
T

102 lines
4.4 KiB
TypeScript

import { spawn } from 'node:child_process';
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import { createGamePostgresConnector } from '@sammo-ts/infra';
import { describe, expect, it } from 'vitest';
const databaseUrl = process.env.PROFILE_SEED_CLI_DATABASE_URL;
const describeDatabase = describe.runIf(Boolean(databaseUrl));
const workspaceRoot = path.resolve(process.cwd(), '../..');
const runSeedCli = async (requestFile: string): Promise<{ code: number | null; output: string }> =>
new Promise((resolve) => {
const child = spawn(process.execPath, [path.join(workspaceRoot, 'app/gateway-api/dist/index.js')], {
cwd: workspaceRoot,
env: {
...process.env,
DATABASE_URL: databaseUrl,
GATEWAY_ROLE: 'profile-seed',
PROFILE_SEED_REQUEST_FILE: requestFile,
},
stdio: ['ignore', 'pipe', 'pipe'],
});
let output = '';
child.stdout.on('data', (chunk) => {
output += chunk.toString();
});
child.stderr.on('data', (chunk) => {
output += chunk.toString();
});
child.on('close', (code) => resolve({ code, output }));
});
describeDatabase('selected workspace profile seed CLI', () => {
it('seeds through the built gateway artifact with the serialized operation identity', async () => {
if (!databaseUrl) {
throw new Error('PROFILE_SEED_CLI_DATABASE_URL is required.');
}
const tempDirectory = await fs.mkdtemp(path.join(os.tmpdir(), 'profile-seed-cli-test-'));
const requestFile = path.join(tempDirectory, 'request.json');
const connector = createGamePostgresConnector({ url: databaseUrl });
try {
await fs.writeFile(
requestFile,
JSON.stringify({
scenarioId: 1010,
tickSeconds: 60,
now: '2036-03-03T00:00:00.000Z',
installOptions: {
serverId: 'selected-cli-seed',
installOperationId: 'selected-cli-operation',
installCommitSha: 'selected-cli-commit',
},
adminUser: {
id: 'selected-cli-admin',
username: 'selected-cli-admin',
displayName: '선택 CLI 관리자',
},
}),
{ encoding: 'utf8', mode: 0o600 }
);
const result = await runSeedCli(requestFile);
expect(result, result.output).toMatchObject({ code: 0 });
await connector.connect();
const world = await connector.prisma.worldState.findFirstOrThrow();
expect(world).toMatchObject({
scenarioCode: '1010',
meta: {
installOperationId: 'selected-cli-operation',
installCommitSha: 'selected-cli-commit',
},
});
const adminGeneral = await connector.prisma.general.findFirstOrThrow({
where: { userId: 'selected-cli-admin' },
});
expect(adminGeneral).toMatchObject({ meta: { createdBy: 'admin-seed' } });
const history = await connector.prisma.gameHistory.findUniqueOrThrow({
where: { serverId: 'selected-cli-seed' },
});
const retry = await runSeedCli(requestFile);
expect(retry, retry.output).toMatchObject({ code: 0 });
await expect(connector.prisma.worldState.findFirstOrThrow()).resolves.toEqual(world);
await expect(
connector.prisma.general.findFirstOrThrow({ where: { userId: 'selected-cli-admin' } })
).resolves.toEqual(adminGeneral);
await expect(
connector.prisma.gameHistory.findUniqueOrThrow({ where: { serverId: 'selected-cli-seed' } })
).resolves.toEqual(history);
await expect(
connector.prisma.gameHistory.count({ where: { serverId: 'selected-cli-seed' } })
).resolves.toBe(1);
} finally {
await connector.prisma.gameHistory.deleteMany({ where: { serverId: 'selected-cli-seed' } });
await connector.disconnect();
await fs.rm(tempDirectory, { recursive: true, force: true });
}
});
});