Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export default function transformProps(chartProps: EchartsBubbleChartProps) {

data.forEach(datum => {
const dataName = bubbleSeries ? datum[bubbleSeries] : datum[entity];
const name = dataName ? String(dataName) : NULL_STRING;
const name = dataName ? String(dataName) : NULL_STRING();
const bubbleSeriesValue = bubbleSeries ? datum[bubbleSeries] : null;

series.push({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export function formatTooltip({
const parentNode =
treePathInfo.length > 2 ? treePathInfo[treePathInfo.length - 2] : undefined;

const title = (node.name || NULL_STRING)
const title = (node.name || NULL_STRING())
.toString()
.replaceAll('<', '&lt;')
.replaceAll('>', '&gt;');
Expand All @@ -144,8 +144,8 @@ export function formatTooltip({
rows.push([metricLabel, formattedValue]);
if (!colorByCategory) {
rows.push([
secondaryMetricLabel || NULL_STRING,
formattedSecondaryValue || NULL_STRING,
secondaryMetricLabel || NULL_STRING(),
formattedSecondaryValue || NULL_STRING(),
]);
rows.push([
`${metricLabel}/${secondaryMetricLabel}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export default function EchartsTreemap({
const drillToDetailFilters: BinaryQueryObjectFilterClause[] = [];
const drillByFilters: BinaryQueryObjectFilterClause[] = [];
treePath.forEach((path, i) => {
const val = path === 'null' ? NULL_STRING : path;
const val = path === 'null' ? NULL_STRING() : path;
drillToDetailFilters.push({
col: groupby[i],
op: '==',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function formatTooltip({

const isTotal = series?.seriesName === totalMark;
if (!series) {
return NULL_STRING;
return NULL_STRING();
}

const title =
Expand Down Expand Up @@ -329,7 +329,7 @@ export default function transformProps(
value = row[breakdownName];
}
if (!value) {
value = NULL_STRING;
value = NULL_STRING();
}
if (typeof value !== 'string' && typeof value !== 'number') {
value = String(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ import {
TitleFormData,
} from './types';

// eslint-disable-next-line import/prefer-default-export
export const NULL_STRING = '<NULL>';
// ATTENTION: If you change any constants, make sure to also change constants.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation Inconsistency

The comment at line 30 states 'If you change any constants, make sure to also change constants.py', but the new TRUE_STRING and FALSE_STRING constants lack Python counterparts. Either update the comment to scope it to NULL_STRING/EMPTY_STRING, or add the new constants to Python to honor the stated contract.

Code Review Run #91c55e


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them


export const EMPTY_STRING = () => t('<empty string>');
export const NULL_STRING = () => t('<NULL>');
export const TRUE_STRING = () => t('TRUE');
export const FALSE_STRING = () => t('FALSE');

export const TIMESERIES_CONSTANTS = {
gridOffsetRight: 20,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ export function extractSeries(
...datum,
[xAxis]:
datum[xAxis] === null && xAxisType === AxisType.Category
? NULL_STRING
? NULL_STRING()
: datum[xAxis],
}));
const sortedSeries = sortAndFilterSeries(
Expand Down Expand Up @@ -730,7 +730,7 @@ export function formatSeriesName(
} = {},
): string {
if (name === undefined || name === null) {
return NULL_STRING;
return NULL_STRING();
}
if (typeof name === 'boolean' || typeof name === 'bigint') {
return name.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ describe('extractSeries', () => {
]);
});

test('should convert NULL x-values to NULL_STRING for categorical axis', () => {
test('should convert NULL x-values to NULL_STRING() for categorical axis', () => {
const data = [
{
browser: 'Firefox',
Expand All @@ -585,7 +585,7 @@ describe('extractSeries', () => {
name: 'count',
data: [
['Firefox', 5],
[NULL_STRING, 10],
[NULL_STRING(), 10],
['Chrome', 8],
],
},
Expand Down Expand Up @@ -1351,7 +1351,7 @@ describe('dedupSeries', () => {

describe('sanitizeHtml', () => {
test('should remove html tags from series name', () => {
expect(sanitizeHtml(NULL_STRING)).toEqual('&lt;NULL&gt;');
expect(sanitizeHtml('<NULL>')).toEqual('&lt;NULL&gt;');
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
*/

import { renderHook } from '@testing-library/react';
import { useCellContentParser } from './useCellContentParser';
import { NULL_STRING, useCellContentParser } from './useCellContentParser';

test('should return NULL for null cell data', () => {
test('should return NULL_STRING() for null cell data', () => {
const { result } = renderHook(() =>
useCellContentParser({ columnKeys: [], expandedColumns: [] }),
);
const parser = result.current;
expect(parser({ cellData: null, columnKey: '' })).toBe('NULL');
expect(parser({ cellData: null, columnKey: '' })).toBe(NULL_STRING());
});

test('should return truncated string for complex columns', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
* under the License.
*/
import { useCallback, useMemo } from 'react';
import { t } from '@apache-superset/core/translation';

export type CellDataType = string | number | null;

export const NULL_STRING = 'NULL';
export const NULL_STRING = () => t('NULL');

type Params = {
columnKeys: string[];
Expand Down Expand Up @@ -50,7 +51,7 @@ export function useCellContentParser({ columnKeys, expandedColumns }: Params) {
columnKey: string;
}) => {
if (cellData === null) {
return NULL_STRING;
return NULL_STRING();
}
const content = String(cellData);
const firstCharacter = content.substring(0, 1);
Expand Down
2 changes: 1 addition & 1 deletion superset-frontend/src/components/FilterableTable/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const renderResultCell = ({
const cellNode =
getCellContent?.({ cellData, columnKey }) ?? String(cellData);
if (cellData === null) {
return <i className="text-muted">{NULL_STRING}</i>;
return <i className="text-muted">{NULL_STRING()}</i>;
}
const jsonObject = safeJsonObjectParse(cellData);
if (jsonObject) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { render, screen, userEvent } from 'spec/helpers/testing-library';
import CollectionControl from '.';

jest.mock('@superset-ui/chart-controls', () => ({
...jest.requireActual('@superset-ui/chart-controls'),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mock targets non-existent export

The mock targets InfoTooltip from @superset-ui/chart-controls, but this component is not exported from that module. The actual source imports InfoTooltip from @superset-ui/core/components (see ControlHeader.tsx:22). This mock will have no effect and may cause test failures.

Code suggestion
Check the AI-generated fix before applying
 --- superset-frontend/src/explore/components/controls/CollectionControl/CollectionControl.test.tsx
 +++ superset-frontend/src/explore/components/controls/CollectionControl/CollectionControl.test.tsx
 @@ -19,7 +19,7 @@ import { render, screen, userEvent } from 'spec/helpers/testing-library';
  import CollectionControl from '.';
 
  jest.mock('@superset-ui/chart-controls', () => ({
 -  ...jest.requireActual('@superset-ui/chart-controls'),
 +  ...jest.requireActual('@superset-ui/chart-controls'),
    InfoTooltip: (props: any) => (
      <button
        onClick={props.onClick}
        type="button"
        data-icon={props.icon}
        data-tooltip={props.tooltip}
      >
        {props.label}
      </button>
    ),
  }));
 
  jest.mock('@superset-ui/core/components', () => ({
    ...jest.requireActual('@superset-ui/core/components'),
    InfoTooltip: (props: any) => (
      <button
        onClick={props.onClick}
        type="button"
        data-icon={props.icon}
        data-tooltip={props.tooltip}
      >
        {props.label}
      </button>
    ),
  }));

Code Review Run #f1b1a5


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

InfoTooltip: (props: any) => (
<button
onClick={props.onClick}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
* under the License.
*/
import { cleanup } from 'spec/helpers/testing-library';
import { EMPTY_STRING, NULL_STRING } from 'src/utils/common';
import {
EMPTY_STRING,
NULL_STRING,
TRUE_STRING,
FALSE_STRING,
} from 'src/utils/common';
import { getSimpleSQLExpression } from '.';
import { Operators } from '../constants';

Expand Down Expand Up @@ -45,7 +50,7 @@ test('Should return "" if subject is falsy', () => {

test('Should return null string and empty string', () => {
expect(getSimpleSQLExpression(params.subject, Operators.In, [null, ''])).toBe(
`subject ${Operators.In} (${NULL_STRING}, ${EMPTY_STRING})`,
`subject ${Operators.In} (${NULL_STRING()}, ${EMPTY_STRING()})`,
);
});

Expand Down Expand Up @@ -73,12 +78,12 @@ test('Should return correct string when subject and operator are valid values',

test('Should handle boolean false comparator as a string value', () => {
expect(getSimpleSQLExpression(params.subject, params.operator, false)).toBe(
"subject operator 'FALSE'",
`subject operator '${FALSE_STRING()}'`,
);
});

test('Should handle boolean true comparator as a string value', () => {
expect(getSimpleSQLExpression(params.subject, params.operator, true)).toBe(
"subject operator 'TRUE'",
`subject operator '${TRUE_STRING()}'`,
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ describe('SelectFilterPlugin', () => {
const filterSelect = screen.getAllByRole('combobox')[0];
userEvent.click(filterSelect);
expect(await screen.findByRole('combobox')).toBeInTheDocument();
userEvent.click(screen.getByTitle(NULL_STRING));
userEvent.click(screen.getByTitle(NULL_STRING()));
expect(setDataMask).toHaveBeenLastCalledWith({
extraFormData: {
filters: [
Expand All @@ -291,7 +291,7 @@ describe('SelectFilterPlugin', () => {
],
},
filterState: {
label: `boy, ${NULL_STRING}`,
label: `boy, ${NULL_STRING()}`,
value: ['boy', null],
excludeFilterValues: true,
},
Expand Down Expand Up @@ -1002,7 +1002,7 @@ test('Select boolean filter with null values', async () => {
const filterSelect = screen.getByRole('combobox');
userEvent.click(filterSelect);

const nullOption = await screen.findByRole('option', { name: NULL_STRING });
const nullOption = await screen.findByRole('option', { name: NULL_STRING() });
userEvent.click(nullOption);

await waitFor(() => {
Expand Down
50 changes: 27 additions & 23 deletions superset-frontend/src/filters/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,23 +143,27 @@ describe('Filter utils', () => {
describe('getDataRecordFormatter', () => {
test('default formatter returns expected values', () => {
const formatter = getDataRecordFormatter();
expect(formatter(null, GenericDataType.String)).toEqual(NULL_STRING);
expect(formatter(null, GenericDataType.Numeric)).toEqual(NULL_STRING);
expect(formatter(null, GenericDataType.Temporal)).toEqual(NULL_STRING);
expect(formatter(null, GenericDataType.Boolean)).toEqual(NULL_STRING);
expect(formatter(null, GenericDataType.String)).toEqual(NULL_STRING());
expect(formatter(null, GenericDataType.Numeric)).toEqual(NULL_STRING());
expect(formatter(null, GenericDataType.Temporal)).toEqual(NULL_STRING());
expect(formatter(null, GenericDataType.Boolean)).toEqual(NULL_STRING());
expect(formatter('foo', GenericDataType.String)).toEqual('foo');
expect(formatter('foo', GenericDataType.Numeric)).toEqual('foo');
expect(formatter('foo', GenericDataType.Temporal)).toEqual('foo');
expect(formatter('foo', GenericDataType.Boolean)).toEqual(FALSE_STRING);
expect(formatter(true, GenericDataType.Boolean)).toEqual(TRUE_STRING);
expect(formatter(false, GenericDataType.Boolean)).toEqual(FALSE_STRING);
expect(formatter('true', GenericDataType.Boolean)).toEqual(TRUE_STRING);
expect(formatter('false', GenericDataType.Boolean)).toEqual(FALSE_STRING);
expect(formatter('TRUE', GenericDataType.Boolean)).toEqual(TRUE_STRING);
expect(formatter('FALSE', GenericDataType.Boolean)).toEqual(FALSE_STRING);
expect(formatter(0, GenericDataType.Boolean)).toEqual(FALSE_STRING);
expect(formatter(1, GenericDataType.Boolean)).toEqual(TRUE_STRING);
expect(formatter(2, GenericDataType.Boolean)).toEqual(TRUE_STRING);
expect(formatter('foo', GenericDataType.Boolean)).toEqual(FALSE_STRING());
expect(formatter(true, GenericDataType.Boolean)).toEqual(TRUE_STRING());
expect(formatter(false, GenericDataType.Boolean)).toEqual(FALSE_STRING());
expect(formatter('true', GenericDataType.Boolean)).toEqual(TRUE_STRING());
expect(formatter('false', GenericDataType.Boolean)).toEqual(
FALSE_STRING(),
);
expect(formatter('TRUE', GenericDataType.Boolean)).toEqual(TRUE_STRING());
expect(formatter('FALSE', GenericDataType.Boolean)).toEqual(
FALSE_STRING(),
);
expect(formatter(0, GenericDataType.Boolean)).toEqual(FALSE_STRING());
expect(formatter(1, GenericDataType.Boolean)).toEqual(TRUE_STRING());
expect(formatter(2, GenericDataType.Boolean)).toEqual(TRUE_STRING());
expect(formatter(0, GenericDataType.String)).toEqual('0');
expect(formatter(0, GenericDataType.Numeric)).toEqual('0');
expect(formatter(0, GenericDataType.Temporal)).toEqual('0');
Expand All @@ -173,7 +177,7 @@ describe('Filter utils', () => {
'1234567.89',
);
expect(formatter(1234567.89, GenericDataType.Boolean)).toEqual(
TRUE_STRING,
TRUE_STRING(),
);
});

Expand All @@ -182,20 +186,20 @@ describe('Filter utils', () => {
timeFormatter: getTimeFormatter(TimeFormats.DATABASE_DATETIME),
numberFormatter: getNumberFormatter(NumberFormats.SMART_NUMBER),
});
expect(formatter(null, GenericDataType.String)).toEqual(NULL_STRING);
expect(formatter(null, GenericDataType.Numeric)).toEqual(NULL_STRING);
expect(formatter(null, GenericDataType.Temporal)).toEqual(NULL_STRING);
expect(formatter(null, GenericDataType.Boolean)).toEqual(NULL_STRING);
expect(formatter(null, GenericDataType.String)).toEqual(NULL_STRING());
expect(formatter(null, GenericDataType.Numeric)).toEqual(NULL_STRING());
expect(formatter(null, GenericDataType.Temporal)).toEqual(NULL_STRING());
expect(formatter(null, GenericDataType.Boolean)).toEqual(NULL_STRING());
expect(formatter('foo', GenericDataType.String)).toEqual('foo');
expect(formatter('foo', GenericDataType.Numeric)).toEqual('foo');
expect(formatter('foo', GenericDataType.Temporal)).toEqual('foo');
expect(formatter('foo', GenericDataType.Boolean)).toEqual(FALSE_STRING);
expect(formatter('foo', GenericDataType.Boolean)).toEqual(FALSE_STRING());
expect(formatter(0, GenericDataType.String)).toEqual('0');
expect(formatter(0, GenericDataType.Numeric)).toEqual('0');
expect(formatter(0, GenericDataType.Temporal)).toEqual(
'1970-01-01 00:00:00',
);
expect(formatter(0, GenericDataType.Boolean)).toEqual(FALSE_STRING);
expect(formatter(0, GenericDataType.Boolean)).toEqual(FALSE_STRING());
expect(formatter(1234567.89, GenericDataType.String)).toEqual(
'1234567.89',
);
Expand All @@ -204,7 +208,7 @@ describe('Filter utils', () => {
'1970-01-01 00:20:34',
);
expect(formatter(1234567.89, GenericDataType.Boolean)).toEqual(
TRUE_STRING,
TRUE_STRING(),
);
expect(formatter('1970-01-01 00:00:00', GenericDataType.String)).toEqual(
'1970-01-01 00:00:00',
Expand All @@ -213,7 +217,7 @@ describe('Filter utils', () => {
'1970-01-01 00:00:00',
);
expect(formatter('1970-01-01 00:00:00', GenericDataType.Boolean)).toEqual(
FALSE_STRING,
FALSE_STRING(),
);
expect(
formatter('1970-01-01 00:00:00', GenericDataType.Temporal),
Expand Down
10 changes: 5 additions & 5 deletions superset-frontend/src/filters/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,18 +130,18 @@ export function getDataRecordFormatter({
} = {}): DataRecordValueFormatter {
return (value, dtype) => {
if (value === null || value === undefined) {
return NULL_STRING;
return NULL_STRING();
}
if (typeof value === 'boolean') {
return value ? TRUE_STRING : FALSE_STRING;
return value ? TRUE_STRING() : FALSE_STRING();
}
if (dtype === GenericDataType.Boolean) {
try {
return JSON.parse(String(value).toLowerCase())
? TRUE_STRING
: FALSE_STRING;
? TRUE_STRING()
: FALSE_STRING();
} catch {
return FALSE_STRING;
return FALSE_STRING();
}
}
if (typeof value === 'string') {
Expand Down
8 changes: 4 additions & 4 deletions superset-frontend/src/utils/common.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ describe('utils/common', () => {
test('converts values as expected', () => {
expect(optionFromValue(false)).toEqual({
value: false,
label: FALSE_STRING,
label: FALSE_STRING(),
});
expect(optionFromValue(true)).toEqual({
value: true,
label: TRUE_STRING,
label: TRUE_STRING(),
});
expect(optionFromValue(null)).toEqual({
value: NULL_STRING,
label: NULL_STRING,
value: NULL_STRING(),
label: NULL_STRING(),
});
expect(optionFromValue('')).toEqual({
value: '',
Expand Down
Loading
Loading