Skip to content

Commit 0ad3fd7

Browse files
committed
Updated filter by me and hide old filter
1 parent 82da8b7 commit 0ad3fd7

5 files changed

Lines changed: 180 additions & 174 deletions

File tree

src/components/Home/RunSection/RunSection.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@ const INCLUDE_EXECUTION_STATS_QUERY_KEY = "include_execution_stats";
3838

3939
type RunSectionSearch = { page_token?: string; filter?: string };
4040

41-
export const RunSection = ({ onEmptyList }: { onEmptyList?: () => void }) => {
41+
interface RunSectionProps {
42+
onEmptyList?: () => void;
43+
/** When true, hides the built-in filter UI (used when new filter bar is enabled) */
44+
hideFilters?: boolean;
45+
}
46+
47+
export const RunSection = ({ onEmptyList, hideFilters }: RunSectionProps) => {
4248
const { backendUrl, configured, available, ready } = useBackend();
4349
const navigate = useNavigate();
4450
const { pathname } = useLocation();
@@ -224,7 +230,7 @@ export const RunSection = ({ onEmptyList }: { onEmptyList?: () => void }) => {
224230
);
225231
}
226232

227-
const searchMarkup = (
233+
const searchMarkup = hideFilters ? null : (
228234
<InlineStack gap="4">
229235
<InlineStack gap="2">
230236
<Switch

src/components/shared/CreatedByFilter/CreatedByFilter.test.tsx

Lines changed: 121 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -2,160 +2,183 @@ import { render, screen } from "@testing-library/react";
22
import userEvent from "@testing-library/user-event";
33
import { describe, expect, it, vi } from "vitest";
44

5-
import { DEFAULT_CREATED_BY_ME_FILTER_VALUE } from "@/utils/constants";
6-
75
import { CreatedByFilter } from "./CreatedByFilter";
86

97
describe("CreatedByFilter", () => {
108
describe("rendering", () => {
11-
it("should render toggle and search input", () => {
12-
render(<CreatedByFilter value={undefined} onChange={vi.fn()} />);
9+
it("should render search input with placeholder", () => {
10+
render(
11+
<CreatedByFilter
12+
value={undefined}
13+
onChange={vi.fn()}
14+
onClear={vi.fn()}
15+
/>,
16+
);
1317

14-
expect(screen.getByRole("switch")).toBeInTheDocument();
15-
expect(screen.getByLabelText("Created by me")).toBeInTheDocument();
16-
expect(screen.getByPlaceholderText("Search by user")).toBeInTheDocument();
1718
expect(
18-
screen.getByRole("button", { name: "Search" }),
19+
screen.getByPlaceholderText("Search by user..."),
1920
).toBeInTheDocument();
2021
});
2122

22-
it("should show 'Created by me' when no value", () => {
23-
render(<CreatedByFilter value={undefined} onChange={vi.fn()} />);
24-
25-
expect(screen.getByLabelText("Created by me")).toBeInTheDocument();
26-
});
27-
28-
it("should show 'Created by {user}' when value is set", () => {
29-
render(<CreatedByFilter value="john.doe" onChange={vi.fn()} />);
23+
it("should not show clear button when empty", () => {
24+
render(
25+
<CreatedByFilter
26+
value={undefined}
27+
onChange={vi.fn()}
28+
onClear={vi.fn()}
29+
/>,
30+
);
3031

31-
expect(screen.getByLabelText("Created by john.doe")).toBeInTheDocument();
32+
expect(
33+
screen.queryByRole("button", { name: "Clear user filter" }),
34+
).not.toBeInTheDocument();
3235
});
3336

34-
it("should have switch unchecked when no value", () => {
35-
render(<CreatedByFilter value={undefined} onChange={vi.fn()} />);
37+
it("should show clear button when value is set", () => {
38+
render(
39+
<CreatedByFilter
40+
value="john.doe"
41+
onChange={vi.fn()}
42+
onClear={vi.fn()}
43+
/>,
44+
);
3645

37-
expect(screen.getByRole("switch")).not.toBeChecked();
46+
expect(
47+
screen.getByRole("button", { name: "Clear user filter" }),
48+
).toBeInTheDocument();
3849
});
3950

40-
it("should show 'Created by {user}' and checked switch when value is set", () => {
41-
render(<CreatedByFilter value="john.doe" onChange={vi.fn()} />);
51+
it("should populate input with current value", () => {
52+
render(
53+
<CreatedByFilter
54+
value="existing-user"
55+
onChange={vi.fn()}
56+
onClear={vi.fn()}
57+
/>,
58+
);
4259

43-
expect(screen.getByRole("switch")).toBeChecked();
44-
expect(screen.getByLabelText("Created by john.doe")).toBeInTheDocument();
60+
expect(screen.getByPlaceholderText("Search by user...")).toHaveValue(
61+
"existing-user",
62+
);
4563
});
4664
});
4765

48-
describe("toggle behavior", () => {
49-
it("should call onChange with 'me' when toggle is turned on", async () => {
50-
const user = userEvent.setup();
51-
const onChange = vi.fn();
52-
render(<CreatedByFilter value={undefined} onChange={onChange} />);
53-
54-
await user.click(screen.getByRole("switch"));
55-
56-
expect(onChange).toHaveBeenCalledWith(DEFAULT_CREATED_BY_ME_FILTER_VALUE);
57-
});
58-
59-
it("should call onChange with undefined when toggle is turned off", async () => {
66+
describe("typing behavior", () => {
67+
it("should call onChange when typing", async () => {
6068
const user = userEvent.setup();
6169
const onChange = vi.fn();
6270
render(
6371
<CreatedByFilter
64-
value={DEFAULT_CREATED_BY_ME_FILTER_VALUE}
72+
value={undefined}
6573
onChange={onChange}
74+
onClear={vi.fn()}
6675
/>,
6776
);
6877

69-
await user.click(screen.getByRole("switch"));
78+
await user.type(screen.getByPlaceholderText("Search by user..."), "jane");
7079

71-
expect(onChange).toHaveBeenCalledWith(undefined);
80+
// Called for each character typed
81+
expect(onChange).toHaveBeenCalledTimes(4);
82+
expect(onChange).toHaveBeenLastCalledWith("jane");
7283
});
7384

74-
it("should clear filter when toggling off with existing value", async () => {
85+
it("should call onChange with undefined when input is cleared by typing", async () => {
7586
const user = userEvent.setup();
7687
const onChange = vi.fn();
77-
render(<CreatedByFilter value="john.doe" onChange={onChange} />);
88+
render(
89+
<CreatedByFilter value="j" onChange={onChange} onClear={vi.fn()} />,
90+
);
7891

79-
await user.click(screen.getByRole("switch"));
92+
await user.clear(screen.getByPlaceholderText("Search by user..."));
8093

81-
expect(onChange).toHaveBeenCalledWith(undefined);
94+
expect(onChange).toHaveBeenLastCalledWith(undefined);
8295
});
8396
});
8497

85-
describe("search behavior", () => {
86-
it("should have search button disabled when input is empty", () => {
87-
render(<CreatedByFilter value={undefined} onChange={vi.fn()} />);
88-
89-
expect(screen.getByRole("button", { name: "Search" })).toBeDisabled();
90-
});
91-
92-
it("should enable search button when input has text", async () => {
93-
const user = userEvent.setup();
94-
render(<CreatedByFilter value={undefined} onChange={vi.fn()} />);
95-
96-
await user.type(screen.getByPlaceholderText("Search by user"), "jane");
97-
98-
expect(screen.getByRole("button", { name: "Search" })).toBeEnabled();
99-
});
100-
101-
it("should call onChange with typed user when search clicked", async () => {
98+
describe("clear button behavior", () => {
99+
it("should call onClear and clear input when clear button is clicked", async () => {
102100
const user = userEvent.setup();
103-
const onChange = vi.fn();
104-
render(<CreatedByFilter value={undefined} onChange={onChange} />);
101+
const onClear = vi.fn();
102+
render(
103+
<CreatedByFilter
104+
value="john.doe"
105+
onChange={vi.fn()}
106+
onClear={onClear}
107+
/>,
108+
);
105109

106-
await user.type(
107-
screen.getByPlaceholderText("Search by user"),
108-
"jane.doe",
110+
await user.click(
111+
screen.getByRole("button", { name: "Clear user filter" }),
109112
);
110-
await user.click(screen.getByRole("button", { name: "Search" }));
111113

112-
expect(onChange).toHaveBeenCalledWith("jane.doe");
114+
expect(onClear).toHaveBeenCalled();
113115
});
114116

115-
it("should call onChange when Enter is pressed in input", async () => {
117+
it("should hide clear button after clearing", async () => {
116118
const user = userEvent.setup();
117-
const onChange = vi.fn();
118-
render(<CreatedByFilter value={undefined} onChange={onChange} />);
119+
render(
120+
<CreatedByFilter
121+
value="john.doe"
122+
onChange={vi.fn()}
123+
onClear={vi.fn()}
124+
/>,
125+
);
119126

120-
const input = screen.getByPlaceholderText("Search by user");
121-
await user.type(input, "jane.doe{Enter}");
127+
await user.click(
128+
screen.getByRole("button", { name: "Clear user filter" }),
129+
);
122130

123-
expect(onChange).toHaveBeenCalledWith("jane.doe");
131+
expect(
132+
screen.queryByRole("button", { name: "Clear user filter" }),
133+
).not.toBeInTheDocument();
124134
});
135+
});
125136

126-
it("should trim whitespace from search input", async () => {
127-
const user = userEvent.setup();
128-
const onChange = vi.fn();
129-
render(<CreatedByFilter value={undefined} onChange={onChange} />);
130-
131-
await user.type(
132-
screen.getByPlaceholderText("Search by user"),
133-
" jane ",
137+
describe("external value sync", () => {
138+
it("should sync input when value prop changes", () => {
139+
const { rerender } = render(
140+
<CreatedByFilter
141+
value="initial"
142+
onChange={vi.fn()}
143+
onClear={vi.fn()}
144+
/>,
134145
);
135-
await user.click(screen.getByRole("button", { name: "Search" }));
136146

137-
expect(onChange).toHaveBeenCalledWith("jane");
138-
});
139-
140-
it("should not call onChange when searching with only whitespace", async () => {
141-
const user = userEvent.setup();
142-
const onChange = vi.fn();
143-
render(<CreatedByFilter value={undefined} onChange={onChange} />);
147+
expect(screen.getByPlaceholderText("Search by user...")).toHaveValue(
148+
"initial",
149+
);
144150

145-
await user.type(screen.getByPlaceholderText("Search by user"), " ");
151+
rerender(
152+
<CreatedByFilter
153+
value="updated"
154+
onChange={vi.fn()}
155+
onClear={vi.fn()}
156+
/>,
157+
);
146158

147-
// Button should still be disabled
148-
expect(screen.getByRole("button", { name: "Search" })).toBeDisabled();
159+
expect(screen.getByPlaceholderText("Search by user...")).toHaveValue(
160+
"updated",
161+
);
149162
});
150-
});
151163

152-
describe("initial state", () => {
153-
it("should populate search input with current value", () => {
154-
render(<CreatedByFilter value="existing-user" onChange={vi.fn()} />);
164+
it("should clear input when value prop becomes undefined", () => {
165+
const { rerender } = render(
166+
<CreatedByFilter
167+
value="some-user"
168+
onChange={vi.fn()}
169+
onClear={vi.fn()}
170+
/>,
171+
);
155172

156-
expect(screen.getByPlaceholderText("Search by user")).toHaveValue(
157-
"existing-user",
173+
rerender(
174+
<CreatedByFilter
175+
value={undefined}
176+
onChange={vi.fn()}
177+
onClear={vi.fn()}
178+
/>,
158179
);
180+
181+
expect(screen.getByPlaceholderText("Search by user...")).toHaveValue("");
159182
});
160183
});
161184
});

0 commit comments

Comments
 (0)