Skip to content

Commit

Permalink
Add test coverage for turbo-frame[busy]
Browse files Browse the repository at this point in the history
During the request lifecycle, `<turbo-frame>` elements will toggle the
`[busy]` boolean attribute to true when the request starts, and then
remove it when the request ends.

This commit adds functional test coverage for that behavior.
  • Loading branch information
seanpdoyle committed Feb 4, 2021
1 parent 57a118e commit 79950a7
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 4 deletions.
6 changes: 4 additions & 2 deletions src/core/frames/frame_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ export class FrameController implements AppearanceObserverDelegate, FetchRequest
// Form submission delegate

formSubmissionStarted(formSubmission: FormSubmission) {

const frame = this.findFrameElement(formSubmission.formElement)
frame.setAttribute("busy", "")
}

formSubmissionSucceededWithResponse(formSubmission: FormSubmission, response: FetchResponse) {
Expand All @@ -175,7 +176,8 @@ export class FrameController implements AppearanceObserverDelegate, FetchRequest
}

formSubmissionFinished(formSubmission: FormSubmission) {

const frame = this.findFrameElement(formSubmission.formElement)
frame.removeAttribute("busy")
}

// View delegate
Expand Down
7 changes: 6 additions & 1 deletion src/tests/fixtures/form.html
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,15 @@
</div>
<hr>
<div id="targets-frame">
<form action="/__turbo/redirect" method="post" data-turbo-frame="frame">
<form action="/__turbo/redirect" method="post" data-turbo-frame="frame" class="one">
<input type="hidden" name="path" value="/src/tests/fixtures/one.html">
<button type="submit">Submit</button>
</form>

<form action="/__turbo/redirect" method="post" data-turbo-frame="frame" class="frame">
<input type="hidden" name="path" value="/src/tests/fixtures/frames/frame.html">
<button type="submit">Submit</button>
</form>
</div>
<turbo-frame id="frame">
<h2>Frame: Form</h2>
Expand Down
22 changes: 21 additions & 1 deletion src/tests/functional/form_submission_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,26 @@ export class FormSubmissionTests extends TurboDriveTestCase {
this.assert.equal(await this.pathname, "/src/tests/fixtures/form.html")
}

async "test frame form submission toggles the ancestor frame's [busy] attribute"() {
this.observeAttributeChanges("frame", "busy")
await this.clickSelector("#frame form.redirect input[type=submit]")
await this.nextBeat

this.assert.ok(await this.hasSelector("turbo-frame[id=frame][data-was-busy=true]"))
this.assert.notOk(await this.hasSelector("turbo-frame[id=frame][busy]"))
}

async "test frame form submission toggles the target frame's [busy] attribute"() {
this.observeAttributeChanges("frame", "busy")
await this.clickSelector('#targets-frame form.frame [type="submit"]')
await this.nextBeat

const title = await this.querySelector("#frame h2")
this.assert.equal(await title.getVisibleText(), "Frame: Loaded")
this.assert.ok(await this.hasSelector("turbo-frame[id=frame][data-was-busy=true]"))
this.assert.notOk(await this.hasSelector("turbo-frame[id=frame][busy]"))
}

async "test frame form submission with empty created response"() {
const htmlBefore = await this.outerHTMLForSelector("#frame")
const button = await this.querySelector("#frame form.created input[type=submit]")
Expand Down Expand Up @@ -254,7 +274,7 @@ export class FormSubmissionTests extends TurboDriveTestCase {

async "test form submission targets disabled frame"() {
this.remote.execute(() => document.getElementById("frame")?.setAttribute("disabled", ""))
await this.clickSelector('#targets-frame [type="submit"]')
await this.clickSelector('#targets-frame form.one [type="submit"]')
await this.nextBody

this.assert.equal(await this.pathname, "/src/tests/fixtures/one.html")
Expand Down
9 changes: 9 additions & 0 deletions src/tests/functional/frame_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ export class FrameTests extends FunctionalTestCase {
await this.goToLocation("/src/tests/fixtures/frames.html")
}

async "test following a link driving a frame toggles the [busy] attribute"() {
await this.observeAttributeChanges("frame", "busy")
await this.clickSelector("#hello a")
await this.nextBeat

this.assert.ok(await this.hasSelector("turbo-frame[id=frame][data-was-busy=true]"))
this.assert.notOk(await this.hasSelector("turbo-frame[id=frame][busy]"))
}

async "test following a link to a page without a matching frame results in an empty frame"() {
await this.clickSelector("#missing a")
await this.nextBeat
Expand Down
20 changes: 20 additions & 0 deletions src/tests/helpers/functional_test_case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,26 @@ export class FunctionalTestCase extends InternTestCase {
return offset > -1 && offset < 1
}

async observeAttributeChanges(elementId: string, attribute: string) {
await this.remote.execute((id: string, attributeName: string) => {
const element = document.getElementById(id)

if (element) {
new MutationObserver((mutations) => {
for (const { target } of mutations) {
if (target instanceof HTMLElement) {
const value = target.getAttribute(attributeName)
const booleanValue = value == "" || value == "true"
if (booleanValue) {
target.setAttribute(`data-was-${attributeName}`, booleanValue.toString())
}
}
}
}).observe(element, { attributeFilter: [attributeName] })
}
}, [elementId, attribute])
}

get nextBeat(): Promise<void> {
return new Promise(resolve => setTimeout(resolve, 100))
}
Expand Down

0 comments on commit 79950a7

Please sign in to comment.