Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions __tests__/contract-sync/listener.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,38 @@ describe('SorobanEventListener', () => {
canonicalListener.stop()
})

it('parses deadline extension events with the milestone id and new deadline', async () => {
vi.useRealTimers()
const canonicalListener = new SorobanEventListener({
rpcUrl: 'https://soroban-testnet.stellar.org',
networkPassphrase: 'Test SDF Network ; September 2015',
contractAddresses: ['CA1234'],
initialLedger: 500,
})
const canonicalCallback = vi.fn()
canonicalListener.setCallback(canonicalCallback)

mockGetEvents.mockResolvedValue({
events: [{
topic: ['DeadlineExtended', 'CA-CONTRACT', '7', 'GARB'],
value: [100, 200, true],
ledger: 501,
txHash: 'tx-deadline-extension',
}],
})
mockGetLatestLedger.mockResolvedValue({ sequence: 505 })

await (canonicalListener as any).poll()

expect(canonicalCallback).toHaveBeenCalledWith(expect.objectContaining({
event: 'deadline_extended',
milestoneId: 7,
deadline: 200,
wasExpired: true,
}))
canonicalListener.stop()
})

it('awaits the callback for each event before advancing the checkpoint', async () => {
// Uses real timers and calls the private poll() directly so the
// ordering can be observed deterministically without racing fake-timer
Expand Down
32 changes: 32 additions & 0 deletions __tests__/contract-sync/mapper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,38 @@ describe('mapEventToAction', () => {
expect(action.milestoneId).toBe(1)
})

it('maps deadline_set to a milestone due date', () => {
const action = mapEventToAction('deadline_set', makePayload({
event: 'deadline_set',
milestoneId: 3,
deadline: 2_000_000_000,
}))
expect(action.kind).toBe('update_milestone')
expect(action.milestoneUpdate?.dueDate).toBe('2033-05-18T03:33:20.000Z')
expect(action.milestoneId).toBe(3)
})

it('maps deadline_expired to the expired milestone state', () => {
const action = mapEventToAction('deadline_expired', makePayload({
event: 'deadline_expired',
milestoneId: 3,
}))
expect(action.milestoneUpdate?.status).toBe('expired')
expect(action.milestoneId).toBe(3)
})

it('maps deadline_extended to an extended milestone and its new due date', () => {
const action = mapEventToAction('deadline_extended', makePayload({
event: 'deadline_extended',
milestoneId: 3,
deadline: 2_000_000_000,
wasExpired: true,
}))
expect(action.milestoneUpdate?.status).toBe('extended')
expect(action.milestoneUpdate?.dueDate).toBe('2033-05-18T03:33:20.000Z')
expect(action.milestoneUpdate?.isOverdue).toBe(false)
})

it('handles unknown event as noop', () => {
const payload = makePayload({ event: 'unknown' as any })
const action = mapEventToAction('unknown' as any, payload)
Expand Down
10 changes: 9 additions & 1 deletion __tests__/deadline-monitor/types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@ import { DEADLINE_EXEMPT_STATUSES, getReminderWindowMs } from '@/lib/deadline-mo

describe('deadline-monitor types', () => {
it('exempts approved, paid, and rejected milestones from deadline tracking', () => {
expect(DEADLINE_EXEMPT_STATUSES).toEqual(['approved', 'paid', 'rejected'])
expect(DEADLINE_EXEMPT_STATUSES).toEqual([
'approved',
'paid',
'rejected',
'disputed',
'refunded',
'expired',
'auto_expired',
])
})

it('uses a 24 hour reminder window', () => {
Expand Down
Loading
Loading