Merge matrix-react-sdk into element-web

Merge remote-tracking branch 'repomerge/t3chguy/repomerge' into t3chguy/repo-merge

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski 2024-10-15 14:57:26 +01:00
commit f0ee7f7905
No known key found for this signature in database
GPG key ID: A2B008A5F49F5D0D
3265 changed files with 484599 additions and 699 deletions

View file

@ -0,0 +1,436 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2023 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
import React from "react";
import { act, fireEvent, render } from "jest-matrix-react";
import { Filter, EventTimeline, Room, MatrixEvent, M_POLL_START } from "matrix-js-sdk/src/matrix";
import { PollHistory } from "../../../../../../src/components/views/polls/pollHistory/PollHistory";
import {
flushPromises,
getMockClientWithEventEmitter,
makePollEndEvent,
makePollStartEvent,
mockClientMethodsRooms,
mockClientMethodsUser,
mockIntlDateTimeFormat,
setupRoomWithPollEvents,
unmockIntlDateTimeFormat,
} from "../../../../../test-utils";
import { RoomPermalinkCreator } from "../../../../../../src/utils/permalinks/Permalinks";
import defaultDispatcher from "../../../../../../src/dispatcher/dispatcher";
import { Action } from "../../../../../../src/dispatcher/actions";
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
describe("<PollHistory />", () => {
// 14.03.2022 16:15
const now = 1647270879403;
const userId = "@alice:domain.org";
const roomId = "!room:domain.org";
const mockClient = getMockClientWithEventEmitter({
...mockClientMethodsUser(userId),
...mockClientMethodsRooms([]),
relations: jest.fn(),
decryptEventIfNeeded: jest.fn(),
getOrCreateFilter: jest.fn(),
paginateEventTimeline: jest.fn(),
});
let room = new Room(roomId, mockClient, userId);
const expectedFilter = new Filter(userId);
expectedFilter.setDefinition({
room: {
timeline: {
types: [M_POLL_START.name, M_POLL_START.altName],
},
},
});
const defaultProps = {
room,
matrixClient: mockClient,
permalinkCreator: new RoomPermalinkCreator(room),
onFinished: jest.fn(),
};
const getComponent = () =>
render(<PollHistory {...defaultProps} />, {
wrapper: ({ children }) => (
<MatrixClientContext.Provider value={mockClient}>{children}</MatrixClientContext.Provider>
),
});
beforeAll(() => {
mockIntlDateTimeFormat();
});
beforeEach(() => {
room = new Room(roomId, mockClient, userId);
mockClient.getRoom.mockReturnValue(room);
defaultProps.room = room;
mockClient.relations.mockResolvedValue({ events: [] });
const timeline = room.getLiveTimeline();
jest.spyOn(timeline, "getEvents").mockReturnValue([]);
jest.spyOn(defaultDispatcher, "dispatch").mockClear();
defaultProps.onFinished.mockClear();
jest.spyOn(room, "getOrCreateFilteredTimelineSet");
mockClient.getOrCreateFilter.mockResolvedValue(expectedFilter.filterId!);
mockClient.paginateEventTimeline.mockReset().mockResolvedValue(false);
jest.spyOn(Date, "now").mockReturnValue(now);
});
afterAll(() => {
unmockIntlDateTimeFormat();
});
it("throws when room is not found", () => {
mockClient.getRoom.mockReturnValue(null);
expect(() => getComponent()).toThrow("Cannot find room");
});
it("renders a loading message while poll history is fetched", async () => {
const timelineSet = room.getOrCreateFilteredTimelineSet(expectedFilter);
const liveTimeline = timelineSet.getLiveTimeline();
jest.spyOn(liveTimeline, "getPaginationToken").mockReturnValueOnce("test-pagination-token");
const { queryByText, getByText } = getComponent();
expect(mockClient.getOrCreateFilter).toHaveBeenCalledWith(
`POLL_HISTORY_FILTER_${room.roomId}}`,
expectedFilter,
);
// no results not shown until loading finished
expect(queryByText("There are no active polls in this room")).not.toBeInTheDocument();
expect(getByText("Loading polls")).toBeInTheDocument();
// flush filter creation request
await act(flushPromises);
expect(liveTimeline.getPaginationToken).toHaveBeenCalledWith(EventTimeline.BACKWARDS);
expect(mockClient.paginateEventTimeline).toHaveBeenCalledWith(liveTimeline, { backwards: true });
// only one page
expect(mockClient.paginateEventTimeline).toHaveBeenCalledTimes(1);
// finished loading
expect(queryByText("Loading polls")).not.toBeInTheDocument();
expect(getByText("There are no active polls in this room")).toBeInTheDocument();
});
it("fetches poll history until end of timeline is reached while within time limit", async () => {
const timelineSet = room.getOrCreateFilteredTimelineSet(expectedFilter);
const liveTimeline = timelineSet.getLiveTimeline();
// mock three pages of timeline history
jest.spyOn(liveTimeline, "getPaginationToken")
.mockReturnValueOnce("test-pagination-token-1")
.mockReturnValueOnce("test-pagination-token-2")
.mockReturnValueOnce("test-pagination-token-3");
const { queryByText, getByText } = getComponent();
expect(mockClient.getOrCreateFilter).toHaveBeenCalledWith(
`POLL_HISTORY_FILTER_${room.roomId}}`,
expectedFilter,
);
// flush filter creation request
await act(flushPromises);
// once per page
expect(mockClient.paginateEventTimeline).toHaveBeenCalledTimes(3);
// finished loading
expect(queryByText("Loading polls")).not.toBeInTheDocument();
expect(getByText("There are no active polls in this room")).toBeInTheDocument();
});
it("fetches poll history until event older than history period is reached", async () => {
const timelineSet = room.getOrCreateFilteredTimelineSet(expectedFilter);
const liveTimeline = timelineSet.getLiveTimeline();
const thirtyOneDaysAgoTs = now - 60000 * 60 * 24 * 31;
jest.spyOn(liveTimeline, "getEvents")
.mockReturnValueOnce([])
.mockReturnValueOnce([makePollStartEvent("Question?", userId, undefined, { ts: thirtyOneDaysAgoTs })]);
// mock three pages of timeline history
jest.spyOn(liveTimeline, "getPaginationToken")
.mockReturnValueOnce("test-pagination-token-1")
.mockReturnValueOnce("test-pagination-token-2")
.mockReturnValueOnce("test-pagination-token-3");
getComponent();
// flush filter creation request
await flushPromises();
// after first fetch the time limit is reached
// stop paging
expect(mockClient.paginateEventTimeline).toHaveBeenCalledTimes(1);
});
it("renders a no polls message when there are no active polls in the room", async () => {
const { getByText } = getComponent();
await act(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 fourtyDaysAgoTs = now - 60000 * 60 * 24 * 40;
const pollStart = makePollStartEvent("Question?", userId, undefined, { ts: fourtyDaysAgoTs, id: "1" });
jest.spyOn(liveTimeline, "getEvents")
.mockReset()
.mockReturnValueOnce([])
.mockReturnValueOnce([pollStart])
.mockReturnValue(undefined as unknown as MatrixEvent[]);
// mock three pages of timeline history
jest.spyOn(liveTimeline, "getPaginationToken")
.mockReturnValueOnce("test-pagination-token-1")
.mockReturnValueOnce("test-pagination-token-2")
.mockReturnValueOnce("test-pagination-token-3");
const { getByText } = getComponent();
await act(flushPromises);
expect(mockClient.paginateEventTimeline).toHaveBeenCalledTimes(1);
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 act(flushPromises);
// 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 () => {
const { getByText } = getComponent();
await flushPromises();
fireEvent.click(getByText("Past polls"));
expect(getByText("There are no past polls in this room")).toBeTruthy();
});
it("renders a list of active polls when there are polls in the room", async () => {
const timestamp = 1675300825090;
const pollStart1 = makePollStartEvent("Question?", userId, undefined, { ts: timestamp, id: "$1" });
const pollStart2 = makePollStartEvent("Where?", userId, undefined, { ts: timestamp + 10000, id: "$2" });
const pollStart3 = makePollStartEvent("What?", userId, undefined, { ts: timestamp + 70000, id: "$3" });
const pollEnd3 = makePollEndEvent(pollStart3.getId()!, roomId, userId, timestamp + 1);
await setupRoomWithPollEvents([pollStart2, pollStart3, pollStart1], [], [pollEnd3], mockClient, room);
const { container, queryByText, getByTestId } = getComponent();
// flush relations calls for polls
await flushPromises();
expect(getByTestId("filter-tab-PollHistory_filter-ACTIVE").firstElementChild).toBeChecked();
expect(container).toMatchSnapshot();
// this poll is ended, and default filter is ACTIVE
expect(queryByText("What?")).not.toBeInTheDocument();
});
it("updates when new polls are added to the room", async () => {
const timestamp = 1675300825090;
const pollStart1 = makePollStartEvent("Question?", userId, undefined, { ts: timestamp, id: "$1" });
const pollStart2 = makePollStartEvent("Where?", userId, undefined, { ts: timestamp + 10000, id: "$2" });
// initially room has only one poll
await setupRoomWithPollEvents([pollStart1], [], [], mockClient, room);
const { getByText } = getComponent();
// wait for relations
await flushPromises();
expect(getByText("Question?")).toBeInTheDocument();
// add another poll
// paged history requests using cli.paginateEventTimeline
// call this with new events
await room.processPollEvents([pollStart2]);
// await relations for new poll
await flushPromises();
expect(getByText("Question?")).toBeInTheDocument();
// list updated to include new poll
expect(getByText("Where?")).toBeInTheDocument();
});
it("filters ended polls", async () => {
const pollStart1 = makePollStartEvent("Question?", userId, undefined, { ts: 1675300825090, id: "$1" });
const pollStart2 = makePollStartEvent("Where?", userId, undefined, { ts: 1675300725090, id: "$2" });
const pollStart3 = makePollStartEvent("What?", userId, undefined, { ts: 1675200725090, id: "$3" });
const pollEnd3 = makePollEndEvent(pollStart3.getId()!, roomId, userId, 1675200725090 + 1);
await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room);
const { getByText, queryByText, getByTestId } = getComponent();
await flushPromises();
expect(getByText("Question?")).toBeInTheDocument();
expect(getByText("Where?")).toBeInTheDocument();
// this poll is ended, and default filter is ACTIVE
expect(queryByText("What?")).not.toBeInTheDocument();
fireEvent.click(getByText("Past polls"));
expect(getByTestId("filter-tab-PollHistory_filter-ENDED").firstElementChild).toBeChecked();
// active polls no longer shown
expect(queryByText("Question?")).not.toBeInTheDocument();
expect(queryByText("Where?")).not.toBeInTheDocument();
// this poll is ended
expect(getByText("What?")).toBeInTheDocument();
});
describe("Poll detail", () => {
const timestamp = 1675300825090;
const pollStart1 = makePollStartEvent("Question?", userId, undefined, { ts: timestamp, id: "$1" });
const pollStart2 = makePollStartEvent("Where?", userId, undefined, { ts: timestamp + 10000, id: "$2" });
const pollStart3 = makePollStartEvent("What?", userId, undefined, { ts: timestamp + 70000, id: "$3" });
const pollEnd3 = makePollEndEvent(pollStart3.getId()!, roomId, userId, timestamp + 1, "$4");
it("displays poll detail on active poll list item click", async () => {
await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room);
const { getByText, queryByText } = getComponent();
await flushPromises();
fireEvent.click(getByText("Question?"));
expect(queryByText("Polls")).not.toBeInTheDocument();
// elements from MPollBody
expect(getByText("Question?")).toMatchSnapshot();
expect(getByText("Socks")).toBeInTheDocument();
expect(getByText("Shoes")).toBeInTheDocument();
});
it("links to the poll start event from an active poll detail", async () => {
await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room);
const { getByText } = getComponent();
await flushPromises();
fireEvent.click(getByText("Question?"));
// links to poll start event
expect(getByText("View poll in timeline").getAttribute("href")).toBe(
`https://matrix.to/#/!room:domain.org/${pollStart1.getId()!}`,
);
});
it("navigates in app when clicking view in timeline button", async () => {
await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room);
const { getByText } = getComponent();
await flushPromises();
fireEvent.click(getByText("Question?"));
const event = new MouseEvent("click", { bubbles: true, cancelable: true });
jest.spyOn(event, "preventDefault");
fireEvent(getByText("View poll in timeline"), event);
expect(event.preventDefault).toHaveBeenCalled();
expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({
action: Action.ViewRoom,
event_id: pollStart1.getId()!,
highlighted: true,
metricsTrigger: undefined,
room_id: pollStart1.getRoomId()!,
});
// dialog closed
expect(defaultProps.onFinished).toHaveBeenCalled();
});
it("doesnt navigate in app when view in timeline link is ctrl + clicked", async () => {
await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room);
const { getByText } = getComponent();
await flushPromises();
fireEvent.click(getByText("Question?"));
const event = new MouseEvent("click", { bubbles: true, cancelable: true, ctrlKey: true });
jest.spyOn(event, "preventDefault");
fireEvent(getByText("View poll in timeline"), event);
expect(event.preventDefault).not.toHaveBeenCalled();
expect(defaultDispatcher.dispatch).not.toHaveBeenCalled();
expect(defaultProps.onFinished).not.toHaveBeenCalled();
});
it("navigates back to poll list from detail view on header click", async () => {
await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room);
const { getByText, queryByText, getByTestId, container } = getComponent();
await flushPromises();
fireEvent.click(getByText("Question?"));
// detail view
expect(getByText("Question?")).toBeInTheDocument();
// header not shown
expect(queryByText("Polls")).not.toBeInTheDocument();
expect(getByText("Active polls")).toMatchSnapshot();
fireEvent.click(getByText("Active polls"));
// main list header displayed again
expect(getByText("Polls")).toBeInTheDocument();
// active filter still active
expect(getByTestId("filter-tab-PollHistory_filter-ACTIVE").firstElementChild).toBeChecked();
// list displayed
expect(container.getElementsByClassName("mx_PollHistoryList_list").length).toBeTruthy();
});
it("displays poll detail on past poll list item click", async () => {
await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room);
const { getByText } = getComponent();
await flushPromises();
fireEvent.click(getByText("Past polls"));
// pollStart3 is ended
fireEvent.click(getByText("What?"));
expect(getByText("What?")).toMatchSnapshot();
});
it("links to the poll end events from a ended poll detail", async () => {
await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room);
const { getByText } = getComponent();
await flushPromises();
fireEvent.click(getByText("Past polls"));
// pollStart3 is ended
fireEvent.click(getByText("What?"));
// links to poll end event
expect(getByText("View poll in timeline").getAttribute("href")).toBe(
`https://matrix.to/#/!room:domain.org/${pollEnd3.getId()!}`,
);
});
});
});

