fix(form-core): add index.d.ts and adjust types for LionInput types

This commit is contained in:
Joren Broekema 2020-09-14 15:04:28 +02:00 committed by Thomas Allmer
parent 10e6ad74c2
commit 46dbaa3f37
4 changed files with 75 additions and 30 deletions

52
packages/form-core/index.d.ts vendored Normal file
View file

@ -0,0 +1,52 @@
export { FocusMixin } from './src/FocusMixin.js';
export { FormatMixin } from './src/FormatMixin.js';
export { FormControlMixin } from './src/FormControlMixin.js';
export { InteractionStateMixin } from './src/InteractionStateMixin.js'; // applies FocusMixin
export { LionField } from './src/LionField.js';
export { FormRegisteringMixin } from './src/registration/FormRegisteringMixin.js';
export { FormRegistrarMixin } from './src/registration/FormRegistrarMixin.js';
export { FormRegistrarPortalMixin } from './src/registration/FormRegistrarPortalMixin.js';
export { FormControlsCollection } from './src/registration/FormControlsCollection.js';
// validate
export { ValidateMixin } from './src/validate/ValidateMixin.js';
export { Unparseable } from './src/validate/Unparseable.js';
export { Validator } from './src/validate/Validator.js';
export { ResultValidator } from './src/validate/ResultValidator.js';
export { Required } from './src/validate/validators/Required.js';
export {
IsString,
EqualsLength,
MinLength,
MaxLength,
MinMaxLength,
IsEmail,
Pattern,
} from './src/validate/validators/StringValidators.js';
export {
IsNumber,
MinNumber,
MaxNumber,
MinMaxNumber,
} from './src/validate/validators/NumberValidators.js';
export {
IsDate,
MinDate,
MaxDate,
MinMaxDate,
IsDateDisabled,
} from './src/validate/validators/DateValidators.js';
export { DefaultSuccess } from './src/validate/resultValidators/DefaultSuccess.js';
export { LionValidationFeedback } from './src/validate/LionValidationFeedback.js';
export { ChoiceGroupMixin } from './src/choice-group/ChoiceGroupMixin.js';
export { ChoiceInputMixin } from './src/choice-group/ChoiceInputMixin.js';
export { FormGroupMixin } from './src/form-group/FormGroupMixin.js';

View file

