Skip to content

Commit 7473e66

Browse files
noraebJakobVogelsang
authored andcommitted
test: add unit tests for FilterListBase component
1 parent 30c9c5b commit 7473e66

File tree

1 file changed

+195
-0
lines changed

1 file changed

+195
-0
lines changed

base-list.spec.ts

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
/* eslint-disable no-unused-expressions */
2+
3+
import { expect, fixture, html } from '@open-wc/testing';
4+
import { customElement } from 'lit/decorators.js';
5+
import { spy } from 'sinon';
6+
7+
import { TextField } from '@scopedelement/material-web/textfield/internal/text-field';
8+
9+
import { FilterListBase } from './base-list.js';
10+
11+
@customElement('test-filterable-list')
12+
class TestFilterableList extends FilterListBase {
13+
render() {
14+
return html`
15+
${this.renderSearchField()}
16+
<div class="content">Test content</div>
17+
`;
18+
}
19+
20+
public testOnFilter() {
21+
this.onFilter();
22+
}
23+
}
24+
25+
describe('FilterListBase', () => {
26+
let element: TestFilterableList;
27+
28+
beforeEach(async () => {
29+
element = await fixture(
30+
html`<test-filterable-list></test-filterable-list>`
31+
);
32+
});
33+
34+
describe('basic properties', () => {
35+
it('has default filterable property as false', () => {
36+
expect(element.filterable).to.be.false;
37+
});
38+
39+
it('has default searchhelper property', () => {
40+
expect(element.searchhelper).to.equal('search');
41+
});
42+
43+
it('has default searchValue as empty string', () => {
44+
expect(element.searchValue).to.equal('');
45+
});
46+
47+
it('has default searchRegex that matches everything', () => {
48+
const regex = element.searchRegex;
49+
expect(regex.test('anything')).to.be.true;
50+
expect(regex.test('')).to.be.true;
51+
});
52+
});
53+
54+
describe('searchValue property', () => {
55+
it('getter returns the current search value', () => {
56+
expect(element.searchValue).to.equal('');
57+
element.searchValue = 'test';
58+
expect(element.searchValue).to.equal('test');
59+
});
60+
61+
it('setter updates internal state and regex', () => {
62+
element.searchValue = 'apple';
63+
expect(element.searchValue).to.equal('apple');
64+
65+
const regex = element.searchRegex;
66+
expect(regex.test('apple')).to.be.true;
67+
expect(regex.test('pineapple')).to.be.true;
68+
expect(regex.test('banana')).to.be.false;
69+
});
70+
71+
it('setter ignores duplicate values', () => {
72+
element.searchValue = 'test';
73+
const requestUpdateSpy = spy(element, 'requestUpdate');
74+
element.searchValue = 'test';
75+
expect(requestUpdateSpy).to.not.have.been.called;
76+
requestUpdateSpy.restore();
77+
});
78+
79+
it('setter triggers requestUpdate for new values', () => {
80+
element.searchValue = 'initial';
81+
const requestUpdateSpy = spy(element, 'requestUpdate');
82+
element.searchValue = 'changed';
83+
expect(requestUpdateSpy).to.have.been.calledWith(
84+
'searchValue',
85+
'initial'
86+
);
87+
requestUpdateSpy.restore();
88+
});
89+
});
90+
91+
describe('search field rendering', () => {
92+
it('does not render search field when filterable is false', () => {
93+
element.filterable = false;
94+
element.requestUpdate();
95+
96+
const searchField = element.shadowRoot?.querySelector(
97+
'md-outlined-text-field'
98+
);
99+
expect(searchField).to.be.null;
100+
});
101+
102+
it('renders search field when filterable is true', async () => {
103+
element.filterable = true;
104+
await element.updateComplete;
105+
106+
const searchField = element.shadowRoot?.querySelector(
107+
'md-outlined-text-field'
108+
);
109+
expect(searchField).to.not.be.null;
110+
});
111+
112+
it('search field has correct placeholder', async () => {
113+
element.filterable = true;
114+
element.searchhelper = 'Custom search placeholder';
115+
await element.updateComplete;
116+
117+
const searchField = element.shadowRoot?.querySelector(
118+
'md-outlined-text-field'
119+
);
120+
expect(searchField?.getAttribute('placeholder')).to.equal(
121+
'Custom search placeholder'
122+
);
123+
});
124+
125+
it('search field reflects searchValue', async () => {
126+
element.filterable = true;
127+
element.searchValue = 'test value';
128+
await element.updateComplete;
129+
130+
const searchField = element.shadowRoot?.querySelector(
131+
'md-outlined-text-field'
132+
) as TextField;
133+
expect(searchField?.value).to.equal('test value');
134+
});
135+
});
136+
137+
describe('search regex functionality', () => {
138+
it('creates case-insensitive regex', () => {
139+
element.searchValue = 'Apple';
140+
const regex = element.searchRegex;
141+
expect(regex.test('apple')).to.be.true;
142+
expect(regex.test('APPLE')).to.be.true;
143+
});
144+
145+
it('handles multiple search terms', () => {
146+
element.searchValue = 'red apple';
147+
const regex = element.searchRegex;
148+
expect(regex.test('red delicious apple')).to.be.true;
149+
expect(regex.test('apple red')).to.be.true;
150+
expect(regex.test('red banana')).to.be.false;
151+
});
152+
153+
it('handles wildcard characters', () => {
154+
element.searchValue = 'app*';
155+
const regex = element.searchRegex;
156+
expect(regex.test('apple')).to.be.true;
157+
expect(regex.test('application')).to.be.true;
158+
expect(regex.test('app')).to.be.true;
159+
});
160+
161+
it('handles quoted strings', () => {
162+
element.searchValue = '"exact phrase"';
163+
const regex = element.searchRegex;
164+
expect(regex.test('this is an exact phrase here')).to.be.true;
165+
expect(regex.test('exact different phrase')).to.be.false;
166+
});
167+
168+
it('escapes special regex characters', () => {
169+
element.searchValue = 'test.value';
170+
const regex = element.searchRegex;
171+
expect(regex.test('test.value')).to.be.true;
172+
expect(regex.test('testXvalue')).to.be.false;
173+
});
174+
});
175+
176+
describe('onFilter method', () => {
177+
it('updates searchValue from search input', async () => {
178+
element.filterable = true;
179+
await element.updateComplete;
180+
181+
const searchField = element.shadowRoot?.querySelector(
182+
'md-outlined-text-field'
183+
) as TextField;
184+
if (searchField) {
185+
searchField.value = 'new search term';
186+
element.testOnFilter();
187+
expect(element.searchValue).to.equal('new search term');
188+
}
189+
});
190+
191+
it('handles missing search input gracefully', () => {
192+
expect(() => element.testOnFilter()).to.not.throw;
193+
});
194+
});
195+
});

0 commit comments

Comments
 (0)