From 2c791eaae0ce288894ad996fcf201212bfd1400b Mon Sep 17 00:00:00 2001 From: Kerry Archibald Date: Thu, 16 Feb 2023 11:13:42 +1300 Subject: [PATCH 01/11] basic navigation to focused poll --- res/css/_components.pcss | 1 + .../dialogs/polls/_PollDetailHeader.pcss | 27 ++++++++++++++ .../views/dialogs/polls/_PollListItem.pcss | 6 +++- .../views/dialogs/polls/PollDetailHeader.tsx | 36 +++++++++++++++++++ .../views/dialogs/polls/PollHistoryDialog.tsx | 21 +++++++++-- .../views/dialogs/polls/PollHistoryList.tsx | 14 ++++++-- .../views/dialogs/polls/PollListItem.tsx | 11 +++--- src/i18n/strings/en_EN.json | 2 ++ .../views/dialogs/polls/PollListItem-test.tsx | 13 +++++-- .../__snapshots__/PollListItem-test.tsx.snap | 25 +++++++------ 10 files changed, 135 insertions(+), 21 deletions(-) create mode 100644 res/css/components/views/dialogs/polls/_PollDetailHeader.pcss create mode 100644 src/components/views/dialogs/polls/PollDetailHeader.tsx diff --git a/res/css/_components.pcss b/res/css/_components.pcss index cda1278df90..88c6f12894f 100644 --- a/res/css/_components.pcss +++ b/res/css/_components.pcss @@ -17,6 +17,7 @@ @import "./components/views/beacon/_ShareLatestLocation.pcss"; @import "./components/views/beacon/_StyledLiveBeaconIcon.pcss"; @import "./components/views/context_menus/_KebabContextMenu.pcss"; +@import "./components/views/dialogs/polls/_PollDetailHeader.pcss"; @import "./components/views/dialogs/polls/_PollListItem.pcss"; @import "./components/views/elements/_FilterDropdown.pcss"; @import "./components/views/elements/_FilterTabGroup.pcss"; diff --git a/res/css/components/views/dialogs/polls/_PollDetailHeader.pcss b/res/css/components/views/dialogs/polls/_PollDetailHeader.pcss new file mode 100644 index 00000000000..6f29b6e08fd --- /dev/null +++ b/res/css/components/views/dialogs/polls/_PollDetailHeader.pcss @@ -0,0 +1,27 @@ +/* +Copyright 2023 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_PollDetailHeader { + // override accessiblebutton style + font-size: $font-15px !important; +} + +.mx_PollDetailHeader_icon { + height: 15px; + width: 15px; + margin-right: $spacing-8; + vertical-align: middle; +} diff --git a/res/css/components/views/dialogs/polls/_PollListItem.pcss b/res/css/components/views/dialogs/polls/_PollListItem.pcss index 7b19e675943..96d85ae582e 100644 --- a/res/css/components/views/dialogs/polls/_PollListItem.pcss +++ b/res/css/components/views/dialogs/polls/_PollListItem.pcss @@ -16,6 +16,10 @@ limitations under the License. .mx_PollListItem { width: 100%; +} + +.mx_PollListItem_link { + width: 100%; display: grid; justify-content: left; align-items: center; @@ -23,7 +27,7 @@ limitations under the License. grid-template-columns: auto auto auto; grid-template-rows: auto; - color: $primary-content; + color: $primary-content !important; } .mx_PollListItem_icon { diff --git a/src/components/views/dialogs/polls/PollDetailHeader.tsx b/src/components/views/dialogs/polls/PollDetailHeader.tsx new file mode 100644 index 00000000000..edabec5b0b9 --- /dev/null +++ b/src/components/views/dialogs/polls/PollDetailHeader.tsx @@ -0,0 +1,36 @@ +/* +Copyright 2023 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from "react"; + +import { Icon as LeftCaretIcon } from "../../../../../res/img/element-icons/caret-left.svg"; +import { _t } from "../../../../languageHandler"; +import AccessibleButton from "../../elements/AccessibleButton"; +import { PollHistoryFilter } from "./types"; + +interface Props { + filter: PollHistoryFilter; + onNavigateBack: () => void; +} + +export const PollDetailHeader: React.FC = ({ filter, onNavigateBack }) => { + return ( + + + {filter === "ACTIVE" ? _t("Active polls") : _t("Past polls")} + + ); +}; diff --git a/src/components/views/dialogs/polls/PollHistoryDialog.tsx b/src/components/views/dialogs/polls/PollHistoryDialog.tsx index e5525fbbaf7..b4ec02d085b 100644 --- a/src/components/views/dialogs/polls/PollHistoryDialog.tsx +++ b/src/components/views/dialogs/polls/PollHistoryDialog.tsx @@ -24,6 +24,7 @@ import { IDialogProps } from "../IDialogProps"; import { PollHistoryList } from "./PollHistoryList"; import { PollHistoryFilter } from "./types"; import { usePolls } from "./usePollHistory"; +import { PollDetailHeader } from "./PollDetailHeader"; type PollHistoryDialogProps = Pick & { roomId: string; @@ -46,15 +47,31 @@ export const PollHistoryDialog: React.FC = ({ roomId, ma const { polls } = usePolls(roomId, matrixClient); const [filter, setFilter] = useState("ACTIVE"); const [pollStartEvents, setPollStartEvents] = useState(filterAndSortPolls(polls, filter)); + const [focusedPollId, setFocusedPollId] = useState(null); useEffect(() => { setPollStartEvents(filterAndSortPolls(polls, filter)); }, [filter, polls]); + const title = focusedPollId ? ( + setFocusedPollId(null)} /> + ) : ( + _t("Polls history") + ); + return ( - +
- + {focusedPollId ? ( +
Focused poll: {focusedPollId}
+ ) : ( + + )}
); diff --git a/src/components/views/dialogs/polls/PollHistoryList.tsx b/src/components/views/dialogs/polls/PollHistoryList.tsx index 7c8714aeac9..2f116a9042d 100644 --- a/src/components/views/dialogs/polls/PollHistoryList.tsx +++ b/src/components/views/dialogs/polls/PollHistoryList.tsx @@ -26,8 +26,14 @@ type PollHistoryListProps = { pollStartEvents: MatrixEvent[]; filter: PollHistoryFilter; onFilterChange: (filter: PollHistoryFilter) => void; + onItemClick: (pollId: string) => void; }; -export const PollHistoryList: React.FC = ({ pollStartEvents, filter, onFilterChange }) => { +export const PollHistoryList: React.FC = ({ + pollStartEvents, + filter, + onFilterChange, + onItemClick, +}) => { return (
@@ -42,7 +48,11 @@ export const PollHistoryList: React.FC = ({ pollStartEvent {!!pollStartEvents.length ? (
    {pollStartEvents.map((pollStartEvent) => ( - + onItemClick(pollStartEvent.getId()!)} + event={pollStartEvent} + /> ))}
) : ( diff --git a/src/components/views/dialogs/polls/PollListItem.tsx b/src/components/views/dialogs/polls/PollListItem.tsx index 49df399bd73..0fc94d85bdc 100644 --- a/src/components/views/dialogs/polls/PollListItem.tsx +++ b/src/components/views/dialogs/polls/PollListItem.tsx @@ -23,9 +23,10 @@ import { formatLocalDateShort } from "../../../../DateUtils"; interface Props { event: MatrixEvent; + onClick: () => void; } -const PollListItem: React.FC = ({ event }) => { +const PollListItem: React.FC = ({ event, onClick }) => { const pollEvent = event.unstableExtensibleEvent as unknown as PollStartEvent; if (!pollEvent) { return null; @@ -33,9 +34,11 @@ const PollListItem: React.FC = ({ event }) => { const formattedDate = formatLocalDateShort(event.getTs()); return (
  • - {formattedDate} - - {pollEvent.question.text} + + {formattedDate} + + {pollEvent.question.text} +
  • ); }; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 8cdb69d5852..2e5db910e41 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -3141,6 +3141,8 @@ "Not a valid Security Key": "Not a valid Security Key", "Access your secure message history and set up secure messaging by entering your Security Key.": "Access your secure message history and set up secure messaging by entering your Security Key.", "If you've forgotten your Security Key you can ": "If you've forgotten your Security Key you can ", + "Active polls": "Active polls", + "Past polls": "Past 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", "Send custom account data event": "Send custom account data event", diff --git a/test/components/views/dialogs/polls/PollListItem-test.tsx b/test/components/views/dialogs/polls/PollListItem-test.tsx index b9e8ffcc749..181ddd71bfb 100644 --- a/test/components/views/dialogs/polls/PollListItem-test.tsx +++ b/test/components/views/dialogs/polls/PollListItem-test.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from "react"; -import { render } from "@testing-library/react"; +import { fireEvent, render } from "@testing-library/react"; import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import PollListItem from "../../../../../src/components/views/dialogs/polls/PollListItem"; @@ -24,7 +24,7 @@ import { makePollStartEvent, mockIntlDateTimeFormat, unmockIntlDateTimeFormat } describe("", () => { const event = makePollStartEvent("Question?", "@me:domain.org"); event.getContent().origin; - const defaultProps = { event }; + const defaultProps = { event, onClick: jest.fn() }; const getComponent = (props = {}) => render(); beforeAll(() => { @@ -50,4 +50,13 @@ describe("", () => { 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(); + }); }); diff --git a/test/components/views/dialogs/polls/__snapshots__/PollListItem-test.tsx.snap b/test/components/views/dialogs/polls/__snapshots__/PollListItem-test.tsx.snap index 00ae9fbd06b..078f07955db 100644 --- a/test/components/views/dialogs/polls/__snapshots__/PollListItem-test.tsx.snap +++ b/test/components/views/dialogs/polls/__snapshots__/PollListItem-test.tsx.snap @@ -6,17 +6,22 @@ exports[` renders a poll 1`] = ` class="mx_PollListItem" data-testid="pollListItem-$mypoll" > - - 01/01/70 - -
    - - Question? - + + 01/01/70 + +
    + + Question? + +
    `; From ca130f093ced0f8af347a95c66ab31390e541743 Mon Sep 17 00:00:00 2001 From: Kerry Archibald Date: Thu, 16 Feb 2023 14:33:51 +1300 Subject: [PATCH 02/11] add tooltip --- .../views/dialogs/polls/_PollListItem.pcss | 5 +++-- .../views/dialogs/polls/PollListItem.tsx | 17 +++++++++++------ src/i18n/strings/en_EN.json | 1 + .../views/dialogs/polls/PollListItem-test.tsx | 2 +- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/res/css/components/views/dialogs/polls/_PollListItem.pcss b/res/css/components/views/dialogs/polls/_PollListItem.pcss index 96d85ae582e..d6036fa3787 100644 --- a/res/css/components/views/dialogs/polls/_PollListItem.pcss +++ b/res/css/components/views/dialogs/polls/_PollListItem.pcss @@ -18,7 +18,7 @@ limitations under the License. width: 100%; } -.mx_PollListItem_link { +.mx_PollListItem_content { width: 100%; display: grid; justify-content: left; @@ -26,8 +26,9 @@ limitations under the License. grid-gap: $spacing-8; grid-template-columns: auto auto auto; grid-template-rows: auto; + cursor: pointer; - color: $primary-content !important; + color: $primary-content; } .mx_PollListItem_icon { diff --git a/src/components/views/dialogs/polls/PollListItem.tsx b/src/components/views/dialogs/polls/PollListItem.tsx index 0fc94d85bdc..a6587f8c192 100644 --- a/src/components/views/dialogs/polls/PollListItem.tsx +++ b/src/components/views/dialogs/polls/PollListItem.tsx @@ -20,6 +20,9 @@ import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import { Icon as PollIcon } from "../../../../../res/img/element-icons/room/composer/poll.svg"; import { formatLocalDateShort } from "../../../../DateUtils"; +import TooltipTarget from "../../elements/TooltipTarget"; +import { _t } from "../../../../languageHandler"; +import { Alignment } from "../../elements/Tooltip"; interface Props { event: MatrixEvent; @@ -33,12 +36,14 @@ const PollListItem: React.FC = ({ event, onClick }) => { } const formattedDate = formatLocalDateShort(event.getTs()); return ( -
  • - - {formattedDate} - - {pollEvent.question.text} - +
  • + +
    + {formattedDate} + + {pollEvent.question.text} +
    +
  • ); }; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 2e5db910e41..4e8891155d6 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -3145,6 +3145,7 @@ "Past polls": "Past 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", + "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", "Event Type": "Event Type", diff --git a/test/components/views/dialogs/polls/PollListItem-test.tsx b/test/components/views/dialogs/polls/PollListItem-test.tsx index 181ddd71bfb..e8156776573 100644 --- a/test/components/views/dialogs/polls/PollListItem-test.tsx +++ b/test/components/views/dialogs/polls/PollListItem-test.tsx @@ -55,7 +55,7 @@ describe("", () => { const onClick = jest.fn(); const { getByText } = getComponent({ onClick }); - fireEvent.click(getByText('Question?')); + fireEvent.click(getByText("Question?")); expect(onClick).toHaveBeenCalled(); }); From 54566984ad2f09725d89b90325ec5142470ce8c4 Mon Sep 17 00:00:00 2001 From: Kerry Archibald Date: Thu, 16 Feb 2023 15:38:20 +1300 Subject: [PATCH 03/11] drill permalinkCreator down to poll history --- .../dialogs/polls/_PollHistoryDialog.pcss | 1 + src/components/structures/RightPanel.tsx | 8 ++- .../views/dialogs/polls/PollHistoryDialog.tsx | 17 ++++-- .../views/right_panel/RoomSummaryCard.tsx | 5 +- src/i18n/strings/en_EN.json | 1 + .../PollHistoryDialog-test.tsx.snap | 52 ++++++++++++------- .../right_panel/RoomSummaryCard-test.tsx | 8 ++- 7 files changed, 67 insertions(+), 25 deletions(-) diff --git a/res/css/views/dialogs/polls/_PollHistoryDialog.pcss b/res/css/views/dialogs/polls/_PollHistoryDialog.pcss index 39a53344ede..bea589bae20 100644 --- a/res/css/views/dialogs/polls/_PollHistoryDialog.pcss +++ b/res/css/views/dialogs/polls/_PollHistoryDialog.pcss @@ -20,4 +20,5 @@ limitations under the License. display: flex; flex-direction: column; + align-items: flex-start; } diff --git a/src/components/structures/RightPanel.tsx b/src/components/structures/RightPanel.tsx index 4f27392e254..3b3b8ca0528 100644 --- a/src/components/structures/RightPanel.tsx +++ b/src/components/structures/RightPanel.tsx @@ -262,7 +262,13 @@ export default class RightPanel extends React.Component { break; case RightPanelPhases.RoomSummary: - card = ; + card = ( + + ); break; case RightPanelPhases.Widget: diff --git a/src/components/views/dialogs/polls/PollHistoryDialog.tsx b/src/components/views/dialogs/polls/PollHistoryDialog.tsx index b4ec02d085b..41ac09b365e 100644 --- a/src/components/views/dialogs/polls/PollHistoryDialog.tsx +++ b/src/components/views/dialogs/polls/PollHistoryDialog.tsx @@ -25,10 +25,13 @@ import { PollHistoryList } from "./PollHistoryList"; import { PollHistoryFilter } from "./types"; import { usePolls } from "./usePollHistory"; import { PollDetailHeader } from "./PollDetailHeader"; +import { PollDetail } from "./PollDetail"; +import { RoomPermalinkCreator } from "../../../../utils/permalinks/Permalinks"; type PollHistoryDialogProps = Pick & { roomId: string; matrixClient: MatrixClient; + permalinkCreator: RoomPermalinkCreator; }; const sortEventsByLatest = (left: MatrixEvent, right: MatrixEvent): number => right.getTs() - left.getTs(); @@ -43,7 +46,12 @@ const filterAndSortPolls = (polls: Map, filter: PollHistoryFilter) .sort(sortEventsByLatest); }; -export const PollHistoryDialog: React.FC = ({ roomId, matrixClient, onFinished }) => { +export const PollHistoryDialog: React.FC = ({ + roomId, + matrixClient, + permalinkCreator, + onFinished, +}) => { const { polls } = usePolls(roomId, matrixClient); const [filter, setFilter] = useState("ACTIVE"); const [pollStartEvents, setPollStartEvents] = useState(filterAndSortPolls(polls, filter)); @@ -53,7 +61,8 @@ export const PollHistoryDialog: React.FC = ({ roomId, ma setPollStartEvents(filterAndSortPolls(polls, filter)); }, [filter, polls]); - const title = focusedPollId ? ( + const focusedPoll = focusedPollId ? polls.get(focusedPollId) : undefined; + const title = focusedPoll ? ( setFocusedPollId(null)} /> ) : ( _t("Polls history") @@ -62,8 +71,8 @@ export const PollHistoryDialog: React.FC = ({ roomId, ma return (
    - {focusedPollId ? ( -
    Focused poll: {focusedPollId}
    + {focusedPoll ? ( + ) : ( { PosthogTrackers.trackInteraction("WebRightPanelRoomInfoSettingsButton", ev); }; -const RoomSummaryCard: React.FC = ({ room, onClose }) => { +const RoomSummaryCard: React.FC = ({ room, permalinkCreator, onClose }) => { const cli = useContext(MatrixClientContext); const onShareRoomClick = (): void => { @@ -287,6 +289,7 @@ const RoomSummaryCard: React.FC = ({ room, onClose }) => { Modal.createDialog(PollHistoryDialog, { roomId: room.roomId, matrixClient: cli, + permalinkCreator, }); }; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 4e8891155d6..1a30080a507 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -3141,6 +3141,7 @@ "Not a valid Security Key": "Not a valid Security Key", "Access your secure message history and set up secure messaging by entering your Security Key.": "Access your secure message history and set up secure messaging by entering your Security Key.", "If you've forgotten your Security Key you can ": "If you've forgotten your Security Key you can ", + "View poll in timeline": "View poll in timeline", "Active polls": "Active polls", "Past polls": "Past polls", "There are no active polls in this room": "There are no active polls in this room", diff --git a/test/components/views/dialogs/polls/__snapshots__/PollHistoryDialog-test.tsx.snap b/test/components/views/dialogs/polls/__snapshots__/PollHistoryDialog-test.tsx.snap index 1672f66fd67..4fbc3b7eeb4 100644 --- a/test/components/views/dialogs/polls/__snapshots__/PollHistoryDialog-test.tsx.snap +++ b/test/components/views/dialogs/polls/__snapshots__/PollHistoryDialog-test.tsx.snap @@ -71,33 +71,49 @@ exports[` renders a list of active polls when there are pol class="mx_PollListItem" data-testid="pollListItem-$2" > - - 02/02/23 -
    - - Where? - +
    + + 02/02/23 + +
    + + Where? + +
    +
  • - - 02/02/23 -
    - - Question? - +
    + + 02/02/23 + +
    + + Question? + +
    +
  • diff --git a/test/components/views/right_panel/RoomSummaryCard-test.tsx b/test/components/views/right_panel/RoomSummaryCard-test.tsx index 7ec61433957..85425080e09 100644 --- a/test/components/views/right_panel/RoomSummaryCard-test.tsx +++ b/test/components/views/right_panel/RoomSummaryCard-test.tsx @@ -30,6 +30,7 @@ import RightPanelStore from "../../../../src/stores/right-panel/RightPanelStore" import { RightPanelPhases } from "../../../../src/stores/right-panel/RightPanelStorePhases"; import { getMockClientWithEventEmitter, mockClientMethodsUser } from "../../../test-utils"; import { PollHistoryDialog } from "../../../../src/components/views/dialogs/polls/PollHistoryDialog"; +import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks"; describe("", () => { const userId = "@alice:domain.org"; @@ -54,6 +55,7 @@ describe("", () => { const defaultProps = { room, onClose: jest.fn(), + permalinkCreator: new RoomPermalinkCreator(room), }; const getComponent = (props = {}) => render(, { @@ -145,7 +147,11 @@ describe("", () => { fireEvent.click(getByText("Polls history")); - expect(modalSpy).toHaveBeenCalledWith(PollHistoryDialog, { roomId, matrixClient: mockClient }); + expect(modalSpy).toHaveBeenCalledWith(PollHistoryDialog, { + roomId, + matrixClient: mockClient, + permalinkCreator: defaultProps.permalinkCreator, + }); }); }); From 2a168a934924c885dd3bb163c844db9216cf501d Mon Sep 17 00:00:00 2001 From: Kerry Archibald Date: Thu, 16 Feb 2023 15:38:32 +1300 Subject: [PATCH 04/11] render poll tile and link to timeline --- .../views/dialogs/polls/PollDetail.tsx | 87 +++++++++++++++++++ .../views/dialogs/polls/PollListItem.tsx | 2 +- .../__snapshots__/PollListItem-test.tsx.snap | 29 ++++--- 3 files changed, 104 insertions(+), 14 deletions(-) create mode 100644 src/components/views/dialogs/polls/PollDetail.tsx diff --git a/src/components/views/dialogs/polls/PollDetail.tsx b/src/components/views/dialogs/polls/PollDetail.tsx new file mode 100644 index 00000000000..ec2c160e6f4 --- /dev/null +++ b/src/components/views/dialogs/polls/PollDetail.tsx @@ -0,0 +1,87 @@ +/* +Copyright 2023 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { Poll } from "matrix-js-sdk/src/matrix"; +import React from "react"; + +import { Icon as LeftCaretIcon } from "../../../../../res/img/element-icons/caret-left.svg"; +import { _t } from "../../../../languageHandler"; +import AccessibleButton from "../../elements/AccessibleButton"; +import MPollBody from "../../messages/MPollBody"; +import { IBodyProps } from "../../messages/IBodyProps"; +import { PollHistoryFilter } from "./types"; +import dispatcher from "../../../../dispatcher/dispatcher"; +import { Action } from "../../../../dispatcher/actions"; +import { ViewRoomPayload } from "../../../../dispatcher/payloads/ViewRoomPayload"; +import { RoomPermalinkCreator } from "../../../../utils/permalinks/Permalinks"; +import { MediaEventHelper } from "../../../../utils/MediaEventHelper"; + +interface Props { + poll: Poll; + requestModalClose: () => void; + permalinkCreator: RoomPermalinkCreator; +} + +const NOOP = () => {}; + +export const PollDetail: React.FC = ({ poll, permalinkCreator, requestModalClose }) => { + // link to end event for ended polls + const eventIdToLinkTo = poll.isEnded ? poll.endEventId! : poll.pollId; + const linkToTimeline = permalinkCreator.forEvent(eventIdToLinkTo); + + const onLinkClick = (e: React.MouseEvent) => { + if (e.ctrlKey || e.metaKey) { + // native behavior for link on ctrl/cmd + click + return; + } + e.preventDefault(); + + dispatcher.dispatch({ + action: Action.ViewRoom, + event_id: eventIdToLinkTo, + highlighted: true, + room_id: poll.roomId, + metricsTrigger: undefined, // room doesn't change + }); + + requestModalClose(); + }; + return ( + <> + +
    + + {_t("View poll in timeline")} + + + ); +}; diff --git a/src/components/views/dialogs/polls/PollListItem.tsx b/src/components/views/dialogs/polls/PollListItem.tsx index a6587f8c192..1a9a4c9d75b 100644 --- a/src/components/views/dialogs/polls/PollListItem.tsx +++ b/src/components/views/dialogs/polls/PollListItem.tsx @@ -38,7 +38,7 @@ const PollListItem: React.FC = ({ event, onClick }) => { return (
  • -
    +
    {formattedDate} {pollEvent.question.text} diff --git a/test/components/views/dialogs/polls/__snapshots__/PollListItem-test.tsx.snap b/test/components/views/dialogs/polls/__snapshots__/PollListItem-test.tsx.snap index 078f07955db..c6ebc5afc98 100644 --- a/test/components/views/dialogs/polls/__snapshots__/PollListItem-test.tsx.snap +++ b/test/components/views/dialogs/polls/__snapshots__/PollListItem-test.tsx.snap @@ -6,22 +6,25 @@ exports[` renders a poll 1`] = ` class="mx_PollListItem" data-testid="pollListItem-$mypoll" > - - - 01/01/70 -
    - - Question? - - + + 01/01/70 + +
    + + Question? + +
    +
  • `; From ac2b24e0957802c47f33586ddbce33798015a320 Mon Sep 17 00:00:00 2001 From: Kerry Archibald Date: Thu, 16 Feb 2023 16:06:59 +1300 Subject: [PATCH 05/11] tidy and lint --- src/components/views/dialogs/polls/PollDetail.tsx | 15 ++++++--------- .../views/dialogs/polls/PollListItem.tsx | 2 +- .../views/right_panel/RoomSummaryCard.tsx | 2 +- .../dialogs/polls/PollHistoryDialog-test.tsx | 2 ++ 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/components/views/dialogs/polls/PollDetail.tsx b/src/components/views/dialogs/polls/PollDetail.tsx index ec2c160e6f4..f09ca9a781f 100644 --- a/src/components/views/dialogs/polls/PollDetail.tsx +++ b/src/components/views/dialogs/polls/PollDetail.tsx @@ -14,20 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Poll } from "matrix-js-sdk/src/matrix"; import React from "react"; +import { Poll } from "matrix-js-sdk/src/matrix"; -import { Icon as LeftCaretIcon } from "../../../../../res/img/element-icons/caret-left.svg"; import { _t } from "../../../../languageHandler"; -import AccessibleButton from "../../elements/AccessibleButton"; -import MPollBody from "../../messages/MPollBody"; -import { IBodyProps } from "../../messages/IBodyProps"; -import { PollHistoryFilter } from "./types"; import dispatcher from "../../../../dispatcher/dispatcher"; import { Action } from "../../../../dispatcher/actions"; import { ViewRoomPayload } from "../../../../dispatcher/payloads/ViewRoomPayload"; import { RoomPermalinkCreator } from "../../../../utils/permalinks/Permalinks"; import { MediaEventHelper } from "../../../../utils/MediaEventHelper"; +import AccessibleButton from "../../elements/AccessibleButton"; +import MPollBody from "../../messages/MPollBody"; interface Props { poll: Poll; @@ -35,20 +32,20 @@ interface Props { permalinkCreator: RoomPermalinkCreator; } -const NOOP = () => {}; +const NOOP = (): void => {}; export const PollDetail: React.FC = ({ poll, permalinkCreator, requestModalClose }) => { // link to end event for ended polls const eventIdToLinkTo = poll.isEnded ? poll.endEventId! : poll.pollId; const linkToTimeline = permalinkCreator.forEvent(eventIdToLinkTo); - const onLinkClick = (e: React.MouseEvent) => { + const onLinkClick = (e: React.MouseEvent): void => { if (e.ctrlKey || e.metaKey) { // native behavior for link on ctrl/cmd + click return; } + // otherwise handle navigation in the app e.preventDefault(); - dispatcher.dispatch({ action: Action.ViewRoom, event_id: eventIdToLinkTo, diff --git a/src/components/views/dialogs/polls/PollListItem.tsx b/src/components/views/dialogs/polls/PollListItem.tsx index 1a9a4c9d75b..d3cf49250ca 100644 --- a/src/components/views/dialogs/polls/PollListItem.tsx +++ b/src/components/views/dialogs/polls/PollListItem.tsx @@ -20,8 +20,8 @@ import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import { Icon as PollIcon } from "../../../../../res/img/element-icons/room/composer/poll.svg"; import { formatLocalDateShort } from "../../../../DateUtils"; -import TooltipTarget from "../../elements/TooltipTarget"; import { _t } from "../../../../languageHandler"; +import TooltipTarget from "../../elements/TooltipTarget"; import { Alignment } from "../../elements/Tooltip"; interface Props { diff --git a/src/components/views/right_panel/RoomSummaryCard.tsx b/src/components/views/right_panel/RoomSummaryCard.tsx index a504162a624..10dbe4672b8 100644 --- a/src/components/views/right_panel/RoomSummaryCard.tsx +++ b/src/components/views/right_panel/RoomSummaryCard.tsx @@ -37,6 +37,7 @@ import WidgetAvatar from "../avatars/WidgetAvatar"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; import WidgetStore, { IApp } from "../../../stores/WidgetStore"; import { E2EStatus } from "../../../utils/ShieldUtils"; +import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks"; import RoomContext from "../../../contexts/RoomContext"; import { UIComponent, UIFeature } from "../../../settings/UIFeature"; import { ChevronFace, ContextMenuTooltipButton, useContextMenu } from "../../structures/ContextMenu"; @@ -52,7 +53,6 @@ import RightPanelStore from "../../../stores/right-panel/RightPanelStore"; import PosthogTrackers from "../../../PosthogTrackers"; import { shouldShowComponent } from "../../../customisations/helpers/UIComponents"; import { PollHistoryDialog } from "../dialogs/polls/PollHistoryDialog"; -import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks"; interface IProps { room: Room; diff --git a/test/components/views/dialogs/polls/PollHistoryDialog-test.tsx b/test/components/views/dialogs/polls/PollHistoryDialog-test.tsx index b02bbb409b1..07caea5e8a8 100644 --- a/test/components/views/dialogs/polls/PollHistoryDialog-test.tsx +++ b/test/components/views/dialogs/polls/PollHistoryDialog-test.tsx @@ -28,6 +28,7 @@ import { setupRoomWithPollEvents, unmockIntlDateTimeFormat, } from "../../../../test-utils"; +import { RoomPermalinkCreator } from "../../../../../src/utils/permalinks/Permalinks"; describe("", () => { const userId = "@alice:domain.org"; @@ -43,6 +44,7 @@ describe("", () => { const defaultProps = { roomId, matrixClient: mockClient, + permalinkCreator: new RoomPermalinkCreator(room), onFinished: jest.fn(), }; const getComponent = () => render(); From 0983ceaf49d00f5d538a0653e73a7689aec3b6e1 Mon Sep 17 00:00:00 2001 From: Kerry Archibald Date: Thu, 16 Feb 2023 16:56:09 +1300 Subject: [PATCH 06/11] unit test poll detail --- .../dialogs/polls/PollHistoryDialog-test.tsx | 157 ++++++++++++++++++ .../PollHistoryDialog-test.tsx.snap | 42 +++++ test/test-utils/poll.ts | 10 +- 3 files changed, 207 insertions(+), 2 deletions(-) diff --git a/test/components/views/dialogs/polls/PollHistoryDialog-test.tsx b/test/components/views/dialogs/polls/PollHistoryDialog-test.tsx index 07caea5e8a8..ea3b521c4ea 100644 --- a/test/components/views/dialogs/polls/PollHistoryDialog-test.tsx +++ b/test/components/views/dialogs/polls/PollHistoryDialog-test.tsx @@ -29,6 +29,8 @@ import { unmockIntlDateTimeFormat, } from "../../../../test-utils"; import { RoomPermalinkCreator } from "../../../../../src/utils/permalinks/Permalinks"; +import defaultDispatcher from "../../../../../src/dispatcher/dispatcher"; +import { Action } from "../../../../../src/dispatcher/actions"; describe("", () => { const userId = "@alice:domain.org"; @@ -58,6 +60,8 @@ describe("", () => { mockClient.relations.mockResolvedValue({ events: [] }); const timeline = room.getLiveTimeline(); jest.spyOn(timeline, "getEvents").mockReturnValue([]); + jest.spyOn(defaultDispatcher, "dispatch").mockClear(); + defaultProps.onFinished.mockClear(); }); afterAll(() => { @@ -124,4 +128,157 @@ describe("", () => { // this poll is ended expect(getByText("What?")).toBeInTheDocument(); }); + + fdescribe("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(); + + fireEvent.click(getByText("Question?")); + + expect(queryByText("Polls history")).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(); + + 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(); + + 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(); + + 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(); + + fireEvent.click(getByText("Question?")); + + // detail view + expect(getByText("Question?")).toBeInTheDocument(); + + // header not shown + expect(queryByText("Polls history")).not.toBeInTheDocument(); + + expect(getByText("Active polls")).toMatchSnapshot(); + fireEvent.click(getByText("Active polls")); + + // main list header displayed again + expect(getByText("Polls history")).toBeInTheDocument(); + // active filter still active + expect(getByTestId("filter-tab-PollHistoryDialog_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(); + + 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(); + + 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()!}`, + ); + }); + + 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(); + + fireEvent.click(getByText("Question?")); + + // detail view + expect(getByText("Question?")).toBeInTheDocument(); + + // header not shown + expect(queryByText("Polls history")).not.toBeInTheDocument(); + + expect(getByText("Active polls")).toMatchSnapshot(); + fireEvent.click(getByText("Active polls")); + + // main list header displayed again + expect(getByText("Polls history")).toBeInTheDocument(); + // active filter still active + expect(getByTestId("filter-tab-PollHistoryDialog_filter-ACTIVE").firstElementChild).toBeChecked(); + // list displayed + expect(container.getElementsByClassName("mx_PollHistoryList_list").length).toBeTruthy(); + }); + }); }); diff --git a/test/components/views/dialogs/polls/__snapshots__/PollHistoryDialog-test.tsx.snap b/test/components/views/dialogs/polls/__snapshots__/PollHistoryDialog-test.tsx.snap index 4fbc3b7eeb4..3a2bd6e511c 100644 --- a/test/components/views/dialogs/polls/__snapshots__/PollHistoryDialog-test.tsx.snap +++ b/test/components/views/dialogs/polls/__snapshots__/PollHistoryDialog-test.tsx.snap @@ -1,5 +1,47 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[` Poll detail displays poll detail on active poll list item click 1`] = ` +

    + Question? +

    +`; + +exports[` Poll detail displays poll detail on past poll list item click 1`] = ` +

    + What? +

    +`; + +exports[` Poll detail navigates back to poll list from detail view on header click 1`] = ` +
    +
    + Active polls +
    +`; + +exports[` Poll detail navigates back to poll list from detail view on header click 2`] = ` +
    +
    + Active polls +
    +`; + exports[` renders a list of active polls when there are polls in the timeline 1`] = `
    { +export const makePollEndEvent = ( + pollStartEventId: string, + roomId: string, + sender: string, + ts = 0, + id?: string, +): MatrixEvent => { return new MatrixEvent({ - event_id: uuid4(), + event_id: id || uuid4(), room_id: roomId, origin_server_ts: ts, type: M_POLL_END.name, From 968807671ae67b48e0ea441b27d47c99f64cd194 Mon Sep 17 00:00:00 2001 From: Kerry Archibald Date: Tue, 21 Feb 2023 10:08:17 +1300 Subject: [PATCH 07/11] add view poll link to ended pollliste item --- .../dialogs/polls/_PollListItemEnded.pcss | 5 + .../dialogs/polls/_PollHistoryDialog.pcss | 1 - .../views/dialogs/polls/PollDetail.tsx | 20 ++- .../views/dialogs/polls/PollHistoryList.tsx | 1 + .../views/dialogs/polls/PollListItemEnded.tsx | 57 +++--- .../dialogs/polls/PollHistoryDialog-test.tsx | 10 +- .../dialogs/polls/PollListItemEnded-test.tsx | 3 +- .../PollHistoryDialog-test.tsx.snap | 170 ++++++++++++++++++ .../PollListItemEnded-test.tsx.snap | 50 +++--- 9 files changed, 259 insertions(+), 58 deletions(-) create mode 100644 test/components/views/dialogs/polls/__snapshots__/PollHistoryDialog-test.tsx.snap diff --git a/res/css/components/views/dialogs/polls/_PollListItemEnded.pcss b/res/css/components/views/dialogs/polls/_PollListItemEnded.pcss index 6518052ab61..16ea5dcce07 100644 --- a/res/css/components/views/dialogs/polls/_PollListItemEnded.pcss +++ b/res/css/components/views/dialogs/polls/_PollListItemEnded.pcss @@ -16,9 +16,14 @@ limitations under the License. .mx_PollListItemEnded { width: 100%; +} + +.mx_PollListItemEnded_content { + width: 100%; display: flex; flex-direction: column; color: $primary-content; + cursor: pointer; } .mx_PollListItemEnded_title { diff --git a/res/css/views/dialogs/polls/_PollHistoryDialog.pcss b/res/css/views/dialogs/polls/_PollHistoryDialog.pcss index bea589bae20..39a53344ede 100644 --- a/res/css/views/dialogs/polls/_PollHistoryDialog.pcss +++ b/res/css/views/dialogs/polls/_PollHistoryDialog.pcss @@ -20,5 +20,4 @@ limitations under the License. display: flex; flex-direction: column; - align-items: flex-start; } diff --git a/src/components/views/dialogs/polls/PollDetail.tsx b/src/components/views/dialogs/polls/PollDetail.tsx index f09ca9a781f..59e123f27ec 100644 --- a/src/components/views/dialogs/polls/PollDetail.tsx +++ b/src/components/views/dialogs/polls/PollDetail.tsx @@ -70,15 +70,17 @@ export const PollDetail: React.FC = ({ poll, permalinkCreator, requestMod mediaEventHelper={{} as unknown as MediaEventHelper} />
    - - {_t("View poll in timeline")} - +
    + + {_t("View poll in timeline")} + +
    ); }; diff --git a/src/components/views/dialogs/polls/PollHistoryList.tsx b/src/components/views/dialogs/polls/PollHistoryList.tsx index 33797770c2d..d3b0cae5048 100644 --- a/src/components/views/dialogs/polls/PollHistoryList.tsx +++ b/src/components/views/dialogs/polls/PollHistoryList.tsx @@ -77,6 +77,7 @@ export const PollHistoryList: React.FC = ({ key={pollStartEvent.getId()!} event={pollStartEvent} poll={polls.get(pollStartEvent.getId()!)!} + onClick={() => onItemClick(pollStartEvent.getId()!)} /> ), )} diff --git a/src/components/views/dialogs/polls/PollListItemEnded.tsx b/src/components/views/dialogs/polls/PollListItemEnded.tsx index 8a6b2c9595f..c78dd19d52d 100644 --- a/src/components/views/dialogs/polls/PollListItemEnded.tsx +++ b/src/components/views/dialogs/polls/PollListItemEnded.tsx @@ -25,10 +25,13 @@ import { formatLocalDateShort } from "../../../../DateUtils"; import { allVotes, collectUserVotes, countVotes } from "../../messages/MPollBody"; import { PollOption } from "../../polls/PollOption"; import { Caption } from "../../typography/Caption"; +import TooltipTarget from "../../elements/TooltipTarget"; +import { Alignment } from "../../elements/Tooltip"; interface Props { event: MatrixEvent; poll: Poll; + onClick: () => void; } type EndedPollState = { @@ -88,7 +91,7 @@ const usePollVotes = (poll: Poll): Partial => { * @param event - the poll start MatrixEvent * @param poll - Poll instance */ -export const PollListItemEnded: React.FC = ({ event, poll }) => { +export const PollListItemEnded: React.FC = ({ event, poll, onClick }) => { const pollEvent = poll.pollEvent; const { winningAnswers, totalVoteCount } = usePollVotes(poll); if (!pollEvent) { @@ -97,31 +100,35 @@ export const PollListItemEnded: React.FC = ({ event, poll }) => { const formattedDate = formatLocalDateShort(event.getTs()); return ( -
  • -
    - - {pollEvent.question.text} - {formattedDate} -
    - {!!winningAnswers?.length && ( -
    - {winningAnswers?.map(({ answer, voteCount }) => ( - - ))} +
  • + +
    +
    + + {pollEvent.question.text} + {formattedDate} +
    + {!!winningAnswers?.length && ( +
    + {winningAnswers?.map(({ answer, voteCount }) => ( + + ))} +
    + )} +
    + {_t("Final result based on %(count)s votes", { count: totalVoteCount })} +
    - )} -
    - {_t("Final result based on %(count)s votes", { count: totalVoteCount })} -
    +
  • ); }; diff --git a/test/components/views/dialogs/polls/PollHistoryDialog-test.tsx b/test/components/views/dialogs/polls/PollHistoryDialog-test.tsx index 623fa84d487..3b585ecfb0e 100644 --- a/test/components/views/dialogs/polls/PollHistoryDialog-test.tsx +++ b/test/components/views/dialogs/polls/PollHistoryDialog-test.tsx @@ -321,7 +321,7 @@ describe("", () => { expect(getByText("What?")).toBeInTheDocument(); }); - fdescribe("Poll detail", () => { + 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" }); @@ -332,6 +332,7 @@ describe("", () => { await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room); const { getByText, queryByText } = getComponent(); + await flushPromises(); fireEvent.click(getByText("Question?")); @@ -346,6 +347,7 @@ describe("", () => { await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room); const { getByText } = getComponent(); + await flushPromises(); fireEvent.click(getByText("Question?")); @@ -359,6 +361,7 @@ describe("", () => { await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room); const { getByText } = getComponent(); + await flushPromises(); fireEvent.click(getByText("Question?")); @@ -384,6 +387,7 @@ describe("", () => { await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room); const { getByText } = getComponent(); + await flushPromises(); fireEvent.click(getByText("Question?")); @@ -400,6 +404,7 @@ describe("", () => { await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room); const { getByText, queryByText, getByTestId, container } = getComponent(); + await flushPromises(); fireEvent.click(getByText("Question?")); @@ -424,6 +429,7 @@ describe("", () => { await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room); const { getByText } = getComponent(); + await flushPromises(); fireEvent.click(getByText("Past polls")); @@ -437,6 +443,7 @@ describe("", () => { await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room); const { getByText } = getComponent(); + await flushPromises(); fireEvent.click(getByText("Past polls")); @@ -453,6 +460,7 @@ describe("", () => { await setupRoomWithPollEvents([pollStart1, pollStart2, pollStart3], [], [pollEnd3], mockClient, room); const { getByText, queryByText, getByTestId, container } = getComponent(); + await flushPromises(); fireEvent.click(getByText("Question?")); diff --git a/test/components/views/dialogs/polls/PollListItemEnded-test.tsx b/test/components/views/dialogs/polls/PollListItemEnded-test.tsx index c58de7c5209..b14982d2cdd 100644 --- a/test/components/views/dialogs/polls/PollListItemEnded-test.tsx +++ b/test/components/views/dialogs/polls/PollListItemEnded-test.tsx @@ -60,7 +60,8 @@ describe("", () => { }); const pollEndEvent = makePollEndEvent(pollId, roomId, userId, timestamp + 60000); - const getComponent = (props: { event: MatrixEvent; poll: Poll }) => render(); + const getComponent = (props: { event: MatrixEvent; poll: Poll }) => + render(); beforeAll(() => { // mock default locale to en-GB and set timezone diff --git a/test/components/views/dialogs/polls/__snapshots__/PollHistoryDialog-test.tsx.snap b/test/components/views/dialogs/polls/__snapshots__/PollHistoryDialog-test.tsx.snap new file mode 100644 index 00000000000..76c76484fb3 --- /dev/null +++ b/test/components/views/dialogs/polls/__snapshots__/PollHistoryDialog-test.tsx.snap @@ -0,0 +1,170 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` Poll detail displays poll detail on active poll list item click 1`] = ` +

    + Question? +

    +`; + +exports[` Poll detail displays poll detail on past poll list item click 1`] = ` +

    + What? +

    +`; + +exports[` Poll detail navigates back to poll list from detail view on header click 1`] = ` +
    +
    + Active polls +
    +`; + +exports[` Poll detail navigates back to poll list from detail view on header click 2`] = ` +
    +
    + Active polls +
    +`; + +exports[` renders a list of active polls when there are polls in the room 1`] = ` +
    +
    +