Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@lion/field

Package Overview
Dependencies
Maintainers
1
Versions
103
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lion/field - npm Package Compare versions

Comparing version 0.1.44 to 0.2.0

test-suites/FormRegistrationMixins.suite.js

16

CHANGELOG.md

@@ -6,2 +6,18 @@ # Change Log

# [0.2.0](https://github.com/ing-bank/lion/compare/@lion/field@0.1.44...@lion/field@0.2.0) (2019-08-15)
### Bug Fixes
* **field:** cleaned up old register code ([95a9ce7](https://github.com/ing-bank/lion/commit/95a9ce7))
### Features
* **field:** add reset method and capture inital model value ([d2035e6](https://github.com/ing-bank/lion/commit/d2035e6))
## [0.1.44](https://github.com/ing-bank/lion/compare/@lion/field@0.1.43...@lion/field@0.1.44) (2019-08-15)

@@ -8,0 +24,0 @@

4

package.json
{
"name": "@lion/field",
"version": "0.1.44",
"version": "0.2.0",
"description": "Fields are the most fundamental building block of the Form System",

@@ -45,3 +45,3 @@ "author": "ing-bank",

},
"gitHead": "d406de45d6c0980fb4c1f2186ea5585667045074"
"gitHead": "59053f161c74e22efd5ba231a2e40a8346786ffc"
}

@@ -32,6 +32,6 @@ import { dedupeMixin } from '@lion/core';

if (formRegistrarManager.ready) {
this._registerFormElement();
this._dispatchRegistration();
} else {
formRegistrarManager.addEventListener('all-forms-open-for-registration', () => {
this._registerFormElement();
this._dispatchRegistration();
});

@@ -41,7 +41,2 @@ }

_registerFormElement() {
this._dispatchRegistration();
this._requestParentFormGroupUpdateOfResetModelValue();
}
_dispatchRegistration() {

@@ -61,14 +56,3 @@ this.dispatchEvent(

}
/**
* Makes sure our parentFormGroup has the most up to date resetModelValue
* FormGroups will call the same on their parentFormGroup so the full tree gets the correct
* values.
*/
_requestParentFormGroupUpdateOfResetModelValue() {
if (this.__parentFormGroup && this.__parentFormGroup._updateResetModelValue) {
this.__parentFormGroup._updateResetModelValue();
}
}
},
);

@@ -104,2 +104,7 @@ import { SlotMixin, LitElement } from '@lion/core';

firstUpdated(c) {
super.firstUpdated(c);
this._initialModelValue = this.modelValue;
}
connectedCallback() {

@@ -121,10 +126,2 @@ // TODO: Normally we put super calls on top for predictability,

super.disconnectedCallback();
if (this.__parentFormGroup) {
const event = new CustomEvent('form-element-unregister', {
detail: { element: this },
bubbles: true,
});
this.__parentFormGroup.dispatchEvent(event);
}
this.inputElement.removeEventListener('change', this._onChange);

@@ -169,2 +166,7 @@ }

reset() {
this.modelValue = this._initialModelValue;
this.resetInteractionState();
}
clear() {

@@ -171,0 +173,0 @@ if (super.clear) {

@@ -1,129 +0,19 @@

import { expect, fixture, html, defineCE, unsafeStatic } from '@open-wc/testing';
import sinon from 'sinon';
import { LitElement, UpdatingElement } from '@lion/core';
import { html } from '@open-wc/testing';
import { UpdatingElement, LitElement } from '@lion/core';
import { runRegistrationSuite } from '../test-suites/FormRegistrationMixins.suite.js';
import { formRegistrarManager } from '../src/formRegistrarManager.js';
import { FormRegisteringMixin } from '../src/FormRegisteringMixin.js';
import { FormRegistrarMixin } from '../src/FormRegistrarMixin.js';
runRegistrationSuite({
suffix: 'with UpdatingElement',
baseElement: UpdatingElement,
});
describe('FormRegistrationMixins', () => {
before(async () => {
const FormRegistrarEl = class extends FormRegistrarMixin(UpdatingElement) {};
customElements.define('form-registrar', FormRegistrarEl);
const FormRegisteringEl = class extends FormRegisteringMixin(UpdatingElement) {};
customElements.define('form-registering', FormRegisteringEl);
});
it('can register a formElement', async () => {
const el = await fixture(html`
<form-registrar>
<form-registering></form-registering>
</form-registrar>
`);
await el.registrationReady;
expect(el.formElements.length).to.equal(1);
});
it('supports nested registrar', async () => {
const el = await fixture(html`
<form-registrar>
<form-registrar>
<form-registering></form-registering>
</form-registrar>
</form-registrar>
`);
await el.registrationReady;
expect(el.formElements.length).to.equal(1);
expect(el.querySelector('form-registrar').formElements.length).to.equal(1);
});
it('forgets disconnected registrars', async () => {
const el = await fixture(html`
<form-registrar>
<form-registrar>
<form-registering></form-registering>
</form-registrar>
</form-registrar>
`);
const secondRegistrar = await fixture(html`
<form-registrar>
<form-registering></form-registering>
</form-registrar>
`);
el.appendChild(secondRegistrar);
expect(formRegistrarManager.__elements.length).to.equal(3);
el.removeChild(secondRegistrar);
expect(formRegistrarManager.__elements.length).to.equal(2);
});
it('works for component that have a delayed render', async () => {
const tagWrapperString = defineCE(
class extends FormRegistrarMixin(LitElement) {
async performUpdate() {
await new Promise(resolve => setTimeout(() => resolve(), 10));
await super.performUpdate();
}
render() {
return html`
<slot></slot>
`;
}
},
);
const tagWrapper = unsafeStatic(tagWrapperString);
const registerSpy = sinon.spy();
const el = await fixture(html`
<${tagWrapper} @form-element-register=${registerSpy}>
<form-registering></form-registering>
</${tagWrapper}>
`);
await el.registrationReady;
expect(el.formElements.length).to.equal(1);
});
it('requests update of the resetModelValue function of its parent formGroup', async () => {
const ParentFormGroupClass = class extends FormRegistrarMixin(LitElement) {
_updateResetModelValue() {
this.resetModelValue = 'foo';
}
};
const ChildFormGroupClass = class extends FormRegisteringMixin(LitElement) {
constructor() {
super();
this.__parentFormGroup = this.parentNode;
}
};
const parentClass = defineCE(ParentFormGroupClass);
const formGroup = unsafeStatic(parentClass);
const childClass = defineCE(ChildFormGroupClass);
const childFormGroup = unsafeStatic(childClass);
const parentFormEl = await fixture(html`
<${formGroup}><${childFormGroup} id="child" name="child[]"></${childFormGroup}></${formGroup}>
`);
expect(parentFormEl.resetModelValue).to.equal('foo');
});
it('can dynamically add/remove elements', async () => {
const el = await fixture(html`
<form-registrar>
<form-registering></form-registering>
</form-registrar>
`);
const newField = await fixture(html`
<form-registering></form-registering>
`);
expect(el.formElements.length).to.equal(1);
el.appendChild(newField);
expect(el.formElements.length).to.equal(2);
el.removeChild(newField);
expect(el.formElements.length).to.equal(1);
});
runRegistrationSuite({
suffix: 'with LitElement, using shadow dom',
baseElement: class ShadowElement extends LitElement {
render() {
return html`
<slot></slot>
`;
}
},
});

@@ -34,3 +34,3 @@ import {

it(`puts a unique id "${tagString}-[hash]" on the native input`, async () => {
const el = await fixture(`<${tagString}>${inputSlotString}</${tagString}>`);
const el = await fixture(html`<${tag}>${inputSlot}</${tag}>`);
expect(el.$$slot('input').id).to.equal(el._inputId);

@@ -40,3 +40,3 @@ });

it('fires focus/blur event on host and native input if focused/blurred', async () => {
const el = await fixture(`<${tagString}>${inputSlotString}</${tagString}>`);
const el = await fixture(html`<${tag}>${inputSlot}</${tag}>`);
const cbFocusHost = sinon.spy();

@@ -73,4 +73,13 @@ el.addEventListener('focus', cbFocusHost);

it('offers simple getter "this.focused" returning true/false for the current focus state', async () => {
const el = await fixture(html`<${tag}>${inputSlot}</${tag}>`);
expect(el.focused).to.equal(false);
await triggerFocusFor(el);
expect(el.focused).to.equal(true);
await triggerBlurFor(el);
expect(el.focused).to.equal(false);
});
it('can be disabled via attribute', async () => {
const elDisabled = await fixture(`<${tagString} disabled>${inputSlotString}</${tagString}>`);
const elDisabled = await fixture(html`<${tag} disabled>${inputSlot}</${tag}>`);
expect(elDisabled.disabled).to.equal(true);

@@ -81,3 +90,3 @@ expect(elDisabled.inputElement.disabled).to.equal(true);

it('can be disabled via property', async () => {
const el = await fixture(`<${tagString}>${inputSlotString}</${tagString}>`);
const el = await fixture(html`<${tag}>${inputSlot}</${tag}>`);
el.disabled = true;

@@ -88,16 +97,4 @@ await el.updateComplete;

// classes are added only for backward compatibility - they are deprecated
it('sets a state-disabled class when disabled', async () => {
const el = await fixture(`<${tagString} disabled>${inputSlotString}</${tagString}>`);
await el.updateComplete;
expect(el.classList.contains('state-disabled')).to.equal(true);
el.disabled = false;
await el.updateComplete;
expect(el.classList.contains('state-disabled')).to.equal(false);
});
it('can be cleared which erases value, validation and interaction states', async () => {
const el = await fixture(
`<${tagString} value="Some value from attribute">${inputSlotString}</${tagString}>`,
);
const el = await fixture(html`<${tag} value="Some value from attribute">${inputSlot}</${tag}>`);
el.clear();

@@ -111,4 +108,15 @@ expect(el.value).to.equal('');

it('can be reset which restores original modelValue', async () => {
const el = await fixture(html`
<${tag} .modelValue="${'foo'}">
${inputSlot}
</${tag}>`);
expect(el._initialModelValue).to.equal('foo');
el.modelValue = 'bar';
el.reset();
expect(el.modelValue).to.equal('foo');
});
it('reads initial value from attribute value', async () => {
const el = await fixture(`<${tagString} value="one">${inputSlotString}</${tagString}>`);
const el = await fixture(html`<${tag} value="one">${inputSlot}</${tag}>`);
expect(el.$$slot('input').value).to.equal('one');

@@ -118,3 +126,3 @@ });

it('delegates value property', async () => {
const el = await fixture(`<${tagString}>${inputSlotString}</${tagString}>`);
const el = await fixture(html`<${tag}>${inputSlot}</${tag}>`);
expect(el.$$slot('input').value).to.equal('');

@@ -126,18 +134,6 @@ el.value = 'one';

it('has a name which is reflected to an attribute and is synced down to the native input', async () => {
const el = await fixture(`<${tagString}>${inputSlotString}</${tagString}>`);
expect(el.name).to.equal('');
expect(el.getAttribute('name')).to.equal('');
expect(el.inputElement.getAttribute('name')).to.equal('');
el.name = 'foo';
await el.updateComplete;
expect(el.getAttribute('name')).to.equal('foo');
expect(el.inputElement.getAttribute('name')).to.equal('foo');
});
// TODO: find out if we could put all listeners on this.value (instead of this.inputElement.value)
// and make it act on this.value again
it('has a class "state-filled" if this.value is filled', async () => {
const el = await fixture(`<${tagString} value="filled">${inputSlotString}</${tagString}>`);
const el = await fixture(html`<${tag} value="filled">${inputSlot}</${tag}>`);
expect(el.classList.contains('state-filled')).to.equal(true);

@@ -153,3 +149,3 @@ el.value = '';

it('preserves the caret position on value change for native text fields (input|textarea)', async () => {
const el = await fixture(`<${tagString}>${inputSlotString}</${tagString}>`);
const el = await fixture(html`<${tag}>${inputSlot}</${tag}>`);
await triggerFocusFor(el);

@@ -167,3 +163,3 @@ await el.updateComplete;

it('has a class "state-disabled"', async () => {
const el = await fixture(`<${tagString}>${inputSlotString}</${tagString}>`);
const el = await fixture(html`<${tag}>${inputSlot}</${tag}>`);
expect(el.classList.contains('state-disabled')).to.equal(false);

@@ -179,3 +175,3 @@ expect(el.inputElement.hasAttribute('disabled')).to.equal(false);

const disabledel = await fixture(`<${tagString} disabled>${inputSlotString}</${tagString}>`);
const disabledel = await fixture(html`<${tag} disabled>${inputSlot}</${tag}>`);
expect(disabledel.classList.contains('state-disabled')).to.equal(true);

@@ -200,8 +196,8 @@ expect(disabledel.inputElement.hasAttribute('disabled')).to.equal(true);

~~~`, async () => {
const el = await fixture(`<${tagString}>
const el = await fixture(html`<${tag}>
<label slot="label">My Name</label>
${inputSlotString}
${inputSlot}
<span slot="help-text">Enter your Name</span>
<span slot="feedback">No name entered</span>
</${tagString}>
</${tag}>
`);

@@ -217,4 +213,4 @@ const nativeInput = el.$$slot('input');

(via attribute data-label) and in describedby (via attribute data-description)`, async () => {
const el = await fixture(`<${tagString}>
${inputSlotString}
const el = await fixture(html`<${tag}>
${inputSlot}
<span slot="before" data-label>[before]</span>

@@ -224,3 +220,3 @@ <span slot="after" data-label>[after]</span>

<span slot="suffix" data-description>[suffix]</span>
</${tagString}>
</${tag}>
`);

@@ -240,29 +236,29 @@

addToAriaDescription()`, async () => {
const wrapper = await fixture(`
const wrapper = await fixture(html`
<div id="wrapper">
<${tagString}>
${inputSlotString}
<${tag}>
${inputSlot}
<label slot="label">Added to label by default</label>
<div slot="feedback">Added to description by default</div>
</${tagString}>
</${tag}>
<div id="additionalLabel"> This also needs to be read whenever the input has focus</div>
<div id="additionalDescription"> Same for this </div>
</div>`);
const el = wrapper.querySelector(`${tagString}`);
const el = wrapper.querySelector(tagString);
// wait until the field element is done rendering
await el.updateComplete;
await el.updateComplete;
const { inputElement } = el;
const get = by => inputElement.getAttribute(`aria-${by}`);
// 1. addToAriaLabel()
// Check if the aria attr is filled initially
expect(get('labelledby')).to.contain(`label-${el._inputId}`);
expect(inputElement.getAttribute('aria-labelledby')).to.contain(`label-${el._inputId}`);
el.addToAriaLabel('additionalLabel');
// Now check if ids are added to the end (not overridden)
expect(get('labelledby')).to.contain(`label-${el._inputId}`);
expect(inputElement.getAttribute('aria-labelledby')).to.contain(`label-${el._inputId}`);
// Should be placed in the end
expect(
get('labelledby').indexOf(`label-${el._inputId}`) <
get('labelledby').indexOf('additionalLabel'),
inputElement.getAttribute('aria-labelledby').indexOf(`label-${el._inputId}`) <
inputElement.getAttribute('aria-labelledby').indexOf('additionalLabel'),
);

@@ -272,10 +268,10 @@

// Check if the aria attr is filled initially
expect(get('describedby')).to.contain(`feedback-${el._inputId}`);
expect(inputElement.getAttribute('aria-describedby')).to.contain(`feedback-${el._inputId}`);
el.addToAriaDescription('additionalDescription');
// Now check if ids are added to the end (not overridden)
expect(get('describedby')).to.contain(`feedback-${el._inputId}`);
expect(inputElement.getAttribute('aria-describedby')).to.contain(`feedback-${el._inputId}`);
// Should be placed in the end
expect(
get('describedby').indexOf(`feedback-${el._inputId}`) <
get('describedby').indexOf('additionalDescription'),
inputElement.getAttribute('aria-describedby').indexOf(`feedback-${el._inputId}`) <
inputElement.getAttribute('aria-describedby').indexOf('additionalDescription'),
);

@@ -304,3 +300,3 @@ });

}
const el = await fixture(`<${tagString}>${inputSlotString}</${tagString}>`);
const el = await fixture(html`<${tag}>${inputSlot}</${tag}>`);
const feedbackEl = el._feedbackElement;

@@ -375,6 +371,6 @@

it('renders correctly all slot elements in light DOM', async () => {
const el = await fixture(`
<${tagString}>
const el = await fixture(html`
<${tag}>
<label slot="label">[label]</label>
${inputSlotString}
${inputSlot}
<span slot="help-text">[help-text]</span>

@@ -386,3 +382,3 @@ <span slot="before">[before]</span>

<span slot="feedback">[feedback]</span>
</${tagString}>
</${tag}>
`);

@@ -410,5 +406,5 @@

describe(`Delegation${nameSuffix}`, () => {
describe('Delegation', () => {
it('delegates property value', async () => {
const el = await fixture(`<${tagString}>${inputSlotString}</${tagString}>`);
const el = await fixture(html`<${tag}>${inputSlot}</${tag}>`);
expect(el.inputElement.value).to.equal('');

@@ -415,0 +411,0 @@ el.value = 'one';

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc