Skip to content

Commit

Permalink
test: add input tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Enes5519 committed Dec 9, 2024
1 parent 93c2148 commit 1b9636f
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 6 deletions.
37 changes: 37 additions & 0 deletions src/components/input/bl-input.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,43 @@ describe("bl-input", () => {
expect(errorMessageElement).to.visible;
});

it("should show custom error", async () => {
const errorMessage = "This field is mandatory";
const el = await fixture<BlInput>(
html`<bl-input error="${errorMessage}"></bl-input>`
);

await elementUpdated(el);

const errorMessageElement = <HTMLParagraphElement>(
el.shadowRoot?.querySelector(".invalid-text")
);

expect(el.validity.valid).to.be.false;

expect(errorMessageElement).to.exist;
expect(errorMessageElement?.innerText).to.equal(errorMessage);
});

it("should show custom invalid text", async () => {
const invalidText = "This field is mandatory";
const el = await fixture<BlInput>(html`<bl-input required></bl-input>`);

el.setCustomValidity(invalidText);
el.setValue(el.value);
el.reportValidity();

await elementUpdated(el);

expect(el.validity.valid).to.be.false;
const errorMessageElement = <HTMLParagraphElement>(
el.shadowRoot?.querySelector(".invalid-text")
);

expect(errorMessageElement).to.visible;
expect(errorMessageElement?.innerText).to.equal(invalidText);
});

it("should set custom error state with forceCustomError method", async () => {
const el = await fixture<BlInput>(html`<bl-input></bl-input>`);

Expand Down
4 changes: 2 additions & 2 deletions src/components/input/bl-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ export default class BlInput extends FormControlMixin(LitElement) {
*/
async forceCustomError() {
await this.updateComplete;
this.validationTarget.setCustomValidity(this.customInvalidText || "An error occurred");
this.setCustomValidity(this.customInvalidText || "An error occurred");
this.setValue(this.value);
this.reportValidity();
}
Expand All @@ -293,7 +293,7 @@ export default class BlInput extends FormControlMixin(LitElement) {
*/
async clearCustomError() {
await this.updateComplete;
this.validationTarget.setCustomValidity("");
this.setCustomValidity("");
this.setValue(this.value);
this.reportValidity();
}
Expand Down
37 changes: 37 additions & 0 deletions src/components/textarea/bl-textarea.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,43 @@ describe("bl-textarea", () => {
expect(errorMsgElement).to.exist;
expect(errorMsgElement.innerText).to.equal(customErrorMsg);
});

it("should show custom error", async () => {
const errorMessage = "This field is mandatory";
const el = await fixture<BlTextarea>(
html`<bl-textarea error="${errorMessage}"></bl-textarea>`
);

await elementUpdated(el);

const errorMessageElement = <HTMLParagraphElement>(
el.shadowRoot?.querySelector(".invalid-text")
);

expect(el.validity.valid).to.be.false;

expect(errorMessageElement).to.exist;
expect(errorMessageElement?.innerText).to.equal(errorMessage);
});

it("should show custom invalid text", async () => {
const invalidText = "This field is mandatory";
const el = await fixture<BlTextarea>(html`<bl-textarea required></bl-textarea>`);

el.setCustomValidity(invalidText);
el.setValue(el.value);
el.reportValidity();

await elementUpdated(el);

expect(el.validity.valid).to.be.false;
const errorMessageElement = <HTMLParagraphElement>(
el.shadowRoot?.querySelector(".invalid-text")
);

expect(errorMessageElement).to.visible;
expect(errorMessageElement?.innerText).to.equal(invalidText);
});
});

describe("events", () => {
Expand Down
31 changes: 29 additions & 2 deletions src/utilities/form-control.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { elementUpdated, expect, fixture, fixtureCleanup } from "@open-wc/testing";
import { html, LitElement } from "lit";
import { customElement, query } from "lit/decorators.js";
import { customElement, query, property } from "lit/decorators.js";
import { innerInputValidators, textareaLengthValidator } from "./form-control";

@customElement("my-valid-input")
Expand All @@ -13,19 +13,35 @@ class MyInvalidInput extends LitElement {
@query("input")
validationTarget: HTMLInputElement;

@property({ reflect: true, type: String })
error: string = "";

render() {
return html`<input required />`;
}
}

@customElement("my-custom-error-input")
class MyCustomErrorInput extends LitElement {
@query("input")
validationTarget: HTMLInputElement;

@property({ reflect: true, type: String })
error: string = "";

render() {
return html`<input />`;
}
}

describe("Form Control Validators", () => {
describe("innerInputValidators", () => {
afterEach(fixtureCleanup);

it("should return true if validationTarget is not present", async () => {
const el = await fixture<MyValidInput>(html`<my-valid-input></my-valid-input>`);

expect(innerInputValidators.every(validator => validator.isValid(el, el.validationTarget.value))).to.be.true;
expect(innerInputValidators.every(validator => validator.isValid(el, ""))).to.be.true;
});

it("should return correct value if validationTarget present", async () => {
Expand All @@ -38,6 +54,17 @@ describe("Form Control Validators", () => {
"valueMissing"
);
});

it("should return false when has custom error", async () => {
const el = await fixture<MyCustomErrorInput>(html`<my-custom-error-input error="sa"></my-custom-error-input>`);

await elementUpdated(el);

expect(innerInputValidators.every(validator => validator.isValid(el, el.validationTarget.value))).to.be.false;
expect(innerInputValidators.find(validator => !validator.isValid(el, el.validationTarget.value))?.key).to.eq(
"customError"
);
});
});

describe("textareaLengthValidator", () => {
Expand Down
21 changes: 19 additions & 2 deletions src/utilities/form-control.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { maxLengthValidator, programmaticValidator, SyncValidator } from "@open-wc/form-control";
import { maxLengthValidator, SyncValidator } from "@open-wc/form-control";

const validityStates: Array<keyof ValidityState> = [
"valueMissing",
Expand All @@ -23,7 +23,24 @@ export const innerInputValidators: SyncValidator[] = validityStates.map(key => (
message: "",
}));

innerInputValidators.push(programmaticValidator as SyncValidator);
innerInputValidators.push({
key: "customError",
attribute: "error",
message(instance) {
return instance.error;
},
isValid(instance: HTMLElement & { error: string; validationTarget: HTMLInputElement }) {
if (instance.error) {
return false;
}

if (instance.validationTarget) {
return !instance.validationTarget.validity["customError"];
}

return true;
},
});

export const textareaLengthValidator = {
...maxLengthValidator,
Expand Down

0 comments on commit 1b9636f

Please sign in to comment.