From ecdb4e1307d62b45f113db6425424f2be28d7536 Mon Sep 17 00:00:00 2001 From: Kiwi Date: Tue, 20 Nov 2018 15:44:07 +0100 Subject: [PATCH] [next] Broadcast mutation events (#2083) * feat: Implement mutation events * fix: correct testcase name --- .../lib/relay/createMutationContainer.tsx | 5 ++- .../stream/containers/UserBoxContainer.tsx | 4 +-- src/core/client/stream/index.tsx | 2 ++ .../client/stream/listeners/OnEvents.spec.tsx | 27 +++++++++++++++ src/core/client/stream/listeners/OnEvents.tsx | 34 +++++++++++++++++++ src/core/client/stream/listeners/index.ts | 1 + 6 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 src/core/client/stream/listeners/OnEvents.spec.tsx create mode 100644 src/core/client/stream/listeners/OnEvents.tsx diff --git a/src/core/client/framework/lib/relay/createMutationContainer.tsx b/src/core/client/framework/lib/relay/createMutationContainer.tsx index 3084635c9..a07c04981 100644 --- a/src/core/client/framework/lib/relay/createMutationContainer.tsx +++ b/src/core/client/framework/lib/relay/createMutationContainer.tsx @@ -27,13 +27,16 @@ function createMutationContainer( return compose( withContext(context => ({ context })), hoistStatics((BaseComponent: React.ComponentType) => { - class CreateMutationContainer extends React.Component { + class CreateMutationContainer extends React.Component<{ + context: TalkContext; + }> { public static displayName = wrapDisplayName( BaseComponent, "createMutationContainer" ); private commit = (input: I) => { + this.props.context.eventEmitter.emit(`mutation.${propName}`, input); return commit( this.props.context.relayEnvironment, input, diff --git a/src/core/client/stream/containers/UserBoxContainer.tsx b/src/core/client/stream/containers/UserBoxContainer.tsx index 90b751e83..8c4c22430 100644 --- a/src/core/client/stream/containers/UserBoxContainer.tsx +++ b/src/core/client/stream/containers/UserBoxContainer.tsx @@ -35,6 +35,7 @@ export class UserBoxContainer extends Component { private handleClose = () => this.props.setAuthPopupState({ open: false }); private handleSignIn = () => this.props.showAuthPopup({ view: "SIGN_IN" }); private handleRegister = () => this.props.showAuthPopup({ view: "SIGN_UP" }); + private handleSignOut = () => this.props.signOut(); public render() { const { @@ -42,13 +43,12 @@ export class UserBoxContainer extends Component { authPopup: { open, focus, view }, }, me, - signOut, } = this.props; if (me) { return ( diff --git a/src/core/client/stream/index.tsx b/src/core/client/stream/index.tsx index 5ba961e83..80ddaeeab 100644 --- a/src/core/client/stream/index.tsx +++ b/src/core/client/stream/index.tsx @@ -7,6 +7,7 @@ import { createManaged } from "talk-framework/lib/bootstrap"; import AppContainer from "talk-stream/containers/AppContainer"; import { + OnEvents, OnPostMessageAuthError, OnPostMessageSetAuthToken, OnPymSetCommentID, @@ -19,6 +20,7 @@ const listeners = ( + ); diff --git a/src/core/client/stream/listeners/OnEvents.spec.tsx b/src/core/client/stream/listeners/OnEvents.spec.tsx new file mode 100644 index 000000000..28c5be2fe --- /dev/null +++ b/src/core/client/stream/listeners/OnEvents.spec.tsx @@ -0,0 +1,27 @@ +import { shallow } from "enzyme"; +import React from "react"; + +import { createSinonStub } from "talk-framework/testHelpers"; + +import { OnEvents } from "./OnEvents"; + +it("Broadcasts events to pym", () => { + const value = { value: true }; + const eventName = "eventName"; + const eventEmitter: any = { + onAny: (cb: (eventName: string, value: any) => void) => { + cb(eventName, value); + }, + }; + + const pym = { + sendMessage: createSinonStub( + s => s.throws(), + s => + s.withArgs("event", JSON.stringify({ eventName, value })).returns(null) + ), + }; + + shallow(); + expect(pym.sendMessage.calledOnce).toBe(true); +}); diff --git a/src/core/client/stream/listeners/OnEvents.tsx b/src/core/client/stream/listeners/OnEvents.tsx new file mode 100644 index 000000000..18a58cb01 --- /dev/null +++ b/src/core/client/stream/listeners/OnEvents.tsx @@ -0,0 +1,34 @@ +import { Component } from "react"; + +import { TalkContext, withContext } from "talk-framework/lib/bootstrap"; + +interface Props { + pym: TalkContext["pym"]; + eventEmitter: TalkContext["eventEmitter"]; +} + +export class OnEvents extends Component { + constructor(props: Props) { + super(props); + // Auth popup will use this to handle a successful login. + props.eventEmitter.onAny((eventName: string, value: any) => { + props.pym!.sendMessage( + "event", + JSON.stringify({ + eventName, + value, + }) + ); + }); + } + + public render() { + return null; + } +} + +const enhanced = withContext(({ pym, eventEmitter }) => ({ + pym, + eventEmitter, +}))(OnEvents); +export default enhanced; diff --git a/src/core/client/stream/listeners/index.ts b/src/core/client/stream/listeners/index.ts index 1c315d81f..6400c538b 100644 --- a/src/core/client/stream/listeners/index.ts +++ b/src/core/client/stream/listeners/index.ts @@ -3,3 +3,4 @@ export { default as OnPostMessageSetAuthToken, } from "./OnPostMessageSetAuthToken"; export { default as OnPostMessageAuthError } from "./OnPostMessageAuthError"; +export { default as OnEvents } from "./OnEvents";