Skip to content
Snippets Groups Projects
Unverified Commit a8d873a7 authored by Mahatthana (Kelvin) Nomsawadi's avatar Mahatthana (Kelvin) Nomsawadi Committed by GitHub
Browse files

Add tests to ensure we can't add empty dashboard filter (#32632)

* Move a component into its own directory so we could add tests

* Delete unused CSS rules so it's easier to migrate

* Migrate to emotion

* Add integration test

* Remove commented out code

* Add additional test for parameters with connected field
parent f69f377b
Branches
Tags
No related merge requests found
:local(.container) {
composes: flex align-center from "style";
transition: opacity 500ms linear;
border: 2px solid var(--color-border);
margin: 0.5em 0;
padding: 0.25em 1em;
width: 100%;
}
:local(.container) legend {
text-transform: none;
position: relative;
height: 2px;
line-height: 0;
margin-left: -0.45em;
padding: 0 0.5em;
}
:local(.container.deemphasized) {
opacity: 0.4;
}
:local(.container.deemphasized:hover) {
opacity: 1;
}
:local(.parameter) {
composes: flex align-center from "style";
font-weight: 600;
......@@ -147,11 +122,6 @@
}
@media screen and (min-width: 440px) {
:local(.container) {
margin-right: 0.85em;
width: auto;
}
:local(.parameter.noPopover) input {
/* NOTE: Fixed with to circumvent issues with flexbox with container having a min-width */
width: 115px;
......
......@@ -33,7 +33,7 @@ import {
} from "metabase-lib/parameters/utils/parameter-type";
import ParameterFieldWidget from "./widgets/ParameterFieldWidget/ParameterFieldWidget";
import S from "./ParameterWidget.css";
import S from "./ParameterValueWidget.css";
const DATE_WIDGETS = {
"date/single": DateSingleWidget,
......
......@@ -4,12 +4,11 @@ import PropTypes from "prop-types";
import cx from "classnames";
import { Icon } from "metabase/core/components/Icon";
import { color } from "metabase/lib/colors";
import FieldSet from "../../components/FieldSet";
import ParameterValueWidget from "./ParameterValueWidget";
import ParameterValueWidget from "../ParameterValueWidget";
import S from "./ParameterWidget.css";
import { StyledFieldSet } from "./ParameterWidget.styled";
export default class ParameterWidget extends Component {
export class ParameterWidget extends Component {
state = {
isEditingName: false,
editingNameValue: undefined,
......@@ -82,10 +81,10 @@ export default class ParameterWidget extends Component {
const legend = fieldHasValueOrFocus ? parameter.name : "";
return (
<FieldSet
<StyledFieldSet
legend={legend}
noPadding={true}
className={cx(className, S.container, {
className={cx(className, {
"border-brand": fieldHasValueOrFocus,
})}
>
......@@ -96,7 +95,7 @@ export default class ParameterWidget extends Component {
isFullscreen,
)}
{children}
</FieldSet>
</StyledFieldSet>
);
};
......
import styled from "@emotion/styled";
import FieldSet from "metabase/components/FieldSet";
import { color } from "metabase/lib/colors";
export const StyledFieldSet = styled(FieldSet)`
display: flex;
align-items: center;
transition: opacity 500ms linear;
border: 2px solid ${color("border")};
margin: 0.5em 0;
padding: 0.25em 1em;
width: 100%;
legend {
text-transform: none;
position: relative;
height: 2px;
line-height: 0;
margin-left: -0.45em;
padding: 0 0.5em;
}
@media screen and (min-width: 440px) {
margin-right: 0.85em;
width: auto;
}
`;
import { screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { createMockField, createMockParameter } from "metabase-types/api/mocks";
import { renderWithProviders } from "__support__/ui";
import type { FieldFilterUiParameter } from "metabase-lib/parameters/types";
import Field from "metabase-lib/metadata/Field";
import { ParameterWidget } from "./ParameterWidget";
interface SetupOpts {
connectedField?: Field;
}
function setup({ connectedField }: SetupOpts = {}) {
const parameter: FieldFilterUiParameter = {
...createMockParameter({
id: "1fe8ce3",
type: "string/contains",
slug: "text_contains",
name: "Text contains",
}),
fields: connectedField ? [connectedField] : [],
};
const setValue = jest.fn();
renderWithProviders(
<ParameterWidget parameter={parameter} setValue={setValue} />,
);
return { setValue };
}
describe("ParameterWidget", () => {
it("should render parameter", () => {
setup();
expect(screen.getByText("Text contains")).toBeInTheDocument();
});
it("should be able to set parameter value", () => {
const { setValue } = setup();
userEvent.click(screen.getByText("Text contains"));
userEvent.type(screen.getByPlaceholderText("Enter some text"), "Gadget");
userEvent.click(screen.getByRole("button", { name: "Add filter" }));
expect(setValue).toHaveBeenCalledWith(["Gadget"]);
});
it("should not be able to submit empty value (metabase#15462)", () => {
const { setValue } = setup();
userEvent.click(screen.getByText("Text contains"));
const text = "Gadget";
const textInput = screen.getByPlaceholderText("Enter some text");
userEvent.type(textInput, text);
expect(screen.getByRole("button", { name: "Add filter" })).toBeEnabled();
userEvent.type(textInput, "{backspace}".repeat(text.length));
expect(screen.getByRole("button", { name: "Add filter" })).toBeDisabled();
userEvent.click(screen.getByRole("button", { name: "Add filter" }));
expect(setValue).not.toHaveBeenCalled();
});
it("should not be able to submit empty value when parameter has connected field (metabase#15462)", () => {
const field = new Field(
createMockField({
id: 1,
base_type: "type/Text",
effective_type: "type/Text",
semantic_type: "type/Category",
}),
);
const { setValue } = setup({ connectedField: field });
userEvent.click(screen.getByText("Text contains"));
const text = "Gadget";
const textInput = screen.getByPlaceholderText("Enter some text");
userEvent.type(textInput, text);
expect(screen.getByRole("button", { name: "Add filter" })).toBeEnabled();
userEvent.type(textInput, "{backspace}".repeat(text.length));
expect(screen.getByRole("button", { name: "Add filter" })).toBeDisabled();
userEvent.click(screen.getByRole("button", { name: "Add filter" }));
expect(setValue).not.toHaveBeenCalled();
});
});
export * from "./ParameterWidget";
......@@ -8,7 +8,7 @@ import {
SortableHandle,
} from "metabase/components/sortable";
import { getVisibleParameters } from "metabase/parameters/utils/ui";
import StaticParameterWidget from "./ParameterWidget";
import { ParameterWidget as StaticParameterWidget } from "./ParameterWidget";
const StaticParameterWidgetList = ({
children,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment