From 57d4729a5c1562fce32e3c9eefe7f21dfdd40c8a Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Tue, 26 Mar 2024 14:31:56 -0700 Subject: [PATCH 1/7] fix: row limits & row count labels are confusing Currently, in explore & dashboard, we usually apply a row limit on the query we issue against the database. Following this, some visualization backend code does some post-processing on data frames using pandas, typically pivoting some things, which affects the result set's row count in intricate capacities. Now from a UX standpoint the user is exposed with: - row limits in the control panels - row count in various areas of the UI where visualiztion, preview, samples and raw results are shown Currently we show the rowcount that's from row-processing. So maybe a hard limit was applied at 1000 rows on the database, but we pivot and it goes does to say 532, and we show the user that we haven't hit the limit when we actually did. Also note that the component that shows rowcount is supposed to turn red if limit is hit, letting the user know they are looking at truncated data. --- superset-frontend/package-lock.json | 1 + .../src/query/types/QueryResponse.ts | 1 + .../plugin-chart-table/test/testData.ts | 1 + .../Chart/DrillBy/useResultsTableView.tsx | 2 ++ .../src/explore/components/ChartPills.tsx | 2 +- .../DataTableControl/RowCount.test.tsx | 36 ------------------- .../components/DataTableControl/index.tsx | 9 ----- .../components/DataTableControls.tsx | 5 +-- .../DataTablesPane/components/SamplesPane.tsx | 4 +++ .../components/SingleQueryResultPane.tsx | 2 ++ .../components/useResultsPane.tsx | 3 +- .../test/DataTablesPane.test.tsx | 13 +++++-- .../test/ResultsPaneOnDashboard.test.tsx | 4 +++ .../DataTablesPane/test/SamplesPane.test.tsx | 2 ++ .../components/DataTablesPane/types.ts | 2 ++ .../RowCountLabel/RowCountLabel.test.tsx | 2 +- .../components/RowCountLabel/index.tsx | 10 ++++-- superset/common/query_actions.py | 2 ++ superset/common/query_context_processor.py | 1 + superset/common/utils/query_cache_manager.py | 5 +++ superset/models/helpers.py | 1 + superset/views/core.py | 2 ++ superset/viz.py | 2 ++ 23 files changed, 57 insertions(+), 55 deletions(-) delete mode 100644 superset-frontend/src/explore/components/DataTableControl/RowCount.test.tsx diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 90ce4b0a7179c..597a05d566502 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -69231,6 +69231,7 @@ "peerDependencies": { "@superset-ui/chart-controls": "*", "@superset-ui/core": "*", + "memoize-one": "*", "react": "^16.13.1" } }, diff --git a/superset-frontend/packages/superset-ui-core/src/query/types/QueryResponse.ts b/superset-frontend/packages/superset-ui-core/src/query/types/QueryResponse.ts index 1705814df11e3..93c7475d42e11 100644 --- a/superset-frontend/packages/superset-ui-core/src/query/types/QueryResponse.ts +++ b/superset-frontend/packages/superset-ui-core/src/query/types/QueryResponse.ts @@ -67,6 +67,7 @@ export interface ChartDataResponseResult { is_cached: boolean; query: string; rowcount: number; + sql_rowcount: number; stacktrace: string | null; status: | 'stopped' diff --git a/superset-frontend/plugins/plugin-chart-table/test/testData.ts b/superset-frontend/plugins/plugin-chart-table/test/testData.ts index 24abc3381e49f..6c76e865e801a 100644 --- a/superset-frontend/plugins/plugin-chart-table/test/testData.ts +++ b/superset-frontend/plugins/plugin-chart-table/test/testData.ts @@ -80,6 +80,7 @@ const basicQueryResult: ChartDataResponseResult = { is_cached: false, query: 'SELECT ...', rowcount: 100, + sql_rowcount: 100, stacktrace: null, status: 'success', from_dttm: null, diff --git a/superset-frontend/src/components/Chart/DrillBy/useResultsTableView.tsx b/superset-frontend/src/components/Chart/DrillBy/useResultsTableView.tsx index b424b95ea558e..bab24fdd479a7 100644 --- a/superset-frontend/src/components/Chart/DrillBy/useResultsTableView.tsx +++ b/superset-frontend/src/components/Chart/DrillBy/useResultsTableView.tsx @@ -44,6 +44,7 @@ export const useResultsTableView = ( {!isLoading && firstQueryResponse && ( )} diff --git a/superset-frontend/src/explore/components/DataTableControl/RowCount.test.tsx b/superset-frontend/src/explore/components/DataTableControl/RowCount.test.tsx deleted file mode 100644 index 6ebbcef77b3f7..0000000000000 --- a/superset-frontend/src/explore/components/DataTableControl/RowCount.test.tsx +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import React from 'react'; -import { render, screen } from 'spec/helpers/testing-library'; -import { RowCount } from '.'; - -test('Render a RowCount with a single row', () => { - render(); - expect(screen.getByText('1 row')).toBeInTheDocument(); -}); - -test('Render a RowCount with multiple rows', () => { - render(); - expect(screen.getByText('3 rows')).toBeInTheDocument(); -}); - -test('Render a RowCount on loading', () => { - render(); - expect(screen.getByText('Loading...')).toBeInTheDocument(); -}); diff --git a/superset-frontend/src/explore/components/DataTableControl/index.tsx b/superset-frontend/src/explore/components/DataTableControl/index.tsx index 8dc4b1d0140d8..60ca470e4a0db 100644 --- a/superset-frontend/src/explore/components/DataTableControl/index.tsx +++ b/superset-frontend/src/explore/components/DataTableControl/index.tsx @@ -44,7 +44,6 @@ import Button from 'src/components/Button'; import Popover from 'src/components/Popover'; import { prepareCopyToClipboardTabularData } from 'src/utils/common'; import CopyToClipboard from 'src/components/CopyToClipboard'; -import RowCountLabel from 'src/explore/components/RowCountLabel'; import { getTimeColumns, setTimeColumns } from './utils'; export const CellNull = styled('span')` @@ -118,14 +117,6 @@ export const FilterInput = ({ ); }; -export const RowCount = ({ - data, - loading, -}: { - data?: Record[]; - loading: boolean; -}) => ; - enum FormatPickerValue { Formatted = 'formatted', Original = 'original', diff --git a/superset-frontend/src/explore/components/DataTablesPane/components/DataTableControls.tsx b/superset-frontend/src/explore/components/DataTablesPane/components/DataTableControls.tsx index 7a02114a2f52b..b1ff73e29e5da 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/components/DataTableControls.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/components/DataTableControls.tsx @@ -22,10 +22,10 @@ import { css, GenericDataType, styled } from '@superset-ui/core'; import { CopyToClipboardButton, FilterInput, - RowCount, } from 'src/explore/components/DataTableControl'; import { applyFormattingToTabularData } from 'src/utils/common'; import { getTimeColumns } from 'src/explore/components/DataTableControl/utils'; +import RowCountLabel from 'src/explore/components/RowCountLabel'; import { TableControlsProps } from '../types'; export const TableControlsWrapper = styled.div` @@ -47,6 +47,7 @@ export const TableControls = ({ onInputChange, columnNames, columnTypes, + rowcount, isLoading, }: TableControlsProps) => { const originalTimeColumns = getTimeColumns(datasourceId); @@ -74,7 +75,7 @@ export const TableControls = ({ align-items: center; `} > - + diff --git a/superset-frontend/src/explore/components/DataTablesPane/components/SamplesPane.tsx b/superset-frontend/src/explore/components/DataTablesPane/components/SamplesPane.tsx index b542aad99643a..eaae35bd2fa56 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/components/SamplesPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/components/SamplesPane.tsx @@ -48,6 +48,7 @@ export const SamplesPane = ({ const [colnames, setColnames] = useState([]); const [coltypes, setColtypes] = useState([]); const [isLoading, setIsLoading] = useState(false); + const [rowcount, setRowCount] = useState(0); const [responseError, setResponseError] = useState(''); const datasourceId = useMemo( () => `${datasource.id}__${datasource.type}`, @@ -66,6 +67,7 @@ export const SamplesPane = ({ setData(ensureIsArray(response.data)); setColnames(ensureIsArray(response.colnames)); setColtypes(ensureIsArray(response.coltypes)); + setRowCount(response.rowcount); setResponseError(''); cache.add(datasource); if (queryForce && actions) { @@ -108,6 +110,7 @@ export const SamplesPane = ({ data={filteredData} columnNames={colnames} columnTypes={coltypes} + rowcount={rowcount} datasourceId={datasourceId} onInputChange={input => setFilterText(input)} isLoading={isLoading} @@ -128,6 +131,7 @@ export const SamplesPane = ({ data={filteredData} columnNames={colnames} columnTypes={coltypes} + rowcount={rowcount} datasourceId={datasourceId} onInputChange={input => setFilterText(input)} isLoading={isLoading} diff --git a/superset-frontend/src/explore/components/DataTablesPane/components/SingleQueryResultPane.tsx b/superset-frontend/src/explore/components/DataTablesPane/components/SingleQueryResultPane.tsx index c2614dfda6ca6..b543167840442 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/components/SingleQueryResultPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/components/SingleQueryResultPane.tsx @@ -30,6 +30,7 @@ export const SingleQueryResultPane = ({ data, colnames, coltypes, + rowcount, datasourceId, dataSize = 50, isVisible, @@ -55,6 +56,7 @@ export const SingleQueryResultPane = ({ data={filteredData} columnNames={colnames} columnTypes={coltypes} + rowcount={rowcount} datasourceId={datasourceId} onInputChange={input => setFilterText(input)} isLoading={false} diff --git a/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx b/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx index 9b6b597c7900f..bae6b6fd7b32a 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx @@ -119,6 +119,7 @@ export const useResultsPane = ({ data={[]} columnNames={[]} columnTypes={[]} + rowcount={0} datasourceId={queryFormData.datasource} onInputChange={() => {}} isLoading={false} @@ -135,7 +136,6 @@ export const useResultsPane = ({ , ); } - return resultResp .slice(0, queryCount) .map((result, idx) => ( @@ -143,6 +143,7 @@ export const useResultsPane = ({ data={result.data} colnames={result.colnames} coltypes={result.coltypes} + rowcount={result.rowcount} dataSize={dataSize} datasourceId={queryFormData.datasource} key={idx} diff --git a/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx b/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx index 74358af959e11..901e571d0e4df 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx @@ -93,6 +93,8 @@ describe('DataTablesPane', () => { data: [{ __timestamp: 1230768000000, genre: 'Action' }], colnames: ['__timestamp', 'genre'], coltypes: [2, 1], + rowcount: 1, + sql_rowcount: 1, }, ], }, @@ -103,7 +105,9 @@ describe('DataTablesPane', () => { useRedux: true, }); userEvent.click(screen.getByText('Results')); - expect(await screen.findByText('1 row')).toBeVisible(); + expect( + screen.container.querySelector('.row-count-label'), + ).toHaveTextContent('1 row'); userEvent.click(screen.getByLabelText('Copy')); expect(copyToClipboardSpy).toHaveBeenCalledTimes(1); @@ -125,6 +129,8 @@ describe('DataTablesPane', () => { ], colnames: ['__timestamp', 'genre'], coltypes: [2, 1], + rowcount: 2, + sql_rowcount: 2, }, ], }, @@ -134,7 +140,10 @@ describe('DataTablesPane', () => { useRedux: true, }); userEvent.click(screen.getByText('Results')); - expect(await screen.findByText('2 rows')).toBeVisible(); + expect( + screen.container.querySelector('.row-count-label'), + ).toHaveTextContent('2 rows'); + expect(screen.getByText('Action')).toBeVisible(); expect(screen.getByText('Horror')).toBeVisible(); diff --git a/superset-frontend/src/explore/components/DataTablesPane/test/ResultsPaneOnDashboard.test.tsx b/superset-frontend/src/explore/components/DataTablesPane/test/ResultsPaneOnDashboard.test.tsx index 839126bb62530..a6f9830d2e174 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/test/ResultsPaneOnDashboard.test.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/test/ResultsPaneOnDashboard.test.tsx @@ -50,6 +50,8 @@ describe('ResultsPaneOnDashboard', () => { ], colnames: ['__timestamp', 'genre'], coltypes: [2, 1], + rowcount: 2, + sql_rowcount: 2, }, ], }, @@ -78,6 +80,8 @@ describe('ResultsPaneOnDashboard', () => { data: [{ genre: 'Action' }, { genre: 'Horror' }], colnames: ['genre'], coltypes: [1], + rowcount: 2, + sql_rowcount: 2, }, ], }, diff --git a/superset-frontend/src/explore/components/DataTablesPane/test/SamplesPane.test.tsx b/superset-frontend/src/explore/components/DataTablesPane/test/SamplesPane.test.tsx index eed6e84808b73..02c421aeec8de 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/test/SamplesPane.test.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/test/SamplesPane.test.tsx @@ -50,6 +50,8 @@ describe('SamplesPane', () => { ], colnames: ['__timestamp', 'genre'], coltypes: [2, 1], + rowcount: 2, + sql_rowcount: 2, }, }, ); diff --git a/superset-frontend/src/explore/components/DataTablesPane/types.ts b/superset-frontend/src/explore/components/DataTablesPane/types.ts index 4e6062ba4a256..4939b7d7488c6 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/types.ts +++ b/superset-frontend/src/explore/components/DataTablesPane/types.ts @@ -71,11 +71,13 @@ export interface TableControlsProps { columnNames: string[]; columnTypes: GenericDataType[]; isLoading: boolean; + rowcount: number; } export interface QueryResultInterface { colnames: string[]; coltypes: GenericDataType[]; + rowcount: number; data: Record[][]; } diff --git a/superset-frontend/src/explore/components/RowCountLabel/RowCountLabel.test.tsx b/superset-frontend/src/explore/components/RowCountLabel/RowCountLabel.test.tsx index 2e7a44c15e159..8e3e3b0c1d7b4 100644 --- a/superset-frontend/src/explore/components/RowCountLabel/RowCountLabel.test.tsx +++ b/superset-frontend/src/explore/components/RowCountLabel/RowCountLabel.test.tsx @@ -52,7 +52,7 @@ test('RowCountLabel renders limit with danger and tooltip', async () => { expect(screen.getByText(expectedText)).toBeInTheDocument(); userEvent.hover(screen.getByText(expectedText)); const tooltip = await screen.findByRole('tooltip'); - expect(tooltip).toHaveTextContent('Limit reached'); + expect(tooltip).toHaveTextContent('The row limit'); expect(tooltip).toHaveStyle('background: rgba(0, 0, 0, 0.902);'); }); diff --git a/superset-frontend/src/explore/components/RowCountLabel/index.tsx b/superset-frontend/src/explore/components/RowCountLabel/index.tsx index be41be0ba67de..80fc362959469 100644 --- a/superset-frontend/src/explore/components/RowCountLabel/index.tsx +++ b/superset-frontend/src/explore/components/RowCountLabel/index.tsx @@ -28,9 +28,13 @@ type RowCountLabelProps = { loading?: boolean; }; +const limitReachedMsg = t( + 'The row limit set for the chart was reached. The chart may show partial data.', +); + export default function RowCountLabel(props: RowCountLabelProps) { - const { rowcount = 0, limit, loading } = props; - const limitReached = rowcount === limit; + const { rowcount = 0, limit = null, loading } = props; + const limitReached = limit && rowcount >= limit; const type = limitReached || (rowcount === 0 && !loading) ? 'danger' : 'default'; const formattedRowCount = getNumberFormatter()(rowcount); @@ -46,7 +50,7 @@ export default function RowCountLabel(props: RowCountLabelProps) { ); return limitReached ? ( - {t('Limit reached')}}> + {limitReachedMsg}}> {label} ) : ( diff --git a/superset/common/query_actions.py b/superset/common/query_actions.py index d73a99d0271c1..bdbccc78dbe2c 100644 --- a/superset/common/query_actions.py +++ b/superset/common/query_actions.py @@ -135,6 +135,8 @@ def _get_full( "data": payload.get("data"), "colnames": payload.get("colnames"), "coltypes": payload.get("coltypes"), + "rowcount": payload.get("rowcount"), + "sql_rowcount": payload.get("sql_rowcount"), } return payload diff --git a/superset/common/query_context_processor.py b/superset/common/query_context_processor.py index d8b5bea4bb729..f003f8ed30c2e 100644 --- a/superset/common/query_context_processor.py +++ b/superset/common/query_context_processor.py @@ -194,6 +194,7 @@ def get_df_payload( "status": cache.status, "stacktrace": cache.stacktrace, "rowcount": len(cache.df.index), + "sql_rowcount": cache.sql_rowcount, "from_dttm": query_obj.from_dttm, "to_dttm": query_obj.to_dttm, "label_map": label_map, diff --git a/superset/common/utils/query_cache_manager.py b/superset/common/utils/query_cache_manager.py index a0fb65b20d4cb..d2e6e07437726 100644 --- a/superset/common/utils/query_cache_manager.py +++ b/superset/common/utils/query_cache_manager.py @@ -64,6 +64,7 @@ def __init__( is_cached: bool | None = None, cache_dttm: str | None = None, cache_value: dict[str, Any] | None = None, + sql_rowcount: int | None = None, ) -> None: self.df = df self.query = query @@ -79,6 +80,7 @@ def __init__( self.is_cached = is_cached self.cache_dttm = cache_dttm self.cache_value = cache_value + self.sql_rowcount = sql_rowcount # pylint: disable=too-many-arguments def set_query_result( @@ -102,6 +104,7 @@ def set_query_result( self.rejected_filter_columns = query_result.rejected_filter_columns self.error_message = query_result.error_message self.df = query_result.df + self.sql_rowcount = query_result.sql_rowcount self.annotation_data = {} if annotation_data is None else annotation_data if self.status != QueryStatus.FAILED: @@ -117,6 +120,7 @@ def set_query_result( "applied_filter_columns": self.applied_filter_columns, "rejected_filter_columns": self.rejected_filter_columns, "annotation_data": self.annotation_data, + "sql_rowcount": self.sql_rowcount, } if self.is_loaded and key and self.status != QueryStatus.FAILED: self.set( @@ -167,6 +171,7 @@ def get( query_cache.status = QueryStatus.SUCCESS query_cache.is_loaded = True query_cache.is_cached = cache_value is not None + query_cache.sql_rowcount = cache_value.get("sql_rowcount", None) query_cache.cache_dttm = ( cache_value["dttm"] if cache_value is not None else None ) diff --git a/superset/models/helpers.py b/superset/models/helpers.py index 450def33b2c15..4b2287390357f 100644 --- a/superset/models/helpers.py +++ b/superset/models/helpers.py @@ -584,6 +584,7 @@ def __init__( # pylint: disable=too-many-arguments self.errors = errors or [] self.from_dttm = from_dttm self.to_dttm = to_dttm + self.sql_rowcount = len(self.df.index) if not self.df.empty else 0 class ExtraJSONMixin: diff --git a/superset/views/core.py b/superset/views/core.py index 4faede0f3450c..287f71e5486c2 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -167,6 +167,8 @@ def get_raw_results(self, viz_obj: BaseViz) -> FlaskResponse: "data": payload["df"].to_dict("records"), "colnames": payload.get("colnames"), "coltypes": payload.get("coltypes"), + "rowcount": payload.get("rowcount"), + "sql_rowcount": payload.get("sql_rowcount"), }, ) diff --git a/superset/viz.py b/superset/viz.py index 7c78f84228fae..447b36d53d985 100644 --- a/superset/viz.py +++ b/superset/viz.py @@ -262,6 +262,8 @@ def get_samples(self) -> dict[str, Any]: "data": payload["df"].to_dict(orient="records"), "colnames": payload.get("colnames"), "coltypes": payload.get("coltypes"), + "rowcount": payload.get("rowcount"), + "sql_rowcount": payload.get("sql_rowcount"), } @deprecated(deprecated_in="3.0") From d19d9bfca85e1aea4bce456ac332f8f812c44b3d Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Thu, 28 Mar 2024 17:31:49 -0700 Subject: [PATCH 2/7] fix tsc --- .../DataTablesPane/test/DataTablesPane.test.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx b/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx index 901e571d0e4df..e6c53cd7a3abe 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx @@ -105,9 +105,7 @@ describe('DataTablesPane', () => { useRedux: true, }); userEvent.click(screen.getByText('Results')); - expect( - screen.container.querySelector('.row-count-label'), - ).toHaveTextContent('1 row'); + expect(await screen.findByText('1 row')).toBeVisible(); userEvent.click(screen.getByLabelText('Copy')); expect(copyToClipboardSpy).toHaveBeenCalledTimes(1); @@ -140,9 +138,7 @@ describe('DataTablesPane', () => { useRedux: true, }); userEvent.click(screen.getByText('Results')); - expect( - screen.container.querySelector('.row-count-label'), - ).toHaveTextContent('2 rows'); + expect(await screen.findByText('1 row')).toBeVisible(); expect(screen.getByText('Action')).toBeVisible(); expect(screen.getByText('Horror')).toBeVisible(); From c99cd015928f481fd33a0bfb925b89cf7e7959f1 Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Fri, 29 Mar 2024 09:17:50 -0700 Subject: [PATCH 3/7] fix unit test --- .../components/DataTablesPane/test/DataTablesPane.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx b/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx index e6c53cd7a3abe..40370638e51e4 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/test/DataTablesPane.test.tsx @@ -138,7 +138,7 @@ describe('DataTablesPane', () => { useRedux: true, }); userEvent.click(screen.getByText('Results')); - expect(await screen.findByText('1 row')).toBeVisible(); + expect(await screen.findByText('2 rows')).toBeVisible(); expect(screen.getByText('Action')).toBeVisible(); expect(screen.getByText('Horror')).toBeVisible(); From ce9c85778185e72c0c144af85b522fd7d0eaa231 Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Thu, 28 Mar 2024 17:16:35 -0700 Subject: [PATCH 4/7] flaky test --- tests/integration_tests/charts/data/api_tests.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/integration_tests/charts/data/api_tests.py b/tests/integration_tests/charts/data/api_tests.py index 58c11b0cea37c..a84328bf34abd 100644 --- a/tests/integration_tests/charts/data/api_tests.py +++ b/tests/integration_tests/charts/data/api_tests.py @@ -21,6 +21,7 @@ import copy from datetime import datetime from io import BytesIO +import time from typing import Any, Optional from unittest import mock from zipfile import ZipFile @@ -718,6 +719,9 @@ def test_chart_data_async(self): app._got_first_request = False async_query_manager_factory.init_app(app) self.login("admin") + # fighting a weird race condition only my mysql in the test matrix where we get + # a 200 instead of a 202 + time.sleep(0.5) rv = self.post_assert_metric(CHART_DATA_URI, self.query_context_payload, "data") self.assertEqual(rv.status_code, 202) data = json.loads(rv.data.decode("utf-8")) From c161cfe9ae8b9e0d23045c1df3ab9970be536d72 Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Fri, 29 Mar 2024 12:18:08 -0700 Subject: [PATCH 5/7] rebasoing --- superset-frontend/package-lock.json | 1 - 1 file changed, 1 deletion(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 597a05d566502..90ce4b0a7179c 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -69231,7 +69231,6 @@ "peerDependencies": { "@superset-ui/chart-controls": "*", "@superset-ui/core": "*", - "memoize-one": "*", "react": "^16.13.1" } }, From d4a259831b33bab088acb3ba800edda40ad84d84 Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Fri, 29 Mar 2024 12:19:20 -0700 Subject: [PATCH 6/7] remove bad flaky fix --- tests/integration_tests/charts/data/api_tests.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/integration_tests/charts/data/api_tests.py b/tests/integration_tests/charts/data/api_tests.py index a84328bf34abd..58c11b0cea37c 100644 --- a/tests/integration_tests/charts/data/api_tests.py +++ b/tests/integration_tests/charts/data/api_tests.py @@ -21,7 +21,6 @@ import copy from datetime import datetime from io import BytesIO -import time from typing import Any, Optional from unittest import mock from zipfile import ZipFile @@ -719,9 +718,6 @@ def test_chart_data_async(self): app._got_first_request = False async_query_manager_factory.init_app(app) self.login("admin") - # fighting a weird race condition only my mysql in the test matrix where we get - # a 200 instead of a 202 - time.sleep(0.5) rv = self.post_assert_metric(CHART_DATA_URI, self.query_context_payload, "data") self.assertEqual(rv.status_code, 202) data = json.loads(rv.data.decode("utf-8")) From 40e243de9c39fef257ddcae55251594c6bf9a8ce Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Tue, 2 Apr 2024 12:55:49 -0700 Subject: [PATCH 7/7] no-op --- .github/workflows/no-op.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/no-op.yml b/.github/workflows/no-op.yml index 2dbd82eb384d5..9cc9e8bec3376 100644 --- a/.github/workflows/no-op.yml +++ b/.github/workflows/no-op.yml @@ -45,7 +45,7 @@ jobs: python-lint: strategy: matrix: - python-version: ["3.9"] + python-version: ["3.9", "3.10"] runs-on: ubuntu-latest steps: - name: No-op for python-lint @@ -55,7 +55,7 @@ jobs: test-postgres-hive: strategy: matrix: - python-version: ["3.9"] + python-version: ["3.9", "3.10"] runs-on: ubuntu-latest steps: - name: No-op for frontend-build @@ -65,7 +65,7 @@ jobs: test-postgres-presto: strategy: matrix: - python-version: ["3.9"] + python-version: ["3.9", "3.10"] runs-on: ubuntu-latest steps: - name: No-op for frontend-build @@ -75,7 +75,7 @@ jobs: unit-tests: strategy: matrix: - python-version: ["3.9"] + python-version: ["3.9", "3.10"] runs-on: ubuntu-latest steps: - name: No-op for frontend-build