1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-09 15:35:22 +02:00

rework test to avoid seeding test user

This commit is contained in:
Tyler Myracle 2024-01-21 20:21:11 -06:00
parent 06b861aea7
commit 9ea0ec6b7a
12 changed files with 78 additions and 130 deletions

View file

@ -1,14 +0,0 @@
{
"presets": [
"@babel/preset-typescript",
"@babel/preset-env",
[
"@nrwl/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}

View file

@ -1,18 +0,0 @@
const rootMain = require('../../../.storybook/main')
module.exports = {
...rootMain,
core: { ...rootMain.core, builder: 'webpack5' },
stories: ['../**/*.stories.@(js|jsx|ts|tsx)'],
addons: [...rootMain.addons, '@nrwl/react/plugins/storybook'],
webpackFinal: async (config, { configType }) => {
// apply any global webpack configs that might have been specified in .storybook/main.js
if (rootMain.webpackFinal) {
config = await rootMain.webpackFinal(config, { configType })
}
// add your own webpack tweaks if needed
return config
},
}

View file

@ -1,18 +0,0 @@
import type { Story, Meta } from '@storybook/react'
import Maintenance from './Maintenance.tsx'
import React from 'react'
export default {
title: 'components/Maintenance.tsx',
component: Maintenance,
} as Meta
const Template: Story = () => {
return (
<>
<Maintenance />
</>
)
}
export const Base = Template.bind({})

View file

@ -37,7 +37,7 @@ async function validateCredentials(credentials: any): Promise<z.infer<typeof aut
lastName: z.string().optional(),
email: z.string().email({ message: 'Invalid email address.' }),
password: z.string().min(6),
isAdmin: z.boolean().default(false),
role: z.string().default('user'),
})
const parsed = authSchema.safeParse(credentials)
@ -53,15 +53,26 @@ async function createNewAuthUser(credentials: {
lastName: string
email: string
password: string
isAdmin: boolean
role: string
}): Promise<SharedType.AuthUser> {
const { firstName, lastName, email, password, isAdmin } = credentials
const { firstName, lastName, email, password, role } = credentials
if (!firstName || !lastName) {
throw new Error('Both first name and last name are required.')
}
const isDevelopment = process.env.NODE_ENV === 'development'
let userRole: AuthUserRole
if (role === AuthUserRole.admin && isDevelopment) {
userRole = AuthUserRole.admin
} else if (role === AuthUserRole.ci) {
userRole = AuthUserRole.ci
} else {
userRole = AuthUserRole.user
}
const hashedPassword = await bcrypt.hash(password, 10)
return createAuthUser({
firstName,
@ -69,7 +80,7 @@ async function createNewAuthUser(credentials: {
name: `${firstName} ${lastName}`,
email,
password: hashedPassword,
role: isAdmin && isDevelopment ? AuthUserRole.admin : AuthUserRole.user,
role: userRole,
})
}
@ -99,14 +110,11 @@ export const authOptions = {
lastName: { label: 'Last name', type: 'text', placeholder: 'Last name' },
email: { label: 'Email', type: 'email', placeholder: 'hello@maybe.co' },
password: { label: 'Password', type: 'password' },
isAdmin: { label: 'Admin', type: 'checkbox' },
role: { label: 'Admin', type: 'text' },
},
async authorize(credentials) {
const { firstName, lastName, email, password, isAdmin } = await validateCredentials(
{
...credentials,
isAdmin: Boolean(credentials?.isAdmin),
}
const { firstName, lastName, email, password, role } = await validateCredentials(
credentials
)
const existingUser = await getAuthUserByEmail(email)
@ -123,7 +131,7 @@ export const authOptions = {
throw new Error('Invalid credentials provided.')
}
return createNewAuthUser({ firstName, lastName, email, password, isAdmin })
return createNewAuthUser({ firstName, lastName, email, password, role })
},
}),
],

View file

@ -15,7 +15,7 @@ export default function RegisterPage() {
const [isValid, setIsValid] = useState(false)
const [errorMessage, setErrorMessage] = useState<string | null>(null)
const [isLoading, setIsLoading] = useState(false)
const [isAdmin, setIsAdmin] = useState(false)
const [isAdmin, setIsAdmin] = useState<boolean>(false)
const { data: session } = useSession()
const router = useRouter()
@ -39,7 +39,7 @@ export default function RegisterPage() {
password,
firstName,
lastName,
isAdmin,
role: isAdmin ? 'admin' : 'user',
redirect: false,
})

View file

@ -27,14 +27,7 @@
"next-env.d.ts",
".next/types/**/*.ts"
],
"exclude": [
"node_modules",
"jest.config.ts",
"**/*.stories.ts",
"**/*.stories.js",
"**/*.stories.jsx",
"**/*.stories.tsx"
],
"exclude": ["node_modules", "jest.config.ts"],
"references": [
{
"path": "./.storybook/tsconfig.json"

View file

@ -4,6 +4,7 @@ declare namespace Cypress {
interface Chainable<Subject> {
login(): Chainable<any>
apiRequest(...params: Parameters<typeof cy.request>): Chainable<any>
nextApiRequest(...params: Parameters<typeof cy.request>): Chainable<any>
getByTestId(...parameters: Parameters<typeof cy.get>): Chainable<any>
selectDate(date: Date): Chainable<any>
preserveAccessToken(): Chainable<any>
@ -28,9 +29,22 @@ Cypress.Commands.add('apiRequest', ({ url, headers = {}, ...options }, ...rest)
)
})
Cypress.Commands.add('nextApiRequest', ({ url, headers = {}, ...options }, ...rest) => {
return cy.request(
{
url: `${Cypress.env('NEXTAUTH_URL')}/${url}`,
headers: {
...headers,
},
...options,
},
...rest
)
})
Cypress.Commands.add('login', () => {
cy.visit('/login')
cy.get('input[name="email"]').type('bond@007.com')
cy.get('input[name="email"]').type('test@test.com')
cy.get('input[name="password"]').type('TestPassword123')
cy.get('button[type="submit"]').click()
//eslint-disable-next-line cypress/no-unnecessary-waiting

View file

@ -1,10 +1,36 @@
import './commands'
beforeEach(() => {
// Login
cy.login()
cy.request({
method: 'GET',
url: 'api/auth/csrf',
}).then((response) => {
let csrfCookies = response.headers['set-cookie']
if (Array.isArray(csrfCookies) && csrfCookies.length > 1) {
csrfCookies = csrfCookies.map((cookie) => cookie.split(';')[0]).join('; ')
}
const csrfToken = response.body.csrfToken.trim()
// Delete the current user to wipe all data before test
cy.request({
method: 'POST',
form: true,
headers: {
Cookie: `${csrfCookies}`,
},
url: `api/auth/callback/credentials`,
body: {
email: 'test@test.com',
firstName: 'Test',
lastName: 'User',
password: 'TestPassword123',
role: 'ci',
csrfToken: csrfToken,
json: 'true',
},
}).then((response) => {
expect(response.status).to.equal(200)
})
})
cy.apiRequest({
method: 'POST',
url: 'e2e/reset',
@ -12,7 +38,5 @@ beforeEach(() => {
}).then((response) => {
expect(response.status).to.equal(200)
})
// Go back to dashboard
cy.visit('/')
})

View file

@ -1,4 +1,5 @@
import type { OnboardingState } from '@maybe-finance/server/features'
import { AuthUserRole } from '@prisma/client'
import { Router } from 'express'
import { DateTime } from 'luxon'
import { z } from 'zod'
@ -6,13 +7,13 @@ import endpoint from '../lib/endpoint'
const router = Router()
const testUserId = 'test_ec3ee8a4-fa01-4f11-8ac5-9c49dd7fbae4'
router.use((req, res, next) => {
if (req.user?.sub === testUserId) {
const role = req.user?.role
if (role === AuthUserRole.admin || role === AuthUserRole.ci) {
next()
} else {
res.status(401).send('Route only available to test users')
res.status(401).send('Route only available to CIUser and Admin roles')
}
})
@ -47,14 +48,15 @@ router.post(
trialLapsed: z.boolean().default(false),
}),
resolve: async ({ ctx, input }) => {
const user = ctx.user!
await ctx.prisma.$transaction([
ctx.prisma.$executeRaw`DELETE FROM "user" WHERE auth_id=${testUserId};`,
ctx.prisma.$executeRaw`DELETE FROM "user" WHERE auth_id=${user.authId};`,
ctx.prisma.user.create({
data: {
authId: testUserId,
email: 'bond@007.com',
firstName: 'James',
lastName: 'Bond',
authId: user.authId,
email: user.email,
firstName: user.firstName,
lastName: user.lastName,
dob: new Date('1990-01-01'),
linkAccountDismissedAt: new Date(), // ensures our auto-account link doesn't trigger

View file

@ -687,7 +687,7 @@ export class InsightService implements IInsightService {
INNER JOIN security s ON s.id = h.security_id
LEFT JOIN LATERAL (
SELECT
asset_class AS "category"
s.asset_class AS "category"
) x ON TRUE
WHERE
h.account_id IN ${accountIds}

View file

@ -35,23 +35,7 @@ async function main() {
},
]
const hashedPassword = await bcrypt.hash('TestPassword123', 10)
await prisma.$transaction([
// create testing auth user
prisma.authUser.upsert({
where: {
id: 'test_ec3ee8a4-fa01-4f11-8ac5-9c49dd7fbae4',
},
create: {
id: 'test_ec3ee8a4-fa01-4f11-8ac5-9c49dd7fbae4',
firstName: 'James',
lastName: 'Bond',
email: 'bond@007.com',
password: hashedPassword,
},
update: {},
}),
// create institution linked to provider institutions
...institutions.map(({ id, name, providers }) =>
prisma.institution.upsert({

View file

@ -66,33 +66,6 @@
"options": {
"command": "node tools/scripts/triggerClientDeploy.js"
}
},
"storybook": {
"executor": "@nrwl/storybook:storybook",
"options": {
"uiFramework": "@storybook/react",
"port": 4400,
"configDir": "apps/client/.storybook"
},
"configurations": {
"ci": {
"quiet": true
}
}
},
"build-storybook": {
"executor": "@nrwl/storybook:build",
"outputs": ["{options.outputDir}"],
"options": {
"uiFramework": "@storybook/react",
"outputDir": "dist/storybook/client",
"configDir": "apps/client/.storybook"
},
"configurations": {
"ci": {
"quiet": true
}
}
}
},
"tags": ["scope:app"]