import { describe, it, expect } from 'vitest' import { matchService } from '../matchService' describe('matchService', () => { describe('getAll', () => { it('returns a ListResponse with match data', async () => { const result = await matchService.getAll() expect(Array.isArray(result.data)).toBe(true) expect(result.data.length).toBeGreaterThan(0) expect(result.meta!.total).toBe(result.data.length) }) it('each match has required fields', async () => { const { data } = await matchService.getAll() for (const m of data) { expect(typeof m.id).toBe('string') expect(typeof m.needId).toBe('string') expect(typeof m.propertyId).toBe('string') expect(typeof m.matchScore).toBe('number') expect(m.matchScore).toBeGreaterThanOrEqual(0) expect(m.matchScore).toBeLessThanOrEqual(100) } }) }) describe('getById', () => { it('returns a match for an existing id', async () => { const { data: all } = await matchService.getAll() const id = all[0].id const result = await matchService.getById(id) expect(result.data?.id).toBe(id) }) it('returns null for an unknown id', async () => { const result = await matchService.getById('no-such-match') expect(result.data).toBeNull() }) }) describe('getByNeed', () => { it('returns only matches for the given needId', async () => { const { data: all } = await matchService.getAll() const needId = all[0].needId const result = await matchService.getByNeed(needId) expect(result.data.every(m => m.needId === needId)).toBe(true) }) }) describe('getByProperty', () => { it('returns only matches for the given propertyId', async () => { const { data: all } = await matchService.getAll() const propertyId = all[0].propertyId const result = await matchService.getByProperty(propertyId) expect(result.data.every(m => m.propertyId === propertyId)).toBe(true) }) }) describe('getScoreBreakdown', () => { it('returns a ScoreBreakdown for a valid match', async () => { const { data: all } = await matchService.getAll() const matchWithBreakdown = all.find(m => !!m.scoreBreakdown) if (!matchWithBreakdown) return // seed data may not always have breakdowns const result = await matchService.getScoreBreakdown(matchWithBreakdown.id) expect(result.data).not.toBeNull() }) it('returns null for an unknown match', async () => { const result = await matchService.getScoreBreakdown('no-such-match') expect(result.data).toBeNull() }) }) describe('computeMatchesForNeed', () => { it('returns computed matches for a valid needId', async () => { const result = await matchService.computeMatchesForNeed('need-001') expect(result.data.length).toBeGreaterThan(0) expect(result.data.every(m => m.needId === 'need-001')).toBe(true) }) it('returns empty array for unknown needId', async () => { const result = await matchService.computeMatchesForNeed('no-such-need') expect(result.data).toEqual([]) }) }) describe('getStrongMatches', () => { it('returns only matches at or above the threshold', async () => { const minScore = 70 const result = await matchService.getStrongMatches(minScore) expect(result.every(m => m.matchScore >= minScore)).toBe(true) }) it('returns at most 5 items', async () => { const result = await matchService.getStrongMatches(0) expect(result.length).toBeLessThanOrEqual(5) }) it('each item has propertyTitle and topReason', async () => { const result = await matchService.getStrongMatches(0) for (const item of result) { expect(typeof item.propertyTitle).toBe('string') expect(typeof item.topReason).toBe('string') expect(typeof item.matchScore).toBe('number') } }) }) })