Skip to content

Commit

Permalink
Skip Snapshot Caching for redirect visits
Browse files Browse the repository at this point in the history
Closes [#794][]

Reverts the implementation change made in [#674][], and in
its place passes `shouldCacheSnapshot: false` alongside `willRender:
false` for the `action: "replace"` Visit proposed when following a
redirect.

In order to test this behavior, this commit introduces the
`readBodyMutationLogs` test utility function, along with the
`window.bodyMutationLogs` property and the `BodyMutationLog` type.

`BodyMutationLog` instances are pushed onto the log `Array` whenever the
`<body>` element is replaced.

[#794]: #794
[#674]: #674
  • Loading branch information
seanpdoyle committed Nov 25, 2022
1 parent 00b287a commit 903d552
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/core/drive/visit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,8 @@ export class Visit implements FetchRequestDelegate {
this.adapter.visitProposedToLocation(this.redirectedToLocation, {
action: "replace",
response: this.response,
shouldCacheSnapshot: false,
willRender: false,
})
this.followedRedirect = true
}
Expand Down
1 change: 1 addition & 0 deletions src/tests/fixtures/rendering.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ <h1>Rendering</h1>
<p><a id="permanent-in-frame-element-link" href="/src/tests/fixtures/permanent_element.html" data-turbo-frame="frame">Permanent element in frame</a></p>
<p><a id="permanent-in-frame-without-layout-element-link" href="/src/tests/fixtures/frames/without_layout.html" data-turbo-frame="frame">Permanent element in frame without layout</a></p>
<p><a id="delayed-link" href="/__turbo/delayed_response">Delayed link</a></p>
<p><a id="redirect-link" href="/__turbo/redirect">Redirect link</a></p>
<form>
<input type="text" id="text-input">
<input type="radio" id="radio-input">
Expand Down
11 changes: 11 additions & 0 deletions src/tests/fixtures/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@
}
}
}).observe(document, { subtree: true, childList: true, attributes: true })

window.bodyMutationLogs = []
addEventListener("turbo:load", () => {
new MutationObserver((mutations) => {
for (const { addedNodes } of mutations) {
for (const { localName, outerHTML } of addedNodes) {
if (localName == "body") bodyMutationLogs.push([outerHTML])
}
}
}).observe(document.documentElement, { childList: true })
}, { once: true })
})([
"turbo:click",
"turbo:before-stream-render",
Expand Down
9 changes: 9 additions & 0 deletions src/tests/functional/rendering_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import {
isScrolledToTop,
nextBeat,
nextBody,
nextBodyMutation,
nextEventNamed,
noNextBodyMutation,
pathname,
propertyForSelector,
readEventLogs,
Expand Down Expand Up @@ -538,6 +540,13 @@ test("test error pages", async ({ page }) => {
assert.equal(await page.textContent("body"), "404 Not Found: /nonexistent\n")
})

test("test rendering a redirect response replaces the body once and only once", async ({ page }) => {
await page.click("#redirect-link")
await nextBodyMutation(page)

assert.ok(await noNextBodyMutation(page), "replaces <body> element once")
})

function deepElementsEqual(
page: Page,
left: JSHandle<SVGElement | HTMLElement>[],
Expand Down
20 changes: 20 additions & 0 deletions src/tests/helpers/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ type MutationAttributeName = string
type MutationAttributeValue = string | null
type MutationLog = [MutationAttributeName, Target, MutationAttributeValue]

type BodyHTML = string
type BodyMutationLog = [BodyHTML]

export function attributeForSelector(page: Page, selector: string, attributeName: string): Promise<string | null> {
return page.locator(selector).getAttribute(attributeName)
}
Expand Down Expand Up @@ -112,6 +115,19 @@ export async function listenForEventOnTarget(page: Page, elementId: string, even
}, eventName)
}

export async function nextBodyMutation(page: Page): Promise<string | null> {
let record: BodyMutationLog | undefined
while (!record) {
;[record] = await readBodyMutationLogs(page, 1)
}
return record[0]
}

export async function noNextBodyMutation(page: Page): Promise<boolean> {
const records = await readBodyMutationLogs(page, 1)
return !records.some((record) => !!record)
}

export async function nextAttributeMutationNamed(
page: Page,
elementId: string,
Expand Down Expand Up @@ -174,6 +190,10 @@ async function readArray<T>(page: Page, identifier: string, length?: number): Pr
)
}

export function readBodyMutationLogs(page: Page, length?: number): Promise<BodyMutationLog[]> {
return readArray<BodyMutationLog>(page, "bodyMutationLogs", length)
}

export function readEventLogs(page: Page, length?: number): Promise<EventLog[]> {
return readArray<EventLog>(page, "eventLogs", length)
}
Expand Down

0 comments on commit 903d552

Please sign in to comment.