Skip to content

Commit ffb41a9

Browse files
committed
feat(test suites): add search filter
1 parent 62e1b4c commit ffb41a9

3 files changed

Lines changed: 78 additions & 48 deletions

File tree

testgen/common/models/test_suite.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def select_minimal_where(
101101

102102
@classmethod
103103
@st.cache_data(show_spinner=False)
104-
def select_summary(cls, project_code: str, table_group_id: str | UUID | None = None) -> Iterable[TestSuiteSummary]:
104+
def select_summary(cls, project_code: str, table_group_id: str | UUID | None = None, test_suite_name: str | None = None) -> Iterable[TestSuiteSummary]:
105105
if table_group_id and not is_uuid4(table_group_id):
106106
return []
107107

@@ -199,9 +199,10 @@ def select_summary(cls, project_code: str, table_group_id: str | UUID | None = N
199199
WHERE suites.is_monitor IS NOT TRUE
200200
AND suites.project_code = :project_code
201201
{"AND suites.table_groups_id = :table_group_id" if table_group_id else ""}
202+
{"AND suites.test_suite ILIKE :test_suite_name" if test_suite_name else ""}
202203
ORDER BY LOWER(suites.test_suite);
203204
"""
204-
params = {"project_code": project_code, "table_group_id": table_group_id}
205+
params = {"project_code": project_code, "table_group_id": table_group_id, "test_suite_name": f"%{test_suite_name}%" if test_suite_name else None}
205206
db_session = get_current_session()
206207
results = db_session.execute(text(query), params).mappings().all()
207208
return [TestSuiteSummary(**row) for row in results]

testgen/ui/components/frontend/js/pages/test_suites.js

Lines changed: 70 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
* @property {ProjectSummary} project_summary
1212
* @property {TestSuiteSummary} test_suites
1313
* @property {FilterOption[]} table_group_filter_options
14+
* @property {string?} test_suite_name
1415
* @property {Permissions} permissions
1516
*/
1617
import van from '../van.min.js';
1718
import { Streamlit } from '../streamlit.js';
1819
import { emitEvent, getValue, loadStylesheet, resizeFrameHeightToElement, resizeFrameHeightOnDOMChange } from '../utils.js';
1920
import { formatTimestamp, DISABLED_ACTION_TEXT } from '../display_utils.js';
21+
import { Input } from '../components/input.js';
2022
import { Select } from '../components/select.js';
2123
import { Button } from '../components/button.js';
2224
import { Card } from '../components/card.js';
@@ -46,51 +48,77 @@ const TestSuites = (/** @type Properties */ props) => {
4648
return projectSummary.test_suite_count > 0
4749
? div(
4850
{ class: 'tg-test-suites'},
49-
() => div(
50-
{ class: 'flex-row fx-align-flex-end fx-justify-space-between fx-gap-4 mb-4' },
51-
Select({
52-
label: 'Table Group',
53-
value: getValue(props.table_group_filter_options)?.find((op) => op.selected)?.value ?? null,
54-
options: getValue(props.table_group_filter_options) ?? [],
55-
allowNull: true,
56-
style: 'font-size: 14px;',
57-
testId: 'table-group-filter',
58-
onChange: (value) => emitEvent('FilterApplied', {payload: value}),
59-
}),
60-
div(
61-
{ class: 'flex-row fx-gap-3' },
62-
Button({
63-
icon: 'notifications',
64-
type: 'stroked',
65-
label: 'Notifications',
66-
tooltip: 'Configure email notifications for test runs',
67-
tooltipPosition: 'bottom',
68-
width: 'fit-content',
69-
style: 'background: var(--button-generic-background-color);',
70-
onclick: () => emitEvent('RunNotificationsClicked', {}),
71-
}),
72-
Button({
73-
icon: 'today',
74-
type: 'stroked',
75-
label: 'Schedules',
76-
tooltip: 'Manage when test suites should run',
77-
tooltipPosition: 'bottom',
78-
width: 'fit-content',
79-
style: 'background: var(--button-generic-background-color);',
80-
onclick: () => emitEvent('RunSchedulesClicked', {}),
81-
}),
82-
userCanEdit
83-
? Button({
84-
icon: 'add',
51+
() => {
52+
const initialTableGroup = getValue(props.table_group_filter_options)?.find((op) => op.selected)?.value ?? null;
53+
const initialTestSuiteName = getValue(props.test_suite_name) || null;
54+
const selectedTableGroup = van.state(initialTableGroup);
55+
const testSuiteNameFilter = van.state(initialTestSuiteName);
56+
57+
van.derive(() => {
58+
if (selectedTableGroup.val !== initialTableGroup || testSuiteNameFilter.val !== initialTestSuiteName) {
59+
emitEvent('FilterApplied', { payload: { table_group_id: selectedTableGroup.val, test_suite_name: testSuiteNameFilter.val } });
60+
}
61+
});
62+
63+
return div(
64+
{ class: 'flex-row fx-align-flex-end fx-justify-space-between fx-gap-4 fx-flex-wrap mb-4' },
65+
div(
66+
{ class: 'flex-row fx-align-flex-end fx-gap-3' },
67+
Select({
68+
label: 'Table Group',
69+
value: selectedTableGroup,
70+
options: getValue(props.table_group_filter_options) ?? [],
71+
allowNull: true,
72+
style: 'font-size: 14px;',
73+
testId: 'table-group-filter',
74+
onChange: (value) => selectedTableGroup.val = value,
75+
}),
76+
Input({
77+
testId: 'test-suite-name-filter',
78+
icon: 'search',
79+
label: '',
80+
placeholder: 'Search test suite names',
81+
width: 300,
82+
clearable: true,
83+
value: testSuiteNameFilter,
84+
onChange: (value) => testSuiteNameFilter.val = value || null,
85+
}),
86+
),
87+
div(
88+
{ class: 'flex-row fx-gap-3' },
89+
Button({
90+
icon: 'notifications',
8591
type: 'stroked',
86-
label: 'Add Test Suite',
92+
label: 'Notifications',
93+
tooltip: 'Configure email notifications for test runs',
94+
tooltipPosition: 'bottom',
8795
width: 'fit-content',
8896
style: 'background: var(--button-generic-background-color);',
89-
onclick: () => emitEvent('AddTestSuiteClicked', {}),
90-
})
91-
: '',
92-
),
93-
),
97+
onclick: () => emitEvent('RunNotificationsClicked', {}),
98+
}),
99+
Button({
100+
icon: 'today',
101+
type: 'stroked',
102+
label: 'Schedules',
103+
tooltip: 'Manage when test suites should run',
104+
tooltipPosition: 'bottom',
105+
width: 'fit-content',
106+
style: 'background: var(--button-generic-background-color);',
107+
onclick: () => emitEvent('RunSchedulesClicked', {}),
108+
}),
109+
userCanEdit
110+
? Button({
111+
icon: 'add',
112+
type: 'stroked',
113+
label: 'Add Test Suite',
114+
width: 'fit-content',
115+
style: 'background: var(--button-generic-background-color);',
116+
onclick: () => emitEvent('AddTestSuiteClicked', {}),
117+
})
118+
: '',
119+
),
120+
);
121+
},
94122
() => getValue(testSuites)?.length
95123
? div(
96124
{ class: 'flex-column' },

testgen/ui/views/test_suites.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ class TestSuitesPage(Page):
3838
order=2,
3939
)
4040

41-
def render(self, project_code: str, table_group_id: str | None = None, **_kwargs) -> None:
41+
def render(self, project_code: str, table_group_id: str | None = None, test_suite_name: str | None = None, **_kwargs) -> None:
4242
testgen.page_header(
4343
PAGE_TITLE,
4444
"connect-your-database/manage-test-suites/",
4545
)
4646

4747
table_groups = TableGroup.select_minimal_where(TableGroup.project_code == project_code)
4848
user_can_edit = session.auth.user_has_permission("edit")
49-
test_suites = TestSuite.select_summary(project_code, table_group_id)
49+
test_suites = TestSuite.select_summary(project_code, table_group_id, test_suite_name)
5050
project_summary = Project.get_summary(project_code)
5151

5252
testgen.testgen_component(
@@ -61,6 +61,7 @@ def render(self, project_code: str, table_group_id: str | None = None, **_kwargs
6161
"selected": str(table_group_id) == str(table_group.id),
6262
} for table_group in table_groups
6363
],
64+
"test_suite_name": test_suite_name,
6465
"permissions": {
6566
"can_edit": user_can_edit,
6667
}
@@ -79,8 +80,8 @@ def render(self, project_code: str, table_group_id: str | None = None, **_kwargs
7980
)
8081

8182

82-
def on_test_suites_filtered(table_group_id: str | None = None) -> None:
83-
Router().set_query_params({ "table_group_id": table_group_id })
83+
def on_test_suites_filtered(params: dict) -> None:
84+
Router().set_query_params(params)
8485

8586

8687
@st.dialog(title="Add Test Suite")

0 commit comments

Comments
 (0)