85 lines
3.4 KiB
TypeScript
85 lines
3.4 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
const tx = vi.hoisted(() => ({
|
|
offer: { update: vi.fn(), findUniqueOrThrow: vi.fn() },
|
|
offerVehicle: { deleteMany: vi.fn(), createMany: vi.fn() },
|
|
}))
|
|
|
|
vi.mock('../../lib/prisma', () => ({
|
|
prisma: {
|
|
offer: { findMany: vi.fn(), findFirstOrThrow: vi.fn(), findFirst: vi.fn(), create: vi.fn(), deleteMany: vi.fn(), updateMany: vi.fn() },
|
|
reservation: { count: vi.fn() },
|
|
$transaction: vi.fn(async (callback: (txArg: typeof tx) => unknown) => callback(tx)),
|
|
},
|
|
}))
|
|
|
|
import { prisma } from '../../lib/prisma'
|
|
import * as repo from './offer.repo'
|
|
|
|
describe('offer.repo edge behavior', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
tx.offer.update.mockReset()
|
|
tx.offer.findUniqueOrThrow.mockReset()
|
|
tx.offerVehicle.deleteMany.mockReset()
|
|
tx.offerVehicle.createMany.mockReset()
|
|
})
|
|
|
|
it('converts active and public query strings into boolean filters', () => {
|
|
repo.findMany('company_1', { active: 'false', public: 'true' })
|
|
|
|
expect(prisma.offer.findMany).toHaveBeenCalledWith({
|
|
where: { companyId: 'company_1', isActive: false, isPublic: true },
|
|
orderBy: { createdAt: 'desc' },
|
|
})
|
|
})
|
|
|
|
it('creates vehicle links only when explicit vehicle ids are supplied', async () => {
|
|
await repo.create('company_1', {
|
|
title: 'Summer',
|
|
type: 'PERCENTAGE',
|
|
discountValue: 10,
|
|
validFrom: '2026-07-01T00:00:00.000Z',
|
|
validUntil: '2026-07-31T23:59:59.000Z',
|
|
}, ['vehicle_1', 'vehicle_2'])
|
|
|
|
expect(prisma.offer.create).toHaveBeenCalledWith({
|
|
data: expect.objectContaining({
|
|
companyId: 'company_1',
|
|
validFrom: new Date('2026-07-01T00:00:00.000Z'),
|
|
validUntil: new Date('2026-07-31T23:59:59.000Z'),
|
|
vehicles: { create: [{ vehicleId: 'vehicle_1' }, { vehicleId: 'vehicle_2' }] },
|
|
}),
|
|
include: { vehicles: true },
|
|
})
|
|
})
|
|
|
|
it('replaces vehicle links inside the update transaction when vehicleIds are provided', async () => {
|
|
await repo.update('offer_1', { title: 'Updated', validFrom: '2026-08-01T00:00:00.000Z' }, ['vehicle_3'])
|
|
|
|
expect(prisma.$transaction).toHaveBeenCalled()
|
|
expect(tx.offer.update).toHaveBeenCalledWith({
|
|
where: { id: 'offer_1' },
|
|
data: expect.objectContaining({ title: 'Updated', validFrom: new Date('2026-08-01T00:00:00.000Z') }),
|
|
})
|
|
expect(tx.offerVehicle.deleteMany).toHaveBeenCalledWith({ where: { offerId: 'offer_1' } })
|
|
expect(tx.offerVehicle.createMany).toHaveBeenCalledWith({ data: [{ offerId: 'offer_1', vehicleId: 'vehicle_3' }] })
|
|
expect(tx.offer.findUniqueOrThrow).toHaveBeenCalledWith({ where: { id: 'offer_1' }, include: { vehicles: true } })
|
|
})
|
|
|
|
it('does not touch vehicle links when update omits vehicleIds', async () => {
|
|
await repo.update('offer_1', { description: 'Copy only' })
|
|
|
|
expect(tx.offerVehicle.deleteMany).not.toHaveBeenCalled()
|
|
expect(tx.offerVehicle.createMany).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('combines redemption counter and reservation count for stats', async () => {
|
|
vi.mocked(prisma.offer.findFirstOrThrow).mockResolvedValue({ id: 'offer_1', redemptionCount: 7 } as never)
|
|
vi.mocked(prisma.reservation.count).mockResolvedValue(3 as never)
|
|
|
|
await expect(repo.getStats('offer_1', 'company_1')).resolves.toEqual({ redemptions: 7, reservations: 3 })
|
|
expect(prisma.reservation.count).toHaveBeenCalledWith({ where: { offerId: 'offer_1' } })
|
|
})
|
|
})
|