Skip to content

Commit

Permalink
feat: add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
eliasrosa committed Nov 22, 2023
1 parent 4942cc8 commit 586d6eb
Show file tree
Hide file tree
Showing 22 changed files with 414 additions and 102 deletions.
48 changes: 48 additions & 0 deletions src/actions/portfoliosActions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { describe, expect, test } from 'vitest'
import { portfoliosActions } from './portfoliosActions'
import { Portfolio } from '@/@types/PortfoliosTypes'

describe('portfoliosActions', () => {
const initialState: Portfolio[] = [
{ id: 'e5d46968-3a05-46d1-b5ec-a003c2a38a3b', name: 'Portfolio 1' },
{ id: 'bdcfe013-ae51-4f79-b8a1-791f745e9116', name: 'Portfolio 2' },
{ id: 'b33c91c4-2661-462c-8cbd-a4501f629351', name: 'Portfolio 3' },
]

test('should update the portfolio with the given payload', () => {
const newState = portfoliosActions.update(initialState, {
id: 'bdcfe013-ae51-4f79-b8a1-791f745e9116',
name: 'Portfolio Edited',
})

expect(newState).toEqual([
{ id: 'e5d46968-3a05-46d1-b5ec-a003c2a38a3b', name: 'Portfolio 1' },
{ id: 'bdcfe013-ae51-4f79-b8a1-791f745e9116', name: 'Portfolio Edited' },
{ id: 'b33c91c4-2661-462c-8cbd-a4501f629351', name: 'Portfolio 3' },
])
})

test('should insert a new portfolio into the state', () => {
const newState = portfoliosActions.insert(initialState, {
name: 'Portfolio New',
})

expect(newState).toEqual([
{ id: 'e5d46968-3a05-46d1-b5ec-a003c2a38a3b', name: 'Portfolio 1' },
{ id: 'bdcfe013-ae51-4f79-b8a1-791f745e9116', name: 'Portfolio 2' },
{ id: 'b33c91c4-2661-462c-8cbd-a4501f629351', name: 'Portfolio 3' },
{ id: expect.any(String), name: 'Portfolio New' },
])
})

test('should remove the specified portfolio from the state', () => {
const newState = portfoliosActions.remove(initialState, {
id: 'bdcfe013-ae51-4f79-b8a1-791f745e9116',
})

expect(newState).toEqual([
{ id: 'e5d46968-3a05-46d1-b5ec-a003c2a38a3b', name: 'Portfolio 1' },
{ id: 'b33c91c4-2661-462c-8cbd-a4501f629351', name: 'Portfolio 3' },
])
})
})
68 changes: 68 additions & 0 deletions src/actions/tickersActions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* eslint-disable prettier/prettier */
import { describe, expect, test } from 'vitest'
import { Ticker } from '@/@types/TickersTypes'
import { tickersActions } from './tickersActions'

describe('tickersActions', () => {
const initialState: Ticker[] = [
{ ticker: 'AABB11', portfolioId: 'e5d46968-3a05-46d1-b5ec-a003c2a38a3b', isHidden: false, quantity: 1 },
{ ticker: 'AABB11', portfolioId: 'bdcfe013-ae51-4f79-b8a1-791f745e9116', isHidden: false, quantity: 1 },
{ ticker: 'AAXX11', portfolioId: 'e5d46968-3a05-46d1-b5ec-a003c2a38a3b', isHidden: false, quantity: 1 },
]

describe('insert', () => {
test('should insert new tickers into the state', () => {
const tickersList = ['AABB11', 'AAXX11']
const portfoliosList = [
'e5d46968-3a05-46d1-b5ec-a003c2a38a3b',
'bdcfe013-ae51-4f79-b8a1-791f745e9116',
]

const newState = tickersActions.insert(initialState, {
tickersList,
portfoliosList,
})

expect(newState).toEqual([
{ ticker: 'AABB11', portfolioId: 'e5d46968-3a05-46d1-b5ec-a003c2a38a3b', isHidden: false, quantity: 1 },
{ ticker: 'AABB11', portfolioId: 'bdcfe013-ae51-4f79-b8a1-791f745e9116', isHidden: false, quantity: 1 },
{ ticker: 'AAXX11', portfolioId: 'e5d46968-3a05-46d1-b5ec-a003c2a38a3b', isHidden: false, quantity: 1 },
{ ticker: 'AAXX11', portfolioId: 'bdcfe013-ae51-4f79-b8a1-791f745e9116', isHidden: false, quantity: 1 },
])
})
})

describe('remove', () => {
test('should remove the specified ticker from the state', () => {
const ticker = 'AAXX11'
const portfolioId = 'e5d46968-3a05-46d1-b5ec-a003c2a38a3b'

const newState = tickersActions.remove(initialState, {
ticker,
portfolioId,
})

expect(newState).toEqual([
{ ticker: 'AABB11', portfolioId: 'e5d46968-3a05-46d1-b5ec-a003c2a38a3b', isHidden: false, quantity: 1 },
{ ticker: 'AABB11', portfolioId: 'bdcfe013-ae51-4f79-b8a1-791f745e9116', isHidden: false, quantity: 1 },
])
})
})

describe('update', () => {
test('should update the specified ticker in the state', () => {
const newState = tickersActions.update(initialState, {
ticker: 'AABB11',
portfolioId: 'bdcfe013-ae51-4f79-b8a1-791f745e9116',
isHidden: true,
quantity: 5,
})

expect(newState).toEqual([
{ ticker: 'AABB11', portfolioId: 'e5d46968-3a05-46d1-b5ec-a003c2a38a3b', isHidden: false, quantity: 1 },
{ ticker: 'AABB11', portfolioId: 'bdcfe013-ae51-4f79-b8a1-791f745e9116', isHidden: true, quantity: 5 },
{ ticker: 'AAXX11', portfolioId: 'e5d46968-3a05-46d1-b5ec-a003c2a38a3b', isHidden: false, quantity: 1 },
])
})
})
})
2 changes: 1 addition & 1 deletion src/components/common/Title.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import { cn } from '@/helpers/utils'
import { cn } from '@/helpers/cn'
import { TitleProps, Title as TitleTremor } from '@tremor/react'

