chore(field): add specs for form registration portals
This commit is contained in:
parent
41e12da90d
commit
f8a3c54f60
2 changed files with 128 additions and 0 deletions
55
packages/field/src/FormRegistrarPortalMixin.js
Normal file
55
packages/field/src/FormRegistrarPortalMixin.js
Normal 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);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
@ -3,6 +3,7 @@ import { LitElement } from '@lion/core';
|
||||||
|
|
||||||
import { FormRegistrarMixin } from '../src/FormRegistrarMixin.js';
|
import { FormRegistrarMixin } from '../src/FormRegistrarMixin.js';
|
||||||
import { FormRegisteringMixin } from '../src/FormRegisteringMixin.js';
|
import { FormRegisteringMixin } from '../src/FormRegisteringMixin.js';
|
||||||
|
import { FormRegistrarPortalMixin } from '../src/FormRegistrarPortalMixin.js';
|
||||||
import { formRegistrarManager } from '../src/formRegistrarManager.js';
|
import { formRegistrarManager } from '../src/formRegistrarManager.js';
|
||||||
|
|
||||||
export const runRegistrationSuite = customConfig => {
|
export const runRegistrationSuite = customConfig => {
|
||||||
|
|
@ -15,6 +16,7 @@ export const runRegistrationSuite = customConfig => {
|
||||||
describe(`FormRegistrationMixins${cfg.suffix ? ` (${cfg.suffix})` : ''}`, () => {
|
describe(`FormRegistrationMixins${cfg.suffix ? ` (${cfg.suffix})` : ''}`, () => {
|
||||||
let parentTag;
|
let parentTag;
|
||||||
let childTag;
|
let childTag;
|
||||||
|
let portalTag;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
if (!cfg.parentTagString) {
|
if (!cfg.parentTagString) {
|
||||||
|
|
@ -23,9 +25,13 @@ export const runRegistrationSuite = customConfig => {
|
||||||
if (!cfg.childTagString) {
|
if (!cfg.childTagString) {
|
||||||
cfg.childTagString = defineCE(class extends FormRegisteringMixin(cfg.baseElement) {});
|
cfg.childTagString = defineCE(class extends FormRegisteringMixin(cfg.baseElement) {});
|
||||||
}
|
}
|
||||||
|
if (!cfg.portalTagString) {
|
||||||
|
cfg.portalTagString = defineCE(class extends FormRegistrarPortalMixin(cfg.baseElement) {});
|
||||||
|
}
|
||||||
|
|
||||||
parentTag = unsafeStatic(cfg.parentTagString);
|
parentTag = unsafeStatic(cfg.parentTagString);
|
||||||
childTag = unsafeStatic(cfg.childTagString);
|
childTag = unsafeStatic(cfg.childTagString);
|
||||||
|
portalTag = unsafeStatic(cfg.portalTagString);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can register a formElement', async () => {
|
it('can register a formElement', async () => {
|
||||||
|
|
@ -117,5 +123,72 @@ export const runRegistrationSuite = customConfig => {
|
||||||
el.removeChild(newField);
|
el.removeChild(newField);
|
||||||
expect(el.formElements.length).to.equal(1);
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue