Skip to content

Commit e51f202

Browse files
committed
Add tests for checkbox and select multiple cases
1 parent f342a7a commit e51f202

File tree

1 file changed

+197
-1
lines changed

1 file changed

+197
-1
lines changed

src/LiveComponent/assets/test/controller/model.test.ts

Lines changed: 197 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
import { clearDOM } from '@symfony/stimulus-testing';
1313
import { initLiveComponent, mockRerender, startStimulus } from '../tools';
14-
import {getByLabelText, getByText, waitFor} from '@testing-library/dom';
14+
import { getByLabelText, getByText, waitFor } from '@testing-library/dom';
1515
import userEvent from '@testing-library/user-event';
1616
import fetchMock from 'fetch-mock-jest';
1717

@@ -238,6 +238,202 @@ describe('LiveController data-model Tests', () => {
238238
fetchMock.done();
239239
});
240240

241+
it('sends correct data for initially checked checkbox fields', async () => {
242+
const checkboxTemplate = (data: any) => `
243+
<div
244+
${initLiveComponent('/_components/my_component', data)}
245+
data-action="change->live#update"
246+
>
247+
<label>
248+
Checkbox 1: <input type="checkbox" name="form[check1]" value="1" ${data.form.check1 ? 'checked' : ''} />
249+
</label>
250+
251+
<label>
252+
Checkbox 2: <input type="checkbox" name="form[check2]" value="1" ${data.form.check2 ? 'checked' : ''} />
253+
</label>
254+
255+
Checkbox 1 is ${data.form.check1 ? 'checked' : 'unchecked' }
256+
</div>
257+
`;
258+
const data = { form: { check1: '1', check2: false} };
259+
const { element, controller } = await startStimulus(checkboxTemplate(data));
260+
261+
const check1Element = getByLabelText(element, 'Checkbox 1:');
262+
const check2Element = getByLabelText(element, 'Checkbox 2:');
263+
264+
// no mockRerender needed... not sure why. This first Ajax call is likely
265+
// interrupted by the next immediately starting
266+
await userEvent.click(check2Element);
267+
268+
mockRerender({ form: {check1: null, check2: '1'}}, checkboxTemplate);
269+
270+
await userEvent.click(check1Element);
271+
await waitFor(() => expect(element).toHaveTextContent('Checkbox 1 is unchecked'));
272+
273+
expect(controller.dataValue).toEqual({form: {check1: null, check2: '1'}});
274+
275+
// assert all calls were done the correct number of times
276+
fetchMock.done();
277+
});
278+
279+
it('sends correct data for array valued checkbox fields', async () => {
280+
const checkboxTemplate = (data: any) => `
281+
<div
282+
${initLiveComponent('/_components/my_component', data)}
283+
data-action="change->live#update"
284+
>
285+
<label>
286+
Checkbox 1: <input type="checkbox" name="form[check][]" value="foo" ${data.form.check.indexOf('foo') > -1 ? 'checked' : ''} />
287+
</label>
288+
289+
<label>
290+
Checkbox 2: <input type="checkbox" name="form[check][]" value="bar" ${data.form.check.indexOf('bar') > -1 ? 'checked' : ''} />
291+
</label>
292+
293+
Checkbox 2 is ${data.form.check.indexOf('bar') > -1 ? 'checked' : 'unchecked' }
294+
</div>
295+
`;
296+
const data = { form: { check: []} };
297+
const { element, controller } = await startStimulus(checkboxTemplate(data));
298+
299+
const check1Element = getByLabelText(element, 'Checkbox 1:');
300+
const check2Element = getByLabelText(element, 'Checkbox 2:');
301+
302+
// no mockRerender needed... not sure why. This first Ajax call is likely
303+
// interrupted by the next immediately starting
304+
await userEvent.click(check1Element);
305+
306+
mockRerender({ form: {check: ['foo', 'bar']}}, checkboxTemplate);
307+
308+
await userEvent.click(check2Element);
309+
await waitFor(() => expect(element).toHaveTextContent('Checkbox 2 is checked'));
310+
311+
expect(controller.dataValue).toEqual({form: {check: ['foo', 'bar']}});
312+
313+
// assert all calls were done the correct number of times
314+
fetchMock.done();
315+
});
316+
317+
it('sends correct data for array valued checkbox fields with initial data', async () => {
318+
const checkboxTemplate = (data: any) => `
319+
<div
320+
${initLiveComponent('/_components/my_component', data)}
321+
data-action="change->live#update"
322+
>
323+
<label>
324+
Checkbox 1: <input type="checkbox" name="form[check][]" value="foo" ${data.form.check.indexOf('foo') > -1 ? 'checked' : ''} />
325+
</label>
326+
327+
<label>
328+
Checkbox 2: <input type="checkbox" name="form[check][]" value="bar" ${data.form.check.indexOf('bar') > -1 ? 'checked' : ''} />
329+
</label>
330+
331+
Checkbox 1 is ${data.form.check.indexOf('foo') > -1 ? 'checked' : 'unchecked' }
332+
</div>
333+
`;
334+
const data = { form: { check: ['foo']} };
335+
const { element, controller } = await startStimulus(checkboxTemplate(data));
336+
337+
const check1Element = getByLabelText(element, 'Checkbox 1:');
338+
const check2Element = getByLabelText(element, 'Checkbox 2:');
339+
340+
// no mockRerender needed... not sure why. This first Ajax call is likely
341+
// interrupted by the next immediately starting
342+
await userEvent.click(check2Element);
343+
344+
mockRerender({ form: {check: ['bar']}}, checkboxTemplate);
345+
346+
await userEvent.click(check1Element);
347+
await waitFor(() => expect(element).toHaveTextContent('Checkbox 1 is unchecked'));
348+
349+
expect(controller.dataValue).toEqual({form: {check: ['bar']}});
350+
351+
// assert all calls were done the correct number of times
352+
fetchMock.done();
353+
});
354+
355+
it('sends correct data for select multiple field', async () => {
356+
const checkboxTemplate = (data: any) => `
357+
<div
358+
${initLiveComponent('/_components/my_component', data)}
359+
data-action="change->live#update"
360+
>
361+
<label>
362+
Select:
363+
<select name="form[select][]" multiple>
364+
<option value="foo" ${data.form.select.indexOf('foo') > -1 ? 'selected' : ''}>foo</option>
365+
<option value="bar" ${data.form.select.indexOf('bar') > -1 ? 'selected' : ''}>bar</option>
366+
</select>
367+
</label>
368+
369+
Option 2 is ${data.form.select.indexOf('bar') > -1 ? 'selected' : 'unselected' }
370+
</div>
371+
`;
372+
const data = { form: { select: []} };
373+
const { element, controller } = await startStimulus(checkboxTemplate(data));
374+
375+
const selectElement = getByLabelText(element, 'Select:');
376+
377+
// no mockRerender needed... not sure why. This first Ajax call is likely
378+
// interrupted by the next immediately starting
379+
await userEvent.selectOptions(selectElement, 'foo');
380+
381+
mockRerender({ form: {select: ['foo', 'bar']}}, checkboxTemplate);
382+
383+
await userEvent.selectOptions(selectElement, 'bar');
384+
385+
await waitFor(() => expect(element).toHaveTextContent('Select: foo bar Option 2 is selected'));
386+
387+
expect(controller.dataValue).toEqual({form: {select: ['foo', 'bar']}});
388+
389+
// assert all calls were done the correct number of times
390+
fetchMock.done();
391+
});
392+
393+
it('sends correct data for select multiple field with initial data', async () => {
394+
const checkboxTemplate = (data: any) => `
395+
<div
396+
${initLiveComponent('/_components/my_component', data)}
397+
data-action="change->live#update"
398+
>
399+
<label>
400+
Select:
401+
<select name="form[select][]" multiple>
402+
<option value="foo" ${data.form.select.indexOf('foo') > -1 ? 'selected' : ''}>foo</option>
403+
<option value="bar" ${data.form.select.indexOf('bar') > -1 ? 'selected' : ''}>bar</option>
404+
</select>
405+
</label>
406+
407+
Option 2 is ${data.form.select.indexOf('bar') > -1 ? 'selected' : 'unselected' }
408+
</div>
409+
`;
410+
const data = { form: { select: ['foo']} };
411+
const { element, controller } = await startStimulus(checkboxTemplate(data));
412+
413+
const selectElement = getByLabelText(element, 'Select:');
414+
415+
// no mockRerender needed... not sure why. This first Ajax call is likely
416+
// interrupted by the next immediately starting
417+
await userEvent.selectOptions(selectElement, 'bar');
418+
419+
mockRerender({ form: {select: ['bar']}}, checkboxTemplate);
420+
421+
await userEvent.deselectOptions(selectElement, 'foo');
422+
423+
await waitFor(() => expect(element).toHaveTextContent('Select: foo bar Option 2 is selected'));
424+
425+
mockRerender({ form: {select: null}}, checkboxTemplate);
426+
427+
await userEvent.deselectOptions(selectElement, 'bar');
428+
429+
await waitFor(() => expect(element).toHaveTextContent('Select: foo bar Option 2 is deselected'));
430+
431+
expect(controller.dataValue).toEqual({form: {select: null}});
432+
433+
// assert all calls were done the correct number of times
434+
fetchMock.done();
435+
});
436+
241437
it('updates correctly when live#update is on a parent element', async () => {
242438
const parentUpdateTemplate = (data) => `
243439
<div

0 commit comments

Comments
 (0)