From 747d89fe4d372f9bc4e77a17e9ec29b99bf203c3 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Mon, 16 Feb 2026 12:05:03 -0800 Subject: [PATCH] =?UTF-8?q?test(platform-service):=20add=20repository=20te?= =?UTF-8?q?sts=20for=20settings,=20referrals=20=E2=80=94=20336=20tests,=20?= =?UTF-8?q?30.64%=20coverage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/modules/referrals/repository.test.ts | 159 ++++++++++++++++++ .../src/modules/settings/repository.test.ts | 72 ++++++++ 2 files changed, 231 insertions(+) create mode 100644 services/platform-service/src/modules/referrals/repository.test.ts create mode 100644 services/platform-service/src/modules/settings/repository.test.ts diff --git a/services/platform-service/src/modules/referrals/repository.test.ts b/services/platform-service/src/modules/referrals/repository.test.ts new file mode 100644 index 00000000..6b6da830 --- /dev/null +++ b/services/platform-service/src/modules/referrals/repository.test.ts @@ -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 }); + }); + }); +}); diff --git a/services/platform-service/src/modules/settings/repository.test.ts b/services/platform-service/src/modules/settings/repository.test.ts new file mode 100644 index 00000000..54295120 --- /dev/null +++ b/services/platform-service/src/modules/settings/repository.test.ts @@ -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); + }); + }); +});