Skip to content

Commit 0fc2cc3

Browse files
committed
feat: Update useSerialLogs to accept URL params
1 parent 9755ea1 commit 0fc2cc3

4 files changed

Lines changed: 254 additions & 4 deletions

File tree

static/js/publisher/hooks/__tests__/useSerialLogs.test.tsx

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,126 @@ describe("useSerialLogs", () => {
9090
});
9191
});
9292

93+
test("returns serial logs data with pageSize param", async () => {
94+
server.use(
95+
http.get(
96+
"/api/store/test-brand-id/models/test-model/serial-log",
97+
({ request }) => {
98+
const url = new URL(request.url);
99+
100+
expect(url.searchParams.get("page-size")).toBe("10");
101+
return HttpResponse.json({
102+
data: serialLogsResponse,
103+
success: true,
104+
});
105+
},
106+
),
107+
);
108+
109+
const { result } = renderHook(
110+
() =>
111+
useSerialLogs("test-brand-id", "test-model", {
112+
pageSize: 10,
113+
}),
114+
{
115+
wrapper: createWrapper(),
116+
},
117+
);
118+
119+
await waitFor(() => {
120+
expect(result.current.isSuccess).toBe(true);
121+
});
122+
123+
expect(result.current.data).toEqual({
124+
data: serialLogsResponse,
125+
success: true,
126+
});
127+
});
128+
129+
test("returns serial logs data with startTime and endTime params", async () => {
130+
server.use(
131+
http.get(
132+
"/api/store/test-brand-id/models/test-model/serial-log",
133+
({ request }) => {
134+
const url = new URL(request.url);
135+
expect(url.searchParams.get("start-time")).toBe(
136+
"2026-03-24T04:00:23.875000",
137+
);
138+
expect(url.searchParams.get("end-time")).toBe(
139+
"2026-03-28T04:00:23.875000",
140+
);
141+
return HttpResponse.json({
142+
data: serialLogsResponse,
143+
success: true,
144+
});
145+
},
146+
),
147+
);
148+
149+
const { result } = renderHook(
150+
() =>
151+
useSerialLogs("test-brand-id", "test-model", {
152+
startTime: "2026-03-24T04:00:23.875000",
153+
endTime: "2026-03-28T04:00:23.875000",
154+
}),
155+
{
156+
wrapper: createWrapper(),
157+
},
158+
);
159+
160+
await waitFor(() => {
161+
expect(result.current.isSuccess).toBe(true);
162+
});
163+
164+
expect(result.current.data).toEqual({
165+
data: serialLogsResponse,
166+
success: true,
167+
});
168+
});
169+
170+
test("returns serial logs data with startTime, endTime and pageSize params", async () => {
171+
server.use(
172+
http.get(
173+
"/api/store/test-brand-id/models/test-model/serial-log",
174+
({ request }) => {
175+
const url = new URL(request.url);
176+
expect(url.searchParams.get("start-time")).toBe(
177+
"2026-03-24T04:00:23.875000",
178+
);
179+
expect(url.searchParams.get("end-time")).toBe(
180+
"2026-03-28T04:00:23.875000",
181+
);
182+
expect(url.searchParams.get("page-size")).toBe("10");
183+
return HttpResponse.json({
184+
data: serialLogsResponse,
185+
success: true,
186+
});
187+
},
188+
),
189+
);
190+
191+
const { result } = renderHook(
192+
() =>
193+
useSerialLogs("test-brand-id", "test-model", {
194+
startTime: "2026-03-24T04:00:23.875000",
195+
endTime: "2026-03-28T04:00:23.875000",
196+
pageSize: 10,
197+
}),
198+
{
199+
wrapper: createWrapper(),
200+
},
201+
);
202+
203+
await waitFor(() => {
204+
expect(result.current.isSuccess).toBe(true);
205+
});
206+
207+
expect(result.current.data).toEqual({
208+
data: serialLogsResponse,
209+
success: true,
210+
});
211+
});
212+
93213
test("returns error if request fails", async () => {
94214
const { result } = renderHook(
95215
() => useSerialLogs("test-brand-id-fail", "test-model"),

static/js/publisher/hooks/useSerialLogs.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,34 @@ import type { SerialLogResponse, ApiResponse } from "../types/shared";
44
const useSerialLogs = (
55
brandId: string | undefined,
66
modelId: string | undefined,
7+
urlSearchParams?: {
8+
startTime?: string;
9+
endTime?: string;
10+
pageSize?: number;
11+
},
712
): UseQueryResult<ApiResponse<SerialLogResponse>, Error> => {
13+
const url = new URL(
14+
`/api/store/${brandId}/models/${modelId}/serial-log`,
15+
window.location.origin,
16+
);
17+
18+
if (urlSearchParams) {
19+
const { startTime, endTime, pageSize } = urlSearchParams;
20+
21+
if (startTime && endTime) {
22+
url.searchParams.set("start-time", startTime);
23+
url.searchParams.set("end-time", endTime);
24+
}
25+
26+
if (pageSize) {
27+
url.searchParams.set("page-size", pageSize.toString());
28+
}
29+
}
30+
831
return useQuery<ApiResponse<SerialLogResponse>, Error>({
9-
queryKey: ["serials", brandId, modelId],
32+
queryKey: ["serials", brandId, modelId, urlSearchParams],
1033
queryFn: async () => {
11-
const response = await fetch(
12-
`/api/store/${brandId}/models/${modelId}/serial-log`,
13-
);
34+
const response = await fetch(url.toString());
1435
const responseData = await response.json();
1536

1637
return responseData;

tests/endpoints/tests_models.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,3 +427,106 @@ def test_get_serial_log_general_error(self, mock_get_serial_log):
427427
self.assertEqual(response.status_code, 500)
428428
self.assertFalse(data["success"])
429429
self.assertEqual(data["message"], "Internal server error")
430+
431+
@patch(
432+
"canonicalwebteam.store_api.publishergw.PublisherGW"
433+
+ ".get_store_model_serial_logs"
434+
)
435+
def test_get_serial_log_with_time_range(self, mock_get_serial_log):
436+
mock_serial_log = []
437+
mock_get_serial_log.return_value = mock_serial_log
438+
response = self.client.get(
439+
"/api/store/1/models/test-model/serial-log"
440+
"?start-time=2026-06-01T00:00:00Z"
441+
"&end-time=2026-06-30T23:59:59Z"
442+
)
443+
data = response.json
444+
445+
self.assertEqual(response.status_code, 200)
446+
self.assertTrue(data["success"])
447+
self.assertEqual(data["data"], [])
448+
449+
mock_get_serial_log.assert_called_once()
450+
# Arguments are passed positionally:
451+
# (session, store_id, model_name, start_time, end_time, page_size)
452+
self.assertEqual(
453+
mock_get_serial_log.call_args.args[3],
454+
"2026-06-01T00:00:00Z",
455+
)
456+
self.assertEqual(
457+
mock_get_serial_log.call_args.args[4],
458+
"2026-06-30T23:59:59Z",
459+
)
460+
461+
@patch(
462+
"canonicalwebteam.store_api.publishergw.PublisherGW"
463+
+ ".get_store_model_serial_logs"
464+
)
465+
def test_get_serial_log_with_page_size(self, mock_get_serial_log):
466+
mock_serial_log = [
467+
{
468+
"brand-id": "test-brand-id",
469+
"created-at": "2026-03-23T04:00:23.875000",
470+
"model-name": "test-model",
471+
"serial": "test-serial",
472+
}
473+
]
474+
mock_get_serial_log.return_value = mock_serial_log
475+
response = self.client.get(
476+
"/api/store/1/models/test-model/serial-log?page-size=50"
477+
)
478+
data = response.json
479+
480+
self.assertEqual(response.status_code, 200)
481+
self.assertTrue(data["success"])
482+
self.assertEqual(data["data"], mock_serial_log)
483+
484+
mock_get_serial_log.assert_called_once()
485+
# Arguments are passed positionally:
486+
# (session, store_id, model_name, start_time, end_time, page_size)
487+
self.assertEqual(
488+
mock_get_serial_log.call_args.args[5],
489+
"50",
490+
)
491+
492+
@patch(
493+
"canonicalwebteam.store_api.publishergw.PublisherGW"
494+
+ ".get_store_model_serial_logs"
495+
)
496+
def test_get_serial_log_with_all_parameters(self, mock_get_serial_log):
497+
mock_serial_log = [
498+
{
499+
"brand-id": "test-brand-id",
500+
"created-at": "2026-03-23T04:00:23.875000",
501+
"model-name": "test-model",
502+
"serial": "test-serial",
503+
}
504+
]
505+
mock_get_serial_log.return_value = mock_serial_log
506+
response = self.client.get(
507+
"/api/store/1/models/test-model/serial-log"
508+
"?start-time=2026-01-01T00:00:00Z"
509+
"&end-time=2026-12-31T23:59:59Z"
510+
"&page-size=25"
511+
)
512+
data = response.json
513+
514+
self.assertEqual(response.status_code, 200)
515+
self.assertTrue(data["success"])
516+
self.assertEqual(data["data"], mock_serial_log)
517+
518+
mock_get_serial_log.assert_called_once()
519+
# Arguments are passed positionally:
520+
# (session, store_id, model_name, start_time, end_time, page_size)
521+
self.assertEqual(
522+
mock_get_serial_log.call_args.args[3],
523+
"2026-01-01T00:00:00Z",
524+
)
525+
self.assertEqual(
526+
mock_get_serial_log.call_args.args[4],
527+
"2026-12-31T23:59:59Z",
528+
)
529+
self.assertEqual(
530+
mock_get_serial_log.call_args.args[5],
531+
"25",
532+
)

webapp/endpoints/models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,13 +353,19 @@ def create_remodel_allowlist(store_id: str):
353353
@login_required
354354
@exchange_required
355355
def get_serial_log(store_id: str, model_name: str):
356+
start_time = flask.request.args.get("start-time")
357+
end_time = flask.request.args.get("end-time")
358+
page_size = flask.request.args.get("page-size")
356359
res = {}
357360

358361
try:
359362
logs = publisher_gateway.get_store_model_serial_logs(
360363
flask.session,
361364
store_id,
362365
model_name,
366+
start_time,
367+
end_time,
368+
page_size,
363369
)
364370
res["data"] = logs
365371
res["success"] = True

0 commit comments

Comments
 (0)