diff --git a/src/ui/sidebar/host-sort.ts b/src/ui/sidebar/host-sort.ts index ef794fbf1..d8e7a9669 100644 --- a/src/ui/sidebar/host-sort.ts +++ b/src/ui/sidebar/host-sort.ts @@ -70,9 +70,9 @@ export function sortHostTree( case "name-desc": return hostB.name.localeCompare(hostA.name); case "ip-asc": - return hostA.ip.localeCompare(hostB.ip); + return hostA.ip.localeCompare(hostB.ip, undefined, { numeric: true }); case "ip-desc": - return hostB.ip.localeCompare(hostA.ip); + return hostB.ip.localeCompare(hostA.ip, undefined, { numeric: true }); case "status-online": return Number(hostB.online) - Number(hostA.online); case "status-offline": diff --git a/src/ui/tests/sidebar/host-sort.test.ts b/src/ui/tests/sidebar/host-sort.test.ts index ffb84db1a..9c6ac6725 100644 --- a/src/ui/tests/sidebar/host-sort.test.ts +++ b/src/ui/tests/sidebar/host-sort.test.ts @@ -75,6 +75,44 @@ describe("sortHostTree", () => { }); }); +describe("sortHostTree ip mode", () => { + const ips = (folder: HostFolder) => + folder.children.map((child) => (child as Host).ip); + const tree: HostFolder = { + name: "root", + children: [ + "10.0.0.210", + "db.internal", + "10.0.0.3", + "10.0.0.255", + "10.0.0.1", + "10.0.0.69", + "10.0.0.9", + ].map((ip) => ({ ...host(ip), ip })), + }; + + it("orders IPv4 addresses numerically by octet", () => { + expect(ips(sortHostTree(tree, "ip-asc"))).toEqual([ + "10.0.0.1", + "10.0.0.3", + "10.0.0.9", + "10.0.0.69", + "10.0.0.210", + "10.0.0.255", + "db.internal", + ]); + expect(ips(sortHostTree(tree, "ip-desc"))).toEqual([ + "db.internal", + "10.0.0.255", + "10.0.0.210", + "10.0.0.69", + "10.0.0.9", + "10.0.0.3", + "10.0.0.1", + ]); + }); +}); + describe("sortHostTree manual mode", () => { it("sorts hosts by sortOrder, nulls last, name tie-break", () => { const tree: HostFolder = {