Files

57 lines
2.7 KiB
TypeScript

import { afterAll, beforeAll, expect, it, vi } from 'vitest';
import { DocumentReference, getFirestore } from 'firebase-admin/firestore';
import { fnPlanetEvolutionRecord } from '../src/fandom/evolution.js';
import { bootAdmin, shutdownAdmin } from './support.js';
const id = 'test-evolution-history';
beforeAll(() => { bootAdmin(); });
afterAll(async () => {
vi.restoreAllMocks();
await getFirestore().recursiveDelete(getFirestore().doc(`fandoms/${id}`));
await shutdownAdmin();
});
async function event(beforeStage: unknown, afterStage: unknown, eventId: string) {
const db = getFirestore();
const ref = db.doc(`fandoms/${id}`);
await ref.set({ ...(beforeStage === undefined ? {} : { stage: beforeStage }) });
const before = (await db.collection('fandoms').where('__name__', '==', id).get()).docs[0]!;
await ref.set({ stage: afterStage });
const after = (await db.collection('fandoms').where('__name__', '==', id).get()).docs[0]!;
return {
specversion: '1.0' as const, id: eventId, source: 'firestore',
type: 'google.cloud.firestore.document.v1.updated', time: new Date().toISOString(),
data: { before, after }, params: { fandomId: id },
location: 'asia-northeast3', project: 'demo-fanuzu', database: '(default)',
namespace: '', document: ref.path,
};
}
it('저장 실패를 재시도하고 동시 재전달에도 확정 진화를 한 번만 남긴다', async () => {
const input = await event(1, 3, 'confirmed/event');
const create = vi.spyOn(DocumentReference.prototype, 'create').mockRejectedValueOnce(new Error('write failed'));
try {
await expect(fnPlanetEvolutionRecord.run(input)).rejects.toThrow('write failed');
} finally {
create.mockRestore();
}
await Promise.all([fnPlanetEvolutionRecord.run(input), fnPlanetEvolutionRecord.run(input)]);
const records = await getFirestore().collection(`fandoms/${id}/stateHistory`).get();
expect(records.size).toBe(1);
const record = records.docs[0]!;
expect(record.get('kind')).toBe('evolution');
expect(record.get('fromStage')).toBe(1);
expect(record.get('toStage')).toBe(3);
expect(record.get('occurredAt').isEqual(input.data.after.updateTime)).toBe(true);
expect(record.get('participantIds')).toBeUndefined();
});
it('동일 Stage·하락·누락·범위 밖 수치를 진화로 기록하지 않는다', async () => {
const history = getFirestore().collection(`fandoms/${id}/stateHistory`);
const count = (await history.get()).size;
for (const [before, after] of [[3, 3], [3, 2], [undefined, 3], [-1, 1], [6, 7], [1, '2']]) {
await fnPlanetEvolutionRecord.run(await event(before, after, `skip-${before}-${after}`));
}
expect((await history.get()).size).toBe(count);
});