chore(field): add specs for form registration portals

This commit is contained in:
Thomas Allmer 2019-08-22 20:29:24 +02:00 committed by Thomas Allmer
parent 41e12da90d
commit f8a3c54f60
2 changed files with 128 additions and 0 deletions

View file

@ -0,0 +1,55 @@
import { dedupeMixin } from '@lion/core';
import { formRegistrarManager } from './formRegistrarManager.js';
/**
* This will forward
*/
export const FormRegistrarPortalMixin = dedupeMixin(
superclass =>
// eslint-disable-next-line no-shadow, no-unused-vars
class FormRegistrarPortalMixin extends superclass {
constructor() {
super();
this.formElements = [];
this.__readyForRegistration = false;
this.registrationReady = new Promise(resolve => {
this.__resolveRegistrationReady = resolve;
});
}
connectedCallback() {
if (super.connectedCallback) {
super.connectedCallback();
}
formRegistrarManager.add(this);
this.__redispatchEventForFormRegistrarPortalMixin = ev => {
ev.stopPropagation();
// TODO: fire event with changed ev.target
this.dispatchEvent(
new CustomEvent('form-element-register', {
detail: { element: ev.element },
bubbles: true,
}),
);
};
this.addEventListener(
'form-element-register',
this.__redispatchEventForFormRegistrarPortalMixin,
);
}
disconnectedCallback() {
if (super.disconnectedCallback) {
super.disconnectedCallback();
}
formRegistrarManager.remove(this);
}
firstUpdated(changedProperties) {
super.firstUpdated(changedProperties);
this.__resolveRegistrationReady();
this.__readyForRegistration = true;
formRegistrarManager.becomesReady(this);
}
},
);

View file

@ -3,6 +3,7 @@ import { LitElement } from '@lion/core';
import { FormRegistrarMixin } from '../src/FormRegistrarMixin.js';
import { FormRegisteringMixin } from '../src/FormRegisteringMixin.js';
import { FormRegistrarPortalMixin } from '../src/FormRegistrarPortalMixin.js';
import { formRegistrarManager } from '../src/formRegistrarManager.js';
export const runRegistrationSuite = customConfig => {
@ -15,6 +16,7 @@ export const runRegistrationSuite = customConfig => {
describe(`FormRegistrationMixins${cfg.suffix ? ` (${cfg.suffix})` : ''}`, () => {
let parentTag;
let childTag;
let portalTag;
before(async () => {
if (!cfg.parentTagString) {
@ -23,9 +25,13 @@ export const runRegistrationSuite = customConfig => {
if (!cfg.childTagString) {
cfg.childTagString = defineCE(class extends FormRegisteringMixin(cfg.baseElement) {});
}
if (!cfg.portalTagString) {
cfg.portalTagString = defineCE(class extends FormRegistrarPortalMixin(cfg.baseElement) {});
}
parentTag = unsafeStatic(cfg.parentTagString);
childTag = unsafeStatic(cfg.childTagString);
portalTag = unsafeStatic(cfg.portalTagString);
});
it('can register a formElement', async () => {
@ -117,5 +123,72 @@ export const runRegistrationSuite = customConfig => {
el.removeChild(newField);
expect(el.formElements.length).to.equal(1);
});
describe('FormRegistrarPortalMixin', () => {
it('throws if there is no .registrationTarget', async () => {
expect(async () => {
await fixture(html`<${portalTag}></${portalTag}>`);
}).to.throw('A FormRegistrarPortal element requires a .registrationTarget');
});
it('forwards registrations to the .registrationTarget', async () => {
const el = await fixture(html`<${parentTag}></${parentTag}>`);
await fixture(html`
<${portalTag} .registrationTarget=${el}>
<${childTag}></${childTag}>
</${portalTag}>
`);
expect(el.formElements.length).to.equal(1);
});
it('can dynamically add/remove elements', async () => {
const el = await fixture(html`<${parentTag}></${parentTag}>`);
const portal = await fixture(html`
<${portalTag} .registrationTarget=${el}>
<${childTag}></${childTag}>
</${portalTag}>
`);
const newField = await fixture(html`
<${childTag}></${childTag}>
`);
expect(el.formElements.length).to.equal(1);
portal.appendChild(newField);
expect(el.formElements.length).to.equal(2);
portal.removeChild(newField);
expect(el.formElements.length).to.equal(1);
});
it('works for portals that have a delayed render', async () => {
const delayedPortalString = defineCE(
class extends FormRegistrarPortalMixin(LitElement) {
async performUpdate() {
await new Promise(resolve => setTimeout(() => resolve(), 10));
await super.performUpdate();
}
render() {
return html`
<slot></slot>
`;
}
},
);
const delayedPortalTag = unsafeStatic(delayedPortalString);
const el = await fixture(html`<${parentTag}></${parentTag}>`);
await fixture(html`
<${delayedPortalTag} .registrationTarget=${el}>
<${childTag}></${childTag}>
</${delayedPortalTag}>
`);
await el.registrationReady;
expect(el.formElements.length).to.equal(1);
});
});
});
};