Add e2e test for detailed poll results

This commit is contained in:
Tim Vahlbrock 2024-11-16 12:08:48 +01:00
parent e55c9a1a5b
commit ebbdf80cd0
No known key found for this signature in database
2 changed files with 95 additions and 4 deletions

View file

@ -6,11 +6,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details. Please see LICENSE files in the repository root for full details.
*/ */
import { test, expect } from "../../element-web-test"; import type { Locator, Page } from "@playwright/test";
import { Bot } from "../../pages/bot";
import { SettingLevel } from "../../../src/settings/SettingLevel"; import { SettingLevel } from "../../../src/settings/SettingLevel";
import { Layout } from "../../../src/settings/enums/Layout"; import { Layout } from "../../../src/settings/enums/Layout";
import type { Locator, Page } from "@playwright/test"; import { expect, test } from "../../element-web-test";
import { Bot } from "../../pages/bot";
test.describe("Polls", () => { test.describe("Polls", () => {
type CreatePollOptions = { type CreatePollOptions = {
@ -59,6 +59,35 @@ test.describe("Polls", () => {
).toContainText(`${votes} vote`); ).toContainText(`${votes} vote`);
}; };
const getPollResultsDialog = (page: Page): Locator => {
return page.locator(".mx_PollResultsDialog");
};
const getPollResultsDialogOption = (page: Page, optionText: string): Locator => {
return getPollResultsDialog(page)
.locator(".mx_AnswerEntry")
.filter({ hasText: optionText });
};
const expectDetailedPollOptionVoteCount = async (
page: Page,
pollId: string,
optionText: string,
votes: number,
optLocator?: Locator,
): Promise<void> => {
await expect(
getPollResultsDialogOption(page, optionText)
.locator(".mx_AnswerEntry_Header")
.locator(".mx_AnswerEntry_Header_answerName"),
).toContainText(optionText);
await expect(
getPollResultsDialogOption(page, optionText)
.locator(".mx_AnswerEntry_Header")
.locator(".mx_AnswerEntry_Header_voteCount"),
).toContainText(`${votes} vote`);
};
const botVoteForOption = async ( const botVoteForOption = async (
page: Page, page: Page,
bot: Bot, bot: Bot,
@ -219,6 +248,67 @@ test.describe("Polls", () => {
await expect(page.locator(".mx_ErrorDialog")).toBeAttached(); await expect(page.locator(".mx_ErrorDialog")).toBeAttached();
}); });
test("should allow to view detailed results after voting", async ({ page, app, bot, user }) => {
const roomId: string = await app.client.createRoom({});
await app.client.inviteUser(roomId, bot.credentials.userId);
await page.goto("/#/room/" + roomId);
// wait until Bob joined
await expect(page.getByText("BotBob joined the room")).toBeAttached();
const locator = await app.openMessageComposerOptions();
await locator.getByRole("menuitem", { name: "Poll" }).click();
// Disabled because flaky - see https://github.com/vector-im/element-web/issues/24688
//cy.get(".mx_CompoundDialog").percySnapshotElement("Polls Composer");
const pollParams = {
title: "Does the polls feature work?",
options: ["Yes", "No", "Maybe?"],
};
await createPoll(page, pollParams);
// Wait for message to send, get its ID and save as @pollId
const pollId = await page
.locator(".mx_RoomView_body .mx_EventTile[data-scroll-tokens]")
.filter({ hasText: pollParams.title })
.getAttribute("data-scroll-tokens");
await expect(getPollTile(page, pollId)).toMatchScreenshot("Polls_Timeline_tile_no_votes.png", {
mask: [page.locator(".mx_MessageTimestamp")],
});
// Bot votes 'Maybe' in the poll
await botVoteForOption(page, bot, roomId, pollId, pollParams.options[2]);
// no votes shown until I vote, check bots vote has arrived
await expect(
page.locator(".mx_MPollBody_totalVotes").getByText("1 vote cast. Vote to see the results"),
).toBeAttached();
// vote 'Maybe'
await getPollOption(page, pollId, pollParams.options[2]).click();
// both me and bot have voted Maybe
await expectPollOptionVoteCount(page, pollId, pollParams.options[2], 2);
// click the 'vote to see results' message
await page.locator(".mx_MPollBody_totalVotes").getByText("Based on 2 votes. Click here to see full results").click();
// expect the detailed results to be shown
await expect(getPollResultsDialog(page)).toBeAttached();
// expect results to be correctly shown
await expectDetailedPollOptionVoteCount(page, pollId, pollParams.options[2], 2);
const voterEntries = getPollResultsDialogOption(page, pollParams.options[2]).locator(".mx_VoterEntry");
expect((await voterEntries.all()).length).toBe(2);
expect(voterEntries.filter({ hasText: bot.credentials.displayName })).not.toBeNull();
expect(voterEntries.filter({hasText: user.displayName})).not.toBeNull();
// close the dialog
await page.locator(".mx_Dialog").getByRole("button", { name: "Close" }).click();
// expect the dialog to be closed
await expect(getPollResultsDialog(page)).not.toBeAttached();
});
test("should be displayed correctly in thread panel", async ({ page, app, user, bot, homeserver }) => { test("should be displayed correctly in thread panel", async ({ page, app, user, bot, homeserver }) => {
const botCharlie = new Bot(page, homeserver, { displayName: "BotCharlie" }); const botCharlie = new Bot(page, homeserver, { displayName: "BotCharlie" });
await botCharlie.prepareClient(); await botCharlie.prepareClient();

View file

@ -27,6 +27,7 @@ export default function PollResultsDialog(props: IProps): JSX.Element {
<BaseDialog <BaseDialog
title={props.pollEvent.question.text} title={props.pollEvent.question.text}
onFinished={() => Modal.closeCurrentModal()} onFinished={() => Modal.closeCurrentModal()}
className="mx_PollResultsDialog"
> >
{ {
props.pollEvent.answers.map((answer) => { props.pollEvent.answers.map((answer) => {
@ -55,7 +56,7 @@ function AnswerEntry(props: {
<div key={answer.id} className="mx_AnswerEntry"> <div key={answer.id} className="mx_AnswerEntry">
<div className="mx_AnswerEntry_Header"> <div className="mx_AnswerEntry_Header">
<span className="mx_AnswerEntry_Header_answerName">{answer.text}</span> <span className="mx_AnswerEntry_Header_answerName">{answer.text}</span>
<span>{_t("poll|result_dialog|count_of_votes", { count: votes.length })}</span> <span className="mx_AnswerEntry_Header_voteCount">{_t("poll|result_dialog|count_of_votes", { count: votes.length })}</span>
</div> </div>
{votes.length === 0 && <div>No one voted for this.</div>} {votes.length === 0 && <div>No one voted for this.</div>}
{votes.map((vote) => { {votes.map((vote) => {