Skip to content

Commit

Permalink
Merge pull request #1207 from Patternslib/scrum-2646--novalidate
Browse files Browse the repository at this point in the history
fix(pat-inject): Allow to submit invalid forms when form/novalidate.
  • Loading branch information
thet authored Oct 25, 2024
2 parents da5703c + 993d27d commit fa870d1
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 4 deletions.
14 changes: 10 additions & 4 deletions src/pat/inject/inject.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,20 @@ const inject = {
const $el = $(e.currentTarget);
let cfgs = $el.data("pat-inject");
if ($el[0].tagName === "FORM" && e.type === "submit") {
if ($el[0].matches(":invalid")) {
// Do not submit invalid forms.
// Works with native form validation and with pat-validation.
const form = $el[0];
const submitter = e.submitter;

// Do not submit invalid forms, if validation is active.
// Works with native form validation and with pat-validation.
if (
!submitter?.matches("[formnovalidate]") &&
!form.matches("[novalidate]") &&
form.matches(":invalid")
) {
log.debug("Form is invalid, aborting");
return;
}

const submitter = e.submitter;
const formaction = submitter?.getAttribute("formaction");
if (formaction) {
const opts = {
Expand Down
122 changes: 122 additions & 0 deletions src/pat/inject/inject.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1439,6 +1439,128 @@ describe("pat-inject", function () {
expect(pattern.onTrigger).toHaveBeenCalledTimes(1);
});
});

describe("9.2.4.6 - Validation on submit", () => {
it("9.2.4.6.1 - Submit valid forms.", async function () {
document.body.innerHTML = `
<form action="." class="pat-inject">
<input name="ok" />
<button>submit</button>
</form>
`;
jest.spyOn(pattern, "execute");

const form = document.querySelector("form");
const button = form.querySelector("button");

// add submit listener
let catched = false;
form.addEventListener("submit", () => {
catched = true;
});

pattern.init($(form));
await utils.timeout(1); // wait a tick for async to settle.

button.click();

expect(catched).toBe(true);
expect(pattern.execute).toHaveBeenCalled();
});

it("9.2.4.6.2 - Do not submit invalid forms.", async function () {
document.body.innerHTML = `
<form action="." class="pat-inject">
<input name="ok" required />
<button>submit</button>
</form>
`;
jest.spyOn(pattern, "execute");

const form = document.querySelector("form");
const button = form.querySelector("button");

// add submit listener
let catched = false;
form.addEventListener("submit", () => {
catched = true;
});

pattern.init($(form));
await utils.timeout(1); // wait a tick for async to settle.

button.click();

expect(catched).toBe(false);
expect(pattern.execute).not.toHaveBeenCalled();
});

it("9.2.4.6.3 - Respect a form novalidate attribute and allow submission.", async function () {
document.body.innerHTML = `
<form novalidate action="." class="pat-inject">
<input name="ok" required />
<button>submit</button>
</form>
`;
jest.spyOn(pattern, "execute");

const form = document.querySelector("form");
const button = form.querySelector("button");

// add submit listener
let catched = false;
form.addEventListener("submit", () => {
catched = true;
});

pattern.init($(form));
await utils.timeout(1); // wait a tick for async to settle.

button.click();

expect(catched).toBe(true);
expect(pattern.execute).toHaveBeenCalled();
});

// The following test does not work with jsDOM 25.0.1.
// jsDOM supports `form[novalidate]` but not `button[formnovalidate]`
// Ref: https://github.com/jsdom/jsdom/pull/3249
it.skip("9.2.4.6.4 - Respect a formnovalidate attribute on buttons and allow submission.", async function () {
document.body.innerHTML = `
<form action="." class="pat-inject">
<input name="ok" required />
<button class="cancel" formnovalidate>cancel</button>
<button class="submit">submit</button>
</form>
`;
jest.spyOn(pattern, "execute");

const form = document.querySelector("form");
const button_cancel = form.querySelector("button.cancel");
const button_submit = form.querySelector("button.submit");

// add submit listener
let catched = false;
form.addEventListener("submit", () => {
catched = true;
});

pattern.init($(form));
await utils.timeout(1); // wait a tick for async to settle.

button_submit.click();

expect(catched).toBe(false);
expect(pattern.execute).not.toHaveBeenCalled();

button_cancel.click();

expect(catched).toBe(true);
expect(pattern.execute).toHaveBeenCalled();

});

});
});
});
});
Expand Down

0 comments on commit fa870d1

Please sign in to comment.