duoqi-api/src/__tests__/services/app/bootstrap-service.test.ts

80 lines
2.8 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
import { db } from '../../../db/client.js';
import { getBootstrap } from '../../../services/app/bootstrap-service.js';
function selectRows(rows: unknown[]) {
return {
from: vi.fn().mockReturnValue({
where: vi.fn().mockReturnValue({
orderBy: vi.fn().mockResolvedValue(rows),
limit: vi.fn().mockResolvedValue(rows),
then: (resolve: (value: unknown) => unknown) => Promise.resolve(rows).then(resolve),
}),
orderBy: vi.fn().mockResolvedValue(rows),
}),
};
}
function mockSelectQueue(queue: unknown[][]) {
let index = 0;
vi.mocked(db.select).mockImplementation((() => {
const rows = index < queue.length ? queue[index]! : [];
index += 1;
return selectRows(rows);
}) as never);
}
function mockUpdate() {
return { set: vi.fn().mockReturnValue({ where: vi.fn().mockResolvedValue(undefined) }) } as never;
}
describe('bootstrap-service', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('includes wallet, inventory, shop catalog, ad benefits, and subscription in bootstrap', async () => {
mockSelectQueue([
[{ id: 'user-1', nickname: '多奇', avatarUrl: null, tier: 'free', xpTotal: 100 }],
// getProgressSummary
[{ id: 'user-1', tier: 'free', xpTotal: 100, activeTrackId: null, dailyAttemptsLeft: 5, dailyAttemptsDate: new Date(), checkInDays: 1, lastCheckInDate: new Date(), streakProtectedUntil: null, heartsRemaining: 5 }],
[{ tier: 'free', heartsRemaining: 5, heartsLastRestore: null }],
[{ streakDays: 1, streakLastDate: new Date() }],
[],
[{ id: 'user-1', tier: 'free', xpTotal: 100, activeTrackId: null, dailyAttemptsLeft: 5, dailyAttemptsDate: new Date(), checkInDays: 1, lastCheckInDate: new Date(), streakProtectedUntil: null, heartsRemaining: 5 }],
[{ used: 1, restored: 0 }],
// getThemeTracks
[],
// getClientSubscription
[],
// getCoinBalance
[{ coinsBalance: 260 }],
// getClientInventory
[{ itemId: 'hint_feather', quantity: 2, activeUntil: null, metadata: null }],
]);
vi.mocked(db.update).mockReturnValue(mockUpdate());
const result = await getBootstrap('user-1');
expect(result.user).toEqual({
id: 'user-1',
nickname: '多奇',
avatarUrl: null,
tier: 'free',
level: 2,
});
expect(result.wallet).toEqual({ coinsBalance: 260 });
expect(result.inventory.items).toEqual([
{ itemId: 'hint_feather', quantity: 2, activeUntil: null, metadata: null },
]);
expect(result.shop.products.map((product) => product.id)).toContain('hint-feather');
expect(result.shopBenefits).toBe(result.shop.benefits);
expect(result.subscription).toEqual({
status: 'none',
tier: 'free',
expiresAt: null,
autoRenew: false,
});
});
});