diff --git a/src/core/drive/navigator.ts b/src/core/drive/navigator.ts index 935f9eea7..1b8f00d42 100644 --- a/src/core/drive/navigator.ts +++ b/src/core/drive/navigator.ts @@ -87,7 +87,8 @@ export class Navigator { if (formSubmission == this.formSubmission) { const responseHTML = await fetchResponse.responseHTML if (responseHTML) { - if (formSubmission.method != FetchMethod.get) { + const shouldCacheSnapshot = formSubmission.method == FetchMethod.get + if (!shouldCacheSnapshot) { this.view.clearSnapshotCache() } @@ -95,6 +96,7 @@ export class Navigator { const action = this.getActionForFormSubmission(formSubmission) const visitOptions = { action, + shouldCacheSnapshot, response: { statusCode, responseHTML, redirected }, } this.proposeVisit(fetchResponse.location, visitOptions) diff --git a/src/core/drive/visit.ts b/src/core/drive/visit.ts index abc9a0c15..9c6566658 100644 --- a/src/core/drive/visit.ts +++ b/src/core/drive/visit.ts @@ -45,6 +45,7 @@ export type VisitOptions = { response?: VisitResponse visitCachedSnapshot(snapshot: Snapshot): void willRender: boolean + shouldCacheSnapshot: boolean } const defaultOptions: VisitOptions = { @@ -52,6 +53,7 @@ const defaultOptions: VisitOptions = { historyChanged: false, visitCachedSnapshot: () => {}, willRender: true, + shouldCacheSnapshot: true, } export type VisitResponse = { @@ -85,6 +87,7 @@ export class Visit implements FetchRequestDelegate { request?: FetchRequest response?: VisitResponse scrolled = false + shouldCacheSnapshot = true snapshotHTML?: string snapshotCached = false state = VisitState.initialized @@ -99,7 +102,16 @@ export class Visit implements FetchRequestDelegate { this.location = location this.restorationIdentifier = restorationIdentifier || uuid() - const { action, historyChanged, referrer, snapshotHTML, response, visitCachedSnapshot, willRender } = { + const { + action, + historyChanged, + referrer, + snapshotHTML, + response, + visitCachedSnapshot, + willRender, + shouldCacheSnapshot, + } = { ...defaultOptions, ...options, } @@ -112,6 +124,7 @@ export class Visit implements FetchRequestDelegate { this.visitCachedSnapshot = visitCachedSnapshot this.willRender = willRender this.scrolled = !willRender + this.shouldCacheSnapshot = shouldCacheSnapshot } get adapter() { @@ -225,7 +238,7 @@ export class Visit implements FetchRequestDelegate { if (this.response) { const { statusCode, responseHTML } = this.response this.render(async () => { - this.cacheSnapshot() + if (this.shouldCacheSnapshot) this.cacheSnapshot() if (this.view.renderPromise) await this.view.renderPromise if (isSuccessful(statusCode) && responseHTML != null) { await this.view.renderPage(PageSnapshot.fromHTMLString(responseHTML), false, this.willRender, this) diff --git a/src/tests/fixtures/navigation.html b/src/tests/fixtures/navigation.html index e7e93b93b..54cd56547 100644 --- a/src/tests/fixtures/navigation.html +++ b/src/tests/fixtures/navigation.html @@ -47,6 +47,10 @@

Navigation

+
+ + +

Same-origin data-turbo=false link

Same-origin unannotated link inside data-turbo=false container

Same-origin data-turbo=true link inside data-turbo=false container

diff --git a/src/tests/functional/form_submission_tests.ts b/src/tests/functional/form_submission_tests.ts index 613fb24a6..009a9098d 100644 --- a/src/tests/functional/form_submission_tests.ts +++ b/src/tests/functional/form_submission_tests.ts @@ -146,7 +146,6 @@ test("test standard POST form submission events", async ({ page }) => { await nextEventNamed(page, "turbo:before-visit") await nextEventNamed(page, "turbo:visit") - await nextEventNamed(page, "turbo:before-cache") await nextEventNamed(page, "turbo:before-render") await nextEventNamed(page, "turbo:render") await nextEventNamed(page, "turbo:load") diff --git a/src/tests/functional/navigation_tests.ts b/src/tests/functional/navigation_tests.ts index cc39c1a10..afaf54221 100644 --- a/src/tests/functional/navigation_tests.ts +++ b/src/tests/functional/navigation_tests.ts @@ -136,6 +136,19 @@ test("test following a same-origin POST form button[data-turbo-action=replace]", assert.equal(await visitAction(page), "replace") }) +test("test following a POST form clears cache", async ({ page }) => { + await page.evaluate(() => { + const cachedElement = document.createElement("some-cached-element") + document.body.appendChild(cachedElement) + }) + + await page.click("#form-post-submit") + await nextBeat() // 301 redirect response + await nextBeat() // 200 response + await page.goBack() + assert.notOk(await hasSelector(page, "some-cached-element")) +}) + test("test following a same-origin data-turbo=false link", async ({ page }) => { page.click("#same-origin-false-link") await nextBody(page)