fix(frontend): normalizeDevice serialNumber 加 trim(WP-C Minor #1)
純空白字串(" ")原判 truthy → 會以空白 serial 組出必失敗的請求路由。 改為先 trim 再判定:serial !== "" ? serial : null。順帶消除字面 "0" 被 falsy 誤判為 null 的隱性行為。補純空白 → null 邊界測試。 Reviewer 通過(0C/0M/0Mi)。tsc/eslint 0、18 test 綠。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
26b433eb10
commit
51dfd0f2d8
@ -175,7 +175,7 @@ describe("useDeviceStore", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("serial_number 正規化:snake_case / camelCase 都吃、缺欄位與空字串 → null(WP-C)", async () => {
|
it("serial_number 正規化:snake_case / camelCase 都吃、缺欄位與空字串/純空白 → null(WP-C)", async () => {
|
||||||
vi.spyOn(globalThis, "fetch").mockResolvedValueOnce(
|
vi.spyOn(globalThis, "fetch").mockResolvedValueOnce(
|
||||||
jsonResponse({
|
jsonResponse({
|
||||||
success: true,
|
success: true,
|
||||||
@ -188,6 +188,8 @@ describe("useDeviceStore", () => {
|
|||||||
{ id: "dev-3", name: "C", type: "kl520", status: "connected" },
|
{ id: "dev-3", name: "C", type: "kl520", status: "connected" },
|
||||||
// 空字串(防禦性;無法路由)→ null
|
// 空字串(防禦性;無法路由)→ null
|
||||||
{ id: "dev-4", name: "D", type: "kl520", status: "connected", serial_number: "" },
|
{ id: "dev-4", name: "D", type: "kl520", status: "connected", serial_number: "" },
|
||||||
|
// 純空白(防禦性;trim 後為空、無法路由)→ null
|
||||||
|
{ id: "dev-5", name: "E", type: "kl520", status: "connected", serial_number: " " },
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@ -198,6 +200,7 @@ describe("useDeviceStore", () => {
|
|||||||
expect(devices[1]?.serialNumber).toBe("KN99887766");
|
expect(devices[1]?.serialNumber).toBe("KN99887766");
|
||||||
expect(devices[2]?.serialNumber).toBeNull();
|
expect(devices[2]?.serialNumber).toBeNull();
|
||||||
expect(devices[3]?.serialNumber).toBeNull();
|
expect(devices[3]?.serialNumber).toBeNull();
|
||||||
|
expect(devices[4]?.serialNumber).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("fetchDevices 遇到 501 NOT_IMPLEMENTED 時視為空 list,不記錯誤", async () => {
|
it("fetchDevices 遇到 501 NOT_IMPLEMENTED 時視為空 list,不記錯誤", async () => {
|
||||||
|
|||||||
@ -112,14 +112,16 @@ function normalizeDevice(raw: unknown): Device {
|
|||||||
const rawRemoteStatus = pick<string>("remote_status", "remoteStatus") as
|
const rawRemoteStatus = pick<string>("remote_status", "remoteStatus") as
|
||||||
| RemoteStatus
|
| RemoteStatus
|
||||||
| undefined;
|
| undefined;
|
||||||
// serial_number 為 omitempty:缺欄位 → null;防禦性把空字串也視為 null
|
// serial_number 為 omitempty:缺欄位 → null;防禦性把空字串/純空白也視為 null
|
||||||
// (空字串無法路由,語意上等同「未回報序號」)。
|
// (空字串與空白皆無法路由,語意上等同「未回報序號」)。先 trim 再判定,
|
||||||
|
// 避免純空白(" ")誤判為 truthy 而以空白 serial 組出必失敗的請求路由。
|
||||||
const rawSerial = pick<string>("serial_number", "serialNumber");
|
const rawSerial = pick<string>("serial_number", "serialNumber");
|
||||||
|
const serial = rawSerial != null ? String(rawSerial).trim() : "";
|
||||||
return {
|
return {
|
||||||
id: String(pick<string>("id") ?? ""),
|
id: String(pick<string>("id") ?? ""),
|
||||||
name: String(pick<string>("name") ?? pick<string>("device_name") ?? ""),
|
name: String(pick<string>("name") ?? pick<string>("device_name") ?? ""),
|
||||||
alias: pick<string>("alias") ?? undefined,
|
alias: pick<string>("alias") ?? undefined,
|
||||||
serialNumber: rawSerial ? String(rawSerial) : null,
|
serialNumber: serial !== "" ? serial : null,
|
||||||
type: String(pick<string>("type", "device_type") ?? ""),
|
type: String(pick<string>("type", "device_type") ?? ""),
|
||||||
status: (pick<string>("status") as DeviceHardwareStatus) ?? "disconnected",
|
status: (pick<string>("status") as DeviceHardwareStatus) ?? "disconnected",
|
||||||
remoteStatus:
|
remoteStatus:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user