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 <martin.braquet@gmail.com>
This commit is contained in:
Okechi Jones-Williams
2026-02-20 15:56:26 +00:00
committed by GitHub
parent 1c26b6381e
commit 1994697fa1
27 changed files with 3729 additions and 2304 deletions

View File

@@ -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",

View File

@@ -27,5 +27,8 @@ export default defineConfig({
// },
],
timeout: 60000,
expect: {
timeout: 120000,
},
});

View File

@@ -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

View File

@@ -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();

View File

@@ -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!',

View File

@@ -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"

View File

@@ -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) {

View File

@@ -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);
}
}
};

View File

@@ -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();
};
};

View File

@@ -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();
};
};

View File

@@ -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<string, number> | 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());
};
};
};

View File

@@ -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();
};
};

View File

@@ -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()

View File

@@ -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 () => {});
});

View File

View File

@@ -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"
},
],
}
};

View File

@@ -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;
};
};

View File

@@ -30,7 +30,7 @@ export function BioBlock(props: {
!edit && 'px-3 py-2'
)}
>
<Row className="w-full">
<Row className="w-full" data-testid="profile-bio">
{!edit && profile.bio && (
<Col className="flex w-full flex-grow">
<Content className="w-full" content={profile.bio as JSONContent} />
@@ -47,7 +47,7 @@ export function BioBlock(props: {
/>
)}
{isCurrentUser && !edit && (
<Tooltip text={t('more_options_user.edit_bio', 'Bio options')} noTap>
<Tooltip text={t('more_options_user.edit_bio', 'Bio options')} noTap testId='profile-bio-options'>
<DropdownMenu
items={[
{

View File

@@ -108,6 +108,7 @@ export const SignUpButton = (props: {
return (
<Button
data-testid='side-bar-sign-up-button'
color={color ?? 'gradient'}
size={size ?? 'xl'}
onClick={signupRedirect}

View File

@@ -402,6 +402,7 @@ export const OptionalProfileUserForm = (props: {
<span>{t('profile.optional.feet', 'Feet')}</span>
<Input
type="number"
data-testid='height-feet'
onChange={(e) => {
if (e.target.value === '') {
setHeightFeet(undefined)
@@ -423,6 +424,7 @@ export const OptionalProfileUserForm = (props: {
<span>{t('profile.optional.inches', 'Inches')}</span>
<Input
type="number"
data-testid='height-inches'
onChange={(e) => {
if (e.target.value === '') {
setHeightInches(undefined)
@@ -449,6 +451,7 @@ export const OptionalProfileUserForm = (props: {
<span>{t('profile.optional.centimeters', 'Centimeters')}</span>
<Input
type="number"
data-testid='height-centimeters'
onChange={(e) => {
if (e.target.value === '') {
setHeightFeet(undefined)
@@ -520,6 +523,7 @@ export const OptionalProfileUserForm = (props: {
<Col>
<span>{t('common.min', 'Min')}</span>
<Select
data-testid='pref-age-min'
value={profile['pref_age_min'] ?? ''}
onChange={(e) => {
const newMin = e.target.value ? Number(e.target.value) : 18
@@ -539,6 +543,7 @@ export const OptionalProfileUserForm = (props: {
<Col>
<span>{t('common.max', 'Max')}</span>
<Select
data-testid='pref-age-max'
value={profile['pref_age_max'] ?? ''}
onChange={(e) => {
const newMax = e.target.value ? Number(e.target.value) : 100
@@ -607,22 +612,23 @@ export const OptionalProfileUserForm = (props: {
<Category title={t('profile.optional.category.family', 'Family')}/>
<Col className={clsx(colClassName)}>
<label className={clsx(labelClassName)}>
{t('profile.optional.num_kids', 'Current number of kids')}
</label>
<Input
type="number"
onChange={(e) => {
const value =
e.target.value === '' ? null : Number(e.target.value)
setProfile('has_kids', value)
}}
className={'w-20'}
min={0}
value={profile['has_kids'] ?? undefined}
/>
</Col>
<Col className={clsx(colClassName)}>
<label className={clsx(labelClassName)}>
{t('profile.optional.num_kids', 'Current number of kids')}
</label>
<Input
data-testid='current-number-of-kids'
type="number"
onChange={(e) => {
const value =
e.target.value === '' ? null : Number(e.target.value)
setProfile('has_kids', value)
}}
className={'w-20'}
min={0}
value={profile['has_kids'] ?? undefined}
/>
</Col>
<Col className={clsx(colClassName)}>
<label className={clsx(labelClassName)}>
@@ -695,6 +701,7 @@ export const OptionalProfileUserForm = (props: {
{t('profile.optional.university', 'University')}
</label>
<Input
data-testid='university'
type="text"
onChange={(e) => setProfile('university', e.target.value)}
className={'w-52'}
@@ -715,6 +722,7 @@ export const OptionalProfileUserForm = (props: {
: t('profile.optional.job_title', 'Job title')}
</label>
<Input
data-testid='job-title'
type="text"
onChange={(e) => setProfile('occupation_title', e.target.value)}
className={'w-52'}
@@ -727,6 +735,7 @@ export const OptionalProfileUserForm = (props: {
{t('profile.optional.company', 'Company')}
</label>
<Input
data-testid='company'
type="text"
onChange={(e) => setProfile('company', e.target.value)}
className={'w-52'}
@@ -759,6 +768,7 @@ export const OptionalProfileUserForm = (props: {
/>
<p>{t('profile.optional.details', 'Details')}</p>
<Input
data-testid='political-belief-details'
type="text"
onChange={(e) => setProfile('political_details', e.target.value)}
className={'w-full sm:w-96'}
@@ -782,6 +792,7 @@ export const OptionalProfileUserForm = (props: {
/>
<p>{t('profile.optional.details', 'Details')}</p>
<Input
data-testid='religious-belief-details'
type="text"
onChange={(e) => setProfile('religious_beliefs', e.target.value)}
className={'w-full sm:w-96'}
@@ -886,6 +897,7 @@ export const OptionalProfileUserForm = (props: {
)}
</label>
<Input
data-testid='alcohol-consumed-per-month'
type="number"
onChange={(e) => {
const value =
@@ -1123,7 +1135,7 @@ const Big5Slider = (props: {
<div>
<div className="mb-1 flex items-center justify-between text-sm text-ink-600">
<span>{label}</span>
<span className="font-semibold text-ink-700">{Math.round(value)}</span>
<span className="font-semibold text-ink-700" data-testid={`${label.toLowerCase()}-value`}>{Math.round(value)}</span>
</div>
<Slider
amount={value}

View File

@@ -42,8 +42,9 @@ export function AboutRow(props: {
text?: string | null | string[]
preText?: string
suffix?: string | null
testId?: string
}) {
const {icon, text, preText, suffix} = props
const {icon, text, preText, suffix, testId} = props
const t = useT()
if (!text?.length && !preText && !suffix) {
return <></>
@@ -65,7 +66,7 @@ export function AboutRow(props: {
formattedText += formattedText ? ` (${suffix})` : suffix
}
return (
<Row className="items-center gap-2">
<Row className="items-center gap-2" data-testid={testId}>
<div className="text-ink-600 w-5">{icon}</div>
<div>{formattedText}</div>
</Row>
@@ -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'
/>
<AboutRow
icon={<RiScales3Line className="h-5 w-5"/>}
@@ -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'
/>
<AboutRow
icon={<PiHandsPrayingBold className="h-5 w-5"/>}
@@ -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'
/>
<AboutRow
icon={<FaStar className="h-5 w-5"/>}
@@ -124,6 +128,7 @@ export default function ProfileAbout(props: {
.filter(Boolean)
.sort((a, b) => a.localeCompare(b, locale)) as string[]
}
testId='profile-about-interests'
/>
<AboutRow
icon={<FaHandsHelping className="h-5 w-5"/>}
@@ -133,10 +138,12 @@ export default function ProfileAbout(props: {
.filter(Boolean)
.sort((a, b) => a.localeCompare(b, locale)) as string[]
}
testId='profile-about-causes'
/>
<AboutRow
icon={<BsPersonVcard className="h-5 w-5"/>}
text={profile.mbti ? INVERTED_MBTI_CHOICES[profile.mbti] : null}
testId='profile-about-personality'
/>
<Big5Traits profile={profile}/>
<AboutRow
@@ -144,6 +151,7 @@ export default function ProfileAbout(props: {
text={profile.ethnicity
?.filter((r) => r !== 'other')
?.map((r: any) => t(`profile.race.${r}`, convertRace(r)))}
testId='profile-about-ethnicity'
/>
<Smoker profile={profile}/>
<Drinks profile={profile}/>
@@ -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'
/>
<AboutRow
icon={<MdLanguage className="h-5 w-5"/>}
text={profile.languages?.map((v) =>
t(`profile.language.${v}`, INVERTED_LANGUAGE_CHOICES[v])
)}
testId='profile-about-languages'
/>
<HasKids profile={profile}/>
<WantsKids profile={profile}/>
@@ -215,6 +225,7 @@ function Seeking(props: { profile: Profile }) {
<AboutRow
icon={<PiMagnifyingGlassBold className="h-5 w-5"/>}
text={`${seekingGenderText} ${ageRangeText}`}
testId='profile-about-seeking'
/>
)
}
@@ -227,6 +238,7 @@ function RelationshipType(props: { profile: Profile }) {
<AboutRow
icon={<BsPersonHeart className="h-5 w-5"/>}
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 <AboutRow icon={<LuGraduationCap className="h-5 w-5"/>} text={text}/>
return <AboutRow
icon={<LuGraduationCap className="h-5 w-5"/>}
text={text}
testId='profile-about-education'
/>
}
function Occupation(props: { profile: Profile }) {
@@ -295,6 +312,7 @@ function Occupation(props: { profile: Profile }) {
<AboutRow
icon={<LuBriefcase className="h-5 w-5"/>}
text={occupationText}
testId='profile-about-occupation'
/>
)
}
@@ -316,6 +334,7 @@ function Smoker(props: { profile: Profile }) {
<AboutRow
icon={<LuCigaretteOff className="h-5 w-5"/>}
text={t('profile.doesnt_smoke', "Doesn't smoke")}
testId='profile-about-smoker'
/>
)
}
@@ -330,6 +349,7 @@ function Drinks(props: { profile: Profile }) {
<AboutRow
icon={<MdNoDrinks className="h-5 w-5"/>}
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 }) {
<AboutRow
icon={<MdOutlineChildFriendly className="h-5 w-5"/>}
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 (
<Col className="gap-2">
<Col className="gap-2" data-testid='profile-about-big-five-personality-traits'>
<div className="text-ink-600 font-medium">
{t('profile.big5', 'Big Five personality traits')}:
</div>
@@ -494,7 +517,13 @@ function HasKids(props: { profile: Profile }) {
) : (
faChild
)
return <AboutRow icon={icon} text={hasKidsText}/>
return (
<AboutRow
icon={icon}
text={hasKidsText}
testId={'profile-about-has-kids'}
/>
)
}
export const formatProfileValue = (

View File

@@ -68,7 +68,7 @@ export default function ProfileHeader(props: {
<Row className={clsx('flex-wrap justify-between gap-2 py-1')}>
<Row className="items-center gap-1">
<Col className="gap-1">
<Row className="items-center gap-1 text-xl">
<Row className="items-center gap-1 text-xl" data-testid="profile-display-name-age">
{/*{!isCurrentUser && <OnlineIcon last_online_time={userActivity?.last_online_time}/>}*/}
<span>
{simpleView ? (
@@ -92,6 +92,7 @@ export default function ProfileHeader(props: {
/>
<Tooltip text={t('more_options_user.edit_profile', 'Edit profile')} noTap>
<Button
data-testid="profile-edit"
color={'gray-outline'}
onClick={() => {
track('editprofile', {userId: user.id})
@@ -103,7 +104,7 @@ export default function ProfileHeader(props: {
</Button>
</Tooltip>
<Tooltip text={t('more_options_user.profile_options', 'Profile options')} noTap>
<Tooltip text={t('more_options_user.profile_options', 'Profile options')} noTap testId='profile-options'>
<DropdownMenu
menuWidth={'w-52'}
icon={

View File

@@ -19,7 +19,10 @@ export default function ProfilePrimaryInfo(props: { profile: Profile }) {
? profile.region_code
: profile.country
return (
<Row className="text-ink-700 gap-4 text-sm">
<Row
className="text-ink-700 gap-4 text-sm"
data-testid="profile-gender-location-height-inches"
>
{profile.city && (
<IconWithInfo
text={`${profile.city ?? ''}, ${stateOrCountry ?? ''}`}

View File

@@ -40,6 +40,7 @@ export function UserHandles(props: { links: Socials; className?: string }) {
'text-ink-400 flex-wrap items-center gap-2 sm:gap-x-4',
className
)}
data-testid="profile-social-media-accounts"
>
{display.map(({platform, label, url}) => (
<a key={platform} target="_blank" href={url}>

View File

@@ -58,7 +58,7 @@ export const AddPhotosWidget = (props: {
disabled={uploadingImages}
/>
<Row className="flex-wrap gap-2">
<div className="relative">
<div className="relative" data-testid='profile-upload-photo'>
<label
className={clsx(
'bg-canvas-50 hover:bg-ink-300 text-ink-0 dark:text-ink-500 hover:dark:text-ink-600 flex h-[200px] w-[200px] cursor-pointer flex-col items-center rounded-md transition-colors',

View File

@@ -25,6 +25,7 @@ export function Tooltip(props: {
noFade?: boolean
hasSafePolygon?: boolean
suppressHydrationWarning?: boolean
testId?: string
}) {
const {
text,
@@ -34,6 +35,7 @@ export function Tooltip(props: {
noFade,
hasSafePolygon,
suppressHydrationWarning,
testId
} = props
const arrowRef = useRef(null)
@@ -141,6 +143,7 @@ export function Tooltip(props: {
return text ? (
<>
<span
data-testid={testId}
suppressHydrationWarning={suppressHydrationWarning}
className={className}
ref={reference}

4392
yarn.lock
View File

File diff suppressed because it is too large Load Diff