forked from FlowwStar/FlowStar
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuse-activity-feed.test.ts
More file actions
181 lines (160 loc) · 7.21 KB
/
Copy pathuse-activity-feed.test.ts
File metadata and controls
181 lines (160 loc) · 7.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
import { describe, it, expect, vi } from 'vitest'
import { renderHook, act } from '@testing-library/react'
import type { StreamData } from '@/types/stream'
const mockUseStreams = vi.hoisted(() => vi.fn())
vi.mock('@/hooks/use-streams', () => ({ useStreams: mockUseStreams }))
import { useActivityFeed } from '@/hooks/use-activity-feed'
const TOKEN = { address: 'CUSDC', symbol: 'USDC', decimals: 7 }
const makeStream = (overrides: Partial<StreamData> = {}): StreamData => ({
id: '1',
sender: 'GSENDER',
recipient: 'GRECIPIENT',
token: TOKEN,
depositedAmount: 1000n,
withdrawnAmount: 0n,
startTime: 0n,
endTime: 9999999999n,
cliffTime: 0n,
cliffAmount: 0n,
amountPerSecond: 1n,
linearAmount: 1000n,
duration: 9999999999n,
cancelled: false,
...overrides,
})
describe('useActivityFeed', () => {
it('returns no events when walletAddress is null', () => {
mockUseStreams.mockReturnValue({ all: [makeStream()] })
const { result } = renderHook(() => useActivityFeed(null))
expect(result.current.events).toEqual([])
expect(result.current.total).toBe(0)
})
it('derives a created event for each stream', () => {
mockUseStreams.mockReturnValue({ all: [makeStream()] })
const { result } = renderHook(() => useActivityFeed('GSENDER'))
expect(result.current.events.some((e) => e.type === 'stream.created')).toBe(true)
expect(result.current.events[0].role).toBe('sent')
})
it('marks role as received when wallet is the recipient', () => {
mockUseStreams.mockReturnValue({ all: [makeStream()] })
const { result } = renderHook(() => useActivityFeed('GRECIPIENT'))
expect(result.current.events[0].role).toBe('received')
})
it('adds a withdrawal event when withdrawnAmount > 0', () => {
mockUseStreams.mockReturnValue({
all: [makeStream({ withdrawnAmount: 500n })],
})
const { result } = renderHook(() => useActivityFeed('GSENDER'))
expect(result.current.events.some((e) => e.type === 'stream.withdrawal')).toBe(true)
})
it('adds a cancelled event when the stream is cancelled', () => {
mockUseStreams.mockReturnValue({
all: [makeStream({ cancelled: true })],
})
const { result } = renderHook(() => useActivityFeed('GSENDER'))
expect(result.current.events.some((e) => e.type === 'stream.cancelled')).toBe(true)
})
it('filters events by eventType', () => {
mockUseStreams.mockReturnValue({
all: [makeStream({ withdrawnAmount: 500n })],
})
const { result } = renderHook(() => useActivityFeed('GSENDER'))
act(() => {
result.current.setFilter({ eventType: 'stream.withdrawal', role: 'all' })
})
expect(result.current.events.every((e) => e.type === 'stream.withdrawal')).toBe(true)
})
it('resets to page 1 when the filter changes', () => {
mockUseStreams.mockReturnValue({ all: [makeStream()] })
const { result } = renderHook(() => useActivityFeed('GSENDER'))
act(() => {
result.current.loadMore()
})
act(() => {
result.current.setFilter({ eventType: 'all', role: 'received' })
})
expect(result.current.events).toEqual([])
})
it('adds a completed event when stream has ended and all tokens are withdrawn', () => {
mockUseStreams.mockReturnValue({
all: [makeStream({ endTime: 1n, withdrawnAmount: 1000n })],
})
const { result } = renderHook(() => useActivityFeed('GSENDER'))
expect(result.current.events.some((e) => e.type === 'stream.completed')).toBe(true)
})
describe('deriveEvents — description text', () => {
const DEPOSITED = 10_000_000n // 1 USDC at 7 decimals
it('stream.created sent: description mentions sender action and recipient address', () => {
mockUseStreams.mockReturnValue({
all: [makeStream({ depositedAmount: DEPOSITED })],
})
const { result } = renderHook(() => useActivityFeed('GSENDER'))
const ev = result.current.events.find((e) => e.type === 'stream.created')!
expect(ev.role).toBe('sent')
expect(ev.description).toContain('You started streaming')
expect(ev.description).toContain('USDC')
expect(ev.description).toContain('GRECI')
})
it('stream.created received: description mentions incoming stream and sender address', () => {
mockUseStreams.mockReturnValue({
all: [makeStream({ depositedAmount: DEPOSITED })],
})
const { result } = renderHook(() => useActivityFeed('GRECIPIENT'))
const ev = result.current.events.find((e) => e.type === 'stream.created')!
expect(ev.role).toBe('received')
expect(ev.description).toContain('Incoming stream of')
expect(ev.description).toContain('USDC')
expect(ev.description).toContain('GSEND')
})
it('stream.withdrawal received: "You" appears in description', () => {
mockUseStreams.mockReturnValue({
all: [makeStream({ depositedAmount: DEPOSITED, withdrawnAmount: 5_000_000n })],
})
const { result } = renderHook(() => useActivityFeed('GRECIPIENT'))
const ev = result.current.events.find((e) => e.type === 'stream.withdrawal')!
expect(ev.role).toBe('received')
expect(ev.description).toContain('You withdrew')
expect(ev.description).toContain('USDC')
})
it('stream.withdrawal sent: recipient address snippet appears in description', () => {
mockUseStreams.mockReturnValue({
all: [makeStream({ depositedAmount: DEPOSITED, withdrawnAmount: 5_000_000n })],
})
const { result } = renderHook(() => useActivityFeed('GSENDER'))
const ev = result.current.events.find((e) => e.type === 'stream.withdrawal')!
expect(ev.role).toBe('sent')
expect(ev.description).toContain('withdrew')
expect(ev.description).toContain('GRECI')
})
it('stream.cancelled sent: description contains "You cancelled" and returned amount', () => {
mockUseStreams.mockReturnValue({
all: [makeStream({ depositedAmount: DEPOSITED, cancelled: true })],
})
const { result } = renderHook(() => useActivityFeed('GSENDER'))
const ev = result.current.events.find((e) => e.type === 'stream.cancelled')!
expect(ev.role).toBe('sent')
expect(ev.description).toContain('You cancelled')
expect(ev.description).toContain('USDC returned')
})
it('stream.cancelled received: description contains "was cancelled" and returned amount', () => {
mockUseStreams.mockReturnValue({
all: [makeStream({ depositedAmount: DEPOSITED, cancelled: true })],
})
const { result } = renderHook(() => useActivityFeed('GRECIPIENT'))
const ev = result.current.events.find((e) => e.type === 'stream.cancelled')!
expect(ev.role).toBe('received')
expect(ev.description).toContain('was cancelled')
expect(ev.description).toContain('USDC returned')
})
it('stream.completed: description contains "fully unlocked" and token symbol', () => {
mockUseStreams.mockReturnValue({
all: [makeStream({ depositedAmount: DEPOSITED, withdrawnAmount: DEPOSITED, endTime: 1n })],
})
const { result } = renderHook(() => useActivityFeed('GSENDER'))
const ev = result.current.events.find((e) => e.type === 'stream.completed')!
expect(ev).toBeDefined()
expect(ev.description).toContain('fully unlocked')
expect(ev.description).toContain('USDC')
})
})
})