export function Title({ children, ...props }: TitleProps) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/layout/Main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import { cn } from '@/helpers/utils'
import { cn } from '@/helpers/cn'
import { useSidebar } from '@/hooks/useSidebar'
import { ReactNode } from 'react'

Expand Down
4 changes: 2 additions & 2 deletions src/components/layout/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'use client'

import { Calculator, Question, Wallet } from '@phosphor-icons/react'
import { Calculator, Wallet } from '@phosphor-icons/react'
import { SidebarMenuItem } from './SidebarMenu'
import { Logo } from '../common/Logo'
import { useSidebar } from '@/hooks/useSidebar'
import { cn } from '@/helpers/utils'
import { cn } from '@/helpers/cn'

export function Sidebar() {
const { isOpen } = useSidebar()
Expand Down
8 changes: 3 additions & 5 deletions src/components/pages/home/history-chart/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ import { usePortfolios } from '@/hooks/usePortfolios'
import { Card } from '../../../common/Card'
import { TickerData } from '@/@types/TickersTypes'
import { Chart } from './Chart'
import {
getLastDays,
getLastMonths,
mergeArrayOfObjects,
} from '@/helpers/utils'
import { getLastDays } from '@/helpers/getLastDays'
import { getLastMonths } from '@/helpers/getLastMonths'
import { mergeArrayOfObjects } from '@/helpers/mergeArrayOfObjects'

type Report = 'pricesHistory' | 'dividendsHistory'

Expand Down
2 changes: 1 addition & 1 deletion src/components/pages/home/stocks-cards/StockCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { cn } from '@/helpers/utils'
import { cn } from '@/helpers/cn'
import { Card, Text, BadgeDelta, Metric, CardProps } from '@tremor/react'

interface Props extends CardProps {
Expand Down
73 changes: 73 additions & 0 deletions src/config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { afterEach, beforeEach, describe, expect, test } from 'vitest'
import { getConfigAPI } from './config'

describe('getConfigAPI', () => {
beforeEach(() => {
process.env.NEXT_PUBLIC_API_KEY = 'test-key'
process.env.NEXT_PUBLIC_API_URL = 'https://api.example.com'
process.env.NEXT_PUBLIC_API_CACHE = 'no-cache'
process.env.NEXT_PUBLIC_API_REVALIDATE = '3600'
})

afterEach(() => {
delete process.env.NEXT_PUBLIC_API_KEY
delete process.env.NEXT_PUBLIC_API_URL
delete process.env.NEXT_PUBLIC_API_CACHE
delete process.env.NEXT_PUBLIC_API_REVALIDATE
})

test('should return config object with valid environment variables', () => {
const expectedConfig = {
key: 'test-key',
url: 'https://api.example.com',
cache: 'no-cache',
revalidate: 3600,
}

const config = getConfigAPI()

expect(config).toEqual(expectedConfig)
})

test('should throw an error if NEXT_PUBLIC_API_KEY is not found', () => {
delete process.env.NEXT_PUBLIC_API_KEY

expect(getConfigAPI).toThrowError('NEXT_PUBLIC_API_KEY not found')
})

test('should throw an error if NEXT_PUBLIC_API_URL is not found', () => {
delete process.env.NEXT_PUBLIC_API_URL

expect(getConfigAPI).toThrowError('NEXT_PUBLIC_API_URL not found')
})

test('should return default values if NEXT_PUBLIC_API_CACHE is not found', () => {
delete process.env.NEXT_PUBLIC_API_CACHE

const expectedConfig = {
key: 'test-key',
url: 'https://api.example.com',
cache: 'force-cache',
revalidate: 3600,
}

const config = getConfigAPI()

expect(config).toEqual(expectedConfig)
})

test('should return default values if NEXT_PUBLIC_API_REVALIDATE is not found', () => {
delete process.env.NEXT_PUBLIC_API_REVALIDATE

const expectedConfig = {
key: 'test-key',
url: 'https://api.example.com',
cache: 'no-cache',
revalidate: 3600,
}

const config = getConfigAPI()

expect(config).toEqual(expectedConfig)
})
})
4 changes: 2 additions & 2 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const getConfigAPI = () => {
export const getConfigAPI = () => {
if (!process.env.NEXT_PUBLIC_API_KEY) {
throw new Error('NEXT_PUBLIC_API_KEY not found')
}
Expand All @@ -10,7 +10,7 @@ const getConfigAPI = () => {
return {
key: process.env.NEXT_PUBLIC_API_KEY,
url: process.env.NEXT_PUBLIC_API_URL,
cache: process.env.NEXT_PUBLIC_API_CACHE as RequestCache,
cache: (process.env.NEXT_PUBLIC_API_CACHE || 'force-cache') as RequestCache,
revalidate: parseInt(process.env.NEXT_PUBLIC_API_REVALIDATE || '3600'),
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/helpers/cn.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { describe, expect, test } from 'vitest'
import { cn } from './cn'

describe('cn', () => {
test('should return string with merged values', () => {
const result = cn('a', 'b', 'c')
expect(result).toBe('a b c')
})
})
6 changes: 6 additions & 0 deletions src/helpers/cn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'

export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
12 changes: 12 additions & 0 deletions src/helpers/currency.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { describe, test, expect } from 'vitest'
import { toCurrency } from './currency'

describe('toCurrency', () => {
test('should return the correct currency format for a given number', () => {
const number = 1234.56
const expected = 'R$ 1.234,56'

const result = toCurrency(number)
expect(result).toBe(expected)
})
})
26 changes: 0 additions & 26 deletions src/helpers/fetchStocks.ts

This file was deleted.

14 changes: 14 additions & 0 deletions src/helpers/getLastDays.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { describe, expect, test } from 'vitest'
import { getLastDays } from './getLastDays'

describe('getLastDays', () => {
test('should return array with last 20 days', () => {
const days = getLastDays()
expect(days.length).toBe(20)
})

test('should return array with custom days', () => {
const days = getLastDays(10)
expect(days.length).toBe(10)
})
})
17 changes: 17 additions & 0 deletions src/helpers/getLastDays.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import moment from 'moment'

export function getLastDays(count = 20): string[] {
const today = moment()
const days = []

for (let i = 0; days.length < count; i++) {
const currentDay = today.clone().subtract(i, 'days')

if (currentDay.isoWeekday() !== 6 && currentDay.isoWeekday() !== 7) {
const dayStr = currentDay.format('DD/MMM')
days.push(dayStr)
}
}

return days
}
14 changes: 14 additions & 0 deletions src/helpers/getLastMonths.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { describe, expect, test } from 'vitest'
import { getLastMonths } from './getLastMonths'

describe('getLastMonths', () => {
test('should return array with last 12 months', () => {
const months = getLastMonths()
expect(months.length).toBe(12)
})

test('should return array with custom months', () => {
const months = getLastMonths(10)
expect(months.length).toBe(10)
})
})
14 changes: 14 additions & 0 deletions src/helpers/getLastMonths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import moment from 'moment'

export function getLastMonths(count = 12): string[] {
const today = moment()
const months = []

for (let i = 0; i < count; i++) {
const currentMonth = today.clone().subtract(i, 'months')
const monthStr = currentMonth.format('MMM/YY')
months.push(monthStr)
}

return months
}
10 changes: 10 additions & 0 deletions src/helpers/mergeArrayOfObjects.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { describe, expect, test } from 'vitest'
import { mergeArrayOfObjects } from './mergeArrayOfObjects'

describe('mergeArrayOfObjects', () => {
test('should return object with merged values', () => {
const arr = [{ a: 1 }, { b: 2 }, { c: 3 }, { a: 4 }]
const result = mergeArrayOfObjects(arr)
expect(result).toEqual({ a: 4, b: 2, c: 3 })
})
})
5 changes: 5 additions & 0 deletions src/helpers/mergeArrayOfObjects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export function mergeArrayOfObjects(arr: object[]): object {
return arr.reduce((mergedObj, currentObj) => {
return { ...mergedObj, ...currentObj }
}, {})
}
Loading

0 comments on commit 586d6eb

Please sign in to comment.