diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 5f1a5f5a..65f5a936 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -17,7 +17,7 @@ reviews: enabled: true # Skip auto-review if PR title contains these keywords ignore_title_keywords: - - "WIP" + - 'WIP' # Don't auto-review draft PRs drafts: false # Only auto-review PRs targeting these branches @@ -57,17 +57,17 @@ reviews: # Exclude these paths from reviews (build artifacts and dependencies) path_filters: - - "!**/node_modules/**" # npm dependencies - - "!**/android/**" # Native Android build files - - "!**/ios/**" # Native iOS build files - - "!**/.expo/**" # Expo build cache - - "!**/.expo-shared/**" # Expo shared config - - "!**/dist/**" # Build output + - '!**/node_modules/**' # npm dependencies + - '!**/android/**' # Native Android build files + - '!**/ios/**' # Native iOS build files + - '!**/.expo/**' # Expo build cache + - '!**/.expo-shared/**' # Expo shared config + - '!**/dist/**' # Build output # Custom review instructions for specific file patterns path_instructions: # TypeScript/JavaScript files - main app code - - path: "**/*.{ts,tsx,js,jsx}" + - path: '**/*.{ts,tsx,js,jsx}' instructions: | General practices: - Summarize the changes clearly. @@ -78,7 +78,7 @@ reviews: - Flag any hardcoded strings; they should be in the constants file. - Check for edge cases like null values or empty arrays. - Suggest performance optimizations where appropriate. - + Mobile best practices: - Proper use of hooks (useRouter, useFonts, useAssets) - Accessibility: touch targets min 44x44, screen reader support @@ -105,7 +105,7 @@ reviews: const message = t('key', 'english string') ``` - - path: "tests/e2e/**/*.ts" + - path: 'tests/e2e/**/*.ts' instructions: | Playwright E2E test guidelines for this repo: - Page objects live in `tests/e2e/web/pages/`. Each class wraps one page/route, holds only `private readonly` Locators, and exposes action methods. diff --git a/backend/api/tests/unit/get-profiles.unit.test.ts b/backend/api/tests/unit/get-profiles.unit.test.ts index 2fdc7995..1e1e8139 100644 --- a/backend/api/tests/unit/get-profiles.unit.test.ts +++ b/backend/api/tests/unit/get-profiles.unit.test.ts @@ -316,7 +316,7 @@ describe('loadProfiles', () => { }) describe('when an error occurs', () => { - it('throw if there is no compatability', async () => { + it('throw if there is no compatibility', async () => { const props = { orderBy: 'compatibility_score', } diff --git a/docs/TESTING.md b/docs/TESTING.md index 7a71f563..e84955b2 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -348,7 +348,6 @@ jest.mock('path/to/module') * This creates an object containing all named exports from ./path/to/module */ import * as mockModule from 'path/to/module' - ;(mockModule.module as jest.Mock).mockResolvedValue(mockReturnValue) ``` diff --git a/tests/e2e/tsconfig.json b/tests/e2e/tsconfig.json index 6bcaa938..a4583100 100644 --- a/tests/e2e/tsconfig.json +++ b/tests/e2e/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "rootDir": "../../", "module": "commonjs", "jsx": "react-jsx", "moduleResolution": "node", diff --git a/tests/e2e/utils/firebaseUtils.ts b/tests/e2e/utils/firebaseUtils.ts index a7c8f0ef..a68d468c 100644 --- a/tests/e2e/utils/firebaseUtils.ts +++ b/tests/e2e/utils/firebaseUtils.ts @@ -1,5 +1,4 @@ import axios from 'axios' - import {config} from '../web/SPEC_CONFIG' export async function firebaseLoginEmailPassword( diff --git a/tests/e2e/web/fixtures/base.ts b/tests/e2e/web/fixtures/base.ts index fcd40d17..4fe2f1dd 100644 --- a/tests/e2e/web/fixtures/base.ts +++ b/tests/e2e/web/fixtures/base.ts @@ -1,29 +1,11 @@ import {test as base} from '@playwright/test' - -import {AuthPage} from '../pages/AuthPage' -import {ComatibilityPage} from '../pages/compatibilityPage' -import {HomePage} from '../pages/homePage' -import {OnboardingPage} from '../pages/onboardingPage' -import {OrganizationPage} from '../pages/organizationPage' -import {ProfilePage} from '../pages/profilePage' -import {SettingsPage} from '../pages/settingsPage' -import {SignUpPage} from '../pages/signUpPage' -import {SocialPage} from '../pages/socialPage' import {testAccounts, UserAccountInformation} from '../utils/accountInformation' import {deleteUser} from '../utils/deleteUser' import {getAuthAccountInfo} from '../utils/networkUtils' +import {App} from '../pages/app' export const test = base.extend<{ - homePage: HomePage - onboardingPage: OnboardingPage - signUpPage: SignUpPage - profilePage: ProfilePage - authPage: AuthPage - settingsPage: SettingsPage - socialPage: SocialPage - organizationPage: OrganizationPage - compatabilityPage: ComatibilityPage - cleanUpUsers: void + app: App onboardingAccount: UserAccountInformation fakerAccount: UserAccountInformation specAccount: UserAccountInformation @@ -62,41 +44,9 @@ export const test = base.extend<{ console.log('Cleaning up spec account...') await deleteUser('Email/Password', 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) - }, - compatabilityPage: async ({page}, use) => { - const compatibilityPage = new ComatibilityPage(page) - await use(compatibilityPage) - }, - settingsPage: async ({page}, use) => { - const settingsPage = new SettingsPage(page) - await use(settingsPage) - }, - socialPage: async ({page}, use) => { - const socialPage = new SocialPage(page) - await use(socialPage) - }, - organizationPage: async ({page}, use) => { - const organizationPage = new OrganizationPage(page) - await use(organizationPage) + app: async ({page}, use) => { + const appPage = new App(page) + await use(appPage) }, }) diff --git a/tests/e2e/web/fixtures/signInFixture.ts b/tests/e2e/web/fixtures/signInFixture.ts index 47c5b727..4167054f 100644 --- a/tests/e2e/web/fixtures/signInFixture.ts +++ b/tests/e2e/web/fixtures/signInFixture.ts @@ -1,47 +1,17 @@ import {test as base} from '@playwright/test' -import {AuthPage} from '../pages/AuthPage' -import {HomePage} from '../pages/homePage' +import {App} from '../pages/app' import {testAccounts, UserAccountInformation} from '../utils/accountInformation' -import { OnboardingPage } from '../pages/onboardingPage' -import { SignUpPage } from '../pages/signUpPage' -import { ProfilePage } from '../pages/profilePage' -import { SettingsPage } from '../pages/settingsPage' export const test = base.extend<{ - homePage: HomePage - onboardingPage: OnboardingPage - signUpPage: SignUpPage - profilePage: ProfilePage - settingsPage: SettingsPage - authPage: AuthPage + app: App dev_one_account: UserAccountInformation fakerAccount: UserAccountInformation googleAccountOne: UserAccountInformation googleAccountTwo: UserAccountInformation }>({ - homePage: async ({page}, use) => { - const homePage = new HomePage(page) - await use(homePage) - }, - onboardingPage: async ({page}, use) => { - const onboardingPage = new OnboardingPage(page) - await use(onboardingPage) - }, - signUpPage: async ({page}, use) => { - const signUpPage = new SignUpPage(page) - await use(signUpPage) - }, - profilePage: async ({page}, use) => { - const profilePage = new ProfilePage(page) - await use(profilePage) - }, - settingsPage: async ({page}, use) => { - const settingsPage = new SettingsPage(page) - await use(settingsPage) - }, - authPage: async ({page}, use) => { - const authPage = new AuthPage(page) - await use(authPage) + app: async ({page}, use) => { + const appPage = new App(page) + await use(appPage) }, dev_one_account: async ({}, use) => { const account = testAccounts.dev_one_account() diff --git a/tests/e2e/web/pages/app.ts b/tests/e2e/web/pages/app.ts new file mode 100644 index 00000000..d8ed56c3 --- /dev/null +++ b/tests/e2e/web/pages/app.ts @@ -0,0 +1,75 @@ +import {Page} from '@playwright/test' +import {UserAccountInformation} from '../utils/accountInformation' +import {AuthPage} from './authPage' +import {ComatibilityPage} from './compatibilityPage' +import {HomePage} from './homePage' +import {OnboardingPage} from './onboardingPage' +import {OrganizationPage} from './organizationPage' +import {ProfilePage} from './profilePage' +import {SettingsPage} from './settingsPage' +import {SignUpPage} from './signUpPage' +import {SocialPage} from './socialPage' + +export class App { + readonly auth: AuthPage + readonly compatibility: ComatibilityPage + readonly home: HomePage + readonly onboarding: OnboardingPage + readonly organization: OrganizationPage + readonly profile: ProfilePage + readonly settings: SettingsPage + readonly signUp: SignUpPage + readonly social: SocialPage + + constructor(public readonly page: Page) { + this.auth = new AuthPage(page) + this.compatibility = new ComatibilityPage(page) + this.home = new HomePage(page) + this.onboarding = new OnboardingPage(page) + this.organization = new OrganizationPage(page) + this.profile = new ProfilePage(page) + this.settings = new SettingsPage(page) + this.signUp = new SignUpPage(page) + this.social = new SocialPage(page) + } + + async deleteProfileFromSettings() { + await this.home.clickSettingsLink() + await this.settings.clickDeleteAccountButton() + await this.settings.fillDeleteAccountSurvey('Delete me') + await this.settings.clickDeleteAccountButton() + await this.home.verifyHomePageLinks() + } + + async skipOnboardingHeadToProfile(account: UserAccountInformation) { + await this.onboarding.clickSkipOnboardingButton() + await this.signUp.fillDisplayName(account.display_name) + await this.signUp.fillUsername(account.username) + await this.signUp.clickNextButton() + await this.signUp.clickNextButton() + await this.profile.clickCloseButton() + await this.onboarding.clickRefineProfileButton() + } + + async registerWithEmail(account: UserAccountInformation) { + await this.home.goToRegisterPage() + await this.auth.fillEmailField(account.email) + await this.auth.fillPasswordField(account.password) + await this.auth.clickSignUpWithEmailButton() + } + + async signinWithEmail(accountOrEmail: UserAccountInformation | string, password?: string) { + const email = typeof accountOrEmail === 'string' ? accountOrEmail : accountOrEmail.email + + const resolvedPassword = typeof accountOrEmail === 'string' ? password : accountOrEmail.password + + if (!email || !resolvedPassword) { + throw new Error('Provide either an `account` or `email` and `password`.') + } + + await this.home.goToSigninPage() + await this.auth.fillEmailField(email) + await this.auth.fillPasswordField(resolvedPassword) + await this.auth.clickSignInWithEmailButton() + } +} diff --git a/tests/e2e/web/pages/AuthPage.ts b/tests/e2e/web/pages/authPage.ts similarity index 100% rename from tests/e2e/web/pages/AuthPage.ts rename to tests/e2e/web/pages/authPage.ts diff --git a/tests/e2e/web/specs/onboardingFlow.spec.ts b/tests/e2e/web/specs/onboardingFlow.spec.ts index a433ee85..f26d490c 100644 --- a/tests/e2e/web/specs/onboardingFlow.spec.ts +++ b/tests/e2e/web/specs/onboardingFlow.spec.ts @@ -1,138 +1,133 @@ import {userInformationFromDb} from '../../utils/databaseUtils' import {expect, test} from '../fixtures/base' -import {registerWithEmail, skipOnboardingHeadToProfile} from '../utils/testCleanupHelpers' test.describe('when given valid input', () => { test('should successfully complete the onboarding flow with email', async ({ - homePage, - onboardingPage, - signUpPage, - authPage, - profilePage, + app, onboardingAccount, }) => { - await registerWithEmail(homePage, authPage, onboardingAccount) - await onboardingPage.clickContinueButton() //First continue - await onboardingPage.clickContinueButton() //Second continue - await onboardingPage.clickGetStartedButton() - await signUpPage.fillDisplayName(onboardingAccount.display_name) - await signUpPage.fillUsername(onboardingAccount.username) - await signUpPage.clickNextButton() - await signUpPage.chooseGender(onboardingAccount.gender) - await signUpPage.fillAge(onboardingAccount.age) - await signUpPage.fillHeight({ + await app.registerWithEmail(onboardingAccount) + await app.onboarding.clickContinueButton() //First continue + await app.onboarding.clickContinueButton() //Second continue + await app.onboarding.clickGetStartedButton() + await app.signUp.fillDisplayName(onboardingAccount.display_name) + await app.signUp.fillUsername(onboardingAccount.username) + await app.signUp.clickNextButton() + await app.signUp.chooseGender(onboardingAccount.gender) + await app.signUp.fillAge(onboardingAccount.age) + await app.signUp.fillHeight({ feet: onboardingAccount.height?.feet, inches: onboardingAccount.height?.inches, }) - 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( + await app.signUp.fillEthnicity(onboardingAccount.ethnicity_origin) + await app.signUp.fillHeadline(onboardingAccount.headline) + await app.signUp.fillKeywords(onboardingAccount.keywords) + await app.signUp.fillInterestedInConnectingWith(onboardingAccount.interested_in) + await app.signUp.fillAgeRangeInterest( 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( + await app.signUp.setConnectionType(onboardingAccount.connection_type) + await app.signUp.setRelationshipStatus(onboardingAccount.relationship_status) + await app.signUp.setRelationshipStyle(onboardingAccount.relationship_style) + await app.signUp.fillCurrentNumberOfChildren(onboardingAccount.number_of_kids) + await app.signUp.setWantChildrenExpectation(onboardingAccount.children_expectation) + await app.signUp.setInterests(onboardingAccount.interests) + await app.signUp.setCauses(onboardingAccount.causes) + await app.signUp.setHighestEducationLevel(onboardingAccount.education_level) + await app.signUp.fillUniversity(onboardingAccount.university) + await app.signUp.fillJobTitle(onboardingAccount.job_title) + await app.signUp.fillCompany(onboardingAccount.company) + await app.signUp.setWorkArea(onboardingAccount.work_area) + await app.signUp.setPoliticalBeliefs( onboardingAccount.beliefs?.political?.belief, onboardingAccount.beliefs?.political?.details, ) - await signUpPage.setReligiousBeliefs( + await app.signUp.setReligiousBeliefs( onboardingAccount.beliefs?.religious?.belief, onboardingAccount.beliefs?.religious?.details, ) - await signUpPage.setPersonalityType(onboardingAccount.personality_type) - await signUpPage.setOpennessPersonalityValue( + await app.signUp.setPersonalityType(onboardingAccount.personality_type) + await app.signUp.setOpennessPersonalityValue( onboardingAccount.big_five_personality_traits?.openness, ) - await signUpPage.setAgreeablenessPersonalityValue( + await app.signUp.setAgreeablenessPersonalityValue( onboardingAccount.big_five_personality_traits?.agreeableness, ) - await signUpPage.setConscientiousnessPersonalityValue( + await app.signUp.setConscientiousnessPersonalityValue( onboardingAccount.big_five_personality_traits?.conscientiousness, ) - await signUpPage.setExtraversionPersonalityValue( + await app.signUp.setExtraversionPersonalityValue( onboardingAccount.big_five_personality_traits?.extraversion, ) - await signUpPage.setNeuroticismPersonalityValue( + await app.signUp.setNeuroticismPersonalityValue( 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( + await app.signUp.setDietType(onboardingAccount.diet) + await app.signUp.setIsSmoker(onboardingAccount.is_smoker) + await app.signUp.fillAlcoholPerMonth(onboardingAccount.alcohol_consumed_per_month) + await app.signUp.setLanguages(onboardingAccount.languages) + await app.signUp.addSocialMediaPlatform(onboardingAccount.social_media) + await app.signUp.fillBio(onboardingAccount.bio) + await app.signUp.clickNextButton() + await app.profile.clickCloseButton() + await app.onboarding.clickRefineProfileButton() + await app.profile.clickAnswerQuestionsButton() + const compatQuestionOne = await app.profile.answerCompatibilityQuestion( onboardingAccount.compatibility, ) - await profilePage.clickNextCompatibilityQuestionButton() - await profilePage.clickSkipCompatibilityQuestionButton() - await profilePage.clickSkipCompatibilityQuestionButton() + await app.profile.clickNextCompatibilityQuestionButton() + await app.profile.clickSkipCompatibilityQuestionButton() + await app.profile.clickSkipCompatibilityQuestionButton() - await profilePage.clickCloseButton() + await app.profile.clickCloseButton() //Verify information is correct - await profilePage.verifyDisplayName(onboardingAccount.display_name) - await profilePage.verifyHeadline(onboardingAccount.headline) - await profilePage.verifyKeywords(onboardingAccount.keywords) - await profilePage.verifyGenderLocationHeightAge( + await app.profile.verifyDisplayName(onboardingAccount.display_name) + await app.profile.verifyHeadline(onboardingAccount.headline) + await app.profile.verifyKeywords(onboardingAccount.keywords) + await app.profile.verifyGenderLocationHeightAge( onboardingAccount.gender, undefined, onboardingAccount.height?.feet, onboardingAccount.height?.inches, onboardingAccount.age, ) - await profilePage.verifySeeking( + await app.profile.verifySeeking( 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( + await app.profile.verifyRelationshipStatus(onboardingAccount.relationship_status) + await app.profile.verifyCurrentNumberOfKids(onboardingAccount.number_of_kids) + await app.profile.verifyWantChildrenExpectation(onboardingAccount.children_expectation) + await app.profile.verifyInterests(onboardingAccount.interests) + await app.profile.verifyCauses(onboardingAccount.causes) + await app.profile.verifyEducationLevelAndUniversity( onboardingAccount.education_level, onboardingAccount.university, ) - await profilePage.verifyJobInformation(onboardingAccount.job_title, onboardingAccount.company) - await profilePage.verifyWorkArea(onboardingAccount.work_area) - await profilePage.verifyPoliticalBeliefs( + await app.profile.verifyJobInformation(onboardingAccount.job_title, onboardingAccount.company) + await app.profile.verifyWorkArea(onboardingAccount.work_area) + await app.profile.verifyPoliticalBeliefs( onboardingAccount.beliefs?.political?.belief, onboardingAccount.beliefs?.political?.details, ) - await profilePage.verifyReligiousBeliefs( + await app.profile.verifyReligiousBeliefs( 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) + await app.profile.verifyPersonalityType(onboardingAccount.personality_type) + await app.profile.verifyBigFivePersonalitySection(onboardingAccount.big_five_personality_traits) + await app.profile.verifyDiet(onboardingAccount.diet) + await app.profile.verifySmoker(onboardingAccount.is_smoker) + await app.profile.verifyDrinksPerMonth(onboardingAccount.alcohol_consumed_per_month) + await app.profile.verifyLanguages(onboardingAccount.languages) + await app.profile.verifySocialMedia(onboardingAccount.social_media) + await app.profile.verifyBio(onboardingAccount.bio) + await app.profile.verifyCompatibilityAnswers(compatQuestionOne) //Verify Database Information const dbInfo = await userInformationFromDb(onboardingAccount) @@ -219,26 +214,22 @@ test.describe('when given valid input', () => { }) test('should successfully complete the onboarding flow with google account', async ({ - homePage, - onboardingPage, - signUpPage, - authPage, - profilePage, + app, googleAccountOne, headless, }) => { test.skip(headless, 'Google popup auth test requires headed mode') - await homePage.goToRegisterPage() - await authPage.fillPasswordField('') //The test only passes when this is added...something is weird here - await authPage.signInToGoogleAccount( + await app.home.goToRegisterPage() + await app.auth.fillPasswordField('') //The test only passes when this is added...something is weird here + await app.auth.signInToGoogleAccount( googleAccountOne.email, googleAccountOne.display_name, googleAccountOne.username, ) - await skipOnboardingHeadToProfile(onboardingPage, signUpPage, profilePage, googleAccountOne) + await app.skipOnboardingHeadToProfile(googleAccountOne) //Verify displayed information is correct - await profilePage.verifyDisplayName(googleAccountOne.display_name) + await app.profile.verifyDisplayName(googleAccountOne.display_name) //Verify database info const dbInfo = await userInformationFromDb(googleAccountOne) @@ -247,19 +238,12 @@ test.describe('when given valid input', () => { await expect(dbInfo.user.username).toContain(googleAccountOne.username) }) - test('should successfully skip the onboarding flow', async ({ - homePage, - onboardingPage, - signUpPage, - authPage, - profilePage, - fakerAccount, - }) => { - await registerWithEmail(homePage, authPage, fakerAccount) - await skipOnboardingHeadToProfile(onboardingPage, signUpPage, profilePage, fakerAccount) + test('should successfully skip the onboarding flow', async ({app, fakerAccount}) => { + await app.registerWithEmail(fakerAccount) + await app.skipOnboardingHeadToProfile(fakerAccount) //Verify displayed information is correct - await profilePage.verifyDisplayName(fakerAccount.display_name) + await app.profile.verifyDisplayName(fakerAccount.display_name) //Verify database info const dbInfo = await userInformationFromDb(fakerAccount) @@ -269,27 +253,23 @@ test.describe('when given valid input', () => { }) test('should successfully enter optional information after completing flow', async ({ - homePage, - onboardingPage, - signUpPage, - authPage, - profilePage, + app, fakerAccount, }) => { - await registerWithEmail(homePage, authPage, fakerAccount) - await skipOnboardingHeadToProfile(onboardingPage, signUpPage, profilePage, fakerAccount) - await profilePage.clickEditProfileButton() - await signUpPage.chooseGender(fakerAccount.gender) - await signUpPage.fillAge(fakerAccount.age) - await signUpPage.fillHeight({ + await app.registerWithEmail(fakerAccount) + await app.skipOnboardingHeadToProfile(fakerAccount) + await app.profile.clickEditProfileButton() + await app.signUp.chooseGender(fakerAccount.gender) + await app.signUp.fillAge(fakerAccount.age) + await app.signUp.fillHeight({ feet: fakerAccount.height?.feet, inches: fakerAccount.height?.inches, }) - await signUpPage.saveProfileChanges() + await app.signUp.saveProfileChanges() //Verify displayed information is correct - await profilePage.verifyDisplayName(fakerAccount.display_name) - await profilePage.verifyGenderLocationHeightAge( + await app.profile.verifyDisplayName(fakerAccount.display_name) + await app.profile.verifyGenderLocationHeightAge( fakerAccount.gender, undefined, fakerAccount.height?.feet, @@ -308,31 +288,27 @@ test.describe('when given valid input', () => { }) test('should successfully use the start answering option', async ({ - homePage, - onboardingPage, - signUpPage, - authPage, - profilePage, + app, fakerAccount, onboardingAccount, }) => { - await registerWithEmail(homePage, authPage, fakerAccount) - 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( + await app.registerWithEmail(fakerAccount) + await app.onboarding.clickSkipOnboardingButton() + await app.signUp.fillDisplayName(fakerAccount.display_name) + await app.signUp.fillUsername(fakerAccount.username) + await app.signUp.clickNextButton() + await app.signUp.clickNextButton() //Skip optional information + await app.profile.clickStartAnsweringButton() + const compatTwoQuestionOne = await app.profile.answerCompatibilityQuestion( onboardingAccount.compatibility, ) - await profilePage.clickNextCompatibilityQuestionButton() - await profilePage.clickCloseButton() - await onboardingPage.clickRefineProfileButton() + await app.profile.clickNextCompatibilityQuestionButton() + await app.profile.clickCloseButton() + await app.onboarding.clickRefineProfileButton() //Verify displayed information is correct - await profilePage.verifyDisplayName(fakerAccount.display_name) - await profilePage.verifyCompatibilityAnswers(compatTwoQuestionOne) + await app.profile.verifyDisplayName(fakerAccount.display_name) + await app.profile.verifyCompatibilityAnswers(compatTwoQuestionOne) //Verify database info const dbInfo = await userInformationFromDb(fakerAccount) @@ -342,29 +318,22 @@ test.describe('when given valid input', () => { }) test.describe('should successfully complete the onboarding flow after using the back button', () => { - test("the first time it's an option", async ({ - homePage, - authPage, - onboardingPage, - signUpPage, - profilePage, - fakerAccount, - }) => { - await registerWithEmail(homePage, authPage, fakerAccount) - await onboardingPage.clickContinueButton() - await onboardingPage.clickBackButton() - await onboardingPage.clickContinueButton() - await onboardingPage.clickContinueButton() - await onboardingPage.clickGetStartedButton() - 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() + test("the first time it's an option", async ({app, fakerAccount}) => { + await app.registerWithEmail(fakerAccount) + await app.onboarding.clickContinueButton() + await app.onboarding.clickBackButton() + await app.onboarding.clickContinueButton() + await app.onboarding.clickContinueButton() + await app.onboarding.clickGetStartedButton() + await app.signUp.fillDisplayName(fakerAccount.display_name) + await app.signUp.fillUsername(fakerAccount.username) + await app.signUp.clickNextButton() + await app.signUp.clickNextButton() //Skip optional information + await app.profile.clickCloseButton() + await app.onboarding.clickRefineProfileButton() //Verify displayed information is correct - await profilePage.verifyDisplayName(fakerAccount.display_name) + await app.profile.verifyDisplayName(fakerAccount.display_name) //Verify database info const dbInfo = await userInformationFromDb(fakerAccount) @@ -373,29 +342,22 @@ test.describe('when given valid input', () => { await expect(dbInfo.user.username).toContain(fakerAccount.username) }) - test("the second time it's an option", async ({ - homePage, - authPage, - onboardingPage, - signUpPage, - profilePage, - fakerAccount, - }) => { - await registerWithEmail(homePage, authPage, fakerAccount) - await onboardingPage.clickContinueButton() - await onboardingPage.clickContinueButton() - await onboardingPage.clickBackButton() - await onboardingPage.clickContinueButton() - await onboardingPage.clickGetStartedButton() - 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() + test("the second time it's an option", async ({app, fakerAccount}) => { + await app.registerWithEmail(fakerAccount) + await app.onboarding.clickContinueButton() + await app.onboarding.clickContinueButton() + await app.onboarding.clickBackButton() + await app.onboarding.clickContinueButton() + await app.onboarding.clickGetStartedButton() + await app.signUp.fillDisplayName(fakerAccount.display_name) + await app.signUp.fillUsername(fakerAccount.username) + await app.signUp.clickNextButton() + await app.signUp.clickNextButton() //Skip optional information + await app.profile.clickCloseButton() + await app.onboarding.clickRefineProfileButton() //Verify displayed information is correct - await profilePage.verifyDisplayName(fakerAccount.display_name) + await app.profile.verifyDisplayName(fakerAccount.display_name) //Verify database info const dbInfo = await userInformationFromDb(fakerAccount) diff --git a/tests/e2e/web/specs/signIn.spec.ts b/tests/e2e/web/specs/signIn.spec.ts index a2755816..2c602ac2 100644 --- a/tests/e2e/web/specs/signIn.spec.ts +++ b/tests/e2e/web/specs/signIn.spec.ts @@ -2,12 +2,6 @@ import {userInformationFromDb} from '../../utils/databaseUtils' import {seedUser} from '../../utils/seedDatabase' import {expect, test} from '../fixtures/signInFixture' import {testAccounts} from '../utils/accountInformation' -import { - deleteProfileFromSettings, - registerWithEmail, - signinWithEmail, - skipOnboardingHeadToProfile, -} from '../utils/testCleanupHelpers' //Seed the account test.beforeAll(async () => { @@ -26,30 +20,21 @@ test.beforeAll(async () => { }) test.describe('when given valid input', () => { - test('should be able to sign in to an available account', async ({ - homePage, - authPage, - dev_one_account, - }) => { - await signinWithEmail(homePage, authPage, dev_one_account) - await homePage.goToHomePage() - await homePage.verifySignedInHomePage(dev_one_account.display_name) + test('should be able to sign in to an available account', async ({app, dev_one_account}) => { + await app.signinWithEmail(dev_one_account) + await app.home.goToHomePage() + await app.home.verifySignedInHomePage(dev_one_account.display_name) }) test('should successfully delete an account created via email and password', async ({ - homePage, - onboardingPage, - signUpPage, - authPage, - profilePage, - settingsPage, + app, fakerAccount, }) => { - await registerWithEmail(homePage, authPage, fakerAccount) - await skipOnboardingHeadToProfile(onboardingPage, signUpPage, profilePage, fakerAccount) + await app.registerWithEmail(fakerAccount) + await app.skipOnboardingHeadToProfile(fakerAccount) //Verify displayed information is correct - await profilePage.verifyDisplayName(fakerAccount.display_name) + await app.profile.verifyDisplayName(fakerAccount.display_name) //Verify database info const dbInfo = await userInformationFromDb(fakerAccount) @@ -57,31 +42,26 @@ test.describe('when given valid input', () => { await expect(dbInfo.user.name).toContain(fakerAccount.display_name) await expect(dbInfo.user.username).toContain(fakerAccount.username) - await deleteProfileFromSettings(homePage, settingsPage) + await app.deleteProfileFromSettings() }) test('should successfully delete an account created via google auth', async ({ - homePage, - onboardingPage, - signUpPage, - authPage, - profilePage, - settingsPage, + app, googleAccountTwo, headless, }) => { test.skip(headless, 'Google popup auth test requires headed mode') - await homePage.goToRegisterPage() - await authPage.fillPasswordField('') //The test only passes when this is added...something is weird here - await authPage.signInToGoogleAccount( + await app.home.goToRegisterPage() + await app.auth.fillPasswordField('') //The test only passes when this is added...something is weird here + await app.auth.signInToGoogleAccount( googleAccountTwo.email, googleAccountTwo.display_name, googleAccountTwo.username, ) - await skipOnboardingHeadToProfile(onboardingPage, signUpPage, profilePage, googleAccountTwo) + await app.skipOnboardingHeadToProfile(googleAccountTwo) //Verify displayed information is correct - await profilePage.verifyDisplayName(googleAccountTwo.display_name) + await app.profile.verifyDisplayName(googleAccountTwo.display_name) //Verify database info const dbInfo = await userInformationFromDb(googleAccountTwo) @@ -89,18 +69,17 @@ test.describe('when given valid input', () => { await expect(dbInfo.user.name).toContain(googleAccountTwo.display_name) await expect(dbInfo.user.username).toContain(googleAccountTwo.username) - await deleteProfileFromSettings(homePage, settingsPage) + await app.deleteProfileFromSettings() }) }) test.describe('when given invalid input', () => { test('should not be able to sign in to an available account', async ({ - homePage, - authPage, + app, dev_one_account, page, }) => { - await signinWithEmail(homePage, authPage, dev_one_account.email, 'ThisPassword') + await app.signinWithEmail(dev_one_account.email, 'ThisPassword') await expect( page.getByText('Failed to sign in with your email and password', {exact: true}), ).toBeVisible() diff --git a/tests/e2e/web/specs/signUp.spec.ts b/tests/e2e/web/specs/signUp.spec.ts index 65f2afbe..53562129 100644 --- a/tests/e2e/web/specs/signUp.spec.ts +++ b/tests/e2e/web/specs/signUp.spec.ts @@ -1,5 +1,4 @@ import {expect, test} from '../fixtures/base' -import {registerWithEmail} from '../utils/testCleanupHelpers' // test.describe('when given valid input', () => { // test('placeholder', async () => {}) @@ -8,31 +7,25 @@ import {registerWithEmail} from '../utils/testCleanupHelpers' 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, + app, }) => { - await registerWithEmail(homePage, authPage, specAccount) - await onboardingPage.clickSkipOnboardingButton() - await signUpPage.fillDisplayName('') - await signUpPage.fillUsername(specAccount.username) - await signUpPage.verifyDisplayNameError() - await expect(signUpPage.nextButtonLocator).toBeDisabled() + await app.registerWithEmail(specAccount) + await app.onboarding.clickSkipOnboardingButton() + await app.signUp.fillDisplayName('') + await app.signUp.fillUsername(specAccount.username) + await app.signUp.verifyDisplayNameError() + await expect(app.signUp.nextButtonLocator).toBeDisabled() }) test('should disable the button "Next" when the username field is empty', async ({ specAccount, - homePage, - authPage, - onboardingPage, - signUpPage, + app, }) => { - await registerWithEmail(homePage, authPage, specAccount) - await onboardingPage.clickSkipOnboardingButton() - await signUpPage.fillDisplayName(specAccount.display_name) - await signUpPage.fillUsername('') - await signUpPage.verifyUsernameError() - await expect(signUpPage.nextButtonLocator).toBeDisabled() + await app.registerWithEmail(specAccount) + await app.onboarding.clickSkipOnboardingButton() + await app.signUp.fillDisplayName(specAccount.display_name) + await app.signUp.fillUsername('') + await app.signUp.verifyUsernameError() + await expect(app.signUp.nextButtonLocator).toBeDisabled() }) }) diff --git a/tests/e2e/web/utils/testCleanupHelpers.ts b/tests/e2e/web/utils/testCleanupHelpers.ts deleted file mode 100644 index c022028d..00000000 --- a/tests/e2e/web/utils/testCleanupHelpers.ts +++ /dev/null @@ -1,64 +0,0 @@ -import {AuthPage} from '../pages/AuthPage' -import {HomePage} from '../pages/homePage' -import { OnboardingPage } from '../pages/onboardingPage' -import { ProfilePage } from '../pages/profilePage' -import { SettingsPage } from '../pages/settingsPage' -import { SignUpPage } from '../pages/signUpPage' -import {UserAccountInformation} from '../utils/accountInformation' - -export async function registerWithEmail( - homePage: HomePage, - authPage: AuthPage, - account: UserAccountInformation, -) { - await homePage.goToRegisterPage() - await authPage.fillEmailField(account.email) - await authPage.fillPasswordField(account.password) - await authPage.clickSignUpWithEmailButton() -} - -export async function signinWithEmail( - homePage: HomePage, - authPage: AuthPage, - accountOrEmail: UserAccountInformation | string, - password?: string, -) { - const email = typeof accountOrEmail === 'string' ? accountOrEmail : accountOrEmail.email - - const resolvedPassword = typeof accountOrEmail === 'string' ? password : accountOrEmail.password - - if (!email || !resolvedPassword) { - throw new Error('Provide either an `account` or `email` and `password`.') - } - - await homePage.goToSigninPage() - await authPage.fillEmailField(email) - await authPage.fillPasswordField(resolvedPassword) - await authPage.clickSignInWithEmailButton() -} - -export async function skipOnboardingHeadToProfile( - onboardingPage: OnboardingPage, - signUpPage: SignUpPage, - profilePage: ProfilePage, - account: UserAccountInformation, -) { - await onboardingPage.clickSkipOnboardingButton() - await signUpPage.fillDisplayName(account.display_name) - await signUpPage.fillUsername(account.username) - await signUpPage.clickNextButton() - await signUpPage.clickNextButton() - await profilePage.clickCloseButton() - await onboardingPage.clickRefineProfileButton() -} - -export async function deleteProfileFromSettings( - homePage: HomePage, - settingsPage: SettingsPage, -) { - await homePage.clickSettingsLink() - await settingsPage.clickDeleteAccountButton() - await settingsPage.fillDeleteAccountSurvey('Delete me') - await settingsPage.clickDeleteAccountButton() - await homePage.verifyHomePageLinks() -} \ No newline at end of file