57 lines
2.7 KiB
TypeScript
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);
|
|
});
|