Skip to content

Commit

Permalink
fix(checkbox): emit odsChange with matching checkbox values
Browse files Browse the repository at this point in the history
  • Loading branch information
dpellier committed Nov 28, 2024
1 parent 935aef5 commit 8525df8
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,16 @@ export class OdsCheckbox {

@Method()
public async clear(): Promise<void> {
const hasChange = this.inputEl?.checked === true;
if (this.inputEl) {
this.inputEl.checked = false;
}
this.odsClear.emit();
hasChange && this.onInput();
this.odsChange.emit({
checked: false,
name: this.name,
validity: this.inputEl?.validity,
value: this.value ?? null,
});
this.inputEl?.focus();
}

Expand All @@ -65,20 +69,27 @@ export class OdsCheckbox {

@Method()
public async reset(): Promise<void> {
const hasChange = this.inputEl?.checked !== this.isChecked;
const defaultCheckedValues: string[] = [];

this.getOdsCheckboxGroupByName().forEach((checkbox) => {
const inputCheckbox = checkbox.querySelector<HTMLInputElement>('input[type="checkbox"]');
if (!inputCheckbox) {
return;
}
if (checkbox.getAttribute('is-checked') !== null && checkbox.getAttribute('is-checked') !== 'false') {
inputCheckbox.checked = true;
defaultCheckedValues.push(inputCheckbox.value);
} else {
inputCheckbox.checked = false;
}
});
this.odsReset.emit();
hasChange && this.onInput();
this.odsChange.emit({
checked: !!defaultCheckedValues.length,
name: this.name,
validity: this.inputEl?.validity,
value: defaultCheckedValues.length ? defaultCheckedValues.join(',') : (this.value ?? null),
});
}

@Method()
Expand Down Expand Up @@ -123,11 +134,28 @@ export class OdsCheckbox {
}

private onInput(): void {
const { checked, validity, values } = Array.from(this.getOdsCheckboxGroupByName())
.reduce<{ checked: boolean, validity: ValidityState | undefined, values: string[] }>((res, odsCheckboxElement) => {
const inputElement = odsCheckboxElement.querySelector<HTMLInputElement>('input[type="checkbox"]');

if (inputElement && inputElement.checked) {
res.checked = true;
res.validity = inputElement.validity;
res.values.push(inputElement.value);
}

return res;
}, {
checked: false,
validity: this.inputEl?.validity,
values: [],
});

this.odsChange.emit({
checked: this.inputEl?.checked ?? false,
checked,
name: this.name,
validity: this.inputEl?.validity,
value: this.value ?? null,
validity,
value: values.length ? values.join(',') : (this.value ?? null),
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { E2EElement, E2EPage } from '@stencil/core/testing';
import { newE2EPage } from '@stencil/core/testing';
import { type E2EElement, type E2EPage, newE2EPage } from '@stencil/core/testing';

describe('ods-checkbox behavior', () => {
describe('ods-checkbox behaviour', () => {
let el: E2EElement;
let page: E2EPage;

Expand All @@ -23,75 +22,100 @@ describe('ods-checkbox behavior', () => {
el = await page.find('ods-checkbox');
}

describe('Methods', () => {
describe('methods', () => {
describe('clear', () => {
it('should receive odsClear event', async() => {
await setup('<ods-checkbox value="value" is-checked></ods-checkbox>');
await setup('<ods-checkbox name="ods-checkbox" value="value" is-checked></ods-checkbox>');
const odsClearSpy = await page.spyOnEvent('odsClear');
const odsChangeSpy = await page.spyOnEvent('odsChange');
expect(await isInputCheckboxChecked(el)).toBe(true);
await el.callMethod('clear');
await page.waitForChanges();

expect(await isInputCheckboxChecked(el)).toBe(false);
expect(odsClearSpy).toHaveReceivedEventTimes(1);
expect(odsChangeSpy).toHaveReceivedEventTimes(1);
});

it('should receive odsClear event but not odsChange if there are no change', async() => {
await setup('<ods-checkbox value="value"></ods-checkbox>');
const odsClearSpy = await page.spyOnEvent('odsClear');
const odsChangeSpy = await page.spyOnEvent('odsChange');
expect(await isInputCheckboxChecked(el)).toBe(false);
expect(await isInputCheckboxChecked(el)).toBe(true);

await el.callMethod('clear');
await page.waitForChanges();

expect(await isInputCheckboxChecked(el)).toBe(false);
expect(odsClearSpy).toHaveReceivedEventTimes(1);
expect(odsChangeSpy).toHaveReceivedEventTimes(0);
expect(odsChangeSpy).toHaveReceivedEventTimes(1);
expect(odsChangeSpy).toHaveReceivedEventDetail({
checked: false,
name: 'ods-checkbox',
validity: {},
value: 'value',
});
});
});

describe('reset', () => {
it('should receive odsReset event but not odsChange if there are no change', async() => {
await setup('<ods-checkbox value="value"></ods-checkbox>');
it('should receive odsReset event', async() => {
await setup('<ods-checkbox name="ods-checkbox" value="value" is-checked></ods-checkbox>');
const odsResetSpy = await page.spyOnEvent('odsReset');
const odsChangeSpy = await page.spyOnEvent('odsChange');
expect(await isInputCheckboxChecked(el)).toBe(false);

expect(await isInputCheckboxChecked(el)).toBe(true);

await el.callMethod('reset');
await page.waitForChanges();

expect(await isInputCheckboxChecked(el)).toBe(false);
expect(await isInputCheckboxChecked(el)).toBe(true);

expect(odsResetSpy).toHaveReceivedEventTimes(1);
expect(odsChangeSpy).toHaveReceivedEventTimes(0);
expect(odsChangeSpy).toHaveReceivedEventTimes(1);

expect(odsChangeSpy).toHaveReceivedEventDetail({
checked: true,
name: 'ods-checkbox',
validity: {},
value: 'value',
});
});

it('should checked the checkbox with is-checked after reset', async() => {
await setup(`<ods-checkbox name="checkbox-group" value="value1" is-checked></ods-checkbox>
<ods-checkbox name="checkbox-group" value="value2"></ods-checkbox>
<ods-checkbox name="checkbox-group" value="value3"></ods-checkbox>`);
const checkboxGroup = await page.findAll('ods-checkbox');
const odsResetSpy = await page.spyOnEvent('odsReset');
const odsChangeSpy = await page.spyOnEvent('odsChange');

expect(await isInputCheckboxChecked(checkboxGroup[0])).toBe(true);

await checkboxGroup[2].click();

expect(await isInputCheckboxChecked(checkboxGroup[2])).toBe(true);

await checkboxGroup[2].callMethod('reset');
await page.waitForChanges();

expect(await isInputCheckboxChecked(checkboxGroup[0])).toBe(true);
expect(await isInputCheckboxChecked(checkboxGroup[2])).toBe(false);
expect(odsResetSpy).toHaveReceivedEventTimes(1);
expect(odsChangeSpy).toHaveReceivedEventTimes(2);
});

it('should send an odsChange with correct values for each item on form reset', async() => {
await setup(`<form method="get">
<ods-checkbox name="checkbox-group" value="value1" is-checked></ods-checkbox>
<ods-checkbox name="checkbox-group" value="value2" is-checked></ods-checkbox>
<ods-checkbox name="checkbox-group" value="value3"></ods-checkbox>
<button type="reset">Reset</button>
</form>`);
const resetButton = await page.find('button[type="reset"]');
const odsResetSpy = await page.spyOnEvent('odsReset');
const odsChangeSpy = await page.spyOnEvent('odsChange');

await resetButton.click();
await page.waitForChanges();

expect(odsResetSpy).toHaveReceivedEventTimes(3);
expect(odsChangeSpy).toHaveReceivedEventTimes(3);
expect(odsChangeSpy).toHaveReceivedEventDetail({
checked: true,
name: 'checkbox-group',
validity: {},
value: 'value1,value2',
});
});
});
});

describe('Checkbox group', () => {
describe('checkbox group', () => {
it('should select multiple checkbox', async() => {
await setup('<ods-checkbox name="checkbox-group" value="value1" is-checked></ods-checkbox><ods-checkbox name="checkbox-group" value="value2"></ods-checkbox><ods-checkbox name="checkbox-group" value="value3"></ods-checkbox>');
const checkboxGroup = await page.findAll('ods-checkbox');
Expand All @@ -104,7 +128,7 @@ describe('ods-checkbox behavior', () => {
});
});

describe('Event', () => {
describe('events', () => {
it('should receive event odsChange', async() => {
await setup('<ods-checkbox value="value" name="name"></ods-checkbox>');
const odsChangeSpy = await page.spyOnEvent('odsChange');
Expand All @@ -122,7 +146,7 @@ describe('ods-checkbox behavior', () => {
});
});

describe('Form', () => {
describe('form', () => {
it('should get form data with button type submit', async() => {
await setup(`<form method="get">
<ods-checkbox input-id="checkbox-form" name="name" value="coding" is-checked></ods-checkbox>
Expand Down

0 comments on commit 8525df8

Please sign in to comment.