View file

@ -0,0 +1,54 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2023 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
import React from "react";
import { fireEvent, render } from "jest-matrix-react";
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
import { PollListItem } from "../../../../../../src/components/views/polls/pollHistory/PollListItem";
import { makePollStartEvent, mockIntlDateTimeFormat, unmockIntlDateTimeFormat } from "../../../../../test-utils";
describe("<PollListItem />", () => {
const event = makePollStartEvent("Question?", "@me:domain.org");
event.getContent().origin;
const defaultProps = { event, onClick: jest.fn() };
const getComponent = (props = {}) => render(<PollListItem {...defaultProps} {...props} />);
beforeAll(() => {
// mock default locale to en-GB and set timezone
// so these tests run the same everywhere
mockIntlDateTimeFormat();
});
afterAll(() => {
unmockIntlDateTimeFormat();
});
it("renders a poll", () => {
const { container } = getComponent();
expect(container).toMatchSnapshot();
});
it("renders null when event does not have an extensible poll start event", () => {
const event = new MatrixEvent({
type: "m.room.message",
content: {},
});
const { container } = getComponent({ event });
expect(container.firstElementChild).toBeFalsy();
});
it("calls onClick handler on click", () => {
const onClick = jest.fn();
const { getByText } = getComponent({ onClick });
fireEvent.click(getByText("Question?"));
expect(onClick).toHaveBeenCalled();
});
});

