Skip to content

Commit 71abc22

Browse files
authored
test: merge combo-box item renderer and class name generator tests (#10241) (#10243)
1 parent 2104fa5 commit 71abc22

File tree

6 files changed

+380
-335
lines changed

6 files changed

+380
-335
lines changed

packages/combo-box/test/item-class-name-generator.test.js

Lines changed: 0 additions & 58 deletions
This file was deleted.

packages/combo-box/test/item-renderer.test.js

Lines changed: 0 additions & 141 deletions
This file was deleted.
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
import { expect } from '@vaadin/chai-plugins';
2+
import { fixtureSync, nextRender } from '@vaadin/testing-helpers';
3+
import sinon from 'sinon';
4+
import '../src/vaadin-combo-box.js';
5+
import { getAllItems, getFirstItem, setInputValue } from './helpers.js';
6+
7+
describe('items', () => {
8+
let comboBox;
9+
10+
describe('renderer', () => {
11+
beforeEach(async () => {
12+
comboBox = fixtureSync('<vaadin-combo-box></vaadin-combo-box>');
13+
await nextRender();
14+
comboBox.items = ['foo', 'bar', 'baz'];
15+
});
16+
17+
describe('arguments', () => {
18+
beforeEach(() => {
19+
comboBox.renderer = sinon.spy();
20+
comboBox.opened = true;
21+
});
22+
23+
it(`should pass the 'root', 'owner', 'model' arguments to the renderer`, () => {
24+
const [root, owner, model] = comboBox.renderer.args[0];
25+
26+
expect(root.localName).to.equal('vaadin-combo-box-item');
27+
expect(owner).to.equal(comboBox);
28+
expect(model).to.deep.equal({
29+
item: 'foo',
30+
index: 0,
31+
focused: false,
32+
selected: false,
33+
});
34+
});
35+
36+
it(`should change the 'model.selected' property`, () => {
37+
comboBox.value = 'foo';
38+
39+
const model = comboBox.renderer.lastCall.args[2];
40+
41+
expect(model.selected).to.be.true;
42+
});
43+
44+
it(`should change the 'model.focused' property`, () => {
45+
comboBox._focusedIndex = 0;
46+
47+
const model = comboBox.renderer.lastCall.args[2];
48+
49+
expect(model.focused).to.be.true;
50+
});
51+
});
52+
53+
it('should use renderer when it is defined', () => {
54+
comboBox.renderer = (root, _comboBox, model) => {
55+
const textNode = document.createTextNode(`${model.item} ${model.index}`);
56+
root.appendChild(textNode);
57+
};
58+
comboBox.opened = true;
59+
60+
expect(getFirstItem(comboBox).textContent.trim()).to.equal('foo 0');
61+
});
62+
63+
it('should run renderers when requesting content update', () => {
64+
comboBox.renderer = sinon.spy();
65+
comboBox.opened = true;
66+
67+
expect(comboBox.renderer.callCount).to.be.equal(comboBox.items.length);
68+
69+
comboBox.requestContentUpdate();
70+
71+
expect(comboBox.renderer.callCount).to.be.equal(comboBox.items.length * 2);
72+
});
73+
74+
it('should not run renderers for invisible items', () => {
75+
// Set up an item renderer that maps item data to DOM elements.
76+
const itemContents = {
77+
foo: document.createElement('div'),
78+
bar: document.createElement('div'),
79+
baz: document.createElement('div'),
80+
};
81+
comboBox.renderer = (root, _, { item }) => {
82+
root.textContent = '';
83+
root.appendChild(itemContents[item]);
84+
};
85+
comboBox.opened = true;
86+
87+
// Filter the items
88+
// This renders `bar` into the first item now, and hides the other items.
89+
// However, the second item still has `bar` as item data.
90+
setInputValue(comboBox, 'bar');
91+
92+
const filteredItem = getAllItems(comboBox)[0];
93+
expect(filteredItem.children.length).to.equal(1);
94+
expect(filteredItem.children[0]).to.equal(itemContents.bar);
95+
96+
// Now run requestContentUpdate. This should only render the first item, but
97+
// not the second one. We test this by verifying that the `bar` item content
98+
// was not moved to the second item by its renderer.
99+
comboBox.requestContentUpdate();
100+
101+
const allItems = getAllItems(comboBox);
102+
expect(allItems[0].children.length).to.equal(1);
103+
expect(allItems[0].children[0]).to.equal(itemContents.bar);
104+
});
105+
106+
it('should not throw if requestContentUpdate() called before opening', () => {
107+
expect(() => comboBox.requestContentUpdate()).not.to.throw(Error);
108+
});
109+
110+
it('should render the item label when removing the renderer', () => {
111+
comboBox.renderer = (root) => {
112+
root.textContent = 'bar';
113+
};
114+
comboBox.opened = true;
115+
116+
expect(getFirstItem(comboBox).textContent).to.equal('bar');
117+
118+
comboBox.renderer = null;
119+
120+
expect(getFirstItem(comboBox).textContent).to.equal('foo');
121+
});
122+
123+
it('should clear the old content after assigning a new renderer', () => {
124+
comboBox.opened = true;
125+
comboBox.renderer = () => {};
126+
expect(getFirstItem(comboBox).textContent).to.equal('');
127+
});
128+
129+
it('should restore filtered item content', () => {
130+
const contentNodes = comboBox.items.map((item) => document.createTextNode(item));
131+
132+
comboBox.renderer = (root, _, { item }) => {
133+
root.textContent = '';
134+
root.append(contentNodes[comboBox.items.indexOf(item)]);
135+
};
136+
137+
comboBox.opened = true;
138+
setInputValue(comboBox, 'r');
139+
setInputValue(comboBox, '');
140+
expect(getAllItems(comboBox)[1].textContent).to.equal('bar');
141+
});
142+
});
143+
144+
describe('itemClassNameGenerator', () => {
145+
beforeEach(async () => {
146+
comboBox = fixtureSync('<vaadin-combo-box></vaadin-combo-box>');
147+
await nextRender();
148+
comboBox.items = ['foo', 'bar', 'baz'];
149+
});
150+
151+
it('should set class name on dropdown items', async () => {
152+
comboBox.itemClassNameGenerator = (item) => `item-${item}`;
153+
comboBox.open();
154+
await nextRender();
155+
const items = getAllItems(comboBox);
156+
expect(items[0].className).to.equal('item-foo');
157+
expect(items[1].className).to.equal('item-bar');
158+
expect(items[2].className).to.equal('item-baz');
159+
});
160+
161+
it('should remove class name when return value is empty string', async () => {
162+
comboBox.itemClassNameGenerator = (item) => `item-${item}`;
163+
comboBox.open();
164+
await nextRender();
165+
166+
comboBox.close();
167+
comboBox.itemClassNameGenerator = () => '';
168+
169+
comboBox.open();
170+
await nextRender();
171+
172+
const items = getAllItems(comboBox);
173+
expect(items[0].className).to.equal('');
174+
expect(items[1].className).to.equal('');
175+
expect(items[2].className).to.equal('');
176+
});
177+
178+
it('should remove class name when generator is set to null', async () => {
179+
comboBox.itemClassNameGenerator = (item) => `item-${item}`;
180+
comboBox.open();
181+
await nextRender();
182+
183+
comboBox.close();
184+
comboBox.itemClassNameGenerator = null;
185+
186+
comboBox.open();
187+
await nextRender();
188+
189+
const items = getAllItems(comboBox);
190+
expect(items[0].className).to.equal('');
191+
expect(items[1].className).to.equal('');
192+
expect(items[2].className).to.equal('');
193+
});
194+
});
195+
});

0 commit comments

Comments
 (0)