mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-05-24 08:49:39 -04:00
[Syncing] Small PR to lay foundations for Testing filtering and to sync with upstream (#51)
* Added Database checks to the onboarding flow * Added compatibility page setup Added more compatibility questions * 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 * . * Fix: Merge conflict * . * 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 * Linting and Prettier * Minor cleaning * Organizing helper func * Added Google account to the Onboarding flow * Added account cleanup for google accounts * Started work on Sign-in tests Updated seedDatabase.ts to throw an error if the user already exists, to also add display names and usernames so they seedUser func acts like a normal basic user Some organising of the google auth code * Linting and Prettier * Added checks to the deleteUser func to check if the accout exists Added account deletion checks * Linting and Prettier * Formatting update, fixed homePage locator for signin * . * . * . * Coderabbitai fix's * Fix * Improve test utilities and stabilize onboarding flow tests * Changes requested * Changed POM/Fixture structure to use an app class to instantiate the page objects * Apply suggestion from @MartinBraquet * Delete .vscode/settings.json * Apply suggestion from @MartinBraquet * Apply suggestion from @MartinBraquet * Apply suggestion from @MartinBraquet * Linting and Prettier * Updated People page * Fix app.ts * Updated peoplePage.ts: continued adding functions to use filters Updated filters.tsx: added data testid * Coderabbitai fix's * . * Explanded seeding to better reflect the different types of profiles * Updated People page Added data test attributes to search.tsx and profile-grid.tsx * Lint and Prettier * Test renamed * CodeRabbit Suggestions * . * Apply suggestions from code review Co-authored-by: Martin Braquet <martin.braquet@gmail.com> --------- Co-authored-by: MartinBraquet <martin.braquet@gmail.com>
This commit is contained in:
committed by
GitHub
parent
9262e4a2be
commit
00c6f2566e
2
.github/workflows/cd-api.yml
vendored
2
.github/workflows/cd-api.yml
vendored
@@ -1,7 +1,7 @@
|
||||
name: API Release
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master ]
|
||||
branches: [main, master]
|
||||
paths:
|
||||
- 'backend/api/package.json'
|
||||
- '.github/workflows/cd-api.yml'
|
||||
|
||||
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -2,9 +2,9 @@ name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
|
||||
@@ -1,16 +1,7 @@
|
||||
import {
|
||||
Body,
|
||||
Button,
|
||||
Container,
|
||||
Head,
|
||||
Html,
|
||||
Preview,
|
||||
Section,
|
||||
Text,
|
||||
} from '@react-email/components'
|
||||
import {Body, Button, Container, Head, Html, Preview, Section, Text} from '@react-email/components'
|
||||
import {DOMAIN} from 'common/envs/constants'
|
||||
import {type User} from 'common/user'
|
||||
import { container, content, Footer, main} from 'email/utils'
|
||||
import {container, content, Footer, main} from 'email/utils'
|
||||
import React from 'react'
|
||||
import {createT} from 'shared/locale'
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import {ANDROID_APP_URL} from 'common/constants'
|
||||
import {DOMAIN} from 'common/envs/constants'
|
||||
import {type ProfileRow} from 'common/profiles/profile'
|
||||
import {type User} from 'common/user'
|
||||
import { container, content, Footer, main} from 'email/utils'
|
||||
import {container, content, Footer, main} from 'email/utils'
|
||||
import React from 'react'
|
||||
import {createT} from 'shared/locale'
|
||||
|
||||
|
||||
@@ -339,3 +339,7 @@ export type SubstanceIntentionTuple = {
|
||||
export type SubstancePreferenceTuple = {
|
||||
[K in keyof typeof SUBSTANCE_PREFERENCE_CHOICES]: [K, (typeof SUBSTANCE_PREFERENCE_CHOICES)[K]]
|
||||
}[keyof typeof SUBSTANCE_PREFERENCE_CHOICES]
|
||||
|
||||
export type LastActiveTuple = {
|
||||
[K in keyof typeof LAST_ONLINE_CHOICES]: [K, (typeof LAST_ONLINE_CHOICES)[K]]
|
||||
}[keyof typeof LAST_ONLINE_CHOICES]
|
||||
|
||||
@@ -7,9 +7,13 @@ import {
|
||||
PSYCHEDELICS_CHOICES,
|
||||
RACE_CHOICES,
|
||||
RELATIONSHIP_CHOICES,
|
||||
RELATIONSHIP_STATUS_CHOICES,
|
||||
ROMANTIC_CHOICES,
|
||||
RELIGION_CHOICES,
|
||||
LANGUAGE_CHOICES,
|
||||
SUBSTANCE_INTENTION_CHOICES,
|
||||
SUBSTANCE_PREFERENCE_CHOICES,
|
||||
MBTI_CHOICES,
|
||||
} from 'common/choices'
|
||||
|
||||
class UserAccountInformationForSeeding {
|
||||
@@ -30,8 +34,13 @@ class UserAccountInformationForSeeding {
|
||||
min: faker.number.int({min: 18, max: 27}),
|
||||
max: faker.number.int({min: 36, max: 68}),
|
||||
}
|
||||
|
||||
has_kids = faker.number.int({min: 0, max: 5})
|
||||
wants_kids_strength = faker.number.int({min: 0, max: 4})
|
||||
is_smoker = faker.datatype.boolean()
|
||||
relationship_status = Object.values(RELATIONSHIP_STATUS_CHOICES)
|
||||
pref_relation_styles = Object.values(RELATIONSHIP_CHOICES)
|
||||
pref_romantic_styles = Object.values(ROMANTIC_CHOICES)
|
||||
languages = Object.values(LANGUAGE_CHOICES)
|
||||
political_beliefs = Object.values(POLITICAL_CHOICES)
|
||||
religion = Object.values(RELIGION_CHOICES)
|
||||
diet = Object.values(DIET_CHOICES)
|
||||
@@ -42,6 +51,7 @@ class UserAccountInformationForSeeding {
|
||||
company = faker.company.name()
|
||||
occupation_title = faker.person.jobTitle()
|
||||
university = faker.company.name()
|
||||
keywords = faker.lorem.word()
|
||||
|
||||
cannabis = Object.values(CANNABIS_CHOICES)
|
||||
psychedelics = Object.values(PSYCHEDELICS_CHOICES)
|
||||
@@ -49,6 +59,12 @@ class UserAccountInformationForSeeding {
|
||||
cannabis_pref = Object.values(SUBSTANCE_PREFERENCE_CHOICES)
|
||||
psychedelics_intention = Object.values(SUBSTANCE_INTENTION_CHOICES)
|
||||
psychedelics_pref = Object.values(SUBSTANCE_PREFERENCE_CHOICES)
|
||||
mbti = Object.values(MBTI_CHOICES)
|
||||
big5_openness = faker.number.int({min: 0, max: 100})
|
||||
big5_conscientiousness = faker.number.int({min: 0, max: 100})
|
||||
big5_extraversion = faker.number.int({min: 0, max: 100})
|
||||
big5_agreeableness = faker.number.int({min: 0, max: 100})
|
||||
big5_neuroticism = faker.number.int({min: 0, max: 100})
|
||||
|
||||
randomElement(array: Array<string>) {
|
||||
return array[Math.floor(Math.random() * array.length)].toLowerCase()
|
||||
|
||||
@@ -78,7 +78,10 @@ export async function deleteAccount(idToken: any) {
|
||||
* Check if a Firebase user exists by email
|
||||
* Returns userId if exists, undefined if not found
|
||||
*/
|
||||
export async function firebaseUserExists(email: string, password: string): Promise<string | undefined> {
|
||||
export async function firebaseUserExists(
|
||||
email: string,
|
||||
password: string,
|
||||
): Promise<string | undefined> {
|
||||
try {
|
||||
const login = await firebaseLoginEmailPassword(email, password)
|
||||
return login.data.localId
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import {faker} from '@faker-js/faker'
|
||||
import {debug} from 'common/logger'
|
||||
import {PrivateUser} from 'common/user'
|
||||
import {getDefaultNotificationPreferences} from 'common/user-notification-preferences'
|
||||
@@ -37,13 +38,46 @@ export async function seedDbUser(
|
||||
},
|
||||
],
|
||||
}
|
||||
const relationshipStyle = userInfo.randomElement(userInfo.pref_relation_styles)
|
||||
let romanticStyle: string | null = null
|
||||
if (relationshipStyle === 'relationship') {
|
||||
romanticStyle = userInfo.randomElement(userInfo.pref_romantic_styles)
|
||||
}
|
||||
|
||||
const numberOfLanguages = faker.number.int({min: 1, max: 3})
|
||||
let languagesKnown = []
|
||||
|
||||
for (let i = 0; i < numberOfLanguages; i++) {
|
||||
languagesKnown.push(userInfo.randomElement(userInfo.languages))
|
||||
}
|
||||
|
||||
const keywords = faker.number.int({min: 1, max: 4})
|
||||
let profileKeywords = []
|
||||
for (let i = 0; i < keywords; i++) {
|
||||
profileKeywords.push(userInfo.keywords)
|
||||
}
|
||||
|
||||
const basicProfile = {
|
||||
user_id: userId,
|
||||
bio_length: userInfo.bio.length,
|
||||
bio: bio,
|
||||
age: userInfo.age,
|
||||
gender: userInfo.randomElement(userInfo.gender),
|
||||
ethnicity: [userInfo.randomElement(userInfo.ethnicity)],
|
||||
height_in_inches: userInfo.height_in_inches,
|
||||
pref_gender: [userInfo.randomElement(userInfo.pref_gender)],
|
||||
pref_relation_styles: [relationshipStyle],
|
||||
relationship_status: [userInfo.randomElement(userInfo.relationship_status)],
|
||||
pref_romantic_styles: romanticStyle ? [romanticStyle] : [],
|
||||
pref_age_min: userInfo.pref_age.min,
|
||||
pref_age_max: userInfo.pref_age.max,
|
||||
born_in_location: userInfo.born_in_location,
|
||||
company: userInfo.company,
|
||||
occupation_title: userInfo.occupation_title,
|
||||
religion: [userInfo.randomElement(userInfo.religion)],
|
||||
has_kids: userInfo.has_kids,
|
||||
wants_kids_strength: userInfo.wants_kids_strength,
|
||||
is_smoker: userInfo.is_smoker,
|
||||
}
|
||||
|
||||
const mediumProfile = {
|
||||
@@ -51,17 +85,12 @@ export async function seedDbUser(
|
||||
drinks_per_month: userInfo.drinks_per_month,
|
||||
diet: [userInfo.randomElement(userInfo.diet)],
|
||||
education_level: userInfo.randomElement(userInfo.education_level),
|
||||
ethnicity: [userInfo.randomElement(userInfo.ethnicity)],
|
||||
gender: userInfo.randomElement(userInfo.gender),
|
||||
height_in_inches: userInfo.height_in_inches,
|
||||
pref_gender: [userInfo.randomElement(userInfo.pref_gender)],
|
||||
pref_age_min: userInfo.pref_age.min,
|
||||
pref_age_max: userInfo.pref_age.max,
|
||||
languages: languagesKnown,
|
||||
keywords: profileKeywords,
|
||||
}
|
||||
|
||||
const fullProfile = {
|
||||
...mediumProfile,
|
||||
occupation_title: userInfo.occupation_title,
|
||||
cannabis: userInfo.randomElement(userInfo.cannabis),
|
||||
psychedelics: userInfo.randomElement(userInfo.psychedelics),
|
||||
cannabis_intention: [userInfo.randomElement(userInfo.cannabis_intention)],
|
||||
@@ -69,8 +98,12 @@ export async function seedDbUser(
|
||||
cannabis_pref: [userInfo.randomElement(userInfo.cannabis_pref)],
|
||||
psychedelics_pref: [userInfo.randomElement(userInfo.psychedelics_pref)],
|
||||
political_beliefs: [userInfo.randomElement(userInfo.political_beliefs)],
|
||||
pref_relation_styles: [userInfo.randomElement(userInfo.pref_relation_styles)],
|
||||
religion: [userInfo.randomElement(userInfo.religion)],
|
||||
mbti: userInfo.randomElement(userInfo.mbti),
|
||||
big5_openness: userInfo.big5_openness,
|
||||
big5_conscientiousness: userInfo.big5_conscientiousness,
|
||||
big5_extraversion: userInfo.big5_extraversion,
|
||||
big5_agreeableness: userInfo.big5_agreeableness,
|
||||
big5_neuroticism: userInfo.big5_neuroticism,
|
||||
}
|
||||
|
||||
const profileData =
|
||||
|
||||
@@ -10,6 +10,8 @@ import {ProfilePage} from './profilePage'
|
||||
import {SettingsPage} from './settingsPage'
|
||||
import {SignUpPage} from './signUpPage'
|
||||
import {SocialPage} from './socialPage'
|
||||
import {PeoplePage} from './peoplePage'
|
||||
import {NotificationPage} from './notificationsPage'
|
||||
|
||||
export class App {
|
||||
readonly auth: AuthPage
|
||||
@@ -21,6 +23,8 @@ export class App {
|
||||
readonly settings: SettingsPage
|
||||
readonly signUp: SignUpPage
|
||||
readonly social: SocialPage
|
||||
readonly people: PeoplePage
|
||||
readonly notifs: NotificationPage
|
||||
|
||||
constructor(public readonly page: Page) {
|
||||
this.auth = new AuthPage(page)
|
||||
@@ -32,6 +36,8 @@ export class App {
|
||||
this.settings = new SettingsPage(page)
|
||||
this.signUp = new SignUpPage(page)
|
||||
this.social = new SocialPage(page)
|
||||
this.people = new PeoplePage(page)
|
||||
this.notifs = new NotificationPage(page)
|
||||
}
|
||||
|
||||
async deleteProfileFromSettings() {
|
||||
|
||||
@@ -55,8 +55,10 @@ export class AuthPage {
|
||||
await popup.getByLabel('Email').fill(email)
|
||||
if (display_name) await popup.getByLabel('Display name').fill(display_name)
|
||||
if (username) await popup.getByLabel('Screen name', {exact: true}).fill(username)
|
||||
await popup.getByText('Sign in with Google.com', {exact: true}).click()
|
||||
await popup.waitForEvent('close')
|
||||
await Promise.all([
|
||||
popup.waitForEvent('close'),
|
||||
popup.getByText('Sign in with Google.com', {exact: true}).click(),
|
||||
])
|
||||
}
|
||||
|
||||
async clickSignUpWithEmailButton() {
|
||||
|
||||
11
tests/e2e/web/pages/notificationsPage.ts
Normal file
11
tests/e2e/web/pages/notificationsPage.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import {expect, Locator, Page} from '@playwright/test'
|
||||
|
||||
export class NotificationPage {
|
||||
private readonly notificationTab: Locator
|
||||
private readonly settingsTab: Locator
|
||||
|
||||
constructor(public readonly page: Page) {
|
||||
this.notificationTab = page.getByTestId('notifications-tab')
|
||||
this.settingsTab = page.getByTestId('settings-tab')
|
||||
}
|
||||
}
|
||||
434
tests/e2e/web/pages/peoplePage.ts
Normal file
434
tests/e2e/web/pages/peoplePage.ts
Normal file
@@ -0,0 +1,434 @@
|
||||
import {expect, Locator, Page} from '@playwright/test'
|
||||
import {
|
||||
ConnectionTypeTuple,
|
||||
GenderTuple,
|
||||
EducationTuple,
|
||||
DietTuple,
|
||||
PsychedelicsTuple,
|
||||
CannabisTuple,
|
||||
LanguageTuple,
|
||||
PoliticalTuple,
|
||||
ReligionTuple,
|
||||
PersonalityKey,
|
||||
LastActiveTuple,
|
||||
} from 'common/choices'
|
||||
import {MinMaxNumbers} from '../utils/accountInformation'
|
||||
|
||||
export type BackgroundFilter = {
|
||||
location?: string
|
||||
education?: EducationTuple
|
||||
work?: string
|
||||
}
|
||||
|
||||
export type LifestyleFilter = {
|
||||
interest?: string
|
||||
cause?: string
|
||||
diet?: DietTuple
|
||||
alcohol?: MinMaxNumbers
|
||||
smoker?: string
|
||||
psychedelics?: PsychedelicsTuple
|
||||
cannabis?: CannabisTuple
|
||||
language?: LanguageTuple
|
||||
}
|
||||
|
||||
export type BeliefsFilter = {
|
||||
political?: PoliticalTuple
|
||||
religious?: ReligionTuple
|
||||
}
|
||||
|
||||
export type PersonalityFilter = {
|
||||
mbti?: PersonalityKey
|
||||
bigFive?: BigFive
|
||||
}
|
||||
|
||||
type BigFive = {
|
||||
openness?: MinMaxNumbers
|
||||
conscientiousness?: MinMaxNumbers
|
||||
extraversion?: MinMaxNumbers
|
||||
agreeableness?: MinMaxNumbers
|
||||
neuroticism?: MinMaxNumbers
|
||||
}
|
||||
|
||||
export type AdvancedFilter = {
|
||||
lastActive?: LastActiveTuple
|
||||
photos?: boolean
|
||||
}
|
||||
|
||||
export type DisplayFilter = {
|
||||
cardSize?: 'Small' | 'Medium' | 'Large'
|
||||
filters?: [string, boolean][]
|
||||
}
|
||||
|
||||
export type PeoplePageFilter = {
|
||||
connectionFilter?: ConnectionTypeTuple
|
||||
ageFilter?: MinMaxNumbers
|
||||
genderFilter?: GenderTuple
|
||||
backgroundFilter?: BackgroundFilter
|
||||
lifestyleFilter?: LifestyleFilter
|
||||
valuesAndBeliefsFilter?: BeliefsFilter
|
||||
personalityFilter?: PersonalityFilter
|
||||
}
|
||||
|
||||
export class PeoplePage {
|
||||
private readonly peopleHeading: Locator
|
||||
private readonly searchBox: Locator
|
||||
private readonly profileCount: Locator
|
||||
private readonly resetFilters: Locator
|
||||
private readonly yourFiltersCheckbox: Locator
|
||||
private readonly incompleteProfilesCheckbox: Locator
|
||||
private readonly connectionTypeDropdown: Locator
|
||||
private readonly locationDropdown: Locator
|
||||
private readonly ageRangeDropdown: Locator
|
||||
private readonly genderDropdown: Locator
|
||||
private readonly backgroundDropdown: Locator
|
||||
private readonly backgroundLocation: Locator
|
||||
private readonly backgroundEducation: Locator
|
||||
private readonly backgroundWork: Locator
|
||||
private readonly lifestyleDropdown: Locator
|
||||
private readonly lifestyleInterests: Locator
|
||||
private readonly lifestyleCauses: Locator
|
||||
private readonly lifestyleDiet: Locator
|
||||
private readonly lifestyleAlcohol: Locator
|
||||
private readonly lifestyleSmoker: Locator
|
||||
private readonly lifestylePsychedelics: Locator
|
||||
private readonly lifestyleCannabis: Locator
|
||||
private readonly lifestyleLanguages: Locator
|
||||
private readonly valuesAndBeliefsDropdown: Locator
|
||||
private readonly valuesAndBeliefsPolitics: Locator
|
||||
private readonly valuesAndBeliefsReligion: Locator
|
||||
private readonly personalityDropdown: Locator
|
||||
private readonly personalityMbti: Locator
|
||||
private readonly personalityBigFive: Locator
|
||||
private readonly advancedDropdown: Locator
|
||||
private readonly advancedActive: Locator
|
||||
private readonly advancedPhotos: Locator
|
||||
private readonly displayDropdown: Locator
|
||||
private readonly profileGrid: Locator
|
||||
private readonly profileResults: Locator
|
||||
private readonly profileName: Locator
|
||||
private readonly profileAgeGender: Locator
|
||||
|
||||
constructor(public readonly page: Page) {
|
||||
this.peopleHeading = page.getByRole('heading', {name: 'People'})
|
||||
this.searchBox = page.getByRole('textbox', {name: 'Search anything...'})
|
||||
this.profileCount = page.getByTestId('people-profile-count')
|
||||
this.resetFilters = page.getByRole('button', {name: 'Reset filters'})
|
||||
this.yourFiltersCheckbox = page.getByText('Your filters', {exact: true})
|
||||
this.incompleteProfilesCheckbox = page.getByText('Include incomplete profiles', {exact: true})
|
||||
this.connectionTypeDropdown = page.getByRole('button', {name: 'Any connection'})
|
||||
this.locationDropdown = page.getByRole('button', {name: 'Living anywhere'})
|
||||
this.ageRangeDropdown = page.getByRole('button', {name: 'Any age'})
|
||||
this.genderDropdown = page.getByRole('button', {name: 'Any gender'})
|
||||
this.backgroundDropdown = page.getByRole('button', {name: 'Background'})
|
||||
this.backgroundLocation = page.getByRole('button', {name: 'Grew up anywhere'})
|
||||
this.backgroundEducation = page.getByText('Any education', {exact: true})
|
||||
this.backgroundWork = page.getByText('Any work', {exact: true})
|
||||
this.lifestyleDropdown = page.getByRole('button', {name: 'Lifestyle'})
|
||||
this.lifestyleInterests = page.getByRole('button', {name: 'Any interests'})
|
||||
this.lifestyleCauses = page.getByRole('button', {name: 'Any causes'})
|
||||
this.lifestyleDiet = page.getByRole('button', {name: 'Any diet'})
|
||||
this.lifestyleAlcohol = page.getByRole('button', {name: 'Any drinks'})
|
||||
this.lifestyleSmoker = page.getByTestId('lifestyle-smoker')
|
||||
this.lifestylePsychedelics = page.getByRole('button', {name: 'Any psychedelics'})
|
||||
this.lifestyleCannabis = page.getByRole('button', {name: 'Any cannabis'})
|
||||
this.lifestyleLanguages = page.getByRole('button', {name: 'Any language'})
|
||||
this.valuesAndBeliefsDropdown = page.getByRole('button', {name: 'Values & Beliefs'})
|
||||
this.valuesAndBeliefsPolitics = page.getByRole('button', {name: 'Any politics'})
|
||||
this.valuesAndBeliefsReligion = page.getByRole('button', {name: 'Any religion'})
|
||||
this.personalityDropdown = page.getByRole('button', {name: 'Personality'})
|
||||
this.personalityMbti = page.getByRole('button', {name: 'Any MBTI'})
|
||||
this.personalityBigFive = page.getByRole('button', {name: 'Any Big 5'})
|
||||
this.advancedDropdown = page.getByRole('button', {name: 'Advanced'})
|
||||
this.advancedActive = page.getByTestId('advanced-active')
|
||||
this.advancedPhotos = page.getByText('Photos', {exact: true})
|
||||
this.displayDropdown = page.getByRole('button', {name: 'Display'})
|
||||
this.profileGrid = page.getByTestId('people-profile-grid')
|
||||
this.profileResults = page.getByTestId('people-profile-results')
|
||||
this.profileName = page.getByTestId('people-profile-name')
|
||||
this.profileAgeGender = page.getByTestId('people-profile-age-gender')
|
||||
}
|
||||
|
||||
get profileCountLocator(): Locator {
|
||||
return this.profileCount
|
||||
}
|
||||
|
||||
async sliderHelper(range: MinMaxNumbers, locator?: Locator) {
|
||||
let minSlider
|
||||
let maxSlider
|
||||
if (locator) {
|
||||
minSlider = await locator.getByRole('slider', {name: 'Minimum'})
|
||||
maxSlider = await locator.getByRole('slider', {name: 'Maximum'})
|
||||
} else {
|
||||
minSlider = await this.page.getByRole('slider', {name: 'Minimum'})
|
||||
maxSlider = await this.page.getByRole('slider', {name: 'Maximum'})
|
||||
}
|
||||
|
||||
await expect(minSlider).toBeVisible()
|
||||
await expect(maxSlider).toBeVisible()
|
||||
if (range.min === null || range.max === null) return
|
||||
|
||||
const minRange = Number(range.min)
|
||||
const maxRange = Number(range.max)
|
||||
const currentMinValue = Number(await minSlider.getAttribute('aria-valuenow'))
|
||||
const currentMaxValue = Number(await maxSlider.getAttribute('aria-valuenow'))
|
||||
|
||||
if (isNaN(currentMinValue) || isNaN(currentMaxValue)) return
|
||||
|
||||
if (minRange > currentMinValue) {
|
||||
await minSlider.click()
|
||||
let iterations = 0
|
||||
const MAX_ITERATIONS = 100
|
||||
while (true) {
|
||||
if (iterations++ > MAX_ITERATIONS) {
|
||||
throw new Error(`Slider adjustment exceeded ${MAX_ITERATIONS} iterations`)
|
||||
}
|
||||
const changedMinValue = Number(await minSlider.getAttribute('aria-valuenow'))
|
||||
|
||||
if (isNaN(changedMinValue)) break
|
||||
if (minRange <= changedMinValue) break
|
||||
await this.page.keyboard.press('ArrowRight')
|
||||
}
|
||||
}
|
||||
|
||||
if (maxRange < currentMaxValue) {
|
||||
await maxSlider.click()
|
||||
let iterations = 0
|
||||
const MAX_ITERATIONS = 100
|
||||
while (true) {
|
||||
if (iterations++ > MAX_ITERATIONS) {
|
||||
throw new Error(`Slider adjustment exceeded ${MAX_ITERATIONS} iterations`)
|
||||
}
|
||||
const changedMaxValue = Number(await maxSlider.getAttribute('aria-valuenow'))
|
||||
if (isNaN(changedMaxValue)) break
|
||||
if (maxRange >= changedMaxValue) break
|
||||
await this.page.keyboard.press('ArrowLeft')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async selectOption(trigger: Locator, label: string) {
|
||||
await expect(trigger).toBeVisible()
|
||||
await trigger.click()
|
||||
|
||||
const option = this.page.getByLabel(label, {exact: true})
|
||||
await expect(option).toBeVisible()
|
||||
await option.click()
|
||||
}
|
||||
|
||||
async verifyPeoplePage() {
|
||||
await expect(this.peopleHeading).toBeVisible()
|
||||
}
|
||||
|
||||
//Doesn't actually work, need to find out why
|
||||
async useSearch(item: string) {
|
||||
await expect(this.searchBox).toBeVisible()
|
||||
await this.searchBox.click()
|
||||
await this.searchBox.fill(item)
|
||||
await this.page.keyboard.press('Enter')
|
||||
}
|
||||
|
||||
async resetFilter() {
|
||||
await expect(this.resetFilters).toBeVisible()
|
||||
await this.resetFilters.click()
|
||||
}
|
||||
|
||||
async setYourFilters() {
|
||||
await expect(this.yourFiltersCheckbox).toBeVisible()
|
||||
await this.yourFiltersCheckbox.click()
|
||||
}
|
||||
|
||||
async setIncludeIncompleteProfiles() {
|
||||
await expect(this.incompleteProfilesCheckbox).toBeVisible()
|
||||
await this.incompleteProfilesCheckbox.click()
|
||||
}
|
||||
|
||||
async setConnectionTypeFilter(connectionType: ConnectionTypeTuple) {
|
||||
await this.selectOption(this.connectionTypeDropdown, connectionType[0])
|
||||
// await expect(this.connectionTypeDropdown).toBeVisible()
|
||||
// await this.connectionTypeDropdown.click()
|
||||
// await expect(this.page.getByLabel(connectionType[0])).toBeVisible()
|
||||
// await this.page.getByLabel(connectionType[0]).click()
|
||||
}
|
||||
|
||||
async setLocationFilter(location: string) {
|
||||
await expect(this.locationDropdown).toBeVisible()
|
||||
await this.locationDropdown.click()
|
||||
await expect(this.page.getByRole('textbox', {name: 'Search city...'})).toBeVisible()
|
||||
await this.page.getByRole('textbox', {name: 'Search city...'}).fill(location)
|
||||
}
|
||||
|
||||
async setAgeRangeFilter(ageRange: MinMaxNumbers) {
|
||||
await expect(this.ageRangeDropdown).toBeVisible()
|
||||
await this.ageRangeDropdown.click()
|
||||
await this.sliderHelper(ageRange)
|
||||
}
|
||||
|
||||
async setGenderTypeFilter(genderType: GenderTuple) {
|
||||
await this.selectOption(this.genderDropdown, genderType[0])
|
||||
// await expect(this.genderDropdown).toBeVisible()
|
||||
// await this.genderDropdown.click()
|
||||
// await expect(this.page.getByLabel(genderType[0], {exact: true})).toBeVisible()
|
||||
// await this.page.getByLabel(genderType[0], {exact: true}).click()
|
||||
}
|
||||
|
||||
async setBackgroundFilter(background: BackgroundFilter) {
|
||||
await expect(this.backgroundDropdown).toBeVisible()
|
||||
await this.backgroundDropdown.click()
|
||||
if (background.location) {
|
||||
await expect(this.backgroundLocation).toBeVisible()
|
||||
await this.backgroundLocation.click()
|
||||
await this.page.getByPlaceholder('Search city...', {exact: true}).fill(background.location)
|
||||
}
|
||||
|
||||
if (background.education) {
|
||||
await expect(this.backgroundEducation).toBeVisible()
|
||||
await this.backgroundEducation.click()
|
||||
await expect(this.page.getByLabel(background.education[0], {exact: true})).toBeVisible()
|
||||
await this.page.getByLabel(background.education[0], {exact: true}).click()
|
||||
}
|
||||
|
||||
if (background.work) {
|
||||
await expect(this.backgroundWork).toBeVisible()
|
||||
await this.backgroundWork.click()
|
||||
await expect(this.page.getByLabel(background.work, {exact: true})).toBeVisible()
|
||||
await this.page.getByLabel(background.work, {exact: true}).click()
|
||||
}
|
||||
}
|
||||
|
||||
async setLifestyleFilter(lifestyle: LifestyleFilter) {
|
||||
await expect(this.lifestyleDropdown).toBeVisible()
|
||||
await this.lifestyleDropdown.click()
|
||||
|
||||
if (lifestyle.interest) await this.selectOption(this.lifestyleInterests, lifestyle.interest)
|
||||
if (lifestyle.cause) await this.selectOption(this.lifestyleCauses, lifestyle.cause)
|
||||
if (lifestyle.diet) await this.selectOption(this.lifestyleDiet, lifestyle.diet[0])
|
||||
|
||||
if (lifestyle.alcohol) {
|
||||
await expect(this.lifestyleAlcohol).toBeVisible()
|
||||
await this.lifestyleAlcohol.click()
|
||||
await this.sliderHelper(lifestyle.alcohol)
|
||||
}
|
||||
|
||||
if (lifestyle.smoker) {
|
||||
await expect(this.lifestyleSmoker).toBeVisible()
|
||||
await this.lifestyleSmoker.click()
|
||||
await expect(this.page.getByText(lifestyle.smoker, {exact: true})).toBeVisible()
|
||||
await this.page.getByText(lifestyle.smoker, {exact: true}).click()
|
||||
}
|
||||
|
||||
if (lifestyle.psychedelics)
|
||||
await this.selectOption(this.lifestylePsychedelics, lifestyle.psychedelics[0])
|
||||
if (lifestyle.cannabis) await this.selectOption(this.lifestyleCannabis, lifestyle.cannabis[0])
|
||||
if (lifestyle.language) await this.selectOption(this.lifestyleLanguages, lifestyle.language[0])
|
||||
}
|
||||
|
||||
async setValuesAndBeliefsFilter(values: BeliefsFilter) {
|
||||
await expect(this.valuesAndBeliefsDropdown).toBeVisible()
|
||||
await this.valuesAndBeliefsDropdown.click()
|
||||
|
||||
if (values.political)
|
||||
await this.selectOption(this.valuesAndBeliefsPolitics, values.political[0])
|
||||
if (values.religious)
|
||||
await this.selectOption(this.valuesAndBeliefsReligion, values.religious[0])
|
||||
}
|
||||
|
||||
async setPersonalityFilter(personality: PersonalityFilter) {
|
||||
await expect(this.personalityDropdown).toBeVisible()
|
||||
await this.personalityDropdown.click()
|
||||
|
||||
if (personality.mbti) await this.selectOption(this.personalityMbti, personality.mbti)
|
||||
|
||||
if (personality.bigFive) {
|
||||
await this.personalityBigFive.click()
|
||||
if (personality.bigFive?.openness) {
|
||||
await this.sliderHelper(
|
||||
personality.bigFive.openness,
|
||||
this.page.getByTestId('big-five-openness'),
|
||||
)
|
||||
}
|
||||
if (personality.bigFive?.conscientiousness) {
|
||||
await this.sliderHelper(
|
||||
personality.bigFive.conscientiousness,
|
||||
this.page.getByTestId('big-five-conscientiousness'),
|
||||
)
|
||||
}
|
||||
if (personality.bigFive?.extraversion) {
|
||||
await this.sliderHelper(
|
||||
personality.bigFive.extraversion,
|
||||
this.page.getByTestId('big-five-extraversion'),
|
||||
)
|
||||
}
|
||||
if (personality.bigFive?.agreeableness) {
|
||||
await this.sliderHelper(
|
||||
personality.bigFive.agreeableness,
|
||||
this.page.getByTestId('big-five-agreeableness'),
|
||||
)
|
||||
}
|
||||
if (personality.bigFive?.neuroticism) {
|
||||
await this.sliderHelper(
|
||||
personality.bigFive.neuroticism,
|
||||
this.page.getByTestId('big-five-neuroticism'),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async setAdvancedFilter(advanced: AdvancedFilter) {
|
||||
await expect(this.advancedDropdown).toBeVisible()
|
||||
await this.advancedDropdown.click()
|
||||
|
||||
if (advanced.lastActive) {
|
||||
await this.advancedActive.click()
|
||||
await this.page.getByRole('button', {name: `${advanced.lastActive[1]}`}).click()
|
||||
}
|
||||
|
||||
if (advanced.photos) {
|
||||
await this.advancedPhotos.click()
|
||||
await this.page.getByRole('checkbox', {name: 'Has photos'}).click()
|
||||
}
|
||||
}
|
||||
|
||||
async setDisplayFilter(display: DisplayFilter) {
|
||||
await expect(this.displayDropdown).toBeVisible()
|
||||
await this.displayDropdown.click()
|
||||
|
||||
if (display.cardSize) await this.page.getByRole('button', {name: `${display.cardSize}`}).click()
|
||||
|
||||
if (!display.filters) return
|
||||
if (display.filters?.length > 0) {
|
||||
for (let i = 0; i < display.filters.length; i++) {
|
||||
const filter = await this.page.getByRole('checkbox', {name: `${display.filters[i][0]}`})
|
||||
await expect(filter).toBeVisible()
|
||||
const isChecked = await filter.isChecked()
|
||||
|
||||
if (display.filters[i][1]) {
|
||||
if (isChecked) continue
|
||||
if (!isChecked) await filter.click()
|
||||
} else if (!display.filters[i][1]) {
|
||||
if (isChecked) await filter.click()
|
||||
if (!isChecked) continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async getProfileInfo() {
|
||||
await expect(this.profileGrid).toBeVisible()
|
||||
const totalResults = await this.profileResults.count()
|
||||
const chosenProfileNumber = Math.floor(Math.random() * totalResults)
|
||||
const chosenProfile = await this.profileResults.nth(chosenProfileNumber)
|
||||
const profileName = await chosenProfile.getByTestId('people-profile-name').textContent()
|
||||
|
||||
if (!profileName) return
|
||||
return {
|
||||
name: profileName,
|
||||
}
|
||||
}
|
||||
|
||||
async verifyNumberOfMatchingProfiles(count: number) {
|
||||
await expect(this.profileCount).toBeVisible()
|
||||
const test = await this.profileCount.textContent()
|
||||
if (!test) return
|
||||
expect(actual).toStrictEqual(expected)
|
||||
}
|
||||
}
|
||||
@@ -9,15 +9,31 @@ test.describe('when given valid input', () => {
|
||||
await app.home.goToHomePage()
|
||||
await app.home.verifySignedInHomePage(account.display_name)
|
||||
})
|
||||
|
||||
test('the profile count should update sucessfully when applying a filter', async ({
|
||||
app,
|
||||
signedOutAccount: account,
|
||||
}) => {
|
||||
await app.signinWithEmail(account)
|
||||
await app.home.clickPeopleLink()
|
||||
await app.people.getProfileInfo()
|
||||
const totalProfiles = await app.people.profileCountLocator.textContent()
|
||||
await app.people.setConnectionTypeFilter(['Collaboration', 'collaboration'])
|
||||
|
||||
const filterdProfiles = await app.people.profileCountLocator.textContent()
|
||||
|
||||
if (!totalProfiles || !filterdProfiles) return
|
||||
await expect(parseInt(totalProfiles)).not.toEqual(parseInt(filterdProfiles))
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('when given invalid input', () => {
|
||||
test('should not be able to sign in to an available account', async ({
|
||||
app,
|
||||
signedOutAccount,
|
||||
signedOutAccount: account,
|
||||
page,
|
||||
}) => {
|
||||
await app.signinWithEmail(signedOutAccount.email, 'ThisPassword', false)
|
||||
await app.signinWithEmail(account.email, 'ThisPassword', false)
|
||||
await expect(
|
||||
page.getByText('Failed to sign in with your email and password', {exact: true}),
|
||||
).toBeVisible()
|
||||
|
||||
@@ -32,7 +32,7 @@ export type UserAccountInformation = {
|
||||
height?: Height
|
||||
ethnicity_origin?: EthnicityTuple
|
||||
interested_in?: InterestedInGenderTuple
|
||||
Interested_in_ages?: InterestedInAges
|
||||
Interested_in_ages?: MinMaxNumbers
|
||||
connection_type?: ConnectionTypeTuple
|
||||
relationship_status?: RelationshipStatusTuple
|
||||
relationship_style?: RelationshipStyleTuple
|
||||
@@ -62,7 +62,7 @@ type Height = {
|
||||
centimeters: string
|
||||
}
|
||||
|
||||
type InterestedInAges = {
|
||||
export type MinMaxNumbers = {
|
||||
min: string
|
||||
max?: string
|
||||
}
|
||||
@@ -89,7 +89,7 @@ export type Socials = {
|
||||
urlOrUsername: string
|
||||
}
|
||||
|
||||
type FiveBigPersonalityTraits = {
|
||||
export type FiveBigPersonalityTraits = {
|
||||
openness?: number
|
||||
conscientiousness?: number
|
||||
extraversion?: number
|
||||
|
||||
@@ -70,7 +70,7 @@ export function Big5SliderRow(props: {
|
||||
const {label, minValue, maxValue, onChange} = props
|
||||
|
||||
return (
|
||||
<div className="mb-4">
|
||||
<div className="mb-4" data-testid={`big-five-${label.toLowerCase()}`}>
|
||||
<div className="mb-1 flex items-center justify-between text-sm text-ink-600">
|
||||
<span>{label}</span>
|
||||
<span className="font-semibold text-ink-700">
|
||||
|
||||
@@ -9,7 +9,12 @@ import {Profile} from 'common/profiles/profile'
|
||||
import {DisplayOptions} from 'common/profiles-rendering'
|
||||
import {nullifyDictValues, removeNullOrUndefinedProps, sampleDictByPrefix} from 'common/util/object'
|
||||
import {ReactNode, useState} from 'react'
|
||||
import {Big5Filters, Big5FilterText, countBig5Filters, hasAnyBig5Filter,} from 'web/components/filters/big5-filter'
|
||||
import {
|
||||
Big5Filters,
|
||||
Big5FilterText,
|
||||
countBig5Filters,
|
||||
hasAnyBig5Filter,
|
||||
} from 'web/components/filters/big5-filter'
|
||||
import {CardSizeSelector} from 'web/components/filters/card-size-selector'
|
||||
import {DietFilter, DietFilterText} from 'web/components/filters/diet-filter'
|
||||
import {EducationFilter, EducationFilterText} from 'web/components/filters/education-filter'
|
||||
@@ -586,6 +591,7 @@ function Filters(props: {
|
||||
</FilterSection>
|
||||
|
||||
<FilterSection
|
||||
testId="lifestyle-smoker"
|
||||
title={t('profile.optional.is_smoker', 'Smoker')}
|
||||
openFilter={openFilter}
|
||||
setOpenFilter={setOpenFilter}
|
||||
@@ -742,6 +748,7 @@ function Filters(props: {
|
||||
{/* LAST ACTIVE */}
|
||||
<FilterSection
|
||||
title={t('filter.last_active.title', 'Last active')}
|
||||
testId="advanced-active"
|
||||
openFilter={openFilter}
|
||||
setOpenFilter={setOpenFilter}
|
||||
isActive={!!filters.last_active}
|
||||
@@ -810,6 +817,7 @@ export function FilterSection(props: {
|
||||
selection?: ReactNode
|
||||
showNewBadge?: boolean
|
||||
newBadgeClassName?: string
|
||||
testId?: string
|
||||
}) {
|
||||
const {
|
||||
title,
|
||||
@@ -823,10 +831,11 @@ export function FilterSection(props: {
|
||||
selection,
|
||||
showNewBadge,
|
||||
newBadgeClassName,
|
||||
testId,
|
||||
} = props
|
||||
const isOpen = openFilter == title
|
||||
return (
|
||||
<Col className={clsx(className)}>
|
||||
<Col className={clsx(className)} data-testid={testId}>
|
||||
<button
|
||||
className={clsx(
|
||||
'text-ink-600 flex w-full flex-row justify-between px-4 pt-4 relative hover-bold',
|
||||
|
||||
@@ -267,7 +267,7 @@ export const Search = forwardRef<
|
||||
</Row>
|
||||
{(profileCount ?? 0) > 0 && (
|
||||
<Row className="text-sm text-ink-500 gap-2">
|
||||
<p>
|
||||
<p data-testid="people-profile-count">
|
||||
{profileCount}{' '}
|
||||
{(profileCount ?? 0) > 1
|
||||
? t('common.people', 'people')
|
||||
|
||||
@@ -140,7 +140,11 @@ export function ControlledTabs(props: TabProps & {activeIndex: number}) {
|
||||
<Row className={'items-center'}>
|
||||
<Col>
|
||||
{tab.title.split('\n').map((line, i) => (
|
||||
<Row className={'items-center justify-center'} key={i}>
|
||||
<Row
|
||||
className={'items-center justify-center'}
|
||||
key={i}
|
||||
data-testid={`${tab.title.toLowerCase()}-tab`}
|
||||
>
|
||||
{line}
|
||||
</Row>
|
||||
))}
|
||||
|
||||
@@ -120,7 +120,12 @@ const Profiles = {
|
||||
href: '/',
|
||||
icon: UsersIcon,
|
||||
}
|
||||
const Home = {key: 'nav.home', name: 'Home', href: '/', icon: HomeIcon}
|
||||
const Home = {
|
||||
key: 'nav.home',
|
||||
name: 'Home',
|
||||
href: '/',
|
||||
icon: HomeIcon,
|
||||
}
|
||||
const faq = {
|
||||
key: 'nav.faq',
|
||||
name: 'FAQ',
|
||||
@@ -163,7 +168,12 @@ const Organization = {
|
||||
href: '/organization',
|
||||
icon: GlobeAltIcon,
|
||||
}
|
||||
const Vote = {key: 'nav.vote', name: 'Vote', href: '/vote', icon: MdThumbUp}
|
||||
const Vote = {
|
||||
key: 'nav.vote',
|
||||
name: 'Vote',
|
||||
href: '/vote',
|
||||
icon: MdThumbUp,
|
||||
}
|
||||
const Contact = {
|
||||
key: 'nav.contact',
|
||||
name: 'Contact',
|
||||
|
||||
@@ -82,7 +82,7 @@ export const ProfileGrid = (props: {
|
||||
}[cardSize ?? 'medium']
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<div className="relative" data-testid="people-profile-grid">
|
||||
<div
|
||||
className={clsx(
|
||||
`grid gap-6 py-4 grid-cols-1`,
|
||||
@@ -328,6 +328,7 @@ function ProfilePreview(props: {
|
||||
isLoading && 'scale-[0.94] transition-transform duration-[80ms] ease-out',
|
||||
!isLoading && 'transition-transform duration-[120ms] ease-in',
|
||||
)}
|
||||
data-testid="people-profile-results"
|
||||
>
|
||||
<Link
|
||||
href={`/${user.username}`}
|
||||
@@ -419,6 +420,7 @@ function ProfilePreview(props: {
|
||||
'main-font font-medium text-lg text-gray-900 dark:text-white truncate my-0 transition-opacity duration-75',
|
||||
isLoading && 'opacity-50',
|
||||
)}
|
||||
data-testid="people-profile-name"
|
||||
>
|
||||
{user.name}
|
||||
</h3>
|
||||
@@ -427,6 +429,7 @@ function ProfilePreview(props: {
|
||||
'flex-wrap gap-x-2 transition-opacity duration-75',
|
||||
isLoading && 'opacity-50',
|
||||
)}
|
||||
data-testid="people-profile-age-gender"
|
||||
>
|
||||
{showCity !== false && <ProfileLocation profile={profile} />}
|
||||
{showAge !== false && profile.age && (
|
||||
|
||||
Reference in New Issue
Block a user