chore(field): improve InteractionStateMixin tests

This commit is contained in:
Thomas Allmer 2019-07-13 01:36:53 +02:00
parent 901fc8c503
commit 89112f6c78

View file

@ -1,14 +1,28 @@
import { expect, fixture, unsafeStatic, html, defineCE } from '@open-wc/testing'; import {
expect,
fixture,
unsafeStatic,
html,
defineCE,
triggerFocusFor,
triggerBlurFor,
} from '@open-wc/testing';
import sinon from 'sinon'; import sinon from 'sinon';
import { LionLitElement } from '@lion/core/src/LionLitElement.js'; import { LitElement } from '@lion/core';
import { InteractionStateMixin } from '../src/InteractionStateMixin.js'; import { InteractionStateMixin } from '../src/InteractionStateMixin.js';
describe('InteractionStateMixin', async () => { describe('InteractionStateMixin', async () => {
let elem; let tagString;
let tag;
before(() => { before(() => {
elem = defineCE( tagString = defineCE(
class IState extends InteractionStateMixin(LionLitElement) { class IState extends InteractionStateMixin(LitElement) {
connectedCallback() {
super.connectedCallback();
this.tabIndex = 0;
}
set modelValue(v) { set modelValue(v) {
this._modelValue = v; this._modelValue = v;
this.dispatchEvent( this.dispatchEvent(
@ -19,149 +33,120 @@ describe('InteractionStateMixin', async () => {
get modelValue() { get modelValue() {
return this._modelValue; return this._modelValue;
} }
get inputElement() {
return this.querySelector('input');
}
}, },
); );
tag = unsafeStatic(tagString);
}); });
it('sets states to false on init', async () => { it('sets states to false on init', async () => {
const input = await fixture(`<${elem}><input slot="input"></${elem}>`); const el = await fixture(html`<${tag}></${tag}>`);
expect(input.dirty).to.equal(false); expect(el.dirty).to.be.false;
expect(input.touched).to.equal(false); expect(el.touched).to.be.false;
expect(input.prefilled).to.equal(false); expect(el.prefilled).to.be.false;
}); });
it('sets dirty when value changed', async () => { it('sets dirty when value changed', async () => {
const input = await fixture(`<${elem}><input slot="input"></${elem}>`); const el = await fixture(html`<${tag}></${tag}>`);
input.modelValue = 'foobar'; expect(el.dirty).to.be.false;
expect(input.dirty).to.equal(true); el.modelValue = 'foobar';
expect(el.dirty).to.be.true;
}); });
// Skipping, since this issue (not being able to set focus on element extending from LitElement)
// only occurs in WCT context (not in Storybook/Stackblitz).
// See: https://stackblitz.com/edit/lit-element-request-update-bug-g59tjq?file=blurry.js
// it.skip
it('sets touched to true when field left after focus', async () => { it('sets touched to true when field left after focus', async () => {
// const formElement = await LionTest.htmlFixture(`<${elem}><input type="text" slot="input"></${elem}>`); const el = await fixture(html`<${tag}></${tag}>`);
// await triggerFocusFor(formElement.inputElement); // focus/blur can't be delegated await triggerFocusFor(el);
// await triggerBlurFor(formElement.inputElement); await triggerBlurFor(el);
// expect(formElement.touched).to.equal(true); expect(el.touched).to.be.true;
}); });
it('sets a class "state-(touched|dirty)"', async () => { it('sets a class "state-(touched|dirty)"', async () => {
const state = await fixture(`<${elem}><input slot="input"></${elem}>`); const el = await fixture(html`<${tag}></${tag}>`);
state.touched = true; el.touched = true;
await state.updateComplete; await el.updateComplete;
expect(state.classList.contains('state-touched')).to.equal(true, 'has class "state-touched"'); expect(el.classList.contains('state-touched')).to.equal(true, 'has class "state-touched"');
state.dirty = true; el.dirty = true;
await state.updateComplete; await el.updateComplete;
expect(state.classList.contains('state-dirty')).to.equal(true, 'has class "state-dirty"'); expect(el.classList.contains('state-dirty')).to.equal(true, 'has class "state-dirty"');
}); });
it('fires "(touched|dirty)-state-changed" event when state changes', async () => { it('fires "(touched|dirty)-state-changed" event when state changes', async () => {
const iState = await fixture(`<${elem}><input slot="input"></${elem}>`); const touchedSpy = sinon.spy();
const cbTouched = sinon.spy(); const dirtySpy = sinon.spy();
const cbDirty = sinon.spy(); const el = await fixture(
html`<${tag} @touched-changed=${touchedSpy} @dirty-changed=${dirtySpy}></${tag}>`,
);
iState.addEventListener('touched-changed', cbTouched); el.touched = true;
iState.addEventListener('dirty-changed', cbDirty); expect(touchedSpy.callCount).to.equal(1);
iState.touched = true; el.dirty = true;
expect(cbTouched.callCount).to.equal(1); expect(dirtySpy.callCount).to.equal(1);
iState.dirty = true;
expect(cbDirty.callCount).to.equal(1);
});
// Skipping, since this issue (not being able to set focus on element extending from LitElement)
// only occurs in WCT context (not in Storybook/Stackblitz).
// See: https://stackblitz.com/edit/lit-element-request-update-bug-g59tjq?file=blurry.js
// it.skip
it('sets prefilled to true when field left and value non-empty', async () => {
// const iState = await LionTest.htmlFixture(`<${elem}><input slot="input"></${elem}>`);
// await triggerFocusFor(iState.inputElement);
// iState.modelValue = externalVariables.prefilledModelValue || '000';
// await triggerBlurFor(iState.inputElement);
// expect(iState.prefilled).to.equal(true);
// await triggerFocusFor(iState.inputElement);
// iState.modelValue = externalVariables.nonPrefilledModelValue || '';
// await triggerBlurFor(iState.inputElement);
// expect(iState.prefilled).to.equal(false);
}); });
it('sets prefilled once instantiated', async () => { it('sets prefilled once instantiated', async () => {
const tag = unsafeStatic(elem); const el = await fixture(html`
const element = await fixture(html` <${tag} .modelValue=${'prefilled'}></${tag}>
<${tag} `);
.modelValue=${'prefilled'} expect(el.prefilled).to.be.true;
><input slot="input"></${tag}>`);
expect(element.prefilled).to.equal(true);
const nonPrefilled = await fixture(html` const nonPrefilled = await fixture(html`
<${tag} <${tag} .modelValue=${''}></${tag}>
.modelValue=''} `);
><input slot="input"></${tag}>`); expect(nonPrefilled.prefilled).to.be.false;
expect(nonPrefilled.prefilled).to.equal(false);
}); });
// This method actually tests the implementation of the _isPrefilled method. // This method actually tests the implementation of the _isPrefilled method.
it(`can determine "prefilled" based on different modelValue types (Arrays, Objects, Numbers, it(`can determine "prefilled" based on different modelValue types (Arrays, Objects, Numbers,
Booleans, Strings)`, async () => { Booleans, Strings)`, async () => {
const input = await fixture(`<${elem}><input slot="input"></${elem}>`); const el = await fixture(html`<${tag}></${tag}>`);
const changeModelValueAndLeave = modelValue => { const changeModelValueAndLeave = modelValue => {
input.dispatchEvent(new Event('focus', { bubbles: true })); el.dispatchEvent(new Event('focus', { bubbles: true }));
input.modelValue = modelValue; el.modelValue = modelValue;
input.dispatchEvent(new Event('blur', { bubbles: true })); el.dispatchEvent(new Event('blur', { bubbles: true }));
}; };
// Prefilled // Prefilled
changeModelValueAndLeave(input, ['bla']); changeModelValueAndLeave(['not-empty']);
expect(input.prefilled).to.equal(false, 'empty array should be considered "prefilled"'); expect(el.prefilled, 'not empty array should be "prefilled"').to.be.true;
changeModelValueAndLeave(input, { bla: 'bla' }); changeModelValueAndLeave({ not: 'empty' });
expect(input.prefilled).to.equal(false, 'empty object should be considered "prefilled"'); expect(el.prefilled, 'not empty object should be "prefilled"').to.be.true;
changeModelValueAndLeave(input, 0); changeModelValueAndLeave(0);
expect(input.prefilled).to.equal(false, 'numbers should be considered "prefilled"'); expect(el.prefilled, 'numbers should be "prefilled"').to.be.true;
changeModelValueAndLeave(input, false); changeModelValueAndLeave(false);
expect(input.prefilled).to.equal(false, 'Booleans should be considered "prefilled"'); expect(el.prefilled, 'booleans should be "prefilled"').to.be.true;
changeModelValueAndLeave(input, '');
expect(input.prefilled).to.equal(false, 'empty string should be considered "prefilled"');
// Not prefilled // Not prefilled
changeModelValueAndLeave(input, []); changeModelValueAndLeave([]);
expect(input.prefilled).to.equal(false, 'empty array should not be considered "prefilled"'); expect(el.prefilled, 'empty array should not be "prefilled"').to.be.false;
changeModelValueAndLeave(input, {}); changeModelValueAndLeave({});
expect(input.prefilled).to.equal(false, 'empty object should not be considered "prefilled"'); expect(el.prefilled, 'empty object should not be "prefilled"').to.be.false;
changeModelValueAndLeave(input, ''); changeModelValueAndLeave('');
expect(input.prefilled).to.equal(false, 'empty string should not be considered "prefilled"'); expect(el.prefilled, 'empty string should not be "prefilled"').to.be.false;
changeModelValueAndLeave(null);
changeModelValueAndLeave(input, null); expect(el.prefilled, 'null should not be "prefilled"').to.be.false;
expect(input.prefilled).to.equal(false, 'null should not be considered "prefilled"'); changeModelValueAndLeave(undefined);
changeModelValueAndLeave(input, undefined); expect(el.prefilled, 'undefined should not be "prefilled"').to.be.false;
expect(input.prefilled).to.equal(false, 'undefined should not be considered "prefilled"');
}); });
it('has a method resetInteractionState()', async () => { it('has a method resetInteractionState()', async () => {
const input = await fixture(`<${elem}><input slot="input"></${elem}>`); const el = await fixture(html`<${tag}></${tag}>`);
input.dirty = true; el.dirty = true;
input.touched = true; el.touched = true;
input.prefilled = true; el.prefilled = true;
input.resetInteractionState(); el.resetInteractionState();
expect(input.dirty).to.equal(false); expect(el.dirty).to.be.false;
expect(input.touched).to.equal(false); expect(el.touched).to.be.false;
expect(input.prefilled).to.equal(false); expect(el.prefilled).to.be.false;
input.dirty = true; el.dirty = true;
input.touched = true; el.touched = true;
input.prefilled = false; el.prefilled = false;
input.modelValue = 'Some value'; el.modelValue = 'Some value';
input.resetInteractionState(); el.resetInteractionState();
expect(input.dirty).to.equal(false); expect(el.dirty).to.be.false;
expect(input.touched).to.equal(false); expect(el.touched).to.be.false;
expect(input.prefilled).to.equal(true); expect(el.prefilled).to.be.true;
}); });
}); });