@rooguys/sdk 0.1.0 → 1.0.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.
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Property-Based Test: HTTP Request Construction
3
3
  * Feature: sdk-testing-enhancement, Property 1: HTTP Request Construction
4
+ * Validates: Requirements 1.1, 3.1
4
5
  *
5
6
  * Tests that any valid SDK method call constructs correct HTTP request
6
7
  * with proper method, URL, headers, and body structure.
@@ -8,20 +9,22 @@
8
9
 
9
10
  import fc from 'fast-check';
10
11
  import { Rooguys } from '../../index';
11
- import { createMockAxiosInstance } from '../utils/mockClient';
12
+ import {
13
+ createMockRooguysClient,
14
+ mockAxiosResponse,
15
+ getLastRequestConfig,
16
+ MockAxiosInstance,
17
+ } from '../utils/mockClient';
12
18
  import { arbitraries } from '../utils/generators';
13
- import axios from 'axios';
14
-
15
- // Mock axios
16
- jest.mock('axios');
17
- const mockedAxios = axios as jest.Mocked<typeof axios>;
18
19
 
19
20
  describe('Property: HTTP Request Construction', () => {
20
- let mockClient: any;
21
+ let client: Rooguys;
22
+ let mockAxios: MockAxiosInstance;
21
23
 
22
24
  beforeEach(() => {
23
- mockClient = createMockAxiosInstance();
24
- mockedAxios.create.mockReturnValue(mockClient);
25
+ const mock = createMockRooguysClient();
26
+ client = mock.client;
27
+ mockAxios = mock.mockAxios;
25
28
  });
26
29
 
27
30
  afterEach(() => {
@@ -31,32 +34,28 @@ describe('Property: HTTP Request Construction', () => {
31
34
  it('should construct valid POST request for event tracking', async () => {
32
35
  await fc.assert(
33
36
  fc.asyncProperty(
34
- arbitraries.apiKey(),
35
37
  arbitraries.eventName(),
36
38
  arbitraries.userId(),
37
39
  arbitraries.properties(),
38
- async (apiKey, eventName, userId, properties) => {
40
+ async (eventName, userId, properties) => {
39
41
  // Arrange
40
- mockClient.post.mockResolvedValue({
41
- data: { status: 'queued', message: 'Event accepted' }
42
- });
43
- const sdk = new Rooguys(apiKey);
42
+ mockAxios.request.mockResolvedValue(mockAxiosResponse({
43
+ status: 'queued',
44
+ message: 'Event accepted'
45
+ }));
44
46
 
45
47
  // Act
46
- await sdk.events.track(eventName, userId, properties);
48
+ await client.events.track(eventName, userId, properties);
47
49
 
48
50
  // Assert
49
- expect(mockClient.post).toHaveBeenCalledWith(
50
- '/event',
51
- {
52
- event_name: eventName,
53
- user_id: userId,
54
- properties,
55
- },
56
- expect.objectContaining({
57
- params: expect.any(Object)
58
- })
59
- );
51
+ const config = getLastRequestConfig(mockAxios);
52
+ expect(config.method).toBe('POST');
53
+ expect(config.url).toBe('/events');
54
+ expect(config.data).toEqual({
55
+ event_name: eventName,
56
+ user_id: userId,
57
+ properties,
58
+ });
60
59
  }
61
60
  ),
62
61
  { numRuns: 100 }
@@ -66,20 +65,21 @@ describe('Property: HTTP Request Construction', () => {
66
65
  it('should construct valid GET request for user profile', async () => {
67
66
  await fc.assert(
68
67
  fc.asyncProperty(
69
- arbitraries.apiKey(),
70
68
  arbitraries.userId(),
71
- async (apiKey, userId) => {
69
+ async (userId) => {
72
70
  // Arrange
73
- mockClient.get.mockResolvedValue({
74
- data: { user_id: userId, points: 100 }
75
- });
76
- const sdk = new Rooguys(apiKey);
71
+ mockAxios.request.mockResolvedValue(mockAxiosResponse({
72
+ user_id: userId,
73
+ points: 100
74
+ }));
77
75
 
78
76
  // Act
79
- await sdk.users.get(userId);
77
+ await client.users.get(userId);
80
78
 
81
79
  // Assert
82
- expect(mockClient.get).toHaveBeenCalledWith(`/user/${encodeURIComponent(userId)}`);
80
+ const config = getLastRequestConfig(mockAxios);
81
+ expect(config.method).toBe('GET');
82
+ expect(config.url).toBe(`/users/${encodeURIComponent(userId)}`);
83
83
  }
84
84
  ),
85
85
  { numRuns: 100 }
@@ -89,23 +89,21 @@ describe('Property: HTTP Request Construction', () => {
89
89
  it('should construct valid POST request for bulk user fetch', async () => {
90
90
  await fc.assert(
91
91
  fc.asyncProperty(
92
- arbitraries.apiKey(),
93
92
  arbitraries.userIds(),
94
- async (apiKey, userIds) => {
93
+ async (userIds) => {
95
94
  // Arrange
96
- mockClient.post.mockResolvedValue({
97
- data: { users: [] }
98
- });
99
- const sdk = new Rooguys(apiKey);
95
+ mockAxios.request.mockResolvedValue(mockAxiosResponse({
96
+ users: []
97
+ }));
100
98
 
101
99
  // Act
102
- await sdk.users.getBulk(userIds);
100
+ await client.users.getBulk(userIds);
103
101
 
104
102
  // Assert
105
- expect(mockClient.post).toHaveBeenCalledWith(
106
- '/users/bulk',
107
- { user_ids: userIds }
108
- );
103
+ const config = getLastRequestConfig(mockAxios);
104
+ expect(config.method).toBe('POST');
105
+ expect(config.url).toBe('/users/bulk');
106
+ expect(config.data).toEqual({ user_ids: userIds });
109
107
  }
110
108
  ),
111
109
  { numRuns: 100 }
@@ -115,26 +113,29 @@ describe('Property: HTTP Request Construction', () => {
115
113
  it('should construct valid GET request with query parameters for leaderboard', async () => {
116
114
  await fc.assert(
117
115
  fc.asyncProperty(
118
- arbitraries.apiKey(),
119
116
  arbitraries.timeframe(),
120
117
  arbitraries.pagination(),
121
- async (apiKey, timeframe, { page, limit }) => {
118
+ async (timeframe, { page, limit }) => {
122
119
  // Arrange
123
- mockClient.get.mockResolvedValue({
124
- data: { rankings: [], page, limit, total: 0 }
125
- });
126
- const sdk = new Rooguys(apiKey);
120
+ mockAxios.request.mockResolvedValue(mockAxiosResponse({
121
+ rankings: [],
122
+ page,
123
+ limit,
124
+ total: 0
125
+ }));
127
126
 
128
127
  // Act
129
- await sdk.leaderboards.getGlobal(timeframe as any, page, limit);
128
+ await client.leaderboards.getGlobal(timeframe as any, page, limit);
130
129
 
131
130
  // Assert
132
- expect(mockClient.get).toHaveBeenCalledWith(
133
- '/leaderboard',
134
- {
135
- params: { timeframe, page, limit }
136
- }
137
- );
131
+ const config = getLastRequestConfig(mockAxios);
132
+ expect(config.method).toBe('GET');
133
+ expect(config.url).toBe('/leaderboards/global');
134
+ expect(config.params).toEqual(expect.objectContaining({
135
+ timeframe,
136
+ page,
137
+ limit
138
+ }));
138
139
  }
139
140
  ),
140
141
  { numRuns: 100 }
@@ -144,57 +145,107 @@ describe('Property: HTTP Request Construction', () => {
144
145
  it('should construct valid POST request for Aha score declaration', async () => {
145
146
  await fc.assert(
146
147
  fc.asyncProperty(
147
- arbitraries.apiKey(),
148
148
  arbitraries.userId(),
149
149
  arbitraries.ahaValue(),
150
- async (apiKey, userId, value) => {
150
+ async (userId, value) => {
151
151
  // Arrange
152
- mockClient.post.mockResolvedValue({
153
- data: { success: true, message: 'Score declared' }
154
- });
155
- const sdk = new Rooguys(apiKey);
152
+ mockAxios.request.mockResolvedValue(mockAxiosResponse({
153
+ success: true,
154
+ message: 'Score declared'
155
+ }));
156
156
 
157
157
  // Act
158
- await sdk.aha.declare(userId, value);
158
+ await client.aha.declare(userId, value);
159
159
 
160
160
  // Assert
161
- expect(mockClient.post).toHaveBeenCalledWith(
162
- '/aha/declare',
163
- {
164
- user_id: userId,
165
- value,
166
- }
167
- );
161
+ const config = getLastRequestConfig(mockAxios);
162
+ expect(config.method).toBe('POST');
163
+ expect(config.url).toBe('/aha/declare');
164
+ expect(config.data).toEqual({
165
+ user_id: userId,
166
+ value,
167
+ });
168
168
  }
169
169
  ),
170
170
  { numRuns: 100 }
171
171
  );
172
172
  });
173
173
 
174
- it('should include API key in request headers', async () => {
174
+ it('should construct valid GET request for badges list', async () => {
175
175
  await fc.assert(
176
176
  fc.asyncProperty(
177
- arbitraries.apiKey(),
178
- arbitraries.userId(),
179
- async (apiKey, userId) => {
177
+ arbitraries.pagination(),
178
+ fc.boolean(),
179
+ async ({ page, limit }, activeOnly) => {
180
180
  // Arrange
181
- mockClient.get.mockResolvedValue({
182
- data: { user_id: userId, points: 100 }
181
+ mockAxios.request.mockResolvedValue(mockAxiosResponse({
182
+ badges: [],
183
+ pagination: { page, limit, total: 0, totalPages: 0 }
184
+ }));
185
+
186
+ // Act
187
+ await client.badges.list(page, limit, activeOnly);
188
+
189
+ // Assert
190
+ const config = getLastRequestConfig(mockAxios);
191
+ expect(config.method).toBe('GET');
192
+ expect(config.url).toBe('/badges');
193
+ expect(config.params).toEqual({
194
+ page,
195
+ limit,
196
+ active_only: activeOnly
183
197
  });
198
+ }
199
+ ),
200
+ { numRuns: 100 }
201
+ );
202
+ });
203
+
204
+ it('should construct valid GET request for levels list', async () => {
205
+ await fc.assert(
206
+ fc.asyncProperty(
207
+ arbitraries.pagination(),
208
+ async ({ page, limit }) => {
209
+ // Arrange
210
+ mockAxios.request.mockResolvedValue(mockAxiosResponse({
211
+ levels: [],
212
+ pagination: { page, limit, total: 0, totalPages: 0 }
213
+ }));
184
214
 
185
215
  // Act
186
- const sdk = new Rooguys(apiKey);
187
- await sdk.users.get(userId);
188
-
189
- // Assert - verify axios.create was called with correct headers
190
- expect(mockedAxios.create).toHaveBeenCalledWith(
191
- expect.objectContaining({
192
- headers: expect.objectContaining({
193
- 'x-api-key': apiKey,
194
- 'Content-Type': 'application/json',
195
- })
196
- })
197
- );
216
+ await client.levels.list(page, limit);
217
+
218
+ // Assert
219
+ const config = getLastRequestConfig(mockAxios);
220
+ expect(config.method).toBe('GET');
221
+ expect(config.url).toBe('/levels');
222
+ expect(config.params).toEqual({ page, limit });
223
+ }
224
+ ),
225
+ { numRuns: 100 }
226
+ );
227
+ });
228
+
229
+ it('should construct valid GET request for questionnaire by slug', async () => {
230
+ await fc.assert(
231
+ fc.asyncProperty(
232
+ fc.string({ minLength: 1, maxLength: 50 }).filter(s => /^[a-z0-9-]+$/.test(s)),
233
+ async (slug) => {
234
+ // Arrange
235
+ mockAxios.request.mockResolvedValue(mockAxiosResponse({
236
+ id: 'q1',
237
+ slug,
238
+ title: 'Test',
239
+ questions: []
240
+ }));
241
+
242
+ // Act
243
+ await client.questionnaires.get(slug);
244
+
245
+ // Assert
246
+ const config = getLastRequestConfig(mockAxios);
247
+ expect(config.method).toBe('GET');
248
+ expect(config.url).toBe(`/questionnaires/${slug}`);
198
249
  }
199
250
  ),
200
251
  { numRuns: 100 }
@@ -1,6 +1,7 @@
1
1
  /**
2
- * Property-Based Test: Response Parsing Preservation
3
- * Feature: sdk-testing-enhancement, Property 2: Response Parsing Preservation
2
+ * Property-Based Test: Response Parsing Round-Trip
3
+ * Task 7.2: Property test for response parsing
4
+ * Validates: Requirements 2.1, 2.3, 2.4, 2.5
4
5
  *
5
6
  * Tests that any successful response is parsed correctly and data structure
6
7
  * is preserved including nested objects, arrays, and null values.
@@ -8,19 +9,21 @@
8
9
 
9
10
  import fc from 'fast-check';
10
11
  import { Rooguys } from '../../index';
11
- import { createMockAxiosInstance } from '../utils/mockClient';
12
- import axios from 'axios';
12
+ import { HttpClient } from '../../http-client';
13
+ import {
14
+ createMockRooguysClient,
15
+ mockAxiosResponse,
16
+ MockAxiosInstance,
17
+ } from '../utils/mockClient';
13
18
 
14
- // Mock axios
15
- jest.mock('axios');
16
- const mockedAxios = axios as jest.Mocked<typeof axios>;
17
-
18
- describe('Property: Response Parsing Preservation', () => {
19
- let mockClient: any;
19
+ describe('Property: Response Parsing Round-Trip', () => {
20
+ let client: Rooguys;
21
+ let mockAxios: MockAxiosInstance;
20
22
 
21
23
  beforeEach(() => {
22
- mockClient = createMockAxiosInstance();
23
- mockedAxios.create.mockReturnValue(mockClient);
24
+ const mock = createMockRooguysClient();
25
+ client = mock.client;
26
+ mockAxios = mock.mockAxios;
24
27
  });
25
28
 
26
29
  afterEach(() => {
@@ -30,7 +33,6 @@ describe('Property: Response Parsing Preservation', () => {
30
33
  it('should preserve nested object structures in responses', async () => {
31
34
  await fc.assert(
32
35
  fc.asyncProperty(
33
- fc.string({ minLength: 10, maxLength: 100 }),
34
36
  fc.string({ minLength: 1, maxLength: 255 }),
35
37
  fc.record({
36
38
  user_id: fc.string(),
@@ -47,16 +49,16 @@ describe('Property: Response Parsing Preservation', () => {
47
49
  }), { nil: null }),
48
50
  metrics: fc.dictionary(fc.string(), fc.integer()),
49
51
  }),
50
- async (apiKey, userId, responseData) => {
52
+ async (userId, responseData) => {
51
53
  // Arrange
52
- mockClient.get.mockResolvedValue({ data: responseData });
53
- const sdk = new Rooguys(apiKey);
54
+ mockAxios.request.mockResolvedValue(mockAxiosResponse(responseData));
54
55
 
55
56
  // Act
56
- const result = await sdk.users.get(userId);
57
+ const result = await client.users.get(userId);
57
58
 
58
- // Assert
59
- expect(result).toEqual(responseData);
59
+ // Assert - SDK preserves the response structure
60
+ expect(result.user_id).toEqual(responseData.user_id);
61
+ expect(result.points).toEqual(responseData.points);
60
62
  expect(result.level).toEqual(responseData.level);
61
63
  expect(result.next_level).toEqual(responseData.next_level);
62
64
  expect(result.metrics).toEqual(responseData.metrics);
@@ -69,62 +71,63 @@ describe('Property: Response Parsing Preservation', () => {
69
71
  it('should preserve arrays in responses', async () => {
70
72
  await fc.assert(
71
73
  fc.asyncProperty(
72
- fc.string({ minLength: 10, maxLength: 100 }),
73
74
  fc.array(fc.string({ minLength: 1, maxLength: 255 }), { minLength: 1, maxLength: 10 }),
74
75
  fc.array(fc.record({
75
76
  user_id: fc.string(),
76
77
  points: fc.integer(),
77
78
  }), { minLength: 0, maxLength: 20 }),
78
- async (apiKey, userIds, usersData) => {
79
+ async (userIds, usersData) => {
79
80
  // Arrange
80
81
  const responseData = { users: usersData };
81
- mockClient.post.mockResolvedValue({ data: responseData });
82
- const sdk = new Rooguys(apiKey);
82
+ mockAxios.request.mockResolvedValue(mockAxiosResponse(responseData));
83
83
 
84
84
  // Act
85
- const result = await sdk.users.getBulk(userIds);
85
+ const result = await client.users.getBulk(userIds);
86
86
 
87
87
  // Assert
88
- expect(result).toEqual(responseData);
89
88
  expect(Array.isArray(result.users)).toBe(true);
90
89
  expect(result.users).toHaveLength(usersData.length);
91
- expect(result.users).toEqual(usersData);
90
+ result.users.forEach((user, index) => {
91
+ expect(user.user_id).toEqual(usersData[index].user_id);
92
+ expect(user.points).toEqual(usersData[index].points);
93
+ });
92
94
  }
93
95
  ),
94
96
  { numRuns: 100 }
95
97
  );
96
98
  });
97
99
 
98
- it('should preserve null values in responses', async () => {
100
+ it('should preserve null values in aha score responses', async () => {
99
101
  await fc.assert(
100
102
  fc.asyncProperty(
101
- fc.string({ minLength: 10, maxLength: 100 }),
102
103
  fc.string({ minLength: 1, maxLength: 255 }),
103
104
  fc.record({
104
105
  user_id: fc.string(),
106
+ current_score: fc.integer({ min: 0, max: 100 }),
105
107
  declarative_score: fc.option(fc.integer({ min: 1, max: 5 }), { nil: null }),
106
108
  inferred_score: fc.option(fc.integer({ min: 0, max: 100 }), { nil: null }),
109
+ status: fc.constantFrom('not_started', 'progressing', 'activated'),
107
110
  history: fc.record({
108
111
  initial: fc.option(fc.integer(), { nil: null }),
109
112
  initial_date: fc.option(fc.string(), { nil: null }),
110
113
  previous: fc.option(fc.integer(), { nil: null }),
111
114
  }),
112
115
  }),
113
- async (apiKey, userId, responseData) => {
114
- // Arrange
115
- mockClient.get.mockResolvedValue({ data: responseData });
116
- const sdk = new Rooguys(apiKey);
116
+ async (userId, ahaData) => {
117
+ // Arrange - mock the wrapped response { success: true, data: {...} }
118
+ const responseData = { success: true, data: ahaData };
119
+ mockAxios.request.mockResolvedValue(mockAxiosResponse(responseData));
117
120
 
118
121
  // Act
119
- const result = await sdk.aha.getUserScore(userId);
120
-
121
- // Assert
122
- expect(result).toEqual(responseData);
123
- expect((result as any).declarative_score).toBe(responseData.declarative_score);
124
- expect((result as any).inferred_score).toBe(responseData.inferred_score);
125
- expect((result as any).history.initial).toBe(responseData.history.initial);
126
- expect((result as any).history.initial_date).toBe(responseData.history.initial_date);
127
- expect((result as any).history.previous).toBe(responseData.history.previous);
122
+ const result = await client.aha.getUserScore(userId);
123
+
124
+ // Assert - SDK unwraps { success: true, data: {...} } to just the data part
125
+ const data = result as any;
126
+ expect(data.declarative_score).toBe(ahaData.declarative_score);
127
+ expect(data.inferred_score).toBe(ahaData.inferred_score);
128
+ expect(data.history.initial).toBe(ahaData.history.initial);
129
+ expect(data.history.initial_date).toBe(ahaData.history.initial_date);
130
+ expect(data.history.previous).toBe(ahaData.history.previous);
128
131
  }
129
132
  ),
130
133
  { numRuns: 100 }
@@ -134,9 +137,8 @@ describe('Property: Response Parsing Preservation', () => {
134
137
  it('should handle empty objects and arrays', async () => {
135
138
  await fc.assert(
136
139
  fc.asyncProperty(
137
- fc.string({ minLength: 10, maxLength: 100 }),
138
140
  fc.constantFrom('all-time', 'weekly', 'monthly'),
139
- async (apiKey, timeframe) => {
141
+ async (timeframe) => {
140
142
  // Arrange
141
143
  const responseData = {
142
144
  timeframe,
@@ -145,53 +147,102 @@ describe('Property: Response Parsing Preservation', () => {
145
147
  total: 0,
146
148
  rankings: [],
147
149
  };
148
- mockClient.get.mockResolvedValue({ data: responseData });
149
- const sdk = new Rooguys(apiKey);
150
+ mockAxios.request.mockResolvedValue(mockAxiosResponse(responseData));
150
151
 
151
152
  // Act
152
- const result = await sdk.leaderboards.getGlobal(timeframe as any);
153
+ const result = await client.leaderboards.getGlobal(timeframe as any);
153
154
 
154
155
  // Assert
155
- expect(result).toEqual(responseData);
156
156
  expect(Array.isArray(result.rankings)).toBe(true);
157
157
  expect(result.rankings).toHaveLength(0);
158
+ expect(result.timeframe).toBe(timeframe);
158
159
  }
159
160
  ),
160
161
  { numRuns: 100 }
161
162
  );
162
163
  });
163
164
 
164
- it('should preserve complex nested structures', async () => {
165
+ it('should preserve complex nested structures with cache metadata', async () => {
165
166
  await fc.assert(
166
167
  fc.asyncProperty(
167
- fc.string({ minLength: 10, maxLength: 100 }),
168
168
  fc.record({
169
- success: fc.boolean(),
170
- data: fc.record({
169
+ timeframe: fc.constantFrom('all-time', 'weekly', 'monthly'),
170
+ page: fc.integer({ min: 1, max: 100 }),
171
+ limit: fc.integer({ min: 1, max: 100 }),
172
+ total: fc.integer({ min: 0, max: 10000 }),
173
+ rankings: fc.array(fc.record({
174
+ rank: fc.integer({ min: 1, max: 1000 }),
171
175
  user_id: fc.string(),
172
- current_score: fc.integer({ min: 0, max: 100 }),
173
- declarative_score: fc.option(fc.integer({ min: 1, max: 5 }), { nil: null }),
174
- inferred_score: fc.option(fc.integer({ min: 0, max: 100 }), { nil: null }),
175
- status: fc.constantFrom('not_started', 'progressing', 'activated'),
176
- history: fc.record({
177
- initial: fc.option(fc.integer(), { nil: null }),
178
- initial_date: fc.option(fc.string(), { nil: null }),
179
- previous: fc.option(fc.integer(), { nil: null }),
180
- }),
176
+ points: fc.integer({ min: 0, max: 100000 }),
177
+ percentile: fc.option(fc.float({ min: 0, max: 100 }), { nil: null }),
178
+ }), { minLength: 0, maxLength: 10 }),
179
+ cache_metadata: fc.option(fc.record({
180
+ cached_at: fc.string(),
181
+ ttl: fc.integer({ min: 0, max: 3600 }),
182
+ }), { nil: undefined }),
183
+ }),
184
+ async (responseData) => {
185
+ // Arrange
186
+ mockAxios.request.mockResolvedValue(mockAxiosResponse(responseData));
187
+
188
+ // Act
189
+ const result = await client.leaderboards.getGlobal();
190
+
191
+ // Assert
192
+ expect(result.timeframe).toBe(responseData.timeframe);
193
+ expect(result.page).toBe(responseData.page);
194
+ expect(result.limit).toBe(responseData.limit);
195
+ expect(result.total).toBe(responseData.total);
196
+ expect(result.rankings).toHaveLength(responseData.rankings.length);
197
+
198
+ // Verify each ranking entry
199
+ result.rankings.forEach((entry, index) => {
200
+ expect(entry.rank).toBe(responseData.rankings[index].rank);
201
+ expect(entry.user_id).toBe(responseData.rankings[index].user_id);
202
+ expect(entry.points).toBe(responseData.rankings[index].points);
203
+ });
204
+ }
205
+ ),
206
+ { numRuns: 100 }
207
+ );
208
+ });
209
+
210
+ it('should preserve badge list structures', async () => {
211
+ await fc.assert(
212
+ fc.asyncProperty(
213
+ fc.record({
214
+ badges: fc.array(fc.record({
215
+ id: fc.string(),
216
+ name: fc.string(),
217
+ description: fc.option(fc.string(), { nil: null }),
218
+ icon_url: fc.option(fc.string(), { nil: null }),
219
+ is_active: fc.boolean(),
220
+ }), { minLength: 0, maxLength: 10 }),
221
+ pagination: fc.record({
222
+ page: fc.integer({ min: 1, max: 100 }),
223
+ limit: fc.integer({ min: 1, max: 100 }),
224
+ total: fc.integer({ min: 0, max: 1000 }),
225
+ totalPages: fc.integer({ min: 0, max: 100 }),
181
226
  }),
182
227
  }),
183
- async (apiKey, responseData) => {
228
+ async (responseData) => {
184
229
  // Arrange
185
- mockClient.get.mockResolvedValue({ data: responseData });
186
- const sdk = new Rooguys(apiKey);
230
+ mockAxios.request.mockResolvedValue(mockAxiosResponse(responseData));
187
231
 
188
232
  // Act
189
- const result = await sdk.aha.getUserScore('test-user');
233
+ const result = await client.badges.list();
190
234
 
191
235
  // Assert
192
- expect(result).toEqual(responseData);
193
- expect(result.data).toEqual(responseData.data);
194
- expect(result.data.history).toEqual(responseData.data.history);
236
+ expect(result.badges).toHaveLength(responseData.badges.length);
237
+ expect(result.pagination).toEqual(responseData.pagination);
238
+
239
+ result.badges.forEach((badge, index) => {
240
+ expect(badge.id).toBe(responseData.badges[index].id);
241
+ expect(badge.name).toBe(responseData.badges[index].name);
242
+ expect(badge.description).toBe(responseData.badges[index].description);
243
+ expect(badge.icon_url).toBe(responseData.badges[index].icon_url);
244
+ expect(badge.is_active).toBe(responseData.badges[index].is_active);
245
+ });
195
246
  }
196
247
  ),
197
248
  { numRuns: 100 }