Skip to content

Commit d1b97ac

Browse files
authored
Merge pull request #38 from jbpratt/filter
feat(index): filter dashboards and groups
2 parents 9976653 + 2031b17 commit d1b97ac

File tree

2 files changed

+152
-3
lines changed

2 files changed

+152
-3
lines changed

web/src/testgrid-index.ts

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ export class TestgridIndex extends LitElement {
5151
@property({ type: Boolean })
5252
show = true;
5353

54+
@property({ type: String })
55+
searchTerm = '';
56+
5457
/**
5558
* Lit-element lifecycle method.
5659
* Invoked when a component is added to the document's DOM.
@@ -61,17 +64,52 @@ export class TestgridIndex extends LitElement {
6164
this.fetchDashboards();
6265
}
6366

67+
get filteredDashboardGroups() {
68+
if (!this.searchTerm) return this.dashboardGroups;
69+
return this.dashboardGroups.filter(group =>
70+
group.toLowerCase().includes(this.searchTerm.toLowerCase())
71+
);
72+
}
73+
74+
get filteredDashboards() {
75+
if (!this.searchTerm) return this.dashboards;
76+
return this.dashboards.filter(dashboard =>
77+
dashboard.toLowerCase().includes(this.searchTerm.toLowerCase())
78+
);
79+
}
80+
81+
get filteredRespectiveDashboards() {
82+
if (!this.searchTerm) return this.respectiveDashboards;
83+
return this.respectiveDashboards.filter(dashboard =>
84+
dashboard.toLowerCase().includes(this.searchTerm.toLowerCase())
85+
);
86+
}
87+
88+
private handleSearchInput(event: Event) {
89+
const input = event.target as HTMLInputElement;
90+
this.searchTerm = input.value;
91+
}
92+
6493
/**
6594
* Lit-element lifecycle method.
6695
* Invoked on each update to perform rendering tasks.
6796
*/
6897
render() {
6998
return html`
99+
<div class="search-container">
100+
<input
101+
type="text"
102+
placeholder="Search dashboards and groups..."
103+
.value=${this.searchTerm}
104+
@input=${this.handleSearchInput}
105+
class="search-input"
106+
/>
107+
</div>
70108
<div class="flex-container">
71109
<!-- loading dashboard groups -->
72110
<mwc-list style="min-width: 760px">
73111
${map(
74-
this.dashboardGroups,
112+
this.filteredDashboardGroups,
75113
(dash: string, index: number) =>
76114
html`
77115
<mwc-list-item
@@ -89,10 +127,10 @@ export class TestgridIndex extends LitElement {
89127
</mwc-list>
90128
91129
<!-- loading dashboards -->
92-
${this.show ? dashboardTemplate(this.dashboards) : ''}
130+
${this.show ? dashboardTemplate(this.filteredDashboards) : ''}
93131
94132
<!-- loading respective dashboards -->
95-
${!this.show ? dashboardTemplate(this.respectiveDashboards) : ''}
133+
${!this.show ? dashboardTemplate(this.filteredRespectiveDashboards) : ''}
96134
${!this.show
97135
? html`
98136
<mwc-button
@@ -185,6 +223,28 @@ export class TestgridIndex extends LitElement {
185223
background-color: var(--example-app-background-color);
186224
}
187225
226+
.search-container {
227+
display: flex;
228+
justify-content: center;
229+
margin: 20px 0;
230+
}
231+
232+
.search-input {
233+
width: 400px;
234+
max-width: 90%;
235+
padding: 12px 16px;
236+
font-size: 16px;
237+
border: 2px solid #ddd;
238+
border-radius: 8px;
239+
outline: none;
240+
transition: border-color 0.2s;
241+
box-sizing: border-box;
242+
}
243+
244+
.search-input:focus {
245+
border-color: #707df1;
246+
}
247+
188248
.flex-container {
189249
display: grid;
190250
gap: 30px;

web/test/testgrid-index.test.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,93 @@ describe('Testgrid Index page', () => {
123123

124124
expect(location.pathname).to.not.equal('/');
125125
});
126+
127+
describe('Search functionality', () => {
128+
it('filters dashboard groups based on search term', async () => {
129+
await waitUntil(
130+
() => element.shadowRoot!.querySelector('mwc-list-item.dashboard-group'),
131+
'Index did not render dashboard groups',
132+
{
133+
timeout: 4000,
134+
}
135+
);
136+
137+
element.searchTerm = 'group-1';
138+
await element.updateComplete;
139+
140+
expect(element.filteredDashboardGroups).to.have.lengthOf(1);
141+
expect(element.filteredDashboardGroups[0]).to.include('group-1');
142+
});
143+
144+
it('filters dashboards based on search term', async () => {
145+
await waitUntil(
146+
() => element.shadowRoot!.querySelector('mwc-list-item.dashboard'),
147+
'Index did not render dashboards',
148+
{
149+
timeout: 4000,
150+
}
151+
);
152+
153+
element.searchTerm = 'dashboard-8';
154+
await element.updateComplete;
155+
156+
expect(element.filteredDashboards).to.have.lengthOf(1);
157+
expect(element.filteredDashboards[0]).to.include('dashboard-8');
158+
});
159+
160+
it('shows no results when search term matches nothing', async () => {
161+
await waitUntil(
162+
() => element.shadowRoot!.querySelector('mwc-list-item.dashboard'),
163+
'Index did not render dashboards',
164+
{
165+
timeout: 4000,
166+
}
167+
);
168+
169+
element.searchTerm = 'nonexistent';
170+
await element.updateComplete;
171+
172+
expect(element.filteredDashboards).to.have.lengthOf(0);
173+
expect(element.filteredDashboardGroups).to.have.lengthOf(0);
174+
});
175+
176+
it('filters respective dashboards when in group view', async () => {
177+
await waitUntil(
178+
() => element.shadowRoot!.querySelector('mwc-list-item.dashboard-group'),
179+
'Index did not render dashboard groups',
180+
{
181+
timeout: 4000,
182+
}
183+
);
184+
185+
// click on a dashboard group to show respective dashboards
186+
const dashboardGroup: ListItemBase = element.shadowRoot!.querySelector(
187+
'mwc-list-item.dashboard-group'
188+
)!;
189+
dashboardGroup.click();
190+
await aTimeout(3000);
191+
192+
element.searchTerm = 'dashboard-1';
193+
await element.updateComplete;
194+
195+
expect(element.filteredRespectiveDashboards).to.have.lengthOf(1);
196+
expect(element.filteredRespectiveDashboards[0]).to.include('dashboard-1');
197+
});
198+
199+
it('performs case-insensitive search', async () => {
200+
await waitUntil(
201+
() => element.shadowRoot!.querySelector('mwc-list-item.dashboard'),
202+
'Index did not render dashboards',
203+
{
204+
timeout: 4000,
205+
}
206+
);
207+
208+
element.searchTerm = 'DASHBOARD-8';
209+
await element.updateComplete;
210+
211+
expect(element.filteredDashboards).to.have.lengthOf(1);
212+
expect(element.filteredDashboards[0]).to.include('dashboard-8');
213+
});
214+
});
126215
});

0 commit comments

Comments
 (0)