Skip to content

Commit f7d14ce

Browse files
authored
Require date range for campaign metrics query (#23)
1 parent 88d0787 commit f7d14ce

File tree

4 files changed

+46
-13
lines changed

4 files changed

+46
-13
lines changed

src/client/campaigns.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,8 @@ export function Campaigns<T extends Constructor<BaseIterableClient>>(Base: T) {
134134
): Promise<CampaignMetricsResponse> {
135135
const params = new URLSearchParams();
136136
params.append("campaignId", options.campaignId.toString());
137-
if (options.startDateTime)
138-
params.append("startDateTime", options.startDateTime);
139-
if (options.endDateTime)
140-
params.append("endDateTime", options.endDateTime);
137+
params.append("startDateTime", options.startDateTime);
138+
params.append("endDateTime", options.endDateTime);
141139

142140
const response = await this.client.get(
143141
`/api/campaigns/metrics?${params.toString()}`,

src/types/campaigns.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,11 @@ export type GetChildCampaignsParams = z.infer<
134134

135135
export const GetCampaignMetricsParamsSchema = z.object({
136136
campaignId: z.number().describe("Campaign ID to get metrics for"),
137-
startDateTime: IterableDateTimeSchema.optional().describe(
138-
"Start date for metrics (YYYY-MM-DD HH:MM:SS format)"
137+
startDateTime: IterableDateTimeSchema.describe(
138+
"Start of the metrics date range (YYYY-MM-DD HH:MM:SS format). Always use the narrowest window possible for performance."
139139
),
140-
endDateTime: IterableDateTimeSchema.optional().describe(
141-
"End date for metrics (YYYY-MM-DD HH:MM:SS format)"
140+
endDateTime: IterableDateTimeSchema.describe(
141+
"End of the metrics date range (YYYY-MM-DD HH:MM:SS format). Always use the narrowest window possible for performance."
142142
),
143143
});
144144

tests/integration/campaigns.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,8 @@ describe("Campaign Management Integration Tests", () => {
293293
withTimeout(
294294
client.getCampaignMetrics({
295295
campaignId: campaign.id,
296+
startDateTime: new Date(campaign.createdAt).toISOString(),
297+
endDateTime: new Date().toISOString(),
296298
})
297299
),
298300
"Get campaign metrics"

tests/unit/campaigns.test.ts

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,17 @@ describe("Campaign Management", () => {
239239
it("should parse CSV metrics correctly", async () => {
240240
const mockCsvData = "id,sent,delivered\n12345,1000,950\n12346,500,475";
241241
const mockResponse = { data: mockCsvData };
242-
const options = { campaignId: 12345, startDateTime: "2023-01-01" };
242+
const options = {
243+
campaignId: 12345,
244+
startDateTime: "2023-01-01",
245+
endDateTime: "2023-12-31",
246+
};
243247
mockAxiosInstance.get.mockResolvedValue(mockResponse);
244248

245249
const result = await client.getCampaignMetrics(options);
246250

247251
expect(mockAxiosInstance.get).toHaveBeenCalledWith(
248-
"/api/campaigns/metrics?campaignId=12345&startDateTime=2023-01-01",
252+
"/api/campaigns/metrics?campaignId=12345&startDateTime=2023-01-01&endDateTime=2023-12-31",
249253
{ responseType: "text" }
250254
);
251255
expect(result).toHaveLength(2);
@@ -261,7 +265,11 @@ describe("Campaign Management", () => {
261265
const mockResponse = { data: "" };
262266
mockAxiosInstance.get.mockResolvedValue(mockResponse);
263267

264-
const result = await client.getCampaignMetrics({ campaignId: 12345 });
268+
const result = await client.getCampaignMetrics({
269+
campaignId: 12345,
270+
startDateTime: "2023-01-01",
271+
endDateTime: "2023-12-31",
272+
});
265273

266274
expect(result).toEqual([]);
267275
});
@@ -270,7 +278,11 @@ describe("Campaign Management", () => {
270278
const mockResponse = { data: "id,sent,delivered" };
271279
mockAxiosInstance.get.mockResolvedValue(mockResponse);
272280

273-
const result = await client.getCampaignMetrics({ campaignId: 12345 });
281+
const result = await client.getCampaignMetrics({
282+
campaignId: 12345,
283+
startDateTime: "2023-01-01",
284+
endDateTime: "2023-12-31",
285+
});
274286

275287
expect(result).toEqual([]);
276288
});
@@ -296,7 +308,11 @@ describe("Campaign Management", () => {
296308
mockAxiosInstance.get.mockResolvedValue(mockResponse);
297309

298310
await expect(
299-
client.getCampaignMetrics({ campaignId: 12345 })
311+
client.getCampaignMetrics({
312+
campaignId: 12345,
313+
startDateTime: "2023-01-01",
314+
endDateTime: "2023-12-31",
315+
})
300316
).rejects.toThrow("CSV parse error");
301317
});
302318
});
@@ -518,6 +534,23 @@ describe("Campaign Management", () => {
518534
expect(() =>
519535
GetCampaignMetricsParamsSchema.parse({
520536
startDateTime: new Date("2023-01-01T00:00:00Z"),
537+
endDateTime: new Date("2023-12-31T23:59:59Z"),
538+
})
539+
).toThrow();
540+
541+
// Missing required startDateTime
542+
expect(() =>
543+
GetCampaignMetricsParamsSchema.parse({
544+
campaignId: 12345,
545+
endDateTime: new Date("2023-12-31T23:59:59Z"),
546+
})
547+
).toThrow();
548+
549+
// Missing required endDateTime
550+
expect(() =>
551+
GetCampaignMetricsParamsSchema.parse({
552+
campaignId: 12345,
553+
startDateTime: new Date("2023-01-01T00:00:00Z"),
521554
})
522555
).toThrow();
523556
});

0 commit comments

Comments
 (0)