From 40952c7fdf61da5ef42b32919e30ec15721dfa38 Mon Sep 17 00:00:00 2001 From: Ruslan Farkhutdinov Date: Tue, 14 Apr 2026 14:14:22 +0300 Subject: [PATCH 1/3] Lookup: Normalize Unicode form before string comparison to support NFD input (T1326069) --- .../js/__internal/core/utils/m_data.ts | 1 + .../lookup.tests.js | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/packages/devextreme/js/__internal/core/utils/m_data.ts b/packages/devextreme/js/__internal/core/utils/m_data.ts index 52a70b038e39..9c1dce560ef6 100644 --- a/packages/devextreme/js/__internal/core/utils/m_data.ts +++ b/packages/devextreme/js/__internal/core/utils/m_data.ts @@ -215,6 +215,7 @@ export const toComparable = function (value, caseSensitive?, options: any = {}) const isCaseSensitive = caseSensitive || collatorSensitivity === 'case' || collatorSensitivity === 'variant'; if (typeof value === 'string' && !isCaseSensitive) { + value = value.normalize('NFC'); const locale = options?.locale?.toLowerCase(); const useUpperCase = locale && !!['hy', 'el'].find((code) => locale === code || locale.startsWith(`${code}-`)); diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/lookup.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/lookup.tests.js index 1d30b961026d..1d94612286f7 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/lookup.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/lookup.tests.js @@ -3379,6 +3379,35 @@ QUnit.module('dataSource integration', { this.clock.tick(loadDelay / 2); assert.ok($loadPanel.is(':hidden'), 'load panel is not visible if value length less than minSearchLength)'); }); + + QUnit.test('search should find items when search value is in NFD Unicode form and items are in NFC form (T1326069)', function(assert) { + const NFC_CHAR = '\u1EC7'; // precomposed form (NFC) + const itemsNFC = [ + `test item 1 h${NFC_CHAR}`, + `test item 2 H${NFC_CHAR}`, + 'test item 3', + ]; + + const instance = this.$element.dxLookup({ + dataSource: itemsNFC, + searchEnabled: true, + searchTimeout: 0, + opened: true + }).dxLookup('instance'); + + const $content = $(instance.content()); + const $input = $content.find(`.${LOOKUP_SEARCH_CLASS} .${TEXTEDITOR_INPUT_CLASS}`); + + const searchValueNFD = 'h\u0065\u0323\u0302'; + + assert.notStrictEqual(searchValueNFD, searchValueNFD.normalize('NFC'), + 'NFD and NFC forms are different strings'); + + $($input.val(searchValueNFD)).trigger('input'); + + const $listItems = $(`.${LIST_ITEM_CLASS}`); + assert.equal($listItems.length, 2, 'items containing the NFC character should be found when searching with its NFD equivalent'); + }); }); From ab9772220b3074f95a7e345f9059a5836cbf1ac8 Mon Sep 17 00:00:00 2001 From: Ruslan Farkhutdinov Date: Tue, 14 Apr 2026 14:21:23 +0300 Subject: [PATCH 2/3] Add this.clock.tick(0) to the test Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Ruslan Farkhutdinov --- .../testing/tests/DevExpress.ui.widgets.editors/lookup.tests.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/lookup.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/lookup.tests.js index 1d94612286f7..af5b3b0e8a8b 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/lookup.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/lookup.tests.js @@ -3404,6 +3404,7 @@ QUnit.module('dataSource integration', { 'NFD and NFC forms are different strings'); $($input.val(searchValueNFD)).trigger('input'); + this.clock.tick(0); const $listItems = $(`.${LIST_ITEM_CLASS}`); assert.equal($listItems.length, 2, 'items containing the NFC character should be found when searching with its NFD equivalent'); From c23828d094491d046717d8aad236cb970fc042c7 Mon Sep 17 00:00:00 2001 From: Ruslan Farkhutdinov Date: Tue, 14 Apr 2026 14:32:09 +0300 Subject: [PATCH 3/3] Update $listItems selector Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Ruslan Farkhutdinov --- .../testing/tests/DevExpress.ui.widgets.editors/lookup.tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/lookup.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/lookup.tests.js index af5b3b0e8a8b..abf7ec47cc4a 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/lookup.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/lookup.tests.js @@ -3406,7 +3406,7 @@ QUnit.module('dataSource integration', { $($input.val(searchValueNFD)).trigger('input'); this.clock.tick(0); - const $listItems = $(`.${LIST_ITEM_CLASS}`); + const $listItems = $content.find(`.${LIST_ITEM_CLASS}`); assert.equal($listItems.length, 2, 'items containing the NFC character should be found when searching with its NFD equivalent'); }); });