View file

@ -0,0 +1,173 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2023 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
import React from "react";
import { render } from "jest-matrix-react";
import { MatrixEvent, Poll, Room, M_TEXT } from "matrix-js-sdk/src/matrix";
import { PollListItemEnded } from "../../../../../../src/components/views/polls/pollHistory/PollListItemEnded";
import {
flushPromises,
getMockClientWithEventEmitter,
makePollEndEvent,
makePollResponseEvent,
makePollStartEvent,
mockClientMethodsUser,
mockIntlDateTimeFormat,
setupRoomWithPollEvents,
unmockIntlDateTimeFormat,
} from "../../../../../test-utils";
describe("<PollListItemEnded />", () => {
const userId = "@alice:domain.org";
const roomId = "!room:domain.org";
const mockClient = getMockClientWithEventEmitter({
...mockClientMethodsUser(userId),
getRoom: jest.fn(),
relations: jest.fn(),
decryptEventIfNeeded: jest.fn(),
});
const room = new Room(roomId, mockClient, userId);
const timestamp = 1675300825090;
const pollId = "1";
const answerOne = {
id: "answerOneId",
[M_TEXT.name]: "Nissan Silvia S15",
};
const answerTwo = {
id: "answerTwoId",
[M_TEXT.name]: "Mitsubishi Lancer Evolution IX",
};
const pollStartEvent = makePollStartEvent("Question?", userId, [answerOne, answerTwo], {
roomId,
id: pollId,
ts: timestamp,
});
const pollEndEvent = makePollEndEvent(pollId, roomId, userId, timestamp + 60000);
const getComponent = (props: { event: MatrixEvent; poll: Poll }) =>
render(<PollListItemEnded {...props} onClick={jest.fn()} />);
beforeAll(() => {
// mock default locale to en-GB and set timezone
// so these tests run the same everywhere
mockIntlDateTimeFormat();
});
afterAll(() => {
unmockIntlDateTimeFormat();
});
it("renders a poll with no responses", async () => {
await setupRoomWithPollEvents([pollStartEvent], [], [pollEndEvent], mockClient, room);
const poll = room.polls.get(pollId)!;
const { container } = getComponent({ event: pollStartEvent, poll });
expect(container).toMatchSnapshot();
});
it("renders a poll with one winning answer", async () => {
const responses = [
makePollResponseEvent(pollId, [answerOne.id], userId, roomId, timestamp + 1),
makePollResponseEvent(pollId, [answerOne.id], "@bob:domain.org", roomId, timestamp + 1),
makePollResponseEvent(pollId, [answerTwo.id], "@charlie:domain.org", roomId, timestamp + 1),
];
await setupRoomWithPollEvents([pollStartEvent], responses, [pollEndEvent], mockClient, room);
const poll = room.polls.get(pollId)!;
const { getByText } = getComponent({ event: pollStartEvent, poll });
// fetch relations
await flushPromises();
expect(getByText("Final result based on 3 votes")).toBeInTheDocument();
// winning answer
expect(getByText("Nissan Silvia S15")).toBeInTheDocument();
});
it("renders a poll with two winning answers", async () => {
const responses = [
makePollResponseEvent(pollId, [answerOne.id], userId, roomId, timestamp + 1),
makePollResponseEvent(pollId, [answerOne.id], "@han:domain.org", roomId, timestamp + 1),
makePollResponseEvent(pollId, [answerTwo.id], "@sean:domain.org", roomId, timestamp + 1),
makePollResponseEvent(pollId, [answerTwo.id], "@dk:domain.org", roomId, timestamp + 1),
];
await setupRoomWithPollEvents([pollStartEvent], responses, [pollEndEvent], mockClient, room);
const poll = room.polls.get(pollId)!;
const { getByText } = getComponent({ event: pollStartEvent, poll });
// fetch relations
await flushPromises();
expect(getByText("Final result based on 4 votes")).toBeInTheDocument();
// both answers answer
expect(getByText("Nissan Silvia S15")).toBeInTheDocument();
expect(getByText("Mitsubishi Lancer Evolution IX")).toBeInTheDocument();
});
it("counts one unique vote per user", async () => {
const responses = [
makePollResponseEvent(pollId, [answerTwo.id], userId, roomId, timestamp + 1),
makePollResponseEvent(pollId, [answerTwo.id], userId, roomId, timestamp + 1),
makePollResponseEvent(pollId, [answerTwo.id], userId, roomId, timestamp + 1),
makePollResponseEvent(pollId, [answerOne.id], userId, roomId, timestamp + 2),
makePollResponseEvent(pollId, [answerOne.id], "@bob:domain.org", roomId, timestamp + 1),
makePollResponseEvent(pollId, [answerTwo.id], "@charlie:domain.org", roomId, timestamp + 1),
];
await setupRoomWithPollEvents([pollStartEvent], responses, [pollEndEvent], mockClient, room);
const poll = room.polls.get(pollId)!;
const { getByText } = getComponent({ event: pollStartEvent, poll });
// fetch relations
await flushPromises();
// still only 3 unique votes
expect(getByText("Final result based on 3 votes")).toBeInTheDocument();
// only latest vote counted
expect(getByText("Nissan Silvia S15")).toBeInTheDocument();
});
it("excludes malformed responses", async () => {
const responses = [
makePollResponseEvent(pollId, ["bad-answer-id"], userId, roomId, timestamp + 1),
makePollResponseEvent(pollId, [answerOne.id], "@bob:domain.org", roomId, timestamp + 1),
makePollResponseEvent(pollId, [answerTwo.id], "@charlie:domain.org", roomId, timestamp + 1),
];
await setupRoomWithPollEvents([pollStartEvent], responses, [pollEndEvent], mockClient, room);
const poll = room.polls.get(pollId)!;
const { getByText } = getComponent({ event: pollStartEvent, poll });
// fetch relations
await flushPromises();
// invalid vote excluded
expect(getByText("Final result based on 2 votes")).toBeInTheDocument();
});
it("updates on new responses", async () => {
const responses = [
makePollResponseEvent(pollId, [answerOne.id], "@bob:domain.org", roomId, timestamp + 1),
makePollResponseEvent(pollId, [answerTwo.id], "@charlie:domain.org", roomId, timestamp + 1),
];
await setupRoomWithPollEvents([pollStartEvent], responses, [pollEndEvent], mockClient, room);
const poll = room.polls.get(pollId)!;
const { getByText, queryByText, findByText } = getComponent({ event: pollStartEvent, poll });
// fetch relations
await flushPromises();
expect(getByText("Final result based on 2 votes")).toBeInTheDocument();
await room.processPollEvents([
makePollResponseEvent(pollId, [answerOne.id], "@han:domain.org", roomId, timestamp + 1),
]);
// updated with more responses
await expect(findByText("Final result based on 3 votes")).resolves.toBeInTheDocument();
expect(getByText("Nissan Silvia S15")).toBeInTheDocument();
expect(queryByText("Mitsubishi Lancer Evolution IX")).not.toBeInTheDocument();
});
});

