From 2c51d073cc7302516008974d42c57149d1316546 Mon Sep 17 00:00:00 2001 From: hided62 Date: Sat, 25 Jul 2026 23:13:11 +0000 Subject: [PATCH] test(game-engine): cover invader actions through month boundary --- .../test/monthlyInvaderAction.test.ts | 52 +++++++++++++------ ...thlyInvaderPersistence.integration.test.ts | 33 ++++++------ 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/app/game-engine/test/monthlyInvaderAction.test.ts b/app/game-engine/test/monthlyInvaderAction.test.ts index edc4098..380c3d1 100644 --- a/app/game-engine/test/monthlyInvaderAction.test.ts +++ b/app/game-engine/test/monthlyInvaderAction.test.ts @@ -288,28 +288,37 @@ describe('invader monthly actions', () => { generals: [buildGeneral(), buildGeneral({ id: 2, name: 'ⓞ도시2대왕', nationId: 2, cityId: 2 })], events: [autoDeleteEvent], }); - harness.world.applyDiplomacyPatch({ + const state = { ...harness.state, currentYear: 199, currentMonth: 12 }; + let world: InMemoryTurnWorld | null = null; + const handler = createAutoDeleteInvaderHandler({ + getWorld: () => world, + reservedTurns: harness.reservedTurns, + }); + world = new InMemoryTurnWorld(state, harness.snapshot, { + schedule: { entries: [{ startMinute: 0, tickMinutes: 10 }] }, + calendarHandler: createMonthlyEventHandler({ + getWorld: () => world, + startYear: 190, + actions: new Map([['AutoDeleteInvader', handler]]), + }), + }); + world.applyDiplomacyPatch({ srcNationId: 2, destNationId: 1, patch: { state: 1, term: 24 }, }); - const handler = createAutoDeleteInvaderHandler({ - getWorld: () => harness.world, - reservedTurns: harness.reservedTurns, - }); - const environment = { ...harness.environment, currentEventID: 8 }; - await handler([2], environment, autoDeleteEvent); - expect(harness.world.listEvents().map((entry) => entry.id)).toContain(8); + await world.advanceMonth(new Date('0200-01-01T00:00:00.000Z')); + expect(world.listEvents().map((entry) => entry.id)).toContain(8); - harness.world.applyDiplomacyPatch({ + world.applyDiplomacyPatch({ srcNationId: 2, destNationId: 1, patch: { state: 2, term: 0 }, }); - await handler([2], environment, autoDeleteEvent); + await world.advanceMonth(new Date('0200-02-01T00:00:00.000Z')); - expect(harness.world.listEvents().map((entry) => entry.id)).not.toContain(8); + expect(world.listEvents().map((entry) => entry.id)).not.toContain(8); expect(harness.reservedTurns.getGeneralTurns(2)).toEqual( Array.from({ length: 30 }, () => ({ action: 'che_방랑', args: {} })) ); @@ -330,14 +339,23 @@ describe('invader monthly actions', () => { events: [endingEvent], meta: { isunited: 1, refreshLimit: 3 }, }); - const handler = createInvaderEndingHandler({ getWorld: () => harness.world }); - const environment = { ...harness.environment, currentEventID: 9 }; + const state = { ...harness.state, currentYear: 199, currentMonth: 12 }; + let world: InMemoryTurnWorld | null = null; + const handler = createInvaderEndingHandler({ getWorld: () => world }); + world = new InMemoryTurnWorld(state, harness.snapshot, { + schedule: { entries: [{ startMinute: 0, tickMinutes: 10 }] }, + calendarHandler: createMonthlyEventHandler({ + getWorld: () => world, + startYear: 190, + actions: new Map([['InvaderEnding', handler]]), + }), + }); - await handler([], environment, endingEvent); + await world.advanceMonth(new Date('0200-01-01T00:00:00.000Z')); - expect(harness.world.getState().meta).toMatchObject({ isunited: 3, refreshLimit: 300 }); - expect(harness.world.listEvents()).toHaveLength(0); - expect(harness.world.peekDirtyState().logs.map((log) => log.text)).toEqual([ + expect(world.getState().meta).toMatchObject({ isunited: 3, refreshLimit: 300 }); + expect(world.listEvents()).toHaveLength(0); + expect(world.peekDirtyState().logs.map((log) => log.text)).toEqual([ '【이벤트】이민족을 모두 소탕했습니다!', '【이벤트】중원은 당분간 태평성대를 누릴 것입니다.', ]); diff --git a/app/game-engine/test/monthlyInvaderPersistence.integration.test.ts b/app/game-engine/test/monthlyInvaderPersistence.integration.test.ts index 97d64f6..0b34277 100644 --- a/app/game-engine/test/monthlyInvaderPersistence.integration.test.ts +++ b/app/game-engine/test/monthlyInvaderPersistence.integration.test.ts @@ -5,6 +5,7 @@ import type { City, Nation } from '@sammo-ts/logic'; import { createDatabaseTurnHooks } from '../src/turn/databaseHooks.js'; import { InMemoryTurnWorld } from '../src/turn/inMemoryWorld.js'; import { createRaiseInvaderHandler } from '../src/turn/monthlyInvaderAction.js'; +import { createMonthlyEventHandler } from '../src/turn/monthlyEventHandler.js'; import { InMemoryReservedTurnStore } from '../src/turn/reservedTurnStore.js'; import { buildCommandEnv } from '../src/turn/reservedTurnCommands.js'; import type { TurnEvent, TurnGeneral, TurnWorldSnapshot, TurnWorldState } from '../src/turn/types.js'; @@ -234,8 +235,8 @@ integration('RaiseInvader database persistence', () => { const stateRow = await db.worldState.create({ data: { scenarioCode: 'monthly-invader-persistence', - currentYear: 200, - currentMonth: 1, + currentYear: 199, + currentMonth: 12, tickSeconds: 600, config: {}, meta: { @@ -248,8 +249,8 @@ integration('RaiseInvader database persistence', () => { }); const state: TurnWorldState = { id: stateRow.id, - currentYear: 200, - currentMonth: 1, + currentYear: 199, + currentMonth: 12, tickSeconds: 600, lastTurnTime: new Date('0200-01-01T00:00:00.000Z'), meta: { @@ -276,30 +277,26 @@ integration('RaiseInvader database persistence', () => { events: [sourceEvent], initialEvents: [], }; - const world = new InMemoryTurnWorld(state, snapshot, { - schedule: { entries: [{ startMinute: 0, tickMinutes: 10 }] }, - }); const reservedTurns = new InMemoryReservedTurnStore(db, { maxGeneralTurns: 30, maxNationTurns: 12 }); + let world: InMemoryTurnWorld | null = null; const handler = createRaiseInvaderHandler({ getWorld: () => world, reservedTurns, env: buildCommandEnv(snapshot.scenarioConfig), loadArchivedNationMaxId: async () => 0, }); + world = new InMemoryTurnWorld(state, snapshot, { + schedule: { entries: [{ startMinute: 0, tickMinutes: 10 }] }, + calendarHandler: createMonthlyEventHandler({ + getWorld: () => world, + startYear: 190, + actions: new Map([['RaiseInvader', handler]]), + }), + }); const dbHooks = await createDatabaseTurnHooks(databaseUrl!, world, { reservedTurns }); try { - await handler( - [10, 150, 100, 20], - { - year: 200, - month: 1, - startyear: 190, - currentEventID: sourceEventId, - turnTime: state.lastTurnTime, - }, - sourceEvent - ); + await world.advanceMonth(new Date('0200-01-01T00:00:00.000Z')); await dbHooks.hooks.flushChanges?.({ lastTurnTime: state.lastTurnTime.toISOString(), processedGenerals: 0,