mirror of
https://github.com/wassname/talk.git
synced 2026-09-11 12:51:33 +08:00
Implement reply
This commit is contained in:
@@ -49,6 +49,7 @@ export class CommentContainer extends Component<InnerProps, State> {
|
||||
footer={
|
||||
<>
|
||||
<ReplyButton
|
||||
id={`comments-commentContainer-replyButton-${comment.id}`}
|
||||
onClick={this.openReplyDialog}
|
||||
active={showReplyDialog}
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
import { shallow } from "enzyme";
|
||||
import { noop } from "lodash";
|
||||
import React from "react";
|
||||
import sinon from "sinon";
|
||||
|
||||
import { PropTypesOf } from "talk-framework/types";
|
||||
|
||||
import { timeout } from "talk-common/utils";
|
||||
import {
|
||||
createFakePymStorage,
|
||||
removeFragmentRefs,
|
||||
} from "talk-framework/testHelpers";
|
||||
import { ReplyCommentFormContainer } from "./ReplyCommentFormContainer";
|
||||
|
||||
const ReplyCommentFormContainerN = removeFragmentRefs(
|
||||
ReplyCommentFormContainer
|
||||
);
|
||||
|
||||
function getContextKey(commentID: string) {
|
||||
return `replyCommentFormBody-${commentID}`;
|
||||
}
|
||||
|
||||
it("renders correctly", async () => {
|
||||
const props: PropTypesOf<typeof ReplyCommentFormContainerN> = {
|
||||
// tslint:disable-next-line:no-empty
|
||||
createComment: (() => {}) as any,
|
||||
asset: {
|
||||
id: "asset-id",
|
||||
},
|
||||
comment: {
|
||||
id: "comment-id",
|
||||
},
|
||||
pymSessionStorage: createFakePymStorage(),
|
||||
};
|
||||
|
||||
const wrapper = shallow(<ReplyCommentFormContainerN {...props} />);
|
||||
await timeout();
|
||||
wrapper.update();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders with initialValues", async () => {
|
||||
const props: PropTypesOf<typeof ReplyCommentFormContainerN> = {
|
||||
// tslint:disable-next-line:no-empty
|
||||
createComment: (() => {}) as any,
|
||||
asset: {
|
||||
id: "asset-id",
|
||||
},
|
||||
comment: {
|
||||
id: "comment-id",
|
||||
},
|
||||
pymSessionStorage: createFakePymStorage(),
|
||||
};
|
||||
|
||||
await props.pymSessionStorage.setItem(
|
||||
getContextKey(props.comment.id),
|
||||
"Hello World!"
|
||||
);
|
||||
|
||||
const wrapper = shallow(<ReplyCommentFormContainerN {...props} />);
|
||||
await timeout();
|
||||
wrapper.update();
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("save values", async () => {
|
||||
const props: PropTypesOf<typeof ReplyCommentFormContainerN> = {
|
||||
// tslint:disable-next-line:no-empty
|
||||
createComment: (() => {}) as any,
|
||||
asset: {
|
||||
id: "asset-id",
|
||||
},
|
||||
comment: {
|
||||
id: "comment-id",
|
||||
},
|
||||
pymSessionStorage: createFakePymStorage(),
|
||||
};
|
||||
|
||||
await props.pymSessionStorage.setItem(
|
||||
getContextKey(props.comment.id),
|
||||
"Hello World!"
|
||||
);
|
||||
|
||||
const wrapper = shallow(<ReplyCommentFormContainerN {...props} />);
|
||||
await timeout();
|
||||
wrapper.update();
|
||||
wrapper
|
||||
.first()
|
||||
.props()
|
||||
.onChange({ values: { body: "changed" } });
|
||||
expect(
|
||||
await props.pymSessionStorage.getItem(getContextKey(props.comment.id))
|
||||
).toBe("changed");
|
||||
});
|
||||
|
||||
it("creates a comment", async () => {
|
||||
const assetID = "asset-id";
|
||||
const input = { body: "Hello World!" };
|
||||
const createCommentStub = sinon.stub();
|
||||
const form = { reset: noop };
|
||||
const onCloseStub = sinon.stub();
|
||||
|
||||
const props: PropTypesOf<typeof ReplyCommentFormContainerN> = {
|
||||
// tslint:disable-next-line:no-empty
|
||||
createComment: createCommentStub,
|
||||
asset: {
|
||||
id: "asset-id",
|
||||
},
|
||||
comment: {
|
||||
id: "comment-id",
|
||||
},
|
||||
pymSessionStorage: createFakePymStorage(),
|
||||
onClose: onCloseStub,
|
||||
};
|
||||
|
||||
await props.pymSessionStorage.setItem(
|
||||
getContextKey(props.comment.id),
|
||||
"Hello World!"
|
||||
);
|
||||
|
||||
const wrapper = shallow(<ReplyCommentFormContainerN {...props} />);
|
||||
await timeout();
|
||||
wrapper.update();
|
||||
wrapper
|
||||
.first()
|
||||
.props()
|
||||
.onSubmit(input, form);
|
||||
expect(
|
||||
createCommentStub.calledWith({
|
||||
assetID,
|
||||
parentID: props.comment.id,
|
||||
...input,
|
||||
})
|
||||
).toBeTruthy();
|
||||
await timeout();
|
||||
expect(onCloseStub.calledOnce).toBe(true);
|
||||
});
|
||||
|
||||
it("closes on cancel", async () => {
|
||||
const onCloseStub = sinon.stub();
|
||||
const props: PropTypesOf<typeof ReplyCommentFormContainerN> = {
|
||||
// tslint:disable-next-line:no-empty
|
||||
createComment: (() => {}) as any,
|
||||
asset: {
|
||||
id: "asset-id",
|
||||
},
|
||||
comment: {
|
||||
id: "comment-id",
|
||||
},
|
||||
pymSessionStorage: createFakePymStorage(),
|
||||
onClose: onCloseStub,
|
||||
};
|
||||
|
||||
await props.pymSessionStorage.setItem(
|
||||
getContextKey(props.comment.id),
|
||||
"Hello World!"
|
||||
);
|
||||
|
||||
const wrapper = shallow(<ReplyCommentFormContainerN {...props} />);
|
||||
await timeout();
|
||||
wrapper.update();
|
||||
wrapper.findWhere(w => !!w.prop("onCancel")).prop("onCancel")();
|
||||
|
||||
// Calls close.
|
||||
expect(onCloseStub.calledOnce).toBe(true);
|
||||
|
||||
// Removes saved value.
|
||||
expect(
|
||||
await props.pymSessionStorage.getItem(getContextKey(props.comment.id))
|
||||
).toBeNull();
|
||||
});
|
||||
@@ -67,6 +67,7 @@ export class ReplyCommentFormContainer extends Component<InnerProps, State> {
|
||||
parentID: this.props.comment.id,
|
||||
...input,
|
||||
});
|
||||
|
||||
this.props.pymSessionStorage.removeItem(this.contextKey);
|
||||
if (this.props.onClose) {
|
||||
this.props.onClose();
|
||||
@@ -95,6 +96,7 @@ export class ReplyCommentFormContainer extends Component<InnerProps, State> {
|
||||
}
|
||||
return (
|
||||
<ReplyCommentForm
|
||||
id={this.props.comment.id}
|
||||
onSubmit={this.handleOnSubmit}
|
||||
onChange={this.handleOnChange}
|
||||
initialValues={this.state.initialValues}
|
||||
|
||||
@@ -18,6 +18,15 @@ interface InnerProps {
|
||||
relay: RelayPaginationProp;
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:no-unused-expression
|
||||
graphql`
|
||||
fragment StreamContainer_comment on Comment {
|
||||
id
|
||||
...CommentContainer_comment
|
||||
...ReplyListContainer_comment
|
||||
}
|
||||
`;
|
||||
|
||||
export class StreamContainer extends React.Component<InnerProps> {
|
||||
public state = {
|
||||
disableLoadMore: false,
|
||||
@@ -81,9 +90,7 @@ const enhanced = withPaginationContainer<
|
||||
@connection(key: "Stream_comments") {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...CommentContainer_comment
|
||||
...ReplyListContainer_comment
|
||||
...StreamContainer_comment @relay(mask: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ exports[`renders body only 1`] = `
|
||||
<React.Fragment>
|
||||
<ReplyButton
|
||||
active={false}
|
||||
id="comments-commentContainer-replyButton"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
<withContext(withLocalStateContainer(PermalinkContainer))
|
||||
@@ -41,6 +42,7 @@ exports[`renders username and body 1`] = `
|
||||
<React.Fragment>
|
||||
<ReplyButton
|
||||
active={false}
|
||||
id="comments-commentContainer-replyButton"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
<withContext(withLocalStateContainer(PermalinkContainer))
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<ReplyCommentForm
|
||||
onCancel={[Function]}
|
||||
onChange={[Function]}
|
||||
onSubmit={[Function]}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`renders with initialValues 1`] = `
|
||||
<ReplyCommentForm
|
||||
initialValues={
|
||||
Object {
|
||||
"body": "Hello World!",
|
||||
}
|
||||
}
|
||||
onCancel={[Function]}
|
||||
onChange={[Function]}
|
||||
onSubmit={[Function]}
|
||||
/>
|
||||
`;
|
||||
Reference in New Issue
Block a user