test: integration coverage for stores, services, MockAIService, and hooks
- Stores (29 tests): compareStore max-4 enforcement, toastStore unique IDs, shortlistStore dialog state, assistantStore context merge + clearConversation - Services (37 tests): needService CRUD, propertyService dashboard summary active-status filter, matchService computeMatchesForNeed + getStrongMatches, futureSignalService summary math (distribution totals, highConfidence count) - MockAIService (18 tests): follow-up question priority ordering, area ambiguity detection (ratio >8 and zero values), max-3 cap, trade-off risk logic (LOW/MEDIUM/HIGH thresholds), match explanation headline tiers, provenance shape - Hooks (20 tests): useNeeds/useProperties/useMatches envelope unwrap, disabled- when-empty guards, useCreateNeed/useCreateProperty mutations, useNeed/useMatchDetail All 257 tests pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { needService } from '../needService'
|
||||
|
||||
describe('needService', () => {
|
||||
describe('getAll', () => {
|
||||
it('returns a ListResponse with data and meta', async () => {
|
||||
const result = await needService.getAll()
|
||||
expect(Array.isArray(result.data)).toBe(true)
|
||||
expect(result.data.length).toBeGreaterThan(0)
|
||||
expect(result.meta.total).toBe(result.data.length)
|
||||
expect(result.meta.page).toBe(1)
|
||||
expect(result.meta.hasMore).toBe(false)
|
||||
})
|
||||
|
||||
it('each need has required fields', async () => {
|
||||
const { data } = await needService.getAll()
|
||||
for (const need of data) {
|
||||
expect(typeof need.id).toBe('string')
|
||||
expect(typeof need.companyName).toBe('string')
|
||||
expect(typeof need.assetType).toBe('string')
|
||||
expect(typeof need.requiredArea.min).toBe('number')
|
||||
expect(typeof need.requiredArea.max).toBe('number')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('getById', () => {
|
||||
it('returns a need for an existing id', async () => {
|
||||
const { data: all } = await needService.getAll()
|
||||
const id = all[0].id
|
||||
const result = await needService.getById(id)
|
||||
expect(result.data).not.toBeNull()
|
||||
expect(result.data?.id).toBe(id)
|
||||
})
|
||||
|
||||
it('returns null for a non-existent id', async () => {
|
||||
const result = await needService.getById('nonexistent-id')
|
||||
expect(result.data).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('create', () => {
|
||||
it('creates a new need and returns it', async () => {
|
||||
const { data: before } = await needService.getAll()
|
||||
const input = {
|
||||
companyName: 'Test GmbH',
|
||||
assetType: 'OFFICE' as const,
|
||||
requiredArea: { min: 200, max: 400 },
|
||||
preferredLocations: ['Zürich'],
|
||||
budgetRange: { maxPerSqm: 400, maxMonthlyTotal: 10000, currency: 'CHF' as const },
|
||||
organizationId: 'org-test',
|
||||
}
|
||||
const result = await needService.create(input)
|
||||
expect(result.data.companyName).toBe('Test GmbH')
|
||||
expect(typeof result.data.id).toBe('string')
|
||||
|
||||
const { data: after } = await needService.getAll()
|
||||
expect(after.length).toBe(before.length + 1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('update', () => {
|
||||
it('updates a need and reflects the change', async () => {
|
||||
const { data: all } = await needService.getAll()
|
||||
const target = all[0]
|
||||
const result = await needService.update(target.id, { companyName: 'Updated GmbH' })
|
||||
expect(result.data.id).toBe(target.id)
|
||||
expect(result.data.companyName).toBe('Updated GmbH')
|
||||
})
|
||||
})
|
||||
|
||||
describe('remove', () => {
|
||||
it('removes a need so it no longer appears in getAll', async () => {
|
||||
// Create a temporary need to avoid disturbing shared seed data
|
||||
const created = await needService.create({
|
||||
companyName: 'Temp GmbH',
|
||||
assetType: 'OFFICE' as const,
|
||||
requiredArea: { min: 100, max: 200 },
|
||||
preferredLocations: ['Bern'],
|
||||
budgetRange: { maxPerSqm: 300, maxMonthlyTotal: 5000, currency: 'CHF' as const },
|
||||
organizationId: 'org-test',
|
||||
})
|
||||
const id = created.data.id
|
||||
await needService.remove(id)
|
||||
const found = await needService.getById(id)
|
||||
expect(found.data).toBeNull()
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user