Skip to content

Commit

Permalink
Merge pull request #1240 from seanpdoyle/rename-morph-stream-action
Browse files Browse the repository at this point in the history
Re-structure `turbo-stream[action=morph]` support
  • Loading branch information
jorgemanrubia authored Jul 12, 2024
2 parents 2ef50c9 + 9369eb9 commit a4f3a90
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 83 deletions.
28 changes: 17 additions & 11 deletions src/core/streams/stream_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,31 @@ export const StreamActions = {
},

replace() {
this.targetElements.forEach((e) => e.replaceWith(this.templateContent))
const method = this.getAttribute("method")

this.targetElements.forEach((targetElement) => {
if (method === "morph") {
morphElements(targetElement, this.templateContent)
} else {
targetElement.replaceWith(this.templateContent)
}
})
},

update() {
const method = this.getAttribute("method")

this.targetElements.forEach((targetElement) => {
targetElement.innerHTML = ""
targetElement.append(this.templateContent)
if (method === "morph") {
morphChildren(targetElement, this.templateContent)
} else {
targetElement.innerHTML = ""
targetElement.append(this.templateContent)
}
})
},

refresh() {
session.refresh(this.baseURI, this.requestId)
},

morph() {
const morph = this.hasAttribute("children-only") ?
morphChildren :
morphElements

this.targetElements.forEach((targetElement) => morph(targetElement, this.templateContent))
}
}
16 changes: 0 additions & 16 deletions src/tests/fixtures/morph_stream_action.html

This file was deleted.

4 changes: 4 additions & 0 deletions src/tests/fixtures/stream.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,9 @@
<div id="container">
<input id="container-element">
</div>

<div id="message_1">
<div>Morph me</div>
</div>
</body>
</html>
48 changes: 0 additions & 48 deletions src/tests/functional/morph_stream_action_tests.js

This file was deleted.

46 changes: 45 additions & 1 deletion src/tests/functional/stream_tests.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { test } from "@playwright/test"
import { expect, test } from "@playwright/test"
import { assert } from "chai"
import {
hasSelector,
nextBeat,
nextEventNamed,
nextEventOnTarget,
noNextEventOnTarget,
readEventLogs,
waitUntilNoSelector,
waitUntilText
Expand Down Expand Up @@ -182,6 +184,48 @@ test("receiving a remove stream message preserves focus blurs the activeElement"
assert.notOk(await hasSelector(page, ":focus"))
})

test("dispatches a turbo:before-morph-element & turbo:morph-element for each morph stream action", async ({ page }) => {
await page.evaluate(() => {
window.Turbo.renderStreamMessage(`
<turbo-stream action="replace" method="morph" target="message_1">
<template>
<div id="message_1">
<h1>Morphed</h1>
</div>
</template>
</turbo-stream>
`)
})

await nextEventOnTarget(page, "message_1", "turbo:before-morph-element")
await nextEventOnTarget(page, "message_1", "turbo:morph-element")
await expect(page.locator("#message_1")).toHaveText("Morphed")
})

test("preventing a turbo:before-morph-element prevents the morph", async ({ page }) => {
await page.evaluate(() => {
addEventListener("turbo:before-morph-element", (event) => {
event.preventDefault()
})
})

await page.evaluate(() => {
window.Turbo.renderStreamMessage(`
<turbo-stream action="replace" method="morph" target="message_1">
<template>
<div id="message_1">
<h1>Morphed</h1>
</div>
</template>
</turbo-stream>
`)
})

await nextEventOnTarget(page, "message_1", "turbo:before-morph-element")
await noNextEventOnTarget(page, "message_1", "turbo:morph-element")
await expect(page.locator("#message_1")).toHaveText("Morph me")
})

async function getReadyState(page, id) {
return page.evaluate((id) => {
const element = document.getElementById(id)
Expand Down
15 changes: 8 additions & 7 deletions src/tests/unit/stream_element_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import { assert } from "@open-wc/testing"
import { sleep } from "../helpers/page"
import * as Turbo from "../../index"

function createStreamElement(action, target, templateElement) {
function createStreamElement(action, target, templateElement, attributes = {}) {
const element = new StreamElement()
if (action) element.setAttribute("action", action)
if (target) element.setAttribute("target", target)
if (templateElement) element.appendChild(templateElement)
Object.entries(attributes).forEach((attribute) => element.setAttribute(...attribute))
return element
}

Expand Down Expand Up @@ -197,9 +198,9 @@ test("test action=refresh discarded when matching request id", async () => {
assert.ok(document.body.hasAttribute("data-modified"))
})

test("action=morph", async () => {
test("action=replace method=morph", async () => {
const templateElement = createTemplateElement(`<h1 id="hello">Hello Turbo Morphed</h1>`)
const element = createStreamElement("morph", "hello", templateElement)
const element = createStreamElement("replace", "hello", templateElement, { method: "morph" })

assert.equal(subject.find("div#hello")?.textContent, "Hello Turbo")

Expand All @@ -210,9 +211,9 @@ test("action=morph", async () => {
assert.equal(subject.find("h1#hello")?.textContent, "Hello Turbo Morphed")
})

test("action=morph with text content change", async () => {
test("action=replace method=morph with text content change", async () => {
const templateElement = createTemplateElement(`<div id="hello">Hello Turbo Morphed</div>`)
const element = createStreamElement("morph", "hello", templateElement)
const element = createStreamElement("replace", "hello", templateElement, { method: "morph" })

assert.equal(subject.find("div#hello")?.textContent, "Hello Turbo")

Expand All @@ -223,9 +224,9 @@ test("action=morph with text content change", async () => {
assert.equal(subject.find("div#hello")?.textContent, "Hello Turbo Morphed")
})

test("action=morph children-only", async () => {
test("action=update method=morph", async () => {
const templateElement = createTemplateElement(`<h1 id="hello-child-element">Hello Turbo Morphed</h1>`)
const element = createStreamElement("morph", "hello", templateElement)
const element = createStreamElement("update", "hello", templateElement, { method: "morph" })
const target = subject.find("div#hello")
assert.equal(target?.textContent, "Hello Turbo")
element.setAttribute("children-only", true)
Expand Down

0 comments on commit a4f3a90

Please sign in to comment.