diff --git a/src/core/drive/page_renderer.ts b/src/core/drive/page_renderer.ts index 04650dea5..1d9392879 100644 --- a/src/core/drive/page_renderer.ts +++ b/src/core/drive/page_renderer.ts @@ -7,8 +7,8 @@ import { nextEventLoopTick } from "../../util" export class PageRenderer extends Renderer { static renderElement(currentElement: HTMLBodyElement, newElement: HTMLBodyElement) { if (document.body && newElement instanceof HTMLBodyElement) { - const currentBody = PageRenderer.getBodyElement(currentElement) - const newBody = PageRenderer.getBodyElement(newElement) + const currentBody = PageRenderer.getBodyElement(currentElement) || currentElement + const newBody = PageRenderer.getBodyElement(newElement) || newElement currentBody.replaceWith(newBody) } else { @@ -17,7 +17,7 @@ export class PageRenderer extends Renderer { } get shouldRender() { - return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical + return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical && this.bodyElementMatches } get reloadReason(): ReloadReason { @@ -32,6 +32,12 @@ export class PageRenderer extends Renderer { reason: "tracked_element_mismatch", } } + + if (!this.bodyElementMatches) { + return { + reason: "body_element_mismatch", + } + } } async prepareToRender() { @@ -94,8 +100,12 @@ export class PageRenderer extends Renderer { return bodyId ? `#${bodyId}` : "body" } - static getBodyElement(element: HTMLElement): HTMLElement { - return element.querySelector(this.bodySelector) || element + static getBodyElement(element: HTMLElement): HTMLElement | null { + if (element.matches(this.bodySelector)) { + return element + } else { + return element.querySelector(this.bodySelector) + } } async copyNewHeadStylesheetElements() { diff --git a/src/tests/fixtures/drive_custom_body.html b/src/tests/fixtures/drive_custom_body.html index 8f0a20929..bfe9cc3cb 100644 --- a/src/tests/fixtures/drive_custom_body.html +++ b/src/tests/fixtures/drive_custom_body.html @@ -13,6 +13,7 @@

Drive (with custom body)

Drive 1

diff --git a/src/tests/fixtures/drive_custom_body_3.html b/src/tests/fixtures/drive_custom_body_3.html new file mode 100644 index 000000000..ae36db305 --- /dev/null +++ b/src/tests/fixtures/drive_custom_body_3.html @@ -0,0 +1,15 @@ + + + + + + Drive (with custom body) + + + + +
+

Drive (with custom body 3)

+
+ + diff --git a/src/tests/functional/drive_custom_body_tests.ts b/src/tests/functional/drive_custom_body_tests.ts index afaed19b8..431c19450 100644 --- a/src/tests/functional/drive_custom_body_tests.ts +++ b/src/tests/functional/drive_custom_body_tests.ts @@ -1,6 +1,6 @@ import { test } from "@playwright/test" import { assert } from "chai" -import { nextEventNamed, pathname } from "../helpers/page" +import { nextEventNamed, pathname, getFromLocalStorage, setLocalStorageFromEvent } from "../helpers/page" test.beforeEach(async ({ page }) => { await page.goto("/src/tests/fixtures/drive_custom_body.html") @@ -28,3 +28,13 @@ test("test drive with a custom body element", async ({ page }) => { assert.equal(await page.textContent("h1"), "Drive (with custom body)") assert.equal(await page.textContent("#different-content"), "Drive 2") }) + +test("test drive with mismatched custom body elements", async ({ page }) => { + await setLocalStorageFromEvent(page, "turbo:reload", "reloaded", "true") + await page.click("#mismatch") + await page.waitForEvent("load") + + assert.equal(await page.textContent("h1"), "Drive (with custom body 3)") + assert.equal(await getFromLocalStorage(page, "reloaded"), "true", "dispatches turbo:reload event") + assert.equal(pathname(page.url()), "/src/tests/fixtures/drive_custom_body_3.html") +})