Skip to content

Add tests, fix DB schema, add docs#243

Open
PankajSingh34 wants to merge 1 commit intocsxark:mainfrom
PankajSingh34:fixes
Open

Add tests, fix DB schema, add docs#243
PankajSingh34 wants to merge 1 commit intocsxark:mainfrom
PankajSingh34:fixes

Conversation

@PankajSingh34
Copy link
Contributor

Add comprehensive Jest tests and testing docs, fix schema syntax, and install missing deps. This commit adds four new test suites (analytics, categories, goals, financialCalculations) with ~100+ assertions to bootstrap testing; includes TEST_SETUP_COMPLETE.md and FIRST_CONTRIBUTION_GUIDE.md. Fixes a schema bug (rename inactivity threshold → inactivityThreshold) and adds subscriptions, subscriptionUsage, and cancellationSuggestions tables to backend/db/schema.js. package.json and lock updated to include testing and mailing dependencies (e.g. Jest, nodemailer). Some new tests are passing (17) while ~15 need minor property-name adjustments documented in the added guides.

📝 Description

Fixes #(issue)

🎯 Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 📚 Documentation update
  • 🎨 UI/UX improvement
  • ♻️ Refactoring

🧪 How to Test

📸 Screenshots (if applicable)

✅ Checklist

  • I have tested my changes
  • My code follows the project style
  • I have updated documentation if needed

Add comprehensive Jest tests and testing docs, fix schema syntax, and install missing deps. This commit adds four new test suites (analytics, categories, goals, financialCalculations) with ~100+ assertions to bootstrap testing; includes TEST_SETUP_COMPLETE.md and FIRST_CONTRIBUTION_GUIDE.md. Fixes a schema bug (rename inactivity threshold → inactivityThreshold) and adds subscriptions, subscriptionUsage, and cancellationSuggestions tables to backend/db/schema.js. package.json and lock updated to include testing and mailing dependencies (e.g. Jest, nodemailer). Some new tests are passing (17) while ~15 need minor property-name adjustments documented in the added guides.
Copilot AI review requested due to automatic review settings February 5, 2026 16:57
@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Thanks for creating a PR for your Issue! ☺️

We'll review it as soon as possible.
In the meantime, please double-check the file changes and ensure that all commits are accurate.

If there are any unresolved review comments, feel free to resolve them. 🙌🏼

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds comprehensive Jest testing infrastructure to the Wealth Vault backend, fixes a critical database schema syntax error, adds three new subscription-related database tables, and installs nodemailer as a dependency. The changes include four new test suites (analytics, categories, goals, financialCalculations) with 100+ assertions, though many tests have critical property name mismatches that cause test failures.

Changes:

  • Fixed schema syntax bug: inactivity thresholdinactivityThreshold in inheritanceRules table
  • Added three new database tables: subscriptions, subscriptionUsage, and cancellationSuggestions
  • Added nodemailer ^8.0.0 dependency and updated package-lock.json
  • Created four new test files with 100+ test assertions
  • Added two documentation files: TEST_SETUP_COMPLETE.md and FIRST_CONTRIBUTION_GUIDE.md

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
backend/package.json Adds nodemailer ^8.0.0 dependency
backend/package-lock.json Updates lock file with nodemailer and transitive dependencies; adds engine requirement; removes peer markers from direct dependencies
backend/db/schema.js Fixes inactivityThreshold property name bug; adds subscriptions, subscriptionUsage, and cancellationSuggestions table definitions
backend/tests/utils/financialCalculations.test.js Adds 32 unit tests for financial utility functions, but contains critical property name mismatches causing 15 test failures
backend/tests/routes/goals.test.js Adds 6 test suites for goals routes with jest.unstable_mockModule mocking strategy
backend/tests/routes/categories.test.js Adds 5 test suites for categories routes with jest.unstable_mockModule mocking strategy
backend/tests/routes/analytics.test.js Adds 6 test suites for analytics routes with jest.unstable_mockModule mocking strategy
TEST_SETUP_COMPLETE.md Documents test setup and current status with 213 lines of comprehensive testing guidance
FIRST_CONTRIBUTION_GUIDE.md Provides 248 lines of contribution guidance with specific examples and workflows
Files not reviewed (1)
  • backend/package-lock.json: Language not supported

Comment on lines +203 to +206
const recurringExpenses = 1500;
const monthlyIncome = 5000;

const prediction = predictCashFlow(monthlyData, recurringExpenses, monthlyIncome);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test's recurringExpenses parameter is a number (1500), but the actual predictCashFlow implementation expects an array of objects with an amount property (line 310 of financialCalculations.js): const recurringTotal = recurringExpenses.reduce((sum, expense) => sum + expense.amount, 0);

