1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-09 07:25:19 +02:00

remove plaid from queue test

This commit is contained in:
Tyler Myracle 2024-01-19 16:54:31 -06:00
parent 024f289ee9
commit 3a9e68c5eb
2 changed files with 66 additions and 111 deletions

View file

@ -2,25 +2,19 @@
// Keep these imports above the rest to avoid errors // Keep these imports above the rest to avoid errors
// ===================================================== // =====================================================
import type { SharedType } from '@maybe-finance/shared' import type { SharedType } from '@maybe-finance/shared'
import type { AccountsGetResponse, TransactionsGetResponse } from 'plaid' import { TellerGenerator } from 'tools/generators'
import type { AccountConnection, User } from '@prisma/client' import type { AccountConnection, User } from '@prisma/client'
import { TestUtil } from '@maybe-finance/shared'
import { PlaidTestData } from '../../../../../tools/test-data'
import { Prisma } from '@prisma/client'
import prisma from '../lib/prisma' import prisma from '../lib/prisma'
import { default as _plaid } from '../lib/plaid' import { default as _teller } from '../lib/teller'
import nock from 'nock'
import { DateTime } from 'luxon'
import { resetUser } from './helpers/user.test-helper' import { resetUser } from './helpers/user.test-helper'
// Import the workers process // Import the workers process
import '../../main' import '../../main'
import { queueService, securityPricingService } from '../lib/di' import { queueService } from '../lib/di'
jest.mock('plaid')
// For TypeScript support // For TypeScript support
const plaid = jest.mocked(_plaid) jest.mock('../lib/teller')
const teller = jest.mocked(_teller)
let user: User | null let user: User | null
let connection: AccountConnection let connection: AccountConnection
@ -30,25 +24,6 @@ if (process.env.IS_VSCODE_DEBUG === 'true') {
jest.setTimeout(100000) jest.setTimeout(100000)
} }
beforeAll(() => {
nock.disableNetConnect()
nock('https://api.polygon.io')
.get((uri) => uri.includes('v2/aggs/ticker/AAPL/range/1/day'))
.reply(200, PlaidTestData.AAPL)
.persist()
nock('https://api.polygon.io')
.get((uri) => uri.includes('v2/aggs/ticker/WMT/range/1/day'))
.reply(200, PlaidTestData.WMT)
.persist()
nock('https://api.polygon.io')
.get((uri) => uri.includes('v2/aggs/ticker/VOO/range/1/day'))
.reply(200, PlaidTestData.VOO)
.persist()
})
beforeEach(async () => { beforeEach(async () => {
jest.clearAllMocks() jest.clearAllMocks()
@ -57,10 +32,10 @@ beforeEach(async () => {
connection = await prisma.accountConnection.create({ connection = await prisma.accountConnection.create({
data: { data: {
name: 'Chase Test', name: 'Chase Test',
type: 'plaid' as SharedType.AccountConnectionType, type: 'teller' as SharedType.AccountConnectionType,
plaidItemId: 'test-plaid-item-workers', tellerEnrollmentId: 'test-teller-item-workers',
plaidInstitutionId: 'ins_3', tellerInstitutionId: 'chase_test',
plaidAccessToken: tellerAccessToken:
'U2FsdGVkX1+WMq9lfTS9Zkbgrn41+XT1hvSK5ain/udRPujzjVCAx/lyPG7EumVZA+nVKXPauGwI+d7GZgtqTA9R3iCZNusU6LFPnmFOCE4=', // need correct encoding here 'U2FsdGVkX1+WMq9lfTS9Zkbgrn41+XT1hvSK5ain/udRPujzjVCAx/lyPG7EumVZA+nVKXPauGwI+d7GZgtqTA9R3iCZNusU6LFPnmFOCE4=', // need correct encoding here
userId: user.id, userId: user.id,
syncStatus: 'PENDING', syncStatus: 'PENDING',
@ -84,7 +59,7 @@ describe('Message queue tests', () => {
it('Should handle sync errors', async () => { it('Should handle sync errors', async () => {
const syncQueue = queueService.getQueue('sync-account-connection') const syncQueue = queueService.getQueue('sync-account-connection')
plaid.accountsGet.mockRejectedValueOnce('forced error for Jest tests') teller.getAccounts.mockRejectedValueOnce(new Error('forced error for Jest tests'))
await syncQueue.add('sync-connection', { accountConnectionId: connection.id }) await syncQueue.add('sync-connection', { accountConnectionId: connection.id })
@ -92,7 +67,7 @@ describe('Message queue tests', () => {
where: { id: connection.id }, where: { id: connection.id },
}) })
expect(plaid.accountsGet).toHaveBeenCalledTimes(1) expect(teller.getAccounts).toHaveBeenCalledTimes(1)
expect(updatedConnection?.status).toEqual('ERROR') expect(updatedConnection?.status).toEqual('ERROR')
}) })
@ -117,28 +92,23 @@ describe('Message queue tests', () => {
const syncQueue = queueService.getQueue('sync-account-connection') const syncQueue = queueService.getQueue('sync-account-connection')
// Mock will return a basic banking checking account // Mock will return a basic banking checking account
plaid.accountsGet.mockResolvedValueOnce( const mockAccounts = TellerGenerator.generateAccountsWithBalances({
TestUtil.axiosSuccess<AccountsGetResponse>({ count: 1,
accounts: [PlaidTestData.checkingAccount], institutionId: 'chase_test',
item: PlaidTestData.item, enrollmentId: 'test-teller-item-workers',
request_id: 'bkVE1BHWMAZ9Rnr', institutionName: 'Chase Test',
}) as any accountType: 'depository',
) accountSubType: 'checking',
})
teller.getAccounts.mockResolvedValueOnce(mockAccounts)
plaid.transactionsGet.mockResolvedValueOnce( const mockTransactions = TellerGenerator.generateTransactions(10, mockAccounts[0].id)
TestUtil.axiosSuccess<TransactionsGetResponse>({ teller.getTransactions.mockResolvedValueOnce(mockTransactions)
accounts: [PlaidTestData.checkingAccount],
transactions: PlaidTestData.checkingTransactions,
item: PlaidTestData.item,
total_transactions: PlaidTestData.checkingTransactions.length,
request_id: '45QSn',
}) as any
)
await syncQueue.add('sync-connection', { accountConnectionId: connection.id }) await syncQueue.add('sync-connection', { accountConnectionId: connection.id })
expect(plaid.accountsGet).toHaveBeenCalledTimes(1) expect(teller.getAccounts).toHaveBeenCalledTimes(1)
expect(plaid.transactionsGet).toHaveBeenCalledTimes(1) expect(teller.getTransactions).toHaveBeenCalledTimes(1)
const item = await prisma.accountConnection.findUniqueOrThrow({ const item = await prisma.accountConnection.findUniqueOrThrow({
where: { id: connection.id }, where: { id: connection.id },
@ -146,7 +116,7 @@ describe('Message queue tests', () => {
accounts: { accounts: {
include: { include: {
balances: { balances: {
where: PlaidTestData.testDates.prismaWhereFilter, where: TellerGenerator.testDates.prismaWhereFilter,
orderBy: { date: 'asc' }, orderBy: { date: 'asc' },
}, },
transactions: true, transactions: true,
@ -161,62 +131,15 @@ describe('Message queue tests', () => {
expect(item.accounts).toHaveLength(1) expect(item.accounts).toHaveLength(1)
const [account] = item.accounts const [account] = item.accounts
const transactionBalance = mockTransactions.reduce(
expect(account.transactions).toHaveLength(PlaidTestData.checkingTransactions.length) (acc, t) => acc + t.amount,
expect(account.balances.map((b) => b.balance)).toEqual( mockAccounts[0].balance.available
[
3630,
5125,
5125,
5125,
5125,
5125,
5125,
5125,
5125,
5125,
5115,
5115,
5115,
5089.45,
5089.45,
PlaidTestData.checkingAccount.balances.current!,
].map((v) => new Prisma.Decimal(v))
) )
expect(account.transactions).toHaveLength(10)
expect(account.balances.map((b) => b.balance)).toEqual(transactionBalance)
expect(account.holdings).toHaveLength(0) expect(account.holdings).toHaveLength(0)
expect(account.valuations).toHaveLength(0) expect(account.valuations).toHaveLength(0)
expect(account.investmentTransactions).toHaveLength(0) expect(account.investmentTransactions).toHaveLength(0)
}) })
it('Should sync valid security prices', async () => {
const security = await prisma.security.create({
data: {
name: 'Walmart Inc.',
symbol: 'WMT',
cusip: '93114210310',
pricingLastSyncedAt: new Date(),
},
})
await securityPricingService.sync(security)
const prices = await prisma.securityPricing.findMany({
where: { securityId: security.id },
orderBy: { date: 'asc' },
})
expect(prices).toHaveLength(PlaidTestData.WMT.results.length)
expect(
prices.map((p) => ({
date: DateTime.fromJSDate(p.date, { zone: 'utc' }).toISODate(),
price: p.priceClose.toNumber(),
}))
).toEqual(
PlaidTestData.WMT.results.map((p) => ({
date: DateTime.fromMillis(p.t, { zone: 'utc' }).toISODate(),
price: p.c,
}))
)
})
}) })

View file

@ -1,5 +1,7 @@
import { faker } from '@faker-js/faker' import { faker } from '@faker-js/faker'
import type { TellerTypes } from '../../libs/teller-api/src' import type { TellerTypes } from '../../libs/teller-api/src'
import type { Prisma } from '@prisma/client'
import { DateTime } from 'luxon'
function generateSubType( function generateSubType(
type: TellerTypes.AccountTypes type: TellerTypes.AccountTypes
@ -23,6 +25,8 @@ type GenerateAccountsParams = {
enrollmentId: string enrollmentId: string
institutionName: string institutionName: string
institutionId: string institutionId: string
accountType?: TellerTypes.AccountTypes
accountSubType?: TellerTypes.DepositorySubtypes | TellerTypes.CreditSubtype
} }
export function generateAccounts({ export function generateAccounts({
@ -30,12 +34,15 @@ export function generateAccounts({
enrollmentId, enrollmentId,
institutionName, institutionName,
institutionId, institutionId,
accountType,
accountSubType,
}: GenerateAccountsParams) { }: GenerateAccountsParams) {
const accounts: TellerTypes.Account[] = [] const accounts: TellerTypes.Account[] = []
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const accountId = faker.string.uuid() const accountId = faker.string.uuid()
const lastFour = faker.finance.creditCardNumber().slice(-4) const lastFour = faker.finance.creditCardNumber().slice(-4)
const type: TellerTypes.AccountTypes = faker.helpers.arrayElement(['depository', 'credit']) const type: TellerTypes.AccountTypes =
accountType ?? faker.helpers.arrayElement(['depository', 'credit'])
let subType: TellerTypes.DepositorySubtypes | TellerTypes.CreditSubtype let subType: TellerTypes.DepositorySubtypes | TellerTypes.CreditSubtype
subType = generateSubType(type) subType = generateSubType(type)
@ -99,6 +106,8 @@ type GenerateAccountsWithBalancesParams = {
enrollmentId: string enrollmentId: string
institutionName: string institutionName: string
institutionId: string institutionId: string
accountType?: TellerTypes.AccountTypes
accountSubType?: TellerTypes.DepositorySubtypes | TellerTypes.CreditSubtype
} }
export function generateAccountsWithBalances({ export function generateAccountsWithBalances({
@ -106,7 +115,9 @@ export function generateAccountsWithBalances({
enrollmentId, enrollmentId,
institutionName, institutionName,
institutionId, institutionId,
}: GenerateAccountsWithBalancesParams): TellerTypes.AccountWithBalances[] { accountType,
accountSubType,
}: GenerateAccountsWithBalancesParams): TellerTypes.GetAccountsResponse {
const accountsWithBalances: TellerTypes.AccountWithBalances[] = [] const accountsWithBalances: TellerTypes.AccountWithBalances[] = []
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const account = generateAccounts({ const account = generateAccounts({
@ -114,6 +125,8 @@ export function generateAccountsWithBalances({
enrollmentId, enrollmentId,
institutionName, institutionName,
institutionId, institutionId,
accountType,
accountSubType,
})[0] })[0]
const balance = generateBalance(account.id) const balance = generateBalance(account.id)
accountsWithBalances.push({ accountsWithBalances.push({
@ -170,7 +183,10 @@ export function generateTransactions(count: number, accountId: string): TellerTy
running_balance: null, running_balance: null,
description: faker.word.words({ count: { min: 3, max: 10 } }), description: faker.word.words({ count: { min: 3, max: 10 } }),
id: transactionId, id: transactionId,
date: faker.date.recent({ days: 30 }).toISOString().split('T')[0], // recent date in 'YYYY-MM-DD' format date: faker.date
.between({ from: lowerBound.toJSDate(), to: now.toJSDate() })
.toISOString()
.split('T')[0], // recent date in 'YYYY-MM-DD' format
account_id: accountId, account_id: accountId,
links: { links: {
account: `https://api.teller.io/accounts/${accountId}`, account: `https://api.teller.io/accounts/${accountId}`,
@ -246,3 +262,19 @@ export function generateConnection(): GenerateConnectionsResponse {
transactions, transactions,
} }
} }
const now = DateTime.fromISO('2022-01-03', { zone: 'utc' })
const lowerBound = DateTime.fromISO('2021-12-01', { zone: 'utc' })
export const testDates = {
now,
lowerBound,
totalDays: now.diff(lowerBound, 'days').days,
prismaWhereFilter: {
date: {
gte: lowerBound.toJSDate(),
lte: now.toJSDate(),
},
} as Prisma.AccountBalanceWhereInput,
}