From aa1e5c028272a38755533c103964a9cd8740bf75 Mon Sep 17 00:00:00 2001 From: Aliullov Vlad Date: Fri, 30 Aug 2024 16:50:54 +0400 Subject: [PATCH] Fix filtering issues for string in different locales (T1242756) --- .../js/__internal/data/m_array_query.ts | 10 +++++++--- packages/devextreme/js/core/utils/data.js | 4 +--- .../tests/DevExpress.data/queryArray.tests.js | 20 ++++++++++++++----- .../dataSource.tests.js | 5 +++-- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/packages/devextreme/js/__internal/data/m_array_query.ts b/packages/devextreme/js/__internal/data/m_array_query.ts index cdb326386a0f..74771603bde6 100644 --- a/packages/devextreme/js/__internal/data/m_array_query.ts +++ b/packages/devextreme/js/__internal/data/m_array_query.ts @@ -247,9 +247,11 @@ const SortIterator = Iterator.inherit({ }); const compileCriteria = (function () { - let langParams = {}; + let langParams: Record = {}; + let useUpperCase = false; + // eslint-disable-next-line @typescript-eslint/naming-convention - const _toComparable = (value) => toComparable(value, false, langParams, { useUpperCase: true }); + const _toComparable = (value) => toComparable(value, false, langParams, { useUpperCase }); const compileUniformEqualsCriteria = (crit) => { const getter = compileGetter(crit[0][0]); @@ -310,7 +312,6 @@ const compileCriteria = (function () { const toString = function (value) { return isDefined(value) - // @ts-expect-error ? langParams?.locale ? value.toLocaleString(langParams.locale) : value.toString() : ''; }; @@ -390,6 +391,9 @@ const compileCriteria = (function () { return function (crit, options) { langParams = options || {}; + const locale = langParams?.locale?.toLowerCase(); + + useUpperCase = locale && !!['hy', 'el'].find((code) => locale === code || locale.startsWith(`${code}-`)); if (isFunction(crit)) { return crit; diff --git a/packages/devextreme/js/core/utils/data.js b/packages/devextreme/js/core/utils/data.js index 89f1fdfd34e7..1722afd45032 100644 --- a/packages/devextreme/js/core/utils/data.js +++ b/packages/devextreme/js/core/utils/data.js @@ -207,9 +207,7 @@ export const toComparable = function(value, caseSensitive, langParams = {}, opti const isCaseSensitive = caseSensitive || collatorSensitivity === 'case'; if(typeof value === 'string' && !isCaseSensitive) { - return options?.useUpperCase ? - toUpperCase(value, langParams) - : toLowerCase(value, langParams); + return (options?.useUpperCase ? toUpperCase : toLowerCase)(value, langParams); } return value; diff --git a/packages/devextreme/testing/tests/DevExpress.data/queryArray.tests.js b/packages/devextreme/testing/tests/DevExpress.data/queryArray.tests.js index 611142c0bf4b..e207925ef03f 100644 --- a/packages/devextreme/testing/tests/DevExpress.data/queryArray.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.data/queryArray.tests.js @@ -414,11 +414,17 @@ QUnit.test('filtering use correct case insensitivity search', function(assert) { { ID: 7, Name: 'baιτησa' }, ]; - const arrayStartsWith = QUERY(input).filter(['Name', 'startswith', 'AΙΤΗΣ']).toArray(); + const query = QUERY(input, { + langParams: { + locale: 'el-GR' + } + }); - const arrayEndsWith = QUERY(input).filter(['Name', 'endswith', 'ΙΤΗΣ']).toArray(); + const arrayStartsWith = query.filter(['Name', 'startswith', 'AΙΤΗΣ']).toArray(); - const arrayContains = QUERY(input).filter(['Name', 'contains', 'ΙΤΗΣ']).toArray(); + const arrayEndsWith = query.filter(['Name', 'endswith', 'ΙΤΗΣ']).toArray(); + + const arrayContains = query.filter(['Name', 'contains', 'ΙΤΗΣ']).toArray(); assert.equal(arrayStartsWith.length, 4); assert.equal(arrayEndsWith.length, 2); @@ -430,13 +436,17 @@ QUnit.test('filtering use correct case insensitivity search', function(assert) { assert.false(containsUnwantedValue); }); -QUnit.test('filtering use correct case insensitivity search for AM locale', function(assert) { +QUnit.test('filtering use correct case insensitivity search for Armenian locale', function(assert) { const input = [ { ID: 1, Name: 'ԵՐԵՒԱՆ' }, { ID: 2, Name: 'Երևան' }, ]; - const arrayStartsWith = QUERY(input).filter(['Name', 'startswith', 'Երև']).toArray(); + const arrayStartsWith = QUERY(input, { + langParams: { + locale: 'hy' + } + }).filter(['Name', 'startswith', 'Երև']).toArray(); assert.equal(arrayStartsWith.length, 2); }); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/dataSource.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/dataSource.tests.js index ce297b8525bc..6cf38d965b14 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/dataSource.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/dataSource.tests.js @@ -7724,8 +7724,9 @@ QUnit.module('DataSource with diacritical marks', { assert.deepEqual(dataSource.items()[2], { id: 3, city: 'İZMİR' }, 'third item'); } else { // assert - assert.strictEqual(dataSource.items().length, 1, 'item count'); - assert.deepEqual(dataSource.items()[0], { id: 3, city: 'İZMİR' }, 'second item'); + assert.strictEqual(dataSource.items().length, 2, 'item count'); + assert.deepEqual(dataSource.items()[0], { id: 2, city: 'İzmi̇r' }, 'first item'); + assert.deepEqual(dataSource.items()[1], { id: 3, city: 'İZMİR' }, 'second item'); } });