@rooguys/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,138 @@
1
+ import axios from 'axios';
2
+ import { Rooguys } from '../../index';
3
+ import { createMockAxiosInstance, mockSuccessResponse, mockErrorResponse } from '../utils/mockClient';
4
+ import { mockResponses, mockErrors } from '../fixtures/responses';
5
+
6
+ jest.mock('axios');
7
+ const mockedAxios = axios as jest.Mocked<typeof axios>;
8
+
9
+ describe('Levels Resource', () => {
10
+ let client: Rooguys;
11
+ let mockAxiosInstance: ReturnType<typeof createMockAxiosInstance>;
12
+ const apiKey = 'test-api-key';
13
+
14
+ beforeEach(() => {
15
+ mockAxiosInstance = createMockAxiosInstance();
16
+ mockedAxios.create.mockReturnValue(mockAxiosInstance as any);
17
+ client = new Rooguys(apiKey);
18
+ jest.clearAllMocks();
19
+ });
20
+
21
+ describe('list', () => {
22
+ it('should list levels with default parameters', async () => {
23
+ mockAxiosInstance.get.mockResolvedValue(
24
+ mockSuccessResponse(mockResponses.levelsListResponse)
25
+ );
26
+
27
+ const result = await client.levels.list();
28
+
29
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/levels', {
30
+ params: { page: 1, limit: 50 },
31
+ });
32
+ expect(result).toEqual(mockResponses.levelsListResponse);
33
+ expect(result.levels).toHaveLength(2);
34
+ });
35
+
36
+ it('should list levels with custom pagination', async () => {
37
+ mockAxiosInstance.get.mockResolvedValue(
38
+ mockSuccessResponse(mockResponses.levelsListResponse)
39
+ );
40
+
41
+ await client.levels.list(2, 25);
42
+
43
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/levels', {
44
+ params: { page: 2, limit: 25 },
45
+ });
46
+ });
47
+
48
+ it('should handle empty levels list', async () => {
49
+ const emptyResponse = {
50
+ levels: [],
51
+ pagination: {
52
+ page: 1,
53
+ limit: 50,
54
+ total: 0,
55
+ totalPages: 0,
56
+ },
57
+ };
58
+ mockAxiosInstance.get.mockResolvedValue(mockSuccessResponse(emptyResponse));
59
+
60
+ const result = await client.levels.list();
61
+
62
+ expect(result.levels).toEqual([]);
63
+ expect(result.pagination.total).toBe(0);
64
+ });
65
+
66
+ it('should handle levels with all fields', async () => {
67
+ mockAxiosInstance.get.mockResolvedValue(
68
+ mockSuccessResponse(mockResponses.levelsListResponse)
69
+ );
70
+
71
+ const result = await client.levels.list();
72
+
73
+ const level = result.levels[0];
74
+ expect(level.id).toBeDefined();
75
+ expect(level.name).toBeDefined();
76
+ expect(level.level_number).toBeDefined();
77
+ expect(level.points_required).toBeDefined();
78
+ expect(level.description).toBeDefined();
79
+ expect(level.icon_url).toBeDefined();
80
+ });
81
+
82
+ it('should handle levels sorted by level_number', async () => {
83
+ mockAxiosInstance.get.mockResolvedValue(
84
+ mockSuccessResponse(mockResponses.levelsListResponse)
85
+ );
86
+
87
+ const result = await client.levels.list();
88
+
89
+ expect(result.levels[0].level_number).toBe(1);
90
+ expect(result.levels[1].level_number).toBe(2);
91
+ });
92
+
93
+ it('should throw error for invalid pagination', async () => {
94
+ mockAxiosInstance.get.mockRejectedValue(
95
+ mockErrorResponse(400, mockErrors.invalidPaginationError.message)
96
+ );
97
+
98
+ await expect(client.levels.list(1, 150)).rejects.toThrow(
99
+ 'Limit must be between 1 and 100'
100
+ );
101
+ });
102
+
103
+ it('should handle server error', async () => {
104
+ mockAxiosInstance.get.mockRejectedValue(
105
+ mockErrorResponse(500, 'Internal server error')
106
+ );
107
+
108
+ await expect(client.levels.list()).rejects.toThrow('Internal server error');
109
+ });
110
+
111
+ it('should handle levels with nullable fields', async () => {
112
+ const levelsWithNulls = {
113
+ levels: [
114
+ {
115
+ id: 'level1',
116
+ name: 'Bronze',
117
+ level_number: 1,
118
+ points_required: 0,
119
+ description: null,
120
+ icon_url: null,
121
+ },
122
+ ],
123
+ pagination: {
124
+ page: 1,
125
+ limit: 50,
126
+ total: 1,
127
+ totalPages: 1,
128
+ },
129
+ };
130
+ mockAxiosInstance.get.mockResolvedValue(mockSuccessResponse(levelsWithNulls));
131
+
132
+ const result = await client.levels.list();
133
+
134
+ expect(result.levels[0].description).toBeNull();
135
+ expect(result.levels[0].icon_url).toBeNull();
136
+ });
137
+ });
138
+ });
@@ -0,0 +1,138 @@
1
+ import axios from 'axios';
2
+ import { Rooguys } from '../../index';
3
+ import { createMockAxiosInstance, mockSuccessResponse, mockErrorResponse } from '../utils/mockClient';
4
+ import { mockResponses, mockErrors } from '../fixtures/responses';
5
+
6
+ jest.mock('axios');
7
+ const mockedAxios = axios as jest.Mocked<typeof axios>;
8
+
9
+ describe('Questionnaires Resource', () => {
10
+ let client: Rooguys;
11
+ let mockAxiosInstance: ReturnType<typeof createMockAxiosInstance>;
12
+ const apiKey = 'test-api-key';
13
+
14
+ beforeEach(() => {
15
+ mockAxiosInstance = createMockAxiosInstance();
16
+ mockedAxios.create.mockReturnValue(mockAxiosInstance as any);
17
+ client = new Rooguys(apiKey);
18
+ jest.clearAllMocks();
19
+ });
20
+
21
+ describe('get', () => {
22
+ it('should get questionnaire by slug', async () => {
23
+ mockAxiosInstance.get.mockResolvedValue(
24
+ mockSuccessResponse(mockResponses.questionnaireResponse)
25
+ );
26
+
27
+ const result = await client.questionnaires.get('user-persona');
28
+
29
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/questionnaire/user-persona');
30
+ expect(result).toEqual(mockResponses.questionnaireResponse);
31
+ expect(result.slug).toBe('user-persona');
32
+ });
33
+
34
+ it('should handle questionnaire with multiple questions', async () => {
35
+ mockAxiosInstance.get.mockResolvedValue(
36
+ mockSuccessResponse(mockResponses.questionnaireResponse)
37
+ );
38
+
39
+ const result = await client.questionnaires.get('user-persona');
40
+
41
+ expect(result.questions).toBeDefined();
42
+ expect(result.questions.length).toBeGreaterThan(0);
43
+ });
44
+
45
+ it('should handle questionnaire with answer options', async () => {
46
+ mockAxiosInstance.get.mockResolvedValue(
47
+ mockSuccessResponse(mockResponses.questionnaireResponse)
48
+ );
49
+
50
+ const result = await client.questionnaires.get('user-persona');
51
+
52
+ const question = result.questions[0];
53
+ expect(question.answer_options).toBeDefined();
54
+ expect(question.answer_options.length).toBeGreaterThan(0);
55
+ });
56
+
57
+ it('should throw 404 error when questionnaire not found', async () => {
58
+ mockAxiosInstance.get.mockRejectedValue(
59
+ mockErrorResponse(404, 'Questionnaire not found')
60
+ );
61
+
62
+ await expect(
63
+ client.questionnaires.get('nonexistent-slug')
64
+ ).rejects.toThrow('Questionnaire not found');
65
+ });
66
+
67
+ it('should handle slug with special characters', async () => {
68
+ mockAxiosInstance.get.mockResolvedValue(
69
+ mockSuccessResponse(mockResponses.questionnaireResponse)
70
+ );
71
+
72
+ await client.questionnaires.get('user-persona-v2');
73
+
74
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/questionnaire/user-persona-v2');
75
+ });
76
+
77
+ it('should handle inactive questionnaire', async () => {
78
+ const inactiveQuestionnaire = {
79
+ ...mockResponses.questionnaireResponse,
80
+ is_active: false,
81
+ };
82
+ mockAxiosInstance.get.mockResolvedValue(mockSuccessResponse(inactiveQuestionnaire));
83
+
84
+ const result = await client.questionnaires.get('old-questionnaire');
85
+
86
+ expect(result.is_active).toBe(false);
87
+ });
88
+ });
89
+
90
+ describe('getActive', () => {
91
+ it('should get active questionnaire', async () => {
92
+ mockAxiosInstance.get.mockResolvedValue(
93
+ mockSuccessResponse(mockResponses.questionnaireResponse)
94
+ );
95
+
96
+ const result = await client.questionnaires.getActive();
97
+
98
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/questionnaire/active');
99
+ expect(result).toEqual(mockResponses.questionnaireResponse);
100
+ expect(result.is_active).toBe(true);
101
+ });
102
+
103
+ it('should throw 404 error when no active questionnaire', async () => {
104
+ mockAxiosInstance.get.mockRejectedValue(
105
+ mockErrorResponse(404, 'No active questionnaire found for this project')
106
+ );
107
+
108
+ await expect(client.questionnaires.getActive()).rejects.toThrow(
109
+ 'No active questionnaire found'
110
+ );
111
+ });
112
+
113
+ it('should handle active questionnaire with all fields', async () => {
114
+ mockAxiosInstance.get.mockResolvedValue(
115
+ mockSuccessResponse(mockResponses.questionnaireResponse)
116
+ );
117
+
118
+ const result = await client.questionnaires.getActive();
119
+
120
+ expect(result.id).toBeDefined();
121
+ expect(result.slug).toBeDefined();
122
+ expect(result.title).toBeDefined();
123
+ expect(result.description).toBeDefined();
124
+ expect(result.is_active).toBe(true);
125
+ expect(result.questions).toBeDefined();
126
+ });
127
+
128
+ it('should handle server error', async () => {
129
+ mockAxiosInstance.get.mockRejectedValue(
130
+ mockErrorResponse(500, 'Internal server error')
131
+ );
132
+
133
+ await expect(client.questionnaires.getActive()).rejects.toThrow(
134
+ 'Internal server error'
135
+ );
136
+ });
137
+ });
138
+ });
@@ -0,0 +1,273 @@
1
+ import axios from 'axios';
2
+ import { Rooguys } from '../../index';
3
+ import { createMockAxiosInstance, mockSuccessResponse, mockErrorResponse } from '../utils/mockClient';
4
+ import { mockResponses, mockErrors } from '../fixtures/responses';
5
+
6
+ jest.mock('axios');
7
+ const mockedAxios = axios as jest.Mocked<typeof axios>;
8
+
9
+ describe('Users Resource', () => {
10
+ let client: Rooguys;
11
+ let mockAxiosInstance: ReturnType<typeof createMockAxiosInstance>;
12
+ const apiKey = 'test-api-key';
13
+
14
+ beforeEach(() => {
15
+ mockAxiosInstance = createMockAxiosInstance();
16
+ mockedAxios.create.mockReturnValue(mockAxiosInstance as any);
17
+ client = new Rooguys(apiKey);
18
+ jest.clearAllMocks();
19
+ });
20
+
21
+ describe('get', () => {
22
+ it('should get a user profile', async () => {
23
+ mockAxiosInstance.get.mockResolvedValue(
24
+ mockSuccessResponse(mockResponses.userProfile)
25
+ );
26
+
27
+ const result = await client.users.get('user_123');
28
+
29
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/user/user_123');
30
+ expect(result).toEqual(mockResponses.userProfile);
31
+ expect(result.user_id).toBe('user123');
32
+ expect(result.points).toBe(100);
33
+ });
34
+
35
+ it('should handle user with no level', async () => {
36
+ const userWithoutLevel = {
37
+ ...mockResponses.userProfile,
38
+ level: null,
39
+ next_level: null,
40
+ };
41
+ mockAxiosInstance.get.mockResolvedValue(mockSuccessResponse(userWithoutLevel));
42
+
43
+ const result = await client.users.get('user_new');
44
+
45
+ expect(result.level).toBeNull();
46
+ expect(result.next_level).toBeNull();
47
+ });
48
+
49
+ it('should handle user with no badges', async () => {
50
+ const userWithoutBadges = {
51
+ ...mockResponses.userProfile,
52
+ badges: [],
53
+ };
54
+ mockAxiosInstance.get.mockResolvedValue(mockSuccessResponse(userWithoutBadges));
55
+
56
+ const result = await client.users.get('user_123');
57
+
58
+ expect(result.badges).toEqual([]);
59
+ });
60
+
61
+ it('should throw 404 error when user not found', async () => {
62
+ mockAxiosInstance.get.mockRejectedValue(
63
+ mockErrorResponse(404, mockErrors.notFoundError.message)
64
+ );
65
+
66
+ await expect(client.users.get('nonexistent_user')).rejects.toThrow(
67
+ "User 'user123' does not exist in this project"
68
+ );
69
+ });
70
+
71
+ it('should handle special characters in user ID', async () => {
72
+ mockAxiosInstance.get.mockResolvedValue(
73
+ mockSuccessResponse(mockResponses.userProfile)
74
+ );
75
+
76
+ await client.users.get('user@example.com');
77
+
78
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/user/user%40example.com');
79
+ });
80
+ });
81
+
82
+ describe('getBulk', () => {
83
+ it('should get multiple user profiles', async () => {
84
+ mockAxiosInstance.post.mockResolvedValue(
85
+ mockSuccessResponse(mockResponses.bulkUsersResponse)
86
+ );
87
+
88
+ const result = await client.users.getBulk(['user1', 'user2']);
89
+
90
+ expect(mockAxiosInstance.post).toHaveBeenCalledWith('/users/bulk', {
91
+ user_ids: ['user1', 'user2'],
92
+ });
93
+ expect(result).toEqual(mockResponses.bulkUsersResponse);
94
+ expect(result.users).toHaveLength(2);
95
+ });
96
+
97
+ it('should handle single user in bulk request', async () => {
98
+ mockAxiosInstance.post.mockResolvedValue(
99
+ mockSuccessResponse({ users: [mockResponses.userProfile] })
100
+ );
101
+
102
+ const result = await client.users.getBulk(['user_123']);
103
+
104
+ expect(result.users).toHaveLength(1);
105
+ });
106
+
107
+ it('should handle empty results', async () => {
108
+ mockAxiosInstance.post.mockResolvedValue(
109
+ mockSuccessResponse({ users: [] })
110
+ );
111
+
112
+ const result = await client.users.getBulk(['nonexistent1', 'nonexistent2']);
113
+
114
+ expect(result.users).toEqual([]);
115
+ });
116
+
117
+ it('should throw error for more than 100 users', async () => {
118
+ mockAxiosInstance.post.mockRejectedValue(
119
+ mockErrorResponse(400, 'Maximum 100 user IDs allowed')
120
+ );
121
+
122
+ const manyUsers = Array.from({ length: 101 }, (_, i) => `user_${i}`);
123
+
124
+ await expect(client.users.getBulk(manyUsers)).rejects.toThrow(
125
+ 'Maximum 100 user IDs allowed'
126
+ );
127
+ });
128
+ });
129
+
130
+ describe('getBadges', () => {
131
+ it('should get user badges', async () => {
132
+ mockAxiosInstance.get.mockResolvedValue(
133
+ mockSuccessResponse({ badges: mockResponses.userProfile.badges })
134
+ );
135
+
136
+ const result = await client.users.getBadges('user_123');
137
+
138
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/user/user_123/badges');
139
+ expect(result.badges).toHaveLength(1);
140
+ expect(result.badges[0].name).toBe('First Steps');
141
+ });
142
+
143
+ it('should handle user with no badges', async () => {
144
+ mockAxiosInstance.get.mockResolvedValue(
145
+ mockSuccessResponse({ badges: [] })
146
+ );
147
+
148
+ const result = await client.users.getBadges('user_new');
149
+
150
+ expect(result.badges).toEqual([]);
151
+ });
152
+
153
+ it('should throw 404 error when user not found', async () => {
154
+ mockAxiosInstance.get.mockRejectedValue(
155
+ mockErrorResponse(404, mockErrors.notFoundError.message)
156
+ );
157
+
158
+ await expect(client.users.getBadges('nonexistent_user')).rejects.toThrow(
159
+ "User 'user123' does not exist in this project"
160
+ );
161
+ });
162
+ });
163
+
164
+ describe('getRank', () => {
165
+ it('should get user rank with default timeframe', async () => {
166
+ mockAxiosInstance.get.mockResolvedValue(
167
+ mockSuccessResponse(mockResponses.userRankResponse)
168
+ );
169
+
170
+ const result = await client.users.getRank('user_123');
171
+
172
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/user/user_123/rank', {
173
+ params: { timeframe: 'all-time' },
174
+ });
175
+ expect(result).toEqual(mockResponses.userRankResponse);
176
+ expect(result.rank).toBe(42);
177
+ });
178
+
179
+ it('should get user rank with weekly timeframe', async () => {
180
+ mockAxiosInstance.get.mockResolvedValue(
181
+ mockSuccessResponse(mockResponses.userRankResponse)
182
+ );
183
+
184
+ await client.users.getRank('user_123', 'weekly');
185
+
186
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/user/user_123/rank', {
187
+ params: { timeframe: 'weekly' },
188
+ });
189
+ });
190
+
191
+ it('should get user rank with monthly timeframe', async () => {
192
+ mockAxiosInstance.get.mockResolvedValue(
193
+ mockSuccessResponse(mockResponses.userRankResponse)
194
+ );
195
+
196
+ await client.users.getRank('user_123', 'monthly');
197
+
198
+ expect(mockAxiosInstance.get).toHaveBeenCalledWith('/user/user_123/rank', {
199
+ params: { timeframe: 'monthly' },
200
+ });
201
+ });
202
+
203
+ it('should throw 404 error when user not found', async () => {
204
+ mockAxiosInstance.get.mockRejectedValue(
205
+ mockErrorResponse(404, mockErrors.notFoundError.message)
206
+ );
207
+
208
+ await expect(client.users.getRank('nonexistent_user')).rejects.toThrow(
209
+ "User 'user123' does not exist in this project"
210
+ );
211
+ });
212
+ });
213
+
214
+ describe('submitAnswers', () => {
215
+ it('should submit questionnaire answers', async () => {
216
+ mockAxiosInstance.post.mockResolvedValue(
217
+ mockSuccessResponse(mockResponses.answerSubmissionResponse)
218
+ );
219
+
220
+ const answers = [
221
+ { question_id: 'q1', answer_option_id: 'a1' },
222
+ { question_id: 'q2', answer_option_id: 'a2' },
223
+ ];
224
+
225
+ const result = await client.users.submitAnswers(
226
+ 'user_123',
227
+ 'questionnaire_id',
228
+ answers
229
+ );
230
+
231
+ expect(mockAxiosInstance.post).toHaveBeenCalledWith('/user/user_123/answers', {
232
+ questionnaire_id: 'questionnaire_id',
233
+ answers,
234
+ });
235
+ expect(result).toEqual(mockResponses.answerSubmissionResponse);
236
+ expect(result.status).toBe('accepted');
237
+ });
238
+
239
+ it('should handle single answer submission', async () => {
240
+ mockAxiosInstance.post.mockResolvedValue(
241
+ mockSuccessResponse(mockResponses.answerSubmissionResponse)
242
+ );
243
+
244
+ const answers = [{ question_id: 'q1', answer_option_id: 'a1' }];
245
+
246
+ await client.users.submitAnswers('user_123', 'questionnaire_id', answers);
247
+
248
+ expect(mockAxiosInstance.post).toHaveBeenCalled();
249
+ });
250
+
251
+ it('should throw error for invalid questionnaire ID', async () => {
252
+ mockAxiosInstance.post.mockRejectedValue(
253
+ mockErrorResponse(400, 'Invalid questionnaire ID')
254
+ );
255
+
256
+ const answers = [{ question_id: 'q1', answer_option_id: 'a1' }];
257
+
258
+ await expect(
259
+ client.users.submitAnswers('user_123', 'invalid_id', answers)
260
+ ).rejects.toThrow('Invalid questionnaire ID');
261
+ });
262
+
263
+ it('should throw error for empty answers array', async () => {
264
+ mockAxiosInstance.post.mockRejectedValue(
265
+ mockErrorResponse(400, 'Answers must be a non-empty array')
266
+ );
267
+
268
+ await expect(
269
+ client.users.submitAnswers('user_123', 'questionnaire_id', [])
270
+ ).rejects.toThrow('non-empty array');
271
+ });
272
+ });
273
+ });
@@ -0,0 +1,80 @@
1
+ import fc from 'fast-check';
2
+
3
+ /**
4
+ * Property-based testing generators for SDK inputs
5
+ */
6
+
7
+ export const arbitraries = {
8
+ // User ID: 1-255 characters, alphanumeric with some special chars
9
+ userId: () => fc.string({ minLength: 1, maxLength: 255 }).filter(s => s.trim().length > 0),
10
+
11
+ // Event name: 1-100 characters
12
+ eventName: () => fc.string({ minLength: 1, maxLength: 100 }).filter(s => s.trim().length > 0),
13
+
14
+ // Properties: any JSON-serializable object
15
+ properties: () => fc.dictionary(
16
+ fc.string({ minLength: 1, maxLength: 50 }),
17
+ fc.oneof(
18
+ fc.string(),
19
+ fc.integer(),
20
+ fc.double().filter(n => Number.isFinite(n)), // Exclude Infinity and NaN
21
+ fc.boolean(),
22
+ fc.constant(null)
23
+ )
24
+ ),
25
+
26
+ // Timeframe: one of the valid values
27
+ timeframe: () => fc.constantFrom('all-time', 'weekly', 'monthly'),
28
+
29
+ // Pagination parameters
30
+ pagination: () => fc.record({
31
+ page: fc.integer({ min: 1, max: 1000 }),
32
+ limit: fc.integer({ min: 1, max: 100 }),
33
+ }),
34
+
35
+ // Aha score value: 1-5
36
+ ahaValue: () => fc.integer({ min: 1, max: 5 }),
37
+
38
+ // Invalid Aha score value: outside 1-5 range
39
+ invalidAhaValue: () => fc.oneof(
40
+ fc.integer({ max: 0 }),
41
+ fc.integer({ min: 6 })
42
+ ),
43
+
44
+ // UUID for leaderboard IDs
45
+ uuid: () => fc.uuid(),
46
+
47
+ // Slug for questionnaires
48
+ slug: () => fc.string({ minLength: 1, maxLength: 100 })
49
+ .filter(s => /^[a-z0-9-]+$/.test(s)),
50
+
51
+ // Array of user IDs for bulk operations
52
+ userIds: () => fc.array(
53
+ fc.string({ minLength: 1, maxLength: 255 }),
54
+ { minLength: 1, maxLength: 100 }
55
+ ),
56
+
57
+ // Boolean for active_only filter
58
+ activeOnly: () => fc.boolean(),
59
+
60
+ // Search query
61
+ searchQuery: () => fc.option(fc.string({ maxLength: 100 }), { nil: null }),
62
+
63
+ // Base URL
64
+ baseUrl: () => fc.webUrl(),
65
+
66
+ // Timeout in milliseconds
67
+ timeout: () => fc.integer({ min: 1000, max: 60000 }),
68
+
69
+ // API key
70
+ apiKey: () => fc.string({ minLength: 10, maxLength: 100 }),
71
+
72
+ // Questionnaire answers
73
+ questionnaireAnswers: () => fc.array(
74
+ fc.record({
75
+ question_id: fc.uuid(),
76
+ answer_option_id: fc.uuid(),
77
+ }),
78
+ { minLength: 1, maxLength: 20 }
79
+ ),
80
+ };
@@ -0,0 +1,48 @@
1
+ import { AxiosInstance } from 'axios';
2
+
3
+ export interface MockAxiosInstance {
4
+ get: jest.Mock;
5
+ post: jest.Mock;
6
+ defaults: {
7
+ headers: {
8
+ common: Record<string, string>;
9
+ };
10
+ };
11
+ interceptors: {
12
+ request: { use: jest.Mock };
13
+ response: { use: jest.Mock };
14
+ };
15
+ }
16
+
17
+ export function createMockAxiosInstance(): MockAxiosInstance {
18
+ return {
19
+ get: jest.fn(),
20
+ post: jest.fn(),
21
+ defaults: {
22
+ headers: {
23
+ common: {},
24
+ },
25
+ },
26
+ interceptors: {
27
+ request: { use: jest.fn() },
28
+ response: { use: jest.fn() },
29
+ },
30
+ };
31
+ }
32
+
33
+ export function mockSuccessResponse<T>(data: T) {
34
+ return { data };
35
+ }
36
+
37
+ export function mockErrorResponse(status: number, message: string, details?: any) {
38
+ const error: any = new Error(message);
39
+ error.response = {
40
+ status,
41
+ data: {
42
+ error: message,
43
+ details,
44
+ },
45
+ };
46
+ error.isAxiosError = true;
47
+ return error;
48
+ }