From 1994697fa13b155d1e34294ead510a0d047dd35b Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams <55924431+O-Bots@users.noreply.github.com> Date: Fri, 20 Feb 2026 15:56:26 +0000 Subject: [PATCH] Adding onboarding E2E foundations and first tests (#30) * . * Centralizing config details * Added data-testId attributes where necessary and started the onboarding flow scaffolding * Continued onboarding test scaffolding * Continued work on tests for the Onboarding flow * . * Updated "Want kids" options to be less flaky Updated playwright.config so that expect timeout matching test timeout * Continued updating front-end scaffolding * . * . * . * . * Updated fixture function deleteUser: to also remove the database user information * Rm * Fix * Fixes --------- Co-authored-by: MartinBraquet --- package.json | 14 +- playwright.config.ts | 3 + scripts/setup-auth.ts | 4 +- tests/e2e/backend/utils/database.ts | 6 +- tests/e2e/web/SPEC_CONFIG.js | 11 +- tests/e2e/web/fixtures/base.ts | 56 + tests/e2e/web/fixtures/deleteUserFixture.ts | 6 +- tests/e2e/web/pages/AuthPage.ts | 82 +- tests/e2e/web/pages/homePage.ts | 30 + tests/e2e/web/pages/onboardingPage.ts | 49 + tests/e2e/web/pages/profilePage.ts | 287 ++ tests/e2e/web/pages/signUpPage.ts | 656 +++ .../web/specs/firebaseAccountCreationTest.ts | 15 + tests/e2e/web/specs/onboardingFlow.spec.ts | 114 + tests/e2e/web/utils/.keep | 0 tests/e2e/web/utils/accountInformation.ts | 158 + tests/e2e/web/utils/deleteUser.ts | 44 + web/components/bio/profile-bio-block.tsx | 4 +- web/components/nav/sidebar.tsx | 1 + web/components/optional-profile-form.tsx | 46 +- web/components/profile-about.tsx | 39 +- web/components/profile/profile-header.tsx | 5 +- .../profile/profile-primary-info.tsx | 5 +- web/components/user/user-handles.tsx | 1 + web/components/widgets/add-photos.tsx | 2 +- web/components/widgets/tooltip.tsx | 3 + yarn.lock | 4392 ++++++++--------- 27 files changed, 3729 insertions(+), 2304 deletions(-) create mode 100644 tests/e2e/web/fixtures/base.ts create mode 100644 tests/e2e/web/pages/homePage.ts create mode 100644 tests/e2e/web/pages/onboardingPage.ts create mode 100644 tests/e2e/web/pages/profilePage.ts create mode 100644 tests/e2e/web/pages/signUpPage.ts create mode 100644 tests/e2e/web/specs/firebaseAccountCreationTest.ts create mode 100644 tests/e2e/web/specs/onboardingFlow.spec.ts delete mode 100644 tests/e2e/web/utils/.keep create mode 100644 tests/e2e/web/utils/accountInformation.ts create mode 100644 tests/e2e/web/utils/deleteUser.ts diff --git a/package.json b/package.json index 643e3bc1..a025b7f1 100644 --- a/package.json +++ b/package.json @@ -74,9 +74,8 @@ "@capacitor/status-bar": "7.0.3", "@capawesome/capacitor-live-update": "7.2.2", "@capgo/capacitor-social-login": "7.14.9", - "@playwright/test": "1.55.0", - "colorette": "2.0.20", - "prismjs": "1.30.0", + "colorette": "^2.0.20", + "prismjs": "^1.30.0", "react": "18.2.0", "react-dom": "18.2.0", "react-markdown": "10.1.0", @@ -88,10 +87,11 @@ "@capacitor/assets": "3.0.5", "@capacitor/cli": "7.4.4", "@faker-js/faker": "10.1.0", - "@testing-library/dom": "10.4.1", - "@testing-library/jest-dom": "6.8.0", - "@testing-library/react": "16.3.0", - "@testing-library/user-event": "14.6.1", + "@playwright/test": "1.58.2", + "@testing-library/dom": "^10.0.0", + "@testing-library/jest-dom": "^6.6.4", + "@testing-library/react": "^16.3.0", + "@testing-library/user-event": "^14.6.1", "@types/jest": "29.2.4", "@types/node": "20.12.11", "@typescript-eslint/eslint-plugin": "^8", diff --git a/playwright.config.ts b/playwright.config.ts index d98fe4dd..7fd83c78 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -27,5 +27,8 @@ export default defineConfig({ // }, ], timeout: 60000, + expect: { + timeout: 120000, + }, }); diff --git a/scripts/setup-auth.ts b/scripts/setup-auth.ts index d0f3b4ea..106eb47a 100644 --- a/scripts/setup-auth.ts +++ b/scripts/setup-auth.ts @@ -2,9 +2,9 @@ import axios from 'axios'; import { config } from '../tests/e2e/web/SPEC_CONFIG.js'; async function createAuth() { - const base = 'http://localhost:9099/identitytoolkit.googleapis.com/v1'; + // const base = 'http://localhost:9099/identitytoolkit.googleapis.com/v1'; - await axios.post(`${base}/accounts:signUp?key=fake-api-key`, { + await axios.post(`${config.FIREBASE_URL.BASE}${config.FIREBASE_URL.SIGNUP}`, { email: config.USERS.DEV_1.EMAIL, password: config.USERS.DEV_1.PASSWORD, returnSecureToken: true diff --git a/tests/e2e/backend/utils/database.ts b/tests/e2e/backend/utils/database.ts index cc9fa6ac..76cc1d09 100644 --- a/tests/e2e/backend/utils/database.ts +++ b/tests/e2e/backend/utils/database.ts @@ -7,7 +7,7 @@ class DatabaseTestingUtilities { `; const userResults = await page.db.query(queryUserById,[name]) return userResults[0] - } + }; findProfileById = async (page: any, user_id: string) => { const queryProfileById = ` @@ -20,8 +20,8 @@ class DatabaseTestingUtilities { `; const profileResults = await page.db.query(queryProfileById,[user_id]) return profileResults[0] - } + }; -} +}; export const databaseUtils = new DatabaseTestingUtilities(); \ No newline at end of file diff --git a/tests/e2e/web/SPEC_CONFIG.js b/tests/e2e/web/SPEC_CONFIG.js index 21478add..819ee998 100644 --- a/tests/e2e/web/SPEC_CONFIG.js +++ b/tests/e2e/web/SPEC_CONFIG.js @@ -1,6 +1,11 @@ export const config = { BASE_URL: 'http://localhost:3000', - + FIREBASE_URL: { + BASE: 'http://localhost:9099/identitytoolkit.googleapis.com/v1', + SIGNUP: '/accounts:signUp?key=fake-api-key', + SIGN_IN_PASSWORD: '/accounts:signInWithPassword?key=fake-api-key', + DELETE: '/accounts:delete?key=fake-api-key', + }, USERS: { DEV_1: { EMAIL: 'dev_1@compass.com', @@ -10,6 +15,10 @@ export const config = { EMAIL: 'dev_2@compass.com', PASSWORD: 'dev_2Password', }, + ONBOARDING: { + EMAIL: 'onboarding@compass.com', + PASSWORD: 'compassConnections1!', + }, SPEC: { EMAIL: 'spec@compass.com', PASSWORD: 'compassConnections1!', diff --git a/tests/e2e/web/fixtures/base.ts b/tests/e2e/web/fixtures/base.ts new file mode 100644 index 00000000..d42617e3 --- /dev/null +++ b/tests/e2e/web/fixtures/base.ts @@ -0,0 +1,56 @@ +import { test as base } from "@playwright/test"; +import { deleteUser } from "../utils/deleteUser"; +import { onboarding, OnboardingUser } from "../utils/accountInformation"; +import { OnboardingPage } from "../pages/onboardingPage"; +import { HomePage } from "../pages/homePage"; +import { ProfilePage } from "../pages/profilePage"; +import { SignUpPage } from "../pages/signUpPage"; +import { AuthPage } from "../pages/AuthPage"; + +export const test = base.extend<{ + homePage: HomePage, + onboardingPage: OnboardingPage, + signUpPage: SignUpPage, + profilePage: ProfilePage, + authPage: AuthPage, + cleanUpUsers: void; + testAccount: OnboardingUser + fakerAccount: OnboardingUser +}>({ + testAccount: async({}, use) => { + await use(onboarding.account_one) + }, + fakerAccount: async({}, use) => { + await use(onboarding.faker_account) + }, + onboardingPage: async ({page}, use) => { + const onboardingPage = new OnboardingPage(page); + await use(onboardingPage); + }, + homePage: async ({page}, use) => { + const homePage = new HomePage(page); + await use(homePage); + }, + signUpPage: async ({page}, use) => { + const signUpPage = new SignUpPage(page); + await use(signUpPage); + }, + authPage: async ({page}, use) => { + const authPage = new AuthPage(page); + await use(authPage); + }, + profilePage: async ({page}, use) => { + const profilePage = new ProfilePage(page); + await use(profilePage); + }, + cleanUpUsers: [ + async ({ }, use) => { + await use(); + await deleteUser(onboarding.account_one.email, onboarding.account_one.password); + await deleteUser(onboarding.faker_account.email, onboarding.faker_account.password); + }, + { auto: true }, + ], +}); + +export { expect } from "@playwright/test" \ No newline at end of file diff --git a/tests/e2e/web/fixtures/deleteUserFixture.ts b/tests/e2e/web/fixtures/deleteUserFixture.ts index b5f2609d..b874f544 100644 --- a/tests/e2e/web/fixtures/deleteUserFixture.ts +++ b/tests/e2e/web/fixtures/deleteUserFixture.ts @@ -2,12 +2,12 @@ import {test as base} from '@playwright/test'; import axios from 'axios'; import {config} from '../SPEC_CONFIG'; -const baseUrl = 'http://localhost:9099/identitytoolkit.googleapis.com/v1'; +// const baseUrl = 'http://localhost:9099/identitytoolkit.googleapis.com/v1'; async function deleteUser(email: string, password: string) { try { const login = await axios.post( - `${baseUrl}/accounts:signInWithPassword?key=fake-api-key`, + `${config.FIREBASE_URL.BASE}${config.FIREBASE_URL.SIGN_IN_PASSWORD}`, { email, password, @@ -16,7 +16,7 @@ async function deleteUser(email: string, password: string) { ); await axios.post( - `${baseUrl}/accounts:delete?key=fake-api-key`, + `${config.FIREBASE_URL.BASE}${config.FIREBASE_URL.DELETE}`, { idToken: login.data.idToken } ); } catch (err: any) { diff --git a/tests/e2e/web/pages/AuthPage.ts b/tests/e2e/web/pages/AuthPage.ts index 769c0672..5e0567d1 100644 --- a/tests/e2e/web/pages/AuthPage.ts +++ b/tests/e2e/web/pages/AuthPage.ts @@ -1,54 +1,54 @@ import { expect, Locator, Page } from '@playwright/test'; //sets up of all the functions that signin tests will use. -export class AuthPage{ -private readonly signInLink: Locator; -private readonly signUpButton: Locator; -private readonly emailField: Locator; -private readonly passwordField: Locator; -private readonly signInWithEmailButton: Locator; -private readonly signInWithGoogleButton: Locator; -private readonly signUpWithEmailButton: Locator; +export class AuthPage { + private readonly signInLink: Locator; + private readonly signUpButton: Locator; + private readonly emailField: Locator; + private readonly passwordField: Locator; + private readonly signInWithEmailButton: Locator; + private readonly signInWithGoogleButton: Locator; + private readonly signUpWithEmailButton: Locator; -constructor(public readonly page: Page) { - this.signInLink=page.getByRole('link', { name: 'Sign in' }); - this.signUpButton=page.getByRole('button', {name: 'Sign up'}); - this.emailField=page.getByLabel('Email'); - this.passwordField=page.getByLabel('Password'); - this.signInWithEmailButton=page.getByRole('button', {name: 'Sign in with Email'}); - this.signInWithGoogleButton=page.getByRole('button', {name: 'Google'}); - this.signUpWithEmailButton=page.getByRole('button', {name: 'Sign up with Email'}); -} + constructor(public readonly page: Page) { + this.signInLink = page.getByRole('link', { name: 'Sign in' }); + this.signUpButton = page.getByRole('button', { name: 'Sign up' }); + this.emailField = page.getByLabel('Email'); + this.passwordField = page.getByLabel('Password'); + this.signInWithEmailButton = page.getByRole('button', { name: 'Sign in with Email' }); + this.signInWithGoogleButton = page.getByRole('button', { name: 'Google' }); + this.signUpWithEmailButton = page.getByRole('button', { name: 'Sign up with Email' }); + } -async clickSignInLink() { - await this.signInLink.click(); -} + async clickSignInLink() { + await this.signInLink.click(); + } -async clickSignUpButton() { - await this.signUpButton.click(); -} + async clickSignUpButton() { + await this.signUpButton.click(); + } -async clickSignInWithEmailButton() { - await this.signInWithEmailButton.click(); -} + async clickSignInWithEmailButton() { + await this.signInWithEmailButton.click(); + } -async clickSignInWithGoogleButton() { - await this.signInWithGoogleButton.click(); -} + async clickSignInWithGoogleButton() { + await this.signInWithGoogleButton.click(); + } -async clickSignUpWithEmailButton() { - await this.signUpWithEmailButton.click(); -} + async clickSignUpWithEmailButton() { + await this.signUpWithEmailButton.click(); + } -async fillEmailField(email: string) { - await expect(this.emailField).toBeVisible(); - await this.emailField.fill(email); -} + async fillEmailField(email: string) { + await expect(this.emailField).toBeVisible(); + await this.emailField.fill(email); + } -async fillPasswordField(password: string) { - await expect(this.passwordField).toBeVisible(); - await this.passwordField.fill(password); -} + async fillPasswordField(password: string) { + await expect(this.passwordField).toBeVisible(); + await this.passwordField.fill(password); + } -} +}; diff --git a/tests/e2e/web/pages/homePage.ts b/tests/e2e/web/pages/homePage.ts new file mode 100644 index 00000000..73989b5b --- /dev/null +++ b/tests/e2e/web/pages/homePage.ts @@ -0,0 +1,30 @@ +import { expect, Locator, Page } from "@playwright/test"; + +export class HomePage { + private readonly homePageLink: Locator; + private readonly aboutLink: Locator; + private readonly faqLink: Locator; + private readonly voteLink: Locator; + private readonly signUpButton: Locator; + private readonly signInLink: Locator; + private readonly closeButton: Locator; + + constructor(public readonly page: Page) { + this.homePageLink = page.getByText('Compass dev', { exact: true }); + this.aboutLink = page.locator('span:has-text("About")'); + this.faqLink = page.getByText('FAQ', { exact: true }); + this.voteLink = page.getByText('Vote', { exact: true }); + this.signUpButton = page.locator('button').filter({ hasText: 'Sign up' }).first(); + this.signInLink = page.locator('span:has-text("Sign in")'); + this.closeButton = page.getByRole('button', { name: 'Close' }); + }; + + async gotToHomePage() { + await this.page.goto('/'); + }; + + async clickSignUpButton() { + await expect(this.signUpButton).toBeVisible(); + await this.signUpButton.click(); + }; +}; \ No newline at end of file diff --git a/tests/e2e/web/pages/onboardingPage.ts b/tests/e2e/web/pages/onboardingPage.ts new file mode 100644 index 00000000..7b2ab7ad --- /dev/null +++ b/tests/e2e/web/pages/onboardingPage.ts @@ -0,0 +1,49 @@ +import { expect, Locator, Page } from "@playwright/test"; + +export class OnboardingPage { + private readonly continueButton: Locator; + private readonly skipOnboardingLink: Locator; + private readonly backButton: Locator; + private readonly getStartedButton: Locator; + private readonly exploreProfilesNowButton: Locator; + private readonly refineProfileButton: Locator; + + constructor(public readonly page: Page) { + this.continueButton = page.getByRole('button', { name: 'Continue', exact: true }); + this.skipOnboardingLink = page.getByRole('button', { name: 'Skip onboarding', exact: true }); + this.backButton = page.getByRole('button', { name: 'Back' }); + this.getStartedButton = page.getByRole('button', { name: 'Get started' }); + this.exploreProfilesNowButton = page.getByRole('button', { name: 'Explore Profiles Now', exact: true }); + this.refineProfileButton = page.getByRole('button', { name: 'Refine Profile', exact: true }); + }; + + async clickContinueButton() { + await expect(this.continueButton).toBeVisible(); + await this.continueButton.click(); + }; + + async clickBackButton() { + await expect(this.backButton).toBeVisible(); + await this.backButton.click(); + }; + + async clickSkipOnboardingButton() { + await expect(this.skipOnboardingLink).toBeVisible(); + await this.skipOnboardingLink.click(); + }; + + async clickGetStartedButton() { + await expect(this.getStartedButton).toBeVisible(); + await this.getStartedButton.click(); + }; + + async clickExploreProfilesNowButton() { + await expect(this.exploreProfilesNowButton).toBeVisible(); + await this.exploreProfilesNowButton.click(); + }; + + async clickRefineProfileButton() { + await expect(this.refineProfileButton).toBeVisible(); + await this.refineProfileButton.click(); + }; +}; \ No newline at end of file diff --git a/tests/e2e/web/pages/profilePage.ts b/tests/e2e/web/pages/profilePage.ts new file mode 100644 index 00000000..e8d2ad05 --- /dev/null +++ b/tests/e2e/web/pages/profilePage.ts @@ -0,0 +1,287 @@ +import { expect, Locator, Page } from "@playwright/test"; +import { Socials } from "../utils/accountInformation"; + +type ProfileDropdownOptions = + | "Public" + | "Private" + | "Disable"; + +export class ProfilePage { + private readonly startAnsweringButton: Locator; + private readonly doThisLaterLink: Locator; + private readonly closeButton: Locator; + private readonly shareButton: Locator; + private readonly editProfileButton: Locator; + private readonly profileOptionsDropdown: Locator; + private readonly listProfilePubliclyDropdownOption: Locator; + private readonly limitProfileToMembersDropdownOption: Locator; + private readonly disableProfileDropdownOption: Locator; + private readonly displayNameAndAgeSection: Locator; + private readonly genderLocationHightInInchesSection: Locator; + private readonly politicalAboutSection: Locator; + private readonly relegiousAboutSection: Locator; + private readonly interestsAboutSection: Locator; + private readonly causesAboutSection: Locator; + private readonly personalityAboutSection: Locator; + private readonly ethnicityAboutSection: Locator; + private readonly dietAboutSection: Locator; + private readonly languagesAboutSection: Locator; + private readonly seekingAboutSection: Locator; + private readonly relationshipTypeAboutSection: Locator; + private readonly relationshipStatusAboutSection: Locator; + private readonly educationAboutSection: Locator; + private readonly occupationAboutSection: Locator; + private readonly workAreaAboutSection: Locator; + private readonly smokerAboutSection: Locator; + private readonly notDrinkerAboutSection: Locator; + private readonly drinkerAboutSection: Locator; + private readonly wantsKidsAboutSection: Locator; + private readonly lastOnlineAboutSection: Locator; + private readonly bigFivePersonalityTraitsAboutSection: Locator; + private readonly hasKidsAboutSection: Locator; + private readonly socialMediaSection: Locator; + private readonly bioSection: Locator; + private readonly bioOptionsDropdown: Locator; + private readonly editBioDropdownOptions: Locator; + private readonly deleteBioDropdownOptions: Locator; + + constructor(public readonly page: Page) { + this.startAnsweringButton = page.getByRole('button', {}); + this.doThisLaterLink = page.getByRole('button', {}); + this.closeButton = page.getByRole('button', { name: 'Close' }); + this.shareButton = page.getByRole('button', { name: 'Share' }); + this.editProfileButton = page.getByTestId('profile-edit'); + this.profileOptionsDropdown = page.getByTestId('profile-options'); + this.listProfilePubliclyDropdownOption = page.getByText('List Profile Publicly', { exact: true }); + this.limitProfileToMembersDropdownOption = page.getByText('Limit to Members Only', { exact: true }); + this.disableProfileDropdownOption = page.getByText('Disable profile', { exact: true }); + this.displayNameAndAgeSection = page.getByTestId('profile-display-name-age'); + this.genderLocationHightInInchesSection = page.getByTestId('profile-gender-location-height-inches'); + this.politicalAboutSection = page.getByTestId('profile-about-political'); + this.relegiousAboutSection = page.getByTestId('profile-about-religious'); + this.interestsAboutSection = page.getByTestId('profile-about-interests'); + this.causesAboutSection = page.getByTestId('profile-about-causes'); + this.personalityAboutSection = page.getByTestId('profile-about-personality'); + this.ethnicityAboutSection = page.getByTestId('profile-about-ethnicity'); + this.dietAboutSection = page.getByTestId('profile-about-diet'); + this.languagesAboutSection = page.getByTestId('profile-about-languages'); + this.seekingAboutSection = page.getByTestId('profile-about-seeking'); + this.relationshipTypeAboutSection = page.getByTestId('profile-about-relationship-type'); + this.relationshipStatusAboutSection = page.getByTestId('profile-about-relationship-status'); + this.educationAboutSection = page.getByTestId('profile-about-education'); + this.occupationAboutSection = page.getByTestId('profile-about-occupation'); + this.workAreaAboutSection = page.getByTestId('profile-about-work-area'); + this.smokerAboutSection = page.getByTestId('profile-about-smoker'); + this.notDrinkerAboutSection = page.getByTestId('profile-about-not-drink'); + this.drinkerAboutSection = page.getByTestId('profile-about-drinker'); + this.wantsKidsAboutSection = page.getByTestId('profile-about-wants-kids'); + this.lastOnlineAboutSection = page.getByTestId('profile-about-wants-last-online'); + this.bigFivePersonalityTraitsAboutSection = page.getByTestId('profile-about-big-five-personality-traits'); + this.hasKidsAboutSection = page.getByTestId('profile-about-has-kids'); + this.socialMediaSection = page.getByTestId('profile-social-media-accounts'); + this.bioSection = page.getByTestId('profile-bio'); + this.bioOptionsDropdown = page.getByTestId('profile-bio-options'); + this.editBioDropdownOptions = page.getByText('Edit', { exact: true }); + this.deleteBioDropdownOptions = page.getByText('Delete', { exact: true }); + }; + + async clickCloseButton() { + await expect(this.closeButton).toBeInViewport(); + await this.closeButton.click(); + }; + + async clickStartAnsweringButton() { + await expect(this.startAnsweringButton).toBeVisible(); + await this.startAnsweringButton.click(); + }; + + async clickDoThisLaterButton() { + await expect(this.doThisLaterLink).toBeVisible(); + await this.doThisLaterLink.click(); + }; + + async clickShareButton() { + await expect(this.shareButton).toBeVisible(); + await this.shareButton.click(); + }; + + async clickEditProfileButton() { + await expect(this.editProfileButton).toBeVisible(); + await this.editProfileButton.click(); + }; + + async selectOptionFromProfileDropdown(option: ProfileDropdownOptions) { + await expect(this.profileOptionsDropdown).toBeVisible(); + await this.profileOptionsDropdown.click(); + + if (option === "Public") { + await expect(this.listProfilePubliclyDropdownOption).toBeVisible(); + await this.listProfilePubliclyDropdownOption.click(); + } else if (option === "Disable") { + await expect(this.disableProfileDropdownOption).toBeVisible(); + await this.disableProfileDropdownOption.click(); + } else if (option === "Private") { + await expect(this.limitProfileToMembersDropdownOption).toBeVisible(); + await this.limitProfileToMembersDropdownOption.click(); + } + }; + + async verifyDisplayNameAndAge(displayName?: string, age?: string) { + await expect(this.displayNameAndAgeSection).toBeVisible() + const textContent = await this.displayNameAndAgeSection.textContent(); + if (displayName) await expect(textContent?.toLowerCase()).toContain(displayName.toLowerCase()); + if (age) await expect(textContent?.toLowerCase()).toContain(age.toLowerCase()); + }; + + async verifyGenderLocationHeight(gender?: string, location?: string, heightFeet?: string, heightInches?: string) { + await expect(this.genderLocationHightInInchesSection).toBeVisible() + const textContent = await this.genderLocationHightInInchesSection.textContent(); + if (gender) await expect(textContent?.toLowerCase()).toContain(gender.toLowerCase()); + if (location) await expect(textContent?.toLowerCase()).toContain(location.toLowerCase()); + if (heightFeet) await expect(textContent?.toLowerCase()).toContain(heightFeet.toLowerCase()); + if (heightInches) await expect(textContent?.toLowerCase()).toContain(heightInches.toLowerCase()); + }; + + async verifyEthnicityOrigin(origin: string) { + await expect(this.ethnicityAboutSection).toBeVisible() + const textContent = await this.ethnicityAboutSection.textContent(); + await expect(textContent?.toLowerCase()).toContain(origin.toLowerCase()); + }; + + async verifyIntrestedInConnectingWith(gender?: string, minAge?: string, maxAge?: string) { + await expect(this.seekingAboutSection).toBeVisible() + const textContent = await this.seekingAboutSection.textContent(); + if (gender) await expect(textContent?.toLowerCase()).toContain(gender.toLowerCase()); + if (minAge) await expect(textContent?.toLowerCase()).toContain(minAge.toLowerCase()); + if (maxAge) await expect(textContent?.toLowerCase()).toContain(maxAge.toLowerCase()); + }; + + async verifyRelationShipTypeAndInterest(type?: string, interest?: string) { + await expect(this.relationshipTypeAboutSection).toBeVisible() + const textContent = await this.relationshipTypeAboutSection.textContent(); + if (type) await expect(textContent?.toLowerCase()).toContain(type.toLowerCase()); + if (interest) await expect(textContent?.toLowerCase()).toContain(interest.toLowerCase()); + }; + + async verifyRelationshipStatus(status: string | undefined) { + if (!status) return; + await expect(this.relationshipStatusAboutSection).toBeVisible() + const textContent = await this.relationshipStatusAboutSection.textContent(); + await expect(textContent?.toLowerCase()).toContain(status.toLowerCase()); + }; + + async verifyCurrentNumberOfKids(numberOfKids: string | undefined) { + if (!numberOfKids) return; + await expect(this.hasKidsAboutSection).toBeVisible() + const textContent = await this.hasKidsAboutSection.textContent(); + await expect(textContent?.toLowerCase()).toContain(numberOfKids.toLowerCase()); + }; + + async verifyWantChildrenExpectation(expectation: string | undefined) { + if (!expectation) return; + await expect(this.wantsKidsAboutSection).toBeVisible() + const textContent = await this.wantsKidsAboutSection.textContent(); + await expect(textContent?.toLowerCase()).toContain(expectation.toLowerCase()); + }; + + async verifyInterests(interest: string[] | undefined) { + if (!interest || interest.length === 0) return; + await expect(this.interestsAboutSection).toBeVisible() + const textContent = await this.interestsAboutSection.textContent(); + for (let i = 0; i < interest.length; i++) { + await expect(textContent?.toLowerCase()).toContain(interest[i].toLowerCase()); + }; + }; + + async verifyCauses(causes: string[] | undefined) { + if (!causes || causes.length === 0) return; + await expect(this.causesAboutSection).toBeVisible() + const textContent = await this.causesAboutSection.textContent(); + for (let i = 0; i < causes.length; i++) { + await expect(textContent?.toLowerCase()).toContain(causes[i].toLowerCase()); + }; + }; + + async verifyEducationLevelAndUniversity(educationLevel?: string, university?: string) { + await expect(this.educationAboutSection).toBeVisible() + const textContent = await this.educationAboutSection.textContent(); + if (educationLevel) await expect(textContent?.toLowerCase()).toContain(educationLevel.toLowerCase()); + if (university) await expect(textContent?.toLowerCase()).toContain(university.toLowerCase()); + }; + + async verifyJobInformation(jobTitle?: string, company?: string) { + await expect(this.occupationAboutSection).toBeVisible() + const textContent = await this.occupationAboutSection.textContent(); + if (jobTitle) await expect(textContent?.toLowerCase()).toContain(jobTitle.toLowerCase()); + if (company) await expect(textContent?.toLowerCase()).toContain(company.toLowerCase()); + }; + + async verifyPoliticalBeliefs(belief?: string, details?: string) { + await expect(this.politicalAboutSection).toBeVisible() + const textContent = await this.politicalAboutSection.textContent(); + if (belief) await expect(textContent?.toLowerCase()).toContain(belief.toLowerCase()); + if (details) await expect(textContent?.toLowerCase()).toContain(details.toLowerCase()); + }; + + async verifyReligiousBeliefs(belief?: string, details?: string) { + await expect(this.relegiousAboutSection).toBeVisible() + const textContent = await this.relegiousAboutSection.textContent(); + if (belief) await expect(textContent?.toLowerCase()).toContain(belief.toLowerCase()); + if (details) await expect(textContent?.toLowerCase()).toContain(details.toLowerCase()); + }; + + async verifyPersonalityType(personalityType: string | undefined) { + if (!personalityType) return; + await expect(this.personalityAboutSection).toBeVisible() + const textContent = await this.personalityAboutSection.textContent(); + await expect(textContent?.toLowerCase()).toContain(personalityType.toLowerCase()); + }; + + async verifyBigFivePersonalitySection(personalityType: Record | undefined) { + if (!personalityType) return; + await expect(this.bigFivePersonalityTraitsAboutSection).toBeVisible() + const textContent = await this.bigFivePersonalityTraitsAboutSection.textContent(); + for (const [key, value] of Object.entries(personalityType)) { + await expect(textContent?.toLowerCase()).toContain(key.toLowerCase()); + await expect(textContent?.toLowerCase()).toContain(`${value}`); + }; + }; + + async verifyDiet(diet: string | undefined) { + if (!diet) return; + await expect(this.dietAboutSection).toBeVisible() + const textContent = await this.dietAboutSection.textContent(); + await expect(textContent?.toLowerCase()).toContain(diet.toLowerCase()); + }; + + async verifySmoker(smoker: boolean | undefined) { + await expect(this.smokerAboutSection).toBeVisible() + const textContent = await this.smokerAboutSection.textContent(); + if (smoker === true) await expect(textContent?.toLowerCase()).toContain("Smokes".toLowerCase()); + if (smoker === false) await expect(textContent?.toLowerCase()).toContain("Doesn't smoke".toLowerCase()); + }; + + async verifyDrinksPerMonth(drinks: string | undefined) { + await expect(this.drinkerAboutSection).toBeVisible() + const textContent = await this.drinkerAboutSection.textContent(); + await expect(textContent?.toLowerCase()).toContain(drinks); + }; + + async verifyLanguages(languages: string[] | undefined) { + if (!languages || languages.length === 0) return; + await expect(this.languagesAboutSection).toBeVisible() + const textContent = await this.languagesAboutSection.textContent(); + for (let i = 0; i < languages.length; i++) { + await expect(textContent?.toLowerCase()).toContain(languages[i].toLowerCase()); + }; + }; + + async verifySocialMedia(socialMedia: Socials [] | undefined) { + if (!socialMedia || socialMedia.length === 0) return; + await expect(this.socialMediaSection).toBeVisible() + const textContent = await this.socialMediaSection.textContent(); + for (let i = 0; i < socialMedia.length; i++) { + await expect(textContent?.toLowerCase()).toContain(socialMedia[i].urlOrUsername.toLowerCase()); + }; + }; +}; \ No newline at end of file diff --git a/tests/e2e/web/pages/signUpPage.ts b/tests/e2e/web/pages/signUpPage.ts new file mode 100644 index 00000000..4749fc37 --- /dev/null +++ b/tests/e2e/web/pages/signUpPage.ts @@ -0,0 +1,656 @@ +import { expect, Locator, Page } from "@playwright/test"; +import { + RELATIONSHIP_CHOICES, + RELATIONSHIP_STATUS_CHOICES, + ROMANTIC_CHOICES, + POLITICAL_CHOICES, + DIET_CHOICES, + EDUCATION_CHOICES, + RELIGION_CHOICES, + LANGUAGE_CHOICES, + RACE_CHOICES, + MBTI_CHOICES, +} from "../../../../web/components/filters/choices"; + +export type Gender = 'Woman' | 'Man' | 'Other'; +export type InterestedIn = 'Women' | 'Men' | 'Other'; +export type ConnectionType = keyof typeof RELATIONSHIP_CHOICES; +export type RelationshipStatus = keyof typeof RELATIONSHIP_STATUS_CHOICES; +export type RelationshipStyle = keyof typeof ROMANTIC_CHOICES; +export type ChildrenExpectation = "Strongly against" | "Against" | "Neutral" | "For" | "Strongly for"; +export type PoliticalBeliefs = keyof typeof POLITICAL_CHOICES; +export type Diet = keyof typeof DIET_CHOICES; +export type Education = keyof typeof EDUCATION_CHOICES; +export type Religion = keyof typeof RELIGION_CHOICES; +export type Language = keyof typeof LANGUAGE_CHOICES; +export type Ethnicity = keyof typeof RACE_CHOICES; +export type Personality = keyof typeof MBTI_CHOICES; +export type Interests = 'Chess' | 'Games' | 'Joy' | 'Livres'; +export type Causes = 'Animal Rights' | 'Feminism'; +export type Platforms = + | 'Website' + | 'Twitter/X' + | 'Discord' + | 'Bluesky' + | 'Mastodon' + | 'Substack' + | 'Paypal' + | 'Instagram' + | 'GitHub' + | 'LinkedIn' + | 'Facebook' + | 'Patreon' + | 'OkCupid' + | 'Calendly' + | 'Dating Doc' + | 'Friendship Doc' + | 'Connection Doc' + | 'Work Doc' + | 'Spotify' + +export class SignUpPage { + private readonly displayNameField: Locator; + private readonly usernameField: Locator; + private readonly nextButton: Locator; + private readonly bioField: Locator; + private readonly locationField: Locator; + private readonly ageField: Locator; + private readonly feetHeightField: Locator; + private readonly inchesHeightField: Locator; + private readonly centimetersHeightField: Locator; + private readonly interestedInWomenCheckbox: Locator; + private readonly interestedInMenCheckbox: Locator; + private readonly interestedInOtherCheckbox: Locator; + private readonly minAgeOption: Locator; + private readonly maxAgeOption: Locator; + private readonly currentNumberOfKidsField: Locator; + private readonly stronglyDisagreeOnWantingKids: Locator; + private readonly disagreeOnWantingKids: Locator; + private readonly neutralOnWantingKids: Locator; + private readonly agreeOnWantingKids: Locator; + private readonly stronglyAgreeOnWantingKids: Locator; + private readonly addInterestsField: Locator; + private readonly addInterestsButton: Locator; + private readonly addCausesField: Locator; + private readonly addCausesButton: Locator; + private readonly universityField: Locator; + private readonly jobTitleField: Locator; + private readonly companyField: Locator; + private readonly universityCheckbox: Locator; + private readonly addWorkAreaField: Locator; + private readonly addWorkAreaButton: Locator; + private readonly politicalBeliefDetailsField: Locator; + private readonly religiousBeliefsDetailsField: Locator; + private readonly opennessPersonalitySlider: Locator; + private readonly opennessPersonalityValue: Locator; + private readonly conscientiousnessPersonalitySlider: Locator; + private readonly conscientiousnessPersonalityValue: Locator; + private readonly extraversionPersonalitySlider: Locator; + private readonly extraversionPersonalityValue: Locator; + private readonly agreeablenessPersonalitySlider: Locator; + private readonly agreeablenessPersonalityValue: Locator; + private readonly neuroticismPersonalitySlider: Locator; + private readonly neuroticismPersonalityValue: Locator; + private readonly smokerField: Locator; + private readonly nonSmokerField: Locator; + private readonly alcoholConsumedPerMonthField: Locator; + private readonly socialPlatformSelectionField: Locator; + private readonly socialPlatformSearchField: Locator; + private readonly addSocialPlatformField: Locator; + private readonly addSocialPlatformButton: Locator; + private readonly photoUploadButton: Locator; + private readonly saveButton: Locator; + + constructor(public readonly page: Page) { + this.displayNameField = page.getByPlaceholder('Display name'); + this.usernameField = page.getByPlaceholder('Username'); + this.nextButton = page.getByRole('button', { name: 'Next', exact: true }); + this.bioField = page.getByRole('paragraph').filter({ hasText: /^$/ }); + this.locationField = page.getByPlaceholder('Search city...'); + this.ageField = page.getByPlaceholder('Age', { exact: true }); + this.feetHeightField = page.getByTestId('height-feet'); + this.inchesHeightField = page.getByTestId('height-inches'); + this.centimetersHeightField = page.getByTestId('height-centimeters'); + this.interestedInWomenCheckbox = page.getByRole('checkbox', { name: 'Women', exact: true }); + this.interestedInMenCheckbox = page.getByRole('checkbox', { name: 'Men', exact: true }); + this.interestedInOtherCheckbox = page.getByRole('checkbox', { name: 'Other' }).nth(1); + this.minAgeOption = page.getByTestId('pref-age-min'); + this.maxAgeOption = page.getByTestId('pref-age-max'); + this.currentNumberOfKidsField = page.getByTestId('current-number-of-kids'); + this.stronglyDisagreeOnWantingKids = page.locator('[id="headlessui-radiogroup-option-:r49:"]'); + this.disagreeOnWantingKids = page.locator('[id="headlessui-radiogroup-option-:r4b:"]'); + this.neutralOnWantingKids = page.locator('[id="headlessui-radiogroup-option-:r4d:"]'); + this.agreeOnWantingKids = page.locator('[id="headlessui-radiogroup-option-:r4f:"]'); + this.stronglyAgreeOnWantingKids = page.locator('[id="headlessui-radiogroup-option-:r4h:"]'); + this.addInterestsField = page.getByRole('textbox', { name: 'Search or add' }).first(); + this.addInterestsButton = page.getByRole('button', { name: 'Add' }).first(); + this.addCausesField = page.getByRole('textbox', { name: 'Search or add' }).nth(1); + this.addCausesButton = page.getByRole('button', { name: 'Add' }).nth(1); + this.universityField = page.getByTestId('university'); + this.jobTitleField = page.getByTestId('job-title'); + this.companyField = page.getByTestId('company'); + this.universityCheckbox = page.getByRole('checkbox', { name: 'University' }); + this.addWorkAreaField = page.getByRole('textbox', { name: 'Search or add' }).nth(2); + this.addWorkAreaButton = page.getByRole('button', { name: 'Add' }).nth(2); + this.politicalBeliefDetailsField = page.getByTestId('political-belief-details'); + this.religiousBeliefsDetailsField = page.getByTestId('religious-belief-details'); + this.opennessPersonalitySlider = page.getByRole('slider').first(); + this.opennessPersonalityValue = page.getByTestId('openness-value'); + this.conscientiousnessPersonalitySlider = page.getByRole('slider').nth(1); + this.conscientiousnessPersonalityValue = page.getByTestId('conscientiousness-value'); + this.extraversionPersonalitySlider = page.getByRole('slider').nth(2); + this.extraversionPersonalityValue = page.getByTestId('extraversion-value'); + this.agreeablenessPersonalitySlider = page.getByRole('slider').nth(3); + this.agreeablenessPersonalityValue = page.getByTestId('agreeableness-value'); + this.neuroticismPersonalitySlider = page.getByRole('slider').nth(4); + this.neuroticismPersonalityValue = page.getByTestId('neuroticism-value'); + this.smokerField = page.getByText('Yes', { exact: true }); + this.nonSmokerField = page.getByText('No', { exact: true }); + this.alcoholConsumedPerMonthField = page.getByTestId('alcohol-consumed-per-month'); + this.socialPlatformSelectionField = page.getByRole('button', { name: 'Platform' }); + this.socialPlatformSearchField = page.getByRole('textbox', { name: 'Search...' }); + this.addSocialPlatformField = page.getByRole('textbox', { name: 'URL' }); + this.addSocialPlatformButton = page.locator('button').filter({ hasText: 'Add' }).nth(3); + this.photoUploadButton = page.getByTestId('profile-upload-photo'); + this.saveButton = page.getByRole('button', { name: 'Save' }); + }; + + async fillUsername(username: string) { + await expect(this.usernameField).toBeVisible(); + await this.usernameField.fill(username); + }; + + async fillDisplayName(displayName: string) { + await expect(this.displayNameField).toBeVisible(); + await this.displayNameField.fill(displayName); + }; + + async fillBio(bio: string | undefined) { + if (!bio) return; + await expect(this.bioField).toBeVisible(); + await this.bioField.fill(bio); + }; + + async fillLocation(location: string | undefined) { + if (!location) return; + await expect(this.locationField).toBeVisible(); + await this.locationField.fill(location); + }; + + async chooseGender(gender: Gender | undefined) { + await expect(this.page.locator(`span:has-text("${gender}")`)).toBeVisible(); + await this.page.locator(`span:has-text("${gender}")`).click(); + await expect(this.page.locator(`span:has-text("${gender}")`)).toBeChecked(); + }; + + async fillAge(age: string | undefined) { + if (!age) return; + await expect(this.ageField).toBeVisible(); + await this.ageField.fill(age); + }; + + async fillHeight(height: {feet?: string, inches?: string, centimeters?: string}) { + const {feet, inches, centimeters} = height; + + if ((!feet || !inches) && !centimeters) return; + + if (centimeters) { + await expect(this.centimetersHeightField).toBeVisible(); + await this.centimetersHeightField.fill(centimeters); + } else if (feet && inches){ + await expect(this.feetHeightField).toBeVisible(); + await expect(this.inchesHeightField).toBeVisible(); + await this.feetHeightField.fill(feet); + await this.inchesHeightField.fill(inches); + } + }; + + async fillHeightFeetInches(feet: string | undefined, inches: string | undefined) { + if (!feet || !inches) return; + await expect(this.feetHeightField).toBeVisible(); + await expect(this.inchesHeightField).toBeVisible(); + await this.feetHeightField.fill(feet); + await this.inchesHeightField.fill(inches); + }; + + async fillHeightCentimeters(centimeters: string | undefined) { + if (!centimeters) return; + await expect(this.centimetersHeightField).toBeVisible(); + await this.centimetersHeightField.fill(centimeters); + }; + + async fillEthnicity(ethnicity: Ethnicity | undefined) { + if (ethnicity === 'Other') { + await expect(this.page.locator('label').filter({ hasText: `${ethnicity}` }).first()).toBeVisible(); + await this.page.locator('label').filter({ hasText: `${ethnicity}` }).first().click(); + await expect(this.page.locator('label').filter({ hasText: `${ethnicity}` }).first()).toBeChecked(); + } else { + await expect(this.page.getByText(`${ethnicity}`, { exact: true })).toBeVisible(); + await this.page.getByText(`${ethnicity}`, { exact: true }).click(); + await expect(this.page.getByText(`${ethnicity}`, { exact: true })).toBeChecked(); + }; + }; + + async fillInterestedInConnectingWith(interestedIn: InterestedIn | undefined) { + if (interestedIn === "Men") { + await expect(this.interestedInMenCheckbox).toBeVisible(); + await this.interestedInMenCheckbox.click() + await expect(this.interestedInMenCheckbox).toBeChecked(); + } else if (interestedIn === "Women") { + await expect(this.interestedInWomenCheckbox).toBeVisible(); + await this.interestedInWomenCheckbox.click() + await expect(this.interestedInWomenCheckbox).toBeChecked(); + } else { + await expect(this.interestedInOtherCheckbox).toBeVisible(); + await this.interestedInOtherCheckbox.click() + await expect(this.interestedInOtherCheckbox).toBeChecked(); + } + + }; + + async fillAgeRangeInterest(min: string | undefined, max?: string | undefined) { + if (!min || !max) return; + await expect(this.minAgeOption).toBeVisible(); + await expect(this.maxAgeOption).toBeVisible(); + await this.minAgeOption.selectOption(min); + if (max){ + await this.maxAgeOption.selectOption(max); + }; + }; + + async setConnectionType(type: ConnectionType | undefined) { + await expect(this.page.getByLabel(`${type}`, { exact: true})).toBeVisible(); + await this.page.getByLabel(`${type}`, { exact: true}).click(); + await expect(this.page.getByLabel(`${type}`, { exact: true})).toBeChecked(); + }; + + async setRelationshipStatus(status: RelationshipStatus | undefined) { + await expect(this.page.getByLabel(`${status}`, { exact: true})).toBeVisible(); + await this.page.getByLabel(`${status}`, { exact: true}).click(); + await expect(this.page.getByLabel(`${status}`, { exact: true})).toBeChecked(); + }; + + async setRelationshipStyle(style: RelationshipStyle | undefined) { + await expect(this.page.getByLabel(`${style}`, { exact: true})).toBeVisible(); + await this.page.getByLabel(`${style}`, { exact: true}).click(); + await expect(this.page.getByLabel(`${style}`, { exact: true})).toBeChecked(); + }; + + async fillCurrentNumberOfChildren(numberOfKids: string | undefined) { + if (!numberOfKids) return; + await expect(this.currentNumberOfKidsField).toBeVisible(); + await this.currentNumberOfKidsField.fill(numberOfKids); + }; + + async setWantChildrenExpectation(expectation: ChildrenExpectation | undefined) { + if (expectation === "Strongly against") { + await expect(this.stronglyDisagreeOnWantingKids).toBeVisible(); + await this.stronglyDisagreeOnWantingKids.click(); + await expect(this.stronglyDisagreeOnWantingKids).toBeChecked(); + } else if (expectation === "Against") { + await expect(this.disagreeOnWantingKids).toBeVisible(); + await this.disagreeOnWantingKids.click(); + await expect(this.disagreeOnWantingKids).toBeChecked(); + } else if (expectation === "Neutral") { + await expect(this.neutralOnWantingKids).toBeVisible(); + await this.neutralOnWantingKids.click(); + await expect(this.neutralOnWantingKids).toBeChecked(); + } else if (expectation === "For") { + await expect(this.agreeOnWantingKids).toBeVisible(); + await this.agreeOnWantingKids.click(); + await expect(this.agreeOnWantingKids).toBeChecked(); + } else { + await expect(this.stronglyAgreeOnWantingKids).toBeVisible(); + await this.stronglyAgreeOnWantingKids.click(); + await expect(this.stronglyAgreeOnWantingKids).toBeChecked(); + } + }; + + async setInterests(interest: (Interests | string)[] | undefined) { + if (!interest || interest.length === 0) return; + + for (let i = 0; i < interest.length; i++) { + const checkbox = this.page.getByRole('checkbox', { name: `${interest[i]}` }); + const isExisting = await checkbox.count() > 0; + + if (isExisting) { + await expect(this.page.getByRole('checkbox', { name: `${interest[i]}` })).toBeVisible(); + await this.page.getByRole('checkbox', { name: `${interest[i]}` }).click(); + } else { + await expect(this.addInterestsField).toBeVisible(); + await expect(this.addInterestsButton).toBeVisible(); + await this.addInterestsField.fill(interest[i]); + await this.addInterestsButton.click(); + }; + await expect(this.page.getByRole('checkbox', { name: `${interest[i]}` })).toBeVisible(); + await expect(this.page.getByRole('checkbox', { name: `${interest[i]}` })).toBeChecked(); + } + }; + + async setCauses(cause: (Causes | string)[] | undefined) { + if (!cause || cause?.length === 0) return; + + for (let i = 0; i < cause.length; i++) { + const checkbox = this.page.getByRole('checkbox', { name: `${cause[i]}` }) + const isExisting = await checkbox.count() > 0 + + if (isExisting) { + await expect(this.page.getByRole('checkbox', { name: `${cause[i]}` })).toBeVisible(); + await this.page.getByRole('checkbox', { name: `${cause[i]}` }).click(); + } else { + await expect(this.addCausesField).toBeVisible(); + await expect(this.addCausesButton).toBeVisible(); + await this.addCausesField.fill(cause[i]); + await this.addCausesButton.click(); + }; + await expect(this.page.getByRole('checkbox', { name: `${cause[i]}` })).toBeVisible(); + await expect(this.page.getByRole('checkbox', { name: `${cause[i]}` })).toBeChecked(); + }; + }; + + async setHighestEducationLevel(education: Education | undefined) { + await expect(this.page.getByText(`${education}`, { exact: true })).toBeVisible(); + await this.page.getByText(`${education}`, { exact: true }).click(); + await expect(this.page.getByText(`${education}`, { exact: true })).toBeChecked(); + }; + + async fillUniversity(university: string | undefined) { + if (!university) return; + await expect(this.universityField).toBeVisible(); + await this.universityField.fill(university); + }; + + async fillJobTitle(jobTitle: string | undefined) { + if (!jobTitle) return; + await expect(this.jobTitleField).toBeVisible(); + await this.jobTitleField.fill(jobTitle); + }; + + async fillCompany(company: string | undefined) { + if (!company) return; + await expect(this.companyField).toBeVisible(); + await this.companyField.fill(company); + }; + + async setWorkArea(workArea: string[] | undefined) { + if (!workArea || workArea?.length === 0) return; + + for (let i = 0; i < workArea.length; i++) { + const checkbox = this.page.getByLabel(`${workArea[i]}`, { exact: true}) + const isExisting = await checkbox.count() > 0 + + if (isExisting) { + await expect(this.page.getByLabel(`${workArea[i]}`, { exact: true})).toBeVisible(); + await this.page.getByLabel(`${workArea[i]}`, { exact: true}).click(); + } else { + await expect(this.addWorkAreaField).toBeVisible(); + await expect(this.addWorkAreaButton).toBeVisible(); + await this.addWorkAreaField.fill(workArea[i]); + await this.addWorkAreaButton.click(); + }; + await expect(this.page.getByLabel(`${workArea[i]}`, { exact: true})).toBeVisible(); + await expect(this.page.getByLabel(`${workArea[i]}`, { exact: true})).toBeChecked(); + }; + }; + + async setPoliticalBeliefs(politicalBeliefs?: PoliticalBeliefs | undefined, details?: string | undefined) { + if (politicalBeliefs) { + await expect(this.page.getByRole('checkbox', { name: `${politicalBeliefs}` })).toBeVisible(); + await this.page.getByRole('checkbox', { name: `${politicalBeliefs}` }).click(); + await expect(this.page.getByRole('checkbox', { name: `${politicalBeliefs}` })).toBeChecked(); + }; + + if (details) { + await expect(this.politicalBeliefDetailsField).toBeVisible(); + await this.politicalBeliefDetailsField.fill(details); + }; + }; + + async setReligiousBeliefs(religiousBeliefs?: Religion | undefined, details?: string | undefined) { + if (religiousBeliefs && religiousBeliefs === 'Other') { + await expect(this.page.locator('label').filter({ hasText: `${religiousBeliefs}` }).nth(3)).toBeVisible(); + await this.page.locator('label').filter({ hasText: `${religiousBeliefs}` }).nth(3).click(); + await expect(this.page.locator('label').filter({ hasText: `${religiousBeliefs}` }).nth(3)).toBeChecked(); + } else { + await expect(this.page.getByRole('checkbox', { name: `${religiousBeliefs}` })).toBeVisible(); + await this.page.getByRole('checkbox', { name: `${religiousBeliefs}` }).click(); + await expect(this.page.getByRole('checkbox', { name: `${religiousBeliefs}` })).toBeChecked(); + }; + + if (details) { + await expect(this.religiousBeliefsDetailsField).toBeVisible(); + await this.religiousBeliefsDetailsField.fill(details); + }; + }; + + async setPersonalityType(personalityType: Personality | undefined) { + await expect(this.page.getByText(`${personalityType}`, { exact: true })).toBeVisible(); + await this.page.getByText(`${personalityType}`, { exact: true }).click(); + await expect(this.page.getByText(`${personalityType}`, { exact: true })).toBeChecked(); + }; + + async setOpennessPersonalityValue(value: number | undefined) { + if (!value) return; + await expect(this.opennessPersonalitySlider).toBeVisible(); + await expect(this.opennessPersonalityValue).toBeVisible(); + await this.opennessPersonalitySlider.click(); + const originalValue = await this.opennessPersonalityValue.textContent(); + if (!originalValue) return; + if (parseInt(originalValue) < value) { + while (true) { + const actualValue = await this.opennessPersonalityValue.textContent(); + if (!actualValue) break; + + if (parseInt(actualValue) >= value) { + break; + }; + await this.page.keyboard.press('ArrowRight'); + }; + }; + if (parseInt(originalValue) > value) { + while (true) { + const actualValue = await this.opennessPersonalityValue.textContent(); + if (!actualValue) break; + + if (parseInt(actualValue) <= value) { + break; + }; + await this.page.keyboard.press('ArrowLeft'); + }; + }; + }; + + async setConscientiousnessPersonalityValue(value: number | undefined) { + if (!value) return; + await expect(this.conscientiousnessPersonalitySlider).toBeVisible(); + await expect(this.conscientiousnessPersonalityValue).toBeVisible(); + await this.conscientiousnessPersonalitySlider.click(); + const originalValue = await this.conscientiousnessPersonalityValue.textContent(); + if (!originalValue) return; + if (parseInt(originalValue) < value) { + while (true) { + const actualValue = await this.conscientiousnessPersonalityValue.textContent(); + if (!actualValue) break; + + if (parseInt(actualValue) >= value) { + break; + }; + await this.page.keyboard.press('ArrowRight'); + }; + }; + if (parseInt(originalValue) > value) { + while (true) { + const actualValue = await this.conscientiousnessPersonalityValue.textContent(); + if (!actualValue) break; + + if (parseInt(actualValue) <= value) { + break; + }; + await this.page.keyboard.press('ArrowLeft'); + }; + }; + }; + + async setExtraversionPersonalityValue(value: number | undefined) { + if (!value) return; + await expect(this.extraversionPersonalitySlider).toBeVisible(); + await expect(this.extraversionPersonalityValue).toBeVisible(); + await this.extraversionPersonalitySlider.click(); + const originalValue = await this.extraversionPersonalityValue.textContent(); + if (!originalValue) return; + if (parseInt(originalValue) < value) { + while (true) { + const actualValue = await this.extraversionPersonalityValue.textContent(); + if (!actualValue) break; + + if (parseInt(actualValue) >= value) { + break; + }; + await this.page.keyboard.press('ArrowRight'); + }; + }; + if (parseInt(originalValue) > value) { + while (true) { + const actualValue = await this.extraversionPersonalityValue.textContent(); + if (!actualValue) break; + + if (parseInt(actualValue) <= value) { + break; + }; + await this.page.keyboard.press('ArrowLeft'); + }; + }; + }; + + async setAgreeablenessPersonalityValue(value: number | undefined) { + if (!value) return; + await expect(this.agreeablenessPersonalitySlider).toBeVisible(); + await expect(this.agreeablenessPersonalityValue).toBeVisible(); + await this.agreeablenessPersonalitySlider.click(); + const originalValue = await this.agreeablenessPersonalityValue.textContent(); + if (!originalValue) return; + if (parseInt(originalValue) < value) { + while (true) { + const actualValue = await this.agreeablenessPersonalityValue.textContent(); + if (!actualValue) break; + + if (parseInt(actualValue) >= value) { + break; + }; + await this.page.keyboard.press('ArrowRight'); + }; + }; + if (parseInt(originalValue) > value) { + while (true) { + const actualValue = await this.agreeablenessPersonalityValue.textContent(); + if (!actualValue) break; + + if (parseInt(actualValue) <= value) { + break; + }; + await this.page.keyboard.press('ArrowLeft'); + }; + }; + }; + + async setNeuroticismPersonalityValue(value: number | undefined) { + if (!value) return; + await expect(this.neuroticismPersonalitySlider).toBeVisible(); + await expect(this.neuroticismPersonalityValue).toBeVisible(); + await this.neuroticismPersonalitySlider.click(); + const originalValue = await this.neuroticismPersonalityValue.textContent(); + if (!originalValue) return; + if (parseInt(originalValue) < value) { + while (true) { + const actualValue = await this.neuroticismPersonalityValue.textContent(); + if (!actualValue) break; + + if (parseInt(actualValue) >= value) { + break; + }; + await this.page.keyboard.press('ArrowRight'); + }; + }; + if (parseInt(originalValue) > value) { + while (true) { + const actualValue = await this.neuroticismPersonalityValue.textContent(); + if (!actualValue) break; + + if (parseInt(actualValue) <= value) { + break; + }; + await this.page.keyboard.press('ArrowLeft'); + }; + }; + }; + + async setDietType(dietType: Diet | undefined) { + if (dietType === 'Other') { + await expect(this.page.locator('label').filter({ hasText: 'Other' }).nth(4)).toBeVisible(); + await this.page.locator('label').filter({ hasText: 'Other' }).nth(4).click(); + await expect(this.page.locator('label').filter({ hasText: 'Other' }).nth(4)).toBeChecked(); + } else { + await expect(this.page.getByRole('checkbox', { name: `${dietType}` })).toBeVisible(); + await this.page.getByRole('checkbox', { name: `${dietType}` }).click(); + await expect(this.page.getByRole('checkbox', { name: `${dietType}` })).toBeChecked(); + }; + }; + + async setIsSmoker(bool: boolean | undefined) { + if (bool) { + await expect(this.smokerField).toBeVisible(); + await this.smokerField.click(); + await expect(this.smokerField).toBeChecked(); + } else { + await expect(this.nonSmokerField).toBeVisible(); + await this.nonSmokerField.click(); + await expect(this.nonSmokerField).toBeChecked(); + }; + }; + + async fillAlcoholPerMonth(amount: string | undefined) { + if (!amount) return; + await expect(this.alcoholConsumedPerMonthField).toBeVisible(); + await this.alcoholConsumedPerMonthField.fill(amount); + }; + + async setLanguages(language: Language[] | undefined) { + if (!language || language.length === 0) return; + for (let i = 0; i < language.length; i++) { + await expect(this.page.getByRole('checkbox', { name: `${language[i]}` })).toBeVisible(); + await this.page.getByRole('checkbox', { name: `${language[i]}` }).click(); + await expect(this.page.getByRole('checkbox', { name: `${language[i]}` })).toBeChecked(); + }; + }; + + async addSocialMediaPlatform(socialMedia: {platform: Platforms, urlOrUsername: string}[] | undefined) { + if (!socialMedia) return; + for (let i = 0; i < socialMedia.length; i++) { + await expect(this.socialPlatformSelectionField).toBeVisible(); + await this.socialPlatformSelectionField.click(); + await expect(this.socialPlatformSearchField).toBeVisible(); + await this.socialPlatformSearchField.fill(socialMedia[i].platform); + await expect(this.page.getByText(`${socialMedia[i].platform}`, { exact: true })).toBeVisible(); + await this.page.getByText(`${socialMedia[i].platform}`, { exact: true }).click(); + await this.addSocialPlatformField.fill(socialMedia[i].urlOrUsername); + await this.addSocialPlatformButton.click(); + await expect(this.page.getByText(`${socialMedia[i].platform}`, { exact: true })).toBeVisible(); + await expect(this.page.locator(`input[value='${socialMedia[i].urlOrUsername}']`)).toBeVisible(); + }; + }; + + async clickNextButton() { + await expect(this.nextButton).toBeVisible(); + await this.nextButton.click(); + }; + + async uploadProfilePhoto() { + await expect(this.photoUploadButton).toBeVisible(); + await this.photoUploadButton.click(); + }; + + async saveProfileChanges() { + await expect(this.saveButton).toBeVisible(); + await this.saveButton.click(); + }; +}; \ No newline at end of file diff --git a/tests/e2e/web/specs/firebaseAccountCreationTest.ts b/tests/e2e/web/specs/firebaseAccountCreationTest.ts new file mode 100644 index 00000000..32035c5a --- /dev/null +++ b/tests/e2e/web/specs/firebaseAccountCreationTest.ts @@ -0,0 +1,15 @@ +import axios from 'axios'; +import { config } from "../SPEC_CONFIG"; + +async function setup() { + const results = await axios.post(`${config.FIREBASE_URL.BASE}${config.FIREBASE_URL.SIGNUP}`, { + email: "trial_test@email.com", + password: "trialTestPassword", + returnSecureToken: true + }); + + console.log('Auth created: ', "trial_test@email.com"); + console.log('Id: ', results.data.localId); +} + +setup() \ No newline at end of file diff --git a/tests/e2e/web/specs/onboardingFlow.spec.ts b/tests/e2e/web/specs/onboardingFlow.spec.ts new file mode 100644 index 00000000..2c94f738 --- /dev/null +++ b/tests/e2e/web/specs/onboardingFlow.spec.ts @@ -0,0 +1,114 @@ +import { test, expect } from "../fixtures/base"; + +test.describe('when given valid input', () => { + test('should successfully complete the onboarding flow', async ({ + homePage, + onboardingPage, + signUpPage, + authPage, + profilePage, + testAccount + }) => { + await homePage.gotToHomePage(); + await homePage.clickSignUpButton(); + await authPage.fillEmailField(testAccount.email); + await authPage.fillPasswordField(testAccount.password); + await authPage.clickSignUpWithEmailButton(); + await onboardingPage.clickContinueButton(); //First continue + await onboardingPage.clickContinueButton(); //Second continue + await onboardingPage.clickGetStartedButton(); + await signUpPage.fillDisplayName(testAccount.display_name); + // TODO: fix? + await signUpPage.fillUsername(testAccount.username + Date.now().toString()); + await signUpPage.clickNextButton(); + await signUpPage.fillBio(testAccount.bio); + await signUpPage.clickNextButton(); + await signUpPage.chooseGender(testAccount.gender); + await signUpPage.fillAge(testAccount.age); + await signUpPage.fillHeight({feet: testAccount.height?.feet, inches: testAccount.height?.inches}); + await signUpPage.fillEthnicity(testAccount.ethnicity_origin); + await signUpPage.fillInterestedInConnectingWith(testAccount.interested_in); + await signUpPage.fillAgeRangeInterest(testAccount.Interested_in_ages?.min, testAccount.Interested_in_ages?.max); + await signUpPage.setConnectionType(testAccount.connection_type); + await signUpPage.setRelationshipStatus(testAccount.relationship_status); + await signUpPage.setRelationshipStyle(testAccount.relationship_style); + await signUpPage.fillCurrentNumberOfChildren(testAccount.number_of_kids); + await signUpPage.setWantChildrenExpectation(testAccount.children_expectation); + await signUpPage.setInterests(testAccount.interests); + await signUpPage.setCauses(testAccount.causes); + await signUpPage.setHighestEducationLevel(testAccount.education_level); + await signUpPage.fillUniversity(testAccount.university); + await signUpPage.fillJobTitle(testAccount.job_title); + await signUpPage.fillCompany(testAccount.company); + await signUpPage.setWorkArea(testAccount.work_area); //Is not displayed correctly + await signUpPage.setPoliticalBeliefs(testAccount.beliefs?.political?.belief, testAccount.beliefs?.political?.details); + await signUpPage.setReligiousBeliefs(testAccount.beliefs?.religious?.belief, testAccount.beliefs?.religious?.details); + await signUpPage.setPersonalityType(testAccount.personality_type); + await signUpPage.setOpennessPersonalityValue(testAccount.big_five_personality_traits?.openness); + await signUpPage.setDietType(testAccount.diet); + await signUpPage.setIsSmoker(testAccount.is_smoker); + await signUpPage.fillAlcoholPerMonth(testAccount.alcohol_consumed_per_month); + await signUpPage.setLanguages(testAccount.languages); + await signUpPage.addSocialMediaPlatform(testAccount.social_media); + await signUpPage.clickNextButton(); + await profilePage.clickCloseButton(); + await onboardingPage.clickRefineProfileButton(); + + await profilePage.verifyDisplayNameAndAge(testAccount.display_name, testAccount.age); + await profilePage.verifyGenderLocationHeight( + testAccount.gender, + undefined, + testAccount.height?.feet, + testAccount.height?.inches + ); + await profilePage.verifyIntrestedInConnectingWith( + testAccount.interested_in, + testAccount.Interested_in_ages?.min, + testAccount.Interested_in_ages?.max + ); + await profilePage.verifyRelationShipTypeAndInterest(testAccount.connection_type, testAccount.relationship_style); + await profilePage.verifyRelationshipStatus(testAccount.relationship_status); + await profilePage.verifyCurrentNumberOfKids(testAccount.number_of_kids); + await profilePage.verifyWantChildrenExpectation(testAccount.children_expectation); + await profilePage.verifyInterests(testAccount.interests); + await profilePage.verifyCauses(testAccount.causes); + await profilePage.verifyEducationLevelAndUniversity(testAccount.education_level, testAccount.university); + await profilePage.verifyJobInformation(testAccount.job_title, testAccount.company); + await profilePage.verifyPoliticalBeliefs(testAccount.beliefs?.political?.belief, testAccount.beliefs?.political?.details); + await profilePage.verifyReligiousBeliefs(testAccount.beliefs?.religious?.belief, testAccount.beliefs?.religious?.details); + await profilePage.verifyPersonalityType(testAccount.personality_type); + await profilePage.verifyBigFivePersonalitySection(testAccount.big_five_personality_traits); + await profilePage.verifyDiet(testAccount.diet); + await profilePage.verifySmoker(testAccount.is_smoker); + await profilePage.verifyDrinksPerMonth(testAccount.alcohol_consumed_per_month); + await profilePage.verifyLanguages(testAccount.languages); + await profilePage.verifySocialMedia(testAccount.social_media); + }); + test('should successfully skip the onboarding flow', async ({ + homePage, + onboardingPage, + signUpPage, + authPage, + profilePage, + fakerAccount + }) => { + await homePage.gotToHomePage(); + await homePage.clickSignUpButton(); + await authPage.fillEmailField(fakerAccount.email); + await authPage.fillPasswordField(fakerAccount.password); + await authPage.clickSignUpWithEmailButton(); + await onboardingPage.clickSkipOnboardingButton(); + await signUpPage.fillDisplayName(fakerAccount.display_name); + await signUpPage.fillUsername(fakerAccount.username); + await signUpPage.clickNextButton(); + await signUpPage.clickNextButton(); //Skip bio + await signUpPage.clickNextButton(); //Skip optional information + // TODO: fix below + // await profilePage.clickCloseButton(); + // await onboardingPage.clickRefineProfileButton(); + }); +}); + +test.describe('when an error occurs', () => { + test('placeholder', async () => {}); +}); \ No newline at end of file diff --git a/tests/e2e/web/utils/.keep b/tests/e2e/web/utils/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/e2e/web/utils/accountInformation.ts b/tests/e2e/web/utils/accountInformation.ts new file mode 100644 index 00000000..43028627 --- /dev/null +++ b/tests/e2e/web/utils/accountInformation.ts @@ -0,0 +1,158 @@ +import { faker } from "@faker-js/faker"; +import { + ConnectionType, + Ethnicity, + Gender, + InterestedIn, + RelationshipStatus, + RelationshipStyle, + ChildrenExpectation, + Interests, + Causes, + Education, + PoliticalBeliefs, + Religion, + Personality, + Diet, + Language, + Platforms, +} from "../pages/signUpPage"; + +export type OnboardingUser = { + email: string; + password: string; + display_name: string; + username: string; + bio?: string; + gender?: Gender; + age?: string; + height?: Height; + ethnicity_origin?: Ethnicity; + interested_in?: InterestedIn; + Interested_in_ages?: InterestedInAges; + connection_type?: ConnectionType; + relationship_status?: RelationshipStatus; + relationship_style?: RelationshipStyle; + number_of_kids?: string; + children_expectation?: ChildrenExpectation; + interests?: (Interests | string)[], + causes?: (Causes | string)[], + education_level?: Education, + university?: string, + job_title?: string, + company?: string, + work_area?: string[], + beliefs?: BeliefDetails, + personality_type?: Personality, + big_five_personality_traits?: FiveBigPersonalityTraits, + diet?: Diet, + is_smoker?: boolean, + alcohol_consumed_per_month?: string, + languages?: Language[], + social_media?: Socials[], +}; + +type Height = { + feet: string; + inches: string; + centimeters: string; +}; + +type InterestedInAges = { + min: string; + max?: string; +}; + +type BeliefDetails = { + political?: { + belief?: PoliticalBeliefs; + details?: string; + }, + religious?: { + belief?: Religion; + details?: string; + }, +}; + +export type Socials = { + platform: Platforms; + urlOrUsername: string; +}; + +type FiveBigPersonalityTraits = { + openness?: number; + conscientiousness?: number; + extraversion?: number; + agreeableness?: number; + neutroticism?: number; +}; + +type OnboardingConfig = { + faker_account: OnboardingUser; + account_one: OnboardingUser; +}; + +export const onboarding: OnboardingConfig = { + "faker_account": { + "email": faker.internet.email(), + "password": faker.internet.password(), + "display_name": faker.internet.displayName(), + "username": faker.internet.username(), + }, + "account_one": { + "email": "onboardingOne@compass.com", + "password": "CompassTest", + "display_name": "Compass Onboarding", + "username": "TheGreatOnboarding", + "bio": "Born beneath twin moons, this wanderer maps forgotten roads, trades riddles for shelter, and keeps stories in glass bottles. Drawn to ancient libraries and glowing forests, they seek lost spells, quiet taverns, and adventures that rewrite fate. Their compass points to wonder. Ever onward. Always. Go", + "gender": "Woman", + "age": "25", + "height": { + "feet": "6", + "inches": "0", + "centimeters": "182.88" + }, + "ethnicity_origin": "South/Southeast Asian", + "interested_in": "Men", + "Interested_in_ages": { + "min": "20", + "max": "30" + }, + "connection_type": "Relationship", + "relationship_status": "In open relationship", + "relationship_style": "Open Relationship", + "number_of_kids": "2", + "children_expectation": "Neutral", + "interests": [ "Chess", "Eating" ], + "causes": [ "Animal Rights", "Free Spotify"], + "education_level": "Bachelors", + "university": "Open-Source University", + "job_title": "Unemployed", + "company": "Home", + "work_area": ["Living Room", "University"], + "beliefs": { + "political": { + "belief": "Green / Eco-Socialist", + "details": "This will be details" + }, + "religious": { + "belief": "Shinto", + "details": "This will be details" + }, + }, + "personality_type": "ENFJ", + "big_five_personality_traits": { + "openness": 43 + }, + "diet": "Omnivore", + "is_smoker": false, + "alcohol_consumed_per_month": "4", + "languages": ["Akan", "Cebuano"], + "social_media": [ + { + "platform": "Bluesky", + "urlOrUsername": "TheGreatConnection" + }, + ], + } +}; \ No newline at end of file diff --git a/tests/e2e/web/utils/deleteUser.ts b/tests/e2e/web/utils/deleteUser.ts new file mode 100644 index 00000000..da957b6a --- /dev/null +++ b/tests/e2e/web/utils/deleteUser.ts @@ -0,0 +1,44 @@ +import axios from 'axios'; +import { createSupabaseDirectClient } from "../../../../backend/shared/src/supabase/init"; +import { config } from '../SPEC_CONFIG'; + +export async function deleteUser(email: string, password: string) { + + try { + const login = await axios.post( + `${config.FIREBASE_URL.BASE}${config.FIREBASE_URL.SIGN_IN_PASSWORD}`, + { + email, + password, + returnSecureToken: true + } + ); + + await deleteFromDb(login.data.localId); + + await axios.post( + `${config.FIREBASE_URL.BASE}${config.FIREBASE_URL.DELETE}`, + { idToken: login.data.idToken } + ); + + + } catch (err: any) { + console.log(err); + } +}; + +async function deleteFromDb(user_id: string) { + const db = createSupabaseDirectClient(); + try { + const deleteEntryById = `DELETE FROM users WHERE id = $1 RETURNING *`; + const result = await db.query(deleteEntryById, [user_id]); + console.log("Deleted data: ",{ + "id": result[0].id, + "name": result[0].name, + "username": result[0].username + }); + } catch (error) { + console.error("Failed to delete user data, all changes rolled back: ", error); + throw error; + }; +}; \ No newline at end of file diff --git a/web/components/bio/profile-bio-block.tsx b/web/components/bio/profile-bio-block.tsx index ab7ec61d..48da4887 100644 --- a/web/components/bio/profile-bio-block.tsx +++ b/web/components/bio/profile-bio-block.tsx @@ -30,7 +30,7 @@ export function BioBlock(props: { !edit && 'px-3 py-2' )} > - + {!edit && profile.bio && ( @@ -47,7 +47,7 @@ export function BioBlock(props: { /> )} {isCurrentUser && !edit && ( - + {t('profile.optional.feet', 'Feet')} { if (e.target.value === '') { setHeightFeet(undefined) @@ -423,6 +424,7 @@ export const OptionalProfileUserForm = (props: { {t('profile.optional.inches', 'Inches')} { if (e.target.value === '') { setHeightInches(undefined) @@ -449,6 +451,7 @@ export const OptionalProfileUserForm = (props: { {t('profile.optional.centimeters', 'Centimeters')} { if (e.target.value === '') { setHeightFeet(undefined) @@ -520,6 +523,7 @@ export const OptionalProfileUserForm = (props: { {t('common.min', 'Min')} { const newMax = e.target.value ? Number(e.target.value) : 100 @@ -607,22 +612,23 @@ export const OptionalProfileUserForm = (props: { - - - { - const value = - e.target.value === '' ? null : Number(e.target.value) - setProfile('has_kids', value) - }} - className={'w-20'} - min={0} - value={profile['has_kids'] ?? undefined} - /> - + + + { + const value = + e.target.value === '' ? null : Number(e.target.value) + setProfile('has_kids', value) + }} + className={'w-20'} + min={0} + value={profile['has_kids'] ?? undefined} + /> + setProfile('university', e.target.value)} className={'w-52'} @@ -715,6 +722,7 @@ export const OptionalProfileUserForm = (props: { : t('profile.optional.job_title', 'Job title')} setProfile('occupation_title', e.target.value)} className={'w-52'} @@ -727,6 +735,7 @@ export const OptionalProfileUserForm = (props: { {t('profile.optional.company', 'Company')} setProfile('company', e.target.value)} className={'w-52'} @@ -759,6 +768,7 @@ export const OptionalProfileUserForm = (props: { />

{t('profile.optional.details', 'Details')}

setProfile('political_details', e.target.value)} className={'w-full sm:w-96'} @@ -782,6 +792,7 @@ export const OptionalProfileUserForm = (props: { />

{t('profile.optional.details', 'Details')}

setProfile('religious_beliefs', e.target.value)} className={'w-full sm:w-96'} @@ -886,6 +897,7 @@ export const OptionalProfileUserForm = (props: { )} { const value = @@ -1123,7 +1135,7 @@ const Big5Slider = (props: {
{label} - {Math.round(value)} + {Math.round(value)}
@@ -65,7 +66,7 @@ export function AboutRow(props: { formattedText += formattedText ? ` (${suffix})` : suffix } return ( - +
{icon}
{formattedText}
@@ -101,6 +102,7 @@ export default function ProfileAbout(props: { .filter(Boolean) .sort((a, b) => a.localeCompare(b, locale)) as string[] } + testId='profile-about-work-area' /> } @@ -108,6 +110,7 @@ export default function ProfileAbout(props: { t(`profile.political.${belief}`, INVERTED_POLITICAL_CHOICES[belief]) )} suffix={profile.political_details} + testId='profile-about-political' /> } @@ -115,6 +118,7 @@ export default function ProfileAbout(props: { t(`profile.religion.${belief}`, INVERTED_RELIGION_CHOICES[belief]) )} suffix={profile.religious_beliefs} + testId='profile-about-religious' /> } @@ -124,6 +128,7 @@ export default function ProfileAbout(props: { .filter(Boolean) .sort((a, b) => a.localeCompare(b, locale)) as string[] } + testId='profile-about-interests' /> } @@ -133,10 +138,12 @@ export default function ProfileAbout(props: { .filter(Boolean) .sort((a, b) => a.localeCompare(b, locale)) as string[] } + testId='profile-about-causes' /> } text={profile.mbti ? INVERTED_MBTI_CHOICES[profile.mbti] : null} + testId='profile-about-personality' /> r !== 'other') ?.map((r: any) => t(`profile.race.${r}`, convertRace(r)))} + testId='profile-about-ethnicity' /> @@ -152,12 +160,14 @@ export default function ProfileAbout(props: { text={profile.diet?.map((e) => t(`profile.diet.${e}`, INVERTED_DIET_CHOICES[e]) )} + testId='profile-about-diet' /> } text={profile.languages?.map((v) => t(`profile.language.${v}`, INVERTED_LANGUAGE_CHOICES[v]) )} + testId='profile-about-languages' /> @@ -215,6 +225,7 @@ function Seeking(props: { profile: Profile }) { } text={`${seekingGenderText} ${ageRangeText}`} + testId='profile-about-seeking' /> ) } @@ -227,6 +238,7 @@ function RelationshipType(props: { profile: Profile }) { } text={seekingGenderText} + testId='profile-about-relationship-type' /> ) } @@ -247,6 +259,7 @@ function RelationshipStatus(props: { profile: Profile }) { INVERTED_RELATIONSHIP_STATUS_CHOICES[v] ) )} + testId='profile-about-relationship-status' /> ) } @@ -274,7 +287,11 @@ function Education(props: { profile: Profile }) { if (text.length === 0) { return <> } - return } text={text}/> + return } + text={text} + testId='profile-about-education' + /> } function Occupation(props: { profile: Profile }) { @@ -295,6 +312,7 @@ function Occupation(props: { profile: Profile }) { } text={occupationText} + testId='profile-about-occupation' /> ) } @@ -316,6 +334,7 @@ function Smoker(props: { profile: Profile }) { } text={t('profile.doesnt_smoke', "Doesn't smoke")} + testId='profile-about-smoker' /> ) } @@ -330,6 +349,7 @@ function Drinks(props: { profile: Profile }) { } text={t('profile.doesnt_drink', "Doesn't drink")} + testId='profile-about-not-drink' /> ) } @@ -343,6 +363,7 @@ function Drinks(props: { profile: Profile }) { count: drinksPerMonth, }) } + testId='profile-about-drinker' /> ) } @@ -367,6 +388,7 @@ function WantsKids(props: { profile: Profile }) { } text={wantsKidsText} + testId='profile-about-wants-kids' /> ) } @@ -382,6 +404,7 @@ function LastOnline(props: { lastOnlineTime?: string }) { text={t('profile.last_online', 'Active {time}', { time: fromNow(lastOnlineTime, true, t, locale), })} + testId='profile-about-last-online' /> ) } @@ -432,7 +455,7 @@ function Big5Traits(props: { profile: Profile }) { } return ( - +
{t('profile.big5', 'Big Five personality traits')}:
@@ -494,7 +517,13 @@ function HasKids(props: { profile: Profile }) { ) : ( faChild ) - return + return ( + + ) } export const formatProfileValue = ( diff --git a/web/components/profile/profile-header.tsx b/web/components/profile/profile-header.tsx index 0674d36b..17f02671 100644 --- a/web/components/profile/profile-header.tsx +++ b/web/components/profile/profile-header.tsx @@ -68,7 +68,7 @@ export default function ProfileHeader(props: { - + {/*{!isCurrentUser && }*/} {simpleView ? ( @@ -92,6 +92,7 @@ export default function ProfileHeader(props: { /> - + + {profile.city && ( {display.map(({platform, label, url}) => ( diff --git a/web/components/widgets/add-photos.tsx b/web/components/widgets/add-photos.tsx index ac4610fb..b69a4be0 100644 --- a/web/components/widgets/add-photos.tsx +++ b/web/components/widgets/add-photos.tsx @@ -58,7 +58,7 @@ export const AddPhotosWidget = (props: { disabled={uploadingImages} /> -
+