@ -1,5 +1,4 @@
import { html, LitElement } from '@lion/core';
// @ts-expect-error
import { LionInput } from '@lion/input';
import '@lion/fieldset/lion-fieldset.js';
import { FormGroupMixin, Required } from '@lion/form-core';
@ -19,7 +18,6 @@ import { ChoiceInputMixin } from '../../src/choice-group/ChoiceInputMixin.js';
describe('ChoiceGroupMixin', () => {
class ChoiceInput extends ChoiceInputMixin(LionInput) {}
// @ts-expect-error base constructors same return type
customElements.define('choice-group-input', ChoiceInput);
// @ts-expect-error
class ChoiceGroup extends ChoiceGroupMixin(FormGroupMixin(LitElement)) {}

View file

@ -1,35 +1,28 @@
import { html } from '@lion/core';
// @ts-expect-error
import { LionInput } from '@lion/input';
import { Required } from '@lion/form-core';
import { expect, fixture } from '@open-wc/testing';
import sinon from 'sinon';
import { ChoiceInputMixin } from '../../src/choice-group/ChoiceInputMixin.js';
/**
* @typedef {import('../../types/choice-group/ChoiceInputMixinTypes').ChoiceInputHost} ChoiceInputHost
*/
describe('ChoiceInputMixin', () => {
/** @typedef {Element & ChoiceClass} ChoiceInput */
class ChoiceClass extends ChoiceInputMixin(LionInput) {
constructor() {
super();
this.type = 'checkbox'; // could also be 'radio', should be tested in integration test
}
}
// @ts-expect-error base constructors same return type
customElements.define('choice-input', ChoiceClass);
it('is hidden when attribute hidden is true', async () => {
const el = /** @type {ChoiceInput} */ (await fixture(
const el = /** @type {ChoiceClass} */ (await fixture(
html`<choice-input hidden></choice-input>`,
));
expect(el).not.to.be.displayed;
});
it('has choiceValue', async () => {
const el = /** @type {ChoiceInput} */ (await fixture(
const el = /** @type {ChoiceClass} */ (await fixture(
html`<choice-input .choiceValue=${'foo'}></choice-input>`,
));
@ -43,7 +36,7 @@ describe('ChoiceInputMixin', () => {
it('can handle complex data via choiceValue', async () => {
const date = new Date(2018, 11, 24, 10, 33, 30, 0);
const el = /** @type {ChoiceInput} */ (await fixture(
const el = /** @type {ChoiceClass} */ (await fixture(
html`<choice-input .choiceValue=${date}></choice-input>`,
));
@ -53,7 +46,7 @@ describe('ChoiceInputMixin', () => {
it('fires one "model-value-changed" event if choiceValue or checked state or modelValue changed', async () => {
let counter = 0;
const el = /** @type {ChoiceInput} */ (await fixture(html`
const el = /** @type {ChoiceClass} */ (await fixture(html`
<choice-input
@model-value-changed=${() => {
counter += 1;
@ -78,7 +71,7 @@ describe('ChoiceInputMixin', () => {
it('fires one "user-input-changed" event after user interaction', async () => {
let counter = 0;
const el = /** @type {ChoiceInput} */ (await fixture(html`
const el = /** @type {ChoiceClass} */ (await fixture(html`
<choice-input
@user-input-changed="${() => {
counter += 1;
@ -97,7 +90,7 @@ describe('ChoiceInputMixin', () => {
});
it('can be required', async () => {
const el = /** @type {ChoiceInput} */ (await fixture(html`
const el = /** @type {ChoiceClass} */ (await fixture(html`
<choice-input .choiceValue=${'foo'} .validators=${[new Required()]}></choice-input>
`));
expect(el.hasFeedbackFor).to.include('error');
@ -111,17 +104,17 @@ describe('ChoiceInputMixin', () => {
describe('Checked state synchronization', () => {
it('synchronizes checked state initially (via attribute or property)', async () => {
const el = /** @type {ChoiceInput} */ (await fixture(`<choice-input></choice-input>`));
const el = /** @type {ChoiceClass} */ (await fixture(`<choice-input></choice-input>`));
expect(el.checked).to.equal(false, 'initially unchecked');
const precheckedElementAttr = /** @type {ChoiceInput} */ (await fixture(html`
const precheckedElementAttr = /** @type {ChoiceClass} */ (await fixture(html`
<choice-input .checked=${true}></choice-input>
`));
expect(precheckedElementAttr.checked).to.equal(true, 'initially checked via attribute');
});
it('can be checked and unchecked programmatically', async () => {
const el = /** @type {ChoiceInput} */ (await fixture(`<choice-input></choice-input>`));
const el = /** @type {ChoiceClass} */ (await fixture(`<choice-input></choice-input>`));
expect(el.checked).to.be.false;
el.checked = true;
expect(el.checked).to.be.true;
@ -131,7 +124,7 @@ describe('ChoiceInputMixin', () => {
});
it('can be checked and unchecked via user interaction', async () => {
const el = /** @type {ChoiceInput} */ (await fixture(`<choice-input></choice-input>`));
const el = /** @type {ChoiceClass} */ (await fixture(`<choice-input></choice-input>`));
el._inputNode.click();
expect(el.checked).to.be.true;
el._inputNode.click();
@ -139,7 +132,7 @@ describe('ChoiceInputMixin', () => {
});
it('synchronizes modelValue to checked state and vice versa', async () => {
const el = /** @type {ChoiceInput} */ (await fixture(
const el = /** @type {ChoiceClass} */ (await fixture(
html`<choice-input .choiceValue=${'foo'}></choice-input>`,
));
expect(el.checked).to.be.false;
@ -158,7 +151,7 @@ describe('ChoiceInputMixin', () => {
it('ensures optimal synchronize performance by preventing redundant computation steps', async () => {
/* we are checking private apis here to make sure we do not have cyclical updates
which can be quite common for these type of connected data */
const el = /** @type {ChoiceInput} */ (await fixture(
const el = /** @type {ChoiceClass} */ (await fixture(
html`<choice-input .choiceValue=${'foo'}></choice-input>`,
));
expect(el.checked).to.be.false;
@ -183,10 +176,10 @@ describe('ChoiceInputMixin', () => {
});
it('synchronizes checked state to [checked] attribute for styling purposes', async () => {
/** @param {ChoiceInput} el */
/** @param {ChoiceClass} el */
const hasAttr = el => el.hasAttribute('checked');
const el = /** @type {ChoiceInput} */ (await fixture(`<choice-input></choice-input>`));
const elChecked = /** @type {ChoiceInput} */ (await fixture(html`
const el = /** @type {ChoiceClass} */ (await fixture(`<choice-input></choice-input>`));
const elChecked = /** @type {ChoiceClass} */ (await fixture(html`
<choice-input .checked=${true}>
<input slot="input" />
</choice-input>
@ -230,22 +223,22 @@ describe('ChoiceInputMixin', () => {
describe('Format/parse/serialize loop', () => {
it('creates a modelValue object like { checked: true, value: foo } on init', async () => {
const el = /** @type {ChoiceInput} */ (await fixture(
const el = /** @type {ChoiceClass} */ (await fixture(
html`<choice-input .choiceValue=${'foo'}></choice-input>`,
));
expect(el.modelValue).deep.equal({ value: 'foo', checked: false });
const elChecked = /** @type {ChoiceInput} */ (await fixture(html`
const elChecked = /** @type {ChoiceClass} */ (await fixture(html`
<choice-input .choiceValue=${'foo'} .checked=${true}></choice-input>
`));
expect(elChecked.modelValue).deep.equal({ value: 'foo', checked: true });
});
it('creates a formattedValue based on modelValue.value', async () => {
const el = /** @type {ChoiceInput} */ (await fixture(`<choice-input></choice-input>`));
const el = /** @type {ChoiceClass} */ (await fixture(`<choice-input></choice-input>`));
expect(el.formattedValue).to.equal('');
const elementWithValue = /** @type {ChoiceInput} */ (await fixture(html`
const elementWithValue = /** @type {ChoiceClass} */ (await fixture(html`
<choice-input .choiceValue=${'foo'}></choice-input>
`));
expect(elementWithValue.formattedValue).to.equal('foo');
@ -254,12 +247,12 @@ describe('ChoiceInputMixin', () => {
describe('Interaction states', () => {
it('is considered prefilled when checked and not considered prefilled when unchecked', async () => {
const el = /** @type {ChoiceInput} */ (await fixture(
const el = /** @type {ChoiceClass} */ (await fixture(
html`<choice-input .checked=${true}></choice-input>`,
));
expect(el.prefilled).equal(true, 'checked element not considered prefilled');
const elUnchecked = /** @type {ChoiceInput} */ (await fixture(
const elUnchecked = /** @type {ChoiceClass} */ (await fixture(
`<choice-input></choice-input>`,
));
expect(elUnchecked.prefilled).equal(false, 'unchecked element not considered prefilled');

View file

@ -17,6 +17,8 @@ export declare class ChoiceInputHost {
modelValue: ChoiceInputModelValue;
serializedValue: ChoiceInputSerializedValue;
checked: boolean;
get choiceValue(): any;
set choiceValue(value: any);