From 1b8df94318a02dd1eb23d97468f1bb689743a544 Mon Sep 17 00:00:00 2001 From: Irina Kuzmina Date: Thu, 26 Dec 2024 16:51:15 +0300 Subject: [PATCH] Fix table null sorting --- .../Table/renderer/components/Table/utils.ts | 11 +++- .../visualizations/flat-table/sorting.test.ts | 61 +++++++++++++++++++ 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/src/ui/libs/DatalensChartkit/ChartKit/plugins/Table/renderer/components/Table/utils.ts b/src/ui/libs/DatalensChartkit/ChartKit/plugins/Table/renderer/components/Table/utils.ts index 1db53c7b99..c8bfe40808 100644 --- a/src/ui/libs/DatalensChartkit/ChartKit/plugins/Table/renderer/components/Table/utils.ts +++ b/src/ui/libs/DatalensChartkit/ChartKit/plugins/Table/renderer/components/Table/utils.ts @@ -57,18 +57,23 @@ function getSortingFunction(args: { } return function (row1, row2) { - const a = getSortAccessor(row1.original[columnIndex].value); - const b = getSortAccessor(row2.original[columnIndex].value); + const nullReplacement = columnType === 'number' ? -Infinity : ''; + const a = getSortAccessor(row1.original[columnIndex].value, nullReplacement); + const b = getSortAccessor(row2.original[columnIndex].value, nullReplacement); return ascending(a as Primitive, b as Primitive); }; } -function getSortAccessor(value: unknown) { +function getSortAccessor(value: unknown, nullReplacement?: Primitive) { if (isMarkupItem(value)) { return markupToRawString(value); } + if (value === null && typeof nullReplacement !== 'undefined') { + return nullReplacement; + } + return value as Primitive; } diff --git a/tests/opensource-suites/wizard/visualizations/flat-table/sorting.test.ts b/tests/opensource-suites/wizard/visualizations/flat-table/sorting.test.ts index bdc8c6a617..0dbbe5e990 100644 --- a/tests/opensource-suites/wizard/visualizations/flat-table/sorting.test.ts +++ b/tests/opensource-suites/wizard/visualizations/flat-table/sorting.test.ts @@ -163,5 +163,66 @@ datalensTest.describe('Wizard', () => { ]; expect(await wizardPage.chartkit.getRowsTexts()).toEqual(expectedOrder); }); + + datalensTest('Sorting numbers with null values', async ({page}) => { + const wizardPage = new WizardPage({page}); + const chartContainer = page.locator(slct(WizardPageQa.SectionPreview)); + const previewLoader = chartContainer.locator(slct(ChartKitQa.Loader)); + + await wizardPage.createNewFieldWithFormula('year', 'year([Order_date])'); + await wizardPage.sectionVisualization.addFieldByClick(PlaceholderName.Filters, 'year'); + await wizardPage.filterEditor.selectFilterOperation(Operations.EQ); + await wizardPage.filterEditor.setInputValue('2015'); + await wizardPage.filterEditor.apply(); + + await wizardPage.createNewFieldWithFormula('month', 'datepart([Order_date], "month")'); + await wizardPage.createNewFieldWithFormula( + 'with_null', + 'if([month] = 2) then null else [month] end', + ); + await wizardPage.sectionVisualization.addFieldByClick( + PlaceholderName.FlatTableColumns, + 'month', + ); + await wizardPage.sectionVisualization.addFieldByClick( + PlaceholderName.FlatTableColumns, + 'with_null', + ); + await expect(previewLoader).not.toBeVisible(); + + const initialOrder = [ + ['1', '1'], + ['2', 'null'], + ['3', '3'], + ['4', '4'], + ['5', '5'], + ['6', '6'], + ['7', '7'], + ['8', '8'], + ['9', '9'], + ['10', '10'], + ['11', '11'], + ['12', '12'], + ]; + expect(await wizardPage.chartkit.getRowsTexts()).toEqual(initialOrder); + + // Sort values by clicking on header + await chartContainer.locator('thead', {hasText: 'with_null'}).first().click(); + const expectedOrder = [ + ['12', '12'], + ['11', '11'], + ['10', '10'], + ['9', '9'], + ['8', '8'], + ['7', '7'], + ['6', '6'], + ['5', '5'], + ['4', '4'], + ['3', '3'], + ['1', '1'], + ['2', 'null'], + ]; + expect(await wizardPage.chartkit.getRowsTexts()).toEqual(expectedOrder); + }); }); });