Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit a53f7f8

Browse files
committed
Merge branch 'develop' of https://github.com/yaya-usman/matrix-react-sdk into favouriteMessages_Panel
2 parents fa57742 + 35ba389 commit a53f7f8

File tree

70 files changed

+2191
-992
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+2191
-992
lines changed

.github/workflows/cypress.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222

2323
- id: prdetails
2424
if: github.event.workflow_run.event == 'pull_request'
25-
uses: matrix-org/pr-details-action@v1.1
25+
uses: matrix-org/pr-details-action@v1.2
2626
with:
2727
owner: ${{ github.event.workflow_run.head_repository.owner.login }}
2828
branch: ${{ github.event.workflow_run.head_branch }}

.github/workflows/netlify.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
Exercise caution. Use test accounts.
2626
2727
- id: prdetails
28-
uses: matrix-org/pr-details-action@v1.1
28+
uses: matrix-org/pr-details-action@v1.2
2929
with:
3030
owner: ${{ github.event.workflow_run.head_repository.owner.login }}
3131
branch: ${{ github.event.workflow_run.head_branch }}

cypress/e2e/12-spotlight/spotlight.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ describe("Spotlight", () => {
139139
const room2Name = "Lounge";
140140
let room2Id: string;
141141

142+
const room3Name = "Public";
143+
let room3Id: string;
144+
142145
beforeEach(() => {
143146
cy.startSynapse("default").then(data => {
144147
synapse = data;
@@ -163,6 +166,19 @@ describe("Spotlight", () => {
163166
room2Id = _room2Id;
164167
bot2.invite(room2Id, bot1.getUserId());
165168
});
169+
bot2.createRoom({
170+
name: room3Name,
171+
visibility: Visibility.Public, initial_state: [{
172+
type: "m.room.history_visibility",
173+
state_key: "",
174+
content: {
175+
history_visibility: "world_readable",
176+
},
177+
}],
178+
}).then(({ room_id: _room3Id }) => {
179+
room3Id = _room3Id;
180+
bot2.invite(room3Id, bot1.getUserId());
181+
});
166182
}),
167183
).then(() =>
168184
cy.get('.mx_RoomSublist_skeletonUI').should('not.exist'),
@@ -212,6 +228,7 @@ describe("Spotlight", () => {
212228
cy.spotlightSearch().clear().type(room1Name);
213229
cy.spotlightResults().should("have.length", 1);
214230
cy.spotlightResults().eq(0).should("contain", room1Name);
231+
cy.spotlightResults().eq(0).should("contain", "View");
215232
cy.spotlightResults().eq(0).click();
216233
cy.url().should("contain", room1Id);
217234
}).then(() => {
@@ -225,6 +242,7 @@ describe("Spotlight", () => {
225242
cy.spotlightSearch().clear().type(room2Name);
226243
cy.spotlightResults().should("have.length", 1);
227244
cy.spotlightResults().eq(0).should("contain", room2Name);
245+
cy.spotlightResults().eq(0).should("contain", "Join");
228246
cy.spotlightResults().eq(0).click();
229247
cy.url().should("contain", room2Id);
230248
}).then(() => {
@@ -233,6 +251,21 @@ describe("Spotlight", () => {
233251
});
234252
});
235253

254+
it("should find unknown public world readable rooms", () => {
255+
cy.openSpotlightDialog().within(() => {
256+
cy.spotlightFilter(Filter.PublicRooms);
257+
cy.spotlightSearch().clear().type(room3Name);
258+
cy.spotlightResults().should("have.length", 1);
259+
cy.spotlightResults().eq(0).should("contain", room3Name);
260+
cy.spotlightResults().eq(0).should("contain", "View");
261+
cy.spotlightResults().eq(0).click();
262+
cy.url().should("contain", room3Id);
263+
}).then(() => {
264+
cy.get(".mx_RoomPreviewBar_actions .mx_AccessibleButton").click();
265+
cy.roomHeaderName().should("contain", room3Name);
266+
});
267+
});
268+
236269
// TODO: We currently can’t test finding rooms on other homeservers/other protocols
237270
// We obviously don’t have federation or bridges in cypress tests
238271
/*

cypress/e2e/15-polls/polls.spec.ts

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
/*
2+
Copyright 2022 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
/// <reference types="cypress" />
18+
19+
import { PollResponseEvent } from "matrix-events-sdk";
20+
21+
import { SynapseInstance } from "../../plugins/synapsedocker";
22+
import { MatrixClient } from "../../global";
23+
import Chainable = Cypress.Chainable;
24+
25+
const hideTimestampCSS = ".mx_MessageTimestamp { visibility: hidden !important; }";
26+
27+
describe("Polls", () => {
28+
let synapse: SynapseInstance;
29+
30+
type CreatePollOptions = {
31+
title: string;
32+
options: string[];
33+
};
34+
const createPoll = ({ title, options }: CreatePollOptions) => {
35+
if (options.length < 2) {
36+
throw new Error('Poll must have at least two options');
37+
}
38+
cy.get('.mx_PollCreateDialog').within((pollCreateDialog) => {
39+
cy.get('#poll-topic-input').type(title);
40+
41+
options.forEach((option, index) => {
42+
const optionId = `#pollcreate_option_${index}`;
43+
44+
// click 'add option' button if needed
45+
if (pollCreateDialog.find(optionId).length === 0) {
46+
cy.get('.mx_PollCreateDialog_addOption').scrollIntoView().click();
47+
}
48+
cy.get(optionId).scrollIntoView().type(option);
49+
});
50+
});
51+
cy.get('.mx_Dialog button[type="submit"]').click();
52+
};
53+
54+
const getPollTile = (pollId: string): Chainable<JQuery> => {
55+
return cy.get(`.mx_EventTile[data-scroll-tokens="${pollId}"]`);
56+
};
57+
58+
const getPollOption = (pollId: string, optionText: string): Chainable<JQuery> => {
59+
return getPollTile(pollId).contains('.mx_MPollBody_option .mx_StyledRadioButton', optionText);
60+
};
61+
62+
const expectPollOptionVoteCount = (pollId: string, optionText: string, votes: number): void => {
63+
getPollOption(pollId, optionText).within(() => {
64+
cy.get('.mx_MPollBody_optionVoteCount').should('contain', `${votes} vote`);
65+
});
66+
};
67+
68+
const botVoteForOption = (bot: MatrixClient, roomId: string, pollId: string, optionText: string): void => {
69+
getPollOption(pollId, optionText).within(ref => {
70+
cy.get('input[type="radio"]').invoke('attr', 'value').then(optionId => {
71+
const pollVote = PollResponseEvent.from([optionId], pollId).serialize();
72+
bot.sendEvent(
73+
roomId,
74+
pollVote.type,
75+
pollVote.content,
76+
);
77+
});
78+
});
79+
};
80+
81+
beforeEach(() => {
82+
cy.enableLabsFeature("feature_thread");
83+
cy.window().then(win => {
84+
win.localStorage.setItem("mx_lhs_size", "0"); // Collapse left panel for these tests
85+
});
86+
cy.startSynapse("default").then(data => {
87+
synapse = data;
88+
89+
cy.initTestUser(synapse, "Tom");
90+
});
91+
});
92+
93+
afterEach(() => {
94+
cy.stopSynapse(synapse);
95+
});
96+
97+
it("Open polls can be created and voted in", () => {
98+
let bot: MatrixClient;
99+
cy.getBot(synapse, { displayName: "BotBob" }).then(_bot => {
100+
bot = _bot;
101+
});
102+
103+
let roomId: string;
104+
cy.createRoom({}).then(_roomId => {
105+
roomId = _roomId;
106+
cy.inviteUser(roomId, bot.getUserId());
107+
cy.visit('/#/room/' + roomId);
108+
});
109+
110+
cy.openMessageComposerOptions().within(() => {
111+
cy.get('[aria-label="Poll"]').click();
112+
});
113+
114+
cy.get('.mx_CompoundDialog').percySnapshotElement('Polls Composer');
115+
116+
const pollParams = {
117+
title: 'Does the polls feature work?',
118+
options: ['Yes', 'No', 'Maybe'],
119+
};
120+
createPoll(pollParams);
121+
122+
// Wait for message to send, get its ID and save as @pollId
123+
cy.get(".mx_RoomView_body .mx_EventTile").contains(".mx_EventTile[data-scroll-tokens]", pollParams.title)
124+
.invoke("attr", "data-scroll-tokens").as("pollId");
125+
126+
cy.get<string>("@pollId").then(pollId => {
127+
getPollTile(pollId).percySnapshotElement('Polls Timeline tile - no votes', { percyCSS: hideTimestampCSS });
128+
129+
// Bot votes 'Maybe' in the poll
130+
botVoteForOption(bot, roomId, pollId, pollParams.options[2]);
131+
132+
// no votes shown until I vote, check bots vote has arrived
133+
cy.get('.mx_MPollBody_totalVotes').should('contain', '1 vote cast');
134+
135+
// vote 'Maybe'
136+
getPollOption(pollId, pollParams.options[2]).click('topLeft');
137+
// both me and bot have voted Maybe
138+
expectPollOptionVoteCount(pollId, pollParams.options[2], 2);
139+
140+
// change my vote to 'Yes'
141+
getPollOption(pollId, pollParams.options[0]).click('topLeft');
142+
143+
// 1 vote for yes
144+
expectPollOptionVoteCount(pollId, pollParams.options[0], 1);
145+
// 1 vote for maybe
146+
expectPollOptionVoteCount(pollId, pollParams.options[2], 1);
147+
148+
// Bot updates vote to 'No'
149+
botVoteForOption(bot, roomId, pollId, pollParams.options[1]);
150+
151+
// 1 vote for yes
152+
expectPollOptionVoteCount(pollId, pollParams.options[0], 1);
153+
// 1 vote for no
154+
expectPollOptionVoteCount(pollId, pollParams.options[0], 1);
155+
// 0 for maybe
156+
expectPollOptionVoteCount(pollId, pollParams.options[2], 0);
157+
});
158+
});
159+
160+
it("displays polls correctly in thread panel", () => {
161+
let botBob: MatrixClient;
162+
let botCharlie: MatrixClient;
163+
cy.getBot(synapse, { displayName: "BotBob" }).then(_bot => {
164+
botBob = _bot;
165+
});
166+
cy.getBot(synapse, { displayName: "BotCharlie" }).then(_bot => {
167+
botCharlie = _bot;
168+
});
169+
170+
let roomId: string;
171+
cy.createRoom({}).then(_roomId => {
172+
roomId = _roomId;
173+
cy.inviteUser(roomId, botBob.getUserId());
174+
cy.inviteUser(roomId, botCharlie.getUserId());
175+
cy.visit('/#/room/' + roomId);
176+
});
177+
178+
cy.openMessageComposerOptions().within(() => {
179+
cy.get('[aria-label="Poll"]').click();
180+
});
181+
182+
const pollParams = {
183+
title: 'Does the polls feature work?',
184+
options: ['Yes', 'No', 'Maybe'],
185+
};
186+
createPoll(pollParams);
187+
188+
// Wait for message to send, get its ID and save as @pollId
189+
cy.get(".mx_RoomView_body .mx_EventTile").contains(".mx_EventTile[data-scroll-tokens]", pollParams.title)
190+
.invoke("attr", "data-scroll-tokens").as("pollId");
191+
192+
cy.get<string>("@pollId").then(pollId => {
193+
// Bob starts thread on the poll
194+
botBob.sendMessage(roomId, pollId, {
195+
body: "Hello there",
196+
msgtype: "m.text",
197+
});
198+
199+
// open the thread summary
200+
cy.get(".mx_RoomView_body .mx_ThreadSummary").click();
201+
202+
// Bob votes 'Maybe' in the poll
203+
botVoteForOption(botBob, roomId, pollId, pollParams.options[2]);
204+
// Charlie votes 'No'
205+
botVoteForOption(botCharlie, roomId, pollId, pollParams.options[1]);
206+
207+
// no votes shown until I vote, check votes have arrived in main tl
208+
cy.get('.mx_RoomView_body .mx_MPollBody_totalVotes').should('contain', '2 votes cast');
209+
// and thread view
210+
cy.get('.mx_ThreadView .mx_MPollBody_totalVotes').should('contain', '2 votes cast');
211+
212+
cy.get('.mx_RoomView_body').within(() => {
213+
// vote 'Maybe' in the main timeline poll
214+
getPollOption(pollId, pollParams.options[2]).click('topLeft');
215+
// both me and bob have voted Maybe
216+
expectPollOptionVoteCount(pollId, pollParams.options[2], 2);
217+
});
218+
219+
cy.get('.mx_ThreadView').within(() => {
220+
// votes updated in thread view too
221+
expectPollOptionVoteCount(pollId, pollParams.options[2], 2);
222+
// change my vote to 'Yes'
223+
getPollOption(pollId, pollParams.options[0]).click('topLeft');
224+
});
225+
226+
// Bob updates vote to 'No'
227+
botVoteForOption(botBob, roomId, pollId, pollParams.options[1]);
228+
229+
// me: yes, bob: no, charlie: no
230+
const expectVoteCounts = () => {
231+
// I voted yes
232+
expectPollOptionVoteCount(pollId, pollParams.options[0], 1);
233+
// Bob and Charlie voted no
234+
expectPollOptionVoteCount(pollId, pollParams.options[1], 2);
235+
// 0 for maybe
236+
expectPollOptionVoteCount(pollId, pollParams.options[2], 0);
237+
};
238+
239+
// check counts are correct in main timeline tile
240+
cy.get('.mx_RoomView_body').within(() => {
241+
expectVoteCounts();
242+
});
243+
// and in thread view tile
244+
cy.get('.mx_ThreadView').within(() => {
245+
expectVoteCounts();
246+
});
247+
});
248+
});
249+
});

0 commit comments

Comments
 (0)