-
Notifications
You must be signed in to change notification settings - Fork 436
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Dispatch lifecycle events within turbo-frames
Closes #54 Closes hotwired/turbo-rails#56 Dispatch life cycle events from within the `FrameController` and `FrameRedirector` when a `<turbo-frame>` element is navigated. The events _do not bubble_ since the conventional (and historical) style of `turbolinks:` and `turbo:` event listeners has been to declare them on the page's `document.documentElement`. If the `<turbo-frame>` events were to bubble, either _all_ application-land event listeners would be required to change, or else they would fire multiple times as the event bubbled up the document. Some tangential changes: * Change `dispatch` default `{ bubbles: true }` value to be an argument instead * Delete `TimingData` in favor of `TimingMetrics` and `TimingMetric`
- Loading branch information
1 parent
c52d87c
commit 7922187
Showing
9 changed files
with
179 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Turbo</title> | ||
<script src="/src/tests/fixtures/turbo.es2017-umd.js" data-turbo-track="reload"></script> | ||
</head> | ||
<body> | ||
<div id="container"> | ||
<a id="outside" href="/src/tests/fixtures/frame_navigation.html" data-turbo-frame="frame">Outside Frame</a> | ||
|
||
<turbo-frame id="frame"> | ||
<h2>Frame Navigation</h2> | ||
|
||
<a id="inside" href="/src/tests/fixtures/frame_navigation.html">Inside Frame</a> | ||
<a id="top" href="/src/tests/fixtures/frame_navigation.html" data-turbo-frame="_top">Top</a> | ||
</turbo-frame> | ||
</div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { TurboDriveTestCase } from "../helpers/turbo_drive_test_case" | ||
|
||
export class FrameNavigationTests extends TurboDriveTestCase { | ||
async setup() { | ||
await this.goToLocation("/src/tests/fixtures/frame_navigation.html") | ||
} | ||
|
||
async "test frame navigation with descendant link"() { | ||
this.trackFrameEvents() | ||
await this.clickSelector("#inside") | ||
await this.nextBeat | ||
|
||
const dispatchedEvents = await this.readDispatchedFrameEvents() | ||
const [ | ||
[ beforeVisit, beforeVisitTarget, { url } ], | ||
[ visit, visitTarget ], | ||
[ beforeRender, beforeRenderTarget, { newBody } ], | ||
[ render, renderTarget ], | ||
[ load, loadTarget, { timing } ], | ||
] = dispatchedEvents | ||
|
||
this.assert.equal(beforeVisit, "turbo:before-visit") | ||
this.assert.equal(beforeVisitTarget, "frame") | ||
this.assert.ok(url.includes("/src/tests/fixtures/frame_navigation.html")) | ||
|
||
this.assert.equal(visit, "turbo:visit") | ||
this.assert.equal(visitTarget, "frame") | ||
|
||
this.assert.equal(beforeRender, "turbo:before-render") | ||
this.assert.equal(beforeRenderTarget, "frame") | ||
this.assert.ok(newBody) | ||
|
||
this.assert.equal(render, "turbo:render") | ||
this.assert.equal(renderTarget, "frame") | ||
|
||
this.assert.equal(load, "turbo:load") | ||
this.assert.equal(loadTarget, "frame") | ||
this.assert.ok(Object.keys(timing).length) | ||
} | ||
|
||
async "test frame navigation with exterior link"() { | ||
this.trackFrameEvents() | ||
await this.clickSelector("#outside") | ||
await this.nextBeat | ||
|
||
const dispatchedEvents = await this.readDispatchedFrameEvents() | ||
const [ | ||
[ beforeVisit, beforeVisitTarget, { url } ], | ||
[ visit, visitTarget ], | ||
[ beforeRender, beforeRenderTarget, { newBody } ], | ||
[ render, renderTarget ], | ||
[ load, loadTarget, { timing } ], | ||
] = dispatchedEvents | ||
|
||
this.assert.equal(beforeVisit, "turbo:before-visit") | ||
this.assert.equal(beforeVisitTarget, "frame") | ||
this.assert.ok(url.includes("/src/tests/fixtures/frame_navigation.html")) | ||
|
||
this.assert.equal(visit, "turbo:visit") | ||
this.assert.equal(visitTarget, "frame") | ||
|
||
this.assert.equal(beforeRender, "turbo:before-render") | ||
this.assert.equal(beforeRenderTarget, "frame") | ||
this.assert.ok(newBody) | ||
|
||
this.assert.equal(render, "turbo:render") | ||
this.assert.equal(renderTarget, "frame") | ||
|
||
this.assert.equal(load, "turbo:load") | ||
this.assert.equal(loadTarget, "frame") | ||
this.assert.ok(Object.keys(timing).length) | ||
} | ||
|
||
async trackFrameEvents() { | ||
this.remote.execute(() => { | ||
const eventNames = "turbo:before-visit turbo:visit turbo:before-render turbo:render turbo:load".split(/\s+/) | ||
document.head.insertAdjacentHTML("beforeend", `<meta id="events" content="[]">`) | ||
const frame = document.getElementById("frame") | ||
|
||
if (frame) { | ||
eventNames.forEach(eventName => frame.addEventListener(eventName, (event) => { | ||
const meta = document.getElementById("events") | ||
|
||
if (meta instanceof HTMLMetaElement && event instanceof CustomEvent && event.target instanceof HTMLElement) { | ||
const dispatchedEvents = JSON.parse(meta.content) | ||
const detail = event.detail || {} | ||
dispatchedEvents.push([ event.type, event.target.id, { ...detail, newBody: !!detail.newBody } ]) | ||
meta.content = JSON.stringify(dispatchedEvents) | ||
} | ||
})) | ||
} | ||
}) | ||
} | ||
|
||
async readDispatchedFrameEvents() { | ||
const meta = await this.querySelector("meta[id=events]") | ||
const content = await meta.getAttribute("content") | ||
|
||
return JSON.parse(content || "[]") | ||
} | ||
} | ||
|
||
FrameNavigationTests.registerSuite() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters