Skip to content

Commit

Permalink
Make requests pausable (#306)
Browse files Browse the repository at this point in the history
  • Loading branch information
kirillplatonov authored Jul 12, 2021
1 parent 8e8a01d commit cd27e50
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/http/fetch_request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export class FetchRequest {
readonly url: URL
readonly body?: FetchRequestBody
readonly abortController = new AbortController
private resolveRequestPromise = (value: any) => {}

constructor(delegate: FetchRequestDelegate, method: FetchMethod, location: URL, body: FetchRequestBody = new URLSearchParams) {
this.delegate = delegate
Expand Down Expand Up @@ -78,7 +79,7 @@ export class FetchRequest {
async perform(): Promise<FetchResponse> {
const { fetchOptions } = this
this.delegate.prepareHeadersForRequest?.(this.headers, this)
dispatch("turbo:before-fetch-request", { detail: { fetchOptions } })
await this.allowRequestToBeIntercepted(fetchOptions)
try {
this.delegate.requestStarted(this)
const response = await fetch(this.url.href, fetchOptions)
Expand Down Expand Up @@ -128,6 +129,12 @@ export class FetchRequest {
get abortSignal() {
return this.abortController.signal
}

private async allowRequestToBeIntercepted(fetchOptions: RequestInit) {
const requestInterception = new Promise(resolve => this.resolveRequestPromise = resolve)
const event = dispatch("turbo:before-fetch-request", { cancelable: true, detail: { fetchOptions, resume: this.resolveRequestPromise } })
if (event.defaultPrevented) await requestInterception
}
}

function mergeFormDataEntries(url: URL, entries: [string, FormDataEntryValue][]): URL {
Expand Down
25 changes: 25 additions & 0 deletions src/tests/fixtures/pausable_requests.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Turbo</title>
<script src="/dist/turbo.es2017-umd.js" data-turbo-track="reload"></script>
<script src="/src/tests/fixtures/test.js"></script>
<script type="module">
addEventListener('turbo:before-fetch-request', function(event) {
event.preventDefault()
if (confirm('Continue request?')) {
event.detail.resume()
} else {
alert('Request aborted')
}
})
</script>
</head>
<body>
<section>
<h1>Pausable Requests</h1>
<p><a id="link" href="/src/tests/fixtures/one.html">Link</a></p>
</section>
</body>
</html>
1 change: 1 addition & 0 deletions src/tests/functional/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export * from "./import_tests"
export * from "./loading_tests"
export * from "./navigation_tests"
export * from "./pausable_rendering_tests"
export * from "./pausable_requests_tests"
export * from "./rendering_tests"
export * from "./scroll_restoration_tests"
export * from "./stream_tests"
Expand Down
35 changes: 35 additions & 0 deletions src/tests/functional/pausable_requests_tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { TurboDriveTestCase } from "../helpers/turbo_drive_test_case"

export class PausableRequestsTests extends TurboDriveTestCase {
async setup() {
await this.goToLocation("/src/tests/fixtures/pausable_requests.html")
}

async "test pauses and resumes request"() {
await this.clickSelector("#link")

await this.nextBeat
this.assert.strictEqual(await this.getAlertText(), 'Continue request?')
await this.acceptAlert()

const h1 = await this.querySelector("h1")
this.assert.equal(await h1.getVisibleText(), "One")
}

async "test aborts request"() {
await this.clickSelector("#link")

await this.nextBeat
this.assert.strictEqual(await this.getAlertText(), 'Continue request?')
await this.dismissAlert()

await this.nextBeat
this.assert.strictEqual(await this.getAlertText(), 'Request aborted')
await this.acceptAlert()

const h1 = await this.querySelector("h1")
this.assert.equal(await h1.getVisibleText(), "Pausable Requests")
}
}

PausableRequestsTests.registerSuite()

0 comments on commit cd27e50

Please sign in to comment.