mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-03-24 17:41:27 -04:00
[Onboarding Flow] Added database checks to the onboarding flow (#34)
* Fixed Type errors * Organizing testing utilities * Added Database checks to the onboarding flow * Updated Onboarding flow Changed type ChildrenExpectation so that it can be used for database verification * Added compatibility page setup Added more compatibility questions * Fix * . * Fix: Typo * Fix: Faker usernames can no longer generate symbols * Fix: Changed how work area is verified * . * . * Fix: Trying to work in headed mode * Fix: Change back to headless * Fix: Added timeout after workArea selection * . * Clean e2e * Improve E2E setup * Prettier * Log * Fix: should pull test account from unique identifier like email, username or id; not the display name * Source env vars in playwright directly * Clean e2e data * Clean test account id to be the same for email and username * Fix import warning * Add error handling * Add log * Temp remove env load * Update * Add logs and safeguards against using remote supabase during e2e tests * Fix playwright report path in C@ * Remove locale log * Check if userInformationFromDb loading with name instead of username was the issue * Remove login log * Check if initial work area names were the issue * Ignore if no files found * Cache Firebase emulators in CI * Reload env vars in playwright * It did not break tests... * Clean verifyWorkArea * Add caching for node modules in CI * Add caching for node modules in CI (2) * Do not raise if emulator not running during db seed * Do not raise if using firebase emulator * Fix supabase cache in CI * Add Cache Playwright browsers in CI * Fix * Test cache * Turn off unused supabase services to speed things up * Back to good one * Set CI=true * api is required for client connection * Add safeguards for missing supabase env vars * Remove echo * Remove supabase cache --------- Co-authored-by: Martin Braquet <martin.braquet@gmail.com>
This commit is contained in:
committed by
GitHub
parent
c69a438d08
commit
b18a6d7ff3
4
.github/workflows/cd-android-live-update.yml
vendored
4
.github/workflows/cd-android-live-update.yml
vendored
@@ -1,7 +1,7 @@
|
||||
name: CD Android Live Update
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master ]
|
||||
branches: [main, master]
|
||||
paths:
|
||||
- 'android/capawesome.json'
|
||||
- '.github/workflows/cd-android-live-update.yml'
|
||||
@@ -73,4 +73,4 @@ jobs:
|
||||
CAPAWESOME_TOKEN: ${{ secrets.CAPAWESOME_TOKEN }}
|
||||
commitRef: ${{ github.head_ref || github.ref_name }}
|
||||
commitSha: ${{ github.sha }}
|
||||
run: yarn android-live-update
|
||||
run: yarn android-live-update
|
||||
|
||||
2
.github/workflows/cd-android.yml
vendored
2
.github/workflows/cd-android.yml
vendored
@@ -94,4 +94,4 @@ jobs:
|
||||
serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
|
||||
packageName: com.compassconnections.app
|
||||
releaseFiles: android/app/build/outputs/bundle/release/app-release.aab
|
||||
track: internal
|
||||
track: internal
|
||||
|
||||
4
.github/workflows/cd-api.yml
vendored
4
.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'
|
||||
@@ -92,4 +92,4 @@ jobs:
|
||||
- name: Run deploy script
|
||||
run: |
|
||||
chmod +x backend/api/deploy-api.sh
|
||||
backend/api/deploy-api.sh
|
||||
backend/api/deploy-api.sh
|
||||
|
||||
2
.github/workflows/cd.yml
vendored
2
.github/workflows/cd.yml
vendored
@@ -4,7 +4,7 @@ name: GitHub Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master ]
|
||||
branches: [main, master]
|
||||
paths:
|
||||
- 'package.json'
|
||||
- '.github/workflows/cd.yml'
|
||||
|
||||
66
.github/workflows/ci-e2e.yml
vendored
66
.github/workflows/ci-e2e.yml
vendored
@@ -16,6 +16,31 @@ jobs:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cache Firebase emulators
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/firebase/emulators
|
||||
key: firebase-emulators-${{ hashFiles('firebase.json') }}
|
||||
restore-keys: firebase-emulators-
|
||||
|
||||
# - name: Cache Docker layers
|
||||
# uses: ScribeMD/docker-cache@0.5.0
|
||||
# with:
|
||||
# key: docker-${{ runner.os }}-${{ hashFiles('supabase/config.toml') }}
|
||||
|
||||
- name: Cache node_modules
|
||||
id: cache-node-modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: node_modules
|
||||
key: node-modules-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
- name: Cache Playwright browsers
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/ms-playwright
|
||||
key: playwright-${{ hashFiles('package.json') }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
@@ -28,22 +53,40 @@ jobs:
|
||||
distribution: 'temurin'
|
||||
java-version: '21' # Required for firebase-tools@15+
|
||||
|
||||
- name: Setup Supabase CLI
|
||||
uses: supabase/setup-cli@v1
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
env:
|
||||
HUSKY: 0
|
||||
|
||||
- name: Install Playwright browsers
|
||||
run: npx playwright install chromium --with-deps
|
||||
|
||||
- name: Start Supabase # optional step, as if supabase is stopped, it would be started in test:e2e, but done here to avoid cluttering the logs of the E2E tests
|
||||
run: |
|
||||
echo "::group::Supabase start (docker pull logs)"
|
||||
npx supabase start
|
||||
echo "::endgroup::"
|
||||
# Docker load from cache is actually slower than pulling the images every time with supabase start
|
||||
# - name: Cache Supabase Docker images
|
||||
# uses: actions/cache@v4
|
||||
# with:
|
||||
# path: /tmp/supabase-docker
|
||||
# key: supabase-docker-${{ hashFiles('supabase/config.toml') }}
|
||||
#
|
||||
# - name: Load cached Docker images
|
||||
# run: |
|
||||
# if [ -d /tmp/supabase-docker ]; then
|
||||
# for tar in /tmp/supabase-docker/*.tar; do
|
||||
# [ -f "$tar" ] && docker load -i "$tar"
|
||||
# done
|
||||
# fi
|
||||
|
||||
- name: Start Supabase
|
||||
run: ./scripts/supabase_start.sh
|
||||
|
||||
# - name: Save Supabase Docker images
|
||||
# run: |
|
||||
# mkdir -p /tmp/supabase-docker
|
||||
# docker images --format '{{.Repository}}:{{.Tag}}' \
|
||||
# | grep -E 'supabase|postgrest|gotrue|realtime|storage' \
|
||||
# | grep -v '<none>' \
|
||||
# | xargs -I{} sh -c \
|
||||
# 'docker save {} -o /tmp/supabase-docker/$(echo {} | tr "/:" "--").tar'
|
||||
|
||||
- name: Run E2E tests
|
||||
env:
|
||||
@@ -58,7 +101,7 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
path: tests/reports/playwright-report/
|
||||
retention-days: 7
|
||||
|
||||
- name: Upload test results
|
||||
@@ -68,3 +111,4 @@ jobs:
|
||||
name: test-results
|
||||
path: test-results/
|
||||
retention-days: 7
|
||||
if-no-files-found: ignore
|
||||
|
||||
@@ -21,7 +21,8 @@ export const getServiceAccountCredentials = () => {
|
||||
try {
|
||||
return JSON.parse(readFileSync(keyPath, {encoding: 'utf8'}))
|
||||
} catch (e) {
|
||||
throw new Error(`Failed to load service account key from ${keyPath}: ${e}`)
|
||||
if (!process.env.NEXT_PUBLIC_ISOLATED_ENV && !process.env.FIREBASE_AUTH_EMULATOR_HOST)
|
||||
throw new Error(`Failed to load service account key from ${keyPath}: ${e}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,14 @@ const newClient = (
|
||||
console.log('Creating Supabase direct client')
|
||||
}
|
||||
|
||||
if (!databaseUrl && process.env.NEXT_PUBLIC_ISOLATED_ENV) {
|
||||
throw new Error(
|
||||
`You are running isolated tests (NEXT_PUBLIC_ISOLATED_ENV=true), so you do not want to call the remote supabase. ${{
|
||||
databaseUrl,
|
||||
}}`,
|
||||
)
|
||||
}
|
||||
|
||||
const config: any = databaseUrl
|
||||
? {
|
||||
// Use connection string for local/dev Postgres
|
||||
|
||||
@@ -247,3 +247,15 @@ export const INVERTED_RACE_CHOICES = invert(RACE_CHOICES)
|
||||
export const INVERTED_MBTI_CHOICES = invert(MBTI_CHOICES)
|
||||
export const INVERTED_GENDERS = invert(GENDERS)
|
||||
export const INVERTED_LAST_ONLINE_CHOICES = invert(LAST_ONLINE_CHOICES)
|
||||
|
||||
//Exported types for test files to use when referencing the keys of the choices objects
|
||||
export type ConnectionTypeKey = keyof typeof RELATIONSHIP_CHOICES
|
||||
export type RelationshipStatusKey = keyof typeof RELATIONSHIP_STATUS_CHOICES
|
||||
export type RelationshipStyleKey = keyof typeof ROMANTIC_CHOICES
|
||||
export type PoliticalBeliefsKey = keyof typeof POLITICAL_CHOICES
|
||||
export type DietKey = keyof typeof DIET_CHOICES
|
||||
export type EducationKey = keyof typeof EDUCATION_CHOICES
|
||||
export type ReligionKey = keyof typeof RELIGION_CHOICES
|
||||
export type LanguageKey = keyof typeof LANGUAGE_CHOICES
|
||||
export type EthnicityKey = keyof typeof RACE_CHOICES
|
||||
export type PersonalityKey = keyof typeof MBTI_CHOICES
|
||||
|
||||
@@ -29,6 +29,7 @@ export function createClient(
|
||||
key: string,
|
||||
opts?: SupabaseClientOptionsGeneric<'public'>,
|
||||
) {
|
||||
if (key === 'null') throw new Error(`Invalid supabase anon key: ${key}`)
|
||||
// Allow passing a full Supabase URL directly (e.g., http://localhost:54321)
|
||||
const url = /:\/\//.test(instanceIdOrUrl)
|
||||
? instanceIdOrUrl
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"test:e2e:ui": "./scripts/e2e.sh --ui",
|
||||
"test:e2e:debug": "./scripts/e2e.sh --debug",
|
||||
"test:e2e:services": "./scripts/e2e_services.sh",
|
||||
"test:db:reset": "npx supabase start && ./scripts/combine-migrations.sh && npx supabase db reset && yarn test:db:seed",
|
||||
"test:db:reset": "./scripts/test_db_reset.sh",
|
||||
"test:db:reset-postgres": "docker compose -f scripts/docker-compose.test.yml down -v && docker compose -f scripts/docker-compose.test.yml up -d",
|
||||
"test:db:migrate": "./scripts/test_db_migration.sh",
|
||||
"test:db:seed": "./scripts/seed.sh",
|
||||
|
||||
@@ -1,15 +1,47 @@
|
||||
import {defineConfig, devices} from '@playwright/test'
|
||||
import {execSync} from 'child_process'
|
||||
import {config} from 'dotenv'
|
||||
|
||||
// Load static env vars from .env.test
|
||||
config({path: '.env.test', quiet: true})
|
||||
|
||||
// Dynamically pull Supabase vars
|
||||
function getSupabaseEnv() {
|
||||
try {
|
||||
const raw = execSync('npx supabase status --output json 2>/dev/null', {encoding: 'utf-8'})
|
||||
const status = JSON.parse(raw)
|
||||
if (!status.API_URL) throw new Error('No supabase API URL')
|
||||
if (!status.ANON_KEY) throw new Error('No supabase ANON_KEY')
|
||||
if (!status.DB_URL) throw new Error('No supabase DB_URL')
|
||||
return {
|
||||
NEXT_PUBLIC_SUPABASE_URL: status.API_URL,
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY: status.ANON_KEY,
|
||||
DATABASE_URL: status.DB_URL,
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
throw new Error('Failed to get Supabase status. Is it running?')
|
||||
}
|
||||
}
|
||||
|
||||
const supabaseEnv = getSupabaseEnv()
|
||||
|
||||
// Inject into process.env so Playwright and your app code can read them
|
||||
Object.assign(process.env, supabaseEnv)
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './tests/e2e',
|
||||
fullyParallel: true,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
// No retries by default (even in CI) because it slows the CI pipeline and masks real bugs
|
||||
// If there is a known intermittent browser timing issue for some tests, it's fine to give 1 retry to those flaky tests
|
||||
retries: process.env.CI ? 0 : 0,
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
reporter: [['html', {outputFolder: `tests/reports/playwright-report`, open: 'on-failure'}]],
|
||||
use: {
|
||||
baseURL: 'http://localhost:3000',
|
||||
trace: 'on-first-retry',
|
||||
// headless: false,
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
@@ -27,7 +59,7 @@ export default defineConfig({
|
||||
// use: { ...devices['Desktop Safari'] },
|
||||
// },
|
||||
],
|
||||
timeout: 60000,
|
||||
timeout: 120000,
|
||||
expect: {
|
||||
timeout: 120000,
|
||||
},
|
||||
|
||||
@@ -72,7 +72,7 @@ while IFS= read -r file; do
|
||||
cat "$file"
|
||||
} > "$OUTPUT"
|
||||
|
||||
echo "✅ $file -> $OUTPUT"
|
||||
# echo "✅ $file -> $OUTPUT"
|
||||
|
||||
COUNTER=$((COUNTER + 100))
|
||||
done <<< "$FILES"
|
||||
|
||||
@@ -4,6 +4,8 @@ set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")"/..
|
||||
|
||||
export NEXT_PUBLIC_ISOLATED_ENV=true
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
@@ -11,22 +13,10 @@ NC='\033[0m'
|
||||
print_status() { echo -e "${GREEN}[E2E-DEV]${NC} $1"; }
|
||||
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
|
||||
get_supabase_status() {
|
||||
SUPABASE_STATUS=$(supabase status --output json 2>/dev/null)
|
||||
}
|
||||
|
||||
get_supabase_status
|
||||
|
||||
# Check services are running (fail fast with helpful message)
|
||||
check_services() {
|
||||
local missing=0
|
||||
|
||||
if [ -z "$(echo "$SUPABASE_STATUS" | jq -r '.API_URL')" ]; then
|
||||
print_error "Supabase is not running. Starting..."
|
||||
yarn test:db:reset
|
||||
get_supabase_status
|
||||
fi
|
||||
|
||||
if ! curl -s http://127.0.0.1:9099 > /dev/null 2>&1; then
|
||||
print_error "Firebase emulator is not running. Run: yarn emulate"
|
||||
missing=1
|
||||
@@ -54,11 +44,6 @@ print_status "Checking services..."
|
||||
check_services
|
||||
print_status "All services running ✅"
|
||||
|
||||
export $(cat .env.test | grep -v '^#' | xargs)
|
||||
export NEXT_PUBLIC_SUPABASE_URL=$(echo "$SUPABASE_STATUS" | jq -r '.API_URL')
|
||||
export NEXT_PUBLIC_SUPABASE_ANON_KEY=$(echo "$SUPABASE_STATUS" | jq -r '.ANON_KEY')
|
||||
export DATABASE_URL=$(echo "$SUPABASE_STATUS" | jq -r '.DB_URL')
|
||||
|
||||
# Run tests - pass all args through to playwright
|
||||
# Examples:
|
||||
# yarn test:e2e:dev → all e2e tests
|
||||
|
||||
@@ -5,6 +5,9 @@ set -euo pipefail
|
||||
# Change to project root
|
||||
cd "$(dirname "$0")"/..
|
||||
|
||||
export NEXT_PUBLIC_ISOLATED_ENV=true
|
||||
export CI=true
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
@@ -60,18 +63,7 @@ supabase stop --no-backup 2>/dev/null || true
|
||||
sleep 2 # Give ports time to free up
|
||||
|
||||
# Build backend (required?)
|
||||
./scripts/build_api.sh
|
||||
|
||||
# Get connection details
|
||||
export NEXT_PUBLIC_SUPABASE_URL=$(supabase status --output json | jq -r '.API_URL')
|
||||
export NEXT_PUBLIC_SUPABASE_ANON_KEY=$(supabase status --output json | jq -r '.ANON_KEY')
|
||||
export DATABASE_URL=$(supabase status --output json | jq -r '.DB_URL')
|
||||
|
||||
echo $NEXT_PUBLIC_SUPABASE_URL
|
||||
echo $NEXT_PUBLIC_SUPABASE_ANON_KEY
|
||||
echo $DATABASE_URL
|
||||
|
||||
print_status "Supabase started at: $DATABASE_URL"
|
||||
#./scripts/build_api.sh
|
||||
|
||||
# Install Playwright browsers
|
||||
print_status "Installing Playwright browsers..."
|
||||
@@ -90,6 +82,26 @@ npx wait-on \
|
||||
# Start Supabase (includes Postgres, Auth, Storage, etc.) and Apply migrations and seed (needs firebase emulator running)
|
||||
yarn test:db:reset
|
||||
|
||||
# Get connection details
|
||||
STATUS_JSON=$(supabase status --output json)
|
||||
export NEXT_PUBLIC_SUPABASE_URL=$(echo "$STATUS_JSON" | jq -r '.API_URL')
|
||||
export NEXT_PUBLIC_SUPABASE_ANON_KEY=$(echo "$STATUS_JSON" | jq -r '.ANON_KEY')
|
||||
export DATABASE_URL=$(echo "$STATUS_JSON" | jq -r '.DB_URL')
|
||||
|
||||
print_status "Supabase started at: $DATABASE_URL"
|
||||
|
||||
echo "Supabase env vars:"
|
||||
echo $NEXT_PUBLIC_SUPABASE_URL
|
||||
echo $NEXT_PUBLIC_SUPABASE_ANON_KEY
|
||||
echo $DATABASE_URL
|
||||
|
||||
for var in NEXT_PUBLIC_SUPABASE_URL NEXT_PUBLIC_SUPABASE_ANON_KEY DATABASE_URL; do
|
||||
if [ -z "${!var}" ] || [ "${!var}" = "null" ]; then
|
||||
echo "Error: $var is not set or null" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Start backend API
|
||||
print_status "Starting backend API..."
|
||||
yarn --cwd=backend/api dev & PIDS+=($!)
|
||||
|
||||
@@ -8,6 +8,8 @@ set -euo pipefail
|
||||
# Change to project root
|
||||
cd "$(dirname "$0")"/..
|
||||
|
||||
export NEXT_PUBLIC_ISOLATED_ENV=true
|
||||
|
||||
export $(cat .env.test | grep -v '^#' | xargs)
|
||||
|
||||
# Ensure Supabase local stack is running; if not, reset/start it
|
||||
@@ -24,6 +26,13 @@ export NEXT_PUBLIC_SUPABASE_URL=$(echo "$STATUS_JSON" | jq -r '.API_URL')
|
||||
export NEXT_PUBLIC_SUPABASE_ANON_KEY=$(echo "$STATUS_JSON" | jq -r '.ANON_KEY')
|
||||
export DATABASE_URL=$(echo "$STATUS_JSON" | jq -r '.DB_URL')
|
||||
|
||||
for var in NEXT_PUBLIC_SUPABASE_URL NEXT_PUBLIC_SUPABASE_ANON_KEY DATABASE_URL; do
|
||||
if [ -z "${!var}" ] || [ "${!var}" = "null" ]; then
|
||||
echo "Error: $var is not set or null" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Build backend (required?)
|
||||
./scripts/build_api.sh
|
||||
|
||||
|
||||
@@ -8,12 +8,10 @@ cd "$(dirname "$0")"/..
|
||||
export $(cat .env.test | grep -v '^#' | xargs)
|
||||
|
||||
# Get connection details
|
||||
export NEXT_PUBLIC_SUPABASE_URL=$(supabase status --output json | jq -r '.API_URL')
|
||||
export NEXT_PUBLIC_SUPABASE_ANON_KEY=$(supabase status --output json | jq -r '.ANON_KEY')
|
||||
export DATABASE_URL=$(supabase status --output json | jq -r '.DB_URL')
|
||||
|
||||
# Build backend (required?)
|
||||
#./scripts/build_api.sh
|
||||
STATUS_JSON=$(supabase status --output json)
|
||||
export NEXT_PUBLIC_SUPABASE_URL=$(echo "$STATUS_JSON" | jq -r '.API_URL')
|
||||
export NEXT_PUBLIC_SUPABASE_ANON_KEY=$(echo "$STATUS_JSON" | jq -r '.ANON_KEY')
|
||||
export DATABASE_URL=$(echo "$STATUS_JSON" | jq -r '.DB_URL')
|
||||
|
||||
cd tests/e2e/utils
|
||||
|
||||
|
||||
11
scripts/supabase_start.sh
Executable file
11
scripts/supabase_start.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
if [ "${CI:-false}" = "true" ]; then
|
||||
npx supabase start --exclude studio
|
||||
else
|
||||
npx supabase start
|
||||
fi
|
||||
13
scripts/test_db_reset.sh
Executable file
13
scripts/test_db_reset.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
./scripts/supabase_start.sh
|
||||
|
||||
./scripts/combine-migrations.sh
|
||||
|
||||
npx supabase db reset
|
||||
|
||||
yarn test:db:seed
|
||||
@@ -58,7 +58,7 @@ enabled = true
|
||||
sql_paths = ["./seed.sql"]
|
||||
|
||||
[realtime]
|
||||
enabled = true
|
||||
enabled = false
|
||||
# Bind realtime via either IPv4 or IPv6. (default: IPv4)
|
||||
# ip_version = "IPv6"
|
||||
# The maximum length in bytes of HTTP request headers. (default: 4096)
|
||||
@@ -76,7 +76,7 @@ openai_api_key = "env(OPENAI_API_KEY)"
|
||||
# Email testing server. Emails sent with the local dev setup are not actually sent - rather, they
|
||||
# are monitored, and you can view the emails that would have been sent from the web interface.
|
||||
[inbucket]
|
||||
enabled = true
|
||||
enabled = false
|
||||
# Port to use for the email testing server web interface.
|
||||
port = 54324
|
||||
# Uncomment to expose additional ports for testing user applications that send emails.
|
||||
@@ -86,7 +86,7 @@ port = 54324
|
||||
# sender_name = "Admin"
|
||||
|
||||
[storage]
|
||||
enabled = true
|
||||
enabled = false
|
||||
# The maximum file size allowed (e.g. "5MB", "500KB").
|
||||
file_size_limit = "50MiB"
|
||||
|
||||
@@ -256,7 +256,7 @@ enabled = false
|
||||
# user_pool_region = "us-east-1"
|
||||
|
||||
[edge_runtime]
|
||||
enabled = true
|
||||
enabled = false
|
||||
# Configure one of the supported request policies: `oneshot`, `per_worker`.
|
||||
# Use `oneshot` for hot reload, or `per_worker` for load testing.
|
||||
policy = "oneshot"
|
||||
@@ -276,7 +276,7 @@ inspector_port = 8083
|
||||
# static_files = [ "./functions/MY_FUNCTION_NAME/*.html" ]
|
||||
|
||||
[analytics]
|
||||
enabled = true
|
||||
enabled = false
|
||||
port = 54327
|
||||
# Configure one of the supported backends: `postgres`, `bigquery`.
|
||||
backend = "postgres"
|
||||
|
||||
47
tests/e2e/utils/databaseUtils.ts
Normal file
47
tests/e2e/utils/databaseUtils.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import {createSupabaseDirectClient} from 'shared/supabase/init'
|
||||
|
||||
export async function deleteFromDb(user_id: string) {
|
||||
const db = createSupabaseDirectClient()
|
||||
const deleteEntryById = `DELETE FROM users WHERE id = $1 RETURNING *`
|
||||
const result = await db.query(deleteEntryById, [user_id])
|
||||
|
||||
if (!result.length) {
|
||||
throw new Error(`No user found with id: ${user_id}`)
|
||||
}
|
||||
|
||||
console.log('Deleted data: ', {
|
||||
id: result[0].id,
|
||||
name: result[0].name,
|
||||
username: result[0].username,
|
||||
})
|
||||
}
|
||||
|
||||
export async function userInformationFromDb(account: any) {
|
||||
const db = createSupabaseDirectClient()
|
||||
const queryUserById = `
|
||||
SELECT p.*
|
||||
FROM users AS p
|
||||
WHERE username = $1
|
||||
`
|
||||
const userResults = await db.query(queryUserById, [account.username])
|
||||
|
||||
if (userResults.length === 0) {
|
||||
throw new Error(`No user found with username: ${account.username}`)
|
||||
}
|
||||
|
||||
const queryProfileById = `
|
||||
SELECT p.*
|
||||
FROM profiles AS p
|
||||
WHERE user_id = $1
|
||||
`
|
||||
const profileResults = await db.query(queryProfileById, [userResults[0].id])
|
||||
|
||||
if (profileResults.length === 0) {
|
||||
throw new Error(`No profile found for user: ${userResults[0].id}`)
|
||||
}
|
||||
|
||||
return {
|
||||
user: userResults[0],
|
||||
profile: profileResults[0],
|
||||
}
|
||||
}
|
||||
33
tests/e2e/utils/firebaseUtils.ts
Normal file
33
tests/e2e/utils/firebaseUtils.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import axios from 'axios'
|
||||
|
||||
import {config} from '../web/SPEC_CONFIG'
|
||||
|
||||
export async function login(email: string, password: string) {
|
||||
const login = await axios.post(
|
||||
`${config.FIREBASE_URL.BASE}${config.FIREBASE_URL.SIGN_IN_PASSWORD}`,
|
||||
{
|
||||
email,
|
||||
password,
|
||||
returnSecureToken: true,
|
||||
},
|
||||
)
|
||||
return login
|
||||
}
|
||||
|
||||
export async function signUp(email: string, password: string) {
|
||||
// const base = 'http://localhost:9099/identitytoolkit.googleapis.com/v1';
|
||||
|
||||
await axios.post(`${config.FIREBASE_URL.BASE}${config.FIREBASE_URL.SIGNUP}`, {
|
||||
email,
|
||||
password,
|
||||
returnSecureToken: true,
|
||||
})
|
||||
|
||||
console.log('Auth created for', email)
|
||||
}
|
||||
|
||||
export async function deleteAccount(login: any) {
|
||||
await axios.post(`${config.FIREBASE_URL.BASE}${config.FIREBASE_URL.DELETE}`, {
|
||||
idToken: login.data.idToken,
|
||||
})
|
||||
}
|
||||
@@ -27,8 +27,8 @@ async function createAuth(email: string, password: string) {
|
||||
) {
|
||||
return
|
||||
}
|
||||
if (err.code === 'ECONNREFUSED')
|
||||
throw Error('Firebase emulator not running. Start it with:\n yarn test:e2e:services\n')
|
||||
if (err.code === 'ECONNREFUSED') return
|
||||
// throw Error('Firebase emulator not running. Start it with:\n yarn test:e2e:services\n')
|
||||
console.log(err)
|
||||
throw err
|
||||
}
|
||||
@@ -36,17 +36,35 @@ async function createAuth(email: string, password: string) {
|
||||
|
||||
async function seedCompatibilityPrompts(pg: any, userId: string | null = null) {
|
||||
// Need some prompts to prevent the onboarding from stopping once it reaches them (just after profile creation)
|
||||
const question = 'What is your favorite color?'
|
||||
const multiple_choice_options = {Blue: 0, Green: 1, Red: 2}
|
||||
const {data, error} = await tryCatch(
|
||||
insert(pg, 'compatibility_prompts', {
|
||||
creator_id: userId,
|
||||
question,
|
||||
answer_type: 'compatibility_multiple_choice',
|
||||
multiple_choice_options,
|
||||
}),
|
||||
)
|
||||
console.log('Compatibility prompts created', {data, error})
|
||||
const compatibilityPrompts = [
|
||||
{
|
||||
question: 'What is your favorite color?',
|
||||
options: {Blue: 0, Green: 1, Red: 2},
|
||||
},
|
||||
{
|
||||
question: 'What is your favorite animal?',
|
||||
options: {Dog: 0, Cat: 1, Bird: 2},
|
||||
},
|
||||
{
|
||||
question: 'What is your preferred time of day?',
|
||||
options: {Morning: 0, Afternoon: 1, Night: 2},
|
||||
},
|
||||
{
|
||||
question: 'What type of movies do you enjoy most?',
|
||||
options: {Action: 0, Comedy: 1, Drama: 2},
|
||||
},
|
||||
]
|
||||
for (let i = 0; i < compatibilityPrompts.length; i++) {
|
||||
const {data, error} = await tryCatch(
|
||||
insert(pg, 'compatibility_prompts', {
|
||||
creator_id: userId,
|
||||
question: compatibilityPrompts[i].question,
|
||||
answer_type: 'compatibility_multiple_choice',
|
||||
multiple_choice_options: compatibilityPrompts[i].options,
|
||||
}),
|
||||
)
|
||||
console.log('Compatibility prompts created', {data, error})
|
||||
}
|
||||
}
|
||||
|
||||
async function seedNotifications() {
|
||||
@@ -76,7 +94,7 @@ type ProfileType = 'basic' | 'medium' | 'full'
|
||||
}
|
||||
userInfo.user_id = await createAuth(userInfo.email, userInfo.password)
|
||||
if (userInfo.user_id) {
|
||||
console.log('User created in Supabase:', userInfo)
|
||||
console.log('User created in Supabase:', userInfo.email)
|
||||
await seedDatabase(pg, userInfo, profileType)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import axios from 'axios'
|
||||
|
||||
import {config} from '../web/SPEC_CONFIG'
|
||||
|
||||
async function createAuth() {
|
||||
// const base = 'http://localhost:9099/identitytoolkit.googleapis.com/v1';
|
||||
|
||||
await axios.post(`${config.FIREBASE_URL.BASE}${config.FIREBASE_URL.SIGNUP}`, {
|
||||
email: config.USERS.DEV_1.EMAIL,
|
||||
password: config.USERS.DEV_1.PASSWORD,
|
||||
returnSecureToken: true,
|
||||
})
|
||||
|
||||
console.log('Auth created', config.USERS.DEV_1.EMAIL)
|
||||
}
|
||||
createAuth()
|
||||
@@ -1,6 +1,7 @@
|
||||
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 {ProfilePage} from '../pages/profilePage'
|
||||
@@ -14,6 +15,7 @@ export const test = base.extend<{
|
||||
signUpPage: SignUpPage
|
||||
profilePage: ProfilePage
|
||||
authPage: AuthPage
|
||||
compatabilityPage: ComatibilityPage
|
||||
cleanUpUsers: void
|
||||
testAccount: OnboardingUser
|
||||
fakerAccount: OnboardingUser
|
||||
@@ -50,12 +52,10 @@ export const test = base.extend<{
|
||||
const profilePage = new ProfilePage(page)
|
||||
await use(profilePage)
|
||||
},
|
||||
// cleanUpUsers: [
|
||||
// async ({}, use) => {
|
||||
// await use()
|
||||
// },
|
||||
// {auto: true},
|
||||
// ],
|
||||
compatabilityPage: async ({page}, use) => {
|
||||
const compatibilityPage = new ComatibilityPage(page)
|
||||
await use(compatibilityPage)
|
||||
},
|
||||
})
|
||||
|
||||
export {expect} from '@playwright/test'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {expect, Page, test as base} from '@playwright/test'
|
||||
|
||||
import {signUp} from '../../utils/firebaseUtils'
|
||||
import {AuthPage} from '../pages/AuthPage'
|
||||
import {config} from '../SPEC_CONFIG'
|
||||
|
||||
@@ -9,9 +10,18 @@ export const test = base.extend<{
|
||||
authenticatedPage: async ({page}, use) => {
|
||||
const authPage = new AuthPage(page)
|
||||
|
||||
const email = config.USERS.DEV_1.EMAIL
|
||||
const password = config.USERS.DEV_1.PASSWORD
|
||||
|
||||
try {
|
||||
await signUp(email, password)
|
||||
} catch (_e) {
|
||||
console.log('User already exists for signinFixture', email)
|
||||
}
|
||||
|
||||
await page.goto('/signin')
|
||||
await authPage.fillEmailField(config.USERS.DEV_1.EMAIL)
|
||||
await authPage.fillPasswordField(config.USERS.DEV_1.PASSWORD)
|
||||
await authPage.fillEmailField(email)
|
||||
await authPage.fillPasswordField(password)
|
||||
await authPage.clickSignInWithEmailButton()
|
||||
|
||||
await page.waitForURL(/^(?!.*signin).*$/)
|
||||
|
||||
28
tests/e2e/web/pages/compatibilityPage.ts
Normal file
28
tests/e2e/web/pages/compatibilityPage.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import {expect, Locator, Page} from '@playwright/test'
|
||||
|
||||
export class ComatibilityPage {
|
||||
private readonly answeredQuestionsTab: Locator
|
||||
private readonly remaningQuestionsTab: Locator
|
||||
private readonly skippedQuestionsTab: Locator
|
||||
|
||||
constructor(public readonly page: Page) {
|
||||
this.answeredQuestionsTab = page.getByText('Answered')
|
||||
this.remaningQuestionsTab = page.getByText('To Answer')
|
||||
this.skippedQuestionsTab = page.getByText('Skipped')
|
||||
}
|
||||
|
||||
async clickAnsweredQuestionsTab() {
|
||||
await expect(this.answeredQuestionsTab).toBeVisible()
|
||||
await this.answeredQuestionsTab.click()
|
||||
}
|
||||
|
||||
async clickRemainingQuestionsTab() {
|
||||
await expect(this.remaningQuestionsTab).toBeVisible()
|
||||
await this.remaningQuestionsTab.click()
|
||||
}
|
||||
|
||||
async clickSkippedQuestionsTab() {
|
||||
await expect(this.skippedQuestionsTab).toBeVisible()
|
||||
await this.skippedQuestionsTab.click()
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import {expect, Locator, Page} from '@playwright/test'
|
||||
|
||||
import {Socials} from '../utils/accountInformation'
|
||||
|
||||
type ProfileDropdownOptions = 'Public' | 'Private' | 'Disable'
|
||||
@@ -41,6 +42,8 @@ export class ProfilePage {
|
||||
private readonly bioOptionsDropdown: Locator
|
||||
private readonly editBioDropdownOptions: Locator
|
||||
private readonly deleteBioDropdownOptions: Locator
|
||||
private readonly answerCoreQuestionsButton: Locator
|
||||
private readonly viewQuestionListButton: Locator
|
||||
|
||||
constructor(public readonly page: Page) {
|
||||
this.startAnsweringButton = page.getByRole('button', {})
|
||||
@@ -86,6 +89,8 @@ export class ProfilePage {
|
||||
this.bioOptionsDropdown = page.getByTestId('profile-bio-options')
|
||||
this.editBioDropdownOptions = page.getByText('Edit', {exact: true})
|
||||
this.deleteBioDropdownOptions = page.getByText('Delete', {exact: true})
|
||||
this.answerCoreQuestionsButton = page.getByRole('button', {name: 'Answer Core Questions'})
|
||||
this.viewQuestionListButton = page.getByRole('link', {name: 'View List of Questions'})
|
||||
}
|
||||
|
||||
async clickCloseButton() {
|
||||
@@ -113,6 +118,16 @@ export class ProfilePage {
|
||||
await this.editProfileButton.click()
|
||||
}
|
||||
|
||||
async clickAnswerQuestionsButton() {
|
||||
await expect(this.answerCoreQuestionsButton).toBeVisible()
|
||||
await this.answerCoreQuestionsButton.click()
|
||||
}
|
||||
|
||||
async clickViewQuestionListButton() {
|
||||
await expect(this.viewQuestionListButton).toBeVisible()
|
||||
await this.viewQuestionListButton.click()
|
||||
}
|
||||
|
||||
async selectOptionFromProfileDropdown(option: ProfileDropdownOptions) {
|
||||
await expect(this.profileOptionsDropdown).toBeVisible()
|
||||
await this.profileOptionsDropdown.click()
|
||||
@@ -185,11 +200,12 @@ export class ProfilePage {
|
||||
await expect(textContent?.toLowerCase()).toContain(numberOfKids.toLowerCase())
|
||||
}
|
||||
|
||||
async verifyWantChildrenExpectation(expectation: string | undefined) {
|
||||
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(expectation.toLowerCase())
|
||||
await expect(textContent?.toLowerCase()).toContain(label.toLowerCase())
|
||||
}
|
||||
|
||||
async verifyInterests(interest: string[] | undefined) {
|
||||
@@ -210,6 +226,14 @@ export class ProfilePage {
|
||||
}
|
||||
}
|
||||
|
||||
async verifyWorkArea(workArea: string[] | undefined) {
|
||||
if (!workArea || workArea.length === 0) return
|
||||
await expect(this.workAreaAboutSection).toBeVisible()
|
||||
for (let i = 0; i < workArea.length; i++) {
|
||||
await expect(this.workAreaAboutSection).toContainText(workArea[i], {ignoreCase: true})
|
||||
}
|
||||
}
|
||||
|
||||
async verifyEducationLevelAndUniversity(educationLevel?: string, university?: string) {
|
||||
await expect(this.educationAboutSection).toBeVisible()
|
||||
const textContent = await this.educationAboutSection.textContent()
|
||||
@@ -294,4 +318,10 @@ export class ProfilePage {
|
||||
await expect(textContent?.toLowerCase()).toContain(socialMedia[i].urlOrUsername.toLowerCase())
|
||||
}
|
||||
}
|
||||
|
||||
async verifyBio(bio: string | undefined) {
|
||||
if (!bio) return
|
||||
await expect(this.bioSection).toBeVisible()
|
||||
await expect(this.bioSection).toContainText(bio)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,25 @@
|
||||
import {expect, Locator, Page} from '@playwright/test'
|
||||
import {
|
||||
RELATIONSHIP_CHOICES,
|
||||
RELATIONSHIP_STATUS_CHOICES,
|
||||
ROMANTIC_CHOICES,
|
||||
POLITICAL_CHOICES,
|
||||
DIET_CHOICES,
|
||||
EDUCATION_CHOICES,
|
||||
RELIGION_CHOICES,
|
||||
LANGUAGE_CHOICES,
|
||||
RACE_CHOICES,
|
||||
MBTI_CHOICES,
|
||||
ConnectionTypeKey,
|
||||
DietKey,
|
||||
EducationKey,
|
||||
EthnicityKey,
|
||||
LanguageKey,
|
||||
PersonalityKey,
|
||||
PoliticalBeliefsKey,
|
||||
RelationshipStatusKey,
|
||||
RelationshipStyleKey,
|
||||
ReligionKey,
|
||||
} from 'common/choices'
|
||||
|
||||
export type Gender = 'Woman' | 'Man' | 'Other'
|
||||
export type InterestedIn = 'Women' | 'Men' | 'Other'
|
||||
export type ConnectionType = keyof typeof RELATIONSHIP_CHOICES
|
||||
export type RelationshipStatus = keyof typeof RELATIONSHIP_STATUS_CHOICES
|
||||
export type RelationshipStyle = keyof typeof ROMANTIC_CHOICES
|
||||
export type ChildrenExpectation =
|
||||
| 'Strongly against'
|
||||
| 'Against'
|
||||
| 'Neutral'
|
||||
| 'For'
|
||||
| 'Strongly for'
|
||||
export type PoliticalBeliefs = keyof typeof POLITICAL_CHOICES
|
||||
export type Diet = keyof typeof DIET_CHOICES
|
||||
export type Education = keyof typeof EDUCATION_CHOICES
|
||||
export type Religion = keyof typeof RELIGION_CHOICES
|
||||
export type Language = keyof typeof LANGUAGE_CHOICES
|
||||
export type Ethnicity = keyof typeof RACE_CHOICES
|
||||
export type Personality = keyof typeof MBTI_CHOICES
|
||||
| ['Strongly against', 0]
|
||||
| ['Against', 1]
|
||||
| ['Neutral', 2]
|
||||
| ['For', 3]
|
||||
| ['Strongly for', 4]
|
||||
export type Interests = 'Chess' | 'Games' | 'Joy' | 'Livres'
|
||||
export type Causes = 'Animal Rights' | 'Feminism'
|
||||
export type Platforms =
|
||||
@@ -110,7 +100,7 @@ export class SignUpPage {
|
||||
this.displayNameField = page.getByPlaceholder('Display name')
|
||||
this.usernameField = page.getByPlaceholder('Username')
|
||||
this.nextButton = page.getByRole('button', {name: 'Next', exact: true})
|
||||
this.bioField = page.getByRole('paragraph').filter({hasText: /^$/})
|
||||
this.bioField = page.locator('.tiptap')
|
||||
this.locationField = page.getByPlaceholder('Search city...')
|
||||
this.ageField = page.getByPlaceholder('Age', {exact: true})
|
||||
this.feetHeightField = page.getByTestId('height-feet')
|
||||
@@ -224,7 +214,7 @@ export class SignUpPage {
|
||||
await this.centimetersHeightField.fill(centimeters)
|
||||
}
|
||||
|
||||
async fillEthnicity(ethnicity: Ethnicity | undefined) {
|
||||
async fillEthnicity(ethnicity: EthnicityKey | undefined) {
|
||||
if (ethnicity === 'Other') {
|
||||
await expect(
|
||||
this.page
|
||||
@@ -276,19 +266,19 @@ export class SignUpPage {
|
||||
}
|
||||
}
|
||||
|
||||
async setConnectionType(type: ConnectionType | undefined) {
|
||||
async setConnectionType(type: ConnectionTypeKey | undefined) {
|
||||
await expect(this.page.getByLabel(`${type}`, {exact: true})).toBeVisible()
|
||||
await this.page.getByLabel(`${type}`, {exact: true}).click()
|
||||
await expect(this.page.getByLabel(`${type}`, {exact: true})).toBeChecked()
|
||||
}
|
||||
|
||||
async setRelationshipStatus(status: RelationshipStatus | undefined) {
|
||||
async setRelationshipStatus(status: RelationshipStatusKey | undefined) {
|
||||
await expect(this.page.getByLabel(`${status}`, {exact: true})).toBeVisible()
|
||||
await this.page.getByLabel(`${status}`, {exact: true}).click()
|
||||
await expect(this.page.getByLabel(`${status}`, {exact: true})).toBeChecked()
|
||||
}
|
||||
|
||||
async setRelationshipStyle(style: RelationshipStyle | undefined) {
|
||||
async setRelationshipStyle(style: RelationshipStyleKey | undefined) {
|
||||
await expect(this.page.getByLabel(`${style}`, {exact: true})).toBeVisible()
|
||||
await this.page.getByLabel(`${style}`, {exact: true}).click()
|
||||
await expect(this.page.getByLabel(`${style}`, {exact: true})).toBeChecked()
|
||||
@@ -301,19 +291,21 @@ export class SignUpPage {
|
||||
}
|
||||
|
||||
async setWantChildrenExpectation(expectation: ChildrenExpectation | undefined) {
|
||||
if (expectation === 'Strongly against') {
|
||||
if (!expectation) return
|
||||
const [label, value] = expectation
|
||||
if (label === 'Strongly against') {
|
||||
await expect(this.stronglyDisagreeOnWantingKids).toBeVisible()
|
||||
await this.stronglyDisagreeOnWantingKids.click()
|
||||
await expect(this.stronglyDisagreeOnWantingKids).toBeChecked()
|
||||
} else if (expectation === 'Against') {
|
||||
} else if (label === 'Against') {
|
||||
await expect(this.disagreeOnWantingKids).toBeVisible()
|
||||
await this.disagreeOnWantingKids.click()
|
||||
await expect(this.disagreeOnWantingKids).toBeChecked()
|
||||
} else if (expectation === 'Neutral') {
|
||||
} else if (label === 'Neutral') {
|
||||
await expect(this.neutralOnWantingKids).toBeVisible()
|
||||
await this.neutralOnWantingKids.click()
|
||||
await expect(this.neutralOnWantingKids).toBeChecked()
|
||||
} else if (expectation === 'For') {
|
||||
} else if (label === 'For') {
|
||||
await expect(this.agreeOnWantingKids).toBeVisible()
|
||||
await this.agreeOnWantingKids.click()
|
||||
await expect(this.agreeOnWantingKids).toBeChecked()
|
||||
@@ -366,7 +358,7 @@ export class SignUpPage {
|
||||
}
|
||||
}
|
||||
|
||||
async setHighestEducationLevel(education: Education | undefined) {
|
||||
async setHighestEducationLevel(education: EducationKey | undefined) {
|
||||
await expect(this.page.getByText(`${education}`, {exact: true})).toBeVisible()
|
||||
await this.page.getByText(`${education}`, {exact: true}).click()
|
||||
await expect(this.page.getByText(`${education}`, {exact: true})).toBeChecked()
|
||||
@@ -400,11 +392,13 @@ export class SignUpPage {
|
||||
if (isExisting) {
|
||||
await expect(this.page.getByLabel(`${workArea[i]}`, {exact: true})).toBeVisible()
|
||||
await this.page.getByLabel(`${workArea[i]}`, {exact: true}).click()
|
||||
await this.page.waitForTimeout(500)
|
||||
} else {
|
||||
await expect(this.addWorkAreaField).toBeVisible()
|
||||
await expect(this.addWorkAreaButton).toBeVisible()
|
||||
await this.addWorkAreaField.fill(workArea[i])
|
||||
await this.addWorkAreaButton.click()
|
||||
await this.page.waitForTimeout(500)
|
||||
}
|
||||
await expect(this.page.getByLabel(`${workArea[i]}`, {exact: true})).toBeVisible()
|
||||
await expect(this.page.getByLabel(`${workArea[i]}`, {exact: true})).toBeChecked()
|
||||
@@ -412,7 +406,7 @@ export class SignUpPage {
|
||||
}
|
||||
|
||||
async setPoliticalBeliefs(
|
||||
politicalBeliefs?: PoliticalBeliefs | undefined,
|
||||
politicalBeliefs?: PoliticalBeliefsKey | undefined,
|
||||
details?: string | undefined,
|
||||
) {
|
||||
if (politicalBeliefs) {
|
||||
@@ -427,7 +421,10 @@ export class SignUpPage {
|
||||
}
|
||||
}
|
||||
|
||||
async setReligiousBeliefs(religiousBeliefs?: Religion | undefined, details?: string | undefined) {
|
||||
async setReligiousBeliefs(
|
||||
religiousBeliefs?: ReligionKey | undefined,
|
||||
details?: string | undefined,
|
||||
) {
|
||||
if (religiousBeliefs && religiousBeliefs === 'Other') {
|
||||
await expect(
|
||||
this.page
|
||||
@@ -458,7 +455,7 @@ export class SignUpPage {
|
||||
}
|
||||
}
|
||||
|
||||
async setPersonalityType(personalityType: Personality | undefined) {
|
||||
async setPersonalityType(personalityType: PersonalityKey | undefined) {
|
||||
await expect(this.page.getByText(`${personalityType}`, {exact: true})).toBeVisible()
|
||||
await this.page.getByText(`${personalityType}`, {exact: true}).click()
|
||||
await expect(this.page.getByText(`${personalityType}`, {exact: true})).toBeChecked()
|
||||
@@ -619,7 +616,7 @@ export class SignUpPage {
|
||||
}
|
||||
}
|
||||
|
||||
async setDietType(dietType: Diet | undefined) {
|
||||
async setDietType(dietType: DietKey | undefined) {
|
||||
if (dietType === 'Other') {
|
||||
await expect(this.page.locator('label').filter({hasText: 'Other'}).nth(4)).toBeVisible()
|
||||
await this.page.locator('label').filter({hasText: 'Other'}).nth(4).click()
|
||||
@@ -649,8 +646,9 @@ export class SignUpPage {
|
||||
await this.alcoholConsumedPerMonthField.fill(amount)
|
||||
}
|
||||
|
||||
async setLanguages(language: Language[] | undefined) {
|
||||
async setLanguages(language: LanguageKey[] | undefined) {
|
||||
if (!language || language.length === 0) return
|
||||
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]}`})).toBeVisible()
|
||||
await this.page.getByRole('checkbox', {name: `${language[i]}`}).click()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {test} from '../fixtures/base'
|
||||
import {userInformationFromDb} from '../../utils/databaseUtils'
|
||||
import {expect, test} from '../fixtures/base'
|
||||
|
||||
test.describe('when given valid input', () => {
|
||||
test('should successfully complete the onboarding flow', async ({
|
||||
@@ -9,6 +10,9 @@ test.describe('when given valid input', () => {
|
||||
profilePage,
|
||||
testAccount,
|
||||
}) => {
|
||||
console.log(
|
||||
`Starting "should successfully complete the onboarding flow" with ${testAccount.username}`,
|
||||
)
|
||||
await homePage.gotToHomePage()
|
||||
await homePage.clickSignUpButton()
|
||||
await authPage.fillEmailField(testAccount.email)
|
||||
@@ -18,10 +22,8 @@ test.describe('when given valid input', () => {
|
||||
await onboardingPage.clickContinueButton() //Second continue
|
||||
await onboardingPage.clickGetStartedButton()
|
||||
await signUpPage.fillDisplayName(testAccount.display_name)
|
||||
// TODO: fix?
|
||||
await signUpPage.fillUsername(testAccount.username + Date.now().toString())
|
||||
await signUpPage.fillUsername(testAccount.username)
|
||||
await signUpPage.clickNextButton()
|
||||
await signUpPage.fillBio(testAccount.bio)
|
||||
await signUpPage.chooseGender(testAccount.gender)
|
||||
await signUpPage.fillAge(testAccount.age)
|
||||
await signUpPage.fillHeight({
|
||||
@@ -45,7 +47,7 @@ test.describe('when given valid input', () => {
|
||||
await signUpPage.fillUniversity(testAccount.university)
|
||||
await signUpPage.fillJobTitle(testAccount.job_title)
|
||||
await signUpPage.fillCompany(testAccount.company)
|
||||
await signUpPage.setWorkArea(testAccount.work_area) //Is not displayed correctly
|
||||
await signUpPage.setWorkArea(testAccount.work_area)
|
||||
await signUpPage.setPoliticalBeliefs(
|
||||
testAccount.beliefs?.political?.belief,
|
||||
testAccount.beliefs?.political?.details,
|
||||
@@ -61,10 +63,12 @@ test.describe('when given valid input', () => {
|
||||
await signUpPage.fillAlcoholPerMonth(testAccount.alcohol_consumed_per_month)
|
||||
await signUpPage.setLanguages(testAccount.languages)
|
||||
await signUpPage.addSocialMediaPlatform(testAccount.social_media)
|
||||
await signUpPage.fillBio(testAccount.bio)
|
||||
await signUpPage.clickNextButton()
|
||||
await profilePage.clickCloseButton()
|
||||
await onboardingPage.clickRefineProfileButton()
|
||||
|
||||
//Verify information is correct
|
||||
await profilePage.verifyDisplayNameAndAge(testAccount.display_name, testAccount.age)
|
||||
await profilePage.verifyGenderLocationHeight(
|
||||
testAccount.gender,
|
||||
@@ -91,6 +95,7 @@ test.describe('when given valid input', () => {
|
||||
testAccount.university,
|
||||
)
|
||||
await profilePage.verifyJobInformation(testAccount.job_title, testAccount.company)
|
||||
await profilePage.verifyWorkArea(testAccount.work_area)
|
||||
await profilePage.verifyPoliticalBeliefs(
|
||||
testAccount.beliefs?.political?.belief,
|
||||
testAccount.beliefs?.political?.details,
|
||||
@@ -106,6 +111,56 @@ test.describe('when given valid input', () => {
|
||||
await profilePage.verifyDrinksPerMonth(testAccount.alcohol_consumed_per_month)
|
||||
await profilePage.verifyLanguages(testAccount.languages)
|
||||
await profilePage.verifySocialMedia(testAccount.social_media)
|
||||
await profilePage.verifyBio(testAccount.bio)
|
||||
|
||||
//Verify Database Information
|
||||
const dbInfo = await userInformationFromDb(testAccount)
|
||||
// console.log(dbInfo.profile.bio_text);
|
||||
|
||||
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(`female`)
|
||||
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('south_asian')
|
||||
await expect(dbInfo.profile.pref_gender).toContain('male')
|
||||
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)
|
||||
await expect(dbInfo.profile.pref_relation_styles).toContain(
|
||||
`${testAccount.connection_type}`.toLowerCase(),
|
||||
)
|
||||
await expect(dbInfo.profile.relationship_status).toContain(`open`)
|
||||
await expect(dbInfo.profile.pref_romantic_styles).toContain(`open`)
|
||||
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.education_level).toContain(
|
||||
`${testAccount.education_level}`.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.political_beliefs).toContain('green')
|
||||
await expect(dbInfo.profile.political_details).toContain(
|
||||
testAccount.beliefs?.political?.details,
|
||||
)
|
||||
await expect(dbInfo.profile.religion).toContain('shinto')
|
||||
await expect(dbInfo.profile.religious_beliefs).toContain(
|
||||
testAccount.beliefs?.religious?.details,
|
||||
)
|
||||
await expect(dbInfo.profile.mbti).toContain(`${testAccount.personality_type}`.toLowerCase())
|
||||
await expect(dbInfo.profile.big5_openness).toEqual(
|
||||
testAccount.big_five_personality_traits?.openness,
|
||||
)
|
||||
await expect(dbInfo.profile.diet).toContain(`${testAccount.diet}`.toLowerCase())
|
||||
await expect(dbInfo.profile.is_smoker).toEqual(testAccount.is_smoker)
|
||||
await expect(dbInfo.profile.languages).toHaveLength(2)
|
||||
await expect(dbInfo.profile.languages).toEqual(
|
||||
expect.arrayContaining(testAccount.languages?.map((l) => l.toLowerCase()) ?? []),
|
||||
)
|
||||
await expect(String(dbInfo.profile.drinks_per_month)).toEqual(
|
||||
testAccount.alcohol_consumed_per_month,
|
||||
)
|
||||
})
|
||||
|
||||
test('should successfully skip the onboarding flow', async ({
|
||||
@@ -116,6 +171,9 @@ test.describe('when given valid input', () => {
|
||||
profilePage,
|
||||
fakerAccount,
|
||||
}) => {
|
||||
console.log(
|
||||
`Starting "should successfully skip the onboarding flow" with ${fakerAccount.username}`,
|
||||
)
|
||||
await homePage.gotToHomePage()
|
||||
await homePage.clickSignUpButton()
|
||||
await authPage.fillEmailField(fakerAccount.email)
|
||||
@@ -126,9 +184,76 @@ test.describe('when given valid input', () => {
|
||||
await signUpPage.fillUsername(fakerAccount.username)
|
||||
await signUpPage.clickNextButton()
|
||||
await signUpPage.clickNextButton() //Skip optional information
|
||||
// TODO: fix below
|
||||
// await profilePage.clickCloseButton();
|
||||
// await onboardingPage.clickRefineProfileButton();
|
||||
await profilePage.clickCloseButton()
|
||||
await onboardingPage.clickRefineProfileButton()
|
||||
|
||||
const dbInfo = await userInformationFromDb(fakerAccount)
|
||||
|
||||
await expect(dbInfo.user.name).toContain(fakerAccount.display_name)
|
||||
await expect(dbInfo.user.username).toContain(fakerAccount.username)
|
||||
})
|
||||
|
||||
test.describe('should successfully complete the onboarding flow after using the back button', () => {
|
||||
test.beforeEach(async ({homePage, authPage, fakerAccount}) => {
|
||||
console.log(`Before each with ${fakerAccount.username}`)
|
||||
await homePage.gotToHomePage()
|
||||
await homePage.clickSignUpButton()
|
||||
await authPage.fillEmailField(fakerAccount.email)
|
||||
await authPage.fillPasswordField(fakerAccount.password)
|
||||
await authPage.clickSignUpWithEmailButton()
|
||||
})
|
||||
|
||||
test('the first time its an option', async ({
|
||||
onboardingPage,
|
||||
signUpPage,
|
||||
profilePage,
|
||||
fakerAccount,
|
||||
}) => {
|
||||
console.log(`Starting "the first time its an option" with ${fakerAccount.username}`)
|
||||
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 bio
|
||||
await signUpPage.clickNextButton() //Skip optional information
|
||||
await profilePage.clickCloseButton()
|
||||
await onboardingPage.clickRefineProfileButton()
|
||||
|
||||
const dbInfo = await userInformationFromDb(fakerAccount)
|
||||
|
||||
await expect(dbInfo.user.name).toContain(fakerAccount.display_name)
|
||||
await expect(dbInfo.user.username).toContain(fakerAccount.username)
|
||||
})
|
||||
|
||||
test('the second time its an option', async ({
|
||||
onboardingPage,
|
||||
signUpPage,
|
||||
profilePage,
|
||||
fakerAccount,
|
||||
}) => {
|
||||
console.log(`Starting "the second time its an option" with ${fakerAccount.username}`)
|
||||
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 bio
|
||||
await signUpPage.clickNextButton() //Skip optional information
|
||||
await profilePage.clickCloseButton()
|
||||
await onboardingPage.clickRefineProfileButton()
|
||||
|
||||
const dbInfo = await userInformationFromDb(fakerAccount)
|
||||
|
||||
await expect(dbInfo.user.name).toContain(fakerAccount.display_name)
|
||||
await expect(dbInfo.user.username).toContain(fakerAccount.username)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
import {faker} from '@faker-js/faker'
|
||||
import {
|
||||
ConnectionTypeKey,
|
||||
DietKey,
|
||||
EducationKey,
|
||||
EthnicityKey,
|
||||
LanguageKey,
|
||||
PersonalityKey,
|
||||
PoliticalBeliefsKey,
|
||||
RelationshipStatusKey,
|
||||
RelationshipStyleKey,
|
||||
ReligionKey,
|
||||
} from 'common/choices'
|
||||
|
||||
import {
|
||||
Causes,
|
||||
ChildrenExpectation,
|
||||
ConnectionType,
|
||||
Diet,
|
||||
Education,
|
||||
Ethnicity,
|
||||
Gender,
|
||||
InterestedIn,
|
||||
Interests,
|
||||
Language,
|
||||
Personality,
|
||||
Platforms,
|
||||
PoliticalBeliefs,
|
||||
RelationshipStatus,
|
||||
RelationshipStyle,
|
||||
Religion,
|
||||
} from '../pages/signUpPage'
|
||||
|
||||
export type OnboardingUser = {
|
||||
@@ -28,28 +30,28 @@ export type OnboardingUser = {
|
||||
gender?: Gender
|
||||
age?: string
|
||||
height?: Height
|
||||
ethnicity_origin?: Ethnicity
|
||||
ethnicity_origin?: EthnicityKey
|
||||
interested_in?: InterestedIn
|
||||
Interested_in_ages?: InterestedInAges
|
||||
connection_type?: ConnectionType
|
||||
relationship_status?: RelationshipStatus
|
||||
relationship_style?: RelationshipStyle
|
||||
connection_type?: ConnectionTypeKey
|
||||
relationship_status?: RelationshipStatusKey
|
||||
relationship_style?: RelationshipStyleKey
|
||||
number_of_kids?: string
|
||||
children_expectation?: ChildrenExpectation
|
||||
interests?: (Interests | string)[]
|
||||
causes?: (Causes | string)[]
|
||||
education_level?: Education
|
||||
education_level?: EducationKey
|
||||
university?: string
|
||||
job_title?: string
|
||||
company?: string
|
||||
work_area?: string[]
|
||||
beliefs?: BeliefDetails
|
||||
personality_type?: Personality
|
||||
personality_type?: PersonalityKey
|
||||
big_five_personality_traits?: FiveBigPersonalityTraits
|
||||
diet?: Diet
|
||||
diet?: DietKey
|
||||
is_smoker?: boolean
|
||||
alcohol_consumed_per_month?: string
|
||||
languages?: Language[]
|
||||
languages?: LanguageKey[]
|
||||
social_media?: Socials[]
|
||||
}
|
||||
|
||||
@@ -66,11 +68,11 @@ type InterestedInAges = {
|
||||
|
||||
type BeliefDetails = {
|
||||
political?: {
|
||||
belief?: PoliticalBeliefs
|
||||
belief?: PoliticalBeliefsKey
|
||||
details?: string
|
||||
}
|
||||
religious?: {
|
||||
belief?: Religion
|
||||
belief?: ReligionKey
|
||||
details?: string
|
||||
}
|
||||
}
|
||||
@@ -95,68 +97,74 @@ type OnboardingConfig = {
|
||||
|
||||
export const onboarding: OnboardingConfig = {
|
||||
// Use a function so email is unique per test call
|
||||
faker_account: () => ({
|
||||
email: `faker+${crypto.randomUUID()}@test.com`,
|
||||
password: faker.internet.password(),
|
||||
display_name: faker.internet.displayName(),
|
||||
username: `user_${crypto.randomUUID().slice(0, 8)}`,
|
||||
}),
|
||||
faker_account: () => {
|
||||
const id = crypto.randomUUID().slice(0, 6)
|
||||
return {
|
||||
email: `faker+${id}@test.com`,
|
||||
password: faker.internet.password(),
|
||||
display_name: faker.internet.displayName(),
|
||||
username: `user_${id}`,
|
||||
}
|
||||
},
|
||||
|
||||
account_one: () => ({
|
||||
// Use a non-real TLD like @test.compass to make it obvious these are test accounts and prevent accidental emails
|
||||
email: `onboarding+${crypto.randomUUID()}@test.compass`,
|
||||
password: 'CompassTest',
|
||||
display_name: 'Compass Onboarding',
|
||||
username: `TheGreatOnboarding_${crypto.randomUUID().slice(0, 8)}`,
|
||||
bio: 'Born beneath twin moons, this wanderer maps forgotten roads, trades riddles for shelter, and keeps stories in glass bottles. Drawn to ancient libraries and glowing forests, they seek lost spells, quiet taverns, and adventures that rewrite fate. Their compass points to wonder. Ever onward. Always. Go',
|
||||
gender: 'Woman',
|
||||
age: '25',
|
||||
height: {
|
||||
feet: '6',
|
||||
inches: '0',
|
||||
centimeters: '182.88',
|
||||
},
|
||||
ethnicity_origin: 'South/Southeast Asian',
|
||||
interested_in: 'Men',
|
||||
Interested_in_ages: {
|
||||
min: '20',
|
||||
max: '30',
|
||||
},
|
||||
connection_type: 'Relationship',
|
||||
relationship_status: 'In open relationship',
|
||||
relationship_style: 'Open Relationship',
|
||||
number_of_kids: '2',
|
||||
children_expectation: 'Neutral',
|
||||
interests: ['Chess', 'Eating'],
|
||||
causes: ['Animal Rights', 'Free Spotify'],
|
||||
education_level: 'Bachelors',
|
||||
university: 'Open-Source University',
|
||||
job_title: 'Unemployed',
|
||||
company: 'Home',
|
||||
work_area: ['Living Room', 'University'],
|
||||
beliefs: {
|
||||
political: {
|
||||
belief: 'Green / Eco-Socialist',
|
||||
details: 'This will be details',
|
||||
account_one: () => {
|
||||
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`,
|
||||
password: 'CompassTest',
|
||||
display_name: 'Compass Onboarding',
|
||||
username: `TheGreatOnboarding_${id}`, // username max length is 25 (see /create-user)
|
||||
bio: 'Born beneath twin moons, this wanderer maps forgotten roads, trades riddles for shelter, and keeps stories in glass bottles. Drawn to ancient libraries and glowing forests, they seek lost spells, quiet taverns, and adventures that rewrite fate. Their compass points to wonder. Ever onward. Always. Go',
|
||||
gender: 'Woman',
|
||||
age: '25',
|
||||
height: {
|
||||
feet: '6',
|
||||
inches: '0',
|
||||
centimeters: '182.88',
|
||||
},
|
||||
religious: {
|
||||
belief: 'Shinto',
|
||||
details: 'This will be details',
|
||||
ethnicity_origin: 'South/Southeast Asian',
|
||||
interested_in: 'Men',
|
||||
Interested_in_ages: {
|
||||
min: '20',
|
||||
max: '30',
|
||||
},
|
||||
},
|
||||
personality_type: 'ENFJ',
|
||||
big_five_personality_traits: {
|
||||
openness: 43,
|
||||
},
|
||||
diet: 'Omnivore',
|
||||
is_smoker: false,
|
||||
alcohol_consumed_per_month: '4',
|
||||
languages: ['Akan', 'Cebuano'],
|
||||
social_media: [
|
||||
{
|
||||
platform: 'Bluesky',
|
||||
urlOrUsername: 'TheGreatConnection',
|
||||
connection_type: 'Relationship',
|
||||
relationship_status: 'In open relationship',
|
||||
relationship_style: 'Open Relationship',
|
||||
number_of_kids: '2',
|
||||
children_expectation: ['Neutral', 2],
|
||||
interests: ['Chess', 'Eating'],
|
||||
causes: ['Animal Rights', 'Free Spotify'],
|
||||
education_level: 'Bachelors',
|
||||
university: 'Open-Source University',
|
||||
job_title: 'Unemployed',
|
||||
company: 'Home',
|
||||
work_area: ['Engineering', 'Academia'],
|
||||
beliefs: {
|
||||
political: {
|
||||
belief: 'Green / Eco-Socialist',
|
||||
details: 'This will be details',
|
||||
},
|
||||
religious: {
|
||||
belief: 'Shinto',
|
||||
details: 'This will be details',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
personality_type: 'ENFJ',
|
||||
big_five_personality_traits: {
|
||||
openness: 43,
|
||||
},
|
||||
diet: 'Omnivore',
|
||||
is_smoker: false,
|
||||
alcohol_consumed_per_month: '4',
|
||||
languages: ['Akan', 'Cebuano'],
|
||||
social_media: [
|
||||
{
|
||||
platform: 'Bluesky',
|
||||
urlOrUsername: 'TheGreatConnection',
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,24 +1,11 @@
|
||||
import axios from 'axios'
|
||||
import {createSupabaseDirectClient} from 'shared/supabase/init'
|
||||
|
||||
import {config} from '../SPEC_CONFIG'
|
||||
import {deleteFromDb} from '../../utils/databaseUtils'
|
||||
import {deleteAccount, login} from '../../utils/firebaseUtils'
|
||||
|
||||
export async function deleteUser(email: string, password: string) {
|
||||
try {
|
||||
const login = await axios.post(
|
||||
`${config.FIREBASE_URL.BASE}${config.FIREBASE_URL.SIGN_IN_PASSWORD}`,
|
||||
{
|
||||
email,
|
||||
password,
|
||||
returnSecureToken: true,
|
||||
},
|
||||
)
|
||||
|
||||
await deleteFromDb(login.data.localId)
|
||||
|
||||
await axios.post(`${config.FIREBASE_URL.BASE}${config.FIREBASE_URL.DELETE}`, {
|
||||
idToken: login.data.idToken,
|
||||
})
|
||||
const loginInfo = await login(email, password)
|
||||
await deleteFromDb(loginInfo.data.localId)
|
||||
await deleteAccount(loginInfo)
|
||||
} catch (err: any) {
|
||||
// Skip deletion if user doesn't exist or other auth errors occur
|
||||
if (
|
||||
@@ -31,19 +18,3 @@ export async function deleteUser(email: string, password: string) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteFromDb(user_id: string) {
|
||||
const db = createSupabaseDirectClient()
|
||||
try {
|
||||
const deleteEntryById = `DELETE FROM users WHERE id = $1 RETURNING *`
|
||||
const result = await db.query(deleteEntryById, [user_id])
|
||||
console.log('Deleted data: ', {
|
||||
id: result[0].id,
|
||||
name: result[0].name,
|
||||
username: result[0].username,
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Failed to delete user data, all changes rolled back: ', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import {useStateCheckEquality} from 'web/hooks/use-state-check-equality'
|
||||
import {useWebsocketPrivateUser, useWebsocketUser} from 'web/hooks/use-user'
|
||||
import {api} from 'web/lib/api'
|
||||
import {auth} from 'web/lib/firebase/users'
|
||||
import {useLocale} from 'web/lib/locale'
|
||||
import {getLocale} from 'web/lib/locale-cookie'
|
||||
import {identifyUser, setUserProperty} from 'web/lib/service/analytics'
|
||||
import {getPrivateUserSafe, getUserSafe} from 'web/lib/supabase/users'
|
||||
@@ -118,8 +117,6 @@ export function AuthProvider(props: {children: ReactNode; serverUser?: AuthUser}
|
||||
)
|
||||
const [authLoaded, setAuthLoaded] = useState(false)
|
||||
const firebaseUser = useAndSetupFirebaseUser()
|
||||
const {locale} = useLocale()
|
||||
console.log('AuthProvider hook locale', locale)
|
||||
|
||||
const authUser = !user
|
||||
? user
|
||||
|
||||
@@ -30,9 +30,9 @@ export function BioBlock(props: {
|
||||
!edit && 'px-3 py-2',
|
||||
)}
|
||||
>
|
||||
<Row className="w-full" data-testid="profile-bio">
|
||||
<Row className="w-full">
|
||||
{!edit && profile.bio && (
|
||||
<Col className="flex w-full flex-grow">
|
||||
<Col className="flex w-full flex-grow" data-testid="profile-bio">
|
||||
<Content className="w-full" content={profile.bio as JSONContent} />
|
||||
</Col>
|
||||
)}
|
||||
|
||||
@@ -92,7 +92,7 @@ export const RequiredProfileUserForm = (props: {
|
||||
<div className="mb-6 text-lg">
|
||||
{t(
|
||||
'profile.required.username_locked_warning',
|
||||
'You cannot change your username after creating a profile, but you can update you name later in your profile settings.',
|
||||
'You cannot change your username after creating a profile, but you can update your name later in your profile settings.',
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -9,12 +9,20 @@ export function initSupabaseClient() {
|
||||
const anonKeyOverride = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || process.env.SUPABASE_ANON_KEY
|
||||
|
||||
if (urlOverride && anonKeyOverride) {
|
||||
console.log('Initializing Supabase client (env URL override)')
|
||||
console.log('Initializing Supabase client (env URL override)', {urlOverride, anonKeyOverride})
|
||||
return createClient(urlOverride, anonKeyOverride)
|
||||
} else if (process.env.NEXT_PUBLIC_ISOLATED_ENV) {
|
||||
throw new Error(
|
||||
`You are running isolated tests (NEXT_PUBLIC_ISOLATED_ENV=true), so you do not want to call the remote supabase. ${{
|
||||
urlOverride,
|
||||
anonKeyOverride,
|
||||
}}`,
|
||||
)
|
||||
}
|
||||
|
||||
if (urlOverride || anonKeyOverride) {
|
||||
console.warn(
|
||||
'Supabase env override is partially set. Both URL and ANON_KEY are required. Falling back to ENV_CONFIG.'
|
||||
'Supabase env override is partially set. Both URL and ANON_KEY are required. Falling back to ENV_CONFIG.',
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -168,12 +168,19 @@ export default function UserPage(props: UserPageProps) {
|
||||
const [fetchedProps, setFetchedProps] = useState(props)
|
||||
const [loading, setLoading] = useState(nativeMobile)
|
||||
|
||||
console.log('UserPage state:', {
|
||||
username,
|
||||
fetchedProps,
|
||||
loading,
|
||||
nativeMobile,
|
||||
})
|
||||
console.log(
|
||||
'UserPage state:',
|
||||
JSON.stringify(
|
||||
{
|
||||
username,
|
||||
fetchedProps,
|
||||
loading,
|
||||
nativeMobile,
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (nativeMobile) {
|
||||
|
||||
@@ -94,7 +94,7 @@ function MyApp(props: AppProps<PageProps>) {
|
||||
const router = useRouter()
|
||||
|
||||
const [locale, setLocaleState] = useState<string>(getLocale())
|
||||
console.log('_app locale', locale)
|
||||
// console.log('_app locale', locale)
|
||||
const setLocale = (newLocale: string) => {
|
||||
console.log('setLocale', newLocale)
|
||||
document.cookie = `lang=${newLocale}; path=/; max-age=31536000`
|
||||
|
||||
Reference in New Issue
Block a user