From e809446b356d62f24007de0dd93ced2785869226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Miko=C5=82ajczak?= Date: Tue, 20 Feb 2024 13:27:35 +0100 Subject: [PATCH 1/5] add function description --- src/libs/LocaleCompare.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libs/LocaleCompare.ts b/src/libs/LocaleCompare.ts index 5142c5b43d9a..ee2944e766fe 100644 --- a/src/libs/LocaleCompare.ts +++ b/src/libs/LocaleCompare.ts @@ -14,6 +14,14 @@ Onyx.connect({ }, }); +/** + * This is a wrapper around the localeCompare function that uses the preferred locale from the user's settings. + * + * It re-uses Intl.Collator for performance reasons. See https://github.com/facebook/hermes/issues/867 for more details. + * @param a + * @param b + * @returns -1 if a < b, 1 if a > b, 0 if a === b + */ function localeCompare(a: string, b: string) { return collator.compare(a, b); } From b880889e924201a000ed9a16cb54053edae3e492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Miko=C5=82ajczak?= Date: Tue, 20 Feb 2024 13:27:53 +0100 Subject: [PATCH 2/5] add basic tests --- tests/unit/LocaleCompareTest.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/unit/LocaleCompareTest.js diff --git a/tests/unit/LocaleCompareTest.js b/tests/unit/LocaleCompareTest.js new file mode 100644 index 000000000000..2fa0448e3be2 --- /dev/null +++ b/tests/unit/LocaleCompareTest.js @@ -0,0 +1,27 @@ +const {default: localeCompare} = require('@libs/LocaleCompare'); + +describe('localeCompare', () => { + it('should return -1 for descending comparison', () => { + const result = localeCompare('Da Vinci', 'Tesla'); + + expect(result).toBe(-1); + }); + + it('should return -1 for ascending comparison', () => { + const result = localeCompare('Zidane', 'Messi'); + + expect(result).toBe(1); + }); + + it('should return 0 for equal strings', () => { + const result = localeCompare('Cat', 'Cat'); + + expect(result).toBe(0); + }); + + it('should discard sensitivity differences', () => { + const result = localeCompare('apple', 'Apple'); + + expect(result).toBe(0); + }); +}); From a14d15f43ab0482e2e733a363973749a62cf4837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Miko=C5=82ajczak?= Date: Tue, 20 Feb 2024 14:58:00 +0100 Subject: [PATCH 3/5] add Onyx setup --- tests/unit/LocaleCompareTest.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/unit/LocaleCompareTest.js b/tests/unit/LocaleCompareTest.js index 2fa0448e3be2..df87b47c93c5 100644 --- a/tests/unit/LocaleCompareTest.js +++ b/tests/unit/LocaleCompareTest.js @@ -1,6 +1,20 @@ -const {default: localeCompare} = require('@libs/LocaleCompare'); +import Onyx from 'react-native-onyx'; +import localeCompare from '@libs/LocaleCompare'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; describe('localeCompare', () => { + beforeAll(() => { + Onyx.init({ + keys: {NVP_PREFERRED_LOCALE: ONYXKEYS.NVP_PREFERRED_LOCALE}, + initialKeyStates: {[ONYXKEYS.NVP_PREFERRED_LOCALE]: CONST.LOCALES.DEFAULT}, + }); + return waitForBatchedUpdates(); + }); + + afterEach(() => Onyx.clear()); + it('should return -1 for descending comparison', () => { const result = localeCompare('Da Vinci', 'Tesla'); From eff12f4ef2239384ba80202212b81fcdeb8b694a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Miko=C5=82ajczak?= Date: Tue, 20 Feb 2024 15:00:47 +0100 Subject: [PATCH 4/5] use default locale from CONST --- src/libs/LocaleCompare.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/libs/LocaleCompare.ts b/src/libs/LocaleCompare.ts index ee2944e766fe..b2c48b410d32 100644 --- a/src/libs/LocaleCompare.ts +++ b/src/libs/LocaleCompare.ts @@ -1,23 +1,22 @@ import Onyx from 'react-native-onyx'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -const DEFAULT_LOCALE = 'en'; - const COLLATOR_OPTIONS: Intl.CollatorOptions = {usage: 'sort', sensitivity: 'base'}; -let collator = new Intl.Collator(DEFAULT_LOCALE, COLLATOR_OPTIONS); +let collator = new Intl.Collator(CONST.LOCALES.DEFAULT, COLLATOR_OPTIONS); Onyx.connect({ key: ONYXKEYS.NVP_PREFERRED_LOCALE, callback: (locale) => { - collator = new Intl.Collator(locale ?? DEFAULT_LOCALE, COLLATOR_OPTIONS); + collator = new Intl.Collator(locale ?? CONST.LOCALES.DEFAULT, COLLATOR_OPTIONS); }, }); /** * This is a wrapper around the localeCompare function that uses the preferred locale from the user's settings. * - * It re-uses Intl.Collator for performance reasons. See https://github.com/facebook/hermes/issues/867 for more details. + * It re-uses Intl.Collator with static options for performance reasons. See https://github.com/facebook/hermes/issues/867 for more details. * @param a * @param b * @returns -1 if a < b, 1 if a > b, 0 if a === b From 5fef2d5d0e0f1d87fffc04e9eff1ddcfce84c3ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Miko=C5=82ajczak?= Date: Tue, 20 Feb 2024 15:10:06 +0100 Subject: [PATCH 5/5] add spanish sorting test --- tests/unit/LocaleCompareTest.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/unit/LocaleCompareTest.js b/tests/unit/LocaleCompareTest.js index df87b47c93c5..3c709675f31d 100644 --- a/tests/unit/LocaleCompareTest.js +++ b/tests/unit/LocaleCompareTest.js @@ -38,4 +38,14 @@ describe('localeCompare', () => { expect(result).toBe(0); }); + + it('distinguishes spanish diacritic characters', async () => { + await Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, CONST.LOCALES.ES); + + const input = ['zorro', 'árbol', 'jalapeño', 'jalapeno', 'nino', 'niño']; + + input.sort(localeCompare); + + expect(input).toEqual(['árbol', 'jalapeno', 'jalapeño', 'nino', 'niño', 'zorro']); + }); });