From 0911c3d39ebf5e66b6481fc94954145d15cb04ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Carden=CC=83a?= <35935591+luisecm@users.noreply.github.com> Date: Mon, 27 May 2024 15:05:42 -0600 Subject: [PATCH] add(test): add tests for chats sidebar and chats main page --- cypress/e2e/01-pin-input.cy.ts | 13 ++ cypress/e2e/02-friends.cy.ts | 181 ++++++++++++++++++++++++++ cypress/e2e/03-chats-sidebar.cy.ts | 86 ++++++++++++ cypress/e2e/PageObjects/ChatsMain.ts | 105 +++++++++++++++ cypress/e2e/PageObjects/LoginPin.ts | 39 ++++++ cypress/e2e/PageObjects/PreLoading.ts | 6 + cypress/support/commands.ts | 27 +--- cypress/support/e2e.ts | 5 + package-lock.json | 10 ++ package.json | 1 + tsconfig.json | 2 +- 11 files changed, 448 insertions(+), 27 deletions(-) create mode 100644 cypress/e2e/02-friends.cy.ts create mode 100644 cypress/e2e/03-chats-sidebar.cy.ts diff --git a/cypress/e2e/01-pin-input.cy.ts b/cypress/e2e/01-pin-input.cy.ts index 95974eb6..a67aea34 100644 --- a/cypress/e2e/01-pin-input.cy.ts +++ b/cypress/e2e/01-pin-input.cy.ts @@ -69,4 +69,17 @@ describe("Create Account and Login Tests", () => { .its("data-keyorder") .should("not.eq", "1,2,3,4,5,6,7,8,9,0"); }); + + it("User can see menu to switch to a different profile", () => { + loginPinPage.launchApplication(); + loginPinPage.waitUntilPageIsLoaded(); + loginPinPage.clickChangeUser(); + loginPinPage.selectProfileModal.should("be.visible"); + loginPinPage.selectProfileLabel.should("have.text", "Profiles"); + loginPinPage.selectProfileUserName.eq(0).should("have.text", "Space Kev"); + loginPinPage.selectProfileUserName.eq(1).should("have.text", "Sara Saturn"); + }); + + // Cannot be automated at this moment + xit("If Stay Unlocked is toggled on, user should bypass PIN page when logging in", () => {}); }); diff --git a/cypress/e2e/02-friends.cy.ts b/cypress/e2e/02-friends.cy.ts new file mode 100644 index 00000000..f55a599d --- /dev/null +++ b/cypress/e2e/02-friends.cy.ts @@ -0,0 +1,181 @@ +import { chatsMainPage } from "./PageObjects/ChatsMain"; +import { loginPinPage } from "./PageObjects/LoginPin"; +import { preLoadingPage } from "./PageObjects/PreLoading"; + +describe("Chat Page Tests", () => { + beforeEach(() => { + loginPinPage.loginWithPin("1234"); + preLoadingPage.validatePreLoadingPage(); + chatsMainPage.validateChatsMainPageIsShown(); + }); + + it("Add Friends should navigate to Friends Page", () => { + chatsMainPage.clickAddFriends(); + cy.location("href").should("include", "/friends"); + }); + + // Cannot be automated at this moment + xit("User should land on this page after logging in", () => {}); + + // Cannot be automated at this moment + xit("Clicking Add Friends should navigate you to Friends page", () => {}); + + // Cannot be automated at this moment + xit("Messages are secured by end-to-end encryption, sent over a peer-to-peer network should be displayed at the top of every chat", () => {}); + + // Cannot be automated at this moment + xit("Amount of coin should be displayed at top right toolbar", () => {}); + + // Cannot be automated at this moment + xit("Highlighted border should appear around call button when clicked", () => {}); + + // Cannot be automated at this moment + xit("Highlighted border should appear around Video button when clicked", () => {}); + + // Cannot be automated at this moment + xit("Favorite button should should be highlighted after clicked and grey when unclicked", () => {}); + + // Cannot be automated at this moment + xit("Clicking Profile button in 1on1 chat should display the friends profile", () => {}); + + // Cannot be automated at this moment + xit("Friends profile should display friends profile picture", () => {}); + + // Cannot be automated at this moment + xit("Friends profile should display friends status (wether you are friends or not)", () => {}); + + // Cannot be automated at this moment + xit("Friends profile should display friends Username", () => {}); + + // Cannot be automated at this moment + xit("Friends profile should display friends profile Status", () => {}); + + // Cannot be automated at this moment + xit("User should be able to write a note on friends profile", () => {}); + + // Cannot be automated at this moment + xit("Highlighted border should appear when user clicks into Notes textbox", () => {}); + + // Cannot be automated at this moment + xit("Clicking Groups button should display group members of the chat", () => {}); + + // Cannot be automated at this moment + xit("Timestamp appears after most recent message sent", () => {}); + + // Cannot be automated at this moment + xit("Users profile picture appears next to messages sent", () => {}); + + // Cannot be automated at this moment + xit("Context menu appears when user right clicks a message", () => {}); + + // Cannot be automated at this moment + xit("When user clicks their own message context menu should display Top 5 Most Used Emojis, Pin Message, Reply, React, Copy, Edit, Delete", () => {}); + + // Cannot be automated at this moment + xit("Clicking Pin Message should pin message in chat", () => {}); + + // Cannot be automated at this moment + xit("Clicking Reply should open reply modal", () => {}); + + // Cannot be automated at this moment + xit("Clicking React should open up emoji menu", () => {}); + + // Cannot be automated at this moment + xit("Clicking Copy should copy text to users clipboard", () => {}); + + // Cannot be automated at this moment + xit("Clicking Edit should open up the edit message modal", () => {}); + + // Cannot be automated at this moment + xit("Clicking Delete should delete message from chat", () => {}); + + // Cannot be automated at this moment + xit("Clicking the X next to a friend in the GroupMembers Modal should remove friend from groupchat", () => {}); + + // Cannot be automated at this moment + xit("Clicking the Settings button should open the Group Chat Settings", () => {}); + + // Cannot be automated at this moment + xit("Highlighted border should appear after clicking into the GroupName input box in GroupChat Settings", () => {}); + + // Cannot be automated at this moment + xit("User can change name off the group", () => {}); + + // Cannot be automated at this moment + xit("Highlighted border should appear after clicking into the GroupDescription input box in GroupChat Settings", () => {}); + + // Cannot be automated at this moment + xit("User should be able to edit the description of the group", () => {}); + + // Cannot be automated at this moment + xit("User can toggle on/off Add Members", () => {}); + + // Cannot be automated at this moment + xit("User can toggle on/off ChangePhoto", () => {}); + + // Cannot be automated at this moment + xit("User can toggle on/off Change Details", () => {}); + + // Cannot be automated at this moment + xit("Highlighted border should appear around textbox in chat when user clicks into it", () => {}); + + // Cannot be automated at this moment + xit("User should already be clicked into textbox when they enter a chat", () => {}); + + // Cannot be automated at this moment + xit("User should not be able to send a blank message (Send button should be greyed out until any text is added into the textbox)", () => {}); + + // Cannot be automated at this moment + xit("Clicking Send Coin should open the modal", () => {}); + + // Cannot be automated at this moment + xit("Amount should be displayed at the top of Send Coin modal and user should be able to click into it and change amount", () => {}); + + // Cannot be automated at this moment + xit("Only numbers should be able to be inputed in Send Coin modal", () => {}); + + // Cannot be automated at this moment + xit("Highlighted border should appear when user clicks into Notes textbox in the Send Coin modal", () => {}); + + // Cannot be automated at this moment + xit("Recipients should appear in recipients box as they are added in Send Coin Modal", () => {}); + + // Cannot be automated at this moment + xit("Clicking the X should clear user from recipients box in Send Coin Modal", () => {}); + + // Cannot be automated at this moment + xit("Highlited border should appear around selected user", () => {}); + + // Cannot be automated at this moment + xit("Scrollbar should appear if uesr has enough friends for it in Send Coin Modal", () => {}); + + // Cannot be automated at this moment + xit("User should have to hold confirm for 3 seconds to send payment in Send Coin Modal", () => {}); + + // Cannot be automated at this moment + xit("Clicking Cancel should close Send Coin modal", () => {}); + + // Cannot be automated at this moment + xit("The chat typing indicator should be displayed when user is typing", () => {}); + + // Cannot be automated at this moment + xit("Scroll to bottom button should appear after scrolling up 2 messages", () => {}); + + // Cannot be automated at this moment + xit("Number of reactions should be displayed underneath message", () => {}); + + // Cannot be automated at this moment + xit("Markdown should show when typing in chatbar", () => {}); + + // Cannot be automated at this moment + xit("User should be able to click on image in chat to see image preview", () => {}); + + // Cannot be automated at this moment + xit("Uesr can download media from chat by clicking download", () => {}); + + // Cannot be automated at this moment + xit("User should be able to view a video through the embedded video player", () => {}); + + // Cannot be automated at this moment + xit("Messages should be limited to 2048 chars", () => {}); +}); diff --git a/cypress/e2e/03-chats-sidebar.cy.ts b/cypress/e2e/03-chats-sidebar.cy.ts new file mode 100644 index 00000000..5de317cc --- /dev/null +++ b/cypress/e2e/03-chats-sidebar.cy.ts @@ -0,0 +1,86 @@ +import { chatsMainPage } from "./PageObjects/ChatsMain"; +import { loginPinPage } from "./PageObjects/LoginPin"; +import { preLoadingPage } from "./PageObjects/PreLoading"; + +describe("Chats Sidebar Tests", () => { + beforeEach(() => { + loginPinPage.loginWithPin("1234"); + preLoadingPage.validatePreLoadingPage(); + chatsMainPage.validateChatsMainPageIsShown(); + }); + + // To be automated + xit("Clicking Create Chat should open modal with option for Group Name and Group Members", () => {}); + + it("Hovering over Create Chat should show tooltips", () => { + chatsMainPage.hoverCreateGroupChatButton(); + chatsMainPage.buttonCreateGroupChat.should( + "have.attr", + "data-tooltip", + "Create Chat", + ); + }); + + it("Hovering over Nav buttons should show tooltips", () => { + chatsMainPage.hoverWalletButton(); + chatsMainPage.buttonWallet.should("have.attr", "data-tooltip", "Wallet"); + chatsMainPage.hoverFilesButton(); + chatsMainPage.buttonFiles.should("have.attr", "data-tooltip", "Files"); + chatsMainPage.hoverChatsButton(); + chatsMainPage.buttonChat.should("have.attr", "data-tooltip", "Chat"); + chatsMainPage.hoverFriendsButton(); + chatsMainPage.buttonFriends.should("have.attr", "data-tooltip", "Friends"); + chatsMainPage.hoverSettingsButton(); + chatsMainPage.buttonSettings.should( + "have.attr", + "data-tooltip", + "Settings", + ); + }); + + // To be automated + xit("Clicking hamburger button should collapse sidebar", () => {}); + + it("Nav bar buttons should redirect to correct page", () => { + chatsMainPage.clickWallet(); + cy.url().should("include", "/wallet"); + chatsMainPage.clickFiles(); + cy.url().should("include", "/files"); + chatsMainPage.clickChat(); + cy.url().should("include", "/chat"); + chatsMainPage.clickFriends(); + cy.url().should("include", "/friends"); + chatsMainPage.clickSettings(); + cy.url().should("include", "/settings/profile"); + }); + + // To be automated + xit("Textbox should have highlighted border when clicking into Chat Search", () => {}); + + // Cannot be automated at this moment + xit("ProfilePicFrame should display for any friends that have one", () => {}); + + // Cannot be automated at this moment + xit("Favorites should appear on left side of Sidebar", () => {}); + + // Cannot be automated at this moment + xit("Number of members in group should appear on that chat in both Sidebar and Favorites", () => {}); + + // Cannot be automated at this moment + xit("Clicking a favorite should take you to that chat ", () => {}); + + // Cannot be automated at this moment + xit("Right clicking a chat in sidebar should open context menu", () => {}); + + // Cannot be automated at this moment + xit("Context menu should display: Favorite, Hide, Mark as read", () => {}); + + // Cannot be automated at this moment + xit("Timestamp of most recent message sent or recieved in chat should be displayed in the sidebar", () => {}); + + // Cannot be automated at this moment + xit("Typing indicator should be displayed around users profile picture when they are typing (this applys to favorites as well)", () => {}); + + // Cannot be automated at this moment + xit("After selecting Hide chat chat should no longer be displayed in sidebar", () => {}); +}); diff --git a/cypress/e2e/PageObjects/ChatsMain.ts b/cypress/e2e/PageObjects/ChatsMain.ts index 1b2c22bd..a654eafa 100644 --- a/cypress/e2e/PageObjects/ChatsMain.ts +++ b/cypress/e2e/PageObjects/ChatsMain.ts @@ -3,10 +3,115 @@ class ChatsMainPage { return cy.get(".add-someone", { timeout: 30000 }); } + get buttonAddFriends() { + return cy.getByTestAttr("button-add-friends"); + } + + get buttonChat() { + return cy.getByTestAttr("button-Chat"); + } + + get buttonCreateGroupChat() { + return cy.getByTestAttr("button-create-group-chat"); + } + + get buttonFiles() { + return cy.getByTestAttr("button-Files"); + } + + get buttonFriends() { + return cy.getByTestAttr("button-Friends"); + } + + get buttonSettings() { + return cy.getByTestAttr("button-Settings"); + } + + get buttonShowSidebar() { + return cy.getByTestAttr("button-show-sidebar"); + } + + get buttonWallet() { + return cy.getByTestAttr("button-Wallet"); + } + + get sectionAddSomeone() { + return cy.getByTestAttr("section-add-someone"); + } + + get slimbar() { + return cy.getByTestAttr("slimbar"); + } + + get topbar() { + return cy.getByTestAttr("topbar"); + } + + public clickAddFriends() { + this.buttonAddFriends.click(); + } + + public clickChat() { + this.buttonChat.click(); + } + + public clickCreateGroupChat() { + this.buttonCreateGroupChat.click(); + } + + public clickFiles() { + this.buttonFiles.click(); + } + + public clickFriends() { + this.buttonFriends.click(); + } + + public clickSettings() { + this.buttonSettings.click(); + } + + public clickShowSidebar() { + this.buttonShowSidebar.click(); + } + + public clickWallet() { + this.buttonWallet.click(); + } + + public hoverChatsButton() { + this.buttonChat.realHover(); + } + + public hoverCreateGroupChatButton() { + this.buttonCreateGroupChat.realHover(); + } + + public hoverFilesButton() { + this.buttonFiles.realHover(); + } + + public hoverFriendsButton() { + this.buttonFriends.realHover(); + } + + public hoverSettingsButton() { + this.buttonSettings.realHover(); + } + + public hoverWalletButton() { + this.buttonWallet.realHover(); + } + public validateAddSomeoneIsShown() { this.addSomeone.should("exist"); } + public validateChatsMainPageIsShown() { + this.validateAddSomeoneIsShown(); + this.validateURL(); + } + public validateURL() { cy.location("href").should("include", "/chat"); } diff --git a/cypress/e2e/PageObjects/LoginPin.ts b/cypress/e2e/PageObjects/LoginPin.ts index 5e73aa4e..1315589a 100644 --- a/cypress/e2e/PageObjects/LoginPin.ts +++ b/cypress/e2e/PageObjects/LoginPin.ts @@ -1,8 +1,16 @@ class LoginPinPage { + get changeUserButton() { + return cy.getByTestAttr("button-change-user"); + } + get clearInputButton() { return cy.getByTestAttr("button-clear-input"); } + get createNewProfileButton() { + return cy.getByTestAttr("button-create-new-profile"); + } + get labelChooseEnterPin() { return cy.getByTestAttr("label-choose-enter-pin"); } @@ -75,6 +83,26 @@ class LoginPinPage { return cy.getByTestAttr("switch-scramble-keypad"); } + get selectProfileLabel() { + return cy.getByTestAttr("label-select-profile"); + } + + get selectProfileUser() { + return cy.getByTestAttr("select-profile-user"); + } + + get selectProfileUserImage() { + return cy.getByTestAttr("select-profile-user-image"); + } + + get selectProfileUserName() { + return cy.getByTestAttr("select-profile-user-name"); + } + + get selectProfileModal() { + return cy.getByTestAttr("modal-select-profile"); + } + get stayUnlockedLabel() { return cy.getByTestAttr("label-stay-unlocked"); } @@ -87,6 +115,10 @@ class LoginPinPage { return cy.getByTestAttr("button-settings"); } + public clickChangeUser() { + this.changeUserButton.click(); + } + public clickClearPin() { this.clearInputButton.click(); } @@ -117,6 +149,13 @@ class LoginPinPage { cy.visit("/"); } + public loginWithPin(pin: string) { + this.launchApplication(); + this.waitUntilPageIsLoaded(); + this.enterPin(pin); + this.clickConfirm(); + } + public validateConfirmButtonIsDisabled() { this.pinButtonConfirm.should("be.disabled"); } diff --git a/cypress/e2e/PageObjects/PreLoading.ts b/cypress/e2e/PageObjects/PreLoading.ts index 2cc7a6ef..8f37972b 100644 --- a/cypress/e2e/PageObjects/PreLoading.ts +++ b/cypress/e2e/PageObjects/PreLoading.ts @@ -7,6 +7,12 @@ class PreLoadingPage { return cy.get(".text.medium"); } + public validatePreLoadingPage() { + this.validateLoadingHeader(); + this.validateLoadingMessage(); + this.validateURL(); + } + public validateLoadingHeader() { this.loadingHeader.should("exist").and("have.text", "Initializing..."); } diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index f2f4b88b..1f9cb543 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -1,35 +1,10 @@ -// *********************************************** -// This example commands.js shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -// -// -// -- This is a parent command -- -// Cypress.Commands.add('login', (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) - declare namespace Cypress { interface Chainable { getByTestAttr( selector: string, ...options: any ): Chainable>; + login(pin: string): Chainable>; } } diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index 3a252243..9c83a469 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -15,6 +15,11 @@ // Import commands.js using ES2015 syntax: import "./commands"; +import "cypress-real-events"; // Alternatively you can use CommonJS syntax: // require('./commands') +Cypress.on("uncaught:exception", (err, runnable) => { + // returning false here prevents Cypress from failing the test + return false; +}); diff --git a/package-lock.json b/package-lock.json index bba1c4ba..ede8406b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "devDependencies": { "cypress": "^13.9.0", + "cypress-real-events": "^1.12.0", "prettier": "3.2.5", "typescript": "^5.4.5" } @@ -582,6 +583,15 @@ "node": "^16.0.0 || ^18.0.0 || >=20.0.0" } }, + "node_modules/cypress-real-events": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/cypress-real-events/-/cypress-real-events-1.12.0.tgz", + "integrity": "sha512-oiy+4kGKkzc2PT36k3GGQqkGxNiVypheWjMtfyi89iIk6bYmTzeqxapaLHS3pnhZOX1IEbTDUVxh8T4Nhs1tyQ==", + "dev": true, + "peerDependencies": { + "cypress": "^4.x || ^5.x || ^6.x || ^7.x || ^8.x || ^9.x || ^10.x || ^11.x || ^12.x || ^13.x" + } + }, "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", diff --git a/package.json b/package.json index 3fee9c0f..b475c193 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "license": "MIT", "devDependencies": { "cypress": "^13.9.0", + "cypress-real-events": "^1.12.0", "prettier": "3.2.5", "typescript": "^5.4.5" } diff --git a/tsconfig.json b/tsconfig.json index fd641777..70a448f4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "target": "es5", "lib": ["es5", "dom"], - "types": ["cypress", "node"], + "types": ["cypress", "node", "cypress-real-events"], "baseUrl": "." }, "include": ["**/*.ts"]