diff --git a/tests/e2e/web/pages/app.ts b/tests/e2e/web/pages/app.ts index da66dec9..89aaea31 100644 --- a/tests/e2e/web/pages/app.ts +++ b/tests/e2e/web/pages/app.ts @@ -13,6 +13,8 @@ import {SignUpPage} from './signUpPage' import {SocialPage} from './socialPage' import {PeoplePage} from './peoplePage' import {NotificationPage} from './notificationsPage' +import { MessagesPage } from './messagesPage' + export class App { readonly auth: AuthPage @@ -26,6 +28,7 @@ export class App { readonly social: SocialPage readonly people: PeoplePage readonly notifs: NotificationPage + readonly messages: MessagesPage readonly contextManager: ContextManager readonly context: BrowserContext @@ -41,6 +44,7 @@ export class App { this.social = new SocialPage(page) this.people = new PeoplePage(page) this.notifs = new NotificationPage(page) + this.messages = new MessagesPage(page) this.context = page.context() const browser = page.context().browser() diff --git a/tests/e2e/web/pages/messagesPage.ts b/tests/e2e/web/pages/messagesPage.ts new file mode 100644 index 00000000..16f99893 --- /dev/null +++ b/tests/e2e/web/pages/messagesPage.ts @@ -0,0 +1,97 @@ +import {expect, Locator, Page} from '@playwright/test' + +export class MessagesPage { + private readonly messagesPageHeader: Locator + private readonly messagesTable: Locator + private readonly messagesRow: Locator + private readonly messagesUsername: Locator + private readonly messagesTimestamp: Locator + private readonly newMessageButton: Locator + private readonly newMessageSearchUsers: Locator + private readonly newMessageSearchResults: Locator + private readonly newMessageSearchCreateButton: Locator + private readonly newMessageStart: Locator + private readonly messageInput: Locator + private readonly messageSubmit: Locator + private readonly conversation: Locator + private readonly conversationMessage: Locator + + constructor(public readonly page: Page) { + this.messagesPageHeader = page.getByRole('heading', { name: 'Messages' }) + this.messagesTable = page.getByTestId('messages-table') + this.messagesRow = page.getByTestId('messages-row') + this.messagesUsername = page.getByTestId('messages-username') + this.messagesTimestamp = page.getByTestId('messages-timestamp') + this.newMessageButton = page.getByRole('button', { name: 'New Message' }) + this.newMessageSearchUsers = page.getByRole('textbox', { name: 'Search users...' }) + this.newMessageSearchResults = page.getByTestId('search-results') + this.newMessageSearchCreateButton = page.getByRole('button', { name: 'Create' }) + this.newMessageStart = page.getByText('No messages yet.', { exact: true }) + this.messageInput = page.locator('.tiptap') + this.messageSubmit = page.getByTestId('conversation-message-submit') + this.conversation = page.getByTestId('conversation') + this.conversationMessage = page.getByTestId('conversation-message') + } + + async verifyMessagesPage() { + await expect(this.messagesPageHeader).toBeVisible() + } + + async createNewMessage(username: string []) { + await expect(this.newMessageButton).toBeVisible() + await this.newMessageButton.click() + await expect(this.newMessageSearchUsers).toBeVisible() + for (let i = 0; i < username.length; i++) { + await this.newMessageSearchUsers.fill(username[i]) + await expect(this.newMessageSearchResults).toBeVisible() + const results = await this.newMessageSearchResults.getByTestId('search-results-username').all() + + for (let i = 0; i < results.length; i++) { + const usernameResults = await results[i].textContent() + if (usernameResults?.toLowerCase() === username[i].toLowerCase()) await results[i].click() + break + } + } + + await expect(this.newMessageSearchCreateButton).toBeVisible() + await this.newMessageSearchCreateButton.click() + } + + async sendMessage(message: string) { + await expect(this.messageInput).toBeVisible() + await this.messageInput.fill(message) + await expect(this.messageSubmit).toBeVisible() + await this.messageSubmit.click() + } + + async findMessageConversation(displayName: string) { + await expect(this.messagesTable).toBeVisible() + const doMessagesExist = await this.messagesRow.count() > 0 + if (doMessagesExist) { + const messages = await this.messagesRow.getByTestId('messages-username').all() + + for (let i = 0; i < messages.length; i++) { + await expect(messages[i]).toBeVisible() + const messageFromUser = await messages[i].textContent() + if (messageFromUser?.toLowerCase() === displayName.toLowerCase()) await messages[i].click() + } + } else { + throw new Error('There are no messages on this account') + } + } + + async verifyMessage(messageContent: string) { + await expect(this.conversation).toBeVisible() + const messageCount = await this.conversationMessage.count() > 0 + if (messageCount) { + const messages = await this.conversationMessage.all() + for (let i = 0; i < messages.length; i++) { + const message = await messages[i].textContent() + if (message?.toLowerCase() === messageContent.toLowerCase()) return true + } + return false + } else { + throw new Error('There are no messages in this conversation') + } + } +} \ No newline at end of file diff --git a/tests/e2e/web/pages/peoplePage.ts b/tests/e2e/web/pages/peoplePage.ts index c089e37b..9c463c02 100644 --- a/tests/e2e/web/pages/peoplePage.ts +++ b/tests/e2e/web/pages/peoplePage.ts @@ -88,7 +88,10 @@ export type PeoplePageFilter = { export class PeoplePage { private readonly peopleHeading: Locator + private readonly savedPeopleHeading: Locator + private readonly savedPeopleList: Locator private readonly searchBox: Locator + private readonly savedPeopleButton: Locator private readonly profileCount: Locator private readonly resetFilters: Locator private readonly yourFiltersCheckbox: Locator @@ -122,13 +125,20 @@ export class PeoplePage { private readonly displayDropdown: Locator private readonly profileGrid: Locator private readonly profileResults: Locator + private readonly profileHide: Locator + private readonly profileStar: Locator + private readonly profileMessage: Locator + private readonly messageInput: Locator private readonly profileName: Locator private readonly profileAgeGender: Locator private readonly profileSeeking: Locator constructor(public readonly page: Page) { this.peopleHeading = page.getByRole('heading', {name: 'People'}) + this.savedPeopleHeading = page.getByRole('heading', { name: 'Saved People' }) + this.savedPeopleList = page.getByTestId('saved-person') this.searchBox = page.getByRole('textbox', {name: 'Search anything...'}) + this.savedPeopleButton = page.getByRole('button', { name: 'Saved People' }) this.profileCount = page.getByTestId('people-profile-count') this.resetFilters = page.getByRole('button', {name: 'Reset filters'}) this.yourFiltersCheckbox = page.getByText('Your filters', {exact: true}) @@ -162,6 +172,10 @@ export class PeoplePage { this.displayDropdown = page.getByRole('button', {name: 'Display'}) this.profileGrid = page.getByTestId('people-profile-grid') this.profileResults = page.getByTestId('people-profile-results') + this.profileHide = page.getByTestId('hide-profile-button') + this.profileStar = page.getByTestId('star-profile-button') + this.profileMessage = page.getByTestId('message-profile-button') + this.messageInput = page.locator('.tiptap') this.profileName = page.getByTestId('people-profile-name') this.profileAgeGender = page.getByTestId('people-profile-age-gender') this.profileSeeking = page.getByTestId('people-profile-seeking') @@ -247,12 +261,16 @@ export class PeoplePage { await expect(this.peopleHeading).toBeVisible() } - //Doesn't actually work, need to find out why + async clickSavedPeopleButton() { + await expect(this.savedPeopleButton).toBeVisible() + await this.savedPeopleButton.click() + } + async useSearch(item: string) { await expect(this.searchBox).toBeVisible() await this.searchBox.click() await this.searchBox.fill(item) - await this.page.keyboard.press('Enter') + await this.page.waitForTimeout(1000) } async resetFilter() { @@ -443,12 +461,18 @@ export class PeoplePage { const profileName = await chosenProfile.getByTestId('people-profile-name').textContent() const ageGender = await chosenProfile.getByTestId('people-profile-age-gender').textContent() const seekingInfo = await chosenProfile.getByTestId('people-profile-seeking').textContent() + const hideProfile = await chosenProfile.getByTestId('hide-profile-button') + const starProfile = await chosenProfile.getByTestId('star-profile-button') + const messageProfile = await chosenProfile.getByTestId('message-profile-button') return { profile: chosenProfile ?? '', name: profileName ?? '', ageGender: ageGender ?? '', seeking: seekingInfo ?? '', + hide: hideProfile ?? '', + star: starProfile ?? '', + message: messageProfile ?? '', } } @@ -465,4 +489,41 @@ export class PeoplePage { await expect(noProfilesFound).toBeVisible() } } + + async selectProfile(displayName: string) { + await expect(this.profileGrid).toBeVisible() + await this.profileName.getByText(displayName).click() + } + + async messageProfile(displayName: string, message: string) { + await expect(this.profileGrid).toBeVisible() + const profiles = await this.profileResults.all() + + for (let i = 0; i < profiles.length; i++) { + const profileName = await profiles[i].getByTestId('people-profile-name').textContent(); + if (profileName?.toLowerCase() === displayName.toLowerCase()) { + await profiles[i].getByTestId('message-profile-button').click() + await expect(this.messageInput).toBeVisible() + await this.messageInput.fill(message) + await this.page.getByTestId('conversation-message-submit').click() + } + } + } + + async verifySavedPerson(displayName: string) { + await expect(this.savedPeopleHeading).toBeVisible() + const isThereSavedPeople = await this.savedPeopleList.count() > 0 + + if (isThereSavedPeople) { + const listOfPeople = await this.savedPeopleList.all() + for (let i = 0; i < listOfPeople.length; i++) { + await expect(listOfPeople[i]).toBeVisible() + const profileName = await listOfPeople[i].textContent() + if (profileName?.toLowerCase() === displayName.toLowerCase()) return true + } + return false + } else { + throw new Error('There are no profiles in the saved people list') + } + } } diff --git a/tests/e2e/web/specs/signIn.spec.ts b/tests/e2e/web/specs/signIn.spec.ts index 2f1e2d0d..0158d48e 100644 --- a/tests/e2e/web/specs/signIn.spec.ts +++ b/tests/e2e/web/specs/signIn.spec.ts @@ -1,5 +1,4 @@ import {expect, test} from '../fixtures/signInFixture' -import {ContextManager} from '../../utils/contextManager' test.describe('when given valid input', () => { test('should be able to sign in to an available account', async ({ @@ -11,6 +10,19 @@ test.describe('when given valid input', () => { await app.home.verifySignedInHomePage(account.display_name) }) + test('should be able to save/favorite people', async ({ + app, + signedOutAccount: account, + }) => { + await app.signinWithEmail(account) + await app.home.clickPeopleLink() + const profile = await app.people.getProfileInfo() + await expect(profile.star).toBeVisible() + await profile.star.click() + await app.people.clickSavedPeopleButton() + await app.people.verifySavedPerson(profile.name) + }) + test.describe('the applied filter should', () => { test('update the profile count', async ({app, signedOutAccount: account}) => { await app.signinWithEmail(account) @@ -226,14 +238,39 @@ test.describe('when given valid input', () => { }) test.describe('a verified account should', () => { - test('be able to send a message', async ({app, devOneAccount, devTwoAccount}) => { + test('be able to send a message from the messages page', async ({app, devOneAccount, devTwoAccount}) => { const devOne = await app.contextManager.createContext('devOne') const devTwo = await app.contextManager.createContext('devTwo') await devOne.signinWithEmail(devOneAccount) - await devOne.home.clickPeopleLink() await devTwo.signinWithEmail(devTwoAccount) - await devTwo.home.clickPeopleLink() + + await devOne.home.clickMessagesLink() + await devOne.messages.createNewMessage([devTwoAccount.display_name]) + await devOne.messages.sendMessage('This is a message') + + await devTwo.home.clickMessagesLink() + await devTwo.messages.findMessageConversation(devOneAccount.display_name) + await devTwo.messages.verifyMessage('This is a message') }) + + test('be able to send a message from the people page', async ({app, devOneAccount, devTwoAccount}) => { + const devOne = await app.contextManager.createContext('devOne') + const devTwo = await app.contextManager.createContext('devTwo') + await devOne.signinWithEmail(devOneAccount) + await devTwo.signinWithEmail(devTwoAccount) + + await devOne.home.clickPeopleLink() + await devOne.people.useSearch(devTwoAccount.display_name) + const message = "This is a message".repeat(20) + await devOne.people.messageProfile(devTwoAccount.display_name, message) + await devOne.messages.verifyMessage(message) + + await devTwo.home.clickMessagesLink() + await devTwo.messages.findMessageConversation(devOneAccount.display_name) + await devTwo.messages.verifyMessage(message) + }) + + }) }) diff --git a/web/components/chat/chat-message.tsx b/web/components/chat/chat-message.tsx index 7d2b1d21..38f3bc25 100644 --- a/web/components/chat/chat-message.tsx +++ b/web/components/chat/chat-message.tsx @@ -95,6 +95,7 @@ export function ChatMessageItem(props: { isMe && 'flex-row-reverse', firstOfUser ? 'mt-2' : 'mt-1', )} + data-testid="conversation-message" > {!isMe && !hideAvatar && ( submit('comment')} diff --git a/web/components/profile-grid.tsx b/web/components/profile-grid.tsx index 5ee41da0..455438cd 100644 --- a/web/components/profile-grid.tsx +++ b/web/components/profile-grid.tsx @@ -431,7 +431,10 @@ function ProfilePreview(props: { /> )} {user && ( -
+
{visibleUsers.map((u) => ( -
+
@@ -243,7 +243,10 @@ function StarModal(props: { />
-
+
{u.name}
@{u.username}
@@ -251,6 +254,7 @@ function StarModal(props: {