Skip to content

Commit

Permalink
feat: add tests with vitest (#4)
Browse files Browse the repository at this point in the history
* feat: add tests with vitest

* ci: add testing job

* chore(ci): change job names
  • Loading branch information
uigywnkiub authored Jul 7, 2024
1 parent ae179d7 commit ed09687
Show file tree
Hide file tree
Showing 8 changed files with 1,896 additions and 26 deletions.
41 changes: 39 additions & 2 deletions .github/workflows/lint.yml → .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
name: Lint
name: Check

on:
workflow_dispatch:
pull_request:
Expand All @@ -8,11 +9,13 @@ on:
push:
branches:
- main

env:
CACHE_NAME: cache-node-modules

jobs:
lint:
name: Linting, Typechecking
name: Lint and Typecheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -47,3 +50,37 @@ jobs:

- name: Run TypeScript
run: yarn typecheck

test:
name: Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "yarn_cache_dir=$(yarn cache dir)" >> $GITHUB_OUTPUT

- name: Cache node modules
id: cache-yarn
uses: actions/cache@v4
with:
# another cache folder on ubuntu
# path: ~/.cache/yarn
path: ${{ steps.yarn-cache-dir-path.outputs.yarn_cache_dir }}
key: ${{ runner.os }}-build-${{ env.CACHE_NAME }}-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ env.CACHE_NAME }}-
${{ runner.os }}-build-
${{ runner.os }}-
- if: ${{ steps.cache-yarn.outputs.cache-hit != 'true' }}
name: List the state of node modules
continue-on-error: true
run: yarn list

- name: Install Dependencies
run: yarn install --immutable

- name: Run Tests
run: yarn test
317 changes: 317 additions & 0 deletions __tests__/functions/calculateMonthlyReportData.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,317 @@
import { describe, expect, it } from 'vitest'

import {
CURRENCY_CODE,
CURRENCY_NAME,
CURRENCY_SIGN,
} from '@/config/constants/main'

import { calculateMonthlyReportData } from '../../app/lib/data'
import type { TCategoryData, TTransaction } from '../../app/lib/types'