View file

@ -0,0 +1,160 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<PollHistory /> Poll detail displays poll detail on active poll list item click 1`] = `
<h2
data-testid="pollQuestion"
>
Question?
</h2>
`;
exports[`<PollHistory /> Poll detail displays poll detail on past poll list item click 1`] = `
<h2
data-testid="pollQuestion"
>
What?
</h2>
`;
exports[`<PollHistory /> Poll detail navigates back to poll list from detail view on header click 1`] = `
<div
class="mx_AccessibleButton mx_PollDetailHeader mx_AccessibleButton_hasKind mx_AccessibleButton_kind_content_inline"
role="button"
tabindex="0"
>
<div
class="mx_PollDetailHeader_icon"
/>
Active polls
</div>
`;
exports[`<PollHistory /> renders a list of active polls when there are polls in the room 1`] = `
<div>
<div
class="mx_PollHistory_content"
>
<h2
class="mx_Heading_h2 mx_PollHistory_header"
>
Polls
</h2>
<div
class="mx_PollHistoryList"
>
<fieldset
class="mx_FilterTabGroup"
>
<label
data-testid="filter-tab-PollHistory_filter-ACTIVE"
>
<input
checked=""
name="PollHistory_filter"
type="radio"
value="ACTIVE"
/>
<span>
Active polls
</span>
</label>
<label
data-testid="filter-tab-PollHistory_filter-ENDED"
>
<input
name="PollHistory_filter"
type="radio"
value="ENDED"
/>
<span>
Past polls
</span>
</label>
</fieldset>
<ol
class="mx_PollHistoryList_list mx_PollHistoryList_list_ACTIVE"
>
<li
class="mx_PollListItem"
data-testid="pollListItem-$2"
>
<span
tabindex="0"
>
<div
aria-labelledby="floating-ui-10"
class="mx_PollListItem_content"
>
<span>
02/02/23
</span>
<div
class="mx_PollListItem_icon"
/>
<span
class="mx_PollListItem_question"
>
Where?
</span>
</div>
</span>
</li>
<li
class="mx_PollListItem"
data-testid="pollListItem-$1"
>
<span
tabindex="0"
>
<div
aria-labelledby="floating-ui-16"
class="mx_PollListItem_content"
>
<span>
02/02/23
</span>
<div
class="mx_PollListItem_icon"
/>
<span
class="mx_PollListItem_question"
>
Question?
</span>
</div>
</span>
</li>
</ol>
</div>
</div>
</div>
`;
exports[`<PollHistory /> 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[`<PollHistory /> 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>
`;

View file

@ -0,0 +1,31 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<PollListItem /> renders a poll 1`] = `
<div>
<li
class="mx_PollListItem"
data-testid="pollListItem-$mypoll"
>
<span
tabindex="0"
>
<div
aria-labelledby="floating-ui-1"
class="mx_PollListItem_content"
>
<span>
01/01/70
</span>
<div
class="mx_PollListItem_icon"
/>
<span
class="mx_PollListItem_question"
>
Question?
</span>
</div>
</span>
</li>
</div>
`;

View file

@ -0,0 +1,46 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<PollListItemEnded /> renders a poll with no responses 1`] = `
<div>
<li
class="mx_PollListItemEnded"
data-testid="pollListItem-1"
>
<span
tabindex="0"
>
<div
aria-labelledby="floating-ui-1"
class="mx_PollListItemEnded_content"
>
<div
class="mx_PollListItemEnded_title"
>
<div
class="mx_PollListItemEnded_icon"
/>
<span
class="mx_PollListItemEnded_question"
>
Question?
</span>
<span
class="mx_Caption"
>
02/02/23
</span>
</div>
<div
class="mx_PollListItemEnded_voteCount"
>
<span
class="mx_Caption"
>
Final result based on 0 votes
</span>
</div>
</div>
</span>
</li>
</div>
`;