mirror of
https://github.com/element-hq/element-web
synced 2024-11-22 09:15:41 +03:00
Poll history: fetch more poll history (#10235)
* load more pages of polls * load more and no results messages * style no results message * remove debug * strict fixes * comments * i18n pluralisations * pluralisation the right way
This commit is contained in:
parent
f57495d3cd
commit
7c70dd9d16
7 changed files with 300 additions and 105 deletions
|
@ -41,10 +41,20 @@ limitations under the License.
|
|||
.mx_PollHistoryList_noResults {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0 $spacing-64;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
|
||||
line-height: $font-24px;
|
||||
color: $secondary-content;
|
||||
|
||||
.mx_PollHistoryList_loadMorePolls {
|
||||
margin-top: $spacing-16;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_PollHistoryList_loading {
|
||||
|
@ -57,3 +67,7 @@ limitations under the License.
|
|||
margin: auto auto;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_PollHistoryList_loadMorePolls {
|
||||
width: max-content;
|
||||
}
|
||||
|
|
|
@ -57,9 +57,9 @@ export const PollHistoryDialog: React.FC<PollHistoryDialogProps> = ({
|
|||
onFinished,
|
||||
}) => {
|
||||
const { polls } = usePollsWithRelations(room.roomId, matrixClient);
|
||||
const { isLoading, loadMorePolls, oldestEventTimestamp } = useFetchPastPolls(room, matrixClient);
|
||||
const [filter, setFilter] = useState<PollHistoryFilter>("ACTIVE");
|
||||
const [focusedPollId, setFocusedPollId] = useState<string | null>(null);
|
||||
const { isLoading } = useFetchPastPolls(room, matrixClient);
|
||||
|
||||
const pollStartEvents = filterAndSortPolls(polls, filter);
|
||||
const isLoadingPollResponses = [...polls.values()].some((poll) => poll.isFetchingResponses);
|
||||
|
@ -78,12 +78,14 @@ export const PollHistoryDialog: React.FC<PollHistoryDialogProps> = ({
|
|||
<PollDetail poll={focusedPoll} permalinkCreator={permalinkCreator} requestModalClose={onFinished} />
|
||||
) : (
|
||||
<PollHistoryList
|
||||
onItemClick={setFocusedPollId}
|
||||
pollStartEvents={pollStartEvents}
|
||||
isLoading={isLoading || isLoadingPollResponses}
|
||||
oldestFetchedEventTimestamp={oldestEventTimestamp}
|
||||
polls={polls}
|
||||
filter={filter}
|
||||
onFilterChange={setFilter}
|
||||
onItemClick={setFocusedPollId}
|
||||
loadMorePolls={loadMorePolls}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -24,6 +24,7 @@ import InlineSpinner from "../../elements/InlineSpinner";
|
|||
import { PollHistoryFilter } from "./types";
|
||||
import { PollListItem } from "./PollListItem";
|
||||
import { PollListItemEnded } from "./PollListItemEnded";
|
||||
import AccessibleButton from "../../elements/AccessibleButton";
|
||||
|
||||
const LoadingPolls: React.FC<{ noResultsYet?: boolean }> = ({ noResultsYet }) => (
|
||||
<div
|
||||
|
@ -36,20 +37,93 @@ const LoadingPolls: React.FC<{ noResultsYet?: boolean }> = ({ noResultsYet }) =>
|
|||
</div>
|
||||
);
|
||||
|
||||
const LoadMorePolls: React.FC<{ loadMorePolls?: () => void; isLoading?: boolean }> = ({ isLoading, loadMorePolls }) =>
|
||||
loadMorePolls ? (
|
||||
<AccessibleButton
|
||||
className="mx_PollHistoryList_loadMorePolls"
|
||||
kind="link_inline"
|
||||
onClick={() => loadMorePolls()}
|
||||
>
|
||||
{_t("Load more polls")}
|
||||
{isLoading && <InlineSpinner />}
|
||||
</AccessibleButton>
|
||||
) : null;
|
||||
|
||||
const ONE_DAY_MS = 60000 * 60 * 24;
|
||||
const getNoResultsMessage = (
|
||||
filter: PollHistoryFilter,
|
||||
oldestEventTimestamp?: number,
|
||||
loadMorePolls?: () => void,
|
||||
): string => {
|
||||
if (!loadMorePolls) {
|
||||
return filter === "ACTIVE"
|
||||
? _t("There are no active polls in this room")
|
||||
: _t("There are no past polls in this room");
|
||||
}
|
||||
|
||||
// we don't know how much history has been fetched
|
||||
if (!oldestEventTimestamp) {
|
||||
return filter === "ACTIVE"
|
||||
? _t("There are no active polls. Load more polls to view polls for previous months")
|
||||
: _t("There are no past polls. Load more polls to view polls for previous months");
|
||||
}
|
||||
|
||||
const fetchedHistoryDaysCount = Math.ceil((Date.now() - oldestEventTimestamp) / ONE_DAY_MS);
|
||||
return filter === "ACTIVE"
|
||||
? _t(
|
||||
"There are no active polls for the past %(count)s days. Load more polls to view polls for previous months",
|
||||
{ count: fetchedHistoryDaysCount },
|
||||
)
|
||||
: _t("There are no past polls for the past %(count)s days. Load more polls to view polls for previous months", {
|
||||
count: fetchedHistoryDaysCount,
|
||||
});
|
||||
};
|
||||
|
||||
const NoResults: React.FC<{
|
||||
filter: PollHistoryFilter;
|
||||
oldestFetchedEventTimestamp?: number;
|
||||
loadMorePolls?: () => void;
|
||||
isLoading?: boolean;
|
||||
}> = ({ filter, isLoading, oldestFetchedEventTimestamp, loadMorePolls }) => {
|
||||
// we can't page the timeline anymore
|
||||
// just use plain loader
|
||||
if (!loadMorePolls && isLoading) {
|
||||
return <LoadingPolls noResultsYet />;
|
||||
}
|
||||
|
||||
return (
|
||||
<span className="mx_PollHistoryList_noResults">
|
||||
{getNoResultsMessage(filter, oldestFetchedEventTimestamp, loadMorePolls)}
|
||||
|
||||
{!!loadMorePolls && <LoadMorePolls loadMorePolls={loadMorePolls} isLoading={isLoading} />}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
type PollHistoryListProps = {
|
||||
pollStartEvents: MatrixEvent[];
|
||||
polls: Map<string, Poll>;
|
||||
filter: PollHistoryFilter;
|
||||
isLoading?: boolean;
|
||||
/**
|
||||
* server ts of the oldest fetched poll
|
||||
* ignoring filter
|
||||
* used to render no results in last x days message
|
||||
* undefined when no polls are found
|
||||
*/
|
||||
oldestFetchedEventTimestamp?: number;
|
||||
onFilterChange: (filter: PollHistoryFilter) => void;
|
||||
onItemClick: (pollId: string) => void;
|
||||
loadMorePolls?: () => void;
|
||||
isLoading?: boolean;
|
||||
};
|
||||
export const PollHistoryList: React.FC<PollHistoryListProps> = ({
|
||||
pollStartEvents,
|
||||
polls,
|
||||
filter,
|
||||
isLoading,
|
||||
oldestFetchedEventTimestamp,
|
||||
onFilterChange,
|
||||
loadMorePolls,
|
||||
onItemClick,
|
||||
}) => {
|
||||
return (
|
||||
|
@ -81,17 +155,18 @@ export const PollHistoryList: React.FC<PollHistoryListProps> = ({
|
|||
/>
|
||||
),
|
||||
)}
|
||||
{isLoading && <LoadingPolls />}
|
||||
{isLoading && !loadMorePolls && <LoadingPolls />}
|
||||
{!!loadMorePolls && <LoadMorePolls loadMorePolls={loadMorePolls} isLoading={isLoading} />}
|
||||
</ol>
|
||||
)}
|
||||
{!pollStartEvents.length && !isLoading && (
|
||||
<span className="mx_PollHistoryList_noResults">
|
||||
{filter === "ACTIVE"
|
||||
? _t("There are no active polls in this room")
|
||||
: _t("There are no past polls in this room")}
|
||||
</span>
|
||||
{!pollStartEvents.length && (
|
||||
<NoResults
|
||||
oldestFetchedEventTimestamp={oldestFetchedEventTimestamp}
|
||||
isLoading={isLoading}
|
||||
filter={filter}
|
||||
loadMorePolls={loadMorePolls}
|
||||
/>
|
||||
)}
|
||||
{!pollStartEvents.length && isLoading && <LoadingPolls noResultsYet />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -14,41 +14,82 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { M_POLL_START } from "matrix-js-sdk/src/@types/polls";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
import { EventTimeline, EventTimelineSet, Room } from "matrix-js-sdk/src/matrix";
|
||||
import { Direction, EventTimeline, EventTimelineSet, Room } from "matrix-js-sdk/src/matrix";
|
||||
import { Filter, IFilterDefinition } from "matrix-js-sdk/src/filter";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
/**
|
||||
* Page timeline backwards until either:
|
||||
* - event older than endOfHistoryPeriodTimestamp is encountered
|
||||
* - end of timeline is reached
|
||||
* @param timelineSet - timelineset to page
|
||||
* @param matrixClient - client
|
||||
* @param endOfHistoryPeriodTimestamp - epoch timestamp to fetch until
|
||||
* @returns void
|
||||
*/
|
||||
const pagePolls = async (
|
||||
timelineSet: EventTimelineSet,
|
||||
matrixClient: MatrixClient,
|
||||
endOfHistoryPeriodTimestamp: number,
|
||||
): Promise<void> => {
|
||||
const liveTimeline = timelineSet.getLiveTimeline();
|
||||
const events = liveTimeline.getEvents();
|
||||
const oldestEventTimestamp = events[0]?.getTs() || Date.now();
|
||||
const hasMorePages = !!liveTimeline.getPaginationToken(EventTimeline.BACKWARDS);
|
||||
|
||||
if (!hasMorePages || oldestEventTimestamp <= endOfHistoryPeriodTimestamp) {
|
||||
const getOldestEventTimestamp = (timelineSet?: EventTimelineSet): number | undefined => {
|
||||
if (!timelineSet) {
|
||||
return;
|
||||
}
|
||||
|
||||
const liveTimeline = timelineSet?.getLiveTimeline();
|
||||
const events = liveTimeline.getEvents();
|
||||
return events[0]?.getTs();
|
||||
};
|
||||
|
||||
/**
|
||||
* Page backwards in timeline history
|
||||
* @param timelineSet - timelineset to page
|
||||
* @param matrixClient - client
|
||||
* @param canPageBackward - whether the timeline has more pages
|
||||
* @param oldestEventTimestamp - server ts of the oldest encountered event
|
||||
*/
|
||||
const pagePollHistory = async (
|
||||
timelineSet: EventTimelineSet,
|
||||
matrixClient: MatrixClient,
|
||||
): Promise<{
|
||||
oldestEventTimestamp?: number;
|
||||
canPageBackward: boolean;
|
||||
}> => {
|
||||
if (!timelineSet) {
|
||||
return { canPageBackward: false };
|
||||
}
|
||||
|
||||
const liveTimeline = timelineSet.getLiveTimeline();
|
||||
|
||||
await matrixClient.paginateEventTimeline(liveTimeline, {
|
||||
backwards: true,
|
||||
});
|
||||
|
||||
return pagePolls(timelineSet, matrixClient, endOfHistoryPeriodTimestamp);
|
||||
return {
|
||||
oldestEventTimestamp: getOldestEventTimestamp(timelineSet),
|
||||
canPageBackward: !!liveTimeline.getPaginationToken(EventTimeline.BACKWARDS),
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Page timeline backwards until either:
|
||||
* - event older than timestamp is encountered
|
||||
* - end of timeline is reached
|
||||
* @param timelineSet - timeline set to page
|
||||
* @param matrixClient - client
|
||||
* @param timestamp - epoch timestamp to page until
|
||||
* @param canPageBackward - whether the timeline has more pages
|
||||
* @param oldestEventTimestamp - server ts of the oldest encountered event
|
||||
*/
|
||||
const fetchHistoryUntilTimestamp = async (
|
||||
timelineSet: EventTimelineSet | undefined,
|
||||
matrixClient: MatrixClient,
|
||||
timestamp: number,
|
||||
canPageBackward: boolean,
|
||||
oldestEventTimestamp?: number,
|
||||
): Promise<void> => {
|
||||
if (!timelineSet || !canPageBackward || (oldestEventTimestamp && oldestEventTimestamp < timestamp)) {
|
||||
return;
|
||||
}
|
||||
const result = await pagePollHistory(timelineSet, matrixClient);
|
||||
|
||||
return fetchHistoryUntilTimestamp(
|
||||
timelineSet,
|
||||
matrixClient,
|
||||
timestamp,
|
||||
result.canPageBackward,
|
||||
result.oldestEventTimestamp,
|
||||
);
|
||||
};
|
||||
|
||||
const ONE_DAY_MS = 60000 * 60 * 24;
|
||||
|
@ -57,35 +98,73 @@ const ONE_DAY_MS = 60000 * 60 * 24;
|
|||
* @param timelineSet - timelineset to page
|
||||
* @param matrixClient - client
|
||||
* @param historyPeriodDays - number of days of history to fetch, from current day
|
||||
* @returns isLoading - true while fetching history
|
||||
* @returns isLoading - true while fetching
|
||||
* @returns oldestEventTimestamp - timestamp of oldest encountered poll, undefined when no polls found in timeline so far
|
||||
* @returns loadMorePolls - function to page timeline backwards, undefined when timeline cannot be paged backwards
|
||||
* @returns loadTimelineHistory - loads timeline history for the given history period
|
||||
*/
|
||||
const useTimelineHistory = (
|
||||
timelineSet: EventTimelineSet | null,
|
||||
timelineSet: EventTimelineSet | undefined,
|
||||
matrixClient: MatrixClient,
|
||||
historyPeriodDays: number,
|
||||
): { isLoading: boolean } => {
|
||||
): {
|
||||
isLoading: boolean;
|
||||
oldestEventTimestamp?: number;
|
||||
loadTimelineHistory: () => Promise<void>;
|
||||
loadMorePolls?: () => Promise<void>;
|
||||
} => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [oldestEventTimestamp, setOldestEventTimestamp] = useState<number | undefined>(undefined);
|
||||
const [canPageBackward, setCanPageBackward] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!timelineSet) {
|
||||
return;
|
||||
}
|
||||
const loadTimelineHistory = useCallback(async () => {
|
||||
const endOfHistoryPeriodTimestamp = Date.now() - ONE_DAY_MS * historyPeriodDays;
|
||||
|
||||
const doFetchHistory = async (): Promise<void> => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
await pagePolls(timelineSet, matrixClient, endOfHistoryPeriodTimestamp);
|
||||
const liveTimeline = timelineSet?.getLiveTimeline();
|
||||
const canPageBackward = !!liveTimeline?.getPaginationToken(Direction.Backward);
|
||||
const oldestEventTimestamp = getOldestEventTimestamp(timelineSet);
|
||||
|
||||
await fetchHistoryUntilTimestamp(
|
||||
timelineSet,
|
||||
matrixClient,
|
||||
endOfHistoryPeriodTimestamp,
|
||||
canPageBackward,
|
||||
oldestEventTimestamp,
|
||||
);
|
||||
|
||||
setCanPageBackward(!!timelineSet?.getLiveTimeline()?.getPaginationToken(EventTimeline.BACKWARDS));
|
||||
setOldestEventTimestamp(getOldestEventTimestamp(timelineSet));
|
||||
} catch (error) {
|
||||
logger.error("Failed to fetch room polls history", error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
doFetchHistory();
|
||||
}, [timelineSet, historyPeriodDays, matrixClient]);
|
||||
}, [historyPeriodDays, timelineSet, matrixClient]);
|
||||
|
||||
return { isLoading };
|
||||
const loadMorePolls = useCallback(async () => {
|
||||
if (!timelineSet) {
|
||||
return;
|
||||
}
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const result = await pagePollHistory(timelineSet, matrixClient);
|
||||
|
||||
setCanPageBackward(result.canPageBackward);
|
||||
setOldestEventTimestamp(result.oldestEventTimestamp);
|
||||
} catch (error) {
|
||||
logger.error("Failed to fetch room polls history", error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [timelineSet, matrixClient]);
|
||||
|
||||
return {
|
||||
isLoading,
|
||||
oldestEventTimestamp,
|
||||
loadTimelineHistory,
|
||||
loadMorePolls: canPageBackward ? loadMorePolls : undefined,
|
||||
};
|
||||
};
|
||||
|
||||
const filterDefinition: IFilterDefinition = {
|
||||
|
@ -97,18 +176,24 @@ const filterDefinition: IFilterDefinition = {
|
|||
};
|
||||
|
||||
/**
|
||||
* Fetch poll start events in the last N days of room history
|
||||
* Fetches poll start events in the last N days of room history
|
||||
* @param room - room to fetch history for
|
||||
* @param matrixClient - client
|
||||
* @param historyPeriodDays - number of days of history to fetch, from current day
|
||||
* @returns isLoading - true while fetching history
|
||||
* @returns oldestEventTimestamp - timestamp of oldest encountered poll, undefined when no polls found in timeline so far
|
||||
* @returns loadMorePolls - function to page timeline backwards, undefined when timeline cannot be paged backwards
|
||||
*/
|
||||
export const useFetchPastPolls = (
|
||||
room: Room,
|
||||
matrixClient: MatrixClient,
|
||||
historyPeriodDays = 30,
|
||||
): { isLoading: boolean } => {
|
||||
const [timelineSet, setTimelineSet] = useState<EventTimelineSet | null>(null);
|
||||
): {
|
||||
isLoading: boolean;
|
||||
oldestEventTimestamp?: number;
|
||||
loadMorePolls?: () => Promise<void>;
|
||||
} => {
|
||||
const [timelineSet, setTimelineSet] = useState<EventTimelineSet | undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
const filter = new Filter(matrixClient.getSafeUserId());
|
||||
|
@ -123,7 +208,15 @@ export const useFetchPastPolls = (
|
|||
getFilteredTimelineSet();
|
||||
}, [room, matrixClient]);
|
||||
|
||||
const { isLoading } = useTimelineHistory(timelineSet, matrixClient, historyPeriodDays);
|
||||
const { isLoading, oldestEventTimestamp, loadMorePolls, loadTimelineHistory } = useTimelineHistory(
|
||||
timelineSet,
|
||||
matrixClient,
|
||||
historyPeriodDays,
|
||||
);
|
||||
|
||||
return { isLoading };
|
||||
useEffect(() => {
|
||||
loadTimelineHistory();
|
||||
}, [loadTimelineHistory]);
|
||||
|
||||
return { isLoading, oldestEventTimestamp, loadMorePolls };
|
||||
};
|
||||
|
|
|
@ -3143,8 +3143,15 @@
|
|||
"Active polls": "Active polls",
|
||||
"Past polls": "Past polls",
|
||||
"Loading polls": "Loading polls",
|
||||
"Load more polls": "Load more polls",
|
||||
"There are no active polls in this room": "There are no active polls in this room",
|
||||
"There are no past polls in this room": "There are no past polls in this room",
|
||||
"There are no active polls. Load more polls to view polls for previous months": "There are no active polls. Load more polls to view polls for previous months",
|
||||
"There are no past polls. Load more polls to view polls for previous months": "There are no past polls. Load more polls to view polls for previous months",
|
||||
"There are no active polls for the past %(count)s days. Load more polls to view polls for previous months|other": "There are no active polls for the past %(count)s days. Load more polls to view polls for previous months",
|
||||
"There are no active polls for the past %(count)s days. Load more polls to view polls for previous months|one": "There are no active polls for the past day. Load more polls to view polls for previous months",
|
||||
"There are no past polls for the past %(count)s days. Load more polls to view polls for previous months|other": "There are no past polls for the past %(count)s days. Load more polls to view polls for previous months",
|
||||
"There are no past polls for the past %(count)s days. Load more polls to view polls for previous months|one": "There are no past polls for the past day. Load more polls to view polls for previous months",
|
||||
"View poll": "View poll",
|
||||
"Send custom account data event": "Send custom account data event",
|
||||
"Send custom room account data event": "Send custom room account data event",
|
||||
|
|
|
@ -176,12 +176,20 @@ describe("<PollHistoryDialog />", () => {
|
|||
expect(mockClient.paginateEventTimeline).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("displays loader and list while paging timeline", async () => {
|
||||
it("renders a no polls message when there are no active polls in the room", async () => {
|
||||
const { getByText } = getComponent();
|
||||
await flushPromises();
|
||||
|
||||
expect(getByText("There are no active polls in this room")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("renders a no polls message and a load more button when not at end of timeline", async () => {
|
||||
const timelineSet = room.getOrCreateFilteredTimelineSet(expectedFilter);
|
||||
const liveTimeline = timelineSet.getLiveTimeline();
|
||||
const tenDaysAgoTs = now - 60000 * 60 * 24 * 10;
|
||||
const fourtyDaysAgoTs = now - 60000 * 60 * 24 * 40;
|
||||
const pollStart = makePollStartEvent("Question?", userId, undefined, { ts: fourtyDaysAgoTs, id: "1" });
|
||||
|
||||
jest.spyOn(liveTimeline, "getEvents").mockReset().mockReturnValue([]);
|
||||
jest.spyOn(liveTimeline, "getEvents").mockReset().mockReturnValueOnce([]).mockReturnValueOnce([pollStart]);
|
||||
|
||||
// mock three pages of timeline history
|
||||
jest.spyOn(liveTimeline, "getPaginationToken")
|
||||
|
@ -189,57 +197,24 @@ describe("<PollHistoryDialog />", () => {
|
|||
.mockReturnValueOnce("test-pagination-token-2")
|
||||
.mockReturnValueOnce("test-pagination-token-3");
|
||||
|
||||
// reference to pagination resolve, so we can assert between pages
|
||||
let resolvePagination1: (value: boolean) => void | undefined;
|
||||
let resolvePagination2: (value: boolean) => void | undefined;
|
||||
mockClient.paginateEventTimeline
|
||||
.mockImplementationOnce(async (_p) => {
|
||||
const pollStart = makePollStartEvent("Question?", userId, undefined, { ts: now, id: "1" });
|
||||
jest.spyOn(liveTimeline, "getEvents").mockReturnValue([pollStart]);
|
||||
room.processPollEvents([pollStart]);
|
||||
return new Promise((resolve) => (resolvePagination1 = resolve));
|
||||
})
|
||||
.mockImplementationOnce(async (_p) => {
|
||||
const pollStart = makePollStartEvent("Older question?", userId, undefined, {
|
||||
ts: tenDaysAgoTs,
|
||||
id: "2",
|
||||
});
|
||||
jest.spyOn(liveTimeline, "getEvents").mockReturnValue([pollStart]);
|
||||
room.processPollEvents([pollStart]);
|
||||
return new Promise((resolve) => (resolvePagination2 = resolve));
|
||||
});
|
||||
|
||||
const { getByText, queryByText } = getComponent();
|
||||
|
||||
const { getByText } = getComponent();
|
||||
await flushPromises();
|
||||
|
||||
expect(mockClient.paginateEventTimeline).toHaveBeenCalledTimes(1);
|
||||
|
||||
resolvePagination1!(true);
|
||||
expect(getByText("There are no active polls. Load more polls to view polls for previous months")).toBeTruthy();
|
||||
|
||||
fireEvent.click(getByText("Load more polls"));
|
||||
|
||||
// paged again
|
||||
expect(mockClient.paginateEventTimeline).toHaveBeenCalledTimes(2);
|
||||
// load more polls button still in UI, with loader
|
||||
expect(getByText("Load more polls")).toMatchSnapshot();
|
||||
|
||||
await flushPromises();
|
||||
|
||||
// first page has results, display immediately
|
||||
expect(getByText("Question?")).toBeInTheDocument();
|
||||
// but we are still fetching history, diaply loader
|
||||
expect(getByText("Loading polls")).toBeInTheDocument();
|
||||
|
||||
resolvePagination2!(true);
|
||||
await flushPromises();
|
||||
|
||||
// additional results addeds
|
||||
expect(getByText("Older question?")).toBeInTheDocument();
|
||||
expect(getByText("Question?")).toBeInTheDocument();
|
||||
// finished paging
|
||||
expect(queryByText("Loading polls")).not.toBeInTheDocument();
|
||||
|
||||
expect(mockClient.paginateEventTimeline).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
it("renders a no polls message when there are no active polls in the room", async () => {
|
||||
const { getByText } = getComponent();
|
||||
await flushPromises();
|
||||
|
||||
expect(getByText("There are no active polls in this room")).toBeTruthy();
|
||||
// no more spinner
|
||||
expect(getByText("Load more polls")).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders a no past polls message when there are no past polls in the room", async () => {
|
||||
|
|
|
@ -168,3 +168,32 @@ exports[`<PollHistoryDialog /> renders a list of active polls when there are pol
|
|||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<PollHistoryDialog /> renders a no polls message and a load more button when not at end of timeline 1`] = `
|
||||
<div
|
||||
class="mx_AccessibleButton mx_PollHistoryList_loadMorePolls mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Load more polls
|
||||
<div
|
||||
class="mx_InlineSpinner"
|
||||
>
|
||||
<div
|
||||
aria-label="Loading…"
|
||||
class="mx_InlineSpinner_icon mx_Spinner_icon"
|
||||
style="width: 16px; height: 16px;"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<PollHistoryDialog /> renders a no polls message and a load more button when not at end of timeline 2`] = `
|
||||
<div
|
||||
class="mx_AccessibleButton mx_PollHistoryList_loadMorePolls mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Load more polls
|
||||
</div>
|
||||
`;
|
||||
|
|
Loading…
Reference in a new issue