diff --git a/src/core/drive/form_submission.ts b/src/core/drive/form_submission.ts index e3811de44..3ae6c49ca 100644 --- a/src/core/drive/form_submission.ts +++ b/src/core/drive/form_submission.ts @@ -136,6 +136,8 @@ export class FormSubmission { requestSucceededWithResponse(request: FetchRequest, response: FetchResponse) { if (response.clientError || response.serverError) { + this.result = { success: false, fetchResponse: response } + dispatch("turbo:submit-failed", { target: this.formElement, detail: { formSubmission: this, ...this.result } }) this.delegate.formSubmissionFailedWithResponse(this, response) } else if (this.requestMustRedirect(request) && responseSucceededWithoutRedirect(response)) { const error = new Error("Form responses must redirect to another location") @@ -149,6 +151,7 @@ export class FormSubmission { requestFailedWithResponse(request: FetchRequest, response: FetchResponse) { this.result = { success: false, fetchResponse: response } + dispatch("turbo:submit-failed", { target: this.formElement, detail: { formSubmission: this, ...this.result } }) this.delegate.formSubmissionFailedWithResponse(this, response) } diff --git a/src/tests/functional/form_submission_tests.ts b/src/tests/functional/form_submission_tests.ts index bb2bc34ee..0a0c97a4b 100644 --- a/src/tests/functional/form_submission_tests.ts +++ b/src/tests/functional/form_submission_tests.ts @@ -5,6 +5,7 @@ export class FormSubmissionTests extends TurboDriveTestCase { await this.goToLocation("/src/tests/fixtures/form.html") await this.remote.execute(() => { addEventListener("turbo:submit-start", () => document.documentElement.setAttribute("data-form-submitted", ""), { once: true }) + addEventListener("turbo:submit-failed", () => document.documentElement.setAttribute("data-form-failed", ""), { once: true }) }) } @@ -138,6 +139,7 @@ export class FormSubmissionTests extends TurboDriveTestCase { await this.nextBody const title = await this.querySelector("h1") + this.assert.ok(await this.formFailed) this.assert.equal(await title.getVisibleText(), "Unprocessable Entity", "renders the response HTML") this.assert.notOk(await this.hasSelector("#frame form.reject"), "replaces entire page") } @@ -147,6 +149,7 @@ export class FormSubmissionTests extends TurboDriveTestCase { await this.nextBody const title = await this.querySelector("h1") + this.assert.ok(await this.formFailed) this.assert.equal(await title.getVisibleText(), "Internal Server Error", "renders the response HTML") this.assert.notOk(await this.hasSelector("#frame form.reject"), "replaces entire page") } @@ -349,6 +352,10 @@ export class FormSubmissionTests extends TurboDriveTestCase { this.assert.equal(await message.getVisibleText(), "Link!") } + get formFailed(): Promise { + return this.hasSelector("html[data-form-failed]") + } + get formSubmitted(): Promise { return this.hasSelector("html[data-form-submitted]") }