@inferevents/mcp 0.3.6 → 0.4.1
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.
- package/dist/api-client.d.ts +5 -0
- package/dist/api-client.d.ts.map +1 -1
- package/dist/index.js +0 -0
- package/dist/remote.d.ts +11 -0
- package/dist/remote.d.ts.map +1 -0
- package/dist/remote.js +69 -0
- package/dist/remote.js.map +1 -0
- package/dist/tools/get-insights.d.ts.map +1 -1
- package/dist/tools/get-insights.js +67 -16
- package/dist/tools/get-insights.js.map +1 -1
- package/package.json +4 -3
- package/dist/api-client.test.d.ts +0 -2
- package/dist/api-client.test.d.ts.map +0 -1
- package/dist/api-client.test.js +0 -383
- package/dist/api-client.test.js.map +0 -1
- package/dist/charts.test.d.ts +0 -2
- package/dist/charts.test.d.ts.map +0 -1
- package/dist/charts.test.js +0 -218
- package/dist/charts.test.js.map +0 -1
- package/dist/config.test.d.ts +0 -2
- package/dist/config.test.d.ts.map +0 -1
- package/dist/config.test.js +0 -409
- package/dist/config.test.js.map +0 -1
- package/dist/tips.test.d.ts +0 -2
- package/dist/tips.test.d.ts.map +0 -1
- package/dist/tips.test.js +0 -92
- package/dist/tips.test.js.map +0 -1
package/dist/api-client.test.js
DELETED
|
@@ -1,383 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { ApiClient, ApiError } from "./api-client.js";
|
|
3
|
-
const mockFetch = vi.fn();
|
|
4
|
-
vi.stubGlobal("fetch", mockFetch);
|
|
5
|
-
function makeConfig(overrides) {
|
|
6
|
-
return {
|
|
7
|
-
apiKey: "pk_read_test123",
|
|
8
|
-
endpoint: "https://api.infer.events",
|
|
9
|
-
projectId: "proj_default",
|
|
10
|
-
...overrides,
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
function jsonResponse(data, status = 200) {
|
|
14
|
-
return {
|
|
15
|
-
ok: status >= 200 && status < 300,
|
|
16
|
-
status,
|
|
17
|
-
json: () => Promise.resolve(data),
|
|
18
|
-
text: () => Promise.resolve(JSON.stringify(data)),
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
function textResponse(body, status) {
|
|
22
|
-
return {
|
|
23
|
-
ok: false,
|
|
24
|
-
status,
|
|
25
|
-
json: () => Promise.reject(new Error("not json")),
|
|
26
|
-
text: () => Promise.resolve(body),
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
describe("ApiClient", () => {
|
|
30
|
-
beforeEach(() => {
|
|
31
|
-
mockFetch.mockReset();
|
|
32
|
-
});
|
|
33
|
-
afterEach(() => {
|
|
34
|
-
mockFetch.mockReset();
|
|
35
|
-
});
|
|
36
|
-
describe("constructor", () => {
|
|
37
|
-
it("sets base URL from config", () => {
|
|
38
|
-
const client = new ApiClient(makeConfig({ endpoint: "https://custom.api.com" }));
|
|
39
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ groups: [], total: 0 }));
|
|
40
|
-
client.getEventCounts({ eventName: "test", timeRange: "7d" });
|
|
41
|
-
// We'll verify the URL in the fetch call
|
|
42
|
-
expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining("https://custom.api.com"), expect.any(Object));
|
|
43
|
-
});
|
|
44
|
-
it("sets auth headers from config apiKey", async () => {
|
|
45
|
-
const client = new ApiClient(makeConfig({ apiKey: "pk_read_mykey" }));
|
|
46
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ groups: [], total: 0 }));
|
|
47
|
-
await client.getEventCounts({ eventName: "test", timeRange: "7d" });
|
|
48
|
-
expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
|
|
49
|
-
headers: expect.objectContaining({
|
|
50
|
-
Authorization: "Bearer pk_read_mykey",
|
|
51
|
-
"Content-Type": "application/json",
|
|
52
|
-
}),
|
|
53
|
-
}));
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
describe("getEventCounts", () => {
|
|
57
|
-
it("calls correct URL with query params", async () => {
|
|
58
|
-
const client = new ApiClient(makeConfig());
|
|
59
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ groups: [], total: 0 }));
|
|
60
|
-
await client.getEventCounts({ eventName: "signup", timeRange: "7d" });
|
|
61
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
62
|
-
expect(url.pathname).toBe("/v1/query/event-counts");
|
|
63
|
-
});
|
|
64
|
-
it("includes event_name and time_range", async () => {
|
|
65
|
-
const client = new ApiClient(makeConfig());
|
|
66
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ groups: [], total: 0 }));
|
|
67
|
-
await client.getEventCounts({ eventName: "signup", timeRange: "30d" });
|
|
68
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
69
|
-
expect(url.searchParams.get("event_name")).toBe("signup");
|
|
70
|
-
expect(url.searchParams.get("time_range")).toBe("30d");
|
|
71
|
-
});
|
|
72
|
-
it("includes optional group_by", async () => {
|
|
73
|
-
const client = new ApiClient(makeConfig());
|
|
74
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ groups: [], total: 0 }));
|
|
75
|
-
await client.getEventCounts({
|
|
76
|
-
eventName: "signup",
|
|
77
|
-
timeRange: "7d",
|
|
78
|
-
groupBy: "country",
|
|
79
|
-
});
|
|
80
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
81
|
-
expect(url.searchParams.get("group_by")).toBe("country");
|
|
82
|
-
});
|
|
83
|
-
it("includes optional filters as JSON", async () => {
|
|
84
|
-
const client = new ApiClient(makeConfig());
|
|
85
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ groups: [], total: 0 }));
|
|
86
|
-
const filters = [{ field: "plan", op: "eq", value: "pro" }];
|
|
87
|
-
await client.getEventCounts({
|
|
88
|
-
eventName: "signup",
|
|
89
|
-
timeRange: "7d",
|
|
90
|
-
filters,
|
|
91
|
-
});
|
|
92
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
93
|
-
expect(url.searchParams.get("filters")).toBe(JSON.stringify(filters));
|
|
94
|
-
});
|
|
95
|
-
it("does not include filters when array is empty", async () => {
|
|
96
|
-
const client = new ApiClient(makeConfig());
|
|
97
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ groups: [], total: 0 }));
|
|
98
|
-
await client.getEventCounts({
|
|
99
|
-
eventName: "signup",
|
|
100
|
-
timeRange: "7d",
|
|
101
|
-
filters: [],
|
|
102
|
-
});
|
|
103
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
104
|
-
expect(url.searchParams.has("filters")).toBe(false);
|
|
105
|
-
});
|
|
106
|
-
it("includes project_id from params when provided", async () => {
|
|
107
|
-
const client = new ApiClient(makeConfig());
|
|
108
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ groups: [], total: 0 }));
|
|
109
|
-
await client.getEventCounts({
|
|
110
|
-
eventName: "signup",
|
|
111
|
-
timeRange: "7d",
|
|
112
|
-
projectId: "proj_override",
|
|
113
|
-
});
|
|
114
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
115
|
-
expect(url.searchParams.get("project_id")).toBe("proj_override");
|
|
116
|
-
});
|
|
117
|
-
it("falls back to default project_id from config", async () => {
|
|
118
|
-
const client = new ApiClient(makeConfig({ projectId: "proj_default" }));
|
|
119
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ groups: [], total: 0 }));
|
|
120
|
-
await client.getEventCounts({ eventName: "signup", timeRange: "7d" });
|
|
121
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
122
|
-
expect(url.searchParams.get("project_id")).toBe("proj_default");
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
describe("getRetention", () => {
|
|
126
|
-
it("calls correct URL with all required params", async () => {
|
|
127
|
-
const client = new ApiClient(makeConfig());
|
|
128
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ cohorts: [] }));
|
|
129
|
-
await client.getRetention({
|
|
130
|
-
startEvent: "signup",
|
|
131
|
-
returnEvent: "login",
|
|
132
|
-
timeRange: "30d",
|
|
133
|
-
granularity: "week",
|
|
134
|
-
});
|
|
135
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
136
|
-
expect(url.pathname).toBe("/v1/query/retention");
|
|
137
|
-
expect(url.searchParams.get("start_event")).toBe("signup");
|
|
138
|
-
expect(url.searchParams.get("return_event")).toBe("login");
|
|
139
|
-
expect(url.searchParams.get("time_range")).toBe("30d");
|
|
140
|
-
expect(url.searchParams.get("granularity")).toBe("week");
|
|
141
|
-
});
|
|
142
|
-
it("includes project_id", async () => {
|
|
143
|
-
const client = new ApiClient(makeConfig({ projectId: "proj_ret" }));
|
|
144
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ cohorts: [] }));
|
|
145
|
-
await client.getRetention({
|
|
146
|
-
startEvent: "signup",
|
|
147
|
-
returnEvent: "login",
|
|
148
|
-
timeRange: "30d",
|
|
149
|
-
granularity: "week",
|
|
150
|
-
});
|
|
151
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
152
|
-
expect(url.searchParams.get("project_id")).toBe("proj_ret");
|
|
153
|
-
});
|
|
154
|
-
it("uses param projectId over default", async () => {
|
|
155
|
-
const client = new ApiClient(makeConfig({ projectId: "proj_default" }));
|
|
156
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ cohorts: [] }));
|
|
157
|
-
await client.getRetention({
|
|
158
|
-
startEvent: "signup",
|
|
159
|
-
returnEvent: "login",
|
|
160
|
-
timeRange: "30d",
|
|
161
|
-
granularity: "week",
|
|
162
|
-
projectId: "proj_override",
|
|
163
|
-
});
|
|
164
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
165
|
-
expect(url.searchParams.get("project_id")).toBe("proj_override");
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
describe("getUserJourney", () => {
|
|
169
|
-
it("calls correct URL with user_id", async () => {
|
|
170
|
-
const client = new ApiClient(makeConfig());
|
|
171
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ events: [] }));
|
|
172
|
-
await client.getUserJourney({ userId: "user_abc" });
|
|
173
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
174
|
-
expect(url.pathname).toBe("/v1/query/user-journey");
|
|
175
|
-
expect(url.searchParams.get("user_id")).toBe("user_abc");
|
|
176
|
-
});
|
|
177
|
-
it("includes optional time_range", async () => {
|
|
178
|
-
const client = new ApiClient(makeConfig());
|
|
179
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ events: [] }));
|
|
180
|
-
await client.getUserJourney({ userId: "user_abc", timeRange: "7d" });
|
|
181
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
182
|
-
expect(url.searchParams.get("time_range")).toBe("7d");
|
|
183
|
-
});
|
|
184
|
-
it("includes optional limit", async () => {
|
|
185
|
-
const client = new ApiClient(makeConfig());
|
|
186
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ events: [] }));
|
|
187
|
-
await client.getUserJourney({ userId: "user_abc", limit: 50 });
|
|
188
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
189
|
-
expect(url.searchParams.get("limit")).toBe("50");
|
|
190
|
-
});
|
|
191
|
-
it("does not include time_range or limit when not provided", async () => {
|
|
192
|
-
const client = new ApiClient(makeConfig());
|
|
193
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ events: [] }));
|
|
194
|
-
await client.getUserJourney({ userId: "user_abc" });
|
|
195
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
196
|
-
expect(url.searchParams.has("time_range")).toBe(false);
|
|
197
|
-
expect(url.searchParams.has("limit")).toBe(false);
|
|
198
|
-
});
|
|
199
|
-
});
|
|
200
|
-
describe("getTopEvents", () => {
|
|
201
|
-
it("calls correct URL with time_range", async () => {
|
|
202
|
-
const client = new ApiClient(makeConfig());
|
|
203
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ events: [], total_event_names: 0 }));
|
|
204
|
-
await client.getTopEvents({ timeRange: "24h" });
|
|
205
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
206
|
-
expect(url.pathname).toBe("/v1/query/top-events");
|
|
207
|
-
expect(url.searchParams.get("time_range")).toBe("24h");
|
|
208
|
-
});
|
|
209
|
-
it("includes optional limit", async () => {
|
|
210
|
-
const client = new ApiClient(makeConfig());
|
|
211
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ events: [], total_event_names: 0 }));
|
|
212
|
-
await client.getTopEvents({ timeRange: "7d", limit: 10 });
|
|
213
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
214
|
-
expect(url.searchParams.get("limit")).toBe("10");
|
|
215
|
-
});
|
|
216
|
-
it("includes project_id from config default", async () => {
|
|
217
|
-
const client = new ApiClient(makeConfig({ projectId: "proj_top" }));
|
|
218
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ events: [], total_event_names: 0 }));
|
|
219
|
-
await client.getTopEvents({ timeRange: "7d" });
|
|
220
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
221
|
-
expect(url.searchParams.get("project_id")).toBe("proj_top");
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
describe("getInsights", () => {
|
|
225
|
-
it("calls correct URL", async () => {
|
|
226
|
-
const client = new ApiClient(makeConfig());
|
|
227
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ insights: [], count: 0 }));
|
|
228
|
-
await client.getInsights();
|
|
229
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
230
|
-
expect(url.pathname).toBe("/v1/query/insights");
|
|
231
|
-
});
|
|
232
|
-
it("includes optional severity filter", async () => {
|
|
233
|
-
const client = new ApiClient(makeConfig());
|
|
234
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ insights: [], count: 0 }));
|
|
235
|
-
await client.getInsights({ severity: "critical" });
|
|
236
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
237
|
-
expect(url.searchParams.get("severity")).toBe("critical");
|
|
238
|
-
});
|
|
239
|
-
it("works without params", async () => {
|
|
240
|
-
const client = new ApiClient(makeConfig());
|
|
241
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ insights: [], count: 0 }));
|
|
242
|
-
await client.getInsights();
|
|
243
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
244
|
-
// No query string when no params
|
|
245
|
-
expect(url.searchParams.has("severity")).toBe(false);
|
|
246
|
-
});
|
|
247
|
-
it("works with empty params object", async () => {
|
|
248
|
-
const client = new ApiClient(makeConfig());
|
|
249
|
-
mockFetch.mockResolvedValueOnce(jsonResponse({ insights: [], count: 0 }));
|
|
250
|
-
await client.getInsights({});
|
|
251
|
-
const url = new URL(mockFetch.mock.calls[0][0]);
|
|
252
|
-
expect(url.searchParams.has("severity")).toBe(false);
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
describe("error handling", () => {
|
|
256
|
-
it("throws ApiError with status 401 and auth failed message", async () => {
|
|
257
|
-
const client = new ApiClient(makeConfig());
|
|
258
|
-
mockFetch.mockResolvedValueOnce(textResponse("Unauthorized", 401));
|
|
259
|
-
try {
|
|
260
|
-
await client.getEventCounts({ eventName: "test", timeRange: "7d" });
|
|
261
|
-
expect.unreachable("Should have thrown");
|
|
262
|
-
}
|
|
263
|
-
catch (err) {
|
|
264
|
-
expect(err).toBeInstanceOf(ApiError);
|
|
265
|
-
expect(err.message).toMatch(/Authentication failed/);
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
it("includes statusCode 401 on ApiError", async () => {
|
|
269
|
-
const client = new ApiClient(makeConfig());
|
|
270
|
-
mockFetch.mockResolvedValueOnce(textResponse("Unauthorized", 401));
|
|
271
|
-
try {
|
|
272
|
-
await client.getEventCounts({ eventName: "test", timeRange: "7d" });
|
|
273
|
-
expect.unreachable("Should have thrown");
|
|
274
|
-
}
|
|
275
|
-
catch (err) {
|
|
276
|
-
expect(err).toBeInstanceOf(ApiError);
|
|
277
|
-
expect(err.statusCode).toBe(401);
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
it("throws ApiError with status 403 and access denied message", async () => {
|
|
281
|
-
const client = new ApiClient(makeConfig());
|
|
282
|
-
mockFetch.mockResolvedValueOnce(textResponse("Forbidden", 403));
|
|
283
|
-
await expect(client.getEventCounts({ eventName: "test", timeRange: "7d" })).rejects.toThrow(ApiError);
|
|
284
|
-
mockFetch.mockResolvedValueOnce(textResponse("Forbidden", 403));
|
|
285
|
-
await expect(client.getEventCounts({ eventName: "test", timeRange: "7d" })).rejects.toThrow(/Access denied/);
|
|
286
|
-
});
|
|
287
|
-
it("throws ApiError with status 500 and includes body detail", async () => {
|
|
288
|
-
const client = new ApiClient(makeConfig());
|
|
289
|
-
mockFetch.mockResolvedValueOnce(textResponse('{"error": "Internal server error"}', 500));
|
|
290
|
-
try {
|
|
291
|
-
await client.getEventCounts({ eventName: "test", timeRange: "7d" });
|
|
292
|
-
expect.unreachable("Should have thrown");
|
|
293
|
-
}
|
|
294
|
-
catch (err) {
|
|
295
|
-
expect(err).toBeInstanceOf(ApiError);
|
|
296
|
-
expect(err.statusCode).toBe(500);
|
|
297
|
-
expect(err.message).toContain("Internal server error");
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
it("throws ApiError on network failure with connection error", async () => {
|
|
301
|
-
const client = new ApiClient(makeConfig());
|
|
302
|
-
mockFetch.mockRejectedValueOnce(new Error("ECONNREFUSED"));
|
|
303
|
-
try {
|
|
304
|
-
await client.getEventCounts({ eventName: "test", timeRange: "7d" });
|
|
305
|
-
expect.unreachable("Should have thrown");
|
|
306
|
-
}
|
|
307
|
-
catch (err) {
|
|
308
|
-
expect(err).toBeInstanceOf(ApiError);
|
|
309
|
-
expect(err.statusCode).toBe(0);
|
|
310
|
-
expect(err.message).toContain("Failed to connect");
|
|
311
|
-
expect(err.message).toContain("ECONNREFUSED");
|
|
312
|
-
}
|
|
313
|
-
});
|
|
314
|
-
it("parses JSON error body when available", async () => {
|
|
315
|
-
const client = new ApiClient(makeConfig());
|
|
316
|
-
mockFetch.mockResolvedValueOnce({
|
|
317
|
-
ok: false,
|
|
318
|
-
status: 422,
|
|
319
|
-
text: () => Promise.resolve('{"error": "Invalid time range"}'),
|
|
320
|
-
});
|
|
321
|
-
try {
|
|
322
|
-
await client.getEventCounts({ eventName: "test", timeRange: "invalid" });
|
|
323
|
-
expect.unreachable("Should have thrown");
|
|
324
|
-
}
|
|
325
|
-
catch (err) {
|
|
326
|
-
expect(err).toBeInstanceOf(ApiError);
|
|
327
|
-
expect(err.message).toContain("Invalid time range");
|
|
328
|
-
}
|
|
329
|
-
});
|
|
330
|
-
it("uses message field from JSON error body", async () => {
|
|
331
|
-
const client = new ApiClient(makeConfig());
|
|
332
|
-
mockFetch.mockResolvedValueOnce({
|
|
333
|
-
ok: false,
|
|
334
|
-
status: 400,
|
|
335
|
-
text: () => Promise.resolve('{"message": "Bad request format"}'),
|
|
336
|
-
});
|
|
337
|
-
try {
|
|
338
|
-
await client.getEventCounts({ eventName: "test", timeRange: "7d" });
|
|
339
|
-
expect.unreachable("Should have thrown");
|
|
340
|
-
}
|
|
341
|
-
catch (err) {
|
|
342
|
-
expect(err).toBeInstanceOf(ApiError);
|
|
343
|
-
expect(err.message).toContain("Bad request format");
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
it("falls back to raw text when body is not JSON", async () => {
|
|
347
|
-
const client = new ApiClient(makeConfig());
|
|
348
|
-
mockFetch.mockResolvedValueOnce({
|
|
349
|
-
ok: false,
|
|
350
|
-
status: 502,
|
|
351
|
-
text: () => Promise.resolve("Bad Gateway"),
|
|
352
|
-
});
|
|
353
|
-
try {
|
|
354
|
-
await client.getEventCounts({ eventName: "test", timeRange: "7d" });
|
|
355
|
-
expect.unreachable("Should have thrown");
|
|
356
|
-
}
|
|
357
|
-
catch (err) {
|
|
358
|
-
expect(err).toBeInstanceOf(ApiError);
|
|
359
|
-
expect(err.message).toContain("Bad Gateway");
|
|
360
|
-
expect(err.statusCode).toBe(502);
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
});
|
|
364
|
-
describe("ApiError", () => {
|
|
365
|
-
it('has name "ApiError"', () => {
|
|
366
|
-
const err = new ApiError("test", 500);
|
|
367
|
-
expect(err.name).toBe("ApiError");
|
|
368
|
-
});
|
|
369
|
-
it("extends Error", () => {
|
|
370
|
-
const err = new ApiError("test", 500);
|
|
371
|
-
expect(err).toBeInstanceOf(Error);
|
|
372
|
-
});
|
|
373
|
-
it("stores statusCode", () => {
|
|
374
|
-
const err = new ApiError("test", 404);
|
|
375
|
-
expect(err.statusCode).toBe(404);
|
|
376
|
-
});
|
|
377
|
-
it("stores message", () => {
|
|
378
|
-
const err = new ApiError("something went wrong", 500);
|
|
379
|
-
expect(err.message).toBe("something went wrong");
|
|
380
|
-
});
|
|
381
|
-
});
|
|
382
|
-
});
|
|
383
|
-
//# sourceMappingURL=api-client.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.test.js","sourceRoot":"","sources":["../src/api-client.test.ts"],"names":[],"mappings":"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"}
|
package/dist/charts.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"charts.test.d.ts","sourceRoot":"","sources":["../src/charts.test.ts"],"names":[],"mappings":""}
|
package/dist/charts.test.js
DELETED
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { sanitize, bar, sparkline, status, trend, miniBarChart } from "./charts.js";
|
|
3
|
-
describe("sanitize", () => {
|
|
4
|
-
it("returns short strings as-is", () => {
|
|
5
|
-
expect(sanitize("hello world")).toBe("hello world");
|
|
6
|
-
});
|
|
7
|
-
it("truncates strings over 100 chars with ellipsis", () => {
|
|
8
|
-
const long = "a".repeat(120);
|
|
9
|
-
const result = sanitize(long);
|
|
10
|
-
expect(result).toHaveLength(103); // 100 + "..."
|
|
11
|
-
expect(result.endsWith("...")).toBe(true);
|
|
12
|
-
expect(result.startsWith("a".repeat(100))).toBe(true);
|
|
13
|
-
});
|
|
14
|
-
it("returns exactly 100-char strings without truncation", () => {
|
|
15
|
-
const exact = "b".repeat(100);
|
|
16
|
-
expect(sanitize(exact)).toBe(exact);
|
|
17
|
-
});
|
|
18
|
-
it("strips control characters", () => {
|
|
19
|
-
const withControl = "hello\x00world\x08test\x1F";
|
|
20
|
-
expect(sanitize(withControl)).toBe("helloworldtest");
|
|
21
|
-
});
|
|
22
|
-
it("preserves newlines and tabs (allowed whitespace)", () => {
|
|
23
|
-
// \n is \x0A, \t is \x09 — both outside the stripped range
|
|
24
|
-
expect(sanitize("line1\nline2\ttab")).toBe("line1\nline2\ttab");
|
|
25
|
-
});
|
|
26
|
-
it("converts numbers via JSON.stringify", () => {
|
|
27
|
-
expect(sanitize(42)).toBe("42");
|
|
28
|
-
expect(sanitize(3.14)).toBe("3.14");
|
|
29
|
-
});
|
|
30
|
-
it("converts objects via JSON.stringify", () => {
|
|
31
|
-
expect(sanitize({ key: "val" })).toBe('{"key":"val"}');
|
|
32
|
-
});
|
|
33
|
-
it("converts arrays via JSON.stringify", () => {
|
|
34
|
-
expect(sanitize([1, 2, 3])).toBe("[1,2,3]");
|
|
35
|
-
});
|
|
36
|
-
it("handles null", () => {
|
|
37
|
-
expect(sanitize(null)).toBe("null");
|
|
38
|
-
});
|
|
39
|
-
it("handles undefined", () => {
|
|
40
|
-
// JSON.stringify(undefined) returns undefined, ?? "" catches it
|
|
41
|
-
expect(sanitize(undefined)).toBe("");
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
describe("bar", () => {
|
|
45
|
-
it("renders correct filled/empty ratio for 50%", () => {
|
|
46
|
-
const result = bar(50, 100, 20);
|
|
47
|
-
const filled = (result.match(/█/g) || []).length;
|
|
48
|
-
const empty = (result.match(/░/g) || []).length;
|
|
49
|
-
expect(filled).toBe(10);
|
|
50
|
-
expect(empty).toBe(10);
|
|
51
|
-
expect(result).toContain("50%");
|
|
52
|
-
});
|
|
53
|
-
it("renders all empty for 0%", () => {
|
|
54
|
-
const result = bar(0, 100, 20);
|
|
55
|
-
const filled = (result.match(/█/g) || []).length;
|
|
56
|
-
const empty = (result.match(/░/g) || []).length;
|
|
57
|
-
expect(filled).toBe(0);
|
|
58
|
-
expect(empty).toBe(20);
|
|
59
|
-
expect(result).toContain("0%");
|
|
60
|
-
});
|
|
61
|
-
it("renders all filled for 100%", () => {
|
|
62
|
-
const result = bar(100, 100, 20);
|
|
63
|
-
const filled = (result.match(/█/g) || []).length;
|
|
64
|
-
const empty = (result.match(/░/g) || []).length;
|
|
65
|
-
expect(filled).toBe(20);
|
|
66
|
-
expect(empty).toBe(0);
|
|
67
|
-
expect(result).toContain("100%");
|
|
68
|
-
});
|
|
69
|
-
it("handles max=0 gracefully", () => {
|
|
70
|
-
const result = bar(0, 0, 20);
|
|
71
|
-
const empty = (result.match(/░/g) || []).length;
|
|
72
|
-
expect(empty).toBe(20);
|
|
73
|
-
expect(result).toContain("0%");
|
|
74
|
-
});
|
|
75
|
-
it("uses default width of 25", () => {
|
|
76
|
-
const result = bar(100, 100);
|
|
77
|
-
const filled = (result.match(/█/g) || []).length;
|
|
78
|
-
expect(filled).toBe(25);
|
|
79
|
-
});
|
|
80
|
-
it("respects custom width parameter", () => {
|
|
81
|
-
const result = bar(100, 100, 10);
|
|
82
|
-
const filled = (result.match(/█/g) || []).length;
|
|
83
|
-
expect(filled).toBe(10);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
describe("sparkline", () => {
|
|
87
|
-
it("renders sparkline characters for varying values", () => {
|
|
88
|
-
const result = sparkline([1, 3, 5, 2, 8, 6, 7]);
|
|
89
|
-
expect(result).toHaveLength(7);
|
|
90
|
-
// Each character should be a valid sparkline char
|
|
91
|
-
for (const ch of result) {
|
|
92
|
-
expect("▁▂▃▄▅▆▇█").toContain(ch);
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
it("uses lowest char for min and highest char for max", () => {
|
|
96
|
-
const result = sparkline([0, 100]);
|
|
97
|
-
expect(result[0]).toBe("▁");
|
|
98
|
-
expect(result[1]).toBe("█");
|
|
99
|
-
});
|
|
100
|
-
it("returns empty string for empty array", () => {
|
|
101
|
-
expect(sparkline([])).toBe("");
|
|
102
|
-
});
|
|
103
|
-
it("handles single value", () => {
|
|
104
|
-
const result = sparkline([5]);
|
|
105
|
-
expect(result).toHaveLength(1);
|
|
106
|
-
expect("▁▂▃▄▅▆▇█").toContain(result);
|
|
107
|
-
});
|
|
108
|
-
it("handles all same values (flat line)", () => {
|
|
109
|
-
const result = sparkline([5, 5, 5, 5]);
|
|
110
|
-
expect(result).toHaveLength(4);
|
|
111
|
-
// When range is 0, all values map to the same index
|
|
112
|
-
const firstChar = result[0];
|
|
113
|
-
expect(result).toBe(firstChar.repeat(4));
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
describe("status", () => {
|
|
117
|
-
const thresholds = { bad: 10, ok: 20, good: 30 };
|
|
118
|
-
it("returns green circle for values >= good threshold", () => {
|
|
119
|
-
expect(status(30, thresholds)).toBe("🟢");
|
|
120
|
-
expect(status(50, thresholds)).toBe("🟢");
|
|
121
|
-
});
|
|
122
|
-
it("returns yellow circle for values between ok and good", () => {
|
|
123
|
-
expect(status(25, thresholds)).toBe("🟡");
|
|
124
|
-
expect(status(20, thresholds)).toBe("🟡");
|
|
125
|
-
});
|
|
126
|
-
it("returns yellow circle for values between bad and ok", () => {
|
|
127
|
-
expect(status(15, thresholds)).toBe("🟡");
|
|
128
|
-
expect(status(10, thresholds)).toBe("🟡");
|
|
129
|
-
});
|
|
130
|
-
it("returns red circle for values below bad threshold", () => {
|
|
131
|
-
expect(status(5, thresholds)).toBe("🔴");
|
|
132
|
-
expect(status(0, thresholds)).toBe("🔴");
|
|
133
|
-
expect(status(9, thresholds)).toBe("🔴");
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
describe("trend", () => {
|
|
137
|
-
it("shows up arrow with positive percentage", () => {
|
|
138
|
-
const result = trend(38, 29);
|
|
139
|
-
expect(result).toContain("↑");
|
|
140
|
-
expect(result).toContain("+31%");
|
|
141
|
-
});
|
|
142
|
-
it("shows down arrow with negative percentage", () => {
|
|
143
|
-
const result = trend(29, 38);
|
|
144
|
-
expect(result).toContain("↓");
|
|
145
|
-
expect(result).toContain("-24%");
|
|
146
|
-
});
|
|
147
|
-
it('shows flat arrow for <1% change', () => {
|
|
148
|
-
const result = trend(100, 100);
|
|
149
|
-
expect(result).toBe("→ flat");
|
|
150
|
-
});
|
|
151
|
-
it('shows "new" when previous is 0 and current > 0', () => {
|
|
152
|
-
const result = trend(10, 0);
|
|
153
|
-
expect(result).toBe("↑ new");
|
|
154
|
-
});
|
|
155
|
-
it('shows "0" when both are 0', () => {
|
|
156
|
-
const result = trend(0, 0);
|
|
157
|
-
expect(result).toBe("→ 0");
|
|
158
|
-
});
|
|
159
|
-
it("handles very small but non-trivial changes", () => {
|
|
160
|
-
// 1% change exactly: (101 - 100) / 100 * 100 = 1%
|
|
161
|
-
const result = trend(101, 100);
|
|
162
|
-
expect(result).toContain("↑");
|
|
163
|
-
expect(result).toContain("+1%");
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
describe("miniBarChart", () => {
|
|
167
|
-
it("renders grouped bars with labels and percentages", () => {
|
|
168
|
-
const result = miniBarChart([
|
|
169
|
-
{ key: "US", count: 450 },
|
|
170
|
-
{ key: "UK", count: 120 },
|
|
171
|
-
], 20);
|
|
172
|
-
expect(result).toContain("US");
|
|
173
|
-
expect(result).toContain("UK");
|
|
174
|
-
expect(result).toContain("450");
|
|
175
|
-
expect(result).toContain("120");
|
|
176
|
-
// Should have percentage labels
|
|
177
|
-
expect(result).toMatch(/\d+%/);
|
|
178
|
-
});
|
|
179
|
-
it("returns empty string for empty groups", () => {
|
|
180
|
-
expect(miniBarChart([])).toBe("");
|
|
181
|
-
});
|
|
182
|
-
it("separates groups with double newlines", () => {
|
|
183
|
-
const result = miniBarChart([
|
|
184
|
-
{ key: "A", count: 10 },
|
|
185
|
-
{ key: "B", count: 20 },
|
|
186
|
-
]);
|
|
187
|
-
expect(result).toContain("\n\n");
|
|
188
|
-
});
|
|
189
|
-
it("pads keys to align bars", () => {
|
|
190
|
-
const result = miniBarChart([
|
|
191
|
-
{ key: "Short", count: 10 },
|
|
192
|
-
{ key: "LongerKey", count: 20 },
|
|
193
|
-
]);
|
|
194
|
-
const lines = result.split("\n\n");
|
|
195
|
-
// Both lines should have the key padded to the same length before the bar
|
|
196
|
-
const firstKeySection = lines[0].split("█")[0].split("░")[0];
|
|
197
|
-
const secondKeySection = lines[1].split("█")[0].split("░")[0];
|
|
198
|
-
expect(firstKeySection.length).toBe(secondKeySection.length);
|
|
199
|
-
});
|
|
200
|
-
it("handles single group", () => {
|
|
201
|
-
const result = miniBarChart([{ key: "Only", count: 100 }], 10);
|
|
202
|
-
expect(result).toContain("Only");
|
|
203
|
-
expect(result).toContain("100%");
|
|
204
|
-
// Full bar for the only group
|
|
205
|
-
const filled = (result.match(/█/g) || []).length;
|
|
206
|
-
expect(filled).toBe(10);
|
|
207
|
-
});
|
|
208
|
-
it("handles all-zero counts", () => {
|
|
209
|
-
const result = miniBarChart([
|
|
210
|
-
{ key: "A", count: 0 },
|
|
211
|
-
{ key: "B", count: 0 },
|
|
212
|
-
]);
|
|
213
|
-
expect(result).toContain("0%");
|
|
214
|
-
// No filled blocks when max is 0
|
|
215
|
-
expect(result).not.toContain("█");
|
|
216
|
-
});
|
|
217
|
-
});
|
|
218
|
-
//# sourceMappingURL=charts.test.js.map
|