fix(form-core): make sure renamed Required validator are identified as such, while remaining compatible with multiple versions

This commit is contained in:
Thijs Louisse 2025-07-29 17:49:13 +02:00 committed by Thijs Louisse
parent 57eec5b599
commit 64b72a049e
3 changed files with 41 additions and 4 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/ui': patch
---
[form-core] make sure renamed Required validator are identified as such, while remaining compatible with multiple versions

View file

@ -420,6 +420,22 @@ export const ValidateMixinImplementation = superclass =>
await this.__executeValidators();
}
/**
* @param {Validator} validator
* @returns {boolean}
*/
#isInstanceOfRequiredValidator(validator) {
// walk prototype and check if validatorName is 'Required'
let validatorLvlInPrototype = validator;
while (validatorLvlInPrototype) {
const ctor = /** @type {typeof Validator} */ (validatorLvlInPrototype.constructor);
if (ctor.validatorName === 'Required') return true;
validatorLvlInPrototype = Object.getPrototypeOf(validatorLvlInPrototype);
}
return false;
}
/**
* @desc step a1-3 + b (as explained in `validate()`)
*/
@ -482,7 +498,7 @@ export const ValidateMixinImplementation = superclass =>
for (const v of this._allValidators) {
if (/** @type {MetaValidator} */ (v)?.executeOnResults) {
metaValidators.push(/** @type {MetaValidator} */ (v));
} else if (/** @type {typeof Validator} */ (v.constructor)?.validatorName === 'Required') {
} else if (this.#isInstanceOfRequiredValidator(v)) {
// Required validator was already handled
} else if (/** @type {typeof Validator} */ (v.constructor).async) {
asyncValidators.push(v);

View file

@ -130,6 +130,7 @@ export function runValidateMixinSuite(customConfig) {
expect(el.hasFeedbackFor).to.deep.equal(['error']);
});
// TODO: keep this use case for backwards compatibility or just required extending Required?
it('determines whether the "Required" validator was already handled by judging the validatorName', async () => {
class BundledValidator extends EventTarget {
static ['_$isValidator$'] = true;
@ -163,9 +164,7 @@ export function runValidateMixinSuite(customConfig) {
}
class BundledRequired extends BundledValidator {
static get validatorName() {
return 'Required';
}
static validatorName = 'Required';
}
const el = /** @type {ValidateElement} */ (
@ -180,6 +179,23 @@ export function runValidateMixinSuite(customConfig) {
expect(el.hasFeedbackFor).to.deep.equal([]);
});
it('determines whether the "Required" validator was already handled by judging the validatorName', async () => {
class MyRequired extends Required {
static validatorName = 'SomethingOtherThanRequired';
}
const el = /** @type {ValidateElement} */ (
await fixture(html`
<${tag}
.validators=${[new MyRequired()]}
.modelValue=${'myValue'}
>${lightDom}</${tag}>
`)
);
expect(el.hasFeedbackFor).to.deep.equal([]);
});
it('determines whether the passed Validators are ResultValidators judging by the presence of "executeOnResults"', async () => {
class ValidateElementWithSuccessType extends ValidateElement {
static get validationTypes() {