From 6a4c4ba3973507337efa543546c5a659eea1fd64 Mon Sep 17 00:00:00 2001 From: Jessica Ho Date: Sat, 24 Feb 2024 08:05:58 +0000 Subject: [PATCH] SeedUtils --- playwright.config.ts | 2 +- prisma/seed.ts | 49 ++--- prisma/utils.ts | 451 +++++++++++++++++++++------------------- src/hooks.server.ts | 7 +- src/routes/+page.svelte | 2 +- tests/db.spec.ts | 10 +- tests/profile.spec.ts | 61 +++--- tests/twilio.spec.ts | 15 +- 8 files changed, 298 insertions(+), 299 deletions(-) diff --git a/playwright.config.ts b/playwright.config.ts index daa0b30..44927e0 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -16,7 +16,7 @@ const config: PlaywrightTestConfig = { expect: { timeout: 3000 }, - timeout: 5000, + // timeout: 10000, testDir: 'tests' }; diff --git a/prisma/seed.ts b/prisma/seed.ts index 1db487a..4185fec 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,41 +1,22 @@ import { PrismaClient } from '@prisma/client'; -import { - createActiveSession, - createExpiredLink, - createFriendRequest, - createHouseholdConnection, - createHouseholdInvite, - createUserWithEmptyHousehold, - createUserWithKid, - createUserWithNothing, - deleteAllFriendRequests -} from './utils'; +import SeedUtils from './utils'; -export const prisma = new PrismaClient(); +const prisma = new PrismaClient(); async function main() { - const now = new Date(); - const expires = new Date(); - expires.setHours(expires.getHours() + 1); - - await deleteAllFriendRequests(); - - await createExpiredLink(1); - - await Promise.all([1, 2].map(async (userInd) => await createUserWithNothing(now, userInd))); - await Promise.all( - [3, 4].map(async (userInd) => await createUserWithEmptyHousehold(now, userInd)) - ); - await Promise.all([2, 4, 6].map(async (userInd) => await createActiveSession(now, userInd))); - - await createUserWithEmptyHousehold(now, 5); - await createUserWithKid(now, 6); - - await createFriendRequest(4, 3); - - await createHouseholdConnection(3, 5); - - await createHouseholdInvite(5, 2); + const utils = new SeedUtils(new Date(), prisma); + await Promise.all([ + utils.deleteAllFriendRequests(), + utils.createExpiredLink(1), + ...[1, 2].map((userInd) => utils.createUserWithNothing(userInd)), + ...[3, 4].map((userInd) => utils.createUserWithEmptyHousehold(userInd)), + ...[2, 4, 6].map((userInd) => utils.createActiveSession(userInd)), + utils.createUserWithEmptyHousehold(5), + utils.createUserWithKid(6), + utils.createFriendRequest(4, 3), + utils.createHouseholdConnection(3, 5), + utils.createHouseholdInvite(5, 2) + ]); } export async function run() { diff --git a/prisma/utils.ts b/prisma/utils.ts index 5ea4805..8bfdf41 100644 --- a/prisma/utils.ts +++ b/prisma/utils.ts @@ -1,226 +1,243 @@ -import { Pronoun } from '@prisma/client'; -import { prisma } from './seed'; -import { PHONES } from './constants'; - -function permsYes(phone: string, now: Date) { - return { - phonePermissions: { - connectOrCreate: { - where: { - phone - }, - create: { - phone, - blocked: false, - allowInvites: true, - allowReminders: true, - acceptedTermsAt: now +import { PrismaClient, Pronoun } from '@prisma/client'; + +export default class SeedUtils { + #now: Date; + #prisma: PrismaClient; + PHONES = [ + '+12015550121', + '+12015550122', + '+12015550123', + '+12015550124', + '+12015550125', + '+12015550126' + ]; + + constructor(now: Date, prisma: PrismaClient) { + this.#now = now; + this.#prisma = prisma + } + + permsYes(phone: string) { + return { + phonePermissions: { + connectOrCreate: { + where: { + phone + }, + create: { + phone, + blocked: false, + allowInvites: true, + allowReminders: true, + acceptedTermsAt: this.#now + } } } - } - }; -} - -function emptyHousehold(ind: number) { - return { - household: { - connectOrCreate: { - where: { - id: ind - }, - create: { - // phone: phones[ind - 1], - id: ind, - name: `Household ${ind}` + }; + } + + emptyHousehold(ind: number) { + return { + household: { + connectOrCreate: { + where: { + id: ind + }, + create: { + // phone: phones[ind - 1], + id: ind, + name: `Household ${ind}` + } } } - } - }; -} - -function householdWithKid(ind: number, kidInd: number) { - return { - household: { - connectOrCreate: { - where: { - id: ind - }, - create: { - id: ind, - name: `Household ${ind}`, - children: { - connectOrCreate: [ - { - where: { - id: kidInd - }, - create: { - firstName: `User ${ind} Kid ${kidInd}`, - pronouns: Pronoun['HE_HIM_HIS'] + }; + } + + householdWithKid(ind: number, kidInd: number) { + return { + household: { + connectOrCreate: { + where: { + id: ind + }, + create: { + id: ind, + name: `Household ${ind}`, + children: { + connectOrCreate: [ + { + where: { + id: kidInd + }, + create: { + firstName: `User ${ind} Kid ${kidInd}`, + pronouns: Pronoun['HE_HIM_HIS'] + } } - } - ] + ] + } } } } - } - }; -} - -function basicUser(id: number) { - return { - firstName: `User ${id}`, - locale: 'English', - pronouns: Pronoun['SHE_HER_HERS'], - timeZone: 'America/Los_Angeles', - reminderDatetime: new Date(), - reminderIntervalDays: 7, - acceptedTermsAt: new Date() - }; -} - -export async function deleteAllFriendRequests() { - await prisma.friendRequest - .deleteMany() - .catch(() => console.log('No friend request table to delete')); -} - -export async function createExpiredLink(userInd: number) { - const expiredLink = { - token: '3e99472f1003794c', - phone: PHONES[userInd - 1], - expires: new Date('8/5/2020') - }; - await prisma.magicLink.upsert({ - where: { - id: userInd - }, - update: expiredLink, - create: expiredLink - }); -} - -export async function createUserWithNothing(now: Date, userInd: number) { - const phone = PHONES[userInd - 1]; - - await prisma.user.upsert({ - where: { - phone - }, - update: basicUser(userInd), - create: { - ...basicUser(userInd), - ...permsYes(phone, now) - } - }); -} - -export async function createActiveSession(now: Date, userInd: number) { - const phone = PHONES[userInd - 1]; - - const expires = new Date(now); - expires.setHours(expires.getHours() + 1); - - const userSessionToken = `user${userInd}session`; - const session = { - token: userSessionToken, - phone, - expires: now - }; - await prisma.session.upsert({ - where: { - token: userSessionToken - }, - update: session, - create: session - }); -} - -export async function createUserWithEmptyHousehold(now: Date, userInd: number) { - const phone = PHONES[userInd - 1]; - const user = { - ...basicUser(userInd), - ...emptyHousehold(userInd) - }; - - await prisma.user.upsert({ - where: { - phone - }, - update: user, - create: { - ...user, - ...permsYes(phone, now) - } - }); -} - -export async function createFriendRequest(fromUserInd: number, toUserInd: number) { - const friendReq = { - id: toUserInd, - targetPhone: PHONES[toUserInd - 1], - fromHouseholdId: fromUserInd, - fromUserId: fromUserInd - }; - - await prisma.friendRequest.upsert({ - where: { - id: toUserInd - }, - update: friendReq, - create: friendReq - }); -} - -export async function createHouseholdConnection(hId1: number, hId2: number) { - const householdConnection = { - id: hId1, - householdId: hId1, - friendHouseholdId: hId2 - }; - await prisma.householdConnection.upsert({ - where: { - id: hId1 - }, - update: householdConnection, - create: householdConnection - }); -} - -export async function createHouseholdInvite(fromUserInd: number, toUserInd: number) { - // household invite from User 5 to User 2 - const householdInvite = { - id: toUserInd, - targetPhone: PHONES[toUserInd - 1], - householdId: fromUserInd, - fromUserId: fromUserInd - }; - - await prisma.joinHouseholdRequest.upsert({ - where: { - id: toUserInd - }, - update: householdInvite, - create: householdInvite - }); -} - -export async function createUserWithKid(now: Date, userInd: number) { - const user = { - ...basicUser(userInd), - ...householdWithKid(userInd, 1) - }; - - const phone = PHONES[userInd - 1]; - - await prisma.user.upsert({ - where: { - phone - }, - update: user, - create: { - ...user, - ...permsYes(phone, now) - } - }); + }; + } + + basicUser(id: number) { + return { + firstName: `User ${id}`, + locale: 'English', + pronouns: Pronoun['SHE_HER_HERS'], + timeZone: 'America/Los_Angeles', + reminderDatetime: new Date(), + reminderIntervalDays: 7, + acceptedTermsAt: new Date() + }; + } + + async deleteAllFriendRequests() { + await this.#prisma.friendRequest + .deleteMany() + .catch(() => console.log('No friend request table to delete')); + } + + async createExpiredLink(userInd: number) { + const expiredLink = { + token: '3e99472f1003794c', + phone: this.PHONES[userInd - 1], + expires: new Date('8/5/2020') + }; + await this.#prisma.magicLink.upsert({ + where: { + id: userInd + }, + update: expiredLink, + create: expiredLink + }); + } + + async createUserWithNothing(userInd: number) { + const phone = this.PHONES[userInd - 1]; + + await this.#prisma.user.upsert({ + where: { + phone + }, + update: this.basicUser(userInd), + create: { + ...this.basicUser(userInd), + ...this.permsYes(phone) + } + }); + } + + async createActiveSession(userInd: number) { + const phone = this.PHONES[userInd - 1]; + + const expires = new Date(this.#now); + expires.setHours(expires.getHours() + 1); + + const userSessionToken = `user${userInd}session`; + const session = { + token: userSessionToken, + phone, + expires + }; + await this.#prisma.session.upsert({ + where: { + token: userSessionToken + }, + update: session, + create: session + }); + } + + async createUserWithEmptyHousehold(userInd: number) { + const phone = this.PHONES[userInd - 1]; + const user = { + ...this.basicUser(userInd), + ...this.emptyHousehold(userInd) + }; + + await this.#prisma.user.upsert({ + where: { + phone + }, + update: user, + create: { + ...user, + ...this.permsYes(phone) + } + }); + } + + async createFriendRequest(fromUserInd: number, toUserInd: number) { + const friendReq = { + id: toUserInd, + targetPhone: this.PHONES[toUserInd - 1], + fromHouseholdId: fromUserInd, + fromUserId: fromUserInd + }; + + await this.#prisma.friendRequest.upsert({ + where: { + id: toUserInd + }, + update: friendReq, + create: friendReq + }); + } + + async createHouseholdConnection(hId1: number, hId2: number) { + const householdConnection = { + id: hId1, + householdId: hId1, + friendHouseholdId: hId2 + }; + await this.#prisma.householdConnection.upsert({ + where: { + id: hId1 + }, + update: householdConnection, + create: householdConnection + }); + } + + async createHouseholdInvite(fromUserInd: number, toUserInd: number) { + // household invite from User 5 to User 2 + const householdInvite = { + id: toUserInd, + targetPhone: this.PHONES[toUserInd - 1], + householdId: fromUserInd, + fromUserId: fromUserInd + }; + + await this.#prisma.joinHouseholdRequest.upsert({ + where: { + id: toUserInd + }, + update: householdInvite, + create: householdInvite + }); + } + + async createUserWithKid(userInd: number) { + const user = { + ...this.basicUser(userInd), + ...this.householdWithKid(userInd, 1) + }; + + const phone = this.PHONES[userInd - 1]; + + await this.#prisma.user.upsert({ + where: { + phone + }, + update: user, + create: { + ...user, + ...this.permsYes(phone) + } + }); + } + } diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 671c7b8..3a418af 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -5,7 +5,7 @@ import { toLocalTimezone } from '$lib/logics/_shared/date'; import prisma from '$lib/logics/_shared/prisma'; import type { UserWithPermissions } from '$lib/logics/_shared/types'; -import { redirect } from '@sveltejs/kit'; +import { error, redirect } from '@sveltejs/kit'; import type { MaybePromise, ResolveOptions } from '@sveltejs/kit/types/internal'; if (import.meta.env.PROD) { @@ -89,7 +89,10 @@ const redirectOrContinue = ( ) => MaybePromise ) => { console.log('REDIRECT OR CONT', event.url.pathname, path); - if (event.url.pathname !== path) throw redirect(308, path); + if (event.url.pathname !== path) { + if (event.url.pathname === '/twilio') throw error(403); + throw redirect(308, path); + } return resolve(event); }; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index d5cd082..218de25 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -47,7 +47,7 @@ }); if (res.status === 200) { const { token } = await res.json(); - if (public_env.PUBLIC_ENV === 'test') console.log('PHONE_TOKEN', phone, token); + if (public_env.PUBLIC_ENV === 'test') console.log('TOKEN', token); const region = new Intl.DateTimeFormat(); const { timeZone } = region.resolvedOptions(); diff --git a/tests/db.spec.ts b/tests/db.spec.ts index d67cc71..89a65f2 100644 --- a/tests/db.spec.ts +++ b/tests/db.spec.ts @@ -36,7 +36,7 @@ that info is derived from the session cookie */ test("User 4 fails to accept friend request on User 3's behalf", async ({ page, context }) => { - context.addCookies([ + await context.addCookies([ { name: 'session', value: 'user4session', @@ -60,7 +60,7 @@ test("User 4 fails to accept friend request on User 3's behalf", async ({ page, }); test("User 4 fails to decline friend request on User 3's behalf", async ({ page, context }) => { - context.addCookies([ + await context.addCookies([ { name: 'session', value: 'user4session', @@ -84,7 +84,7 @@ test("User 4 fails to decline friend request on User 3's behalf", async ({ page, }); test("User 4 fails to delete friend on User 3's behalf", async ({ page, context }) => { - context.addCookies([ + await context.addCookies([ { name: 'session', value: 'user4session', @@ -108,7 +108,7 @@ test("User 4 fails to delete friend on User 3's behalf", async ({ page, context }); test("User 4 fails to accept household invite on User 2's behalf", async ({ page, context }) => { - context.addCookies([ + await context.addCookies([ { name: 'session', value: 'user4session', @@ -132,7 +132,7 @@ test("User 4 fails to accept household invite on User 2's behalf", async ({ page }); test("User 4 fails to decline household invite on User 2's behalf", async ({ page, context }) => { - context.addCookies([ + await context.addCookies([ { name: 'session', value: 'user4session', diff --git a/tests/profile.spec.ts b/tests/profile.spec.ts index 39cd36a..46fdd6c 100644 --- a/tests/profile.spec.ts +++ b/tests/profile.spec.ts @@ -1,4 +1,4 @@ -import { test, expect } from '@playwright/test'; +import { test, expect, type ConsoleMessage } from '@playwright/test'; import { run } from '../prisma/seed'; // const url = 'http://localhost:5173/profile'; @@ -8,36 +8,33 @@ test.beforeEach(async () => { await run(); }); -test.only("User can create new profile with valid phone number", async ({ page, context }) => { - await page.goto('http://localhost:5173'); +test.skip('User can create new profile with valid phone number', async ({ page, context }) => { + await page.goto('http://localhost:5173'); - await page.waitForTimeout(3000); - await page.getByRole('textbox').fill('2016660127'); - await page.getByRole('button').click(); + await page.waitForTimeout(3000); + await page.getByRole('textbox').fill('2016660127'); + await page.getByRole('button').click(); - let token: string, phone: string; - page.on('dialog', async (dialog) => { - const thing = dialog.message().split(' '); - phone = thing[0]; - token = thing[1]; - dialog.accept(); - }); - page.on('console', async (msg) => { - const first = await msg.args()[0]?.jsonValue(); - if (first === 'PHONE_TOKEN') { - phone = await msg.args()[1].jsonValue(); - token = await msg.args()[2].jsonValue(); - } - }); - await new Promise((resolve) => { - let intervalId = setInterval(() => { - if (phone && token) { - clearInterval(intervalId); - resolve(); - } - }, 100); - }); - await page.goto(`http://localhost:5173/login/${phone!}/${token!}`); - await page.mainFrame().waitForLoadState(); - await expect(page).toHaveURL(host + '/profile'); -}) + let token: string; + const retrieveTokenFromServerLog = async (msg: ConsoleMessage) => { + const first = await msg.args()[0]?.jsonValue(); + if (first === 'TOKEN') { + token = await msg.args()[1].jsonValue(); + } + }; + page.on('console', retrieveTokenFromServerLog); + + await new Promise((resolve) => { + let intervalId = setInterval(() => { + if (token) { + console.log({ token }); + page.off('console', retrieveTokenFromServerLog); + clearInterval(intervalId); + resolve(); + } + }, 100); + }); + await page.goto(`http://localhost:5173/login/${token!}`); + await page.waitForURL(`${host}/profile`); + console.log('completed'); +}); diff --git a/tests/twilio.spec.ts b/tests/twilio.spec.ts index 11e0ce4..cbfb704 100644 --- a/tests/twilio.spec.ts +++ b/tests/twilio.spec.ts @@ -34,7 +34,7 @@ test("User can't send circleNotif msg without session cookie", async ({ page, co }); test("User 2 can't send circleNotif msg (no household)", async ({ page, context }) => { - context.addCookies([ + await context.addCookies([ { name: 'session', value: 'user2session', @@ -44,7 +44,8 @@ test("User 2 can't send circleNotif msg (no household)", async ({ page, context const res = await context.request.fetch(host + '/twilio', { method: 'post', headers: { - 'Content-Type': 'application/json' + 'Content-Type': 'application/json', + 'Accept': 'application/json' }, data: { phone: '+1xxxxxxxxxx', @@ -53,13 +54,13 @@ test("User 2 can't send circleNotif msg (no household)", async ({ page, context diff: true } }); - // endpoint itself has a check for this but gonna get stopped by hooks routing even before raeching that point - expect(res.status()).not.toEqual(200); + // endpoint itself has a check for this but gonna get stopped by hooks routing even before reaching that point + expect(res.status()).toEqual(403); await page.close(); }); test("User 6 can't send circleNotif msg to nonexistent user", async ({ page, context }) => { - context.addCookies([ + await context.addCookies([ { name: 'session', value: 'user6session', @@ -86,7 +87,7 @@ test("User 6 can't send circleNotif msg to nonexistent user", async ({ page, con }); test("User 6 can't send circleNotif msg to user w/ no household", async ({ page, context }) => { - context.addCookies([ + await context.addCookies([ { name: 'session', value: 'user6session', @@ -113,7 +114,7 @@ test("User 6 can't send circleNotif msg to user w/ no household", async ({ page, }); test("User 6 can't send circleNotif msg to user outside of circle", async ({ page, context }) => { - context.addCookies([ + await context.addCookies([ { name: 'session', value: 'user6session',