import { describe, it, expect, vi, beforeEach } from 'vitest' const mockGetTariffs = vi.fn() const mockPayloadFind = vi.fn() const mockPayloadUpdate = vi.fn() const mockPayloadCreate = vi.fn() const mockGetPayload = vi.fn(() => ({ find: mockPayloadFind, update: mockPayloadUpdate, create: mockPayloadCreate, })) vi.mock('@/lib/ezy', () => ({ getTariffs: mockGetTariffs })) vi.mock('payload', () => ({ getPayload: mockGetPayload })) vi.mock('@payload-config', () => ({ default: {} })) let syncTariffs: () => Promise<{ synced: number; created: number; hidden: number }> beforeEach(async () => { vi.resetModules() mockGetTariffs.mockReset() mockPayloadFind.mockReset() mockPayloadUpdate.mockReset() mockPayloadCreate.mockReset() const mod = await import('@/lib/syncTariffs') syncTariffs = mod.syncTariffs }) describe('syncTariffs', () => { it('updates existing tariffs and returns correct synced count', async () => { mockGetTariffs.mockResolvedValueOnce([ { id: 1, name: 'Adult', price: 250 }, { id: 2, name: 'Child', price: 150 }, ]) // per-tariff find calls + final visible-tariffs scan mockPayloadFind .mockResolvedValueOnce({ docs: [{ id: 'tariff-1', ezy_id: 1 }] }) .mockResolvedValueOnce({ docs: [{ id: 'tariff-2', ezy_id: 2 }] }) .mockResolvedValueOnce({ docs: [] }) mockPayloadUpdate.mockResolvedValue({}) const result = await syncTariffs() expect(result.synced).toBe(2) expect(result.created).toBe(0) expect(result.hidden).toBe(0) expect(mockPayloadUpdate).toHaveBeenCalledTimes(2) }) it('creates new tariffs when ezy_id does not exist in DB', async () => { mockGetTariffs.mockResolvedValueOnce([ { id: 1, name: 'Adult', price: 250 }, { id: 2, name: 'Child', price: 150 }, ]) mockPayloadFind .mockResolvedValueOnce({ docs: [] }) .mockResolvedValueOnce({ docs: [] }) .mockResolvedValueOnce({ docs: [] }) mockPayloadCreate.mockResolvedValue({}) const result = await syncTariffs() expect(result.created).toBe(2) expect(result.synced).toBe(0) expect(mockPayloadCreate).toHaveBeenCalledTimes(2) }) it('hides DB tariffs that are no longer present in ezy', async () => { mockGetTariffs.mockResolvedValueOnce([{ id: 1, name: 'Adult', price: 250 }]) mockPayloadFind .mockResolvedValueOnce({ docs: [{ id: 'tariff-1', ezy_id: 1 }] }) // visible scan: id:99 is not in ezy anymore .mockResolvedValueOnce({ docs: [{ id: 'tariff-stale', ezy_id: 99 }] }) mockPayloadUpdate.mockResolvedValue({}) const result = await syncTariffs() expect(result.hidden).toBe(1) expect(mockPayloadUpdate).toHaveBeenCalledWith( expect.objectContaining({ id: 'tariff-stale', data: { visible: false }, }) ) }) it('returns zero counts when ezy returns an empty array', async () => { mockGetTariffs.mockResolvedValueOnce([]) mockPayloadFind.mockResolvedValueOnce({ docs: [] }) const result = await syncTariffs() expect(result).toEqual({ synced: 0, created: 0, hidden: 0 }) }) it('propagates error when getTariffs throws', async () => { mockGetTariffs.mockRejectedValueOnce(new Error('ezy unavailable')) await expect(syncTariffs()).rejects.toThrow('ezy unavailable') }) it('writes last_synced_name and last_synced_price when updating an existing tariff', async () => { mockGetTariffs.mockResolvedValueOnce([{ id: 1, name: 'Updated Adult', price: 300 }]) mockPayloadFind .mockResolvedValueOnce({ docs: [{ id: 'tariff-1', ezy_id: 1 }] }) .mockResolvedValueOnce({ docs: [] }) mockPayloadUpdate.mockResolvedValue({}) await syncTariffs() expect(mockPayloadUpdate).toHaveBeenCalledWith( expect.objectContaining({ collection: 'tariffs', id: 'tariff-1', data: expect.objectContaining({ last_synced_name: 'Updated Adult', last_synced_price: 300, }), }) ) }) it('creates new tariff with category_tag dyno and visible:true', async () => { mockGetTariffs.mockResolvedValueOnce([{ id: 5, name: 'VIP', price: 500 }]) mockPayloadFind .mockResolvedValueOnce({ docs: [] }) .mockResolvedValueOnce({ docs: [] }) mockPayloadCreate.mockResolvedValue({}) await syncTariffs() expect(mockPayloadCreate).toHaveBeenCalledWith( expect.objectContaining({ collection: 'tariffs', data: expect.objectContaining({ ezy_id: 5, category_tag: 'dyno', visible: true, }), }) ) }) })