add validation tests; fixes #1065

This commit is contained in:
Cory LaViska
2023-01-10 15:05:44 -05:00
parent 62c58b3a8c
commit 68ed69292c
8 changed files with 407 additions and 67 deletions

View File

@@ -1,6 +1,7 @@
import { aTimeout, expect, fixture, html, oneEvent, waitUntil } from '@open-wc/testing';
import { expect, fixture, html, oneEvent, waitUntil } from '@open-wc/testing';
import { sendKeys } from '@web/test-runner-commands';
import sinon from 'sinon';
import { clickOnElement } from '../../internal/test';
import type SlCheckbox from './checkbox';
describe('<sl-checkbox>', () => {
@@ -48,8 +49,7 @@ describe('<sl-checkbox>', () => {
it('should be valid by default', async () => {
const el = await fixture<SlCheckbox>(html` <sl-checkbox></sl-checkbox> `);
expect(el.invalid).to.be.false;
expect(el.checkValidity()).to.be.true;
});
it('should emit sl-change and sl-input when clicked', async () => {
@@ -139,25 +139,35 @@ describe('<sl-checkbox>', () => {
expect(formData!.get('a')).to.equal('on');
});
it('should show a constraint validation error when setCustomValidity() is called', async () => {
const form = await fixture<HTMLFormElement>(html`
<form>
<sl-checkbox name="a" value="1" checked></sl-checkbox>
<sl-button type="submit">Submit</sl-button>
</form>
`);
const button = form.querySelector('sl-button')!;
const checkbox = form.querySelector('sl-checkbox')!;
const submitHandler = sinon.spy((event: SubmitEvent) => event.preventDefault());
it('should be invalid when setCustomValidity() is called with a non-empty value', async () => {
const checkbox = await fixture<HTMLFormElement>(html` <sl-checkbox></sl-checkbox> `);
// Submitting the form after setting custom validity should not trigger the handler
checkbox.setCustomValidity('Invalid selection');
form.addEventListener('submit', submitHandler);
button.click();
await checkbox.updateComplete;
await aTimeout(100);
expect(checkbox.checkValidity()).to.be.false;
expect(checkbox.checkValidity()).to.be.false;
expect(checkbox.hasAttribute('data-invalid')).to.be.true;
expect(checkbox.hasAttribute('data-valid')).to.be.false;
expect(checkbox.hasAttribute('data-user-invalid')).to.be.false;
expect(checkbox.hasAttribute('data-user-valid')).to.be.false;
expect(submitHandler).to.not.have.been.called;
await clickOnElement(checkbox);
await checkbox.updateComplete;
expect(checkbox.hasAttribute('data-user-invalid')).to.be.true;
expect(checkbox.hasAttribute('data-user-valid')).to.be.false;
});
it('should be invalid when required and unchecked', async () => {
const checkbox = await fixture<HTMLFormElement>(html` <sl-checkbox required></sl-checkbox> `);
expect(checkbox.checkValidity()).to.be.false;
});
it('should be valid when required and checked', async () => {
const checkbox = await fixture<HTMLFormElement>(html` <sl-checkbox required checked></sl-checkbox> `);
expect(checkbox.checkValidity()).to.be.true;
});
});

View File

@@ -352,4 +352,62 @@ describe('<sl-color-picker>', () => {
expect(colorPicker.value).to.equal('');
});
});
describe('when using constraint validation', () => {
it('should be valid by default', async () => {
const el = await fixture<SlColorPicker>(html` <sl-color-picker></sl-color-picker> `);
expect(el.checkValidity()).to.be.true;
});
it('should be invalid when required and empty', async () => {
const el = await fixture<SlColorPicker>(html` <sl-input required></sl-input> `);
expect(el.checkValidity()).to.be.false;
});
it('should be invalid when required and disabled is removed', async () => {
const el = await fixture<SlColorPicker>(html` <sl-input disabled required></sl-input> `);
el.disabled = false;
await el.updateComplete;
expect(el.checkValidity()).to.be.false;
});
it('should receive the correct validation attributes ("states") when valid', async () => {
const el = await fixture<SlColorPicker>(html` <sl-input required value="a"></sl-input> `);
expect(el.checkValidity()).to.be.true;
expect(el.hasAttribute('data-required')).to.be.true;
expect(el.hasAttribute('data-optional')).to.be.false;
expect(el.hasAttribute('data-invalid')).to.be.false;
expect(el.hasAttribute('data-valid')).to.be.true;
expect(el.hasAttribute('data-user-invalid')).to.be.false;
expect(el.hasAttribute('data-user-valid')).to.be.false;
el.focus();
await sendKeys({ press: 'b' });
await el.updateComplete;
expect(el.checkValidity()).to.be.true;
expect(el.hasAttribute('data-user-invalid')).to.be.false;
expect(el.hasAttribute('data-user-valid')).to.be.true;
});
it('should receive the correct validation attributes ("states") when invalid', async () => {
const el = await fixture<SlColorPicker>(html` <sl-input required></sl-input> `);
expect(el.hasAttribute('data-required')).to.be.true;
expect(el.hasAttribute('data-optional')).to.be.false;
expect(el.hasAttribute('data-invalid')).to.be.true;
expect(el.hasAttribute('data-valid')).to.be.false;
expect(el.hasAttribute('data-user-invalid')).to.be.false;
expect(el.hasAttribute('data-user-valid')).to.be.false;
el.focus();
await sendKeys({ press: 'a' });
await sendKeys({ press: 'Backspace' });
await el.updateComplete;
expect(el.hasAttribute('data-user-invalid')).to.be.true;
expect(el.hasAttribute('data-user-valid')).to.be.false;
});
});
});

View File

@@ -85,38 +85,73 @@ describe('<sl-input>', () => {
it('should focus the input when clicking on the label', async () => {
const el = await fixture<SlInput>(html` <sl-input label="Name"></sl-input> `);
const label = el.shadowRoot!.querySelector('[part~="form-control-label"]')!;
const submitHandler = sinon.spy();
const focusHandler = sinon.spy();
el.addEventListener('sl-focus', submitHandler);
el.addEventListener('sl-focus', focusHandler);
(label as HTMLLabelElement).click();
await waitUntil(() => submitHandler.calledOnce);
await waitUntil(() => focusHandler.calledOnce);
expect(submitHandler).to.have.been.calledOnce;
expect(focusHandler).to.have.been.calledOnce;
});
describe('when using constraint validation', () => {
it('should be valid by default', async () => {
const el = await fixture<SlInput>(html` <sl-input></sl-input> `);
expect(el.invalid).to.be.false;
expect(el.checkValidity()).to.be.true;
});
it('should be invalid when required and empty', async () => {
const el = await fixture<SlInput>(html` <sl-input required></sl-input> `);
expect(el.reportValidity()).to.be.false;
expect(el.invalid).to.be.true;
});
it('should be invalid when the pattern does not match', async () => {
const el = await fixture<SlInput>(html` <sl-input pattern="^test" value="fail"></sl-input> `);
expect(el.invalid).to.be.true;
expect(el.reportValidity()).to.be.false;
expect(el.checkValidity()).to.be.false;
});
it('should be invalid when required and disabled is removed', async () => {
const el = await fixture<SlInput>(html` <sl-input disabled required></sl-input> `);
el.disabled = false;
await el.updateComplete;
expect(el.invalid).to.be.true;
expect(el.checkValidity()).to.be.false;
});
it('should receive the correct validation attributes ("states") when valid', async () => {
const el = await fixture<SlInput>(html` <sl-input required value="a"></sl-input> `);
expect(el.checkValidity()).to.be.true;
expect(el.hasAttribute('data-required')).to.be.true;
expect(el.hasAttribute('data-optional')).to.be.false;
expect(el.hasAttribute('data-invalid')).to.be.false;
expect(el.hasAttribute('data-valid')).to.be.true;
expect(el.hasAttribute('data-user-invalid')).to.be.false;
expect(el.hasAttribute('data-user-valid')).to.be.false;
el.focus();
await el.updateComplete;
await sendKeys({ press: 'b' });
await el.updateComplete;
expect(el.checkValidity()).to.be.true;
expect(el.hasAttribute('data-user-invalid')).to.be.false;
expect(el.hasAttribute('data-user-valid')).to.be.true;
});
it('should receive the correct validation attributes ("states") when invalid', async () => {
const el = await fixture<SlInput>(html` <sl-input required></sl-input> `);
expect(el.hasAttribute('data-required')).to.be.true;
expect(el.hasAttribute('data-optional')).to.be.false;
expect(el.hasAttribute('data-invalid')).to.be.true;
expect(el.hasAttribute('data-valid')).to.be.false;
expect(el.hasAttribute('data-user-invalid')).to.be.false;
expect(el.hasAttribute('data-user-valid')).to.be.false;
el.focus();
await el.updateComplete;
await sendKeys({ press: 'a' });
await sendKeys({ press: 'Backspace' });
await el.updateComplete;
expect(el.hasAttribute('data-user-invalid')).to.be.true;
expect(el.hasAttribute('data-user-valid')).to.be.false;
});
});
@@ -167,6 +202,26 @@ describe('<sl-input>', () => {
expect(keydownHandler).to.have.been.calledOnce;
expect(submitHandler).to.not.have.been.called;
});
it('should be invalid when setCustomValidity() is called with a non-empty value', async () => {
const input = await fixture<HTMLFormElement>(html` <sl-input></sl-input> `);
input.setCustomValidity('Invalid selection');
await input.updateComplete;
expect(input.checkValidity()).to.be.false;
expect(input.hasAttribute('data-invalid')).to.be.true;
expect(input.hasAttribute('data-valid')).to.be.false;
expect(input.hasAttribute('data-user-invalid')).to.be.false;
expect(input.hasAttribute('data-user-valid')).to.be.false;
input.focus();
await sendKeys({ type: 'test' });
await input.updateComplete;
expect(input.hasAttribute('data-user-invalid')).to.be.true;
expect(input.hasAttribute('data-user-valid')).to.be.false;
});
});
describe('when resetting a form', () => {
@@ -261,7 +316,7 @@ describe('<sl-input>', () => {
await el.updateComplete;
});
it('should not emit sl-change or sl-input when calling setRangeText()', async () => {
it('should not emit sl-change or sl-input when calling setinputText()', async () => {
const el = await fixture<SlInput>(html` <sl-input value="hi there"></sl-input> `);
el.addEventListener('sl-change', () => expect.fail('sl-change should not be emitted'));
@@ -277,21 +332,21 @@ describe('<sl-input>', () => {
describe('when type="number"', () => {
it('should be valid when the value is within the boundary of a step', async () => {
const el = await fixture<SlInput>(html` <sl-input type="number" step=".5" value="1.5"></sl-input> `);
expect(el.invalid).to.be.false;
expect(el.checkValidity()).to.be.true;
});
it('should be invalid when the value is not within the boundary of a step', async () => {
const el = await fixture<SlInput>(html` <sl-input type="number" step=".5" value="1.25"></sl-input> `);
expect(el.invalid).to.be.true;
expect(el.checkValidity()).to.be.false;
});
it('should update validity when step changes', async () => {
const el = await fixture<SlInput>(html` <sl-input type="number" step=".5" value="1.5"></sl-input> `);
expect(el.invalid).to.be.false;
expect(el.checkValidity()).to.be.true;
el.step = 1;
await el.updateComplete;
expect(el.invalid).to.be.true;
expect(el.checkValidity()).to.be.false;
});
it('should increment by step when stepUp() is called', async () => {

View File

@@ -1,6 +1,7 @@
import { aTimeout, expect, fixture, html, oneEvent, waitUntil } from '@open-wc/testing';
import { sendKeys } from '@web/test-runner-commands';
import sinon from 'sinon';
import { clickOnElement } from '../../internal/test';
import type SlRadio from '../radio/radio';
import type SlRadioGroup from './radio-group';
@@ -14,7 +15,7 @@ describe('<sl-radio-group>', () => {
</sl-radio-group>
`);
expect(radioGroup.invalid).to.be.true;
expect(radioGroup.checkValidity()).to.be.false;
});
it('should become valid when an option is checked', async () => {
@@ -28,7 +29,7 @@ describe('<sl-radio-group>', () => {
radioGroup.value = '1';
await radioGroup.updateComplete;
expect(radioGroup.invalid).to.be.false;
expect(radioGroup.checkValidity()).to.be.true;
});
it(`should be valid when required and one radio is checked`, async () => {
@@ -40,7 +41,7 @@ describe('<sl-radio-group>', () => {
</sl-radio-group>
`);
expect(el.reportValidity()).to.be.true;
expect(el.checkValidity()).to.be.true;
});
it(`should be invalid when required and no radios are checked`, async () => {
@@ -52,7 +53,7 @@ describe('<sl-radio-group>', () => {
</sl-radio-group>
`);
expect(el.reportValidity()).to.be.false;
expect(el.checkValidity()).to.be.false;
});
it(`should be valid when required and a different radio is checked`, async () => {
@@ -64,7 +65,7 @@ describe('<sl-radio-group>', () => {
</sl-radio-group>
`);
expect(el.reportValidity()).to.be.true;
expect(el.checkValidity()).to.be.true;
});
it(`should be invalid when custom validity is set`, async () => {
@@ -78,15 +79,64 @@ describe('<sl-radio-group>', () => {
el.setCustomValidity('Error');
expect(el.reportValidity()).to.be.false;
expect(el.checkValidity()).to.be.false;
});
it('should receive the correct validation attributes ("states") when valid', async () => {
const radioGroup = await fixture<SlRadioGroup>(html`
<sl-radio-group value="1" required>
<sl-radio value="1"></sl-radio>
<sl-radio value="2"></sl-radio>
</sl-radio-group>
`);
const secondRadio = radioGroup.querySelectorAll('sl-radio')[1];
expect(radioGroup.checkValidity()).to.be.true;
expect(radioGroup.hasAttribute('data-required')).to.be.true;
expect(radioGroup.hasAttribute('data-optional')).to.be.false;
expect(radioGroup.hasAttribute('data-invalid')).to.be.false;
expect(radioGroup.hasAttribute('data-valid')).to.be.true;
expect(radioGroup.hasAttribute('data-user-invalid')).to.be.false;
expect(radioGroup.hasAttribute('data-user-valid')).to.be.false;
await clickOnElement(secondRadio);
await secondRadio.updateComplete;
expect(radioGroup.checkValidity()).to.be.true;
expect(radioGroup.hasAttribute('data-user-invalid')).to.be.false;
expect(radioGroup.hasAttribute('data-user-valid')).to.be.true;
});
it('should receive the correct validation attributes ("states") when invalid', async () => {
const radioGroup = await fixture<SlRadioGroup>(html`
<sl-radio-group required>
<sl-radio value="1"></sl-radio>
<sl-radio value="2"></sl-radio>
</sl-radio-group>
`);
const secondRadio = radioGroup.querySelectorAll('sl-radio')[1];
expect(radioGroup.hasAttribute('data-required')).to.be.true;
expect(radioGroup.hasAttribute('data-optional')).to.be.false;
expect(radioGroup.hasAttribute('data-invalid')).to.be.true;
expect(radioGroup.hasAttribute('data-valid')).to.be.false;
expect(radioGroup.hasAttribute('data-user-invalid')).to.be.false;
expect(radioGroup.hasAttribute('data-user-valid')).to.be.false;
await clickOnElement(secondRadio);
radioGroup.value = '';
await radioGroup.updateComplete;
expect(radioGroup.hasAttribute('data-user-invalid')).to.be.true;
expect(radioGroup.hasAttribute('data-user-valid')).to.be.false;
});
});
it('should show a constraint validation error when setCustomValidity() is called', async () => {
const form = await fixture<HTMLFormElement>(html`
<form>
<sl-radio-group>
<sl-radio id="radio-1" name="a" value="1" checked></sl-radio>
<sl-radio-group value="1">
<sl-radio id="radio-1" name="a" value="1"></sl-radio>
<sl-radio id="radio-2" name="a" value="2"></sl-radio>
</sl-radio-group>
<sl-button type="submit">Submit</sl-button>

View File

@@ -20,7 +20,7 @@ describe('<sl-range>', () => {
expect(el.label).to.equal('');
expect(el.helpText).to.equal('');
expect(el.disabled).to.be.false;
expect(el.invalid).to.be.false;
expect(el.checkValidity()).to.be.true;
expect(el.min).to.equal(0);
expect(el.max).to.equal(100);
expect(el.step).to.equal(1);
@@ -137,6 +137,27 @@ describe('<sl-range>', () => {
});
});
describe('when submitting a form', () => {
it('should be invalid when setCustomValidity() is called with a non-empty value', async () => {
const range = await fixture<HTMLFormElement>(html` <sl-range></sl-range> `);
range.setCustomValidity('Invalid selection');
await range.updateComplete;
expect(range.checkValidity()).to.be.false;
expect(range.hasAttribute('data-invalid')).to.be.true;
expect(range.hasAttribute('data-valid')).to.be.false;
expect(range.hasAttribute('data-user-invalid')).to.be.false;
expect(range.hasAttribute('data-user-valid')).to.be.false;
await clickOnElement(range);
await range.updateComplete;
expect(range.hasAttribute('data-user-invalid')).to.be.true;
expect(range.hasAttribute('data-user-valid')).to.be.false;
});
});
describe('when serializing', () => {
it('should serialize its name and value with FormData', async () => {
const form = await fixture<HTMLFormElement>(html` <form><sl-range name="a" value="1"></sl-range></form> `);

View File

@@ -241,6 +241,59 @@ describe('<sl-select>', () => {
el.requestSubmit();
expect(select.shadowRoot!.activeElement).to.equal(select.displayInput);
});
it('should receive the correct validation attributes ("states") when valid', async () => {
const el = await fixture<SlSelect>(html`
<sl-select label="Select one" required value="option-1">
<sl-option value="option-1">Option 1</sl-option>
<sl-option value="option-2">Option 2</sl-option>
<sl-option value="option-3">Option 3</sl-option>
</sl-select>
`);
const secondOption = el.querySelectorAll('sl-option')[1]!;
expect(el.checkValidity()).to.be.true;
expect(el.hasAttribute('data-required')).to.be.true;
expect(el.hasAttribute('data-optional')).to.be.false;
expect(el.hasAttribute('data-invalid')).to.be.false;
expect(el.hasAttribute('data-valid')).to.be.true;
expect(el.hasAttribute('data-user-invalid')).to.be.false;
expect(el.hasAttribute('data-user-valid')).to.be.false;
await el.show();
await clickOnElement(secondOption);
await el.updateComplete;
expect(el.checkValidity()).to.be.true;
expect(el.hasAttribute('data-user-invalid')).to.be.false;
expect(el.hasAttribute('data-user-valid')).to.be.true;
});
it('should receive the correct validation attributes ("states") when invalid', async () => {
const el = await fixture<SlSelect>(html`
<sl-select label="Select one" required>
<sl-option value="option-1">Option 1</sl-option>
<sl-option value="option-2">Option 2</sl-option>
<sl-option value="option-3">Option 3</sl-option>
</sl-select>
`);
const secondOption = el.querySelectorAll('sl-option')[1]!;
expect(el.hasAttribute('data-required')).to.be.true;
expect(el.hasAttribute('data-optional')).to.be.false;
expect(el.hasAttribute('data-invalid')).to.be.true;
expect(el.hasAttribute('data-valid')).to.be.false;
expect(el.hasAttribute('data-user-invalid')).to.be.false;
expect(el.hasAttribute('data-user-valid')).to.be.false;
await el.show();
await clickOnElement(secondOption);
el.value = '';
await el.updateComplete;
expect(el.hasAttribute('data-user-invalid')).to.be.true;
expect(el.hasAttribute('data-user-valid')).to.be.false;
});
});
describe('when serializing', () => {

View File

@@ -1,4 +1,4 @@
import { expect, fixture, html, oneEvent, waitUntil } from '@open-wc/testing';
import { aTimeout, expect, fixture, html, oneEvent, waitUntil } from '@open-wc/testing';
import { sendKeys } from '@web/test-runner-commands';
import sinon from 'sinon';
import type SlSwitch from './switch';
@@ -38,7 +38,7 @@ describe('<sl-switch>', () => {
it('should be valid by default', async () => {
const el = await fixture<SlSwitch>(html` <sl-switch></sl-switch> `);
expect(el.invalid).to.be.false;
expect(el.checkValidity()).to.be.true;
});
it('should emit sl-change and sl-input when clicked', async () => {
@@ -103,7 +103,7 @@ describe('<sl-switch>', () => {
expect(el.checked).to.be.false;
});
it('should not emit sl-change or sl-input when checked is set by javascript', async () => {
it('should not emit sl-change or sl-input when checked is set by JavaScript', async () => {
const el = await fixture<SlSwitch>(html` <sl-switch></sl-switch> `);
el.addEventListener('sl-change', () => expect.fail('sl-change incorrectly emitted'));
el.addEventListener('sl-input', () => expect.fail('sl-change incorrectly emitted'));
@@ -113,26 +113,80 @@ describe('<sl-switch>', () => {
await el.updateComplete;
});
it('should submit "on" when no value is provided', async () => {
const form = await fixture<HTMLFormElement>(html`
<form>
<sl-switch name="a" checked></sl-switch>
<sl-button type="submit">Submit</sl-button>
</form>
`);
const button = form.querySelector('sl-button')!;
const submitHandler = sinon.spy((event: SubmitEvent) => {
formData = new FormData(form);
event.preventDefault();
describe('when submitting a form', () => {
it('should submit the correct value when a value is provided', async () => {
const form = await fixture<HTMLFormElement>(html`
<form>
<sl-switch name="a" value="1" checked></sl-switch>
<sl-button type="submit">Submit</sl-button>
</form>
`);
const button = form.querySelector('sl-button')!;
const submitHandler = sinon.spy((event: SubmitEvent) => {
formData = new FormData(form);
event.preventDefault();
});
let formData: FormData;
form.addEventListener('submit', submitHandler);
button.click();
await waitUntil(() => submitHandler.calledOnce);
expect(formData!.get('a')).to.equal('1');
});
let formData: FormData;
form.addEventListener('submit', submitHandler);
button.click();
it('should submit "on" when no value is provided', async () => {
const form = await fixture<HTMLFormElement>(html`
<form>
<sl-switch name="a" checked></sl-switch>
<sl-button type="submit">Submit</sl-button>
</form>
`);
const button = form.querySelector('sl-button')!;
const submitHandler = sinon.spy((event: SubmitEvent) => {
formData = new FormData(form);
event.preventDefault();
});
let formData: FormData;
await waitUntil(() => submitHandler.calledOnce);
form.addEventListener('submit', submitHandler);
button.click();
expect(formData!.get('a')).to.equal('on');
await waitUntil(() => submitHandler.calledOnce);
expect(formData!.get('a')).to.equal('on');
});
it('should show a constraint validation error when setCustomValidity() is called', async () => {
const form = await fixture<HTMLFormElement>(html`
<form>
<sl-switch name="a" value="1" checked></sl-switch>
<sl-button type="submit">Submit</sl-button>
</form>
`);
const button = form.querySelector('sl-button')!;
const slSwitch = form.querySelector('sl-switch')!;
const submitHandler = sinon.spy((event: SubmitEvent) => event.preventDefault());
// Submitting the form after setting custom validity should not trigger the handler
slSwitch.setCustomValidity('Invalid selection');
form.addEventListener('submit', submitHandler);
button.click();
await aTimeout(100);
expect(submitHandler).to.not.have.been.called;
});
it('should be invalid when required and unchecked', async () => {
const slSwitch = await fixture<HTMLFormElement>(html` <sl-switch required></sl-switch> `);
expect(slSwitch.checkValidity()).to.be.false;
});
it('should be valid when required and checked', async () => {
const slSwitch = await fixture<HTMLFormElement>(html` <sl-switch required checked></sl-switch> `);
expect(slSwitch.checkValidity()).to.be.true;
});
});
describe('when resetting a form', () => {

View File

@@ -108,13 +108,13 @@ describe('<sl-textarea>', () => {
it('should be valid by default', async () => {
const el = await fixture<SlTextarea>(html` <sl-textarea></sl-textarea> `);
expect(el.invalid).to.be.false;
expect(el.checkValidity()).to.be.true;
});
it('should be invalid when required and empty', async () => {
const el = await fixture<SlTextarea>(html` <sl-textarea required></sl-textarea> `);
expect(el.invalid).to.be.true;
expect(el.checkValidity()).to.be.false;
});
it('should be invalid when required and after removing disabled ', async () => {
@@ -123,14 +123,53 @@ describe('<sl-textarea>', () => {
el.disabled = false;
await el.updateComplete;
expect(el.invalid).to.be.true;
expect(el.checkValidity()).to.be.false;
});
it('should be invalid when required and disabled is removed', async () => {
const el = await fixture<SlTextarea>(html` <sl-textarea disabled required></sl-textarea> `);
el.disabled = false;
await el.updateComplete;
expect(el.invalid).to.be.true;
expect(el.checkValidity()).to.be.false;
});
it('should receive the correct validation attributes ("states") when valid', async () => {
const el = await fixture<SlTextarea>(html` <sl-textarea required value="a"></sl-textarea> `);
expect(el.checkValidity()).to.be.true;
expect(el.hasAttribute('data-required')).to.be.true;
expect(el.hasAttribute('data-optional')).to.be.false;
expect(el.hasAttribute('data-invalid')).to.be.false;
expect(el.hasAttribute('data-valid')).to.be.true;
expect(el.hasAttribute('data-user-invalid')).to.be.false;
expect(el.hasAttribute('data-user-valid')).to.be.false;
el.focus();
await sendKeys({ press: 'b' });
await el.updateComplete;
expect(el.checkValidity()).to.be.true;
expect(el.hasAttribute('data-user-invalid')).to.be.false;
expect(el.hasAttribute('data-user-valid')).to.be.true;
});
it('should receive the correct validation attributes ("states") when invalid', async () => {
const el = await fixture<SlTextarea>(html` <sl-textarea required></sl-textarea> `);
expect(el.hasAttribute('data-required')).to.be.true;
expect(el.hasAttribute('data-optional')).to.be.false;
expect(el.hasAttribute('data-invalid')).to.be.true;
expect(el.hasAttribute('data-valid')).to.be.false;
expect(el.hasAttribute('data-user-invalid')).to.be.false;
expect(el.hasAttribute('data-user-valid')).to.be.false;
el.focus();
await sendKeys({ press: 'a' });
await sendKeys({ press: 'Backspace' });
await el.updateComplete;
expect(el.hasAttribute('data-user-invalid')).to.be.true;
expect(el.hasAttribute('data-user-valid')).to.be.false;
});
});