test(platform-service): add repository tests for settings, referrals — 336 tests, 30.64% coverage
This commit is contained in:
parent
fbb2197f7c
commit
747d89fe4d
@ -0,0 +1,159 @@
|
||||
/**
|
||||
* Repository tests for referrals module — mocked Cosmos DB.
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
const mockFetchAll = vi.fn();
|
||||
const mockCreate = vi.fn();
|
||||
const mockRead = vi.fn();
|
||||
const mockReplace = vi.fn();
|
||||
|
||||
vi.mock('../../lib/cosmos.js', () => ({
|
||||
getContainer: vi.fn(() => ({
|
||||
items: {
|
||||
query: () => ({ fetchAll: mockFetchAll }),
|
||||
create: mockCreate,
|
||||
},
|
||||
item: () => ({ read: mockRead, replace: mockReplace }),
|
||||
})),
|
||||
}));
|
||||
|
||||
import {
|
||||
listAll,
|
||||
getByReferrer,
|
||||
getByReferredEmail,
|
||||
getById,
|
||||
create,
|
||||
update,
|
||||
countReferrals,
|
||||
} from './repository.js';
|
||||
import type { ReferralDoc } from './types.js';
|
||||
|
||||
const baseReferral: ReferralDoc = {
|
||||
id: 'ref_1',
|
||||
productId: 'lysnrai',
|
||||
referrerId: 'user_1',
|
||||
referrerEmail: 'referrer@example.com',
|
||||
referredUserId: null,
|
||||
referredEmail: 'new@example.com',
|
||||
status: 'pending',
|
||||
referrerRewardTokens: 1000,
|
||||
referredRewardTokens: 500,
|
||||
referrerRewarded: false,
|
||||
referredRewarded: false,
|
||||
createdAt: '2026-02-16T00:00:00Z',
|
||||
completedAt: null,
|
||||
};
|
||||
|
||||
describe('referrals repository', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listAll', () => {
|
||||
it('returns referrals', async () => {
|
||||
mockFetchAll.mockResolvedValue({ resources: [baseReferral] });
|
||||
const result = await listAll(100, 0, 'lysnrai');
|
||||
expect(result).toEqual([baseReferral]);
|
||||
});
|
||||
|
||||
it('returns empty array when no referrals', async () => {
|
||||
mockFetchAll.mockResolvedValue({ resources: [] });
|
||||
const result = await listAll();
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getByReferrer', () => {
|
||||
it('returns referrals for referrer', async () => {
|
||||
mockFetchAll.mockResolvedValue({ resources: [baseReferral] });
|
||||
const result = await getByReferrer('user_1', 'lysnrai');
|
||||
expect(result).toEqual([baseReferral]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getByReferredEmail', () => {
|
||||
it('returns referral when found', async () => {
|
||||
mockFetchAll.mockResolvedValue({ resources: [baseReferral] });
|
||||
const result = await getByReferredEmail('new@example.com', 'lysnrai');
|
||||
expect(result).toEqual(baseReferral);
|
||||
});
|
||||
|
||||
it('returns null when not found', async () => {
|
||||
mockFetchAll.mockResolvedValue({ resources: [] });
|
||||
const result = await getByReferredEmail('none@example.com', 'lysnrai');
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getById', () => {
|
||||
it('returns referral when found', async () => {
|
||||
mockRead.mockResolvedValue({ resource: baseReferral });
|
||||
const result = await getById('ref_1', 'user_1');
|
||||
expect(result).toEqual(baseReferral);
|
||||
});
|
||||
|
||||
it('returns null when not found', async () => {
|
||||
mockRead.mockRejectedValue(new Error('Not found'));
|
||||
const result = await getById('ref_1', 'user_1');
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null when resource is undefined', async () => {
|
||||
mockRead.mockResolvedValue({ resource: undefined });
|
||||
const result = await getById('ref_1', 'user_1');
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('create', () => {
|
||||
it('creates and returns referral', async () => {
|
||||
mockCreate.mockResolvedValue({ resource: baseReferral });
|
||||
const result = await create(baseReferral);
|
||||
expect(result).toEqual(baseReferral);
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', () => {
|
||||
it('merges updates and returns referral', async () => {
|
||||
mockRead.mockResolvedValue({ resource: baseReferral });
|
||||
const updated = { ...baseReferral, status: 'signed_up' as const };
|
||||
mockReplace.mockResolvedValue({ resource: updated });
|
||||
const result = await update('ref_1', 'user_1', { status: 'signed_up' });
|
||||
expect(result).toEqual(updated);
|
||||
});
|
||||
|
||||
it('returns null when not found', async () => {
|
||||
mockRead.mockResolvedValue({ resource: undefined });
|
||||
const result = await update('ref_1', 'user_1', { status: 'signed_up' });
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null on error', async () => {
|
||||
mockRead.mockRejectedValue(new Error('Not found'));
|
||||
const result = await update('ref_1', 'user_1', { status: 'signed_up' });
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('countReferrals', () => {
|
||||
it('returns counts', async () => {
|
||||
mockFetchAll
|
||||
.mockResolvedValueOnce({ resources: [10] })
|
||||
.mockResolvedValueOnce({ resources: [5] })
|
||||
.mockResolvedValueOnce({ resources: [2] });
|
||||
const result = await countReferrals('lysnrai');
|
||||
expect(result).toEqual({ total: 10, completed: 5, rewarded: 2 });
|
||||
});
|
||||
|
||||
it('returns zeros when no data', async () => {
|
||||
mockFetchAll
|
||||
.mockResolvedValueOnce({ resources: [] })
|
||||
.mockResolvedValueOnce({ resources: [] })
|
||||
.mockResolvedValueOnce({ resources: [] });
|
||||
const result = await countReferrals('lysnrai');
|
||||
expect(result).toEqual({ total: 0, completed: 0, rewarded: 0 });
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Repository tests for settings module — mocked Cosmos DB.
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
const mockRead = vi.fn();
|
||||
const mockUpsert = vi.fn();
|
||||
|
||||
vi.mock('../../lib/cosmos.js', () => ({
|
||||
getContainer: vi.fn(() => ({
|
||||
items: { upsert: mockUpsert },
|
||||
item: () => ({ read: mockRead }),
|
||||
})),
|
||||
}));
|
||||
|
||||
import { getSettingsId, getByUserId, upsert } from './repository.js';
|
||||
import type { UserSettingsDoc } from './types.js';
|
||||
|
||||
const baseSettings: UserSettingsDoc = {
|
||||
id: 'set_lysnrai_user_1',
|
||||
productId: 'lysnrai',
|
||||
userId: 'user_1',
|
||||
settings: { theme: 'dark', language: 'en' },
|
||||
deviceOverrides: { dev_mac_001: { volume: 0.8 } },
|
||||
createdAt: '2026-02-16T00:00:00Z',
|
||||
updatedAt: '2026-02-16T00:00:00Z',
|
||||
};
|
||||
|
||||
describe('settings repository', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('getSettingsId', () => {
|
||||
it('generates correct id format', () => {
|
||||
expect(getSettingsId('lysnrai', 'user_1')).toBe('set_lysnrai_user_1');
|
||||
});
|
||||
|
||||
it('handles different products', () => {
|
||||
expect(getSettingsId('mindlyst', 'user_2')).toBe('set_mindlyst_user_2');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getByUserId', () => {
|
||||
it('returns settings when found', async () => {
|
||||
mockRead.mockResolvedValue({ resource: baseSettings });
|
||||
const result = await getByUserId('user_1', 'lysnrai');
|
||||
expect(result).toEqual(baseSettings);
|
||||
});
|
||||
|
||||
it('returns null when not found', async () => {
|
||||
mockRead.mockRejectedValue(new Error('Not found'));
|
||||
const result = await getByUserId('user_1', 'lysnrai');
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null when resource is undefined', async () => {
|
||||
mockRead.mockResolvedValue({ resource: undefined });
|
||||
const result = await getByUserId('user_1', 'lysnrai');
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('upsert', () => {
|
||||
it('upserts and returns settings', async () => {
|
||||
mockUpsert.mockResolvedValue({ resource: baseSettings });
|
||||
const result = await upsert(baseSettings);
|
||||
expect(result).toEqual(baseSettings);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user