mirror of
https://github.com/wassname/talk.git
synced 2026-08-14 12:50:17 +08:00
Refactor stream + some tests
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
|
||||
<body>
|
||||
<h1 style="text-align: center" }>Talk 5.0 – Embed Stream</h1>
|
||||
<div id="coralStreamEmbed"></div>
|
||||
<div id="coralStreamEmbed" style="max-width: 600px; margin: 0 auto"></div>
|
||||
<script>
|
||||
window.TalkEmbed = Talk.render(document.getElementById('coralStreamEmbed'));
|
||||
</script>
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import * as React from "react";
|
||||
import { compose, hoistStatics, InferableComponentEnhancer } from "recompose";
|
||||
import {
|
||||
compose,
|
||||
hoistStatics,
|
||||
InferableComponentEnhancer,
|
||||
wrapDisplayName,
|
||||
} from "recompose";
|
||||
import {
|
||||
CSelector,
|
||||
CSnapshot,
|
||||
Disposable,
|
||||
Environment,
|
||||
GraphQLTaggedNode,
|
||||
} from "relay-runtime";
|
||||
@@ -36,6 +42,12 @@ function withLocalStateContainer<T>(
|
||||
withContext(({ relayEnvironment }) => ({ relayEnvironment })),
|
||||
hoistStatics((BaseComponent: React.ComponentType<any>) => {
|
||||
class LocalStateContainer extends React.Component<Props, any> {
|
||||
public static displayName = wrapDisplayName(
|
||||
BaseComponent,
|
||||
"withLocalStateContainer"
|
||||
);
|
||||
private subscription: Disposable;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
const fragment = (fragmentSpec as any).data().default;
|
||||
@@ -53,7 +65,10 @@ function withLocalStateContainer<T>(
|
||||
variables: {},
|
||||
};
|
||||
const snapshot = props.relayEnvironment.lookup(selector);
|
||||
props.relayEnvironment.subscribe(snapshot, this.updateSnapshot);
|
||||
this.subscription = props.relayEnvironment.subscribe(
|
||||
snapshot,
|
||||
this.updateSnapshot
|
||||
);
|
||||
this.state = {
|
||||
data: snapshot.data,
|
||||
};
|
||||
@@ -63,6 +78,10 @@ function withLocalStateContainer<T>(
|
||||
this.setState({ data: snapshot.data });
|
||||
};
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.subscription.dispose();
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { relayEnvironment: _, ...rest } = this.props;
|
||||
return <BaseComponent {...rest} local={this.state.data} />;
|
||||
|
||||
@@ -11,4 +11,5 @@
|
||||
}
|
||||
|
||||
.root {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -5,17 +5,17 @@ import { PropTypesOf } from "talk-framework/types";
|
||||
|
||||
import App from "./App";
|
||||
|
||||
it("renders correctly", () => {
|
||||
it("renders stream", () => {
|
||||
const props: PropTypesOf<typeof App> = {
|
||||
asset: {},
|
||||
showPermalinkView: false,
|
||||
};
|
||||
const wrapper = shallow(<App {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders correctly when asset is null", () => {
|
||||
it("renders permalink view", () => {
|
||||
const props: PropTypesOf<typeof App> = {
|
||||
asset: null,
|
||||
showPermalinkView: true,
|
||||
};
|
||||
const wrapper = shallow(<App {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
@@ -3,23 +3,26 @@ import { StatelessComponent } from "react";
|
||||
|
||||
import { Flex } from "talk-ui/components";
|
||||
|
||||
import StreamContainer from "../containers/StreamContainer";
|
||||
import PermalinkViewQuery from "../queries/PermalinkViewQuery";
|
||||
import StreamQuery from "../queries/StreamQuery";
|
||||
|
||||
import * as styles from "./App.css";
|
||||
|
||||
export interface AppProps {
|
||||
asset: {} | null;
|
||||
showPermalinkView: boolean;
|
||||
}
|
||||
|
||||
const App: StatelessComponent<AppProps> = props => {
|
||||
if (props.asset) {
|
||||
return (
|
||||
<Flex justifyContent="center" className={styles.root}>
|
||||
<StreamContainer asset={props.asset} />
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
return <div>Asset not found </div>;
|
||||
const view = props.showPermalinkView ? (
|
||||
<PermalinkViewQuery />
|
||||
) : (
|
||||
<StreamQuery />
|
||||
);
|
||||
return (
|
||||
<Flex justifyContent="center" className={styles.root}>
|
||||
{view}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
||||
@@ -18,7 +18,7 @@ exports[`renders username and body 1`] = `
|
||||
<div
|
||||
className="Comment-footer"
|
||||
>
|
||||
<withContext(LocalStateContainer)
|
||||
<withContext(withLocalStateContainer(PermalinkContainer))
|
||||
commentID="comment-id"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
.root {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
margin: calc(0.5 * var(--spacing-unit)) auto;
|
||||
}
|
||||
|
||||
.button {
|
||||
|
||||
@@ -20,6 +20,7 @@ const PermalinkView: StatelessComponent<PermalinkViewProps> = ({
|
||||
<div className={styles.root}>
|
||||
{assetURL && (
|
||||
<Button
|
||||
id="talk-comments-permalinkView-showAllComments"
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={onShowAllComments}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
.root {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
exports[`renders permalink view 1`] = `
|
||||
<withPropsOnChange(Flex)
|
||||
className="App-root"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Relay(StreamContainer)
|
||||
asset={Object {}}
|
||||
/>
|
||||
<withContext(withLocalStateContainer(PermalinkViewQuery)) />
|
||||
</withPropsOnChange(Flex)>
|
||||
`;
|
||||
|
||||
exports[`renders correctly when asset is null 1`] = `
|
||||
<div>
|
||||
Asset not found
|
||||
</div>
|
||||
exports[`renders stream 1`] = `
|
||||
<withPropsOnChange(Flex)
|
||||
className="App-root"
|
||||
justifyContent="center"
|
||||
>
|
||||
<withContext(withLocalStateContainer(StreamQuery)) />
|
||||
</withPropsOnChange(Flex)>
|
||||
`;
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { shallow } from "enzyme";
|
||||
import React from "react";
|
||||
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
|
||||
import { AppContainer } from "./AppContainer";
|
||||
|
||||
it("renders correctly", () => {
|
||||
const props: PropTypesOf<typeof AppContainer> = {
|
||||
data: {
|
||||
asset: {},
|
||||
},
|
||||
};
|
||||
const wrapper = shallow(<AppContainer {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
@@ -1,30 +1,27 @@
|
||||
import React, { StatelessComponent } from "react";
|
||||
import { graphql } from "react-relay";
|
||||
import * as React from "react";
|
||||
import { StatelessComponent } from "react";
|
||||
|
||||
import { withFragmentContainer } from "talk-framework/lib/relay";
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
import { AppContainer as Data } from "talk-stream/__generated__/AppContainer.graphql";
|
||||
import { graphql, withLocalStateContainer } from "talk-framework/lib/relay";
|
||||
import { AppContainerLocal as Local } from "talk-stream/__generated__/AppContainerLocal.graphql";
|
||||
|
||||
import App from "../components/App";
|
||||
|
||||
interface InnerProps {
|
||||
data: Data;
|
||||
local: Local;
|
||||
}
|
||||
|
||||
export const AppContainer: StatelessComponent<InnerProps> = props => {
|
||||
return <App {...props.data} />;
|
||||
const AppContainer: StatelessComponent<InnerProps> = ({
|
||||
local: { commentID },
|
||||
}) => {
|
||||
return <App showPermalinkView={!!commentID} />;
|
||||
};
|
||||
|
||||
const enhanced = withFragmentContainer<{ data: Data }>({
|
||||
data: graphql`
|
||||
fragment AppContainer on Query
|
||||
@argumentDefinitions(assetID: { type: "ID!" }) {
|
||||
asset(id: $assetID) {
|
||||
...StreamContainer_asset
|
||||
}
|
||||
const enhanced = withLocalStateContainer<Local>(
|
||||
graphql`
|
||||
fragment AppContainerLocal on Local {
|
||||
commentID
|
||||
}
|
||||
`,
|
||||
})(AppContainer);
|
||||
`
|
||||
)(AppContainer);
|
||||
|
||||
export type AppContainerProps = PropTypesOf<typeof enhanced>;
|
||||
export default enhanced;
|
||||
|
||||
@@ -24,6 +24,7 @@ it("renders username and body", () => {
|
||||
it("renders body only", () => {
|
||||
const props: PropTypesOf<typeof CommentContainer> = {
|
||||
data: {
|
||||
id: "comment-id",
|
||||
author: {
|
||||
username: null,
|
||||
},
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import React from "react";
|
||||
import { graphql } from "react-relay";
|
||||
import {
|
||||
withFragmentContainer,
|
||||
withLocalStateContainer,
|
||||
} from "talk-framework/lib/relay";
|
||||
import { AppQueryLocal as Local } from "talk-stream/__generated__/AppQueryLocal.graphql";
|
||||
import { PermalinkViewContainerQuery as Data } from "talk-stream/__generated__/PermalinkViewContainerQuery.graphql";
|
||||
import { withFragmentContainer } from "talk-framework/lib/relay";
|
||||
import { PermalinkViewContainer_asset as AssetData } from "talk-stream/__generated__/PermalinkViewContainer_asset.graphql";
|
||||
import { PermalinkViewContainer_comment as CommentData } from "talk-stream/__generated__/PermalinkViewContainer_comment.graphql";
|
||||
import {
|
||||
SetCommentIDMutation,
|
||||
withSetCommentIDMutation,
|
||||
@@ -13,8 +10,8 @@ import {
|
||||
import PermalinkView from "../components/PermalinkView";
|
||||
|
||||
interface PermalinkViewContainerProps {
|
||||
data: Data;
|
||||
local: Local;
|
||||
comment: CommentData;
|
||||
asset: AssetData;
|
||||
setCommentID: SetCommentIDMutation;
|
||||
}
|
||||
|
||||
@@ -25,11 +22,11 @@ class PermalinkViewContainer extends React.Component<
|
||||
this.props.setCommentID({ id: null });
|
||||
};
|
||||
public render() {
|
||||
const { data, local } = this.props;
|
||||
const { comment, asset } = this.props;
|
||||
return (
|
||||
<PermalinkView
|
||||
{...data}
|
||||
assetURL={local.assetURL}
|
||||
comment={comment}
|
||||
assetURL={asset.url}
|
||||
onShowAllComments={this.showAllComments}
|
||||
/>
|
||||
);
|
||||
@@ -37,24 +34,18 @@ class PermalinkViewContainer extends React.Component<
|
||||
}
|
||||
|
||||
const enhanced = withSetCommentIDMutation(
|
||||
withFragmentContainer<{ data: Data }>({
|
||||
data: graphql`
|
||||
fragment PermalinkViewContainerQuery on Query
|
||||
@argumentDefinitions(commentID: { type: "ID!" }) {
|
||||
comment(id: $commentID) {
|
||||
...CommentContainer
|
||||
}
|
||||
withFragmentContainer<{ comment: CommentData; asset: AssetData }>({
|
||||
comment: graphql`
|
||||
fragment PermalinkViewContainer_comment on Comment {
|
||||
...CommentContainer
|
||||
}
|
||||
`,
|
||||
})(
|
||||
withLocalStateContainer<Local>(
|
||||
graphql`
|
||||
fragment PermalinkViewContainerLocal on Local {
|
||||
assetURL
|
||||
}
|
||||
`
|
||||
)(PermalinkViewContainer)
|
||||
)
|
||||
asset: graphql`
|
||||
fragment PermalinkViewContainer_asset on Asset {
|
||||
url
|
||||
}
|
||||
`,
|
||||
})(PermalinkViewContainer)
|
||||
);
|
||||
|
||||
export default enhanced;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<App
|
||||
asset={Object {}}
|
||||
/>
|
||||
`;
|
||||
@@ -9,6 +9,7 @@ exports[`renders body only 1`] = `
|
||||
}
|
||||
body="Woof"
|
||||
createdAt="1995-12-17T03:24:00.000Z"
|
||||
id="comment-id"
|
||||
/>
|
||||
`;
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ import {
|
||||
TalkContextProvider,
|
||||
} from "talk-framework/lib/bootstrap";
|
||||
|
||||
import AppContainer from "./containers/AppContainer";
|
||||
import { initLocalState } from "./local";
|
||||
import localesData from "./locales";
|
||||
import AppQuery from "./queries/AppQuery";
|
||||
|
||||
// This is called when the context is first initialized.
|
||||
async function init({ relayEnvironment }: TalkContext) {
|
||||
@@ -29,7 +29,7 @@ async function main() {
|
||||
|
||||
const Index: StatelessComponent = () => (
|
||||
<TalkContextProvider value={context}>
|
||||
<AppQuery />
|
||||
<AppContainer />
|
||||
</TalkContextProvider>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
import { shallow } from "enzyme";
|
||||
import React from "react";
|
||||
|
||||
import PermalinkViewContainer from "talk-stream/containers/PermalinkViewContainer";
|
||||
import AppContainer from "../containers/AppContainer";
|
||||
import { renderWrapper } from "./AppQuery";
|
||||
|
||||
it("renders permalink view", () => {
|
||||
const data = {
|
||||
props: {} as any,
|
||||
error: null,
|
||||
};
|
||||
const component = renderWrapper(PermalinkViewContainer);
|
||||
const wrapper = shallow(React.createElement(() => component(data)));
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders app", () => {
|
||||
const data = {
|
||||
props: {} as any,
|
||||
error: null,
|
||||
};
|
||||
const component = renderWrapper(AppContainer);
|
||||
const wrapper = shallow(React.createElement(() => component(data)));
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders loading", () => {
|
||||
const data = {
|
||||
props: null,
|
||||
error: null,
|
||||
};
|
||||
const component = renderWrapper(AppContainer);
|
||||
const wrapper = shallow(React.createElement(() => component(data)));
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders error", () => {
|
||||
const data = {
|
||||
props: null,
|
||||
error: new Error("error"),
|
||||
};
|
||||
const component = renderWrapper(AppContainer);
|
||||
const wrapper = shallow(React.createElement(() => component(data)));
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
@@ -1,86 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { StatelessComponent } from "react";
|
||||
import { ReadyState } from "react-relay";
|
||||
|
||||
import {
|
||||
graphql,
|
||||
QueryRenderer,
|
||||
withLocalStateContainer,
|
||||
} from "talk-framework/lib/relay";
|
||||
import {
|
||||
AppQueryResponse,
|
||||
AppQueryVariables,
|
||||
} from "talk-stream/__generated__/AppQuery.graphql";
|
||||
import { AppQueryLocal as Local } from "talk-stream/__generated__/AppQueryLocal.graphql";
|
||||
|
||||
import PermalinkViewContainer from "talk-stream/containers/PermalinkViewContainer";
|
||||
import AppContainer from "../containers/AppContainer";
|
||||
|
||||
interface InnerProps {
|
||||
local: Local;
|
||||
}
|
||||
|
||||
interface WrappedProps {
|
||||
data: any;
|
||||
}
|
||||
|
||||
// TODO (bc) Break down the needs of each component into another file (maybe).
|
||||
// (careful porting QueryRenderer into another stateless component)
|
||||
|
||||
export const renderWrapper = (
|
||||
WrappedComponent: React.ComponentType<WrappedProps>
|
||||
) => ({ error, props }: ReadyState<AppQueryResponse>) => {
|
||||
if (error) {
|
||||
return <div>{error.message}</div>;
|
||||
}
|
||||
if (props) {
|
||||
return <WrappedComponent data={props} />;
|
||||
}
|
||||
return <div>Loading</div>;
|
||||
};
|
||||
|
||||
const AppQuery: StatelessComponent<InnerProps> = ({
|
||||
local: { commentID, assetID },
|
||||
}) => {
|
||||
if (commentID) {
|
||||
return (
|
||||
<QueryRenderer<AppQueryVariables, AppQueryResponse>
|
||||
query={graphql`
|
||||
query AppQuery_PermalinkViewContainer_Query($commentID: ID!) {
|
||||
...PermalinkViewContainerQuery @arguments(commentID: $commentID)
|
||||
}
|
||||
`}
|
||||
variables={{
|
||||
commentID,
|
||||
}}
|
||||
render={renderWrapper(PermalinkViewContainer)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<QueryRenderer<AppQueryVariables, AppQueryResponse>
|
||||
query={graphql`
|
||||
query AppQuery($assetID: ID!) {
|
||||
...AppContainer @arguments(assetID: $assetID)
|
||||
}
|
||||
`}
|
||||
variables={{
|
||||
assetID,
|
||||
}}
|
||||
render={renderWrapper(AppContainer)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const enhanced = withLocalStateContainer<Local>(
|
||||
graphql`
|
||||
fragment AppQueryLocal on Local {
|
||||
assetID
|
||||
commentID
|
||||
assetURL
|
||||
}
|
||||
`
|
||||
)(AppQuery);
|
||||
|
||||
export default enhanced;
|
||||
@@ -0,0 +1,34 @@
|
||||
import { shallow } from "enzyme";
|
||||
import React from "react";
|
||||
|
||||
import { render } from "./PermalinkViewQuery";
|
||||
|
||||
it("renders permalink view container", () => {
|
||||
const data = {
|
||||
props: {
|
||||
asset: {},
|
||||
comment: {},
|
||||
} as any,
|
||||
error: null,
|
||||
};
|
||||
const wrapper = shallow(React.createElement(() => render(data)));
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders loading", () => {
|
||||
const data = {
|
||||
props: null,
|
||||
error: null,
|
||||
};
|
||||
const wrapper = shallow(React.createElement(() => render(data)));
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders error", () => {
|
||||
const data = {
|
||||
props: null,
|
||||
error: new Error("error"),
|
||||
};
|
||||
const wrapper = shallow(React.createElement(() => render(data)));
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
@@ -0,0 +1,68 @@
|
||||
import * as React from "react";
|
||||
import { StatelessComponent } from "react";
|
||||
import { ReadyState } from "react-relay";
|
||||
|
||||
import {
|
||||
graphql,
|
||||
QueryRenderer,
|
||||
withLocalStateContainer,
|
||||
} from "talk-framework/lib/relay";
|
||||
import {
|
||||
PermalinkViewQueryResponse,
|
||||
PermalinkViewQueryVariables,
|
||||
} from "talk-stream/__generated__/PermalinkViewQuery.graphql";
|
||||
import { PermalinkViewQueryLocal as Local } from "talk-stream/__generated__/PermalinkViewQueryLocal.graphql";
|
||||
|
||||
import PermalinkViewContainer from "../containers/PermalinkViewContainer";
|
||||
|
||||
interface InnerProps {
|
||||
local: Local;
|
||||
}
|
||||
|
||||
export const render = ({
|
||||
error,
|
||||
props,
|
||||
}: ReadyState<PermalinkViewQueryResponse>) => {
|
||||
if (error) {
|
||||
return <div>{error.message}</div>;
|
||||
}
|
||||
if (props) {
|
||||
return (
|
||||
<PermalinkViewContainer asset={props.asset} comment={props.comment} />
|
||||
);
|
||||
}
|
||||
return <div>Loading</div>;
|
||||
};
|
||||
|
||||
const PermalinkViewQuery: StatelessComponent<InnerProps> = ({
|
||||
local: { commentID, assetID },
|
||||
}) => (
|
||||
<QueryRenderer<PermalinkViewQueryVariables, PermalinkViewQueryResponse>
|
||||
query={graphql`
|
||||
query PermalinkViewQuery($assetID: ID!, $commentID: ID!) {
|
||||
asset(id: $assetID) {
|
||||
...PermalinkViewContainer_asset
|
||||
}
|
||||
comment(id: $commentID) {
|
||||
...PermalinkViewContainer_comment
|
||||
}
|
||||
}
|
||||
`}
|
||||
variables={{
|
||||
assetID,
|
||||
commentID,
|
||||
}}
|
||||
render={render}
|
||||
/>
|
||||
);
|
||||
|
||||
const enhanced = withLocalStateContainer<Local>(
|
||||
graphql`
|
||||
fragment PermalinkViewQueryLocal on Local {
|
||||
assetID
|
||||
commentID
|
||||
}
|
||||
`
|
||||
)(PermalinkViewQuery);
|
||||
|
||||
export default enhanced;
|
||||
@@ -0,0 +1,33 @@
|
||||
import { shallow } from "enzyme";
|
||||
import React from "react";
|
||||
|
||||
import { render } from "./StreamQuery";
|
||||
|
||||
it("renders stream container", () => {
|
||||
const data = {
|
||||
props: {
|
||||
asset: {},
|
||||
} as any,
|
||||
error: null,
|
||||
};
|
||||
const wrapper = shallow(React.createElement(() => render(data)));
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders loading", () => {
|
||||
const data = {
|
||||
props: null,
|
||||
error: null,
|
||||
};
|
||||
const wrapper = shallow(React.createElement(() => render(data)));
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders error", () => {
|
||||
const data = {
|
||||
props: null,
|
||||
error: new Error("error"),
|
||||
};
|
||||
const wrapper = shallow(React.createElement(() => render(data)));
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
import * as React from "react";
|
||||
import { StatelessComponent } from "react";
|
||||
import { ReadyState } from "react-relay";
|
||||
|
||||
import {
|
||||
graphql,
|
||||
QueryRenderer,
|
||||
withLocalStateContainer,
|
||||
} from "talk-framework/lib/relay";
|
||||
import {
|
||||
StreamQueryResponse,
|
||||
StreamQueryVariables,
|
||||
} from "talk-stream/__generated__/StreamQuery.graphql";
|
||||
import { StreamQueryLocal as Local } from "talk-stream/__generated__/StreamQueryLocal.graphql";
|
||||
|
||||
import StreamContainer from "../containers/StreamContainer";
|
||||
|
||||
interface InnerProps {
|
||||
local: Local;
|
||||
}
|
||||
|
||||
export const render = ({ error, props }: ReadyState<StreamQueryResponse>) => {
|
||||
if (error) {
|
||||
return <div>{error.message}</div>;
|
||||
}
|
||||
if (props) {
|
||||
return <StreamContainer asset={props.asset} />;
|
||||
}
|
||||
return <div>Loading</div>;
|
||||
};
|
||||
|
||||
const StreamQuery: StatelessComponent<InnerProps> = ({
|
||||
local: { assetID },
|
||||
}) => (
|
||||
<QueryRenderer<StreamQueryVariables, StreamQueryResponse>
|
||||
query={graphql`
|
||||
query StreamQuery($assetID: ID!) {
|
||||
asset(id: $assetID) {
|
||||
...StreamContainer_asset
|
||||
}
|
||||
}
|
||||
`}
|
||||
variables={{
|
||||
assetID,
|
||||
}}
|
||||
render={render}
|
||||
/>
|
||||
);
|
||||
|
||||
const enhanced = withLocalStateContainer<Local>(
|
||||
graphql`
|
||||
fragment StreamQueryLocal on Local {
|
||||
assetID
|
||||
}
|
||||
`
|
||||
)(StreamQuery);
|
||||
|
||||
export default enhanced;
|
||||
@@ -1,25 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders app 1`] = `
|
||||
<Relay(AppContainer)
|
||||
data={Object {}}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`renders error 1`] = `
|
||||
<div>
|
||||
error
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders loading 1`] = `
|
||||
<div>
|
||||
Loading
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders permalink view 1`] = `
|
||||
<withContext(createMutationContainer(Relay(withContext(LocalStateContainer))))
|
||||
data={Object {}}
|
||||
/>
|
||||
`;
|
||||
@@ -0,0 +1,20 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders error 1`] = `
|
||||
<div>
|
||||
error
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders loading 1`] = `
|
||||
<div>
|
||||
Loading
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders permalink view container 1`] = `
|
||||
<withContext(createMutationContainer(Relay(PermalinkViewContainer)))
|
||||
asset={Object {}}
|
||||
comment={Object {}}
|
||||
/>
|
||||
`;
|
||||
@@ -0,0 +1,19 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders error 1`] = `
|
||||
<div>
|
||||
error
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders loading 1`] = `
|
||||
<div>
|
||||
Loading
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders stream container 1`] = `
|
||||
<Relay(StreamContainer)
|
||||
asset={Object {}}
|
||||
/>
|
||||
`;
|
||||
@@ -0,0 +1,136 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders permalink view 1`] = `
|
||||
<div
|
||||
className="Flex-root App-root Flex-justifyCenter Flex-alignCenter"
|
||||
>
|
||||
<div
|
||||
className="PermalinkView-root"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root PermalinkView-button Button-sizeRegular Button-colorPrimary Button-variantOutlined Button-fullWidth"
|
||||
id="talk-comments-permalinkView-showAllComments"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
>
|
||||
Show all Comments
|
||||
</button>
|
||||
<div
|
||||
className="Flex-root Flex-alignFlexStart Flex-directionColumn"
|
||||
>
|
||||
<div
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Joining Too
|
||||
</p>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`show all comments 1`] = `
|
||||
<div
|
||||
className="Flex-root App-root Flex-justifyCenter Flex-alignCenter"
|
||||
>
|
||||
<div
|
||||
className="Stream-root"
|
||||
>
|
||||
<form
|
||||
autoComplete="off"
|
||||
onSubmit={[Function]}
|
||||
>
|
||||
<div>
|
||||
<textarea
|
||||
className="PostCommentForm-textarea"
|
||||
name="body"
|
||||
onChange={[Function]}
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="PostCommentForm-postButtonContainer"
|
||||
>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled"
|
||||
disabled={false}
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
>
|
||||
Post
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<div
|
||||
aria-live="polite"
|
||||
className="Flex-root Flex-itemGutter Flex-alignFlexStart Flex-directionColumn"
|
||||
id="talk-comments-stream-log"
|
||||
role="log"
|
||||
>
|
||||
<div
|
||||
className="Flex-root Flex-itemGutter Flex-alignFlexStart Flex-directionColumn"
|
||||
>
|
||||
<div
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
<p
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Joining Too
|
||||
</p>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -37,6 +37,7 @@ export const comments = [
|
||||
export const assets = [
|
||||
{
|
||||
id: "asset-1",
|
||||
url: "http://localhost/assets/asset-1",
|
||||
isClosed: false,
|
||||
comments: {
|
||||
edges: [
|
||||
@@ -68,6 +69,7 @@ export const commentWithReplies = {
|
||||
|
||||
export const assetWithReplies = {
|
||||
id: "asset-with-replies",
|
||||
url: "http://localhost/assets/asset-with-replies",
|
||||
isClosed: false,
|
||||
comments: {
|
||||
edges: [
|
||||
|
||||
@@ -5,7 +5,7 @@ import sinon from "sinon";
|
||||
|
||||
import { timeout } from "talk-common/utils";
|
||||
import { TalkContext, TalkContextProvider } from "talk-framework/lib/bootstrap";
|
||||
import AppQuery from "talk-stream/queries/AppQuery";
|
||||
import AppContainer from "talk-stream/containers/AppContainer";
|
||||
|
||||
import createEnvironment from "./createEnvironment";
|
||||
import { assets, comments } from "./fixtures";
|
||||
@@ -77,7 +77,7 @@ const context: TalkContext = {
|
||||
|
||||
const testRenderer = TestRenderer.create(
|
||||
<TalkContextProvider value={context}>
|
||||
<AppQuery />
|
||||
<AppContainer />
|
||||
</TalkContextProvider>
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import React from "react";
|
||||
import TestRenderer from "react-test-renderer";
|
||||
import { RecordProxy } from "relay-runtime";
|
||||
import sinon from "sinon";
|
||||
|
||||
import { timeout } from "talk-common/utils";
|
||||
import { TalkContext, TalkContextProvider } from "talk-framework/lib/bootstrap";
|
||||
import AppContainer from "talk-stream/containers/AppContainer";
|
||||
|
||||
import createEnvironment from "./createEnvironment";
|
||||
import { assets, comments } from "./fixtures";
|
||||
|
||||
const commentStub = {
|
||||
...comments[0],
|
||||
};
|
||||
|
||||
const assetStub = {
|
||||
...assets[0],
|
||||
comments: {
|
||||
pageInfo: {
|
||||
hasNextPage: false,
|
||||
},
|
||||
edges: [
|
||||
{
|
||||
node: commentStub,
|
||||
cursor: commentStub.createdAt,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
comment: sinon
|
||||
.stub()
|
||||
.throws()
|
||||
.withArgs(undefined, { id: commentStub.id })
|
||||
.returns(commentStub),
|
||||
asset: sinon
|
||||
.stub()
|
||||
.throws()
|
||||
.withArgs(undefined, { id: assetStub.id })
|
||||
.returns(assetStub),
|
||||
},
|
||||
};
|
||||
|
||||
const environment = createEnvironment({
|
||||
// Set this to true, to see graphql responses.
|
||||
logNetwork: false,
|
||||
resolvers,
|
||||
initLocalState: (localRecord: RecordProxy) => {
|
||||
localRecord.setValue(assetStub.id, "assetID");
|
||||
localRecord.setValue(commentStub.id, "commentID");
|
||||
},
|
||||
});
|
||||
|
||||
const context: TalkContext = {
|
||||
relayEnvironment: environment,
|
||||
localeMessages: [],
|
||||
};
|
||||
|
||||
const testRenderer = TestRenderer.create(
|
||||
<TalkContextProvider value={context}>
|
||||
<AppContainer />
|
||||
</TalkContextProvider>
|
||||
);
|
||||
|
||||
it("renders permalink view", async () => {
|
||||
// Wait for loading.
|
||||
await timeout();
|
||||
expect(testRenderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("show all comments", async () => {
|
||||
testRenderer.root
|
||||
.findByProps({
|
||||
id: "talk-comments-permalinkView-showAllComments",
|
||||
})
|
||||
.props.onClick();
|
||||
await timeout();
|
||||
expect(testRenderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
@@ -5,7 +5,7 @@ import sinon from "sinon";
|
||||
|
||||
import { timeout } from "talk-common/utils";
|
||||
import { TalkContext, TalkContextProvider } from "talk-framework/lib/bootstrap";
|
||||
import AppQuery from "talk-stream/queries/AppQuery";
|
||||
import AppContainer from "talk-stream/containers/AppContainer";
|
||||
|
||||
import createEnvironment from "./createEnvironment";
|
||||
import { assetWithReplies } from "./fixtures";
|
||||
@@ -36,7 +36,7 @@ const context: TalkContext = {
|
||||
|
||||
const testRenderer = TestRenderer.create(
|
||||
<TalkContextProvider value={context}>
|
||||
<AppQuery />
|
||||
<AppContainer />
|
||||
</TalkContextProvider>
|
||||
);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import sinon from "sinon";
|
||||
|
||||
import { timeout } from "talk-common/utils";
|
||||
import { TalkContext, TalkContextProvider } from "talk-framework/lib/bootstrap";
|
||||
import AppQuery from "talk-stream/queries/AppQuery";
|
||||
import AppContainer from "talk-stream/containers/AppContainer";
|
||||
|
||||
import createEnvironment from "./createEnvironment";
|
||||
import { assets } from "./fixtures";
|
||||
@@ -36,7 +36,7 @@ const context: TalkContext = {
|
||||
|
||||
const testRenderer = TestRenderer.create(
|
||||
<TalkContextProvider value={context}>
|
||||
<AppQuery />
|
||||
<AppContainer />
|
||||
</TalkContextProvider>
|
||||
);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import sinon from "sinon";
|
||||
|
||||
import { timeout } from "talk-common/utils";
|
||||
import { TalkContext, TalkContextProvider } from "talk-framework/lib/bootstrap";
|
||||
import AppQuery from "talk-stream/queries/AppQuery";
|
||||
import AppContainer from "talk-stream/containers/AppContainer";
|
||||
|
||||
import createEnvironment from "./createEnvironment";
|
||||
import { assets, comments } from "./fixtures";
|
||||
@@ -93,7 +93,7 @@ const context: TalkContext = {
|
||||
|
||||
const testRenderer = TestRenderer.create(
|
||||
<TalkContextProvider value={context}>
|
||||
<AppQuery />
|
||||
<AppContainer />
|
||||
</TalkContextProvider>
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user