diff --git a/src/core/drive/page_snapshot.ts b/src/core/drive/page_snapshot.ts index 9b5247fad..9db0743fb 100644 --- a/src/core/drive/page_snapshot.ts +++ b/src/core/drive/page_snapshot.ts @@ -24,7 +24,22 @@ export class PageSnapshot extends Snapshot { } clone() { - return new PageSnapshot(this.element.cloneNode(true), this.headSnapshot) + const clonedElement = this.element.cloneNode(true) + + const selectElements = this.element.querySelectorAll("select") + const clonedSelectElements = clonedElement.querySelectorAll("select") + + for (const [index, source] of selectElements.entries()) { + for (const [optionIndex, option] of Array.from(source.options).entries()) { + clonedSelectElements[index].options[optionIndex].selected = option.selected + } + } + + for (const clonedPasswordInput of clonedElement.querySelectorAll('input[type="password"]')) { + clonedPasswordInput.value = "" + } + + return new PageSnapshot(clonedElement, this.headSnapshot) } get headElement() { diff --git a/src/tests/fixtures/rendering.html b/src/tests/fixtures/rendering.html index a10308f8e..44e2d09f6 100644 --- a/src/tests/fixtures/rendering.html +++ b/src/tests/fixtures/rendering.html @@ -44,6 +44,24 @@

Rendering

Permanent element in frame

Permanent element in frame without layout

Delayed link

+
+ + + + + + + + + + +
Rendering
diff --git a/src/tests/functional/rendering_tests.ts b/src/tests/functional/rendering_tests.ts index d29b82b88..24a6fc2b6 100644 --- a/src/tests/functional/rendering_tests.ts +++ b/src/tests/functional/rendering_tests.ts @@ -8,6 +8,8 @@ import { nextBody, nextEventNamed, pathname, + propertyForSelector, + readEventLogs, scrollToSelector, selectorHasFocus, sleep, @@ -19,6 +21,7 @@ import { test.beforeEach(async ({ page }) => { await page.goto("/src/tests/fixtures/rendering.html") await clearLocalStorage(page) + await readEventLogs(page) }) test("test triggers before-render and render events", async ({ page }) => { @@ -392,6 +395,61 @@ test("test preserves permanent element video playback", async ({ page }) => { assert.equal(timeAfterRender, timeBeforeRender, "element state is preserved") }) +test("test preserves input values", async ({ page }) => { + await page.fill("#text-input", "test") + await page.click("#checkbox-input") + await page.click("#radio-input") + await page.fill("#textarea", "test") + await page.selectOption("#select", "2") + await page.selectOption("#select-multiple", "2") + + await page.click("#same-origin-link") + await nextEventNamed(page, "turbo:load") + await page.goBack() + await nextEventNamed(page, "turbo:load") + + assert.equal(await propertyForSelector(page, "#text-input", "value"), "test") + assert.equal(await propertyForSelector(page, "#checkbox-input", "checked"), true) + assert.equal(await propertyForSelector(page, "#radio-input", "checked"), true) + assert.equal(await propertyForSelector(page, "#textarea", "value"), "test") + assert.equal(await propertyForSelector(page, "#select", "value"), "2") + assert.equal(await propertyForSelector(page, "#select-multiple", "value"), "2") +}) + +test("test does not preserve password values", async ({ page }) => { + await page.fill("#password-input", "test") + + await page.click("#same-origin-link") + await nextEventNamed(page, "turbo:load") + await page.goBack() + await nextEventNamed(page, "turbo:load") + + assert.equal(await propertyForSelector(page, "#password-input", "value"), "") +}) + +test("test clears values when restored from cache", async ({ page }) => { + await page.fill("#text-input", "test") + await page.click("#checkbox-input") + await page.click("#radio-input") + await page.fill("#textarea", "test") + await page.selectOption("#select", "2") + await page.selectOption("#select-multiple", "2") + + await page.click("#same-origin-link") + await nextEventNamed(page, "turbo:load") + await page.goBack() + await nextEventNamed(page, "turbo:load") + + await page.click("#reset-input") + + assert.equal(await propertyForSelector(page, "#text-input", "value"), "") + assert.equal(await propertyForSelector(page, "#checkbox-input", "checked"), false) + assert.equal(await propertyForSelector(page, "#radio-input", "checked"), false) + assert.equal(await propertyForSelector(page, "#textarea", "value"), "") + assert.equal(await propertyForSelector(page, "#select", "value"), "1") + assert.equal(await propertyForSelector(page, "#select-multiple", "value"), "") +}) + test("test before-cache event", async ({ page }) => { await page.evaluate(() => { addEventListener("turbo:before-cache", () => (document.body.innerHTML = "Modified"), { once: true })