feat(payments): add Order & Escrow repository tests, prisma config, docs
Add 26 unit tests for PrismaOrderRepository and PrismaEscrowRepository covering CRUD operations, pagination, domain mapping (bigint → Money), idempotency key lookup, and escrow dispute workflow fields. Update prisma.config.ts with dotenv import and seed command for Prisma 7. Add architecture summary and codebase overview documentation files. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
import { type EscrowStatus } from '@prisma/client';
|
||||
import { PrismaEscrowRepository } from '../repositories/prisma-escrow.repository';
|
||||
|
||||
describe('PrismaEscrowRepository', () => {
|
||||
let repository: PrismaEscrowRepository;
|
||||
let mockPrisma: {
|
||||
escrow: {
|
||||
findUnique: ReturnType<typeof vi.fn>;
|
||||
create: ReturnType<typeof vi.fn>;
|
||||
update: ReturnType<typeof vi.fn>;
|
||||
};
|
||||
};
|
||||
|
||||
const now = new Date('2026-04-01T10:00:00Z');
|
||||
const later = new Date('2026-04-01T10:05:00Z');
|
||||
const heldDate = new Date('2026-04-01T10:02:00Z');
|
||||
|
||||
const mockPrismaEscrow = {
|
||||
id: 'escrow-1',
|
||||
orderId: 'order-1',
|
||||
amountVND: 500_000_000n,
|
||||
feeVND: 25_000_000n,
|
||||
status: 'PENDING' as EscrowStatus,
|
||||
heldAt: null as Date | null,
|
||||
releasedAt: null as Date | null,
|
||||
disputeReason: null as string | null,
|
||||
disputedAt: null as Date | null,
|
||||
createdAt: now,
|
||||
updatedAt: later,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
mockPrisma = {
|
||||
escrow: {
|
||||
findUnique: vi.fn(),
|
||||
create: vi.fn(),
|
||||
update: vi.fn(),
|
||||
},
|
||||
};
|
||||
repository = new PrismaEscrowRepository(mockPrisma as any);
|
||||
});
|
||||
|
||||
describe('findById', () => {
|
||||
it('returns domain entity when escrow exists', async () => {
|
||||
mockPrisma.escrow.findUnique.mockResolvedValue(mockPrismaEscrow);
|
||||
|
||||
const result = await repository.findById('escrow-1');
|
||||
|
||||
expect(mockPrisma.escrow.findUnique).toHaveBeenCalledWith({
|
||||
where: { id: 'escrow-1' },
|
||||
});
|
||||
expect(result).not.toBeNull();
|
||||
expect(result!.id).toBe('escrow-1');
|
||||
expect(result!.orderId).toBe('order-1');
|
||||
expect(result!.amount.value).toBe(500_000_000n);
|
||||
expect(result!.fee.value).toBe(25_000_000n);
|
||||
expect(result!.status).toBe('PENDING');
|
||||
expect(result!.heldAt).toBeNull();
|
||||
expect(result!.releasedAt).toBeNull();
|
||||
expect(result!.disputeReason).toBeNull();
|
||||
expect(result!.disputedAt).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null when escrow does not exist', async () => {
|
||||
mockPrisma.escrow.findUnique.mockResolvedValue(null);
|
||||
|
||||
const result = await repository.findById('nonexistent');
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('findByOrderId', () => {
|
||||
it('returns domain entity when escrow exists for order', async () => {
|
||||
mockPrisma.escrow.findUnique.mockResolvedValue(mockPrismaEscrow);
|
||||
|
||||
const result = await repository.findByOrderId('order-1');
|
||||
|
||||
expect(mockPrisma.escrow.findUnique).toHaveBeenCalledWith({
|
||||
where: { orderId: 'order-1' },
|
||||
});
|
||||
expect(result).not.toBeNull();
|
||||
expect(result!.orderId).toBe('order-1');
|
||||
});
|
||||
|
||||
it('returns null when no escrow exists for order', async () => {
|
||||
mockPrisma.escrow.findUnique.mockResolvedValue(null);
|
||||
|
||||
const result = await repository.findByOrderId('order-999');
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('save', () => {
|
||||
it('persists a new escrow with correct field mapping', async () => {
|
||||
mockPrisma.escrow.create.mockResolvedValue(mockPrismaEscrow);
|
||||
|
||||
const { EscrowEntity } = await import('../../domain/entities/escrow.entity');
|
||||
const { Money } = await import('../../domain/value-objects/money.vo');
|
||||
|
||||
const amount = Money.create(500_000_000n).unwrap();
|
||||
const fee = Money.create(25_000_000n).unwrap();
|
||||
|
||||
const entity = new EscrowEntity('escrow-1', {
|
||||
orderId: 'order-1',
|
||||
amount,
|
||||
fee,
|
||||
status: 'PENDING',
|
||||
heldAt: null,
|
||||
releasedAt: null,
|
||||
disputeReason: null,
|
||||
disputedAt: null,
|
||||
});
|
||||
|
||||
await repository.save(entity);
|
||||
|
||||
expect(mockPrisma.escrow.create).toHaveBeenCalledWith({
|
||||
data: {
|
||||
id: 'escrow-1',
|
||||
orderId: 'order-1',
|
||||
amountVND: 500_000_000n,
|
||||
feeVND: 25_000_000n,
|
||||
status: 'PENDING',
|
||||
heldAt: null,
|
||||
releasedAt: null,
|
||||
disputeReason: null,
|
||||
disputedAt: null,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('persists escrow with held status and heldAt date', async () => {
|
||||
const heldEscrow = {
|
||||
...mockPrismaEscrow,
|
||||
status: 'HELD' as EscrowStatus,
|
||||
heldAt: heldDate,
|
||||
};
|
||||
mockPrisma.escrow.create.mockResolvedValue(heldEscrow);
|
||||
|
||||
const { EscrowEntity } = await import('../../domain/entities/escrow.entity');
|
||||
const { Money } = await import('../../domain/value-objects/money.vo');
|
||||
|
||||
const amount = Money.create(500_000_000n).unwrap();
|
||||
const fee = Money.create(25_000_000n).unwrap();
|
||||
|
||||
const entity = new EscrowEntity('escrow-1', {
|
||||
orderId: 'order-1',
|
||||
amount,
|
||||
fee,
|
||||
status: 'HELD',
|
||||
heldAt: heldDate,
|
||||
releasedAt: null,
|
||||
disputeReason: null,
|
||||
disputedAt: null,
|
||||
});
|
||||
|
||||
await repository.save(entity);
|
||||
|
||||
expect(mockPrisma.escrow.create).toHaveBeenCalledWith({
|
||||
data: expect.objectContaining({
|
||||
status: 'HELD',
|
||||
heldAt: heldDate,
|
||||
}),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', () => {
|
||||
it('updates status and temporal fields', async () => {
|
||||
const releasedDate = new Date('2026-04-01T12:00:00Z');
|
||||
mockPrisma.escrow.update.mockResolvedValue({
|
||||
...mockPrismaEscrow,
|
||||
status: 'RELEASED',
|
||||
heldAt: heldDate,
|
||||
releasedAt: releasedDate,
|
||||
});
|
||||
|
||||
const { EscrowEntity } = await import('../../domain/entities/escrow.entity');
|
||||
const { Money } = await import('../../domain/value-objects/money.vo');
|
||||
|
||||
const amount = Money.create(500_000_000n).unwrap();
|
||||
const fee = Money.create(25_000_000n).unwrap();
|
||||
|
||||
const entity = new EscrowEntity('escrow-1', {
|
||||
orderId: 'order-1',
|
||||
amount,
|
||||
fee,
|
||||
status: 'RELEASED',
|
||||
heldAt: heldDate,
|
||||
releasedAt: releasedDate,
|
||||
disputeReason: null,
|
||||
disputedAt: null,
|
||||
});
|
||||
|
||||
await repository.update(entity);
|
||||
|
||||
expect(mockPrisma.escrow.update).toHaveBeenCalledWith({
|
||||
where: { id: 'escrow-1' },
|
||||
data: {
|
||||
status: 'RELEASED',
|
||||
heldAt: heldDate,
|
||||
releasedAt: releasedDate,
|
||||
disputeReason: null,
|
||||
disputedAt: null,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('updates dispute fields when escrow is disputed', async () => {
|
||||
const disputedDate = new Date('2026-04-02T08:00:00Z');
|
||||
mockPrisma.escrow.update.mockResolvedValue({
|
||||
...mockPrismaEscrow,
|
||||
status: 'DISPUTED',
|
||||
heldAt: heldDate,
|
||||
disputeReason: 'Hàng không đúng mô tả',
|
||||
disputedAt: disputedDate,
|
||||
});
|
||||
|
||||
const { EscrowEntity } = await import('../../domain/entities/escrow.entity');
|
||||
const { Money } = await import('../../domain/value-objects/money.vo');
|
||||
|
||||
const amount = Money.create(500_000_000n).unwrap();
|
||||
const fee = Money.create(25_000_000n).unwrap();
|
||||
|
||||
const entity = new EscrowEntity('escrow-1', {
|
||||
orderId: 'order-1',
|
||||
amount,
|
||||
fee,
|
||||
status: 'DISPUTED',
|
||||
heldAt: heldDate,
|
||||
releasedAt: null,
|
||||
disputeReason: 'Hàng không đúng mô tả',
|
||||
disputedAt: disputedDate,
|
||||
});
|
||||
|
||||
await repository.update(entity);
|
||||
|
||||
expect(mockPrisma.escrow.update).toHaveBeenCalledWith({
|
||||
where: { id: 'escrow-1' },
|
||||
data: expect.objectContaining({
|
||||
status: 'DISPUTED',
|
||||
disputeReason: 'Hàng không đúng mô tả',
|
||||
disputedAt: disputedDate,
|
||||
}),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('toDomain mapping', () => {
|
||||
it('correctly maps bigint amounts to Money value objects', async () => {
|
||||
mockPrisma.escrow.findUnique.mockResolvedValue({
|
||||
...mockPrismaEscrow,
|
||||
amountVND: 999_999_999_999n,
|
||||
feeVND: 50_000_000n,
|
||||
});
|
||||
|
||||
const result = await repository.findById('escrow-1');
|
||||
|
||||
expect(result!.amount.value).toBe(999_999_999_999n);
|
||||
expect(result!.fee.value).toBe(50_000_000n);
|
||||
});
|
||||
|
||||
it('preserves nullable temporal fields', async () => {
|
||||
const disputedDate = new Date('2026-04-03T09:00:00Z');
|
||||
mockPrisma.escrow.findUnique.mockResolvedValue({
|
||||
...mockPrismaEscrow,
|
||||
status: 'DISPUTED',
|
||||
heldAt: heldDate,
|
||||
disputeReason: 'Test dispute',
|
||||
disputedAt: disputedDate,
|
||||
});
|
||||
|
||||
const result = await repository.findById('escrow-1');
|
||||
|
||||
expect(result!.heldAt).toEqual(heldDate);
|
||||
expect(result!.releasedAt).toBeNull();
|
||||
expect(result!.disputeReason).toBe('Test dispute');
|
||||
expect(result!.disputedAt).toEqual(disputedDate);
|
||||
});
|
||||
|
||||
it('preserves createdAt and updatedAt timestamps', async () => {
|
||||
mockPrisma.escrow.findUnique.mockResolvedValue(mockPrismaEscrow);
|
||||
|
||||
const result = await repository.findById('escrow-1');
|
||||
|
||||
expect(result!.createdAt).toEqual(now);
|
||||
expect(result!.updatedAt).toEqual(later);
|
||||
});
|
||||
|
||||
it('computes netPayout correctly from mapped amounts', async () => {
|
||||
mockPrisma.escrow.findUnique.mockResolvedValue({
|
||||
...mockPrismaEscrow,
|
||||
amountVND: 1_000_000_000n,
|
||||
feeVND: 50_000_000n,
|
||||
});
|
||||
|
||||
const result = await repository.findById('escrow-1');
|
||||
|
||||
expect(result!.netPayout).toBe(950_000_000n);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,308 @@
|
||||
import { type OrderStatus } from '@prisma/client';
|
||||
import { PrismaOrderRepository } from '../repositories/prisma-order.repository';
|
||||
|
||||
describe('PrismaOrderRepository', () => {
|
||||
let repository: PrismaOrderRepository;
|
||||
let mockPrisma: {
|
||||
order: {
|
||||
findUnique: ReturnType<typeof vi.fn>;
|
||||
findMany: ReturnType<typeof vi.fn>;
|
||||
count: ReturnType<typeof vi.fn>;
|
||||
create: ReturnType<typeof vi.fn>;
|
||||
update: ReturnType<typeof vi.fn>;
|
||||
};
|
||||
};
|
||||
|
||||
const now = new Date('2026-04-01T10:00:00Z');
|
||||
const later = new Date('2026-04-01T10:05:00Z');
|
||||
|
||||
const mockPrismaOrder = {
|
||||
id: 'order-1',
|
||||
buyerId: 'buyer-1',
|
||||
sellerId: 'seller-1',
|
||||
listingId: 'listing-1',
|
||||
status: 'CREATED' as OrderStatus,
|
||||
amountVND: 500_000_000n,
|
||||
platformFeeVND: 25_000_000n,
|
||||
sellerPayoutVND: 475_000_000n,
|
||||
idempotencyKey: 'idem-key-1',
|
||||
metadata: { note: 'test order' },
|
||||
createdAt: now,
|
||||
updatedAt: later,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
mockPrisma = {
|
||||
order: {
|
||||
findUnique: vi.fn(),
|
||||
findMany: vi.fn(),
|
||||
count: vi.fn(),
|
||||
create: vi.fn(),
|
||||
update: vi.fn(),
|
||||
},
|
||||
};
|
||||
repository = new PrismaOrderRepository(mockPrisma as any);
|
||||
});
|
||||
|
||||
describe('findById', () => {
|
||||
it('returns domain entity when order exists', async () => {
|
||||
mockPrisma.order.findUnique.mockResolvedValue(mockPrismaOrder);
|
||||
|
||||
const result = await repository.findById('order-1');
|
||||
|
||||
expect(mockPrisma.order.findUnique).toHaveBeenCalledWith({
|
||||
where: { id: 'order-1' },
|
||||
});
|
||||
expect(result).not.toBeNull();
|
||||
expect(result!.id).toBe('order-1');
|
||||
expect(result!.buyerId).toBe('buyer-1');
|
||||
expect(result!.sellerId).toBe('seller-1');
|
||||
expect(result!.listingId).toBe('listing-1');
|
||||
expect(result!.status).toBe('CREATED');
|
||||
expect(result!.amount.value).toBe(500_000_000n);
|
||||
expect(result!.platformFee.value).toBe(25_000_000n);
|
||||
expect(result!.sellerPayout.value).toBe(475_000_000n);
|
||||
expect(result!.idempotencyKey).toBe('idem-key-1');
|
||||
});
|
||||
|
||||
it('returns null when order does not exist', async () => {
|
||||
mockPrisma.order.findUnique.mockResolvedValue(null);
|
||||
|
||||
const result = await repository.findById('nonexistent');
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('findByIdempotencyKey', () => {
|
||||
it('returns domain entity when key matches', async () => {
|
||||
mockPrisma.order.findUnique.mockResolvedValue(mockPrismaOrder);
|
||||
|
||||
const result = await repository.findByIdempotencyKey('idem-key-1');
|
||||
|
||||
expect(mockPrisma.order.findUnique).toHaveBeenCalledWith({
|
||||
where: { idempotencyKey: 'idem-key-1' },
|
||||
});
|
||||
expect(result).not.toBeNull();
|
||||
expect(result!.id).toBe('order-1');
|
||||
expect(result!.idempotencyKey).toBe('idem-key-1');
|
||||
});
|
||||
|
||||
it('returns null when key does not match', async () => {
|
||||
mockPrisma.order.findUnique.mockResolvedValue(null);
|
||||
|
||||
const result = await repository.findByIdempotencyKey('unknown-key');
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('findByBuyerId', () => {
|
||||
it('returns paginated items and total count', async () => {
|
||||
const orders = [
|
||||
{ ...mockPrismaOrder, id: 'order-2' },
|
||||
{ ...mockPrismaOrder, id: 'order-1' },
|
||||
];
|
||||
mockPrisma.order.findMany.mockResolvedValue(orders);
|
||||
mockPrisma.order.count.mockResolvedValue(5);
|
||||
|
||||
const result = await repository.findByBuyerId('buyer-1', {
|
||||
limit: 2,
|
||||
offset: 0,
|
||||
});
|
||||
|
||||
expect(mockPrisma.order.findMany).toHaveBeenCalledWith({
|
||||
where: { buyerId: 'buyer-1' },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 2,
|
||||
skip: 0,
|
||||
});
|
||||
expect(mockPrisma.order.count).toHaveBeenCalledWith({
|
||||
where: { buyerId: 'buyer-1' },
|
||||
});
|
||||
expect(result.items).toHaveLength(2);
|
||||
expect(result.total).toBe(5);
|
||||
expect(result.items[0]!.id).toBe('order-2');
|
||||
});
|
||||
|
||||
it('filters by status when provided', async () => {
|
||||
mockPrisma.order.findMany.mockResolvedValue([]);
|
||||
mockPrisma.order.count.mockResolvedValue(0);
|
||||
|
||||
await repository.findByBuyerId('buyer-1', { status: 'PAYMENT_PENDING' });
|
||||
|
||||
expect(mockPrisma.order.findMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
where: { buyerId: 'buyer-1', status: 'PAYMENT_PENDING' },
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('uses default limit and offset when not provided', async () => {
|
||||
mockPrisma.order.findMany.mockResolvedValue([]);
|
||||
mockPrisma.order.count.mockResolvedValue(0);
|
||||
|
||||
await repository.findByBuyerId('buyer-1');
|
||||
|
||||
expect(mockPrisma.order.findMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
take: 20,
|
||||
skip: 0,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findBySellerId', () => {
|
||||
it('returns paginated items and total count', async () => {
|
||||
const orders = [mockPrismaOrder];
|
||||
mockPrisma.order.findMany.mockResolvedValue(orders);
|
||||
mockPrisma.order.count.mockResolvedValue(1);
|
||||
|
||||
const result = await repository.findBySellerId('seller-1', {
|
||||
limit: 10,
|
||||
offset: 0,
|
||||
});
|
||||
|
||||
expect(mockPrisma.order.findMany).toHaveBeenCalledWith({
|
||||
where: { sellerId: 'seller-1' },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 10,
|
||||
skip: 0,
|
||||
});
|
||||
expect(result.items).toHaveLength(1);
|
||||
expect(result.total).toBe(1);
|
||||
expect(result.items[0]!.sellerId).toBe('seller-1');
|
||||
});
|
||||
|
||||
it('filters by status when provided', async () => {
|
||||
mockPrisma.order.findMany.mockResolvedValue([]);
|
||||
mockPrisma.order.count.mockResolvedValue(0);
|
||||
|
||||
await repository.findBySellerId('seller-1', { status: 'ESCROW_HELD' });
|
||||
|
||||
expect(mockPrisma.order.findMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
where: { sellerId: 'seller-1', status: 'ESCROW_HELD' },
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('save', () => {
|
||||
it('persists a new order with correct field mapping', async () => {
|
||||
mockPrisma.order.create.mockResolvedValue(mockPrismaOrder);
|
||||
|
||||
// Reconstruct a domain entity to pass to save
|
||||
const { OrderEntity } = await import('../../domain/entities/order.entity');
|
||||
const { Money } = await import('../../domain/value-objects/money.vo');
|
||||
const { PlatformFee } = await import('../../domain/value-objects/platform-fee.vo');
|
||||
|
||||
const amount = Money.create(500_000_000n).unwrap();
|
||||
const fee = PlatformFee.create(25_000_000n).unwrap();
|
||||
const payout = Money.create(475_000_000n).unwrap();
|
||||
|
||||
const entity = new OrderEntity('order-1', {
|
||||
buyerId: 'buyer-1',
|
||||
sellerId: 'seller-1',
|
||||
listingId: 'listing-1',
|
||||
status: 'CREATED',
|
||||
amount,
|
||||
platformFee: fee,
|
||||
sellerPayout: payout,
|
||||
idempotencyKey: 'idem-key-1',
|
||||
metadata: { note: 'test' },
|
||||
});
|
||||
|
||||
await repository.save(entity);
|
||||
|
||||
expect(mockPrisma.order.create).toHaveBeenCalledWith({
|
||||
data: {
|
||||
id: 'order-1',
|
||||
buyerId: 'buyer-1',
|
||||
sellerId: 'seller-1',
|
||||
listingId: 'listing-1',
|
||||
status: 'CREATED',
|
||||
amountVND: 500_000_000n,
|
||||
platformFeeVND: 25_000_000n,
|
||||
sellerPayoutVND: 475_000_000n,
|
||||
idempotencyKey: 'idem-key-1',
|
||||
metadata: { note: 'test' },
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', () => {
|
||||
it('updates status and metadata', async () => {
|
||||
mockPrisma.order.update.mockResolvedValue({
|
||||
...mockPrismaOrder,
|
||||
status: 'PAYMENT_PENDING',
|
||||
metadata: { note: 'updated' },
|
||||
});
|
||||
|
||||
const { OrderEntity } = await import('../../domain/entities/order.entity');
|
||||
const { Money } = await import('../../domain/value-objects/money.vo');
|
||||
const { PlatformFee } = await import('../../domain/value-objects/platform-fee.vo');
|
||||
|
||||
const amount = Money.create(500_000_000n).unwrap();
|
||||
const fee = PlatformFee.create(25_000_000n).unwrap();
|
||||
const payout = Money.create(475_000_000n).unwrap();
|
||||
|
||||
const entity = new OrderEntity('order-1', {
|
||||
buyerId: 'buyer-1',
|
||||
sellerId: 'seller-1',
|
||||
listingId: 'listing-1',
|
||||
status: 'PAYMENT_PENDING',
|
||||
amount,
|
||||
platformFee: fee,
|
||||
sellerPayout: payout,
|
||||
idempotencyKey: 'idem-key-1',
|
||||
metadata: { note: 'updated' },
|
||||
});
|
||||
|
||||
await repository.update(entity);
|
||||
|
||||
expect(mockPrisma.order.update).toHaveBeenCalledWith({
|
||||
where: { id: 'order-1' },
|
||||
data: {
|
||||
status: 'PAYMENT_PENDING',
|
||||
metadata: { note: 'updated' },
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('toDomain mapping', () => {
|
||||
it('correctly maps bigint amountVND to Money value object', async () => {
|
||||
mockPrisma.order.findUnique.mockResolvedValue({
|
||||
...mockPrismaOrder,
|
||||
amountVND: 999_999_999_999n,
|
||||
});
|
||||
|
||||
const result = await repository.findById('order-1');
|
||||
|
||||
expect(result!.amount.value).toBe(999_999_999_999n);
|
||||
});
|
||||
|
||||
it('preserves null idempotencyKey', async () => {
|
||||
mockPrisma.order.findUnique.mockResolvedValue({
|
||||
...mockPrismaOrder,
|
||||
idempotencyKey: null,
|
||||
});
|
||||
|
||||
const result = await repository.findById('order-1');
|
||||
|
||||
expect(result!.idempotencyKey).toBeNull();
|
||||
});
|
||||
|
||||
it('preserves createdAt and updatedAt timestamps', async () => {
|
||||
mockPrisma.order.findUnique.mockResolvedValue(mockPrismaOrder);
|
||||
|
||||
const result = await repository.findById('order-1');
|
||||
|
||||
expect(result!.createdAt).toEqual(now);
|
||||
expect(result!.updatedAt).toEqual(later);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user