Add Cypress Testing Library (#10446)
This commit is contained in:
parent
6eda1fa6e2
commit
7cb90d0f78
7 changed files with 123 additions and 12 deletions
|
@ -20,8 +20,8 @@ import { HomeserverInstance } from "../../plugins/utils/homeserver";
|
|||
import Chainable = Cypress.Chainable;
|
||||
|
||||
function openCreateRoomDialog(): Chainable<JQuery<HTMLElement>> {
|
||||
cy.get('[aria-label="Add room"]').click();
|
||||
cy.get('.mx_ContextualMenu [aria-label="New room"]').click();
|
||||
cy.findButton("Add room").click();
|
||||
cy.findMenuitem("New room").click();
|
||||
return cy.get(".mx_CreateRoomDialog");
|
||||
}
|
||||
|
||||
|
@ -46,20 +46,23 @@ describe("Create Room", () => {
|
|||
|
||||
openCreateRoomDialog().within(() => {
|
||||
// Fill name & topic
|
||||
cy.get('[label="Name"]').type(name);
|
||||
cy.get('[label="Topic (optional)"]').type(topic);
|
||||
cy.findTextbox("Name").type(name);
|
||||
cy.findTextbox("Topic (optional)").type(topic);
|
||||
// Change room to public
|
||||
cy.get('[aria-label="Room visibility"]').click();
|
||||
cy.get("#mx_JoinRuleDropdown__public").click();
|
||||
cy.findButton("Room visibility").click();
|
||||
cy.findOption("Public room").click();
|
||||
// Fill room address
|
||||
cy.get('[label="Room address"]').type("test-room-1");
|
||||
cy.findTextbox("Room address").type("test-room-1");
|
||||
// Submit
|
||||
cy.get(".mx_Dialog_primary").click();
|
||||
cy.findButton("Create room").click();
|
||||
});
|
||||
|
||||
cy.url().should("contain", "/#/room/#test-room-1:localhost");
|
||||
cy.contains(".mx_RoomHeader_nametext", name);
|
||||
cy.contains(".mx_RoomHeader_topic", topic);
|
||||
|
||||
cy.get(".mx_RoomHeader").within(() => {
|
||||
cy.findByText(name);
|
||||
cy.findByText(topic);
|
||||
});
|
||||
});
|
||||
|
||||
it("should create a room with a long room name, which is displayed with ellipsis", () => {
|
||||
|
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
|||
|
||||
import "@percy/cypress";
|
||||
import "cypress-real-events";
|
||||
import "@testing-library/cypress/add-commands";
|
||||
|
||||
import "./homeserver";
|
||||
import "./login";
|
||||
|
@ -37,3 +38,4 @@ import "./network";
|
|||
import "./composer";
|
||||
import "./proxy";
|
||||
import "./axe";
|
||||
import "./find";
|
||||
|
|
70
cypress/support/find.ts
Normal file
70
cypress/support/find.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/// <reference types="cypress" />
|
||||
|
||||
import Chainable = Cypress.Chainable;
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
/**
|
||||
* Finds an element with the role "button".
|
||||
*
|
||||
* @param name - accessible name of the element to find
|
||||
*/
|
||||
findButton(name: string): Chainable<JQuery>;
|
||||
/**
|
||||
* Finds an element with the role "textbox".
|
||||
*
|
||||
* @param name - accessible name of the element to find
|
||||
*/
|
||||
findTextbox(name: string): Chainable<JQuery>;
|
||||
/**
|
||||
* Finds an element with the role "option".
|
||||
*
|
||||
* @param name - accessible name of the element to find
|
||||
*/
|
||||
findOption(name: string): Chainable<JQuery>;
|
||||
/**
|
||||
* Finds an element with the role "menuitem".
|
||||
*
|
||||
* @param name - accessible name of the element to find
|
||||
*/
|
||||
findMenuitem(name: string): Chainable<JQuery>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cypress.Commands.add("findButton", (name: string): Chainable<JQuery> => {
|
||||
return cy.findByRole("button", { name });
|
||||
});
|
||||
|
||||
Cypress.Commands.add("findTextbox", (name: string): Chainable<JQuery> => {
|
||||
return cy.findByRole("textbox", { name });
|
||||
});
|
||||
|
||||
Cypress.Commands.add("findOption", (name: string): Chainable<JQuery> => {
|
||||
return cy.findByRole("option", { name });
|
||||
});
|
||||
|
||||
Cypress.Commands.add("findMenuitem", (name: string): Chainable<JQuery> => {
|
||||
return cy.findByRole("menuitem", { name });
|
||||
});
|
||||
|
||||
// Needed to make this file a module
|
||||
export {};
|
|
@ -3,7 +3,7 @@
|
|||
"target": "es2016",
|
||||
"jsx": "react",
|
||||
"lib": ["es2020", "dom", "dom.iterable"],
|
||||
"types": ["cypress", "cypress-axe", "@percy/cypress"],
|
||||
"types": ["cypress", "cypress-axe", "@percy/cypress", "@testing-library/cypress"],
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "node",
|
||||
|
|
|
@ -154,6 +154,14 @@ API before logging the user in. You can make use of `cy.getBot(homeserver)` and
|
|||
We should probably end up with convenience APIs that wrap the homeserver creation, logging in and room
|
||||
creation that can be called to set up tests.
|
||||
|
||||
### Try to write tests from the users's perspective
|
||||
|
||||
Like for instance a user will not look for a button by querying a CSS selector. Instead you should work
|
||||
with roles / labels etc.. You can make use of `cy.findBy…` queries provided by
|
||||
[Cypress Testing Library](https://github.com/testing-library/cypress-testing-library) and some convencience
|
||||
commands, such as `findButton(name)` or `findTextbox(name)`.
|
||||
See [`/cypress/support/find.ts`](../cypress/support/find.ts) for a complete list.
|
||||
|
||||
### Using matrix-js-sdk
|
||||
|
||||
Due to the way we run the Cypress tests in CI, at this time you can only use the matrix-js-sdk module
|
||||
|
|
|
@ -143,6 +143,7 @@
|
|||
"@percy/cli": "^1.11.0",
|
||||
"@percy/cypress": "^3.1.2",
|
||||
"@sinonjs/fake-timers": "^9.1.2",
|
||||
"@testing-library/cypress": "^9.0.0",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^12.1.5",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
|
|
29
yarn.lock
29
yarn.lock
|
@ -1138,7 +1138,7 @@
|
|||
pirates "^4.0.5"
|
||||
source-map-support "^0.5.16"
|
||||
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.9", "@babel/runtime@^7.20.7", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
|
||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.9", "@babel/runtime@^7.20.7", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
|
||||
version "7.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673"
|
||||
integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
|
||||
|
@ -2048,6 +2048,14 @@
|
|||
dependencies:
|
||||
"@sinonjs/commons" "^1.7.0"
|
||||
|
||||
"@testing-library/cypress@^9.0.0":
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/cypress/-/cypress-9.0.0.tgz#3facad49c4654a99bbd138f83f33b415d2d6f097"
|
||||
integrity sha512-c1XiCGeHGGTWn0LAU12sFUfoX3qfId5gcSE2yHode+vsyHDWraxDPALjVnHd4/Fa3j4KBcc5k++Ccy6A9qnkMA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.14.6"
|
||||
"@testing-library/dom" "^8.1.0"
|
||||
|
||||
"@testing-library/dom@^8.0.0":
|
||||
version "8.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.19.0.tgz#bd3f83c217ebac16694329e413d9ad5fdcfd785f"
|
||||
|
@ -2062,6 +2070,20 @@
|
|||
lz-string "^1.4.4"
|
||||
pretty-format "^27.0.2"
|
||||
|
||||
"@testing-library/dom@^8.1.0":
|
||||
version "8.20.0"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.20.0.tgz#914aa862cef0f5e89b98cc48e3445c4c921010f6"
|
||||
integrity sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.10.4"
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@types/aria-query" "^5.0.1"
|
||||
aria-query "^5.0.0"
|
||||
chalk "^4.1.0"
|
||||
dom-accessibility-api "^0.5.9"
|
||||
lz-string "^1.4.4"
|
||||
pretty-format "^27.0.2"
|
||||
|
||||
"@testing-library/jest-dom@^5.16.5":
|
||||
version "5.16.5"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz#3912846af19a29b2dbf32a6ae9c31ef52580074e"
|
||||
|
@ -2109,6 +2131,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc"
|
||||
integrity sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==
|
||||
|
||||
"@types/aria-query@^5.0.1":
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.1.tgz#3286741fb8f1e1580ac28784add4c7a1d49bdfbc"
|
||||
integrity sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==
|
||||
|
||||
"@types/babel__core@^7.1.14":
|
||||
version "7.1.20"
|
||||
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.20.tgz#e168cdd612c92a2d335029ed62ac94c95b362359"
|
||||
|
|
Loading…
Reference in a new issue