The test should pass an array like [{ amount: 1500 }] instead of just 1500.

Copilot uses AI. Check for mistakes.

### Step 1: Check What Changed
```bash
cd "/Users/pankajsingh/Movies/OPENSOURCE PROJECT/Wealth-Vault"
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hardcoded file path is specific to one developer's machine and will not work for anyone else. This should be replaced with a relative path or removed entirely. Users can determine their current directory with pwd and don't need to see someone else's absolute path.

Replace with: cd backend (assuming users are in the project root)

Suggested change
cd "/Users/pankajsingh/Movies/OPENSOURCE PROJECT/Wealth-Vault"
cd backend

Copilot uses AI. Check for mistakes.
Comment on lines +70 to +74
# If you haven't forked yet, fork the repo on GitHub first
# Then add your fork as a remote
git remote add origin https://github.com/YOUR_USERNAME/Wealth-Vault.git

# Push to your fork
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This instruction assumes the user hasn't forked the repository yet and provides a generic remote URL. However, if this guide is being committed to the main repository, the instructions are potentially misleading:

  1. Users should fork the original repository first (github.com/PankajSingh34/Wealth-Vault)
  2. Clone their fork (not the original)
  3. Add the original as 'upstream' (not 'origin')
  4. 'origin' should already exist pointing to their fork

The typical Git workflow for contributing to open source is:

# Fork on GitHub first, then:
git clone https://github.com/YOUR_USERNAME/Wealth-Vault.git
cd Wealth-Vault
git remote add upstream https://github.com/PankajSingh34/Wealth-Vault.git
git checkout -b fixes
# Make changes, then:
git push origin fixes
Suggested change
# If you haven't forked yet, fork the repo on GitHub first
# Then add your fork as a remote
git remote add origin https://github.com/YOUR_USERNAME/Wealth-Vault.git
# Push to your fork
# Make sure you've forked the repo on GitHub and cloned *your fork*:
# https://github.com/YOUR_USERNAME/Wealth-Vault.git
# Optional (do this once): add the original repo as "upstream"
git remote add upstream https://github.com/PankajSingh34/Wealth-Vault.git
# Push your fixes branch to your fork

Copilot uses AI. Check for mistakes.
Comment on lines +169 to +194
describe('calculateFinancialHealthScore', () => {
it('should calculate overall health score', () => {
const metrics = {
savingsRate: 20,
dti: 25,
emergencyFund: 6,
spendingVolatility: 15,
};
const score = calculateFinancialHealthScore(metrics);
expect(score).toHaveProperty('overallScore');
expect(score).toHaveProperty('category');
expect(score.overallScore).toBeGreaterThan(0);
expect(score.overallScore).toBeLessThanOrEqual(100);
});

it('should categorize excellent health', () => {
const metrics = {
savingsRate: 30,
dti: 15,
emergencyFund: 8,
spendingVolatility: 10,
};
const score = calculateFinancialHealthScore(metrics);
expect(score.category).toBe('excellent');
});
});
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test expectations don't match the actual implementation. The calculateFinancialHealthScore function returns properties: overallScore, rating, recommendation, breakdown, weights, and timestamp, but the test expects category which doesn't exist.

The correct property name is rating (not category). The rating values are: 'Excellent', 'Good', 'Fair', or 'Needs Improvement' (note the capitalization and different value for scores < 40). The test expects 'excellent' (lowercase) which won't match.

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +36
// Mock the database before importing routes
jest.unstable_mockModule('../../config/db.js', () => ({
default: {
select: jest.fn().mockReturnThis(),
from: jest.fn().mockReturnThis(),
leftJoin: jest.fn().mockReturnThis(),
where: jest.fn().mockReturnThis(),
groupBy: jest.fn().mockReturnThis(),
orderBy: jest.fn().mockReturnThis(),
query: {
expenses: {
findMany: jest.fn().mockResolvedValue([]),
},
},
},
}));

// Mock currency service
jest.unstable_mockModule('../../services/currencyService.js', () => ({
convertAmount: jest.fn().mockResolvedValue(100),
getAllRates: jest.fn().mockResolvedValue([]),
}));

// Mock other services
jest.unstable_mockModule('../../services/assetService.js', () => ({
default: {
getTotalNetWorth: jest.fn().mockResolvedValue(0),
},
}));

jest.unstable_mockModule('../../services/projectionEngine.js', () => ({
default: {
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mocking strategy in these new test files (jest.unstable_mockModule) is inconsistent with the existing test patterns in the codebase. The existing tests in backend/__tests__/routes/auth.test.js and backend/__tests__/routes/expenses.test.js directly import the routers without mocking the database layer, which is simpler and more maintainable.

The jest.unstable_mockModule API is also marked as "unstable" in its name, indicating it may change in future Jest versions. Consider following the existing pattern used in the codebase:

  1. Import routers directly without complex mocking
  2. Use simple status code checks like expect([200, 500]).toContain(res.status)
  3. Focus on testing the API contract rather than implementation details

This will make tests more maintainable and consistent with the project's established testing conventions.

Copilot uses AI. Check for mistakes.
Comment on lines +96 to +118
it('should return adequate for 6+ months coverage', () => {
const result = calculateEmergencyFundAdequacy(18000, 3000);
expect(result).toHaveProperty('months');
expect(result).toHaveProperty('status');
expect(result.months).toBe(6);
expect(result.status).toBe('adequate');
});

it('should return needs_improvement for 3-5 months', () => {
const result = calculateEmergencyFundAdequacy(12000, 3000);
expect(result.months).toBe(4);
expect(result.status).toBe('needs_improvement');
});

it('should return critical for less than 3 months', () => {
const result = calculateEmergencyFundAdequacy(6000, 3000);
expect(result.months).toBe(2);
expect(result.status).toBe('critical');
});

it('should handle zero monthly expenses', () => {
const result = calculateEmergencyFundAdequacy(10000, 0);
expect(result.months).toBe(0);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test expectations don't match the actual implementation. According to the source code in backend/utils/financialCalculations.js, the calculateEmergencyFundAdequacy function returns properties: monthsCovered, adequacy, and score, but these tests expect months and status.

Expected properties should be:

  • monthsCovered (not months)
  • adequacy (not status)
  • score (missing from tests)

Additionally, the adequacy values differ from what's tested. The actual implementation returns:

  • 'excellent' for >= 6 months (not 'adequate')
  • 'good' for >= 3 months (not 'needs_improvement')
  • 'fair' for >= 1 month (not 'critical')
  • 'insufficient' for < 1 month
Suggested change
it('should return adequate for 6+ months coverage', () => {
const result = calculateEmergencyFundAdequacy(18000, 3000);
expect(result).toHaveProperty('months');
expect(result).toHaveProperty('status');
expect(result.months).toBe(6);
expect(result.status).toBe('adequate');
});
it('should return needs_improvement for 3-5 months', () => {
const result = calculateEmergencyFundAdequacy(12000, 3000);
expect(result.months).toBe(4);
expect(result.status).toBe('needs_improvement');
});
it('should return critical for less than 3 months', () => {
const result = calculateEmergencyFundAdequacy(6000, 3000);
expect(result.months).toBe(2);
expect(result.status).toBe('critical');
});
it('should handle zero monthly expenses', () => {
const result = calculateEmergencyFundAdequacy(10000, 0);
expect(result.months).toBe(0);
it('should return excellent for 6+ months coverage', () => {
const result = calculateEmergencyFundAdequacy(18000, 3000);
expect(result).toHaveProperty('monthsCovered');
expect(result).toHaveProperty('adequacy');
expect(result).toHaveProperty('score');
expect(result.monthsCovered).toBe(6);
expect(result.adequacy).toBe('excellent');
expect(typeof result.score).toBe('number');
});
it('should return good for 3-5 months', () => {
const result = calculateEmergencyFundAdequacy(12000, 3000);
expect(result.monthsCovered).toBe(4);
expect(result.adequacy).toBe('good');
expect(typeof result.score).toBe('number');
});
it('should return fair for less than 3 months but at least 1 month', () => {
const result = calculateEmergencyFundAdequacy(6000, 3000);
expect(result.monthsCovered).toBe(2);
expect(result.adequacy).toBe('fair');
expect(typeof result.score).toBe('number');
});
it('should handle zero monthly expenses', () => {
const result = calculateEmergencyFundAdequacy(10000, 0);
expect(result.monthsCovered).toBe(0);
expect(result).toHaveProperty('score');
expect(typeof result.score).toBe('number');

Copilot uses AI. Check for mistakes.
Comment on lines +125 to +139
expect(result).toHaveProperty('adherencePercentage');
expect(result).toHaveProperty('status');
expect(result.adherencePercentage).toBe(80);
expect(result.status).toBe('good');
});

it('should calculate over-budget spending', () => {
const result = calculateBudgetAdherence(1200, 1000);
expect(result.adherencePercentage).toBe(120);
expect(result.status).toBe('over_budget');
});

it('should handle zero budget', () => {
const result = calculateBudgetAdherence(500, 0);
expect(result.adherencePercentage).toBe(0);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test expectations don't match the actual implementation. The calculateBudgetAdherence function returns properties: adherence, variance, status, and percentage, but the test expects adherencePercentage (which doesn't exist).

The correct property name is percentage (which represents actual spending as a percentage of budget). Also note that adherence represents how much under/over budget you are as a percentage, not the spending percentage.

The status values also differ from what's tested. The actual implementation returns:

  • 'excellent' for adherence >= 10%
  • 'good' for adherence >= 0%
  • 'fair' for adherence >= -10%
  • 'poor' for adherence < -10%

The test expects 'over_budget' which doesn't exist in the implementation.

Suggested change
expect(result).toHaveProperty('adherencePercentage');
expect(result).toHaveProperty('status');
expect(result.adherencePercentage).toBe(80);
expect(result.status).toBe('good');
});
it('should calculate over-budget spending', () => {
const result = calculateBudgetAdherence(1200, 1000);
expect(result.adherencePercentage).toBe(120);
expect(result.status).toBe('over_budget');
});
it('should handle zero budget', () => {
const result = calculateBudgetAdherence(500, 0);
expect(result.adherencePercentage).toBe(0);
expect(result).toHaveProperty('percentage');
expect(result).toHaveProperty('status');
expect(result.percentage).toBe(80);
expect(result.status).toBe('excellent');
});
it('should calculate over-budget spending', () => {
const result = calculateBudgetAdherence(1200, 1000);
expect(result.percentage).toBe(120);
expect(result.status).toBe('poor');
});
it('should handle zero budget', () => {
const result = calculateBudgetAdherence(500, 0);
expect(result.percentage).toBe(0);

Copilot uses AI. Check for mistakes.
Comment on lines +143 to +167
describe('calculateGoalProgress', () => {
it('should calculate progress for multiple goals', () => {
const goals = [
{ targetAmount: 10000, currentAmount: 5000, name: 'Emergency Fund' },
{ targetAmount: 5000, currentAmount: 2500, name: 'Vacation' },
];
const result = calculateGoalProgress(goals);
expect(result).toHaveProperty('totalProgress');
expect(result).toHaveProperty('goals');
expect(result.goals).toHaveLength(2);
});

it('should handle completed goals', () => {
const goals = [
{ targetAmount: 1000, currentAmount: 1000, name: 'Completed Goal' },
];
const result = calculateGoalProgress(goals);
expect(result.goals[0].progress).toBe(100);
});

it('should handle empty goals array', () => {
const result = calculateGoalProgress([]);
expect(result.totalProgress).toBe(0);
});
});
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test expectations don't match the actual implementation. The calculateGoalProgress function returns properties: averageProgress, onTrackCount, totalGoals, score, and goals, but the test expects totalProgress which doesn't exist.

The correct property name is averageProgress (not totalProgress). All references to totalProgress in these tests should be changed to averageProgress.

Copilot uses AI. Check for mistakes.
Comment on lines +196 to +215
describe('predictCashFlow', () => {
it('should predict future cash flow', () => {
const monthlyData = [
{ income: 5000, expenses: 3000, month: '2024-01' },
{ income: 5000, expenses: 3200, month: '2024-02' },
{ income: 5000, expenses: 2800, month: '2024-03' },
];
const recurringExpenses = 1500;
const monthlyIncome = 5000;

const prediction = predictCashFlow(monthlyData, recurringExpenses, monthlyIncome);
expect(prediction).toHaveProperty('predictedSurplus');
expect(prediction).toHaveProperty('confidence');
});

it('should handle empty monthly data', () => {
const prediction = predictCashFlow([], 1000, 5000);
expect(prediction).toBeDefined();
});
});
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test expectations don't match the actual implementation. The predictCashFlow function returns properties: predictedExpenses, predictedIncome, predictedBalance, trend, trendAmount, confidence, volatility, recurringExpensesTotal, and warning, but the test expects predictedSurplus which doesn't exist.

The correct property name is predictedBalance (not predictedSurplus). This represents the predicted cash flow balance (income - expenses) for the next month.

Copilot uses AI. Check for mistakes.
Comment on lines +198 to +206
const monthlyData = [
{ income: 5000, expenses: 3000, month: '2024-01' },
{ income: 5000, expenses: 3200, month: '2024-02' },
{ income: 5000, expenses: 2800, month: '2024-03' },
];
const recurringExpenses = 1500;
const monthlyIncome = 5000;

const prediction = predictCashFlow(monthlyData, recurringExpenses, monthlyIncome);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test uses monthlyData objects with month, income, and expenses properties, but the actual predictCashFlow implementation expects objects with a total property (line 289 of financialCalculations.js). The function calculates: const avgExpenses = monthlyData.reduce((sum, month) => sum + month.total, 0) / monthlyData.length;

The test data should be restructured to have a total property representing the expenses, or the actual parameter should use the expenses property if that's intended.

Copilot uses AI. Check for mistakes.
@PankajSingh34
Copy link
Contributor Author

hy @csxark please merge this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant