Skip to content

Commit de1558d

Browse files
authored
test: merge combo-box item renderer and class name generator tests (#10241)
1 parent c948aae commit de1558d

File tree

6 files changed

+384
-327
lines changed

6 files changed

+384
-327
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: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
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+
let comboBox;
146+
147+
beforeEach(async () => {
148+
comboBox = fixtureSync('<vaadin-combo-box></vaadin-combo-box>');
149+
await nextRender();
150+
comboBox.items = ['foo', 'bar', 'baz'];
151+
});
152+
153+
it('should set class name on dropdown items', async () => {
154+
comboBox.itemClassNameGenerator = (item) => `item-${item}`;
155+
comboBox.open();
156+
await nextRender();
157+
const items = getAllItems(comboBox);
158+
expect(items[0].className).to.equal('item-foo');
159+
expect(items[1].className).to.equal('item-bar');
160+
expect(items[2].className).to.equal('item-baz');
161+
});
162+
163+
it('should remove class name when return value is empty string', async () => {
164+
comboBox.itemClassNameGenerator = (item) => `item-${item}`;
165+
comboBox.open();
166+
await nextRender();
167+
168+
comboBox.close();
169+
comboBox.itemClassNameGenerator = () => '';
170+
171+
comboBox.open();
172+
await nextRender();
173+
174+
const items = getAllItems(comboBox);
175+
expect(items[0].className).to.equal('');
176+
expect(items[1].className).to.equal('');
177+
expect(items[2].className).to.equal('');
178+
});
179+
180+
it('should remove class name when generator is set to null', async () => {
181+
comboBox.itemClassNameGenerator = (item) => `item-${item}`;
182+
comboBox.open();
183+
await nextRender();
184+
185+
comboBox.close();
186+
comboBox.itemClassNameGenerator = null;
187+
188+
comboBox.open();
189+
await nextRender();
190+
191+
const items = getAllItems(comboBox);
192+
expect(items[0].className).to.equal('');
193+
expect(items[1].className).to.equal('');
194+
expect(items[2].className).to.equal('');
195+
});
196+
});
197+
});

0 commit comments

Comments
 (0)