diff --git a/src/common/string/compare.ts b/src/common/string/compare.ts index 9d6aca76b8..8a8daa64df 100644 --- a/src/common/string/compare.ts +++ b/src/common/string/compare.ts @@ -2,12 +2,13 @@ import memoizeOne from "memoize-one"; import { isIPAddress } from "./is_ip_address"; const collator = memoizeOne( - (language: string | undefined) => new Intl.Collator(language) + (language: string | undefined) => + new Intl.Collator(language, { numeric: true }) ); const caseInsensitiveCollator = memoizeOne( (language: string | undefined) => - new Intl.Collator(language, { sensitivity: "accent" }) + new Intl.Collator(language, { sensitivity: "accent", numeric: true }) ); const fallbackStringCompare = (a: string, b: string) => { diff --git a/test/common/string/sort.test.ts b/test/common/string/sort.test.ts new file mode 100644 index 0000000000..3eafdadb67 --- /dev/null +++ b/test/common/string/sort.test.ts @@ -0,0 +1,51 @@ +import { assert, describe, it } from "vitest"; + +import { stringCompare } from "../../../src/common/string/compare"; + +describe("stringCompare", () => { + // Node only ships with English support for `Intl`, so we cannot test for other language collators. + it("Ensure natural order reutrned when numeric value is included", () => { + assert.strictEqual(stringCompare("Helper 2", "Helper 10"), -1); + }); + + it("Ensure prefixed numeric value is sorted naturally", () => { + assert.strictEqual(stringCompare("2 Helper", "10 Helper"), -1); + }); + + it("Ensure order has reversed alphabet is sorted", () => { + const reverseAlphabet = [ + "z", + "y", + "x", + "w", + "v", + "u", + "t", + "d", + "c", + "b", + "a", + ]; + assert.deepStrictEqual( + [...reverseAlphabet].sort(stringCompare), + [...reverseAlphabet].reverse() + ); + }); + + it("Ensure natural order when using numbers", () => { + const testArray = [ + "Helper 1", + "Helper 10", + "Helper 2", + "Helper 3", + "Helper 4", + ]; + assert.deepStrictEqual([...testArray].sort(stringCompare), [ + "Helper 1", + "Helper 2", + "Helper 3", + "Helper 4", + "Helper 10", + ]); + }); +});