diff --git a/src/core/client/stream/components/ReplyList.spec.tsx b/src/core/client/stream/components/ReplyList.spec.tsx index 2e5d6a984..514dab24c 100644 --- a/src/core/client/stream/components/ReplyList.spec.tsx +++ b/src/core/client/stream/components/ReplyList.spec.tsx @@ -1,27 +1,29 @@ import { shallow } from "enzyme"; import { noop } from "lodash"; import React from "react"; -import sinon from "sinon"; +import sinon, { SinonSpy } from "sinon"; -import ReplyList from "./ReplyList"; +import ReplyList, { ReplyListProps } from "./ReplyList"; it("renders correctly", () => { - const props = { + const props: ReplyListProps = { commentID: "comment-id", comments: [{ id: "comment-1" }, { id: "comment-2" }], - onLoadMore: noop, + onShowAll: noop, hasMore: false, + disableShowAll: false, }; const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); describe("when there is more", () => { - const props = { + const props: ReplyListProps = { commentID: "comment-id", comments: [{ id: "comment-1" }, { id: "comment-2" }], - onLoadMore: sinon.spy(), + onShowAll: sinon.spy(), hasMore: true, + disableShowAll: false, }; const wrapper = shallow(); @@ -31,6 +33,6 @@ describe("when there is more", () => { it("calls onLoadMore", () => { wrapper.find("#talk-reply-list--show-all--comment-id").simulate("click"); - expect(props.onLoadMore.calledOnce).toBe(true); + expect((props.onShowAll as SinonSpy).calledOnce).toBe(true); }); }); diff --git a/src/core/client/stream/components/ReplyList.tsx b/src/core/client/stream/components/ReplyList.tsx index ce9aa13c5..61ec5c314 100644 --- a/src/core/client/stream/components/ReplyList.tsx +++ b/src/core/client/stream/components/ReplyList.tsx @@ -9,8 +9,9 @@ import Indent from "./Indent"; export interface ReplyListProps { commentID: string; comments: ReadonlyArray<{ id: string }>; - onLoadMore: () => void; + onShowAll: () => void; hasMore: boolean; + disableShowAll: boolean; } const ReplyList: StatelessComponent = props => { @@ -22,7 +23,8 @@ const ReplyList: StatelessComponent = props => { {props.hasMore && ( diff --git a/src/core/client/stream/components/Username.tsx b/src/core/client/stream/components/Username.tsx index 3424e1f62..03a730121 100644 --- a/src/core/client/stream/components/Username.tsx +++ b/src/core/client/stream/components/Username.tsx @@ -11,7 +11,7 @@ export interface CommentProps { const Username: StatelessComponent = props => { return ( - + {props.children} ); diff --git a/src/core/client/stream/components/__snapshots__/ReplyList.spec.tsx.snap b/src/core/client/stream/components/__snapshots__/ReplyList.spec.tsx.snap index e9b0bd654..f049fede4 100644 --- a/src/core/client/stream/components/__snapshots__/ReplyList.spec.tsx.snap +++ b/src/core/client/stream/components/__snapshots__/ReplyList.spec.tsx.snap @@ -44,6 +44,7 @@ exports[`when there is more renders a load more button 1`] = ` key="comment-2" /> `; +exports[`when there is more disables load more button 1`] = ` +
+ + +
+ + +
+
+ + +
+ + Load More + +
+`; + exports[`when there is more renders a load more button 1`] = `
Marvin diff --git a/src/core/client/stream/containers/ReplyListContainer.spec.tsx b/src/core/client/stream/containers/ReplyListContainer.spec.tsx index d2fbb7534..75cb129ca 100644 --- a/src/core/client/stream/containers/ReplyListContainer.spec.tsx +++ b/src/core/client/stream/containers/ReplyListContainer.spec.tsx @@ -1,7 +1,10 @@ -import { shallow } from "enzyme"; +import { shallow, ShallowWrapper } from "enzyme"; import { noop } from "lodash"; import React from "react"; +import { PropTypesOf } from "talk-framework/types"; + +import ReplyList from "../components/ReplyList"; import { ReplyListContainer } from "./ReplyListContainer"; it("renders correctly", () => { @@ -35,3 +38,49 @@ it("renders correctly when replies are null", () => { const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); + +describe("when has more replies", () => { + let finishLoading: ((error?: Error) => void) | null = null; + const props: PropTypesOf = { + comment: { + id: "comment-id", + replies: { + edges: [{ node: { id: "comment-1" } }, { node: { id: "comment-2" } }], + }, + }, + relay: { + hasMore: () => true, + isLoading: () => false, + loadMore: (_: any, callback: () => void) => (finishLoading = callback), + } as any, + }; + + let wrapper: ShallowWrapper; + + beforeAll(() => (wrapper = shallow())); + + it("renders hasMore", () => { + expect(wrapper).toMatchSnapshot(); + }); + + describe("when showing all", () => { + beforeAll(() => { + wrapper + .find(ReplyList) + .props() + .onShowAll(); + }); + it("calls relay loadMore", () => { + expect(finishLoading).not.toBeNull(); + }); + it("disables show all button", () => { + wrapper.update(); + expect(wrapper).toMatchSnapshot(); + }); + it("enable show all button after loading is done", () => { + finishLoading!(); + wrapper.update(); + expect(wrapper).toMatchSnapshot(); + }); + }); +}); diff --git a/src/core/client/stream/containers/ReplyListContainer.tsx b/src/core/client/stream/containers/ReplyListContainer.tsx index 47f940f54..d147edb1c 100644 --- a/src/core/client/stream/containers/ReplyListContainer.tsx +++ b/src/core/client/stream/containers/ReplyListContainer.tsx @@ -17,6 +17,10 @@ export interface InnerProps { } export class ReplyListContainer extends React.Component { + public state = { + disableShowAll: false, + }; + public render() { if (this.props.comment.replies === null) { return null; @@ -26,20 +30,23 @@ export class ReplyListContainer extends React.Component { ); } - private loadMore = () => { + private showAll = () => { if (!this.props.relay.hasMore() || this.props.relay.isLoading()) { return; } + this.setState({ disableShowAll: true }); this.props.relay.loadMore( 999999999, // Fetch All Replies error => { + this.setState({ disableShowAll: false }); if (error) { // tslint:disable-next-line:no-console console.error(error); diff --git a/src/core/client/stream/containers/StreamContainer.spec.tsx b/src/core/client/stream/containers/StreamContainer.spec.tsx index 3ab0875d2..2e19bda86 100644 --- a/src/core/client/stream/containers/StreamContainer.spec.tsx +++ b/src/core/client/stream/containers/StreamContainer.spec.tsx @@ -1,11 +1,14 @@ -import { shallow } from "enzyme"; +import { shallow, ShallowWrapper } from "enzyme"; import { noop } from "lodash"; import React from "react"; +import { PropTypesOf } from "talk-framework/types"; + +import Stream from "../components/Stream"; import { StreamContainer } from "./StreamContainer"; it("renders correctly", () => { - const props: any = { + const props: PropTypesOf = { asset: { id: "asset-id", isClosed: false, @@ -16,8 +19,55 @@ it("renders correctly", () => { relay: { hasMore: noop, isLoading: noop, - }, + } as any, }; const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); + +describe("when has more comments", () => { + let finishLoading: ((error?: Error) => void) | null = null; + const props: PropTypesOf = { + asset: { + id: "asset-id", + isClosed: false, + comments: { + edges: [{ node: { id: "comment-1" } }, { node: { id: "comment-2" } }], + }, + }, + relay: { + hasMore: () => true, + isLoading: () => false, + loadMore: (_: any, callback: () => void) => (finishLoading = callback), + } as any, + }; + + let wrapper: ShallowWrapper; + + beforeAll(() => (wrapper = shallow())); + + it("renders hasMore", () => { + expect(wrapper).toMatchSnapshot(); + }); + + describe("when loading more", () => { + beforeAll(() => { + wrapper + .find(Stream) + .props() + .onLoadMore(); + }); + it("calls relay loadMore", () => { + expect(finishLoading).not.toBeNull(); + }); + it("disables load more button", () => { + wrapper.update(); + expect(wrapper).toMatchSnapshot(); + }); + it("enable load more button after loading is done", () => { + finishLoading!(); + wrapper.update(); + expect(wrapper).toMatchSnapshot(); + }); + }); +}); diff --git a/src/core/client/stream/containers/StreamContainer.tsx b/src/core/client/stream/containers/StreamContainer.tsx index e263337a2..9f13938b4 100644 --- a/src/core/client/stream/containers/StreamContainer.tsx +++ b/src/core/client/stream/containers/StreamContainer.tsx @@ -17,6 +17,10 @@ interface InnerProps { } export class StreamContainer extends React.Component { + public state = { + disableLoadMore: false, + }; + public render() { const comments = this.props.asset.comments ? this.props.asset.comments.edges.map(edge => edge.node) @@ -28,6 +32,7 @@ export class StreamContainer extends React.Component { comments={comments} onLoadMore={this.loadMore} hasMore={this.props.relay.hasMore()} + disableLoadMore={this.state.disableLoadMore} /> ); } @@ -36,10 +41,11 @@ export class StreamContainer extends React.Component { if (!this.props.relay.hasMore() || this.props.relay.isLoading()) { return; } - + this.setState({ disableLoadMore: true }); this.props.relay.loadMore( 10, // Fetch the next 10 feed items error => { + this.setState({ disableLoadMore: false }); if (error) { // tslint:disable-next-line:no-console console.error(error); diff --git a/src/core/client/stream/containers/__snapshots__/ReplyListContainer.spec.tsx.snap b/src/core/client/stream/containers/__snapshots__/ReplyListContainer.spec.tsx.snap index 4c6e7dabd..52aa9c57b 100644 --- a/src/core/client/stream/containers/__snapshots__/ReplyListContainer.spec.tsx.snap +++ b/src/core/client/stream/containers/__snapshots__/ReplyListContainer.spec.tsx.snap @@ -13,8 +13,66 @@ exports[`renders correctly 1`] = ` }, ] } - onLoadMore={[Function]} + disableShowAll={false} + onShowAll={[Function]} /> `; exports[`renders correctly when replies are null 1`] = `""`; + +exports[`when has more replies renders hasMore 1`] = ` + +`; + +exports[`when has more replies when showing all disables show all button 1`] = ` + +`; + +exports[`when has more replies when showing all enable show all button after loading is done 1`] = ` + +`; diff --git a/src/core/client/stream/containers/__snapshots__/StreamContainer.spec.tsx.snap b/src/core/client/stream/containers/__snapshots__/StreamContainer.spec.tsx.snap index 743ef5627..e3813397c 100644 --- a/src/core/client/stream/containers/__snapshots__/StreamContainer.spec.tsx.snap +++ b/src/core/client/stream/containers/__snapshots__/StreamContainer.spec.tsx.snap @@ -13,6 +13,67 @@ exports[`renders correctly 1`] = ` }, ] } + disableLoadMore={false} + isClosed={false} + onLoadMore={[Function]} +/> +`; + +exports[`when has more comments renders hasMore 1`] = ` + +`; + +exports[`when has more comments when loading more disables load more button 1`] = ` + +`; + +exports[`when has more comments when loading more enable load more button after loading is done 1`] = ` + diff --git a/src/core/client/stream/test/__snapshots__/loadMore.spec.tsx.snap b/src/core/client/stream/test/__snapshots__/loadMore.spec.tsx.snap index e349723c8..2ce30f68c 100644 --- a/src/core/client/stream/test/__snapshots__/loadMore.spec.tsx.snap +++ b/src/core/client/stream/test/__snapshots__/loadMore.spec.tsx.snap @@ -40,11 +40,11 @@ exports[`loads more comments 1`] = `
-

Markus -

+

@@ -56,11 +56,11 @@ exports[`loads more comments 1`] = `

-

Lukas -

+

@@ -72,11 +72,11 @@ exports[`loads more comments 1`] = `

-

Isabelle -

+

@@ -128,11 +128,11 @@ exports[`renders comment stream 1`] = `

-

Markus -

+

@@ -144,11 +144,11 @@ exports[`renders comment stream 1`] = `

-

Lukas -

+

@@ -158,6 +158,7 @@ exports[`renders comment stream 1`] = `

- - - - - + + + + + + + + + + + + + diff --git a/src/core/client/ui/types.ts b/src/core/client/ui/types.ts index 061b7d3d5..576b881c3 100644 --- a/src/core/client/ui/types.ts +++ b/src/core/client/ui/types.ts @@ -29,4 +29,6 @@ export type Overwrite = Pick> & U; * * E.g. type ButtonProps = ReturnPropTypes