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:
parent
06b861aea7
commit
9ea0ec6b7a
12 changed files with 78 additions and 130 deletions
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"presets": [
|
||||
"@babel/preset-typescript",
|
||||
"@babel/preset-env",
|
||||
[
|
||||
"@nrwl/react/babel",
|
||||
{
|
||||
"runtime": "automatic",
|
||||
"useBuiltIns": "usage"
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": []
|
||||
}
|
|
@ -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
|
||||
},
|
||||
}
|
|
@ -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({})
|
|
@ -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 })
|
||||
},
|
||||
}),
|
||||
],
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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('/')
|
||||
})
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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"]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue