Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Override Frame response target from server #397

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions src/core/frames/frame_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,16 @@ export class FrameController implements AppearanceObserverDelegate, FetchRequest
}

async requestSucceededWithResponse(request: FetchRequest, response: FetchResponse) {
await this.loadResponse(response)
this.resolveVisitPromise()
const { location, redirected, statusCode } = response

if (redirected && response.header("Turbo-Frame") == "_top") {
const responseHTML = await response.responseHTML

session.visit(location, { response: { statusCode, redirected, responseHTML } })
} else {
await this.loadResponse(response)
this.resolveVisitPromise()
}
}

requestFailedWithResponse(request: FetchRequest, response: FetchResponse) {
Expand All @@ -197,9 +205,18 @@ export class FrameController implements AppearanceObserverDelegate, FetchRequest
frame.setAttribute("busy", "")
}

formSubmissionSucceededWithResponse(formSubmission: FormSubmission, response: FetchResponse) {
const frame = this.findFrameElement(formSubmission.formElement, formSubmission.submitter)
frame.delegate.loadResponse(response)
async formSubmissionSucceededWithResponse(formSubmission: FormSubmission, response: FetchResponse) {
const { location, redirected, statusCode } = response

if (redirected && response.header("Turbo-Frame") == "_top") {
const responseHTML = await response.responseHTML

session.view.clearSnapshotCache()
session.visit(location, { response: { statusCode, redirected, responseHTML } })
} else {
const frame = this.findFrameElement(formSubmission.formElement, formSubmission.submitter)
frame.delegate.loadResponse(response)
}
}

formSubmissionFailedWithResponse(formSubmission: FormSubmission, fetchResponse: FetchResponse) {
Expand Down
5 changes: 5 additions & 0 deletions src/tests/fixtures/form.html
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,11 @@ <h2>Frame: Form</h2>
<input type="hidden" name="path" value="/src/tests/fixtures/frames/form.html">
<input type="submit">
</form>
<form action="/__turbo/redirect" method="post" class="redirect turbo-frame-header">
<input type="hidden" name="turbo_frame" value="_top">
<input type="hidden" name="path" value="/__turbo/headers">
<button>response with Turbo-Frame: _top</button>
</form>
<form action="/__turbo/messages" method="post" class="created">
<input type="hidden" name="content" value="Hello!">
<input type="submit" style="">
Expand Down
1 change: 1 addition & 0 deletions src/tests/fixtures/frames.html
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ <h2>Frames: #nested-child</h2>
</turbo-frame>

<a id="frame-self" href="/src/tests/fixtures/frames/self.html" data-turbo-frame="frame">Visit self.html</a>
<a id="navigate-form-redirect-top" href="/__turbo/redirect?turbo_frame=_top&path=%2F__turbo%2Fheaders" data-turbo-frame="frame">Response with Turbo-Frame: _top</a>

<a id="navigate-form-redirect" href="/src/tests/fixtures/frames/form-redirect.html" data-turbo-frame="form-redirect">Visit form-redirect.html</a>
<turbo-frame id="form-redirect"></turbo-frame>
Expand Down
12 changes: 12 additions & 0 deletions src/tests/functional/form_submission_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,18 @@ export class FormSubmissionTests extends TurboDriveTestCase {
this.assert.equal(await title.getVisibleText(), "Frame: Unprocessable Entity")
}

async "test frame form submission response with Turbo-Frame=_top header"() {
await this.clickSelector("#frame form.redirect.turbo-frame-header button")
await this.nextEventNamed("turbo:before-fetch-request")
await this.nextEventNamed("turbo:before-fetch-response")
const eventLog = await this.eventLogChannel.read()
await this.nextBody

this.assert.notOk(await this.hasSelector("#frame"), "Navigates entire page")
this.assert.equal(await (await this.querySelector("h1")).getVisibleText(), "Request Headers")
this.assert.notOk(eventLog.some(([ name ]) => name == "turbo:before-fetch-request" || name == "turbo:before-fetch-response"), "does not make subsequent requests")
}

async "test invalid frame form submission with internal server errror status"() {
await this.clickSelector("#frame form.internal_server_error input[type=submit]")
await this.nextBeat
Expand Down
12 changes: 12 additions & 0 deletions src/tests/functional/frame_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ export class FrameTests extends TurboDriveTestCase {
this.assert.equal(otherEvents.length, 0, "no more events")
}

async "test a frame request with Turbo-Frame=_top header in response"() {
await this.clickSelector("#navigate-form-redirect-top")
await this.nextEventOnTarget("frame", "turbo:before-fetch-request")
await this.nextEventOnTarget("frame", "turbo:before-fetch-response")
const eventLog = await this.eventLogChannel.read()
await this.nextBody

this.assert.notOk(await this.hasSelector("#frame"), "Navigates entire page")
this.assert.equal(await (await this.querySelector("h1")).getVisibleText(), "Request Headers")
this.assert.notOk(eventLog.some(([ name ]) => name == "turbo:before-fetch-request" || name == "turbo:before-fetch-response"), "does not make subsequent requests")
}

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

Expand Down
4 changes: 4 additions & 0 deletions src/tests/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ router.post("/reject", (request, response) => {

router.get("/headers", (request, response) => {
const template = fs.readFileSync("src/tests/fixtures/headers.html").toString()
const { turbo_frame } = request.query

if (typeof turbo_frame == "string") response.set("Turbo-Frame", turbo_frame)

response.type("html").status(200).send(template.replace('$HEADERS', JSON.stringify(request.headers, null, 4)))
})

Expand Down