describe('calculateMonthlyReportData', () => {
it('should calculate total income and total expense correctly', () => {
const income: TTransaction[] = [
{
id: '1',
userId: 'user1',
category: 'Salary',
description: 'Monthly Salary',
amount: '1000',
isIncome: true,
balance: '1000',
currency: {
name: CURRENCY_NAME.UAH,
code: CURRENCY_CODE.UAH,
sign: CURRENCY_SIGN.UAH,
},
transactionLimit: null,
createdAt: new Date(),
updatedAt: new Date(),
},
]

const expense: TTransaction[] = [
{
id: '2',
userId: 'user1',
category: 'Groceries',
description: 'Weekly groceries',
amount: '200',
isIncome: false,
balance: '800',
currency: {
name: CURRENCY_NAME.UAH,
code: CURRENCY_CODE.UAH,
sign: CURRENCY_SIGN.UAH,
},
transactionLimit: null,
createdAt: new Date(),
updatedAt: new Date(),
},
]

const result = calculateMonthlyReportData(income, expense)
expect(result.totalIncome).toBe(1000)
expect(result.totalExpense).toBe(200)
})

it('should calculate totals by category correctly', () => {
const income: TTransaction[] = []
const expense: TTransaction[] = [
{
id: '1',
userId: 'user1',
category: 'Groceries',
description: 'Groceries',
amount: '200',
isIncome: false,
balance: '800',
currency: {
name: CURRENCY_NAME.UAH,
code: CURRENCY_CODE.UAH,
sign: CURRENCY_SIGN.UAH,
},
transactionLimit: null,
createdAt: new Date(),
updatedAt: new Date(),
},
{
id: '2',
userId: 'user1',
category: 'Transport',
description: 'Bus fare',
amount: '100',
isIncome: false,
balance: '700',
currency: {
name: CURRENCY_NAME.UAH,
code: CURRENCY_CODE.UAH,
sign: CURRENCY_SIGN.UAH,
},
transactionLimit: null,
createdAt: new Date(),
updatedAt: new Date(),
},
{
id: '3',
userId: 'user1',
category: 'Groceries',
description: 'More groceries',
amount: '150',
isIncome: false,
balance: '550',
currency: {
name: CURRENCY_NAME.UAH,
code: CURRENCY_CODE.UAH,
sign: CURRENCY_SIGN.UAH,
},
transactionLimit: null,
createdAt: new Date(),
updatedAt: new Date(),
},
]

const result = calculateMonthlyReportData(income, expense)
const expectedMonthlyReportData: TCategoryData[] = [
{ category: 'Groceries', spent: 350, percentage: '77.78' },
{ category: 'Transport', spent: 100, percentage: '22.22' },
]

expect(result.monthlyReportData).toEqual(expectedMonthlyReportData)
})

it('should handle zero expenses', () => {
const income: TTransaction[] = [
{
id: '1',
userId: 'user1',
category: 'Salary',
description: 'Monthly Salary',
amount: '1000',
isIncome: true,
balance: '1000',
currency: {
name: CURRENCY_NAME.UAH,
code: CURRENCY_CODE.UAH,
sign: CURRENCY_SIGN.UAH,
},
transactionLimit: null,
createdAt: new Date(),
updatedAt: new Date(),
},
]

const expense: TTransaction[] = []

const result = calculateMonthlyReportData(income, expense)
expect(result.totalIncome).toBe(1000)
expect(result.totalExpense).toBe(0)
expect(result.monthlyReportData).toEqual([])
})

it('should handle zero income transactions', () => {
const income: TTransaction[] = []
const expense: TTransaction[] = [
{
id: '1',
userId: 'user1',
category: 'Groceries',
description: 'Groceries',
amount: '200',
isIncome: false,
balance: '800',
currency: {
name: CURRENCY_NAME.UAH,
code: CURRENCY_CODE.UAH,
sign: CURRENCY_SIGN.UAH,
},
transactionLimit: null,
createdAt: new Date(),
updatedAt: new Date(),
},
]

const result = calculateMonthlyReportData(income, expense)
expect(result.totalIncome).toBe(0)
expect(result.totalExpense).toBe(200)
})

it('should handle transactions with different currencies', () => {
const income: TTransaction[] = [
{
id: '1',
userId: 'user1',
category: 'Salary',
description: 'Monthly Salary',
amount: '1000',
isIncome: true,
balance: '1000',
currency: {
name: CURRENCY_NAME.UAH,
code: CURRENCY_CODE.UAH,
sign: CURRENCY_SIGN.UAH,
},
transactionLimit: null,
createdAt: new Date(),
updatedAt: new Date(),
},
]

const expense: TTransaction[] = [
{
id: '2',
userId: 'user1',
category: 'Groceries',
description: 'Groceries',
amount: '200',
isIncome: false,
balance: '800',
currency: {
name: CURRENCY_NAME.UAH,
code: CURRENCY_CODE.UAH,
sign: CURRENCY_SIGN.UAH,
},
transactionLimit: null,
createdAt: new Date(),
updatedAt: new Date(),
},
]

const result = calculateMonthlyReportData(income, expense)
expect(result.totalIncome).toBe(1000)
expect(result.totalExpense).toBe(200)
})

it('should handle transactions with transaction limits', () => {
const income: TTransaction[] = [
{
id: '1',
userId: 'user1',
category: 'Salary',
description: 'Monthly Salary',
amount: '1000',
isIncome: true,
balance: '1000',
currency: {
name: CURRENCY_NAME.UAH,
code: CURRENCY_CODE.UAH,
sign: CURRENCY_SIGN.UAH,
},
transactionLimit: 40,
createdAt: new Date(),
updatedAt: new Date(),
},
]

const expense: TTransaction[] = [
{
id: '2',
userId: 'user1',
category: 'Groceries',
description: 'Groceries',
amount: '200',
isIncome: false,
balance: '800',
currency: {
name: CURRENCY_NAME.UAH,
code: CURRENCY_CODE.UAH,
sign: CURRENCY_SIGN.UAH,
},
transactionLimit: 40,
createdAt: new Date(),
updatedAt: new Date(),
},
]

const result = calculateMonthlyReportData(income, expense)
expect(result.totalIncome).toBe(1000)
expect(result.totalExpense).toBe(200)
})

it('should handle transactions created in different time frames', () => {
const income: TTransaction[] = [
{
id: '1',
userId: 'user1',
category: 'Salary',
description: 'Monthly Salary',
amount: '1000',
isIncome: true,
balance: '1000',
currency: {
name: CURRENCY_NAME.UAH,
code: CURRENCY_CODE.UAH,
sign: CURRENCY_SIGN.UAH,
},
transactionLimit: 30,
createdAt: new Date('2024-07-01'),
updatedAt: new Date('2024-07-01'),
},
]

const expense: TTransaction[] = [
{
id: '2',
userId: 'user1',
category: 'Groceries',
description: 'Groceries',
amount: '200',
isIncome: false,
balance: '800',
currency: {
name: CURRENCY_NAME.UAH,
code: CURRENCY_CODE.UAH,
sign: CURRENCY_SIGN.UAH,
},
transactionLimit: 30,
createdAt: new Date('2024-08-01'),
updatedAt: new Date('2024-08-01'),
},
]

const result = calculateMonthlyReportData(income, expense)
expect(result.totalIncome).toBe(1000)
expect(result.totalExpense).toBe(200)
})
})
Loading

0 comments on commit ed09687

Please sign in to comment.