Skip to content

Commit 4b78912

Browse files
client farcaster: test config and test coverage (elizaOS#2567)
* client-farcaster: test configuration * client-farcaster: tests for cast * client-farcaster: tests for client * client-farcaster: tests for interaction * client-farcaster: test utils * client-farcaster: adding test for like iteration --------- Co-authored-by: Sayo <hi@sayo.wtf>
1 parent 80dbb30 commit 4b78912

File tree

7 files changed

+487
-4
lines changed

7 files changed

+487
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { describe, it, expect, vi, beforeEach } from 'vitest';
2+
import { createTestCast } from './test-utils';
3+
import { FarcasterClient } from '../src/client';
4+
import { NeynarAPIClient } from '@neynar/nodejs-sdk';
5+
6+
// Mock dependencies
7+
vi.mock('@neynar/nodejs-sdk', () => ({
8+
NeynarAPIClient: vi.fn().mockImplementation(() => ({
9+
publishCast: vi.fn().mockResolvedValue({
10+
success: true,
11+
cast: {
12+
hash: 'cast-1',
13+
author: { fid: '123' },
14+
text: 'Test cast',
15+
timestamp: '2025-01-20T20:00:00Z'
16+
}
17+
}),
18+
fetchBulkUsers: vi.fn().mockResolvedValue({
19+
users: [{
20+
fid: '123',
21+
username: 'test.farcaster',
22+
display_name: 'Test User',
23+
pfp: {
24+
url: 'https://example.com/pic.jpg'
25+
}
26+
}]
27+
})
28+
}))
29+
}));
30+
31+
describe('Cast Functions', () => {
32+
let client: FarcasterClient;
33+
34+
beforeEach(() => {
35+
vi.clearAllMocks();
36+
client = new FarcasterClient({
37+
runtime: {
38+
name: 'test-runtime',
39+
memory: new Map(),
40+
getMemory: vi.fn(),
41+
setMemory: vi.fn(),
42+
clearMemory: vi.fn()
43+
},
44+
url: 'https://api.example.com',
45+
ssl: true,
46+
neynar: new NeynarAPIClient({ apiKey: 'test-key' }),
47+
signerUuid: 'test-signer',
48+
cache: new Map(),
49+
farcasterConfig: {
50+
apiKey: 'test-key',
51+
signerUuid: 'test-signer'
52+
}
53+
});
54+
});
55+
56+
describe('createTestCast', () => {
57+
it('should create a cast successfully', async () => {
58+
const content = 'Test cast content';
59+
const result = await createTestCast(client, content);
60+
61+
expect(result).toBeDefined();
62+
expect(result.success).toBe(true);
63+
expect(result.cast.text).toBe(content);
64+
expect(client.neynar.publishCast).toHaveBeenCalledWith({
65+
text: content,
66+
signerUuid: 'test-signer'
67+
});
68+
});
69+
70+
it('should handle cast creation errors', async () => {
71+
const content = 'Test cast content';
72+
vi.mocked(client.neynar.publishCast).mockRejectedValueOnce(new Error('Cast creation failed'));
73+
await expect(createTestCast(client, content)).rejects.toThrow('Cast creation failed');
74+
});
75+
76+
it('should handle empty content', async () => {
77+
const content = '';
78+
await expect(createTestCast(client, content)).rejects.toThrow('Cast content cannot be empty');
79+
});
80+
81+
it('should handle very long content', async () => {
82+
const content = 'a'.repeat(321); // Farcaster limit is 320 characters
83+
await expect(createTestCast(client, content)).rejects.toThrow('Cast content too long');
84+
});
85+
});
86+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import { describe, it, expect, vi, beforeEach } from 'vitest';
2+
import { FarcasterClient } from '../src/client';
3+
import { NeynarAPIClient } from '@neynar/nodejs-sdk';
4+
5+
// Mock dependencies
6+
vi.mock('@neynar/nodejs-sdk', () => ({
7+
NeynarAPIClient: vi.fn().mockImplementation(() => ({
8+
publishCast: vi.fn().mockResolvedValue({
9+
success: true,
10+
cast: {
11+
hash: 'cast-1',
12+
author: { fid: '123' },
13+
text: 'Test cast',
14+
timestamp: '2025-01-20T20:00:00Z'
15+
}
16+
}),
17+
fetchBulkUsers: vi.fn().mockResolvedValue({
18+
users: [{
19+
fid: '123',
20+
username: 'test.farcaster',
21+
display_name: 'Test User',
22+
pfp: {
23+
url: 'https://example.com/pic.jpg'
24+
}
25+
}]
26+
}),
27+
fetchCastsForUser: vi.fn().mockResolvedValue({
28+
casts: [
29+
{
30+
hash: 'cast-1',
31+
author: {
32+
fid: '123',
33+
username: 'test.farcaster',
34+
display_name: 'Test User'
35+
},
36+
text: 'Test cast',
37+
timestamp: '2025-01-20T20:00:00Z'
38+
}
39+
]
40+
})
41+
}))
42+
}));
43+
44+
describe('FarcasterClient', () => {
45+
let client: FarcasterClient;
46+
const mockRuntime = {
47+
name: 'test-runtime',
48+
memory: new Map(),
49+
getMemory: vi.fn(),
50+
setMemory: vi.fn(),
51+
clearMemory: vi.fn()
52+
};
53+
54+
beforeEach(() => {
55+
vi.clearAllMocks();
56+
client = new FarcasterClient({
57+
runtime: mockRuntime,
58+
url: 'https://api.example.com',
59+
ssl: true,
60+
neynar: new NeynarAPIClient({ apiKey: 'test-key' }),
61+
signerUuid: 'test-signer',
62+
cache: new Map(),
63+
farcasterConfig: {
64+
apiKey: 'test-key',
65+
signerUuid: 'test-signer'
66+
}
67+
});
68+
});
69+
70+
describe('loadCastFromNeynarResponse', () => {
71+
it('should load cast from Neynar response', async () => {
72+
const neynarResponse = {
73+
hash: 'cast-1',
74+
author: { fid: '123' },
75+
text: 'Test cast',
76+
timestamp: '2025-01-20T20:00:00Z'
77+
};
78+
79+
const cast = await client.loadCastFromNeynarResponse(neynarResponse);
80+
expect(cast).toBeDefined();
81+
expect(cast.hash).toBe('cast-1');
82+
expect(cast.authorFid).toBe('123');
83+
expect(cast.text).toBe('Test cast');
84+
expect(cast.profile).toBeDefined();
85+
expect(cast.profile.fid).toBe('123');
86+
expect(cast.profile.username).toBe('test.farcaster');
87+
});
88+
89+
it('should handle cast with parent', async () => {
90+
const neynarResponse = {
91+
hash: 'cast-2',
92+
author: { fid: '123' },
93+
text: 'Reply cast',
94+
parent_hash: 'cast-1',
95+
parent_author: { fid: '456' },
96+
timestamp: '2025-01-20T20:00:00Z'
97+
};
98+
99+
const cast = await client.loadCastFromNeynarResponse(neynarResponse);
100+
expect(cast.inReplyTo).toBeDefined();
101+
expect(cast.inReplyTo?.hash).toBe('cast-1');
102+
expect(cast.inReplyTo?.fid).toBe('456');
103+
});
104+
});
105+
106+
describe('getProfile', () => {
107+
it('should fetch profile successfully', async () => {
108+
const profile = await client.getProfile('123');
109+
expect(profile).toBeDefined();
110+
expect(profile.fid).toBe('123');
111+
expect(profile.username).toBe('test.farcaster');
112+
expect(profile.name).toBe('Test User');
113+
});
114+
115+
it('should handle profile fetch errors', async () => {
116+
vi.mocked(client.neynar.fetchBulkUsers).mockRejectedValueOnce(new Error('Profile fetch failed'));
117+
await expect(client.getProfile('123')).rejects.toThrow('Profile fetch failed');
118+
});
119+
});
120+
121+
describe('getCastsByFid', () => {
122+
it('should fetch casts successfully', async () => {
123+
const casts = await client.getCastsByFid({ fid: '123', pageSize: 10 });
124+
expect(casts).toHaveLength(1);
125+
expect(casts[0].hash).toBe('cast-1');
126+
expect(casts[0].authorFid).toBe('123');
127+
expect(casts[0].text).toBe('Test cast');
128+
});
129+
130+
it('should handle cast fetch errors', async () => {
131+
vi.mocked(client.neynar.fetchCastsForUser).mockRejectedValueOnce(new Error('Cast fetch failed'));
132+
await expect(client.getCastsByFid({ fid: '123', pageSize: 10 })).rejects.toThrow('Cast fetch failed');
133+
});
134+
});
135+
});

0 commit comments

Comments
 (0)