diff --git a/superset-frontend/src/components/Select/AsyncSelect.test.tsx b/superset-frontend/src/components/Select/AsyncSelect.test.tsx
index e5569f1be0..b11dcde017 100644
--- a/superset-frontend/src/components/Select/AsyncSelect.test.tsx
+++ b/superset-frontend/src/components/Select/AsyncSelect.test.tsx
@@ -98,6 +98,11 @@ const findSelectOption = (text: string) =>
within(getElementByClassName('.rc-virtual-list')).getByText(text),
);
+const querySelectOption = (text: string) =>
+ waitFor(() =>
+ within(getElementByClassName('.rc-virtual-list')).queryByText(text),
+ );
+
const findAllSelectOptions = () =>
waitFor(() => getElementsByClassName('.ant-select-item-option-content'));
@@ -736,6 +741,21 @@ test('renders a helper text when one is provided', async () => {
expect(screen.queryByText(helperText)).toBeInTheDocument();
});
+test('finds an element with a numeric value and does not duplicate the options', async () => {
+ const options = jest.fn(async () => ({
+ data: [
+ { label: 'a', value: 11 },
+ { label: 'b', value: 12 },
+ ],
+ totalCount: 2,
+ }));
+ render();
+ await open();
+ await type('11');
+ expect(await findSelectOption('a')).toBeInTheDocument();
+ expect(await querySelectOption('11')).not.toBeInTheDocument();
+});
+
/*
TODO: Add tests that require scroll interaction. Needs further investigation.
- Fetches more data when scrolling and more data is available
diff --git a/superset-frontend/src/components/Select/Select.test.tsx b/superset-frontend/src/components/Select/Select.test.tsx
index 0ee1f409e4..06f5f7b8e5 100644
--- a/superset-frontend/src/components/Select/Select.test.tsx
+++ b/superset-frontend/src/components/Select/Select.test.tsx
@@ -77,6 +77,11 @@ const findSelectOption = (text: string) =>
within(getElementByClassName('.rc-virtual-list')).getByText(text),
);
+const querySelectOption = (text: string) =>
+ waitFor(() =>
+ within(getElementByClassName('.rc-virtual-list')).queryByText(text),
+ );
+
const findAllSelectOptions = () =>
waitFor(() => getElementsByClassName('.ant-select-item-option-content'));
@@ -549,6 +554,18 @@ test('renders a helper text when one is provided', async () => {
expect(screen.queryByText(helperText)).toBeInTheDocument();
});
+test('finds an element with a numeric value and does not duplicate the options', async () => {
+ const options = [
+ { label: 'a', value: 11 },
+ { label: 'b', value: 12 },
+ ];
+ render();
+ await open();
+ await type('11');
+ expect(await findSelectOption('a')).toBeInTheDocument();
+ expect(await querySelectOption('11')).not.toBeInTheDocument();
+});
+
/*
TODO: Add tests that require scroll interaction. Needs further investigation.
- Fetches more data when scrolling and more data is available
diff --git a/superset-frontend/src/components/Select/utils.tsx b/superset-frontend/src/components/Select/utils.tsx
index 9916ef07e2..27a97ac8bd 100644
--- a/superset-frontend/src/components/Select/utils.tsx
+++ b/superset-frontend/src/components/Select/utils.tsx
@@ -96,20 +96,26 @@ export function getValue(
return isLabeledValue(option) ? option.value : option;
}
-type LabeledValue = { label?: ReactNode; value?: V };
+type V = string | number | null | undefined;
-export function hasOption(
+type LabeledValue = { label?: ReactNode; value?: V };
+
+export function hasOption(
value: V,
- options?: V | LabeledValue | (V | LabeledValue)[],
+ options?: V | LabeledValue | (V | LabeledValue)[],
checkLabel = false,
): boolean {
const optionsArray = ensureIsArray(options);
+ // When comparing the values we use the equality
+ // operator to automatically convert different types
return (
optionsArray.find(
x =>
- x === value ||
+ // eslint-disable-next-line eqeqeq
+ x == value ||
(isObject(x) &&
- (('value' in x && x.value === value) ||
+ // eslint-disable-next-line eqeqeq
+ (('value' in x && x.value == value) ||
(checkLabel && 'label' in x && x.label === value))),
) !== undefined
);