{
public render(): JSX.Element {
const { children: content, language } = this.props;
- const highlighted = language ? hljs.highlight(language, content) : hljs.highlightAuto(content);
+ const highlighted = language ? hljs.highlight(content, { language }) : hljs.highlightAuto(content);
return (
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 4da12e366b..54272b871c 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -3452,6 +3452,7 @@
"User menu": "User menu",
"Could not load user profile": "Could not load user profile",
"Decrypted event source": "Decrypted event source",
+ "Decrypted source unavailable": "Decrypted source unavailable",
"Original event source": "Original event source",
"Event ID: %(eventId)s": "Event ID: %(eventId)s",
"Thread root ID: %(threadRootId)s": "Thread root ID: %(threadRootId)s",
diff --git a/test/components/structures/ViewSource-test.tsx b/test/components/structures/ViewSource-test.tsx
new file mode 100644
index 0000000000..a4bc8b1eca
--- /dev/null
+++ b/test/components/structures/ViewSource-test.tsx
@@ -0,0 +1,59 @@
+/*
+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 { render } from "@testing-library/react";
+import { EventType, MatrixEvent } from "matrix-js-sdk/src/matrix";
+import React from "react";
+
+import ViewSource from "../../../src/components/structures/ViewSource";
+import { mkEvent, stubClient } from "../../test-utils/test-utils";
+
+describe("ThreadView", () => {
+ const ROOM_ID = "!roomId:example.org";
+ const SENDER = "@alice:example.org";
+
+ let messageEvent: MatrixEvent;
+
+ const redactionEvent = mkEvent({
+ user: SENDER,
+ event: true,
+ type: EventType.RoomRedaction,
+ content: {},
+ });
+
+ beforeEach(() => {
+ messageEvent = new MatrixEvent({
+ type: EventType.RoomMessageEncrypted,
+ room_id: ROOM_ID,
+ sender: SENDER,
+ content: {},
+ state_key: undefined,
+ });
+ messageEvent.makeRedacted(redactionEvent);
+ });
+
+ beforeEach(stubClient);
+
+ // See https://github.com/vector-im/element-web/issues/24165
+ it("doesn't error when viewing redacted encrypted messages", () => {
+ // Sanity checks
+ expect(messageEvent.isEncrypted()).toBeTruthy();
+ // @ts-ignore clearEvent is private, but it's being used directly
+ expect(messageEvent.clearEvent).toBe(undefined);
+
+ expect(() => render( {}} />)).not.toThrow();
+ });
+});
diff --git a/test/components/views/elements/SyntaxHighlight-test.tsx b/test/components/views/elements/SyntaxHighlight-test.tsx
new file mode 100644
index 0000000000..bdd3e50cf0
--- /dev/null
+++ b/test/components/views/elements/SyntaxHighlight-test.tsx
@@ -0,0 +1,38 @@
+/* eslint @typescript-eslint/no-unused-vars: ["error", { "varsIgnorePattern": "^_" }] */
+/*
+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 { render } from "@testing-library/react";
+import hljs, { type HighlightOptions } from "highlight.js";
+import React from "react";
+
+import SyntaxHighlight from "../../../../src/components/views/elements/SyntaxHighlight";
+
+describe(" ", () => {
+ it("renders", () => {
+ const { container } = render(console.log("Hello, World!"); );
+ expect(container).toMatchSnapshot();
+ });
+
+ it.each(["json", "javascript", "css"])("uses the provided language", (lang) => {
+ const mock = jest.spyOn(hljs, "highlight");
+
+ render(// Hello, World );
+
+ const [_lang, opts] = mock.mock.lastCall!;
+ expect((opts as HighlightOptions)["language"]).toBe(lang);
+ });
+});
diff --git a/test/components/views/elements/__snapshots__/SyntaxHighlight-test.tsx.snap b/test/components/views/elements/__snapshots__/SyntaxHighlight-test.tsx.snap
new file mode 100644
index 0000000000..e7ad9c057b
--- /dev/null
+++ b/test/components/views/elements/__snapshots__/SyntaxHighlight-test.tsx.snap
@@ -0,0 +1,30 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` renders 1`] = `
+
+
+
+
+ console
+
+ .
+
+ log
+
+ (
+
+ "Hello, World!"
+
+ );
+
+
+
+`;
From 0758b8cdfe40a8b2baf4b4b817e24d6ef5cfe837 Mon Sep 17 00:00:00 2001
From: Kerry
Date: Mon, 16 Jan 2023 10:31:07 +1300
Subject: [PATCH 5/6] Device manager - tweak settings display (#9905)
* compound devices icon
* update icon for new session manager tab
* condense privacy > analytics / sessions sections slightly
---
res/css/views/dialogs/_UserSettingsDialog.pcss | 4 ++++
res/img/element-icons/settings/devices.svg | 5 +++++
src/components/views/dialogs/UserSettingsDialog.tsx | 2 +-
.../views/settings/tabs/user/SecurityUserSettingsTab.tsx | 2 --
4 files changed, 10 insertions(+), 3 deletions(-)
create mode 100644 res/img/element-icons/settings/devices.svg
diff --git a/res/css/views/dialogs/_UserSettingsDialog.pcss b/res/css/views/dialogs/_UserSettingsDialog.pcss
index 118c057b83..41d39f8b79 100644
--- a/res/css/views/dialogs/_UserSettingsDialog.pcss
+++ b/res/css/views/dialogs/_UserSettingsDialog.pcss
@@ -49,6 +49,10 @@ limitations under the License.
mask-image: url("$(res)/img/element-icons/security.svg");
}
+.mx_UserSettingsDialog_sessionsIcon::before {
+ mask-image: url("$(res)/img/element-icons/settings/devices.svg");
+}
+
.mx_UserSettingsDialog_helpIcon::before {
mask-image: url("$(res)/img/element-icons/settings/help.svg");
}
diff --git a/res/img/element-icons/settings/devices.svg b/res/img/element-icons/settings/devices.svg
new file mode 100644
index 0000000000..4d2f171993
--- /dev/null
+++ b/res/img/element-icons/settings/devices.svg
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/src/components/views/dialogs/UserSettingsDialog.tsx b/src/components/views/dialogs/UserSettingsDialog.tsx
index a7877072b3..7b33ca58da 100644
--- a/src/components/views/dialogs/UserSettingsDialog.tsx
+++ b/src/components/views/dialogs/UserSettingsDialog.tsx
@@ -164,7 +164,7 @@ export default class UserSettingsDialog extends React.Component
new Tab(
UserTab.SessionManager,
_td("Sessions"),
- "mx_UserSettingsDialog_securityIcon",
+ "mx_UserSettingsDialog_sessionsIcon",
,
// don't track with posthog while under construction
undefined,
diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx
index 018ecf76ae..550b395da5 100644
--- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx
+++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx
@@ -353,8 +353,6 @@ export default class SecurityUserSettingsTab extends React.Component
)}
-
-
{_t("Sessions")}
From 33e8a62daedfdcb85dc588bc4dd9df1d2942a4af Mon Sep 17 00:00:00 2001
From: Kerry
Date: Mon, 16 Jan 2023 14:25:33 +1300
Subject: [PATCH 6/6] convert MPollBody tests into rtl (#9906)
* convert MPollBody tests into rtl
* strict fixes
* more strict
* more semantic assertions
* update types for extensible events changes
---
src/components/views/messages/MPollBody.tsx | 13 +-
.../views/messages/MPollBody-test.tsx | 618 +--
.../__snapshots__/MPollBody-test.tsx.snap | 3575 ++++++-----------
3 files changed, 1616 insertions(+), 2590 deletions(-)
diff --git a/src/components/views/messages/MPollBody.tsx b/src/components/views/messages/MPollBody.tsx
index 85500cfbb2..a9317957c6 100644
--- a/src/components/views/messages/MPollBody.tsx
+++ b/src/components/views/messages/MPollBody.tsx
@@ -448,7 +448,7 @@ export default class MPollBody extends React.Component {
return (
-
+
{poll.question.text}
{editedSpan}
@@ -471,7 +471,12 @@ export default class MPollBody extends React.Component {
const answerPercent = totalVotes === 0 ? 0 : Math.round((100.0 * answerVotes) / totalVotes);
return (
- this.selectOption(answer.id)}>
+
this.selectOption(answer.id)}
+ >
{ended ? (
) : (
@@ -493,7 +498,9 @@ export default class MPollBody extends React.Component {
);
})}
-
{totalText}
+
+ {totalText}
+
);
}
diff --git a/test/components/views/messages/MPollBody-test.tsx b/test/components/views/messages/MPollBody-test.tsx
index 1be993f88e..a6f9b5e11c 100644
--- a/test/components/views/messages/MPollBody-test.tsx
+++ b/test/components/views/messages/MPollBody-test.tsx
@@ -15,8 +15,7 @@ limitations under the License.
*/
import React from "react";
-// eslint-disable-next-line deprecate/import
-import { mount, ReactWrapper } from "enzyme";
+import { fireEvent, render, RenderResult } from "@testing-library/react";
import { MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
import { Relations } from "matrix-js-sdk/src/models/relations";
import { RelatedRelations } from "matrix-js-sdk/src/models/related-relations";
@@ -44,6 +43,8 @@ import { IBodyProps } from "../../../../src/components/views/messages/IBodyProps
import { getMockClientWithEventEmitter } from "../../../test-utils";
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
import MPollBody from "../../../../src/components/views/messages/MPollBody";
+import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks";
+import { MediaEventHelper } from "../../../../src/utils/MediaEventHelper";
const CHECKED = "mx_MPollBody_option_checked";
@@ -85,13 +86,13 @@ describe("MPollBody", () => {
new RelatedRelations([newEndRelations([])]),
),
).toEqual([
- new UserVote(ev1.getTs(), ev1.getSender(), ev1.getContent()[M_POLL_RESPONSE.name].answers),
+ new UserVote(ev1.getTs(), ev1.getSender()!, ev1.getContent()[M_POLL_RESPONSE.name].answers),
new UserVote(
badEvent.getTs(),
- badEvent.getSender(),
+ badEvent.getSender()!,
[], // should be spoiled
),
- new UserVote(ev2.getTs(), ev2.getSender(), ev2.getContent()[M_POLL_RESPONSE.name].answers),
+ new UserVote(ev2.getTs(), ev2.getSender()!, ev2.getContent()[M_POLL_RESPONSE.name].answers),
]);
});
@@ -146,14 +147,14 @@ describe("MPollBody", () => {
});
it("renders no votes if none were made", () => {
- const votes = [];
- const body = newMPollBody(votes);
- expect(votesCount(body, "pizza")).toBe("");
- expect(votesCount(body, "poutine")).toBe("");
- expect(votesCount(body, "italian")).toBe("");
- expect(votesCount(body, "wings")).toBe("");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("No votes cast");
- expect(body.find("h2").html()).toEqual("What should we order for the party? ");
+ const votes: MatrixEvent[] = [];
+ const renderResult = newMPollBody(votes);
+ expect(votesCount(renderResult, "pizza")).toBe("");
+ expect(votesCount(renderResult, "poutine")).toBe("");
+ expect(votesCount(renderResult, "italian")).toBe("");
+ expect(votesCount(renderResult, "wings")).toBe("");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("No votes cast");
+ expect(renderResult.getByText("What should we order for the party?")).toBeTruthy();
});
it("finds votes from multiple people", () => {
@@ -163,12 +164,12 @@ describe("MPollBody", () => {
responseEvent("@catrd:example.com", "poutine"),
responseEvent("@dune2:example.com", "wings"),
];
- const body = newMPollBody(votes);
- expect(votesCount(body, "pizza")).toBe("2 votes");
- expect(votesCount(body, "poutine")).toBe("1 vote");
- expect(votesCount(body, "italian")).toBe("0 votes");
- expect(votesCount(body, "wings")).toBe("1 vote");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Based on 4 votes");
+ const renderResult = newMPollBody(votes);
+ expect(votesCount(renderResult, "pizza")).toBe("2 votes");
+ expect(votesCount(renderResult, "poutine")).toBe("1 vote");
+ expect(votesCount(renderResult, "italian")).toBe("0 votes");
+ expect(votesCount(renderResult, "wings")).toBe("1 vote");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Based on 4 votes");
});
it("ignores end poll events from unauthorised users", () => {
@@ -179,15 +180,15 @@ describe("MPollBody", () => {
responseEvent("@dune2:example.com", "wings"),
];
const ends = [endEvent("@notallowed:example.com", 12)];
- const body = newMPollBody(votes, ends);
+ const renderResult = newMPollBody(votes, ends);
// Even though an end event was sent, we render the poll as unfinished
// because this person is not allowed to send these events
- expect(votesCount(body, "pizza")).toBe("2 votes");
- expect(votesCount(body, "poutine")).toBe("1 vote");
- expect(votesCount(body, "italian")).toBe("0 votes");
- expect(votesCount(body, "wings")).toBe("1 vote");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Based on 4 votes");
+ expect(votesCount(renderResult, "pizza")).toBe("2 votes");
+ expect(votesCount(renderResult, "poutine")).toBe("1 vote");
+ expect(votesCount(renderResult, "italian")).toBe("0 votes");
+ expect(votesCount(renderResult, "wings")).toBe("1 vote");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Based on 4 votes");
});
it("hides scores if I have not voted", () => {
@@ -197,22 +198,22 @@ describe("MPollBody", () => {
responseEvent("@catrd:example.com", "poutine"),
responseEvent("@dune2:example.com", "wings"),
];
- const body = newMPollBody(votes);
- expect(votesCount(body, "pizza")).toBe("");
- expect(votesCount(body, "poutine")).toBe("");
- expect(votesCount(body, "italian")).toBe("");
- expect(votesCount(body, "wings")).toBe("");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("4 votes cast. Vote to see the results");
+ const renderResult = newMPollBody(votes);
+ expect(votesCount(renderResult, "pizza")).toBe("");
+ expect(votesCount(renderResult, "poutine")).toBe("");
+ expect(votesCount(renderResult, "italian")).toBe("");
+ expect(votesCount(renderResult, "wings")).toBe("");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("4 votes cast. Vote to see the results");
});
it("hides a single vote if I have not voted", () => {
const votes = [responseEvent("@alice:example.com", "pizza")];
- const body = newMPollBody(votes);
- expect(votesCount(body, "pizza")).toBe("");
- expect(votesCount(body, "poutine")).toBe("");
- expect(votesCount(body, "italian")).toBe("");
- expect(votesCount(body, "wings")).toBe("");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("1 vote cast. Vote to see the results");
+ const renderResult = newMPollBody(votes);
+ expect(votesCount(renderResult, "pizza")).toBe("");
+ expect(votesCount(renderResult, "poutine")).toBe("");
+ expect(votesCount(renderResult, "italian")).toBe("");
+ expect(votesCount(renderResult, "wings")).toBe("");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("1 vote cast. Vote to see the results");
});
it("takes someone's most recent vote if they voted several times", () => {
@@ -223,12 +224,12 @@ describe("MPollBody", () => {
responseEvent("@qbert:example.com", "poutine", 16), // latest qbert
responseEvent("@qbert:example.com", "wings", 15),
];
- const body = newMPollBody(votes);
- expect(votesCount(body, "pizza")).toBe("0 votes");
- expect(votesCount(body, "poutine")).toBe("1 vote");
- expect(votesCount(body, "italian")).toBe("0 votes");
- expect(votesCount(body, "wings")).toBe("1 vote");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Based on 2 votes");
+ const renderResult = newMPollBody(votes);
+ expect(votesCount(renderResult, "pizza")).toBe("0 votes");
+ expect(votesCount(renderResult, "poutine")).toBe("1 vote");
+ expect(votesCount(renderResult, "italian")).toBe("0 votes");
+ expect(votesCount(renderResult, "wings")).toBe("1 vote");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Based on 2 votes");
});
it("uses my local vote", () => {
@@ -238,18 +239,18 @@ describe("MPollBody", () => {
responseEvent("@fg:example.com", "pizza", 15),
responseEvent("@hi:example.com", "pizza", 15),
];
- const body = newMPollBody(votes);
+ const renderResult = newMPollBody(votes);
// When I vote for Italian
- clickRadio(body, "italian");
+ clickOption(renderResult, "italian");
// My vote is counted
- expect(votesCount(body, "pizza")).toBe("3 votes");
- expect(votesCount(body, "poutine")).toBe("0 votes");
- expect(votesCount(body, "italian")).toBe("1 vote");
- expect(votesCount(body, "wings")).toBe("0 votes");
+ expect(votesCount(renderResult, "pizza")).toBe("3 votes");
+ expect(votesCount(renderResult, "poutine")).toBe("0 votes");
+ expect(votesCount(renderResult, "italian")).toBe("1 vote");
+ expect(votesCount(renderResult, "wings")).toBe("0 votes");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Based on 4 votes");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Based on 4 votes");
});
it("overrides my other votes with my local vote", () => {
@@ -260,53 +261,66 @@ describe("MPollBody", () => {
responseEvent("@me:example.com", "italian", 14),
responseEvent("@nf:example.com", "italian", 15),
];
- const body = newMPollBody(votes);
+ const renderResult = newMPollBody(votes);
// When I click Wings
- clickRadio(body, "wings");
+ clickOption(renderResult, "wings");
// Then my vote is counted for Wings, and not for Italian
- expect(votesCount(body, "pizza")).toBe("0 votes");
- expect(votesCount(body, "poutine")).toBe("0 votes");
- expect(votesCount(body, "italian")).toBe("1 vote");
- expect(votesCount(body, "wings")).toBe("1 vote");
+ expect(votesCount(renderResult, "pizza")).toBe("0 votes");
+ expect(votesCount(renderResult, "poutine")).toBe("0 votes");
+ expect(votesCount(renderResult, "italian")).toBe("1 vote");
+ expect(votesCount(renderResult, "wings")).toBe("1 vote");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Based on 2 votes");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Based on 2 votes");
// And my vote is highlighted
- expect(voteButton(body, "wings").hasClass(CHECKED)).toBe(true);
- expect(voteButton(body, "italian").hasClass(CHECKED)).toBe(false);
+ expect(voteButton(renderResult, "wings").className.includes(CHECKED)).toBe(true);
+ expect(voteButton(renderResult, "italian").className.includes(CHECKED)).toBe(false);
});
it("cancels my local vote if another comes in", () => {
// Given I voted locally
const votes = [responseEvent("@me:example.com", "pizza", 100)];
- const body = newMPollBody(votes);
- const props: IBodyProps = body.instance().props as IBodyProps;
+ const mxEvent = new MatrixEvent({
+ type: M_POLL_START.name,
+ event_id: "$mypoll",
+ room_id: "#myroom:example.com",
+ content: newPollStart(undefined, undefined, true),
+ });
+ const props = getMPollBodyPropsFromEvent(mxEvent, votes);
+ const renderResult = renderMPollBodyWithWrapper(props);
const voteRelations = props!.getRelationsForEvent!("$mypoll", "m.reference", M_POLL_RESPONSE.name);
expect(voteRelations).toBeDefined();
- clickRadio(body, "pizza");
+ clickOption(renderResult, "pizza");
// When a new vote from me comes in
voteRelations!.addEvent(responseEvent("@me:example.com", "wings", 101));
// Then the new vote is counted, not the old one
- expect(votesCount(body, "pizza")).toBe("0 votes");
- expect(votesCount(body, "poutine")).toBe("0 votes");
- expect(votesCount(body, "italian")).toBe("0 votes");
- expect(votesCount(body, "wings")).toBe("1 vote");
+ expect(votesCount(renderResult, "pizza")).toBe("0 votes");
+ expect(votesCount(renderResult, "poutine")).toBe("0 votes");
+ expect(votesCount(renderResult, "italian")).toBe("0 votes");
+ expect(votesCount(renderResult, "wings")).toBe("1 vote");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Based on 1 vote");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Based on 1 vote");
});
it("doesn't cancel my local vote if someone else votes", () => {
// Given I voted locally
const votes = [responseEvent("@me:example.com", "pizza")];
- const body = newMPollBody(votes);
- const props: IBodyProps = body.instance().props as IBodyProps;
+ const mxEvent = new MatrixEvent({
+ type: M_POLL_START.name,
+ event_id: "$mypoll",
+ room_id: "#myroom:example.com",
+ content: newPollStart(undefined, undefined, true),
+ });
+ const props = getMPollBodyPropsFromEvent(mxEvent, votes);
+ const renderResult = renderMPollBodyWithWrapper(props);
+
const voteRelations = props!.getRelationsForEvent!("$mypoll", "m.reference", M_POLL_RESPONSE.name);
expect(voteRelations).toBeDefined();
- clickRadio(body, "pizza");
+ clickOption(renderResult, "pizza");
// When a new vote from someone else comes in
voteRelations!.addEvent(responseEvent("@xx:example.com", "wings", 101));
@@ -315,39 +329,39 @@ describe("MPollBody", () => {
// NOTE: the new event does not affect the counts for other people -
// that is handled through the Relations, not by listening to
// these timeline events.
- expect(votesCount(body, "pizza")).toBe("1 vote");
- expect(votesCount(body, "poutine")).toBe("0 votes");
- expect(votesCount(body, "italian")).toBe("0 votes");
- expect(votesCount(body, "wings")).toBe("1 vote");
+ expect(votesCount(renderResult, "pizza")).toBe("1 vote");
+ expect(votesCount(renderResult, "poutine")).toBe("0 votes");
+ expect(votesCount(renderResult, "italian")).toBe("0 votes");
+ expect(votesCount(renderResult, "wings")).toBe("1 vote");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Based on 2 votes");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Based on 2 votes");
// And my vote is highlighted
- expect(voteButton(body, "pizza").hasClass(CHECKED)).toBe(true);
- expect(voteButton(body, "wings").hasClass(CHECKED)).toBe(false);
+ expect(voteButton(renderResult, "pizza").className.includes(CHECKED)).toBe(true);
+ expect(voteButton(renderResult, "wings").className.includes(CHECKED)).toBe(false);
});
it("highlights my vote even if I did it on another device", () => {
// Given I voted italian
const votes = [responseEvent("@me:example.com", "italian"), responseEvent("@nf:example.com", "wings")];
- const body = newMPollBody(votes);
+ const renderResult = newMPollBody(votes);
// But I didn't click anything locally
// Then my vote is highlighted, and others are not
- expect(voteButton(body, "italian").hasClass(CHECKED)).toBe(true);
- expect(voteButton(body, "wings").hasClass(CHECKED)).toBe(false);
+ expect(voteButton(renderResult, "italian").className.includes(CHECKED)).toBe(true);
+ expect(voteButton(renderResult, "wings").className.includes(CHECKED)).toBe(false);
});
it("ignores extra answers", () => {
// When cb votes for 2 things, we consider the first only
const votes = [responseEvent("@cb:example.com", ["pizza", "wings"]), responseEvent("@me:example.com", "wings")];
- const body = newMPollBody(votes);
- expect(votesCount(body, "pizza")).toBe("1 vote");
- expect(votesCount(body, "poutine")).toBe("0 votes");
- expect(votesCount(body, "italian")).toBe("0 votes");
- expect(votesCount(body, "wings")).toBe("1 vote");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Based on 2 votes");
+ const renderResult = newMPollBody(votes);
+ expect(votesCount(renderResult, "pizza")).toBe("1 vote");
+ expect(votesCount(renderResult, "poutine")).toBe("0 votes");
+ expect(votesCount(renderResult, "italian")).toBe("0 votes");
+ expect(votesCount(renderResult, "wings")).toBe("1 vote");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Based on 2 votes");
});
it("allows un-voting by passing an empty vote", () => {
@@ -356,12 +370,12 @@ describe("MPollBody", () => {
responseEvent("@nc:example.com", [], 13),
responseEvent("@me:example.com", "italian"),
];
- const body = newMPollBody(votes);
- expect(votesCount(body, "pizza")).toBe("0 votes");
- expect(votesCount(body, "poutine")).toBe("0 votes");
- expect(votesCount(body, "italian")).toBe("1 vote");
- expect(votesCount(body, "wings")).toBe("0 votes");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Based on 1 vote");
+ const renderResult = newMPollBody(votes);
+ expect(votesCount(renderResult, "pizza")).toBe("0 votes");
+ expect(votesCount(renderResult, "poutine")).toBe("0 votes");
+ expect(votesCount(renderResult, "italian")).toBe("1 vote");
+ expect(votesCount(renderResult, "wings")).toBe("0 votes");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Based on 1 vote");
});
it("allows re-voting after un-voting", () => {
@@ -371,12 +385,12 @@ describe("MPollBody", () => {
responseEvent("@op:example.com", "italian", 14),
responseEvent("@me:example.com", "italian"),
];
- const body = newMPollBody(votes);
- expect(votesCount(body, "pizza")).toBe("0 votes");
- expect(votesCount(body, "poutine")).toBe("0 votes");
- expect(votesCount(body, "italian")).toBe("2 votes");
- expect(votesCount(body, "wings")).toBe("0 votes");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Based on 2 votes");
+ const renderResult = newMPollBody(votes);
+ expect(votesCount(renderResult, "pizza")).toBe("0 votes");
+ expect(votesCount(renderResult, "poutine")).toBe("0 votes");
+ expect(votesCount(renderResult, "italian")).toBe("2 votes");
+ expect(votesCount(renderResult, "wings")).toBe("0 votes");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Based on 2 votes");
});
it("treats any invalid answer as a spoiled ballot", () => {
@@ -389,12 +403,12 @@ describe("MPollBody", () => {
responseEvent("@uy:example.com", "italian", 14),
responseEvent("@uy:example.com", "doesntexist", 15),
];
- const body = newMPollBody(votes);
- expect(votesCount(body, "pizza")).toBe("0 votes");
- expect(votesCount(body, "poutine")).toBe("0 votes");
- expect(votesCount(body, "italian")).toBe("0 votes");
- expect(votesCount(body, "wings")).toBe("0 votes");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Based on 0 votes");
+ const renderResult = newMPollBody(votes);
+ expect(votesCount(renderResult, "pizza")).toBe("0 votes");
+ expect(votesCount(renderResult, "poutine")).toBe("0 votes");
+ expect(votesCount(renderResult, "italian")).toBe("0 votes");
+ expect(votesCount(renderResult, "wings")).toBe("0 votes");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Based on 0 votes");
});
it("allows re-voting after a spoiled ballot", () => {
@@ -405,31 +419,31 @@ describe("MPollBody", () => {
responseEvent("@uy:example.com", "doesntexist", 15),
responseEvent("@uy:example.com", "poutine", 16),
];
- const body = newMPollBody(votes);
- expect(body.find('input[type="radio"]')).toHaveLength(4);
- expect(votesCount(body, "pizza")).toBe("0 votes");
- expect(votesCount(body, "poutine")).toBe("1 vote");
- expect(votesCount(body, "italian")).toBe("0 votes");
- expect(votesCount(body, "wings")).toBe("0 votes");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Based on 1 vote");
+ const renderResult = newMPollBody(votes);
+ expect(renderResult.container.querySelectorAll('input[type="radio"]')).toHaveLength(4);
+ expect(votesCount(renderResult, "pizza")).toBe("0 votes");
+ expect(votesCount(renderResult, "poutine")).toBe("1 vote");
+ expect(votesCount(renderResult, "italian")).toBe("0 votes");
+ expect(votesCount(renderResult, "wings")).toBe("0 votes");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Based on 1 vote");
});
it("renders nothing if poll has no answers", () => {
- const answers = [];
- const votes = [];
- const ends = [];
- const body = newMPollBody(votes, ends, answers);
- expect(body.html()).toBeNull();
+ const answers: PollAnswer[] = [];
+ const votes: MatrixEvent[] = [];
+ const ends: MatrixEvent[] = [];
+ const { container } = newMPollBody(votes, ends, answers);
+ expect(container.childElementCount).toEqual(0);
});
it("renders the first 20 answers if 21 were given", () => {
const answers = Array.from(Array(21).keys()).map((i) => {
return { id: `id${i}`, [M_TEXT.name]: `Name ${i}` };
});
- const votes = [];
- const ends = [];
- const body = newMPollBody(votes, ends, answers);
- expect(body.find(".mx_MPollBody_option").length).toBe(20);
+ const votes: MatrixEvent[] = [];
+ const ends: MatrixEvent[] = [];
+ const { container } = newMPollBody(votes, ends, answers);
+ expect(container.querySelectorAll(".mx_MPollBody_option").length).toBe(20);
});
it("hides scores if I voted but the poll is undisclosed", () => {
@@ -440,12 +454,12 @@ describe("MPollBody", () => {
responseEvent("@catrd:example.com", "poutine"),
responseEvent("@dune2:example.com", "wings"),
];
- const body = newMPollBody(votes, [], undefined, false);
- expect(votesCount(body, "pizza")).toBe("");
- expect(votesCount(body, "poutine")).toBe("");
- expect(votesCount(body, "italian")).toBe("");
- expect(votesCount(body, "wings")).toBe("");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Results will be visible when the poll is ended");
+ const renderResult = newMPollBody(votes, [], undefined, false);
+ expect(votesCount(renderResult, "pizza")).toBe("");
+ expect(votesCount(renderResult, "poutine")).toBe("");
+ expect(votesCount(renderResult, "italian")).toBe("");
+ expect(votesCount(renderResult, "wings")).toBe("");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Results will be visible when the poll is ended");
});
it("highlights my vote if the poll is undisclosed", () => {
@@ -456,13 +470,13 @@ describe("MPollBody", () => {
responseEvent("@catrd:example.com", "poutine"),
responseEvent("@dune2:example.com", "wings"),
];
- const body = newMPollBody(votes, [], undefined, false);
+ const { container } = newMPollBody(votes, [], undefined, false);
// My vote is marked
- expect(body.find('input[value="pizza"]').prop("checked")).toBeTruthy();
+ expect(container.querySelector('input[value="pizza"]')!).toBeChecked();
// Sanity: other items are not checked
- expect(body.find('input[value="poutine"]').prop("checked")).toBeFalsy();
+ expect(container.querySelector('input[value="poutine"]')!).not.toBeChecked();
});
it("shows scores if the poll is undisclosed but ended", () => {
@@ -474,47 +488,47 @@ describe("MPollBody", () => {
responseEvent("@dune2:example.com", "wings"),
];
const ends = [endEvent("@me:example.com", 12)];
- const body = newMPollBody(votes, ends, undefined, false);
- expect(endedVotesCount(body, "pizza")).toBe("3 votes");
- expect(endedVotesCount(body, "poutine")).toBe("1 vote");
- expect(endedVotesCount(body, "italian")).toBe("0 votes");
- expect(endedVotesCount(body, "wings")).toBe("1 vote");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Final result based on 5 votes");
+ const renderResult = newMPollBody(votes, ends, undefined, false);
+ expect(endedVotesCount(renderResult, "pizza")).toBe("3 votes");
+ expect(endedVotesCount(renderResult, "poutine")).toBe("1 vote");
+ expect(endedVotesCount(renderResult, "italian")).toBe("0 votes");
+ expect(endedVotesCount(renderResult, "wings")).toBe("1 vote");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Final result based on 5 votes");
});
it("sends a vote event when I choose an option", () => {
- const votes = [];
- const body = newMPollBody(votes);
- clickRadio(body, "wings");
+ const votes: MatrixEvent[] = [];
+ const renderResult = newMPollBody(votes);
+ clickOption(renderResult, "wings");
expect(mockClient.sendEvent).toHaveBeenCalledWith(...expectedResponseEventCall("wings"));
});
it("sends only one vote event when I click several times", () => {
- const votes = [];
- const body = newMPollBody(votes);
- clickRadio(body, "wings");
- clickRadio(body, "wings");
- clickRadio(body, "wings");
- clickRadio(body, "wings");
+ const votes: MatrixEvent[] = [];
+ const renderResult = newMPollBody(votes);
+ clickOption(renderResult, "wings");
+ clickOption(renderResult, "wings");
+ clickOption(renderResult, "wings");
+ clickOption(renderResult, "wings");
expect(mockClient.sendEvent).toHaveBeenCalledWith(...expectedResponseEventCall("wings"));
});
it("sends no vote event when I click what I already chose", () => {
const votes = [responseEvent("@me:example.com", "wings")];
- const body = newMPollBody(votes);
- clickRadio(body, "wings");
- clickRadio(body, "wings");
- clickRadio(body, "wings");
- clickRadio(body, "wings");
+ const renderResult = newMPollBody(votes);
+ clickOption(renderResult, "wings");
+ clickOption(renderResult, "wings");
+ clickOption(renderResult, "wings");
+ clickOption(renderResult, "wings");
expect(mockClient.sendEvent).not.toHaveBeenCalled();
});
it("sends several events when I click different options", () => {
- const votes = [];
- const body = newMPollBody(votes);
- clickRadio(body, "wings");
- clickRadio(body, "italian");
- clickRadio(body, "poutine");
+ const votes: MatrixEvent[] = [];
+ const renderResult = newMPollBody(votes);
+ clickOption(renderResult, "wings");
+ clickOption(renderResult, "italian");
+ clickOption(renderResult, "poutine");
expect(mockClient.sendEvent).toHaveBeenCalledTimes(3);
expect(mockClient.sendEvent).toHaveBeenCalledWith(...expectedResponseEventCall("wings"));
expect(mockClient.sendEvent).toHaveBeenCalledWith(...expectedResponseEventCall("italian"));
@@ -524,10 +538,10 @@ describe("MPollBody", () => {
it("sends no events when I click in an ended poll", () => {
const ends = [endEvent("@me:example.com", 25)];
const votes = [responseEvent("@uy:example.com", "wings", 15), responseEvent("@uy:example.com", "poutine", 15)];
- const body = newMPollBody(votes, ends);
- clickEndedOption(body, "wings");
- clickEndedOption(body, "italian");
- clickEndedOption(body, "poutine");
+ const renderResult = newMPollBody(votes, ends);
+ clickOption(renderResult, "wings");
+ clickOption(renderResult, "italian");
+ clickOption(renderResult, "poutine");
expect(mockClient.sendEvent).not.toHaveBeenCalled();
});
@@ -577,9 +591,9 @@ describe("MPollBody", () => {
it("shows non-radio buttons if the poll is ended", () => {
const events = [endEvent()];
- const body = newMPollBody([], events);
- expect(body.find(".mx_StyledRadioButton")).toHaveLength(0);
- expect(body.find('input[type="radio"]')).toHaveLength(0);
+ const { container } = newMPollBody([], events);
+ expect(container.querySelector(".mx_StyledRadioButton")).not.toBeInTheDocument();
+ expect(container.querySelector('input[type="radio"]')).not.toBeInTheDocument();
});
it("counts votes as normal if the poll is ended", () => {
@@ -591,23 +605,23 @@ describe("MPollBody", () => {
responseEvent("@qbert:example.com", "wings", 15),
];
const ends = [endEvent("@me:example.com", 25)];
- const body = newMPollBody(votes, ends);
- expect(endedVotesCount(body, "pizza")).toBe("0 votes");
- expect(endedVotesCount(body, "poutine")).toBe("1 vote");
- expect(endedVotesCount(body, "italian")).toBe("0 votes");
- expect(endedVotesCount(body, "wings")).toBe("1 vote");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Final result based on 2 votes");
+ const renderResult = newMPollBody(votes, ends);
+ expect(endedVotesCount(renderResult, "pizza")).toBe("0 votes");
+ expect(endedVotesCount(renderResult, "poutine")).toBe("1 vote");
+ expect(endedVotesCount(renderResult, "italian")).toBe("0 votes");
+ expect(endedVotesCount(renderResult, "wings")).toBe("1 vote");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Final result based on 2 votes");
});
it("counts a single vote as normal if the poll is ended", () => {
const votes = [responseEvent("@qbert:example.com", "poutine", 16)];
const ends = [endEvent("@me:example.com", 25)];
- const body = newMPollBody(votes, ends);
- expect(endedVotesCount(body, "pizza")).toBe("0 votes");
- expect(endedVotesCount(body, "poutine")).toBe("1 vote");
- expect(endedVotesCount(body, "italian")).toBe("0 votes");
- expect(endedVotesCount(body, "wings")).toBe("0 votes");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Final result based on 1 vote");
+ const renderResult = newMPollBody(votes, ends);
+ expect(endedVotesCount(renderResult, "pizza")).toBe("0 votes");
+ expect(endedVotesCount(renderResult, "poutine")).toBe("1 vote");
+ expect(endedVotesCount(renderResult, "italian")).toBe("0 votes");
+ expect(endedVotesCount(renderResult, "wings")).toBe("0 votes");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Final result based on 1 vote");
});
it("shows ended vote counts of different numbers", () => {
@@ -619,15 +633,15 @@ describe("MPollBody", () => {
responseEvent("@hi:example.com", "pizza", 15),
];
const ends = [endEvent("@me:example.com", 25)];
- const body = newMPollBody(votes, ends);
+ const renderResult = newMPollBody(votes, ends);
- expect(body.find(".mx_StyledRadioButton")).toHaveLength(0);
- expect(body.find('input[type="radio"]')).toHaveLength(0);
- expect(endedVotesCount(body, "pizza")).toBe("2 votes");
- expect(endedVotesCount(body, "poutine")).toBe("0 votes");
- expect(endedVotesCount(body, "italian")).toBe("0 votes");
- expect(endedVotesCount(body, "wings")).toBe("3 votes");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Final result based on 5 votes");
+ expect(renderResult.container.querySelectorAll(".mx_StyledRadioButton")).toHaveLength(0);
+ expect(renderResult.container.querySelectorAll('input[type="radio"]')).toHaveLength(0);
+ expect(endedVotesCount(renderResult, "pizza")).toBe("2 votes");
+ expect(endedVotesCount(renderResult, "poutine")).toBe("0 votes");
+ expect(endedVotesCount(renderResult, "italian")).toBe("0 votes");
+ expect(endedVotesCount(renderResult, "wings")).toBe("3 votes");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Final result based on 5 votes");
});
it("ignores votes that arrived after poll ended", () => {
@@ -641,13 +655,13 @@ describe("MPollBody", () => {
responseEvent("@ld:example.com", "pizza", 15),
];
const ends = [endEvent("@me:example.com", 25)];
- const body = newMPollBody(votes, ends);
+ const renderResult = newMPollBody(votes, ends);
- expect(endedVotesCount(body, "pizza")).toBe("2 votes");
- expect(endedVotesCount(body, "poutine")).toBe("0 votes");
- expect(endedVotesCount(body, "italian")).toBe("0 votes");
- expect(endedVotesCount(body, "wings")).toBe("3 votes");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Final result based on 5 votes");
+ expect(endedVotesCount(renderResult, "pizza")).toBe("2 votes");
+ expect(endedVotesCount(renderResult, "poutine")).toBe("0 votes");
+ expect(endedVotesCount(renderResult, "italian")).toBe("0 votes");
+ expect(endedVotesCount(renderResult, "wings")).toBe("3 votes");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Final result based on 5 votes");
});
it("counts votes that arrived after an unauthorised poll end event", () => {
@@ -664,13 +678,13 @@ describe("MPollBody", () => {
endEvent("@unauthorised:example.com", 5), // Should be ignored
endEvent("@me:example.com", 25),
];
- const body = newMPollBody(votes, ends);
+ const renderResult = newMPollBody(votes, ends);
- expect(endedVotesCount(body, "pizza")).toBe("2 votes");
- expect(endedVotesCount(body, "poutine")).toBe("0 votes");
- expect(endedVotesCount(body, "italian")).toBe("0 votes");
- expect(endedVotesCount(body, "wings")).toBe("3 votes");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Final result based on 5 votes");
+ expect(endedVotesCount(renderResult, "pizza")).toBe("2 votes");
+ expect(endedVotesCount(renderResult, "poutine")).toBe("0 votes");
+ expect(endedVotesCount(renderResult, "italian")).toBe("0 votes");
+ expect(endedVotesCount(renderResult, "wings")).toBe("3 votes");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Final result based on 5 votes");
});
it("ignores votes that arrived after the first end poll event", () => {
@@ -691,13 +705,13 @@ describe("MPollBody", () => {
endEvent("@me:example.com", 25),
endEvent("@me:example.com", 75),
];
- const body = newMPollBody(votes, ends);
+ const renderResult = newMPollBody(votes, ends);
- expect(endedVotesCount(body, "pizza")).toBe("2 votes");
- expect(endedVotesCount(body, "poutine")).toBe("0 votes");
- expect(endedVotesCount(body, "italian")).toBe("0 votes");
- expect(endedVotesCount(body, "wings")).toBe("3 votes");
- expect(body.find(".mx_MPollBody_totalVotes").text()).toBe("Final result based on 5 votes");
+ expect(endedVotesCount(renderResult, "pizza")).toBe("2 votes");
+ expect(endedVotesCount(renderResult, "poutine")).toBe("0 votes");
+ expect(endedVotesCount(renderResult, "italian")).toBe("0 votes");
+ expect(endedVotesCount(renderResult, "wings")).toBe("3 votes");
+ expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("Final result based on 5 votes");
});
it("highlights the winning vote in an ended poll", () => {
@@ -708,15 +722,15 @@ describe("MPollBody", () => {
responseEvent("@xy:example.com", "wings", 15),
];
const ends = [endEvent("@me:example.com", 25)];
- const body = newMPollBody(votes, ends);
+ const renderResult = newMPollBody(votes, ends);
// Then the winner is highlighted
- expect(endedVoteChecked(body, "wings")).toBe(true);
- expect(endedVoteChecked(body, "pizza")).toBe(false);
+ expect(endedVoteChecked(renderResult, "wings")).toBe(true);
+ expect(endedVoteChecked(renderResult, "pizza")).toBe(false);
// Double-check by looking for the endedOptionWinner class
- expect(endedVoteDiv(body, "wings").hasClass("mx_MPollBody_endedOptionWinner")).toBe(true);
- expect(endedVoteDiv(body, "pizza").hasClass("mx_MPollBody_endedOptionWinner")).toBe(false);
+ expect(endedVoteDiv(renderResult, "wings").className.includes("mx_MPollBody_endedOptionWinner")).toBe(true);
+ expect(endedVoteDiv(renderResult, "pizza").className.includes("mx_MPollBody_endedOptionWinner")).toBe(false);
});
it("highlights multiple winning votes", () => {
@@ -726,23 +740,23 @@ describe("MPollBody", () => {
responseEvent("@fg:example.com", "poutine", 15),
];
const ends = [endEvent("@me:example.com", 25)];
- const body = newMPollBody(votes, ends);
+ const renderResult = newMPollBody(votes, ends);
- expect(endedVoteChecked(body, "pizza")).toBe(true);
- expect(endedVoteChecked(body, "wings")).toBe(true);
- expect(endedVoteChecked(body, "poutine")).toBe(true);
- expect(endedVoteChecked(body, "italian")).toBe(false);
- expect(body.find(".mx_MPollBody_option_checked")).toHaveLength(3);
+ expect(endedVoteChecked(renderResult, "pizza")).toBe(true);
+ expect(endedVoteChecked(renderResult, "wings")).toBe(true);
+ expect(endedVoteChecked(renderResult, "poutine")).toBe(true);
+ expect(endedVoteChecked(renderResult, "italian")).toBe(false);
+ expect(renderResult.container.getElementsByClassName("mx_MPollBody_option_checked")).toHaveLength(3);
});
it("highlights nothing if poll has no votes", () => {
const ends = [endEvent("@me:example.com", 25)];
- const body = newMPollBody([], ends);
- expect(body.find(".mx_MPollBody_option_checked")).toHaveLength(0);
+ const renderResult = newMPollBody([], ends);
+ expect(renderResult.container.getElementsByClassName("mx_MPollBody_option_checked")).toHaveLength(0);
});
it("says poll is not ended if there is no end event", () => {
- const ends = [];
+ const ends: MatrixEvent[] = [];
expect(runIsPollEnded(ends)).toBe(false);
});
@@ -810,26 +824,26 @@ describe("MPollBody", () => {
},
});
pollEvent.makeReplaced(replacingEvent);
- const body = newMPollBodyFromEvent(pollEvent, []);
- expect(body.find("h2").html()).toEqual(
- "new question" + ' (edited) ' + " ",
+ const { getByTestId, container } = newMPollBodyFromEvent(pollEvent, []);
+ expect(getByTestId("pollQuestion").innerHTML).toEqual(
+ 'new question (edited) ',
);
- const inputs = body.find('input[type="radio"]');
+ const inputs = container.querySelectorAll('input[type="radio"]');
expect(inputs).toHaveLength(3);
- expect(inputs.at(0).prop("value")).toEqual("n1");
- expect(inputs.at(1).prop("value")).toEqual("n2");
- expect(inputs.at(2).prop("value")).toEqual("n3");
- const options = body.find(".mx_MPollBody_optionText");
+ expect(inputs[0].getAttribute("value")).toEqual("n1");
+ expect(inputs[1].getAttribute("value")).toEqual("n2");
+ expect(inputs[2].getAttribute("value")).toEqual("n3");
+ const options = container.querySelectorAll(".mx_MPollBody_optionText");
expect(options).toHaveLength(3);
- expect(options.at(0).text()).toEqual("new answer 1");
- expect(options.at(1).text()).toEqual("new answer 2");
- expect(options.at(2).text()).toEqual("new answer 3");
+ expect(options[0].innerHTML).toEqual("new answer 1");
+ expect(options[1].innerHTML).toEqual("new answer 2");
+ expect(options[2].innerHTML).toEqual("new answer 3");
});
it("renders a poll with no votes", () => {
- const votes = [];
- const body = newMPollBody(votes);
- expect(body).toMatchSnapshot();
+ const votes: MatrixEvent[] = [];
+ const { container } = newMPollBody(votes);
+ expect(container).toMatchSnapshot();
});
it("renders a poll with only non-local votes", () => {
@@ -840,8 +854,8 @@ describe("MPollBody", () => {
responseEvent("@me:example.com", "wings", 15),
responseEvent("@qr:example.com", "italian", 16),
];
- const body = newMPollBody(votes);
- expect(body).toMatchSnapshot();
+ const { container } = newMPollBody(votes);
+ expect(container).toMatchSnapshot();
});
it("renders a poll with local, non-local and invalid votes", () => {
@@ -853,9 +867,9 @@ describe("MPollBody", () => {
responseEvent("@e:example.com", "wings", 15),
responseEvent("@me:example.com", "italian", 16),
];
- const body = newMPollBody(votes);
- clickRadio(body, "italian");
- expect(body).toMatchSnapshot();
+ const renderResult = newMPollBody(votes);
+ clickOption(renderResult, "italian");
+ expect(renderResult.container).toMatchSnapshot();
});
it("renders a poll that I have not voted in", () => {
@@ -866,14 +880,14 @@ describe("MPollBody", () => {
responseEvent("@yo:example.com", "wings", 15),
responseEvent("@qr:example.com", "italian", 16),
];
- const body = newMPollBody(votes);
- expect(body).toMatchSnapshot();
+ const { container } = newMPollBody(votes);
+ expect(container).toMatchSnapshot();
});
it("renders a finished poll with no votes", () => {
const ends = [endEvent("@me:example.com", 25)];
- const body = newMPollBody([], ends);
- expect(body).toMatchSnapshot();
+ const { container } = newMPollBody([], ends);
+ expect(container).toMatchSnapshot();
});
it("renders a finished poll", () => {
@@ -885,8 +899,8 @@ describe("MPollBody", () => {
responseEvent("@qr:example.com", "italian", 16),
];
const ends = [endEvent("@me:example.com", 25)];
- const body = newMPollBody(votes, ends);
- expect(body).toMatchSnapshot();
+ const { container } = newMPollBody(votes, ends);
+ expect(container).toMatchSnapshot();
});
it("renders a finished poll with multiple winners", () => {
@@ -899,8 +913,8 @@ describe("MPollBody", () => {
responseEvent("@yh:example.com", "poutine", 14),
];
const ends = [endEvent("@me:example.com", 25)];
- const body = newMPollBody(votes, ends);
- expect(body).toMatchSnapshot();
+ const { container } = newMPollBody(votes, ends);
+ expect(container).toMatchSnapshot();
});
it("renders an undisclosed, unfinished poll", () => {
@@ -912,9 +926,9 @@ describe("MPollBody", () => {
responseEvent("@th:example.com", "poutine", 13),
responseEvent("@yh:example.com", "poutine", 14),
];
- const ends = [];
- const body = newMPollBody(votes, ends, undefined, false);
- expect(body.html()).toMatchSnapshot();
+ const ends: MatrixEvent[] = [];
+ const { container } = newMPollBody(votes, ends, undefined, false);
+ expect(container).toMatchSnapshot();
});
it("renders an undisclosed, finished poll", () => {
@@ -927,8 +941,8 @@ describe("MPollBody", () => {
responseEvent("@yh:example.com", "poutine", 14),
];
const ends = [endEvent("@me:example.com", 25)];
- const body = newMPollBody(votes, ends, undefined, false);
- expect(body.html()).toMatchSnapshot();
+ const { container } = newMPollBody(votes, ends, undefined, false);
+ expect(container).toMatchSnapshot();
});
});
@@ -941,7 +955,7 @@ function newEndRelations(relationEvents: Array): Relations {
}
function newRelations(relationEvents: Array, eventType: string): Relations {
- const voteRelations = new Relations("m.reference", eventType, null);
+ const voteRelations = new Relations("m.reference", eventType, mockClient);
for (const ev of relationEvents) {
voteRelations.addEvent(ev);
}
@@ -953,84 +967,88 @@ function newMPollBody(
endEvents: Array = [],
answers?: PollAnswer[],
disclosed = true,
-): ReactWrapper {
+): RenderResult {
const mxEvent = new MatrixEvent({
type: M_POLL_START.name,
event_id: "$mypoll",
room_id: "#myroom:example.com",
- content: newPollStart(answers, null, disclosed),
+ content: newPollStart(answers, undefined, disclosed),
});
return newMPollBodyFromEvent(mxEvent, relationEvents, endEvents);
}
+function getMPollBodyPropsFromEvent(
+ mxEvent: MatrixEvent,
+ relationEvents: Array,
+ endEvents: Array = [],
+): IBodyProps {
+ const voteRelations = newVoteRelations(relationEvents);
+ const endRelations = newEndRelations(endEvents);
+
+ const getRelationsForEvent = (eventId: string, relationType: string, eventType: string) => {
+ expect(eventId).toBe("$mypoll");
+ expect(relationType).toBe("m.reference");
+ if (M_POLL_RESPONSE.matches(eventType)) {
+ return voteRelations;
+ } else if (M_POLL_END.matches(eventType)) {
+ return endRelations;
+ } else {
+ fail("Unexpected eventType: " + eventType);
+ }
+ };
+
+ return {
+ mxEvent,
+ getRelationsForEvent,
+ // We don't use any of these props, but they're required.
+ highlightLink: "unused",
+ highlights: [],
+ mediaEventHelper: {} as unknown as MediaEventHelper,
+ onHeightChanged: () => {},
+ onMessageAllowed: () => {},
+ permalinkCreator: {} as unknown as RoomPermalinkCreator,
+ };
+}
+
+function renderMPollBodyWithWrapper(props: IBodyProps): RenderResult {
+ return render( , {
+ wrapper: ({ children }) => (
+ {children}
+ ),
+ });
+}
+
function newMPollBodyFromEvent(
mxEvent: MatrixEvent,
relationEvents: Array,
endEvents: Array = [],
-): ReactWrapper {
- const voteRelations = newVoteRelations(relationEvents);
- const endRelations = newEndRelations(endEvents);
- return mount(
- {
- expect(eventId).toBe("$mypoll");
- expect(relationType).toBe("m.reference");
- if (M_POLL_RESPONSE.matches(eventType)) {
- return voteRelations;
- } else if (M_POLL_END.matches(eventType)) {
- return endRelations;
- } else {
- fail("Unexpected eventType: " + eventType);
- }
- }}
- // We don't use any of these props, but they're required.
- highlightLink="unused"
- highlights={[]}
- mediaEventHelper={null}
- onHeightChanged={() => {}}
- onMessageAllowed={() => {}}
- permalinkCreator={null}
- />,
- {
- wrappingComponent: MatrixClientContext.Provider,
- wrappingComponentProps: {
- value: mockClient,
- },
- },
- );
+): RenderResult {
+ const props = getMPollBodyPropsFromEvent(mxEvent, relationEvents, endEvents);
+ return renderMPollBodyWithWrapper(props);
}
-function clickRadio(wrapper: ReactWrapper, value: string) {
- const div = wrapper.find(`StyledRadioButton[value="${value}"]`);
- expect(div).toHaveLength(1);
- div.simulate("click");
+function clickOption({ getByTestId }: RenderResult, value: string) {
+ fireEvent.click(getByTestId(`pollOption-${value}`));
}
-function clickEndedOption(wrapper: ReactWrapper, value: string) {
- const div = wrapper.find(`div[data-value="${value}"]`);
- expect(div).toHaveLength(1);
- div.simulate("click");
+function voteButton({ getByTestId }: RenderResult, value: string): Element {
+ return getByTestId(`pollOption-${value}`);
}
-function voteButton(wrapper: ReactWrapper, value: string): ReactWrapper {
- return wrapper.find(`div.mx_MPollBody_option`).findWhere((w) => w.key() === value);
+function votesCount({ getByTestId }: RenderResult, value: string): string {
+ return getByTestId(`pollOption-${value}`).querySelector(".mx_MPollBody_optionVoteCount")!.innerHTML;
}
-function votesCount(wrapper: ReactWrapper, value: string): string {
- return wrapper.find(`StyledRadioButton[value="${value}"] .mx_MPollBody_optionVoteCount`).text();
+function endedVoteChecked({ getByTestId }: RenderResult, value: string): boolean {
+ return getByTestId(`pollOption-${value}`).className.includes("mx_MPollBody_option_checked");
}
-function endedVoteChecked(wrapper: ReactWrapper, value: string): boolean {
- return endedVoteDiv(wrapper, value).closest(".mx_MPollBody_option").hasClass("mx_MPollBody_option_checked");
+function endedVoteDiv({ getByTestId }: RenderResult, value: string): Element {
+ return getByTestId(`pollOption-${value}`).firstElementChild!;
}
-function endedVoteDiv(wrapper: ReactWrapper, value: string): ReactWrapper {
- return wrapper.find(`div[data-value="${value}"]`);
-}
-
-function endedVotesCount(wrapper: ReactWrapper, value: string): string {
- return wrapper.find(`div[data-value="${value}"] .mx_MPollBody_optionVoteCount`).text();
+function endedVotesCount(renderResult: RenderResult, value: string): string {
+ return votesCount(renderResult, value);
}
function newPollStart(answers?: PollAnswer[], question?: string, disclosed = true): PollStartEventContent {
diff --git a/test/components/views/messages/__snapshots__/MPollBody-test.tsx.snap b/test/components/views/messages/__snapshots__/MPollBody-test.tsx.snap
index e4039b82b6..2263527148 100644
--- a/test/components/views/messages/__snapshots__/MPollBody-test.tsx.snap
+++ b/test/components/views/messages/__snapshots__/MPollBody-test.tsx.snap
@@ -1,2626 +1,1627 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`MPollBody renders a finished poll 1`] = `
-
+
-
+
What should we order for the party?
-
+ Pizza
+
+
+ 0 votes
+
+
+
+
+
+
+
+
+
+ Poutine
+
+
+ 0 votes
+
+
+
+
+
+
+
+
+
+ Italian
+
+
+ 2 votes
+
+
+
+
+
+
+
+
+
+ Wings
+
+
+ 1 vote
+
+
+
+
+
+
+
+ Final result based on 3 votes
+
+
+
+`;
+
+exports[`MPollBody renders a finished poll with multiple winners 1`] = `
+
+
+
+ What should we order for the party?
+
+
+
+
+
+
+ Pizza
+
+
+ 2 votes
+
+
+
+
+
+
+
+
+
+ Poutine
+
+
+ 0 votes
+
+
+
+
+
+
+
+
+
+ Italian
+
+
+ 0 votes
+
+
+
+
+
+
+
+
+
+ Wings
+
+
+ 2 votes
+
+
+
+
+
+
+
+ Final result based on 4 votes
+
+
+
+`;
+
+exports[`MPollBody renders a finished poll with no votes 1`] = `
+
+
+
+ What should we order for the party?
+
+
+
+
+
+
+ Pizza
+
+
+ 0 votes
+
+
+
+
+
+
+
+
+
+ Poutine
+
+
+ 0 votes
+
+
+
+
+
+
+
+
+
+ Italian
+
+
+ 0 votes
+
+
+
+
+
+
+
+
+
+ Wings
+
+
+ 0 votes
+
+
+
+
+
+
+
+ Final result based on 0 votes
+
+
+
+`;
+
+exports[`MPollBody renders a poll that I have not voted in 1`] = `
+
+
+
+ What should we order for the party?
+
+
+
+
+
+
+
+
Pizza
- 0 votes
-
+ class="mx_MPollBody_optionVoteCount"
+ />
-
+
+
-
+
+
Poutine
- 0 votes
-
+ class="mx_MPollBody_optionVoteCount"
+ />
-
+
+
-
+
+
Italian
- 2 votes
-
+ class="mx_MPollBody_optionVoteCount"
+ />
-
+
+
+
+
+ 3 votes cast. Vote to see the results
+
+
+
+`;
+
+exports[`MPollBody renders a poll with local, non-local and invalid votes 1`] = `
+
+
+
+ What should we order for the party?
+
+
-
- Final result based on 3 votes
-
-
-
-`;
-
-exports[`MPollBody renders a finished poll with multiple winners 1`] = `
-
-
-
- What should we order for the party?
-
-
-
-
-
-
- Pizza
-
-
- 2 votes
-
-
+
+
-
-
-
-
-
+
+
Italian
- 0 votes
+ 3 votes
-
+
+
- Final result based on 4 votes
-
-
-
-`;
-
-exports[`MPollBody renders a finished poll with no votes 1`] = `
-
-
-
- What should we order for the party?
-
-
-
-
-
-
-
- Pizza
-
-
- 0 votes
-
-
-
-
-
-
-
-
-
-
-
- Poutine
-
-
- 0 votes
-
-
-
-
-
-
-
-
-
-
-
- Italian
-
-
- 0 votes
-
-
-
-
-
-
-
-
-
-
-
- Wings
-
-
- 0 votes
-
-
-
-
-
-
-
-
- Final result based on 0 votes
-
-
-
-`;
-
-exports[`MPollBody renders a poll that I have not voted in 1`] = `
-
-
-
- What should we order for the party?
-
-
-
- 3 votes cast. Vote to see the results
-
-
-
-`;
-
-exports[`MPollBody renders a poll with local, non-local and invalid votes 1`] = `
-
-
-
- What should we order for the party?
-
-
-
-
-
-
-
-
-
-
-
- Pizza
-
-
- 1 vote
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Poutine
-
-
- 0 votes
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Italian
-
-
- 3 votes
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Wings
-
-
- 1 vote
-
-
-
-
-
-
-
-
-
-
-
Based on 5 votes
-
+
`;
exports[`MPollBody renders a poll with no votes 1`] = `
-
+
-
+
What should we order for the party?
+
+
+
+
+
+
No votes cast
-
+
`;
exports[`MPollBody renders a poll with only non-local votes 1`] = `
-
+
-
+
What should we order for the party?
-
-
+
+
-
-
-
-
-
- Pizza
-
-
- 0 votes
-
-
+ Pizza
-
-
-
+ class="mx_MPollBody_optionVoteCount"
+ >
+ 0 votes
+
+
+
+
+
-
-
+
+
-
-
-
-
-
- Poutine
-
-
- 0 votes
-
-
+ Poutine
-
-
-
+ class="mx_MPollBody_optionVoteCount"
+ >
+ 0 votes
+
+
+
+
+
-
-
+
+
-
-
-
-
-
- Italian
-
-
- 2 votes
-
-
+ Italian
-
-
-
+ class="mx_MPollBody_optionVoteCount"
+ >
+ 2 votes
+
+
+
+
+
-
-
+
+
-
-
-
-
-
- Wings
-
-
- 1 vote
-
-
+ Wings
-
-
-
+ class="mx_MPollBody_optionVoteCount"
+ >
+ 1 vote
+
+
+
+
+
Based on 3 votes
-
+
`;
-exports[`MPollBody renders an undisclosed, finished poll 1`] = `"What should we order for the party? Final result based on 4 votes
"`;
+exports[`MPollBody renders an undisclosed, finished poll 1`] = `
+
+
+
+ What should we order for the party?
+
+
+
+
+
+
+ Pizza
+
+
+ 2 votes
+
+
+
+
+
+
+
+
+
+ Poutine
+
+
+ 0 votes
+
+
+
+
+
+
+
+
+
+ Italian
+
+
+ 0 votes
+
+
+
+
+
+
+
+
+
+ Wings
+
+
+ 2 votes
+
+
+
+
+
+
+
+ Final result based on 4 votes
+
+
+
+`;
-exports[`MPollBody renders an undisclosed, unfinished poll 1`] = `"What should we order for the party? Results will be visible when the poll is ended
"`;
+exports[`MPollBody renders an undisclosed, unfinished poll 1`] = `
+
+
+
+ What should we order for the party?
+
+
+
+ Results will be visible when the poll is ended
+
+
+
+`;