Skip to content

Commit

Permalink
fix(validator): validator report customError. Fix #5302
Browse files Browse the repository at this point in the history
  • Loading branch information
christophe-g committed Dec 18, 2023
1 parent 839667d commit d19e809
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 8 deletions.
2 changes: 1 addition & 1 deletion labs/behaviors/constraint-validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ export function mixinConstraintValidation<
const {validity, validationMessage: nonCustomValidationMessage} =
this[privateValidator].getValidity();

const customError = !!this[privateCustomValidationMessage];
const customError = !!this[privateCustomValidationMessage] || validity.customError;
const validationMessage =
this[privateCustomValidationMessage] || nonCustomValidationMessage;

Expand Down
84 changes: 77 additions & 7 deletions labs/behaviors/constraint-validation_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@

// import 'jasmine'; (google3-only)

import {LitElement, html} from 'lit';
import {customElement, property} from 'lit/decorators.js';
import { LitElement, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';

import {
createValidator,
getValidityAnchor,
mixinConstraintValidation,
} from './constraint-validation.js';
import {mixinElementInternals} from './element-internals.js';
import {getFormValue, mixinFormAssociated} from './form-associated.js';
import {CheckboxValidator} from './validators/checkbox-validator.js';
import { mixinElementInternals } from './element-internals.js';
import { getFormValue, mixinFormAssociated } from './form-associated.js';
import { CheckboxValidator } from './validators/checkbox-validator.js';
import { Validator } from './validators/validator.js';
import { SelectState } from './validators/select-validator.js';

describe('mixinConstraintValidation()', () => {
const baseClass = mixinConstraintValidation(
Expand All @@ -25,8 +27,8 @@ describe('mixinConstraintValidation()', () => {

@customElement('test-constraint-validation')
class TestConstraintValidation extends baseClass {
@property({type: Boolean}) checked = false;
@property({type: Boolean}) required = false;
@property({ type: Boolean }) checked = false;
@property({ type: Boolean }) required = false;

override render() {
return html`<div id="root"></div>`;
Expand All @@ -45,6 +47,52 @@ describe('mixinConstraintValidation()', () => {
}
}

/**
* A validator that set customError flag to true
*/
class CustomErrorValidator extends Validator<SelectState> {
private control?: HTMLInputElement;

protected override computeValidity(state: SelectState) {
if (!this.control) {
this.control = document.createElement('input');
}
this.control.setCustomValidity('validator custom error');
return {
validity: this.control.validity,
validationMessage: this.control.validationMessage,
};
}

protected override equals(prev: SelectState, next: SelectState) {
return prev.value === next.value
}

protected override copy({ value, required }: SelectState) {
return { value, required };
}
}

@customElement('test-custom-error-constraint-validation')
class TestCustomErrorConstraintValidation extends baseClass {
@property() value = '';
@property({ type: Boolean }) required = false;
override render() {
return html`<div id="root"></div>`;
}
[createValidator]() {
return new CustomErrorValidator(() => this);
}

[getValidityAnchor]() {
return this.shadowRoot?.querySelector<HTMLElement>('#root') ?? null;
}

[getFormValue]() {
return String(this.value);
}
}

describe('validity', () => {
it('should return a ValidityState value', () => {
const control = new TestConstraintValidation();
Expand Down Expand Up @@ -174,4 +222,26 @@ describe('mixinConstraintValidation()', () => {
.toBe('Error');
});
});

describe('customError', () => {
it('should set customError to true when validator has customError', () => {
const control = new TestCustomErrorConstraintValidation();
expect(control.validity.customError)
.withContext('validity.customError')
.toBeTrue();
});
it('should dispatch invalid event when validator has customError', () => {
const control = new TestCustomErrorConstraintValidation();
const invalidListener = jasmine.createSpy('invalidListener');
control.addEventListener('invalid', invalidListener);
control.reportValidity();
expect(invalidListener).toHaveBeenCalledWith(jasmine.any(Event));
});
it('should report custom validation message over other validation messages', () => {
const control = new TestCustomErrorConstraintValidation();
expect(control.validationMessage)
.withContext('validationMessage')
.toBe('validator custom error');
});
})
});

0 comments on commit d19e809

Please sign in to comment.