test(integration): verify committed read-model projections

This commit is contained in:
2026-08-09 23:55:07 +00:00
parent 6063b91b73
commit 6cc5157b6d
4 changed files with 29 additions and 1 deletions
@@ -306,6 +306,7 @@ integration('adjustGeneralIcon PostgreSQL persistence', () => {
CHECK (request_id <> '${rollbackRequestId}' OR status <> 'SUCCEEDED') CHECK (request_id <> '${rollbackRequestId}' OR status <> 'SUCCEEDED')
`); `);
await expect(execute(rollbackCommand)).rejects.toThrow(`violates check constraint "${rollbackConstraint}"`); await expect(execute(rollbackCommand)).rejects.toThrow(`violates check constraint "${rollbackConstraint}"`);
expect(hooks.takeCommittedReadModelChanges()).toBeNull();
expect(world.getGeneralById(targetGeneralId)).toMatchObject({ expect(world.getGeneralById(targetGeneralId)).toMatchObject({
picture: initialPicture, picture: initialPicture,
imageServer: initialImageServer, imageServer: initialImageServer,
@@ -334,6 +335,7 @@ integration('adjustGeneralIcon PostgreSQL persistence', () => {
); );
await createInputEvent(actorMismatchCommand, foreignUserId); await createInputEvent(actorMismatchCommand, foreignUserId);
await expect(execute(actorMismatchCommand)).rejects.toThrow('actor does not match'); await expect(execute(actorMismatchCommand)).rejects.toThrow('actor does not match');
expect(hooks.takeCommittedReadModelChanges()).toBeNull();
expect(world.getGeneralById(targetGeneralId)).toMatchObject({ expect(world.getGeneralById(targetGeneralId)).toMatchObject({
picture: initialPicture, picture: initialPicture,
imageServer: initialImageServer, imageServer: initialImageServer,
@@ -357,6 +359,13 @@ integration('adjustGeneralIcon PostgreSQL persistence', () => {
generalId: targetGeneralId, generalId: targetGeneralId,
updated: true, updated: true,
}); });
expect(hooks.takeCommittedReadModelChanges()).toMatchObject({
generalIds: [targetGeneralId],
mapGeneralIds: [],
frontStatusGeneralIds: [],
lobbyGeneralIds: [targetGeneralId],
reservedGeneralIds: [],
});
expect(world.getGeneralById(targetGeneralId)).toMatchObject({ expect(world.getGeneralById(targetGeneralId)).toMatchObject({
picture: nextPicture, picture: nextPicture,
imageServer: nextImageServer, imageServer: nextImageServer,
+7
View File
@@ -84,6 +84,13 @@ runner는 test 시작 전에 실패합니다. 지원 mode에 marker가 하나도
실행 group의 marker 정규식이 비어도 전체 파일로 선택 범위를 넓히지 않고 실행 group의 marker 정규식이 비어도 전체 파일로 선택 범위를 넓히지 않고
실패합니다. 실패합니다.
`external_fixture` mode는 격리 빈 schema로 만들 수 없는 명시적 예외입니다.
현재 `CURRENT_SEASON_FIXTURE_DATABASE_URL`은 별도 Ref 현 시즌 importer가 만든
read-only snapshot을 요구하므로 조건부 runner의 pass/skip 집계에 포함하지
않습니다. 이 mode는 registry 누락을 숨기기 위한 일반 제외 수단이 아니며,
해당 fixture 검증은 실제 imported snapshot URL을 주입해 별도로 실행하고 결과를
외부 fixture 범위로 보고해야 합니다.
관리자 시간 조정의 PostgreSQL 경계는 관리자 시간 조정의 PostgreSQL 경계는
`runtimeClockShiftPersistence.integration.test.ts`, gateway action `runtimeClockShiftPersistence.integration.test.ts`, gateway action
`PARTIAL → APPLIED` 경계는 `gatewayRuntimeAction.integration.test.ts`입니다. `PARTIAL → APPLIED` 경계는 `gatewayRuntimeAction.integration.test.ts`입니다.
@@ -1,5 +1,6 @@
# Environment variable Execution mode # Environment variable Execution mode
CREATE_GENERAL_DATABASE_URL create_general CREATE_GENERAL_DATABASE_URL create_general
CURRENT_SEASON_FIXTURE_DATABASE_URL external_fixture
GATEWAY_RUNTIME_ACTION_DATABASE_URL gateway_runtime GATEWAY_RUNTIME_ACTION_DATABASE_URL gateway_runtime
GATEWAY_OPERATION_DATABASE_URL gateway_runtime GATEWAY_OPERATION_DATABASE_URL gateway_runtime
GATEWAY_RELEASE_DATABASE_URL gateway_runtime GATEWAY_RELEASE_DATABASE_URL gateway_runtime
1 # Environment variable Execution mode
2 CREATE_GENERAL_DATABASE_URL create_general
3 CURRENT_SEASON_FIXTURE_DATABASE_URL external_fixture
4 GATEWAY_RUNTIME_ACTION_DATABASE_URL gateway_runtime
5 GATEWAY_OPERATION_DATABASE_URL gateway_runtime
6 GATEWAY_RELEASE_DATABASE_URL gateway_runtime
+12 -1
View File
@@ -41,7 +41,7 @@ node_tag=$(printf '%s' "${CI_NODE_INDEX:-local}" | tr -cd 'a-zA-Z0-9_' | tr 'A-Z
run_id=$(date -u +%m%d%H%M%S)_$$_${node_tag} run_id=$(date -u +%m%d%H%M%S)_$$_${node_tag}
export CONDITIONAL_INTEGRATION_RUN_ID=$run_id export CONDITIONAL_INTEGRATION_RUN_ID=$run_id
schema_ownership_token="sammo-conditional-integration:$run_id" schema_ownership_token="sammo-conditional-integration:$run_id"
supported_registry_modes="core create_general gateway_runtime immediate_action npc_possession reference_live_sortie reference_npc_possession select_pool" supported_registry_modes="core create_general external_fixture gateway_runtime immediate_action npc_possession reference_live_sortie reference_npc_possession select_pool"
term_grace_seconds=${CONDITIONAL_INTEGRATION_TERM_GRACE_SECONDS:-10} term_grace_seconds=${CONDITIONAL_INTEGRATION_TERM_GRACE_SECONDS:-10}
case "$term_grace_seconds" in case "$term_grace_seconds" in
''|*[!0-9]*) ''|*[!0-9]*)
@@ -88,6 +88,15 @@ done
report_dir=$(mktemp -d) report_dir=$(mktemp -d)
summary_file="$report_dir/summary.tsv" summary_file="$report_dir/summary.tsv"
validated_registry_file="$report_dir/validated-registry.tsv" validated_registry_file="$report_dir/validated-registry.tsv"
image_upload_secret_file="$report_dir/image-upload-secret"
(
umask 077
node --input-type=module -e \
'import { randomBytes } from "node:crypto"; process.stdout.write(randomBytes(32).toString("hex"));' \
>"$image_upload_secret_file"
)
export GAME_IMAGE_UPLOAD_SECRET_FILE=$image_upload_secret_file
export GATEWAY_IMAGE_UPLOAD_SECRET_FILE=$image_upload_secret_file
active_process_group= active_process_group=
cleanup_resources_started=0 cleanup_resources_started=0
@@ -452,7 +461,9 @@ validate_marker_registry
pnpm install --frozen-lockfile pnpm install --frozen-lockfile
pnpm --filter @sammo-ts/infra prisma:generate pnpm --filter @sammo-ts/infra prisma:generate
pnpm --filter @sammo-ts/common build pnpm --filter @sammo-ts/common build
pnpm --filter @sammo-ts/logic build
pnpm --filter @sammo-ts/infra build pnpm --filter @sammo-ts/infra build
pnpm --filter @sammo-ts/game-engine build
GATEWAY_MIGRATION_TEST_DATABASE_URL=$base_database_url \ GATEWAY_MIGRATION_TEST_DATABASE_URL=$base_database_url \
pnpm --filter @sammo-ts/infra verify:migration:account-icon pnpm --filter @sammo-ts/infra verify:migration:account-icon