element-web/cypress/integration/6-spaces/spaces.spec.ts
Michael Telatynski f3f14afbbf
Move spaces tests from Puppeteer to Cypress (#8645)
* Move spaces tests from Puppeteer to Cypress

* Add missing fixture

* Tweak synapsedocker to not double error on a docker failure

* Fix space hierarchy loading race condition

Fixes https://github.com/matrix-org/element-web-rageshakes/issues/10345

* Fix race condition when creating public space with url update code

* Try Electron once more due to perms issues around clipboard

* Try set browser permissions properly

* Try to enable clipboard another way

* Try electron again

* Try electron again again

* Switch to built-in cypress feature for file uploads

* Mock clipboard instead

* TMPDIR ftw?

* uid:gid pls

* Clipboard tests can now run on any browser due to mocking

* Test Enter as well as button for space creation

* Make the test actually work

* Update cypress/support/util.ts

Co-authored-by: Eric Eastwood <erice@element.io>

Co-authored-by: Eric Eastwood <erice@element.io>
2022-05-26 10:19:00 +01:00

244 lines
9.4 KiB
TypeScript

/*
Copyright 2022 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.
*/
/// <reference types="cypress" />
import type { MatrixClient } from "matrix-js-sdk/src/client";
import type { ICreateRoomOpts } from "matrix-js-sdk/src/@types/requests";
import { SynapseInstance } from "../../plugins/synapsedocker";
import Chainable = Cypress.Chainable;
import { UserCredentials } from "../../support/login";
function openSpaceCreateMenu(): Chainable<JQuery> {
cy.get(".mx_SpaceButton_new").click();
return cy.get(".mx_SpaceCreateMenu_wrapper .mx_ContextualMenu");
}
function getSpacePanelButton(spaceName: string): Chainable<JQuery> {
return cy.get(`.mx_SpaceButton[aria-label="${spaceName}"]`);
}
function openSpaceContextMenu(spaceName: string): Chainable<JQuery> {
getSpacePanelButton(spaceName).rightclick();
return cy.get(".mx_SpacePanel_contextMenu");
}
function spaceCreateOptions(spaceName: string): ICreateRoomOpts {
return {
creation_content: {
type: "m.space",
},
initial_state: [{
type: "m.room.name",
content: {
name: spaceName,
},
}],
};
}
function spaceChildInitialState(roomId: string): ICreateRoomOpts["initial_state"]["0"] {
return {
type: "m.space.child",
state_key: roomId,
content: {
via: [roomId.split(":")[1]],
},
};
}
describe("Spaces", () => {
let synapse: SynapseInstance;
let user: UserCredentials;
beforeEach(() => {
cy.startSynapse("default").then(data => {
synapse = data;
cy.initTestUser(synapse, "Sue").then(_user => {
user = _user;
cy.mockClipboard();
});
});
});
afterEach(() => {
cy.stopSynapse(synapse);
});
it("should allow user to create public space", () => {
openSpaceCreateMenu().within(() => {
cy.get(".mx_SpaceCreateMenuType_public").click();
cy.get('.mx_SpaceBasicSettings_avatarContainer input[type="file"]')
.selectFile("cypress/fixtures/riot.png", { force: true });
cy.get('input[label="Name"]').type("Let's have a Riot");
cy.get('input[label="Address"]').should("have.value", "lets-have-a-riot");
cy.get('textarea[label="Description"]').type("This is a space to reminisce Riot.im!");
cy.get(".mx_AccessibleButton").contains("Create").click();
});
// Create the default General & Random rooms, as well as a custom "Jokes" room
cy.get('input[label="Room name"][value="General"]').should("exist");
cy.get('input[label="Room name"][value="Random"]').should("exist");
cy.get('input[placeholder="Support"]').type("Jokes");
cy.get(".mx_AccessibleButton").contains("Continue").click();
// Copy matrix.to link
cy.get(".mx_SpacePublicShare_shareButton").focus().realClick();
cy.getClipboardText().should("eq", "https://matrix.to/#/#lets-have-a-riot:localhost");
// Go to space home
cy.get(".mx_AccessibleButton").contains("Go to my first room").click();
// Assert rooms exist in the room list
cy.get(".mx_RoomTile").contains("General").should("exist");
cy.get(".mx_RoomTile").contains("Random").should("exist");
cy.get(".mx_RoomTile").contains("Jokes").should("exist");
});
it("should allow user to create private space", () => {
openSpaceCreateMenu().within(() => {
cy.get(".mx_SpaceCreateMenuType_private").click();
cy.get('.mx_SpaceBasicSettings_avatarContainer input[type="file"]')
.selectFile("cypress/fixtures/riot.png", { force: true });
cy.get('input[label="Name"]').type("This is not a Riot");
cy.get('input[label="Address"]').should("not.exist");
cy.get('textarea[label="Description"]').type("This is a private space of mourning Riot.im...");
cy.get(".mx_AccessibleButton").contains("Create").click();
});
cy.get(".mx_SpaceRoomView_privateScope_meAndMyTeammatesButton").click();
// Create the default General & Random rooms, as well as a custom "Projects" room
cy.get('input[label="Room name"][value="General"]').should("exist");
cy.get('input[label="Room name"][value="Random"]').should("exist");
cy.get('input[placeholder="Support"]').type("Projects");
cy.get(".mx_AccessibleButton").contains("Continue").click();
cy.get(".mx_SpaceRoomView").should("contain", "Invite your teammates");
cy.get(".mx_AccessibleButton").contains("Skip for now").click();
// Assert rooms exist in the room list
cy.get(".mx_RoomTile").contains("General").should("exist");
cy.get(".mx_RoomTile").contains("Random").should("exist");
cy.get(".mx_RoomTile").contains("Projects").should("exist");
// Assert rooms exist in the space explorer
cy.get(".mx_SpaceHierarchy_roomTile").contains("General").should("exist");
cy.get(".mx_SpaceHierarchy_roomTile").contains("Random").should("exist");
cy.get(".mx_SpaceHierarchy_roomTile").contains("Projects").should("exist");
});
it("should allow user to create just-me space", () => {
cy.createRoom({
name: "Sample Room",
});
openSpaceCreateMenu().within(() => {
cy.get(".mx_SpaceCreateMenuType_private").click();
cy.get('.mx_SpaceBasicSettings_avatarContainer input[type="file"]')
.selectFile("cypress/fixtures/riot.png", { force: true });
cy.get('input[label="Address"]').should("not.exist");
cy.get('textarea[label="Description"]').type("This is a personal space to mourn Riot.im...");
cy.get('input[label="Name"]').type("This is my Riot{enter}");
});
cy.get(".mx_SpaceRoomView_privateScope_justMeButton").click();
cy.get(".mx_AddExistingToSpace_entry").click();
cy.get(".mx_AccessibleButton").contains("Add").click();
cy.get(".mx_RoomTile").contains("Sample Room").should("exist");
cy.get(".mx_SpaceHierarchy_roomTile").contains("Sample Room").should("exist");
});
it("should allow user to invite another to a space", () => {
let bot: MatrixClient;
cy.getBot(synapse, "BotBob").then(_bot => {
bot = _bot;
});
cy.createSpace({
visibility: "public" as any,
room_alias_name: "space",
}).as("spaceId");
openSpaceContextMenu("#space:localhost").within(() => {
cy.get('.mx_SpacePanel_contextMenu_inviteButton[aria-label="Invite"]').click();
});
cy.get(".mx_SpacePublicShare").within(() => {
// Copy link first
cy.get(".mx_SpacePublicShare_shareButton").focus().realClick();
cy.getClipboardText().should("eq", "https://matrix.to/#/#space:localhost");
// Start Matrix invite flow
cy.get(".mx_SpacePublicShare_inviteButton").click();
});
cy.get(".mx_InviteDialog_other").within(() => {
cy.get('input[type="text"]').type(bot.getUserId());
cy.get(".mx_AccessibleButton").contains("Invite").click();
});
cy.get(".mx_InviteDialog_other").should("not.exist");
});
it("should show space invites at the top of the space panel", () => {
cy.createSpace({
name: "My Space",
});
getSpacePanelButton("My Space").should("exist");
cy.getBot(synapse, "BotBob").then({ timeout: 10000 }, async bot => {
const { room_id: roomId } = await bot.createRoom(spaceCreateOptions("Space Space"));
await bot.invite(roomId, user.userId);
});
// Assert that `Space Space` is above `My Space` due to it being an invite
getSpacePanelButton("Space Space").should("exist")
.parent().next().find('.mx_SpaceButton[aria-label="My Space"]').should("exist");
});
it("should include rooms in space home", () => {
cy.createRoom({
name: "Music",
}).as("roomId1");
cy.createRoom({
name: "Gaming",
}).as("roomId2");
const spaceName = "Spacey Mc. Space Space";
cy.all([
cy.get<string>("@roomId1"),
cy.get<string>("@roomId2"),
]).then(([roomId1, roomId2]) => {
cy.createSpace({
name: spaceName,
initial_state: [
spaceChildInitialState(roomId1),
spaceChildInitialState(roomId2),
],
}).as("spaceId");
});
cy.get("@spaceId").then(() => {
getSpacePanelButton(spaceName).dblclick(); // Open space home
});
cy.get(".mx_SpaceRoomView .mx_SpaceHierarchy_list").within(() => {
cy.get(".mx_SpaceHierarchy_roomTile").contains("Music").should("exist");
cy.get(".mx_SpaceHierarchy_roomTile").contains("Gaming").should("exist");
});
});
});