From 3e313d21f9ea2eb8a9892ed86b11f39c000cf80a Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams Date: Sun, 22 Feb 2026 18:34:09 +0000 Subject: [PATCH 01/19] Added Database checks to the onboarding flow --- tests/e2e/web/pages/signUpPage.ts | 2 +- tests/e2e/web/specs/onboardingFlow.spec.ts | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/e2e/web/pages/signUpPage.ts b/tests/e2e/web/pages/signUpPage.ts index e725d154..8a07d8a1 100644 --- a/tests/e2e/web/pages/signUpPage.ts +++ b/tests/e2e/web/pages/signUpPage.ts @@ -662,7 +662,7 @@ export class SignUpPage { async setLanguages(language: LanguageTuple[] | undefined) { if (!language || language.length === 0) return - await this.page.getByRole('checkbox', {name: `English`}).click() + await this.page.getByRole('checkbox', {name: `English`}).click(); for (let i = 0; i < language.length; i++) { await expect(this.page.getByRole('checkbox', {name: `${language[i][0]}`})).toBeVisible() await this.page.getByRole('checkbox', {name: `${language[i][0]}`}).click() diff --git a/tests/e2e/web/specs/onboardingFlow.spec.ts b/tests/e2e/web/specs/onboardingFlow.spec.ts index a6aadb0e..855f2f34 100644 --- a/tests/e2e/web/specs/onboardingFlow.spec.ts +++ b/tests/e2e/web/specs/onboardingFlow.spec.ts @@ -53,7 +53,7 @@ test.describe('when given valid input', () => { await signUpPage.setPoliticalBeliefs( testAccount.beliefs?.political?.belief, testAccount.beliefs?.political?.details, - ) + ); await signUpPage.setReligiousBeliefs( testAccount.beliefs?.religious?.belief, testAccount.beliefs?.religious?.details, @@ -106,16 +106,16 @@ test.describe('when given valid input', () => { 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.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, @@ -125,7 +125,7 @@ test.describe('when given valid input', () => { await profilePage.verifyPoliticalBeliefs( testAccount.beliefs?.political?.belief, testAccount.beliefs?.political?.details, - ) + ); await profilePage.verifyReligiousBeliefs( testAccount.beliefs?.religious?.belief, testAccount.beliefs?.religious?.details, From e45cf442ddcef4d7c94298759673d796fde5eaa6 Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams Date: Wed, 25 Feb 2026 15:19:06 +0000 Subject: [PATCH 02/19] Added compatibility page setup Added more compatibility questions --- tests/e2e/web/pages/profilePage.ts | 54 +++++++++++----------- tests/e2e/web/specs/onboardingFlow.spec.ts | 4 +- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/tests/e2e/web/pages/profilePage.ts b/tests/e2e/web/pages/profilePage.ts index 1f999cc8..6d6826b0 100644 --- a/tests/e2e/web/pages/profilePage.ts +++ b/tests/e2e/web/pages/profilePage.ts @@ -64,13 +64,13 @@ export class ProfilePage { private readonly profileCompatibilityExplanation: 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.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, }) @@ -90,7 +90,7 @@ export class ProfilePage { 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-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') @@ -274,19 +274,19 @@ export class ProfilePage { } async clickStartAnsweringButton() { - await expect(this.startAnsweringButton).toBeVisible() - await this.startAnsweringButton.click() - } + await expect(this.startAnsweringButton).toBeVisible(); + await this.startAnsweringButton.click(); + }; async clickDoThisLaterButton() { - await expect(this.doThisLaterLink).toBeVisible() - await this.doThisLaterLink.click() - } + await expect(this.doThisLaterLink).toBeVisible(); + await this.doThisLaterLink.click(); + }; async clickShareButton() { - await expect(this.shareButton).toBeVisible() - await this.shareButton.click() - } + await expect(this.shareButton).toBeVisible(); + await this.shareButton.click(); + }; async clickEditProfileButton() { await expect(this.editProfileButton).toBeVisible() @@ -304,20 +304,20 @@ export class ProfilePage { } async selectOptionFromProfileDropdown(option: ProfileDropdownOptions) { - await expect(this.profileOptionsDropdown).toBeVisible() - await this.profileOptionsDropdown.click() + await expect(this.profileOptionsDropdown).toBeVisible(); + await this.profileOptionsDropdown.click(); if (option === 'Public') { - await expect(this.listProfilePubliclyDropdownOption).toBeVisible() - await this.listProfilePubliclyDropdownOption.click() + await expect(this.listProfilePubliclyDropdownOption).toBeVisible(); + await this.listProfilePubliclyDropdownOption.click(); } else if (option === 'Disable') { - await expect(this.disableProfileDropdownOption).toBeVisible() - await this.disableProfileDropdownOption.click() + await expect(this.disableProfileDropdownOption).toBeVisible(); + await this.disableProfileDropdownOption.click(); } else if (option === 'Private') { - await expect(this.limitProfileToMembersDropdownOption).toBeVisible() - await this.limitProfileToMembersDropdownOption.click() - } - } + await expect(this.limitProfileToMembersDropdownOption).toBeVisible(); + await this.limitProfileToMembersDropdownOption.click(); + }; + }; async verifyDisplayName(displayName?: string) { await expect(this.displayNameAndAgeSection).toBeVisible() diff --git a/tests/e2e/web/specs/onboardingFlow.spec.ts b/tests/e2e/web/specs/onboardingFlow.spec.ts index 855f2f34..52ddcb2f 100644 --- a/tests/e2e/web/specs/onboardingFlow.spec.ts +++ b/tests/e2e/web/specs/onboardingFlow.spec.ts @@ -301,5 +301,5 @@ test.describe('when given valid input', () => { }) test.describe('when an error occurs', () => { - test('placeholder', async () => {}) -}) + test('placeholder', async () => {}); +}); From 93a8659ceffa7432ce986784dde7069b8e6494bf Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams Date: Wed, 4 Mar 2026 01:30:41 +0000 Subject: [PATCH 03/19] Finished up the onboarding flow suite Added compatibility question tests and verifications Updated tests to cover Keywords and Headline changes recently made Updated tests to cover all of the big5 personality traits --- tests/e2e/web/specs/onboardingFlow.spec.ts | 2 +- tests/e2e/web/utils/accountInformation.ts | 2 +- .../answer-compatibility-question-content.tsx | 14 ++++++++++++++ .../answers/compatibility-questions-display.tsx | 4 ++-- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/tests/e2e/web/specs/onboardingFlow.spec.ts b/tests/e2e/web/specs/onboardingFlow.spec.ts index 52ddcb2f..39041cd6 100644 --- a/tests/e2e/web/specs/onboardingFlow.spec.ts +++ b/tests/e2e/web/specs/onboardingFlow.spec.ts @@ -301,5 +301,5 @@ test.describe('when given valid input', () => { }) test.describe('when an error occurs', () => { - test('placeholder', async () => {}); + test('placeholder', async () => {}) }); diff --git a/tests/e2e/web/utils/accountInformation.ts b/tests/e2e/web/utils/accountInformation.ts index 603ddcb4..43ece972 100644 --- a/tests/e2e/web/utils/accountInformation.ts +++ b/tests/e2e/web/utils/accountInformation.ts @@ -190,4 +190,4 @@ export const onboarding: OnboardingConfig = { }, } }, -} +} \ No newline at end of file diff --git a/web/components/answers/answer-compatibility-question-content.tsx b/web/components/answers/answer-compatibility-question-content.tsx index d40af5e1..029cfe5d 100644 --- a/web/components/answers/answer-compatibility-question-content.tsx +++ b/web/components/answers/answer-compatibility-question-content.tsx @@ -33,6 +33,7 @@ export const IMPORTANCE_CHOICES = { Important: 2, 'Very Important': 3, } as const +} as const type ImportanceColorsType = { [key: number]: string @@ -175,6 +176,9 @@ export function AnswerCompatibilityQuestionContent(props: { {shortenedPopularity && ( +
{compatibilityQuestion.question}
+ {shortenedPopularity && ( + ) => @@ -308,6 +313,7 @@ export const SelectAnswer = (props: { const {value, setValue, options} = props return ( clsx( disabled @@ -346,6 +353,7 @@ export const MultiSelectAnswers = (props: { return ( {question.question} @@ -481,7 +481,7 @@ export function CompatibilityAnswerBlock(props: { {answerText && ( {answerText} From 98b237e159d952aee356234fe1976c15de8ae11b Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams Date: Wed, 4 Mar 2026 15:41:37 +0000 Subject: [PATCH 04/19] Fix: Added 'tsconfig-paths/register' to playwright config so it applies tsconfig/ts-node to test files and imported modules....there was a syntax error: SyntaxError: tests/e2e/web/pages/homePage.ts: Unexpected token (2:0) --- playwright.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/playwright.config.ts b/playwright.config.ts index cbdc6cf2..094ee5a4 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,4 +1,5 @@ import {defineConfig, devices} from '@playwright/test' +import 'tsconfig-paths/register' import {execSync} from 'child_process' import {config} from 'dotenv' From bda801582f9d6e9705f18fb213bc310b01f650af Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams Date: Wed, 4 Mar 2026 15:44:07 +0000 Subject: [PATCH 05/19] . --- tests/e2e/web/pages/profilePage.ts | 52 +++++++++++----------- tests/e2e/web/pages/signUpPage.ts | 2 +- tests/e2e/web/specs/onboardingFlow.spec.ts | 20 ++++----- tests/e2e/web/utils/accountInformation.ts | 2 +- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/tests/e2e/web/pages/profilePage.ts b/tests/e2e/web/pages/profilePage.ts index 6d6826b0..304878c9 100644 --- a/tests/e2e/web/pages/profilePage.ts +++ b/tests/e2e/web/pages/profilePage.ts @@ -64,13 +64,13 @@ export class ProfilePage { private readonly profileCompatibilityExplanation: 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.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, }) @@ -274,19 +274,19 @@ export class ProfilePage { } async clickStartAnsweringButton() { - await expect(this.startAnsweringButton).toBeVisible(); - await this.startAnsweringButton.click(); - }; + await expect(this.startAnsweringButton).toBeVisible() + await this.startAnsweringButton.click() + } async clickDoThisLaterButton() { - await expect(this.doThisLaterLink).toBeVisible(); - await this.doThisLaterLink.click(); - }; + await expect(this.doThisLaterLink).toBeVisible() + await this.doThisLaterLink.click() + } async clickShareButton() { - await expect(this.shareButton).toBeVisible(); - await this.shareButton.click(); - }; + await expect(this.shareButton).toBeVisible() + await this.shareButton.click() + } async clickEditProfileButton() { await expect(this.editProfileButton).toBeVisible() @@ -304,20 +304,20 @@ export class ProfilePage { } async selectOptionFromProfileDropdown(option: ProfileDropdownOptions) { - await expect(this.profileOptionsDropdown).toBeVisible(); - await this.profileOptionsDropdown.click(); + await expect(this.profileOptionsDropdown).toBeVisible() + await this.profileOptionsDropdown.click() if (option === 'Public') { - await expect(this.listProfilePubliclyDropdownOption).toBeVisible(); - await this.listProfilePubliclyDropdownOption.click(); + await expect(this.listProfilePubliclyDropdownOption).toBeVisible() + await this.listProfilePubliclyDropdownOption.click() } else if (option === 'Disable') { - await expect(this.disableProfileDropdownOption).toBeVisible(); - await this.disableProfileDropdownOption.click(); + await expect(this.disableProfileDropdownOption).toBeVisible() + await this.disableProfileDropdownOption.click() } else if (option === 'Private') { - await expect(this.limitProfileToMembersDropdownOption).toBeVisible(); - await this.limitProfileToMembersDropdownOption.click(); - }; - }; + await expect(this.limitProfileToMembersDropdownOption).toBeVisible() + await this.limitProfileToMembersDropdownOption.click() + } + } async verifyDisplayName(displayName?: string) { await expect(this.displayNameAndAgeSection).toBeVisible() diff --git a/tests/e2e/web/pages/signUpPage.ts b/tests/e2e/web/pages/signUpPage.ts index 8a07d8a1..e725d154 100644 --- a/tests/e2e/web/pages/signUpPage.ts +++ b/tests/e2e/web/pages/signUpPage.ts @@ -662,7 +662,7 @@ export class SignUpPage { async setLanguages(language: LanguageTuple[] | undefined) { if (!language || language.length === 0) return - await this.page.getByRole('checkbox', {name: `English`}).click(); + await this.page.getByRole('checkbox', {name: `English`}).click() for (let i = 0; i < language.length; i++) { await expect(this.page.getByRole('checkbox', {name: `${language[i][0]}`})).toBeVisible() await this.page.getByRole('checkbox', {name: `${language[i][0]}`}).click() diff --git a/tests/e2e/web/specs/onboardingFlow.spec.ts b/tests/e2e/web/specs/onboardingFlow.spec.ts index 39041cd6..a6aadb0e 100644 --- a/tests/e2e/web/specs/onboardingFlow.spec.ts +++ b/tests/e2e/web/specs/onboardingFlow.spec.ts @@ -53,7 +53,7 @@ test.describe('when given valid input', () => { await signUpPage.setPoliticalBeliefs( testAccount.beliefs?.political?.belief, testAccount.beliefs?.political?.details, - ); + ) await signUpPage.setReligiousBeliefs( testAccount.beliefs?.religious?.belief, testAccount.beliefs?.religious?.details, @@ -106,16 +106,16 @@ test.describe('when given valid input', () => { 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.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, @@ -125,7 +125,7 @@ test.describe('when given valid input', () => { await profilePage.verifyPoliticalBeliefs( testAccount.beliefs?.political?.belief, testAccount.beliefs?.political?.details, - ); + ) await profilePage.verifyReligiousBeliefs( testAccount.beliefs?.religious?.belief, testAccount.beliefs?.religious?.details, @@ -302,4 +302,4 @@ test.describe('when given valid input', () => { test.describe('when an error occurs', () => { test('placeholder', async () => {}) -}); +}) diff --git a/tests/e2e/web/utils/accountInformation.ts b/tests/e2e/web/utils/accountInformation.ts index 43ece972..603ddcb4 100644 --- a/tests/e2e/web/utils/accountInformation.ts +++ b/tests/e2e/web/utils/accountInformation.ts @@ -190,4 +190,4 @@ export const onboarding: OnboardingConfig = { }, } }, -} \ No newline at end of file +} From 47717ea1118cf5f84708e72675ad8d7f4647e9a2 Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams Date: Thu, 5 Mar 2026 19:13:44 +0000 Subject: [PATCH 06/19] Updated ProfilePage: In some cases removed the use of "one shot grabs" using .textContent() to prevent flaky tests Added test for entering profile information post signup flow --- tests/e2e/web/pages/profilePage.ts | 80 +++++++--------- tests/e2e/web/pages/signUpPage.ts | 6 +- tests/e2e/web/specs/onboardingFlow.spec.ts | 102 +++++++++++++++++++++ tests/e2e/web/utils/accountInformation.ts | 7 ++ 4 files changed, 143 insertions(+), 52 deletions(-) diff --git a/tests/e2e/web/pages/profilePage.ts b/tests/e2e/web/pages/profilePage.ts index 304878c9..3f9b3e99 100644 --- a/tests/e2e/web/pages/profilePage.ts +++ b/tests/e2e/web/pages/profilePage.ts @@ -64,8 +64,8 @@ export class ProfilePage { private readonly profileCompatibilityExplanation: Locator constructor(public readonly page: Page) { - this.startAnsweringButton = page.getByRole('button', {}) - this.doThisLaterLink = page.getByRole('button', {}) + this.startAnsweringButton = page.getByRole('button', { name: 'Start answering' }) + this.doThisLaterLink = page.getByRole('button', { name: 'Do this later' }) this.closeButton = page.getByRole('button', {name: 'Close'}) this.shareButton = page.getByRole('button', {name: 'Share'}) this.editProfileButton = page.getByTestId('profile-edit') @@ -343,62 +343,54 @@ export class ProfilePage { async verifyEthnicityOrigin(origin: string) { await expect(this.ethnicityAboutSection).toBeVisible() - const textContent = await this.ethnicityAboutSection.textContent() - await expect(textContent?.toLowerCase()).toContain(origin.toLowerCase()) + await expect(this.ethnicityAboutSection).toContainText(origin, {ignoreCase: true}) } async verifyInterestedInConnectingWith(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[0].toLowerCase()) - if (minAge) await expect(textContent?.toLowerCase()).toContain(minAge.toLowerCase()) - if (maxAge) await expect(textContent?.toLowerCase()).toContain(maxAge.toLowerCase()) + if (gender) await expect(this.seekingAboutSection).toContainText(gender[0], {ignoreCase: true}) + if (minAge) await expect(this.seekingAboutSection).toContainText(minAge) + if (maxAge) await expect(this.seekingAboutSection).toContainText(maxAge) } 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[0].toLowerCase()) - if (interest) await expect(textContent?.toLowerCase()).toContain(interest[0].toLowerCase()) + if (type) await expect(this.relationshipTypeAboutSection).toContainText(type[0], {ignoreCase: true}) + if (interest) await expect(this.relationshipTypeAboutSection).toContainText(interest[0], {ignoreCase: true}) } 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[0].toLowerCase()) + await expect(this.relationshipStatusAboutSection).toContainText(status[0], {ignoreCase: true}) } 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()) + await expect(this.hasKidsAboutSection).toContainText(numberOfKids) } async verifyWantChildrenExpectation(expectation: [string, number] | undefined) { if (!expectation) return const [label, _value] = expectation await expect(this.wantsKidsAboutSection).toBeVisible() - const textContent = await this.wantsKidsAboutSection.textContent() - await expect(textContent?.toLowerCase()).toContain(label.toLowerCase()) + await expect(this.wantsKidsAboutSection).toContainText(label, {ignoreCase: true}) } 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()) + await expect(this.interestsAboutSection).toContainText(interest[i], {ignoreCase: true}) } } 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()) + await expect(this.causesAboutSection).toContainText(causes[i], {ignoreCase: true}) } } @@ -412,86 +404,76 @@ export class ProfilePage { 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[0].toLowerCase()) - if (university) await expect(textContent?.toLowerCase()).toContain(university.toLowerCase()) + await expect(this.educationAboutSection).toContainText(educationLevel[0], {ignoreCase: true}) + if (university) await expect(this.educationAboutSection).toContainText(university, {ignoreCase: true}) } 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()) + if (jobTitle) await expect(this.occupationAboutSection).toContainText(jobTitle, {ignoreCase: true}) + if (company) await expect(this.occupationAboutSection).toContainText(company, {ignoreCase: true}) } 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[0].toLowerCase()) - if (details) await expect(textContent?.toLowerCase()).toContain(details.toLowerCase()) + if (belief) await expect(this.politicalAboutSection).toContainText(belief[0], {ignoreCase: true}) + if (details) await expect(this.politicalAboutSection).toContainText(details, {ignoreCase: true}) } 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[0].toLowerCase()) - if (details) await expect(textContent?.toLowerCase()).toContain(details.toLowerCase()) + if (belief) await expect(this.relegiousAboutSection).toContainText(belief[0], {ignoreCase: true}) + if (details) await expect(this.relegiousAboutSection).toContainText(details, {ignoreCase: true}) } 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()) + await expect(this.personalityAboutSection).toContainText(personalityType, {ignoreCase: true}) } 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(String(value)) + await expect(this.bigFivePersonalityTraitsAboutSection).toContainText(key, {ignoreCase: true}) + await expect(this.bigFivePersonalityTraitsAboutSection).toContainText(String(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[0].toLowerCase()) + await expect(this.dietAboutSection).toContainText(diet[0], {ignoreCase: true}) } 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 === true) await expect(this.smokerAboutSection).toContainText('Smokes', {ignoreCase: true}) if (smoker === false) - await expect(textContent?.toLowerCase()).toContain("Doesn't smoke".toLowerCase()) + await expect(this.smokerAboutSection).toContainText("Doesn't smoke", {ignoreCase: true}) } async verifyDrinksPerMonth(drinks: string | undefined) { + if (!drinks) return await expect(this.drinkerAboutSection).toBeVisible() - const textContent = await this.drinkerAboutSection.textContent() - await expect(textContent?.toLowerCase()).toContain(drinks) + await expect(this.drinkerAboutSection).toContainText(drinks) } async verifyLanguages(languages: LanguageTuple[] | undefined) { if (!languages || languages.length === 0) return await expect(this.languagesAboutSection).toBeVisible() - const textContent = await this.languagesAboutSection.textContent() for (const language of languages) { - await expect(textContent?.toLowerCase()).toContain(language[0].toLowerCase()) + await expect(this.languagesAboutSection).toContainText(language[0], {ignoreCase: true}) } } async verifySocialMedia(socialMedia: Socials[] | undefined) { if (!socialMedia || socialMedia.length === 0) return await expect(this.socialMediaSection).toBeVisible() - const textContent = await this.socialMediaSection.textContent() for (const {urlOrUsername} of socialMedia) { - await expect(textContent?.toLowerCase()).toContain(urlOrUsername.toLowerCase()) + await expect(this.socialMediaSection).toContainText(urlOrUsername, {ignoreCase: true}) } } diff --git a/tests/e2e/web/pages/signUpPage.ts b/tests/e2e/web/pages/signUpPage.ts index e725d154..7411a788 100644 --- a/tests/e2e/web/pages/signUpPage.ts +++ b/tests/e2e/web/pages/signUpPage.ts @@ -179,9 +179,9 @@ export class SignUpPage { async chooseGender(gender: GenderTuple | undefined) { if (!gender) return - await expect(this.page.locator(`span:has-text("${gender[0]}")`)).toBeVisible() - await this.page.locator(`span:has-text("${gender[0]}")`).click() - await expect(this.page.locator(`span:has-text("${gender[0]}")`)).toBeChecked() + await expect(this.page.locator(`:text-is("${gender[0]}")`)).toBeVisible() + await this.page.locator(`:text-is("${gender[0]}")`).click() + await expect(this.page.locator(`:text-is("${gender[0]}")`)).toBeChecked() } async fillAge(age: string | undefined) { diff --git a/tests/e2e/web/specs/onboardingFlow.spec.ts b/tests/e2e/web/specs/onboardingFlow.spec.ts index a6aadb0e..c000fae9 100644 --- a/tests/e2e/web/specs/onboardingFlow.spec.ts +++ b/tests/e2e/web/specs/onboardingFlow.spec.ts @@ -232,6 +232,100 @@ test.describe('when given valid input', () => { await profilePage.clickCloseButton() await onboardingPage.clickRefineProfileButton() + //Verify displayed information is correct + await profilePage.verifyDisplayNameAndAge(fakerAccount.display_name) + + //Verify database info + const dbInfo = await userInformationFromDb(fakerAccount) + + await expect(dbInfo.user.name).toContain(fakerAccount.display_name) + await expect(dbInfo.user.username).toContain(fakerAccount.username) + }) + + test('should successfully enter optional information after completing flow', async ({ + homePage, + onboardingPage, + signUpPage, + authPage, + profilePage, + fakerAccount, + }) => { + console.log( + `Starting "should successfully enter optional information after completing flow" with ${fakerAccount.username}`, + ) + 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 optional information + await profilePage.clickCloseButton() + await onboardingPage.clickRefineProfileButton() + await profilePage.clickEditProfileButton() + await signUpPage.chooseGender(fakerAccount.gender) + await signUpPage.fillAge(fakerAccount.age) + await signUpPage.fillHeight({ + feet: fakerAccount.height?.feet, + inches: fakerAccount.height?.inches, + }) + await signUpPage.saveProfileChanges() + + //Verify displayed information is correct + await profilePage.verifyDisplayNameAndAge(fakerAccount.display_name, fakerAccount.age) + await profilePage.verifyGenderLocationHeight( + fakerAccount.gender, + undefined, + fakerAccount.height?.feet, + fakerAccount.height?.inches, + ) + + //Verify database info + const dbInfo = await userInformationFromDb(fakerAccount) + + await expect(dbInfo.user.name).toContain(fakerAccount.display_name) + await expect(dbInfo.user.username).toContain(fakerAccount.username) + await expect(dbInfo.profile.gender).toEqual(fakerAccount.gender?.[1]) + await expect(String(dbInfo.profile.age)).toEqual(fakerAccount.age) + await expect(dbInfo.profile.height_in_inches).toEqual(Number(fakerAccount.height?.feet) * 12) + }) + + test('should successfully use the start answering option', async ({ + homePage, + onboardingPage, + signUpPage, + authPage, + profilePage, + fakerAccount, + testAccount, + }) => { + console.log( + `Starting "should successfully use the start answering option" with ${fakerAccount.username}`, + ) + 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 optional information + await profilePage.clickStartAnsweringButton() + const compatTwoQuestionOne = await profilePage.answerCompatibilityQuestion(testAccount.compatibility) + await profilePage.clickNextCompatibilityQuestionButton() + await profilePage.clickCloseButton() + await onboardingPage.clickRefineProfileButton() + + //Verify displayed information is correct + await profilePage.verifyDisplayNameAndAge(fakerAccount.display_name) + await profilePage.verifyCompatibilityAnswers(compatTwoQuestionOne) + + //Verify database info const dbInfo = await userInformationFromDb(fakerAccount) await expect(dbInfo.user.name).toContain(fakerAccount.display_name) @@ -267,6 +361,10 @@ test.describe('when given valid input', () => { await profilePage.clickCloseButton() await onboardingPage.clickRefineProfileButton() + //Verify displayed information is correct + await profilePage.verifyDisplayNameAndAge(fakerAccount.display_name) + + //Verify database info const dbInfo = await userInformationFromDb(fakerAccount) await expect(dbInfo.user.name).toContain(fakerAccount.display_name) @@ -292,6 +390,10 @@ test.describe('when given valid input', () => { await profilePage.clickCloseButton() await onboardingPage.clickRefineProfileButton() + //Verify displayed information is correct + await profilePage.verifyDisplayNameAndAge(fakerAccount.display_name) + + //Verify database info const dbInfo = await userInformationFromDb(fakerAccount) await expect(dbInfo.user.name).toContain(fakerAccount.display_name) diff --git a/tests/e2e/web/utils/accountInformation.ts b/tests/e2e/web/utils/accountInformation.ts index 603ddcb4..5797f668 100644 --- a/tests/e2e/web/utils/accountInformation.ts +++ b/tests/e2e/web/utils/accountInformation.ts @@ -111,6 +111,13 @@ export const onboarding: OnboardingConfig = { password: faker.internet.password(), display_name: faker.internet.displayName(), username: `user_${id}`, + gender: ["Man", "male"], + age: '35', + height: { + feet: '5', + inches: '0', + centimeters: '152.4', + }, } }, From 09d16c977264371f0199779f99d73d77d456a4b0 Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams Date: Thu, 5 Mar 2026 19:50:26 +0000 Subject: [PATCH 07/19] Linting and Prettier --- tests/e2e/web/pages/profilePage.ts | 28 ++++++++++++++-------- tests/e2e/web/specs/onboardingFlow.spec.ts | 4 +++- tests/e2e/web/utils/accountInformation.ts | 2 +- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/tests/e2e/web/pages/profilePage.ts b/tests/e2e/web/pages/profilePage.ts index 3f9b3e99..3c872ed7 100644 --- a/tests/e2e/web/pages/profilePage.ts +++ b/tests/e2e/web/pages/profilePage.ts @@ -64,8 +64,8 @@ export class ProfilePage { private readonly profileCompatibilityExplanation: Locator constructor(public readonly page: Page) { - this.startAnsweringButton = page.getByRole('button', { name: 'Start answering' }) - this.doThisLaterLink = page.getByRole('button', { name: 'Do this later' }) + this.startAnsweringButton = page.getByRole('button', {name: 'Start answering'}) + this.doThisLaterLink = page.getByRole('button', {name: 'Do this later'}) this.closeButton = page.getByRole('button', {name: 'Close'}) this.shareButton = page.getByRole('button', {name: 'Share'}) this.editProfileButton = page.getByTestId('profile-edit') @@ -355,8 +355,10 @@ export class ProfilePage { async verifyRelationShipTypeAndInterest(type?: string[], interest?: string[]) { await expect(this.relationshipTypeAboutSection).toBeVisible() - if (type) await expect(this.relationshipTypeAboutSection).toContainText(type[0], {ignoreCase: true}) - if (interest) await expect(this.relationshipTypeAboutSection).toContainText(interest[0], {ignoreCase: true}) + if (type) + await expect(this.relationshipTypeAboutSection).toContainText(type[0], {ignoreCase: true}) + if (interest) + await expect(this.relationshipTypeAboutSection).toContainText(interest[0], {ignoreCase: true}) } async verifyRelationshipStatus(status: string[] | undefined) { @@ -406,24 +408,29 @@ export class ProfilePage { await expect(this.educationAboutSection).toBeVisible() if (educationLevel) await expect(this.educationAboutSection).toContainText(educationLevel[0], {ignoreCase: true}) - if (university) await expect(this.educationAboutSection).toContainText(university, {ignoreCase: true}) + if (university) + await expect(this.educationAboutSection).toContainText(university, {ignoreCase: true}) } async verifyJobInformation(jobTitle?: string, company?: string) { await expect(this.occupationAboutSection).toBeVisible() - if (jobTitle) await expect(this.occupationAboutSection).toContainText(jobTitle, {ignoreCase: true}) - if (company) await expect(this.occupationAboutSection).toContainText(company, {ignoreCase: true}) + if (jobTitle) + await expect(this.occupationAboutSection).toContainText(jobTitle, {ignoreCase: true}) + if (company) + await expect(this.occupationAboutSection).toContainText(company, {ignoreCase: true}) } async verifyPoliticalBeliefs(belief?: string[], details?: string) { await expect(this.politicalAboutSection).toBeVisible() - if (belief) await expect(this.politicalAboutSection).toContainText(belief[0], {ignoreCase: true}) + if (belief) + await expect(this.politicalAboutSection).toContainText(belief[0], {ignoreCase: true}) if (details) await expect(this.politicalAboutSection).toContainText(details, {ignoreCase: true}) } async verifyReligiousBeliefs(belief?: string[], details?: string) { await expect(this.relegiousAboutSection).toBeVisible() - if (belief) await expect(this.relegiousAboutSection).toContainText(belief[0], {ignoreCase: true}) + if (belief) + await expect(this.relegiousAboutSection).toContainText(belief[0], {ignoreCase: true}) if (details) await expect(this.relegiousAboutSection).toContainText(details, {ignoreCase: true}) } @@ -450,7 +457,8 @@ export class ProfilePage { async verifySmoker(smoker: boolean | undefined) { await expect(this.smokerAboutSection).toBeVisible() - if (smoker === true) await expect(this.smokerAboutSection).toContainText('Smokes', {ignoreCase: true}) + if (smoker === true) + await expect(this.smokerAboutSection).toContainText('Smokes', {ignoreCase: true}) if (smoker === false) await expect(this.smokerAboutSection).toContainText("Doesn't smoke", {ignoreCase: true}) } diff --git a/tests/e2e/web/specs/onboardingFlow.spec.ts b/tests/e2e/web/specs/onboardingFlow.spec.ts index c000fae9..f4aa1cf6 100644 --- a/tests/e2e/web/specs/onboardingFlow.spec.ts +++ b/tests/e2e/web/specs/onboardingFlow.spec.ts @@ -316,7 +316,9 @@ test.describe('when given valid input', () => { await signUpPage.clickNextButton() await signUpPage.clickNextButton() //Skip optional information await profilePage.clickStartAnsweringButton() - const compatTwoQuestionOne = await profilePage.answerCompatibilityQuestion(testAccount.compatibility) + const compatTwoQuestionOne = await profilePage.answerCompatibilityQuestion( + testAccount.compatibility, + ) await profilePage.clickNextCompatibilityQuestionButton() await profilePage.clickCloseButton() await onboardingPage.clickRefineProfileButton() diff --git a/tests/e2e/web/utils/accountInformation.ts b/tests/e2e/web/utils/accountInformation.ts index 5797f668..8415981a 100644 --- a/tests/e2e/web/utils/accountInformation.ts +++ b/tests/e2e/web/utils/accountInformation.ts @@ -111,7 +111,7 @@ export const onboarding: OnboardingConfig = { password: faker.internet.password(), display_name: faker.internet.displayName(), username: `user_${id}`, - gender: ["Man", "male"], + gender: ['Man', 'male'], age: '35', height: { feet: '5', From e57e25541b33f3ce976d63b40b7a360f4002a431 Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams Date: Wed, 11 Mar 2026 17:04:54 +0000 Subject: [PATCH 08/19] Fix: Merge conflict --- .../answer-compatibility-question-content.tsx | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/web/components/answers/answer-compatibility-question-content.tsx b/web/components/answers/answer-compatibility-question-content.tsx index 029cfe5d..d40af5e1 100644 --- a/web/components/answers/answer-compatibility-question-content.tsx +++ b/web/components/answers/answer-compatibility-question-content.tsx @@ -33,7 +33,6 @@ export const IMPORTANCE_CHOICES = { Important: 2, 'Very Important': 3, } as const -} as const type ImportanceColorsType = { [key: number]: string @@ -176,9 +175,6 @@ export function AnswerCompatibilityQuestionContent(props: { {shortenedPopularity && ( -
{compatibilityQuestion.question}
- {shortenedPopularity && ( - ) => @@ -313,7 +308,6 @@ export const SelectAnswer = (props: { const {value, setValue, options} = props return ( clsx( disabled @@ -353,7 +346,6 @@ export const MultiSelectAnswers = (props: { return ( Date: Thu, 12 Mar 2026 17:18:04 +0000 Subject: [PATCH 09/19] Fix: Modified sortedAndFilteredAnswers to use "UseMemo" so that it doesnt run every time something changes --- web/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/README.md b/web/README.md index 3fa82f20..3e7d90a3 100644 --- a/web/README.md +++ b/web/README.md @@ -220,7 +220,6 @@ Catches React errors and shows user-friendly message: ```tsx import {ErrorBoundary} from 'web/components/error-boundary' - ; @@ -250,7 +249,6 @@ Keyboard users can skip to main content: ```tsx import {SkipLink, MainContent} from 'web/components/skip-link' - ;<> ... From 9a023ef8a0a3a1c12a6c039489e9e0ca55aeb833 Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams Date: Thu, 12 Mar 2026 17:42:38 +0000 Subject: [PATCH 10/19] . --- tests/e2e/web/specs/onboardingFlow.spec.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/e2e/web/specs/onboardingFlow.spec.ts b/tests/e2e/web/specs/onboardingFlow.spec.ts index f4aa1cf6..27f14572 100644 --- a/tests/e2e/web/specs/onboardingFlow.spec.ts +++ b/tests/e2e/web/specs/onboardingFlow.spec.ts @@ -233,7 +233,7 @@ test.describe('when given valid input', () => { await onboardingPage.clickRefineProfileButton() //Verify displayed information is correct - await profilePage.verifyDisplayNameAndAge(fakerAccount.display_name) + await profilePage.verifyDisplayName(fakerAccount.display_name) //Verify database info const dbInfo = await userInformationFromDb(fakerAccount) @@ -275,12 +275,13 @@ test.describe('when given valid input', () => { await signUpPage.saveProfileChanges() //Verify displayed information is correct - await profilePage.verifyDisplayNameAndAge(fakerAccount.display_name, fakerAccount.age) - await profilePage.verifyGenderLocationHeight( + await profilePage.verifyDisplayName(fakerAccount.display_name) + await profilePage.verifyGenderLocationHeightAge( fakerAccount.gender, undefined, fakerAccount.height?.feet, fakerAccount.height?.inches, + fakerAccount.age, ) //Verify database info @@ -324,7 +325,7 @@ test.describe('when given valid input', () => { await onboardingPage.clickRefineProfileButton() //Verify displayed information is correct - await profilePage.verifyDisplayNameAndAge(fakerAccount.display_name) + await profilePage.verifyDisplayName(fakerAccount.display_name) await profilePage.verifyCompatibilityAnswers(compatTwoQuestionOne) //Verify database info @@ -364,7 +365,7 @@ test.describe('when given valid input', () => { await onboardingPage.clickRefineProfileButton() //Verify displayed information is correct - await profilePage.verifyDisplayNameAndAge(fakerAccount.display_name) + await profilePage.verifyDisplayName(fakerAccount.display_name) //Verify database info const dbInfo = await userInformationFromDb(fakerAccount) @@ -393,7 +394,7 @@ test.describe('when given valid input', () => { await onboardingPage.clickRefineProfileButton() //Verify displayed information is correct - await profilePage.verifyDisplayNameAndAge(fakerAccount.display_name) + await profilePage.verifyDisplayName(fakerAccount.display_name) //Verify database info const dbInfo = await userInformationFromDb(fakerAccount) From de83492820e68e55237c26fef9eb076e6978b117 Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams Date: Fri, 13 Mar 2026 19:32:32 +0000 Subject: [PATCH 11/19] . --- playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright.config.ts b/playwright.config.ts index 094ee5a4..047574cf 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -28,7 +28,7 @@ function getSupabaseEnv() { const supabaseEnv = getSupabaseEnv() // Inject into process.env so Playwright and your app code can read them -Object.assign(process.env, supabaseEnv) +// Object.assign(process.env, supabaseEnv) export default defineConfig({ testDir: './tests/e2e', From 863658bf56a659cce1a981587262797d05790f7f Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams Date: Fri, 13 Mar 2026 20:46:46 +0000 Subject: [PATCH 12/19] Merged "verifyInterestedInConnectingWith" and "verifyRelationShipTypeAndInterest" into "verifySeeking" to match ui changes --- tests/e2e/web/pages/profilePage.ts | 14 +++----------- tests/e2e/web/specs/onboardingFlow.spec.ts | 4 +--- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/tests/e2e/web/pages/profilePage.ts b/tests/e2e/web/pages/profilePage.ts index 3c872ed7..342ae1c6 100644 --- a/tests/e2e/web/pages/profilePage.ts +++ b/tests/e2e/web/pages/profilePage.ts @@ -29,7 +29,6 @@ export class ProfilePage { 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 @@ -90,7 +89,6 @@ export class ProfilePage { 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') @@ -346,19 +344,13 @@ export class ProfilePage { await expect(this.ethnicityAboutSection).toContainText(origin, {ignoreCase: true}) } - async verifyInterestedInConnectingWith(gender?: string[], minAge?: string, maxAge?: string) { + async verifySeeking(gender?: string[], minAge?: string, maxAge?: string, type?: string[], interest?: string[]) { await expect(this.seekingAboutSection).toBeVisible() if (gender) await expect(this.seekingAboutSection).toContainText(gender[0], {ignoreCase: true}) if (minAge) await expect(this.seekingAboutSection).toContainText(minAge) if (maxAge) await expect(this.seekingAboutSection).toContainText(maxAge) - } - - async verifyRelationShipTypeAndInterest(type?: string[], interest?: string[]) { - await expect(this.relationshipTypeAboutSection).toBeVisible() - if (type) - await expect(this.relationshipTypeAboutSection).toContainText(type[0], {ignoreCase: true}) - if (interest) - await expect(this.relationshipTypeAboutSection).toContainText(interest[0], {ignoreCase: true}) + if (type) await expect(this.seekingAboutSection).toContainText(type[0], {ignoreCase: true}) + if (interest) await expect(this.seekingAboutSection).toContainText(interest[0], {ignoreCase: true}) } async verifyRelationshipStatus(status: string[] | undefined) { diff --git a/tests/e2e/web/specs/onboardingFlow.spec.ts b/tests/e2e/web/specs/onboardingFlow.spec.ts index 27f14572..ea71836d 100644 --- a/tests/e2e/web/specs/onboardingFlow.spec.ts +++ b/tests/e2e/web/specs/onboardingFlow.spec.ts @@ -102,12 +102,10 @@ test.describe('when given valid input', () => { testAccount.height?.inches, testAccount.age, ) - await profilePage.verifyInterestedInConnectingWith( + await profilePage.verifySeeking( testAccount.interested_in, testAccount.Interested_in_ages?.min, testAccount.Interested_in_ages?.max, - ) - await profilePage.verifyRelationShipTypeAndInterest( testAccount.connection_type, testAccount.relationship_style, ) From 1f0ad4c8ebc99781ddd1af281341fe18e5fdef9f Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams Date: Fri, 13 Mar 2026 22:04:58 +0000 Subject: [PATCH 13/19] Added error message outlining the minimum character requirement for display names and usernames --- web/components/required-profile-form.tsx | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/web/components/required-profile-form.tsx b/web/components/required-profile-form.tsx index 2f90092b..a191bf01 100644 --- a/web/components/required-profile-form.tsx +++ b/web/components/required-profile-form.tsx @@ -49,13 +49,25 @@ export const RequiredProfileUserForm = (props: { const [step, setStep] = useState(0) const [loadingUsername, setLoadingUsername] = useState(false) const [isSubmitting, setIsSubmitting] = useState(false) - const [errorUsername, setErrorUsername] = useState('') + const [errorUsername, setErrorUsername] = useState(null) + const [displayNameError, setDisplayNameError] = useState(null) const t = useT() const updateUsername = async () => { let success = true setLoadingUsername(true) try { + if (data.name.length === 0 || (data.name.length > 0 && data.name.length < 3)) { + setDisplayNameError('Minimum 3 characters for display names') + } else { + setDisplayNameError(null) + } + if (data.username.length === 0) { + setErrorUsername('Minimum 3 characters required for usernames') + success = false + setLoadingUsername(false) + return success + } const { valid, message = undefined, @@ -94,13 +106,16 @@ export const RequiredProfileUserForm = (props: { ) => { - setData('name', e.target.value || '') + const value = e.target.value || '' + setData('name', value) }} /> + {displayNameError &&

{displayNameError}

} )} From 2fb07453f6be302124c0eca057b149148327d254 Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams Date: Sat, 14 Mar 2026 22:24:14 +0000 Subject: [PATCH 14/19] Updated displayName error message to show when editing the user profile post signup --- web/components/required-profile-form.tsx | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/web/components/required-profile-form.tsx b/web/components/required-profile-form.tsx index a191bf01..f995bfce 100644 --- a/web/components/required-profile-form.tsx +++ b/web/components/required-profile-form.tsx @@ -57,12 +57,8 @@ export const RequiredProfileUserForm = (props: { let success = true setLoadingUsername(true) try { - if (data.name.length === 0 || (data.name.length > 0 && data.name.length < 3)) { - setDisplayNameError('Minimum 3 characters for display names') - } else { - setDisplayNameError(null) - } - if (data.username.length === 0) { + const usernameForErrorMsg = data.username.length + if (usernameForErrorMsg === 0 || (usernameForErrorMsg > 0 && usernameForErrorMsg < 3)) { setErrorUsername('Minimum 3 characters required for usernames') success = false setLoadingUsername(false) @@ -111,6 +107,11 @@ export const RequiredProfileUserForm = (props: { value={data.name || ''} onChange={(e: React.ChangeEvent) => { const value = e.target.value || '' + if (value.length === 0 || (value.length > 0 && value.length < 3)) { + setDisplayNameError('Minimum 3 characters for display names') + } else { + setDisplayNameError(null) + } setData('name', value) }} /> @@ -133,7 +134,13 @@ export const RequiredProfileUserForm = (props: { placeholder="Username" value={data.username || ''} onChange={(e: React.ChangeEvent) => { - setData('username', e.target.value || '') + const value = e.target.value || '' + if (value.length === 0 || (value.length > 0 && value.length < 3)) { + setErrorUsername('Minimum 3 characters required for usernames') + } else { + setErrorUsername(null) + } + setData('username', value) }} /> {loadingUsername && } From 64856b451fe2ab75793d2af74f727775301eae72 Mon Sep 17 00:00:00 2001 From: Okechi Jones-Williams Date: Sun, 15 Mar 2026 17:57:48 +0000 Subject: [PATCH 15/19] Fix: Added fix for None discriptive error issue #36 Updated signUp.spec.ts to use new fixture Updated Account information variable names Deleted "deleteUserFixture.ts" as it was incorporated into the "base.ts" file --- tests/e2e/web/fixtures/base.ts | 19 +- tests/e2e/web/fixtures/deleteUserFixture.ts | 48 ---- tests/e2e/web/pages/AuthPage.ts | 5 + tests/e2e/web/pages/signUpPage.ts | 18 +- tests/e2e/web/specs/onboardingFlow.spec.ts | 242 ++++++++++---------- tests/e2e/web/specs/signUp.spec.ts | 67 ++++-- tests/e2e/web/utils/accountInformation.ts | 47 +++- tests/e2e/web/utils/deleteUser.ts | 2 +- web/components/required-profile-form.tsx | 23 +- 9 files changed, 258 insertions(+), 213 deletions(-) delete mode 100644 tests/e2e/web/fixtures/deleteUserFixture.ts diff --git a/tests/e2e/web/fixtures/base.ts b/tests/e2e/web/fixtures/base.ts index 277f5887..23ec87fc 100644 --- a/tests/e2e/web/fixtures/base.ts +++ b/tests/e2e/web/fixtures/base.ts @@ -6,7 +6,7 @@ import {HomePage} from '../pages/homePage' import {OnboardingPage} from '../pages/onboardingPage' import {ProfilePage} from '../pages/profilePage' import {SignUpPage} from '../pages/signUpPage' -import {onboarding, OnboardingUser} from '../utils/accountInformation' +import {testAccounts, UserAccountInformation} from '../utils/accountInformation' import {deleteUser} from '../utils/deleteUser' export const test = base.extend<{ @@ -17,21 +17,28 @@ export const test = base.extend<{ authPage: AuthPage compatabilityPage: ComatibilityPage cleanUpUsers: void - testAccount: OnboardingUser - fakerAccount: OnboardingUser + onboardingAccount: UserAccountInformation + fakerAccount: UserAccountInformation + specAccount: UserAccountInformation }>({ - testAccount: async ({}, use) => { - const account = onboarding.account_one() // email captured here + onboardingAccount: async ({}, use) => { + const account = testAccounts.account_all_info() // email captured here await use(account) console.log('Cleaning up onboarding 1 account...') await deleteUser(account.email, account.password) // same account, guaranteed }, fakerAccount: async ({}, use) => { - const account = onboarding.faker_account() // email captured here + const account = testAccounts.faker_account() // email captured here await use(account) console.log('Cleaning up faker account...') await deleteUser(account.email, account.password) // same account, guaranteed }, + specAccount: async ({}, use) => { + const account = testAccounts.spec_account() + await use(account) + console.log('Cleaning up spec account...') + await deleteUser(account.email, account.password) + }, onboardingPage: async ({page}, use) => { const onboardingPage = new OnboardingPage(page) await use(onboardingPage) diff --git a/tests/e2e/web/fixtures/deleteUserFixture.ts b/tests/e2e/web/fixtures/deleteUserFixture.ts deleted file mode 100644 index 583c4335..00000000 --- a/tests/e2e/web/fixtures/deleteUserFixture.ts +++ /dev/null @@ -1,48 +0,0 @@ -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'; - -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 axios.post(`${config.FIREBASE_URL.BASE}${config.FIREBASE_URL.DELETE}`, { - idToken: login.data.idToken, - }) - } catch (err: any) { - // Skip deletion if user doesn't exist or other auth errors occur - if ( - err.response?.status === 400 || - err.response?.data?.error?.message?.includes('EMAIL_NOT_FOUND') - ) { - return - } - console.log(err) - } -} - -type CleanupFixtures = { - cleanupUsers: void -} - -export const test = base.extend({ - cleanupUsers: [ - async ({}, use) => { - // Run all tests first - await use() - - //then delete users - await deleteUser(config.USERS.SPEC.EMAIL, config.USERS.SPEC.PASSWORD) - }, - {auto: true}, - ], -}) diff --git a/tests/e2e/web/pages/AuthPage.ts b/tests/e2e/web/pages/AuthPage.ts index c3c56107..36b33ece 100644 --- a/tests/e2e/web/pages/AuthPage.ts +++ b/tests/e2e/web/pages/AuthPage.ts @@ -21,22 +21,27 @@ export class AuthPage { } async clickSignInLink() { + await expect(this.signInLink).toBeVisible() await this.signInLink.click() } async clickSignUpButton() { + await expect(this.signUpButton).toBeVisible() await this.signUpButton.click() } async clickSignInWithEmailButton() { + await expect(this.signInWithEmailButton).toBeVisible() await this.signInWithEmailButton.click() } async clickSignInWithGoogleButton() { + await expect(this.signInWithGoogleButton).toBeVisible() await this.signInWithGoogleButton.click() } async clickSignUpWithEmailButton() { + await expect(this.signUpWithEmailButton).toBeVisible() await this.signUpWithEmailButton.click() } diff --git a/tests/e2e/web/pages/signUpPage.ts b/tests/e2e/web/pages/signUpPage.ts index 7411a788..56246e5d 100644 --- a/tests/e2e/web/pages/signUpPage.ts +++ b/tests/e2e/web/pages/signUpPage.ts @@ -45,7 +45,9 @@ export type Platforms = export class SignUpPage { private readonly displayNameField: Locator + private readonly displayNameError: Locator private readonly usernameField: Locator + private readonly usernameError: Locator private readonly nextButton: Locator private readonly bioField: Locator private readonly locationField: Locator @@ -101,7 +103,9 @@ export class SignUpPage { constructor(public readonly page: Page) { this.displayNameField = page.getByPlaceholder('Display name') + this.displayNameError = page.getByTestId('signup-display-name') this.usernameField = page.getByPlaceholder('Username') + this.usernameError = page.getByTestId('signup-username') this.nextButton = page.getByRole('button', {name: 'Next', exact: true}) this.bioField = page.locator('.tiptap') this.locationField = page.getByPlaceholder('Search city...') @@ -155,6 +159,10 @@ export class SignUpPage { this.saveButton = page.getByRole('button', {name: 'Save'}) } + get nextButtonLocator(): Locator { + return this.nextButton + } + async fillUsername(username: string) { await expect(this.usernameField).toBeVisible() await this.usernameField.fill(username) @@ -716,4 +724,12 @@ export class SignUpPage { await expect(this.keywordsField).toBeVisible() await this.keywordsField.fill(keywords) } -} + + async verifyDisplayNameError() { + await expect(this.displayNameError).toBeVisible() + } + + async verifyUsernameError() { + await expect(this.usernameError).toBeVisible() + } +} \ No newline at end of file diff --git a/tests/e2e/web/specs/onboardingFlow.spec.ts b/tests/e2e/web/specs/onboardingFlow.spec.ts index ea71836d..e92b17de 100644 --- a/tests/e2e/web/specs/onboardingFlow.spec.ts +++ b/tests/e2e/web/specs/onboardingFlow.spec.ts @@ -8,82 +8,82 @@ test.describe('when given valid input', () => { signUpPage, authPage, profilePage, - testAccount, + onboardingAccount, }) => { console.log( - `Starting "should successfully complete the onboarding flow" with ${testAccount.username}`, + `Starting "should successfully complete the onboarding flow" with ${onboardingAccount.username}`, ) await homePage.gotToHomePage() await homePage.clickSignUpButton() - await authPage.fillEmailField(testAccount.email) - await authPage.fillPasswordField(testAccount.password) + await authPage.fillEmailField(onboardingAccount.email) + await authPage.fillPasswordField(onboardingAccount.password) await authPage.clickSignUpWithEmailButton() await onboardingPage.clickContinueButton() //First continue await onboardingPage.clickContinueButton() //Second continue await onboardingPage.clickGetStartedButton() - await signUpPage.fillDisplayName(testAccount.display_name) - await signUpPage.fillUsername(testAccount.username) + await signUpPage.fillDisplayName(onboardingAccount.display_name) + await signUpPage.fillUsername(onboardingAccount.username) await signUpPage.clickNextButton() - await signUpPage.chooseGender(testAccount.gender) - await signUpPage.fillAge(testAccount.age) + await signUpPage.chooseGender(onboardingAccount.gender) + await signUpPage.fillAge(onboardingAccount.age) await signUpPage.fillHeight({ - feet: testAccount.height?.feet, - inches: testAccount.height?.inches, + feet: onboardingAccount.height?.feet, + inches: onboardingAccount.height?.inches, }) - await signUpPage.fillEthnicity(testAccount.ethnicity_origin) - await signUpPage.fillHeadline(testAccount.headline) - await signUpPage.fillKeywords(testAccount.keywords) - await signUpPage.fillInterestedInConnectingWith(testAccount.interested_in) + await signUpPage.fillEthnicity(onboardingAccount.ethnicity_origin) + await signUpPage.fillHeadline(onboardingAccount.headline) + await signUpPage.fillKeywords(onboardingAccount.keywords) + await signUpPage.fillInterestedInConnectingWith(onboardingAccount.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) + onboardingAccount.Interested_in_ages?.min, + onboardingAccount.Interested_in_ages?.max, + ) + await signUpPage.setConnectionType(onboardingAccount.connection_type) + await signUpPage.setRelationshipStatus(onboardingAccount.relationship_status) + await signUpPage.setRelationshipStyle(onboardingAccount.relationship_style) + await signUpPage.fillCurrentNumberOfChildren(onboardingAccount.number_of_kids) + await signUpPage.setWantChildrenExpectation(onboardingAccount.children_expectation) + await signUpPage.setInterests(onboardingAccount.interests) + await signUpPage.setCauses(onboardingAccount.causes) + await signUpPage.setHighestEducationLevel(onboardingAccount.education_level) + await signUpPage.fillUniversity(onboardingAccount.university) + await signUpPage.fillJobTitle(onboardingAccount.job_title) + await signUpPage.fillCompany(onboardingAccount.company) + await signUpPage.setWorkArea(onboardingAccount.work_area) await signUpPage.setPoliticalBeliefs( - testAccount.beliefs?.political?.belief, - testAccount.beliefs?.political?.details, + onboardingAccount.beliefs?.political?.belief, + onboardingAccount.beliefs?.political?.details, ) await signUpPage.setReligiousBeliefs( - testAccount.beliefs?.religious?.belief, - testAccount.beliefs?.religious?.details, + onboardingAccount.beliefs?.religious?.belief, + onboardingAccount.beliefs?.religious?.details, ) - await signUpPage.setPersonalityType(testAccount.personality_type) - await signUpPage.setOpennessPersonalityValue(testAccount.big_five_personality_traits?.openness) + await signUpPage.setPersonalityType(onboardingAccount.personality_type) + await signUpPage.setOpennessPersonalityValue(onboardingAccount.big_five_personality_traits?.openness) await signUpPage.setAgreeablenessPersonalityValue( - testAccount.big_five_personality_traits?.agreeableness, + onboardingAccount.big_five_personality_traits?.agreeableness, ) await signUpPage.setConscientiousnessPersonalityValue( - testAccount.big_five_personality_traits?.conscientiousness, + onboardingAccount.big_five_personality_traits?.conscientiousness, ) await signUpPage.setExtraversionPersonalityValue( - testAccount.big_five_personality_traits?.extraversion, + onboardingAccount.big_five_personality_traits?.extraversion, ) await signUpPage.setNeuroticismPersonalityValue( - testAccount.big_five_personality_traits?.neuroticism, - ) - 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.fillBio(testAccount.bio) + onboardingAccount.big_five_personality_traits?.neuroticism, + ) + await signUpPage.setDietType(onboardingAccount.diet) + await signUpPage.setIsSmoker(onboardingAccount.is_smoker) + await signUpPage.fillAlcoholPerMonth(onboardingAccount.alcohol_consumed_per_month) + await signUpPage.setLanguages(onboardingAccount.languages) + await signUpPage.addSocialMediaPlatform(onboardingAccount.social_media) + await signUpPage.fillBio(onboardingAccount.bio) await signUpPage.clickNextButton() await profilePage.clickCloseButton() await onboardingPage.clickRefineProfileButton() await profilePage.clickAnswerQuestionsButton() const compatQuestionOne = await profilePage.answerCompatibilityQuestion( - testAccount.compatibility, + onboardingAccount.compatibility, ) await profilePage.clickNextCompatibilityQuestionButton() await profilePage.clickSkipCompatibilityQuestionButton() @@ -92,117 +92,117 @@ test.describe('when given valid input', () => { await profilePage.clickCloseButton() //Verify information is correct - await profilePage.verifyDisplayName(testAccount.display_name) - await profilePage.verifyHeadline(testAccount.headline) - await profilePage.verifyKeywords(testAccount.keywords) + await profilePage.verifyDisplayName(onboardingAccount.display_name) + await profilePage.verifyHeadline(onboardingAccount.headline) + await profilePage.verifyKeywords(onboardingAccount.keywords) await profilePage.verifyGenderLocationHeightAge( - testAccount.gender, + onboardingAccount.gender, undefined, - testAccount.height?.feet, - testAccount.height?.inches, - testAccount.age, + onboardingAccount.height?.feet, + onboardingAccount.height?.inches, + onboardingAccount.age, ) await profilePage.verifySeeking( - testAccount.interested_in, - testAccount.Interested_in_ages?.min, - testAccount.Interested_in_ages?.max, - 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) + onboardingAccount.interested_in, + onboardingAccount.Interested_in_ages?.min, + onboardingAccount.Interested_in_ages?.max, + onboardingAccount.connection_type, + onboardingAccount.relationship_style, + ) + await profilePage.verifyRelationshipStatus(onboardingAccount.relationship_status) + await profilePage.verifyCurrentNumberOfKids(onboardingAccount.number_of_kids) + await profilePage.verifyWantChildrenExpectation(onboardingAccount.children_expectation) + await profilePage.verifyInterests(onboardingAccount.interests) + await profilePage.verifyCauses(onboardingAccount.causes) await profilePage.verifyEducationLevelAndUniversity( - testAccount.education_level, - testAccount.university, + onboardingAccount.education_level, + onboardingAccount.university, ) - await profilePage.verifyJobInformation(testAccount.job_title, testAccount.company) - await profilePage.verifyWorkArea(testAccount.work_area) + await profilePage.verifyJobInformation(onboardingAccount.job_title, onboardingAccount.company) + await profilePage.verifyWorkArea(onboardingAccount.work_area) await profilePage.verifyPoliticalBeliefs( - testAccount.beliefs?.political?.belief, - testAccount.beliefs?.political?.details, + onboardingAccount.beliefs?.political?.belief, + onboardingAccount.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) - await profilePage.verifyBio(testAccount.bio) + onboardingAccount.beliefs?.religious?.belief, + onboardingAccount.beliefs?.religious?.details, + ) + await profilePage.verifyPersonalityType(onboardingAccount.personality_type) + await profilePage.verifyBigFivePersonalitySection(onboardingAccount.big_five_personality_traits) + await profilePage.verifyDiet(onboardingAccount.diet) + await profilePage.verifySmoker(onboardingAccount.is_smoker) + await profilePage.verifyDrinksPerMonth(onboardingAccount.alcohol_consumed_per_month) + await profilePage.verifyLanguages(onboardingAccount.languages) + await profilePage.verifySocialMedia(onboardingAccount.social_media) + await profilePage.verifyBio(onboardingAccount.bio) await profilePage.verifyCompatibilityAnswers(compatQuestionOne) //Verify Database Information - const dbInfo = await userInformationFromDb(testAccount) + const dbInfo = await userInformationFromDb(onboardingAccount) console.log(dbInfo.profile) - await expect(dbInfo.user.name).toBe(testAccount.display_name) - await expect(dbInfo.user.username).toBe(testAccount.username) - await expect(dbInfo.profile.bio_text).toBe(testAccount.bio) - await expect(dbInfo.profile.gender).toEqual(testAccount.gender?.[1]) - await expect(dbInfo.profile.headline).toEqual(testAccount.headline) + await expect(dbInfo.user.name).toBe(onboardingAccount.display_name) + await expect(dbInfo.user.username).toBe(onboardingAccount.username) + await expect(dbInfo.profile.bio_text).toBe(onboardingAccount.bio) + await expect(dbInfo.profile.gender).toEqual(onboardingAccount.gender?.[1]) + await expect(dbInfo.profile.headline).toEqual(onboardingAccount.headline) await expect(dbInfo.profile.keywords).toEqual( - expect.arrayContaining(testAccount.keywords?.split(', ') ?? []), - ) - await expect(String(dbInfo.profile.age)).toEqual(testAccount.age) - await expect(dbInfo.profile.height_in_inches).toEqual(Number(testAccount.height?.feet) * 12) - await expect(dbInfo.profile.ethnicity).toContain(testAccount.ethnicity_origin?.[1]) - await expect(dbInfo.profile.pref_gender).toContain(testAccount.interested_in?.[1]) - await expect(String(dbInfo.profile.pref_age_min)).toContain(testAccount.Interested_in_ages?.min) - await expect(String(dbInfo.profile.pref_age_max)).toContain(testAccount.Interested_in_ages?.max) + expect.arrayContaining(onboardingAccount.keywords?.split(', ') ?? []), + ) + await expect(String(dbInfo.profile.age)).toEqual(onboardingAccount.age) + await expect(dbInfo.profile.height_in_inches).toEqual(Number(onboardingAccount.height?.feet) * 12) + await expect(dbInfo.profile.ethnicity).toContain(onboardingAccount.ethnicity_origin?.[1]) + await expect(dbInfo.profile.pref_gender).toContain(onboardingAccount.interested_in?.[1]) + await expect(String(dbInfo.profile.pref_age_min)).toContain(onboardingAccount.Interested_in_ages?.min) + await expect(String(dbInfo.profile.pref_age_max)).toContain(onboardingAccount.Interested_in_ages?.max) await expect(dbInfo.profile.pref_relation_styles).toContain( - `${testAccount.connection_type?.[1]}`.toLowerCase(), + `${onboardingAccount.connection_type?.[1]}`.toLowerCase(), ) - await expect(dbInfo.profile.relationship_status).toContain(testAccount.relationship_status?.[1]) - await expect(dbInfo.profile.pref_romantic_styles).toContain(testAccount.relationship_style?.[1]) - await expect(dbInfo.profile.has_kids).toEqual(Number(testAccount.number_of_kids)) - await expect(dbInfo.profile.wants_kids_strength).toEqual(testAccount.children_expectation?.[1]) + await expect(dbInfo.profile.relationship_status).toContain(onboardingAccount.relationship_status?.[1]) + await expect(dbInfo.profile.pref_romantic_styles).toContain(onboardingAccount.relationship_style?.[1]) + await expect(dbInfo.profile.has_kids).toEqual(Number(onboardingAccount.number_of_kids)) + await expect(dbInfo.profile.wants_kids_strength).toEqual(onboardingAccount.children_expectation?.[1]) await expect(dbInfo.profile.education_level).toContain( - `${testAccount.education_level?.[1]}`.toLowerCase(), + `${onboardingAccount.education_level?.[1]}`.toLowerCase(), ) - await expect(dbInfo.profile.university).toContain(testAccount.university) - await expect(dbInfo.profile.occupation_title).toContain(testAccount.job_title) - await expect(dbInfo.profile.company).toContain(testAccount.company) + await expect(dbInfo.profile.university).toContain(onboardingAccount.university) + await expect(dbInfo.profile.occupation_title).toContain(onboardingAccount.job_title) + await expect(dbInfo.profile.company).toContain(onboardingAccount.company) await expect(dbInfo.profile.political_beliefs).toContain( - testAccount.beliefs?.political?.belief?.[1], + onboardingAccount.beliefs?.political?.belief?.[1], ) await expect(dbInfo.profile.political_details).toContain( - testAccount.beliefs?.political?.details, + onboardingAccount.beliefs?.political?.details, ) - await expect(dbInfo.profile.religion).toContain(testAccount.beliefs?.religious?.belief?.[1]) + await expect(dbInfo.profile.religion).toContain(onboardingAccount.beliefs?.religious?.belief?.[1]) await expect(dbInfo.profile.religious_beliefs).toContain( - testAccount.beliefs?.religious?.details, + onboardingAccount.beliefs?.religious?.details, ) - await expect(dbInfo.profile.mbti).toContain(`${testAccount.personality_type}`.toLowerCase()) + await expect(dbInfo.profile.mbti).toContain(`${onboardingAccount.personality_type}`.toLowerCase()) await expect(dbInfo.profile.big5_openness).toEqual( - testAccount.big_five_personality_traits?.openness, + onboardingAccount.big_five_personality_traits?.openness, ) await expect(dbInfo.profile.big5_conscientiousness).toEqual( - testAccount.big_five_personality_traits?.conscientiousness, + onboardingAccount.big_five_personality_traits?.conscientiousness, ) await expect(dbInfo.profile.big5_extraversion).toEqual( - testAccount.big_five_personality_traits?.extraversion, + onboardingAccount.big_five_personality_traits?.extraversion, ) await expect(dbInfo.profile.big5_agreeableness).toEqual( - testAccount.big_five_personality_traits?.agreeableness, + onboardingAccount.big_five_personality_traits?.agreeableness, ) await expect(dbInfo.profile.big5_neuroticism).toEqual( - testAccount.big_five_personality_traits?.neuroticism, + onboardingAccount.big_five_personality_traits?.neuroticism, ) - await expect(dbInfo.profile.diet).toContain(testAccount.diet?.[1].toLowerCase()) - await expect(dbInfo.profile.is_smoker).toEqual(testAccount.is_smoker) + await expect(dbInfo.profile.diet).toContain(onboardingAccount.diet?.[1].toLowerCase()) + await expect(dbInfo.profile.is_smoker).toEqual(onboardingAccount.is_smoker) await expect(dbInfo.profile.languages).toHaveLength(2) await expect(dbInfo.profile.languages).toEqual( - expect.arrayContaining(testAccount.languages?.map(([_, l]) => l.toLowerCase()) ?? []), + expect.arrayContaining(onboardingAccount.languages?.map(([_, l]) => l.toLowerCase()) ?? []), ) await expect(String(dbInfo.profile.drinks_per_month)).toEqual( - testAccount.alcohol_consumed_per_month, + onboardingAccount.alcohol_consumed_per_month, ) }) @@ -299,7 +299,7 @@ test.describe('when given valid input', () => { authPage, profilePage, fakerAccount, - testAccount, + onboardingAccount, }) => { console.log( `Starting "should successfully use the start answering option" with ${fakerAccount.username}`, @@ -316,7 +316,7 @@ test.describe('when given valid input', () => { await signUpPage.clickNextButton() //Skip optional information await profilePage.clickStartAnsweringButton() const compatTwoQuestionOne = await profilePage.answerCompatibilityQuestion( - testAccount.compatibility, + onboardingAccount.compatibility, ) await profilePage.clickNextCompatibilityQuestionButton() await profilePage.clickCloseButton() diff --git a/tests/e2e/web/specs/signUp.spec.ts b/tests/e2e/web/specs/signUp.spec.ts index 0434a27d..126ae4c0 100644 --- a/tests/e2e/web/specs/signUp.spec.ts +++ b/tests/e2e/web/specs/signUp.spec.ts @@ -1,22 +1,45 @@ -import {expect} from '@playwright/test' - -import {test} from '../fixtures/deleteUserFixture' -import {AuthPage} from '../pages/AuthPage' -import {config} from '../SPEC_CONFIG' - -test('user can sign up with email + password', async ({page}) => { - const auth = new AuthPage(page) - - await page.goto('/') - - await auth.clickSignUpButton() - - await auth.fillEmailField(config.USERS.SPEC.EMAIL) - await auth.fillPasswordField(config.USERS.SPEC.PASSWORD) - - await auth.clickSignUpWithEmailButton() - - await page.waitForURL(/^(?!.*\/signup).*$/) - - expect(page.url()).not.toContain('/signup') -}) +import {expect, test} from '../fixtures/base' + +test.describe('when given valid input', () => { + test('placeholder', async () => {}); +}); + +test.describe('when an error occurs', () => { + test('should disable the button "Next" when the display name field is empty', async ({ + specAccount, + homePage, + authPage, + onboardingPage, + signUpPage, + }) => { + await homePage.gotToHomePage() + await homePage.clickSignUpButton() + await authPage.fillEmailField(specAccount.email) + await authPage.fillPasswordField(specAccount.password) + await authPage.clickSignUpWithEmailButton() + await onboardingPage.clickSkipOnboardingButton() + await signUpPage.fillDisplayName('') + await signUpPage.fillUsername(specAccount.username) + await signUpPage.verifyDisplayNameError() + await expect(signUpPage.nextButtonLocator).toBeDisabled() + }) + + test('should disable the button "Next" when the username field is empty', async ({ + specAccount, + homePage, + authPage, + onboardingPage, + signUpPage, + }) => { + await homePage.gotToHomePage() + await homePage.clickSignUpButton() + await authPage.fillEmailField(specAccount.email) + await authPage.fillPasswordField(specAccount.password) + await authPage.clickSignUpWithEmailButton() + await onboardingPage.clickSkipOnboardingButton() + await signUpPage.fillDisplayName(specAccount.display_name) + await signUpPage.fillUsername('') + await signUpPage.verifyUsernameError() + await expect(signUpPage.nextButtonLocator).toBeDisabled() + }) +}); \ No newline at end of file diff --git a/tests/e2e/web/utils/accountInformation.ts b/tests/e2e/web/utils/accountInformation.ts index 8415981a..a8bb3fdb 100644 --- a/tests/e2e/web/utils/accountInformation.ts +++ b/tests/e2e/web/utils/accountInformation.ts @@ -17,7 +17,7 @@ import {ImportanceTuple} from 'web/components/answers/answer-compatibility-quest import {Causes, ChildrenExpectation, Interests, Platforms} from '../pages/signUpPage' -export type OnboardingUser = { +export type UserAccountInformation = { email: string password: string display_name: string @@ -97,12 +97,15 @@ type FiveBigPersonalityTraits = { neuroticism?: number } -type OnboardingConfig = { - faker_account: () => OnboardingUser - account_one: () => OnboardingUser +type AccountConfig = { + faker_account: () => UserAccountInformation + spec_account: () => UserAccountInformation + dev_one_account: () => UserAccountInformation + dev_two_account: () => UserAccountInformation + account_all_info: () => UserAccountInformation } -export const onboarding: OnboardingConfig = { +export const testAccounts: AccountConfig = { // Use a function so email is unique per test call faker_account: () => { const id = crypto.randomUUID().slice(0, 6) @@ -121,11 +124,41 @@ export const onboarding: OnboardingConfig = { } }, - account_one: () => { + spec_account: () => { + const id = crypto.randomUUID().slice(0, 6) + return { + email: `spec${id}@compass.com`, + password: 'compassConnections1!', + display_name: 'Spec.Compass', + username: `Spec.Connections_${id}`, + } + }, + + dev_one_account: () => { + const id = crypto.randomUUID().slice(0, 6) + return { + email: `dev_1_${id}@compass.com`, + password: 'dev_1Password', + display_name: 'Dev1.Compass', + username: `Dev1.Connections_${id}`, + } + }, + + dev_two_account: () => { + const id = crypto.randomUUID().slice(0, 6) + return { + email: 'dev_2@compass.com', + password: 'dev_2Password', + display_name: 'Dev2.Compass', + username: `Dev2.Connections_${id}`, + } + }, + + account_all_info: () => { const id = crypto.randomUUID().slice(0, 6) return { // Use a non-real TLD like @test.compass to make it obvious these are test accounts and prevent accidental emails - email: `onboarding${id}@test.compass`, + email: `testAccounts${id}@test.compass`, password: 'CompassTest', display_name: 'Compass Onboarding', username: `TheGreatOnboarding_${id}`, // username max length is 25 (see /create-user) diff --git a/tests/e2e/web/utils/deleteUser.ts b/tests/e2e/web/utils/deleteUser.ts index eca1da27..96968b22 100644 --- a/tests/e2e/web/utils/deleteUser.ts +++ b/tests/e2e/web/utils/deleteUser.ts @@ -4,8 +4,8 @@ import {deleteAccount, firebaseLogin} from '../../utils/firebaseUtils' export async function deleteUser(email: string, password: string) { try { const loginInfo = await firebaseLogin(email, password) - await deleteFromDb(loginInfo.data.localId) await deleteAccount(loginInfo) + await deleteFromDb(loginInfo.data.localId) } catch (err: any) { // Skip deletion if user doesn't exist or other auth errors occur if ( diff --git a/web/components/required-profile-form.tsx b/web/components/required-profile-form.tsx index f995bfce..dfd1373b 100644 --- a/web/components/required-profile-form.tsx +++ b/web/components/required-profile-form.tsx @@ -49,9 +49,10 @@ export const RequiredProfileUserForm = (props: { const [step, setStep] = useState(0) const [loadingUsername, setLoadingUsername] = useState(false) const [isSubmitting, setIsSubmitting] = useState(false) - const [errorUsername, setErrorUsername] = useState(null) - const [displayNameError, setDisplayNameError] = useState(null) + const [errorMessageUsername, setErrorUsername] = useState(null) + const [errorMessageDisplayName, setErrorDisplayName] = useState(null) const t = useT() + const isFormValid = !!(errorMessageDisplayName || errorMessageUsername || isSubmitting) const updateUsername = async () => { let success = true @@ -108,15 +109,19 @@ export const RequiredProfileUserForm = (props: { onChange={(e: React.ChangeEvent) => { const value = e.target.value || '' if (value.length === 0 || (value.length > 0 && value.length < 3)) { - setDisplayNameError('Minimum 3 characters for display names') + setErrorDisplayName('Minimum 3 characters for display names') } else { - setDisplayNameError(null) + setErrorDisplayName(null) } setData('name', value) }} />
- {displayNameError &&

{displayNameError}

} + {errorMessageDisplayName && ( +

+ {errorMessageDisplayName} +

+ )} )} @@ -153,7 +158,11 @@ export const RequiredProfileUserForm = (props: { )} } - {errorUsername && {errorUsername}} + {errorMessageUsername && ( + + {errorMessageUsername} + + )} )} @@ -176,7 +185,7 @@ export const RequiredProfileUserForm = (props: { {onSubmit && (