From 280d3816774b7d4b9998d7e67833d6db9951d83b Mon Sep 17 00:00:00 2001 From: Steffen Deusch Date: Fri, 18 Oct 2024 21:27:01 +0200 Subject: [PATCH] proof of concept: support pushEvent returning a promise (#3475) This is a breaking change. Until now, pushEvent always returned the ref, but with this change it returns a promise by default, if no onReply function is given. Relates to: #1937 --- assets/js/phoenix_live_view/view_hook.js | 30 +++++++++++++++++++++-- assets/test/event_test.js | 31 +++++++++++++++++++++++- assets/test/js_test.js | 4 +-- assets/test/view_test.js | 2 +- 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/assets/js/phoenix_live_view/view_hook.js b/assets/js/phoenix_live_view/view_hook.js index dce5b357c0..7847006b39 100644 --- a/assets/js/phoenix_live_view/view_hook.js +++ b/assets/js/phoenix_live_view/view_hook.js @@ -249,11 +249,37 @@ export default class ViewHook { } } - pushEvent(event, payload = {}, onReply = function (){ }){ + pushEvent(event, payload = {}, onReply){ + if (onReply === undefined) { + return new Promise((resolve, reject) => { + try { + const ref = this.__view().pushHookEvent(this.el, null, event, payload, (reply, _ref) => resolve(reply)); + if (ref === false) { + reject(new Error("unable to push hook event. LiveView not connected")) + } + } catch (error) { + reject(error) + } + }); + } return this.__view().pushHookEvent(this.el, null, event, payload, onReply) } - pushEventTo(phxTarget, event, payload = {}, onReply = function (){ }){ + pushEventTo(phxTarget, event, payload = {}, onReply){ + if (onReply === undefined) { + return new Promise((resolve, reject) => { + try { + this.__view().withinTargets(phxTarget, (view, targetCtx) => { + const ref = view.pushHookEvent(this.el, targetCtx, event, payload, (reply, _ref) => resolve(reply)) + if (ref === false) { + reject(new Error("unable to push hook event. LiveView not connected")) + } + }) + } catch (error) { + reject(error) + } + }); + } return this.__view().withinTargets(phxTarget, (view, targetCtx) => { return view.pushHookEvent(this.el, targetCtx, event, payload, onReply) }) diff --git a/assets/test/event_test.js b/assets/test/event_test.js index 4ffb2a4395..a00f9e9cce 100644 --- a/assets/test/event_test.js +++ b/assets/test/event_test.js @@ -182,6 +182,35 @@ describe("pushEvent replies", () => { }) }) + test("promise", (done) => { + let view + let liveSocket = new LiveSocket("/live", Socket, { + hooks: { + Gateway: { + mounted(){ + stubNextChannelReply(view, {transactionID: "1001"}) + this.pushEvent("charge", {amount: 123}).then((reply) => { + processedReplies.push(reply) + view.el.dispatchEvent(new CustomEvent("replied", {detail: reply})) + }) + } + } + } + }) + view = simulateView(liveSocket, [], "") + view.update({ + s: [` +
+
+ `] + }, []) + + view.el.addEventListener("replied", () => { + expect(processedReplies).toEqual([{transactionID: "1001"}]) + done() + }) + }) + test("pushEvent without connection noops", () => { let view let pushedRef = "before" @@ -190,7 +219,7 @@ describe("pushEvent replies", () => { Gateway: { mounted(){ stubNextChannelReply(view, {transactionID: "1001"}) - pushedRef = this.pushEvent("charge", {amount: 123}) + pushedRef = this.pushEvent("charge", {amount: 123}, () => {}) } } } diff --git a/assets/test/js_test.js b/assets/test/js_test.js index a18628c668..25d1f97a84 100644 --- a/assets/test/js_test.js +++ b/assets/test/js_test.js @@ -26,7 +26,7 @@ describe("JS", () => { describe("hook.js()", () => { let js, view, modal beforeEach(() => { - view = setupView(``) + view = setupView("
modal
") modal = view.el.querySelector("#modal") let hook = new ViewHook(view, view.el, {}) js = hook.js() @@ -35,7 +35,7 @@ describe("JS", () => { test("exec", done => { simulateVisibility(modal) expect(modal.style.display).toBe("") - js.exec(`[["toggle", {"to": "#modal"}]]`) + js.exec("[[\"toggle\", {\"to\": \"#modal\"}]]") jest.advanceTimersByTime(100) expect(modal.style.display).toBe("none") done() diff --git a/assets/test/view_test.js b/assets/test/view_test.js index 533149f03a..73ff1c66db 100644 --- a/assets/test/view_test.js +++ b/assets/test/view_test.js @@ -860,7 +860,7 @@ describe("View Hooks", function(){ }) let customEl = document.createElement("custom-el") el.appendChild(customEl) - let view = simulateJoinedView(el, liveSocket) + simulateJoinedView(el, liveSocket) }) test("view destroyed", async () => {