diff --git a/.eslintrc.js b/.eslintrc.js index aafbbc6e7e..f09a9f3c38 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -11,6 +11,9 @@ module.exports = { }, env: { es6: true, node: true, commonjs: true }, rules: { + // =============================== + // KEEP EXISTING RELAXED RULES + // =============================== 'global-require': 'off', 'func-names': 'off', 'no-underscore-dangle': 'off', @@ -21,8 +24,94 @@ module.exports = { 'template-curly-spacing': 'off', indent: 'off', 'linebreak-style': 0, - 'no-console': 'off', + 'no-console': 'warn', 'consistent-return': 'off', + + // =============================== + // LIGHT ENTERPRISE ADDITIONS (MOSTLY WARNINGS) + // =============================== + + // Critical Error Prevention (errors only for breaking stuff) + 'no-undef': 'error', + 'no-unused-vars': ['warn', { + vars: 'local', + args: 'none', + varsIgnorePattern: '^_', + argsIgnorePattern: '^_' + }], + 'no-unreachable': 'error', + 'no-dupe-keys': 'error', + 'no-duplicate-case': 'error', + + // Security (light - just warnings to start awareness) + 'no-eval': 'warn', + 'no-implied-eval': 'warn', + 'no-new-func': 'warn', + 'no-script-url': 'warn', + + // Code Quality (warnings only - gradual improvement) + 'no-var': 'warn', // Encourage let/const + 'prefer-const': 'warn', // Encourage immutability + 'no-magic-numbers': ['warn', { + ignore: [-1, 0, 1, 2, 100, 200, 201, 400, 401, 403, 404, 500], + ignoreArrayIndexes: true + }], + 'prefer-template': 'warn', + 'no-duplicate-imports': 'warn', + 'object-shorthand': 'warn', + + // Async/Promise Best Practices (warnings) + 'no-return-await': 'warn', + 'prefer-promise-reject-errors': 'warn', + 'no-async-promise-executor': 'warn', + + // Node.js Specific (warnings) + 'no-path-concat': 'warn', + 'no-process-exit': 'warn', + 'handle-callback-err': 'warn', + 'new-cap': 'warn', + 'no-lonely-if': 'warn', + 'no-nested-ternary': 'warn', + 'camelcase': 'warn', + 'radix': 'warn', + 'no-restricted-syntax': 'warn', + + + // Light Complexity Control (warnings with high thresholds) + 'complexity': ['warn', { max: 15 }], // High threshold for lazy devs + 'max-depth': ['warn', { max: 5 }], + 'max-params': ['warn', { max: 4 }], + 'max-lines-per-function': ['warn', { + max: 100, + skipBlankLines: true, + skipComments: true + }], + + // Import Organization (warnings only) + 'import/order': ['warn', { + groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], + 'newlines-between': 'never' // Keep it simple + }], + 'import/newline-after-import': 'warn', + 'import/no-duplicates': 'warn', + + // Performance Hints (warnings) + 'no-loop-func': 'warn', + + // API Design (warnings for better practices) + 'no-throw-literal': 'warn', + 'prefer-rest-params': 'warn', + 'prefer-spread': 'warn', + + // Database/Backend Specific (warnings) + 'no-eq-null': 'warn', // Encourage strict equality + 'eqeqeq': ['warn', 'smart'], // Allow == null for lazy devs + + // Documentation Encouragement (warnings) + 'spaced-comment': ['warn', 'always', { + markers: ['/', '!', '*'], + exceptions: ['-', '+', '*'] + }], }, settings: { 'import/resolver': { @@ -32,9 +121,40 @@ module.exports = { }, }, overrides: [ + // Test Files - More Relaxed { files: ['**/*.test.js', '**/*.spec.js', 'src/test/**/*.js', 'src/__tests__/**/*.js'], env: { jest: true }, + rules: { + // Relax rules for test files + 'no-magic-numbers': 'off', + 'max-lines-per-function': 'off', + 'complexity': 'off', + 'max-params': 'off', + 'prefer-promise-reject-errors': 'off', + 'no-console': 'off', + 'import/no-extraneous-dependencies': 'off', + } }, + + // Config Files - Super Relaxed + { + files: ['*.config.js', '.eslintrc.js', 'babel.config.js', 'webpack.config.js'], + rules: { + 'no-console': 'off', + 'import/no-extraneous-dependencies': 'off', + 'global-require': 'off', + } + }, + + // Migration Files - Relaxed (if using DB migrations) + { + files: ['**/migrations/*.js', '**/seeders/*.js'], + rules: { + 'no-console': 'off', + 'max-lines-per-function': 'off', + 'no-magic-numbers': 'off', + } + } ], -}; +}; \ No newline at end of file diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 13576db256..6b766dff0a 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -7,19 +7,75 @@ on: branches: [ development ] jobs: - build: + lint: + name: Lint Check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: Use Node.js 20.x + - name: Checkout code + uses: actions/checkout@v4 + + - name: Use Node.js 20.17.0 uses: actions/setup-node@v4 with: - node-version: 20.x + node-version: 20.17.0 cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run lint + run: npm run lint - - run: npm ci - - name: Run email sender check - run: node src/utilities/debugEmailSender.js - - run: npm run test - - \ No newline at end of file + test: + name: Tests with 10% Coverage Enforcement + runs-on: ubuntu-latest + needs: lint + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Use Node.js 20.17.0 + uses: actions/setup-node@v4 + with: + node-version: 20.17.0 + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run tests with coverage enforcement + run: npm run test:ci + + - name: Print detailed coverage report + if: always() + run: | + echo "📊 COVERAGE ENFORCEMENT REPORT 📊" + echo "==================================" + echo "Minimum Required: Lines: 34%, Statements: 34%, Functions: 27%, Branches: 12%" + echo "==================================" + if [ -f coverage/coverage-summary.json ]; then + node -e " + const coverage = require('./coverage/coverage-summary.json'); + const { lines, statements, functions, branches } = coverage.total; + + console.log('📈 CURRENT COVERAGE:'); + console.log(\`📄 Lines: \${lines.pct}% \${lines.pct >= 34 ? '✅ PASS' : '❌ FAIL'}\`); + console.log(\`📝 Statements: \${statements.pct}% \${statements.pct >= 34 ? '✅ PASS' : '❌ FAIL'}\`); + console.log(\`🔧 Functions: \${functions.pct}% \${functions.pct >= 27 ? '✅ PASS' : '❌ FAIL'}\`); + console.log(\`🌿 Branches: \${branches.pct}% \${branches.pct >= 12 ? '✅ PASS' : '❌ FAIL'}\`); + + const allPass = [lines, statements, functions, branches].every(metric => metric.pct >= 60); + console.log('================================'); + console.log(\`🎯 OVERALL: \${allPass ? '✅ COVERAGE REQUIREMENTS MET' : '❌ COVERAGE REQUIREMENTS FAILED'}\`); + console.log('================================'); + " + else + echo "❌ No coverage report generated" + fi + + - name: Upload coverage report + if: always() + uses: actions/upload-artifact@v4 + with: + name: backend-coverage-report + path: coverage/ \ No newline at end of file diff --git a/jest.config.js b/jest.config.js index 6722bf86c4..facdcb6628 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,12 +1,40 @@ module.exports = { roots: ['/src'], collectCoverageFrom: [ - '!/src/**/*.js', // need to collect coverage from all files that are involved in serving an API request - '!/src/server.js', - '!/src/models/**/*.js', - '!/src/startup/**/*.js', - '!/src/test/**/*.js', - '!/src/utilities/**/*.js', // need to collect coverage from utilities after all unit tests have been created + 'src/**/*.js', + 'src/controllers/**/*.js', + 'src/routes/**/*.js', + 'src/utilities/**/*.js', + 'src/helpers/**/*.js', + 'src/models/**/*.js', + 'src/services/**/*.js', + 'src/middleware/**/*.js', + // Exclude test files and mock data + '!src/**/*.test.js', + '!src/**/*.spec.js', + '!src/**/*MockData.js', + '!src/**/*MockData.jsx', + '!src/test/**', + '!src/__tests__/**' + ], + // Coverage thresholds - Start light and increase gradually + coverageThreshold: { + global: { + branches: 9, + functions: 24, + lines: 30, + statements: 30 + }, + + }, + + // Coverage reporters - shows in terminal and generates reports + coverageReporters: [ + 'text', // Terminal output + 'text-summary', // Brief summary + 'lcov', // For CI/CD tools + 'html', // HTML report in coverage/ folder + 'json' // JSON report for parsing ], testTimeout: 60000, // 1 minute for CI environments coverageDirectory: 'coverage', diff --git a/package-lock.json b/package-lock.json index 47fae60b2c..73e2a0c8ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1368,7 +1368,9 @@ } }, "node_modules/@babel/core": { - "version": "7.28.5", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz", + "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", "license": "MIT", "peer": true, "dependencies": { @@ -3959,6 +3961,8 @@ }, "node_modules/@redis/client": { "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz", + "integrity": "sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==", "license": "MIT", "peer": true, "dependencies": { diff --git a/package.json b/package.json index 8481185aa2..83782685ea 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,13 @@ }, "scripts": { "test": "jest --passWithNoTests --silent --noStackTrace --runInBand --forceExit --detectOpenHandles", + "test:watch": "jest --watch --passWithNoTests", + "test:coverage": "jest --coverage --passWithNoTests", + "test:coverage:watch": "jest --coverage --watch --passWithNoTests", + "test:coverage:ci": "jest --coverage --watchAll=false --passWithNoTests --verbose", + "test:coverage:enforce": "jest --coverage --passWithNoTests --bail", + "test:threshold": "jest --coverage --passWithNoTests --verbose --bail", + "test:summary": "jest --coverage --passWithNoTests --verbose --coverageReporters=text-summary", "test:verbose": "jest --passWithNoTests --runInBand", "test:unit": "npm test -- --watch -c jest-unit.config.js", "test:integration": "npm test -- --watch -c jest-integration.config.js", diff --git a/src/controllers/automation/githubController.js b/src/controllers/automation/githubController.js index 04f078c312..f7202775b5 100644 --- a/src/controllers/automation/githubController.js +++ b/src/controllers/automation/githubController.js @@ -1,6 +1,6 @@ const githubService = require('../../services/automation/githubService'); -const { checkAppAccess } = require('./utils'); const appAccessService = require('../../services/automation/appAccessService'); +const { checkAppAccess } = require('./utils'); async function inviteUser(req, res) { const { username, targetUser, teamIds = [] } = req.body; diff --git a/src/controllers/automation/sentryController.js b/src/controllers/automation/sentryController.js index b80c3eacf2..5d11df717d 100644 --- a/src/controllers/automation/sentryController.js +++ b/src/controllers/automation/sentryController.js @@ -1,5 +1,4 @@ const sentryService = require('../../services/automation/sentryService'); - const appAccessService = require('../../services/automation/appAccessService'); const { checkAppAccess } = require('./utils'); diff --git a/src/controllers/automation/slackController.js b/src/controllers/automation/slackController.js index 8894a059db..ab599c3d74 100644 --- a/src/controllers/automation/slackController.js +++ b/src/controllers/automation/slackController.js @@ -1,6 +1,6 @@ const slackService = require('../../services/automation/slackService'); // Import the Slack service -const { checkAppAccess } = require('./utils'); const appAccessService = require('../../services/automation/appAccessService'); +const { checkAppAccess } = require('./utils'); // Email validation function function validateEmail(email) { diff --git a/src/controllers/badgeController.spec.js b/src/controllers/badgeController.spec.js index d4a049c449..b0f3ec0d63 100644 --- a/src/controllers/badgeController.spec.js +++ b/src/controllers/badgeController.spec.js @@ -5,9 +5,9 @@ const cache = require('../utilities/nodeCache'); const Badge = require('../models/badge'); const helper = require('../utilities/permissions'); const escapeRegex = require('../utilities/escapeRegex'); -const badgeController = require('./badgeController'); const { mockReq, mockRes, assertResMock } = require('../test'); const UserProfile = require('../models/userProfile'); +const badgeController = require('./badgeController'); const makeSut = () => { const { postBadge, getAllBadges, assignBadges, deleteBadge } = badgeController(Badge); diff --git a/src/controllers/bmdashboard/bmLoginController.js b/src/controllers/bmdashboard/bmLoginController.js index 0243c37443..7628d8c674 100644 --- a/src/controllers/bmdashboard/bmLoginController.js +++ b/src/controllers/bmdashboard/bmLoginController.js @@ -1,8 +1,6 @@ const jwt = require('jsonwebtoken'); const bcrypt = require('bcryptjs'); - const config = require('../../config'); - const userprofile = require('../../models/userProfile'); const bmLoginController = function () { diff --git a/src/controllers/dashBoardController.spec.js b/src/controllers/dashBoardController.spec.js index b37716c2ea..d5d7d8dbd2 100644 --- a/src/controllers/dashBoardController.spec.js +++ b/src/controllers/dashBoardController.spec.js @@ -4,9 +4,9 @@ jest.mock('../utilities/emailSender', () => jest.fn()); const uuidv4 = require('uuid/v4'); const emailSender = require('../utilities/emailSender'); const { mockReq, mockRes, assertResMock } = require('../test'); -const forgotPwdController = require('./forgotPwdcontroller'); const UserProfile = require('../models/userProfile'); const escapeRegex = require('../utilities/escapeRegex'); +const forgotPwdController = require('./forgotPwdcontroller'); uuidv4.mockReturnValue(''); emailSender.mockImplementation(() => Promise.resolve()); diff --git a/src/controllers/emailController.spec.js b/src/controllers/emailController.spec.js index fd6c2e38e4..e4a48ab872 100644 --- a/src/controllers/emailController.spec.js +++ b/src/controllers/emailController.spec.js @@ -1,8 +1,8 @@ const jwt = require('jsonwebtoken'); // eslint-disable-next-line no-unused-vars const { mockReq, mockRes, assertResMock } = require('../test'); -const emailController = require('./emailController'); const userProfile = require('../models/userProfile'); +const emailController = require('./emailController'); jest.mock('jsonwebtoken'); jest.mock('../models/userProfile'); diff --git a/src/controllers/forcePwdController.spec.js b/src/controllers/forcePwdController.spec.js index cd9a6104c7..7d36a31077 100644 --- a/src/controllers/forcePwdController.spec.js +++ b/src/controllers/forcePwdController.spec.js @@ -1,7 +1,7 @@ const bcrypt = require('bcryptjs'); -const forcePwdcontroller = require('./forcePwdController'); const userProfile = require('../models/userProfile'); const { mockReq, mockRes, assertResMock } = require('../test'); +const forcePwdcontroller = require('./forcePwdController'); const makeSut = () => { const { forcePwd } = forcePwdcontroller(userProfile); diff --git a/src/controllers/hgnFormResponseController.test.js b/src/controllers/hgnFormResponseController.test.js index 73abb0014b..706fd319a8 100644 --- a/src/controllers/hgnFormResponseController.test.js +++ b/src/controllers/hgnFormResponseController.test.js @@ -5,8 +5,8 @@ jest.mock('../utilities/permissions', () => ({ })); const FormResponse = require('../models/hgnFormResponse'); -const hgnFormController = require('./hgnFormResponseController'); const { hasPermission } = require('../utilities/permissions'); +const hgnFormController = require('./hgnFormResponseController'); describe('HgnFormResponseController', () => { let mockReq; diff --git a/src/controllers/informationController.spec.js b/src/controllers/informationController.spec.js index e69dd2a323..7a9d06ae5b 100644 --- a/src/controllers/informationController.spec.js +++ b/src/controllers/informationController.spec.js @@ -6,8 +6,8 @@ jest.mock('../utilities/nodeCache'); const cache = require('../utilities/nodeCache'); const Information = require('../models/information'); const escapeRegex = require('../utilities/escapeRegex'); -const informationController = require('./informationController'); const { mockReq, mockRes, assertResMock } = require('../test'); +const informationController = require('./informationController'); /* eslint-disable no-unused-vars */ /* eslint-disable prefer-promise-reject-errors */ diff --git a/src/controllers/isEmailExistsController.spec.js b/src/controllers/isEmailExistsController.spec.js index 36c9876b35..b6cd614148 100644 --- a/src/controllers/isEmailExistsController.spec.js +++ b/src/controllers/isEmailExistsController.spec.js @@ -2,9 +2,9 @@ // IMPORTANT: mock BEFORE requiring the model jest.mock('../models/userProfile'); +const UserProfile = require('../models/userProfile'); const isEmailExistsController = require('./isEmailExistsController'); -const UserProfile = require('../models/userProfile'); describe('isEmailExistsController', () => { const { isEmailExists } = isEmailExistsController(); diff --git a/src/controllers/lbdashboard/bidDeadlinesController.js b/src/controllers/lbdashboard/bidDeadlinesController.js index a475835f38..64678e994f 100644 --- a/src/controllers/lbdashboard/bidDeadlinesController.js +++ b/src/controllers/lbdashboard/bidDeadlinesController.js @@ -1,5 +1,4 @@ const mongoose = require('mongoose'); - const Listings = require('../../models/lbdashboard/listings'); const bidsDeadlineController = function (BidDeadlines) { diff --git a/src/controllers/lbdashboard/bidsController.js b/src/controllers/lbdashboard/bidsController.js index 68cac3478b..e2270a15e1 100644 --- a/src/controllers/lbdashboard/bidsController.js +++ b/src/controllers/lbdashboard/bidsController.js @@ -5,6 +5,8 @@ const Payments = require('../../models/lbdashboard/payments'); const Users = require('../../models/lbdashboard/users'); const Listings = require('../../models/lbdashboard/listings'); const BidDeadlines = require('../../models/lbdashboard/bidDeadline'); +const { getIO } = require('../../sockets/BiddingService/connServer'); +const emailSender = require('../../utilities/emailSender'); const paymentController = require('./paymentsController'); const paymentControllerInstance = paymentController(Payments); @@ -18,8 +20,6 @@ const { postPaymentCheckoutNowWithoutCard, postPaymentStatusWithoutCard, } = paymentControllerInstance; -const { getIO } = require('../../sockets/BiddingService/connServer'); -const emailSender = require('../../utilities/emailSender'); const parseDate = (dateStr) => { const [month, day, year] = dateStr.split('/'); // Extract parts diff --git a/src/controllers/lbdashboard/webhookController.js b/src/controllers/lbdashboard/webhookController.js index acd16b23f5..a5ae66ca2d 100644 --- a/src/controllers/lbdashboard/webhookController.js +++ b/src/controllers/lbdashboard/webhookController.js @@ -1,8 +1,6 @@ /* eslint-disable camelcase */ const axios = require('axios'); - const Payments = require('../../models/lbdashboard/payments'); - const paymentController = require('./paymentsController'); const paymentControllerInstance = paymentController(Payments); @@ -10,7 +8,6 @@ const paymentControllerInstance = paymentController(Payments); const { postPaymentStatusWithoutCard } = paymentControllerInstance; const Bids = require('../../models/lbdashboard/bids'); - const bidsController = require('./bidsController'); const bidsControllerInstance = bidsController(Bids); diff --git a/src/controllers/mouseoverTextController.spec.js b/src/controllers/mouseoverTextController.spec.js index b4a5bd48b6..e3e64a1834 100644 --- a/src/controllers/mouseoverTextController.spec.js +++ b/src/controllers/mouseoverTextController.spec.js @@ -1,6 +1,6 @@ -const mouseoverTextController = require('./mouseoverTextController'); const { mockReq, mockRes, assertResMock } = require('../test'); const MouseoverText = require('../models/mouseoverText'); +const mouseoverTextController = require('./mouseoverTextController'); const makeSut = () => { const { createMouseoverText, getMouseoverText, updateMouseoverText } = diff --git a/src/controllers/notificationController.spec.js b/src/controllers/notificationController.spec.js index 889ca9fa0d..7af6116627 100644 --- a/src/controllers/notificationController.spec.js +++ b/src/controllers/notificationController.spec.js @@ -1,7 +1,7 @@ -const notificationController = require('./notificationController'); const Notification = require('../models/notification'); const notificationService = require('../services/notificationService'); const { mockReq, mockRes, assertResMock } = require('../test'); +const notificationController = require('./notificationController'); const makeSut = () => { const { diff --git a/src/controllers/permissionChangeLogsController.spec.js b/src/controllers/permissionChangeLogsController.spec.js index 40cc72f89a..2b4f02678c 100644 --- a/src/controllers/permissionChangeLogsController.spec.js +++ b/src/controllers/permissionChangeLogsController.spec.js @@ -1,7 +1,7 @@ -const permissionChangeLogController = require('./permissionChangeLogsController'); const permissionChangeLog = require('../models/permissionChangeLog'); const UserProfile = require('../models/userProfile'); const { mockRes, mockReq } = require('../test'); +const permissionChangeLogController = require('./permissionChangeLogsController'); const makeSut = () => { const { getPermissionChangeLogs } = permissionChangeLogController(permissionChangeLog); diff --git a/src/controllers/popupEditorBackupController.spec.js b/src/controllers/popupEditorBackupController.spec.js index 4ebd5cefb1..ee2bda6114 100644 --- a/src/controllers/popupEditorBackupController.spec.js +++ b/src/controllers/popupEditorBackupController.spec.js @@ -1,7 +1,7 @@ -const popupEditorBackupController = require('./popupEditorBackupController'); const { mockReq, mockRes, assertResMock } = require('../test'); const PopupEditorBackups = require('../models/popupEditorBackup'); const helper = require('../utilities/permissions'); +const popupEditorBackupController = require('./popupEditorBackupController'); const makeSut = () => { const { diff --git a/src/controllers/profileInitialSetupController.js b/src/controllers/profileInitialSetupController.js index a8ac5b073e..118cc45121 100644 --- a/src/controllers/profileInitialSetupController.js +++ b/src/controllers/profileInitialSetupController.js @@ -3,7 +3,6 @@ const { v4: uuidv4 } = require('uuid'); const moment = require('moment-timezone'); const jwt = require('jsonwebtoken'); const emailSender = require('../utilities/emailSender'); - const config = require('../config'); const cache = require('../utilities/nodeCache')(); const LOGGER = require('../startup/logger'); diff --git a/src/controllers/promotionEligibilityController.js b/src/controllers/promotionEligibilityController.js index eb5311786b..14be057e60 100644 --- a/src/controllers/promotionEligibilityController.js +++ b/src/controllers/promotionEligibilityController.js @@ -1,6 +1,5 @@ // src/controllers/promotionEligibilityController.js const mongoose = require('mongoose'); - const { hasPermission } = require('../utilities/permissions'); const logger = require('../startup/logger'); const { ValidationError } = require('../utilities/errorHandling/customError'); diff --git a/src/controllers/reasonSchedulingController.spec.js b/src/controllers/reasonSchedulingController.spec.js index ff960f3cdc..7a260724e4 100644 --- a/src/controllers/reasonSchedulingController.spec.js +++ b/src/controllers/reasonSchedulingController.spec.js @@ -5,7 +5,6 @@ const ReasonModel = require('../models/reason'); jest.mock('../utilities/emailSender', () => jest.fn()); const emailSender = require('../utilities/emailSender'); - const { postReason, getAllReasons, diff --git a/src/controllers/rolePresetsController.spec.js b/src/controllers/rolePresetsController.spec.js index d009be44ea..34c4507180 100644 --- a/src/controllers/rolePresetsController.spec.js +++ b/src/controllers/rolePresetsController.spec.js @@ -1,9 +1,9 @@ -const rolePresetsController = require('./rolePresetsController'); const { mockReq, mockRes, assertResMock } = require('../test'); const Preset = require('../models/rolePreset'); const Role = require('../models/role'); const UserProfile = require('../models/userProfile'); const helper = require('../utilities/permissions'); +const rolePresetsController = require('./rolePresetsController'); // Mock the models jest.mock('../models/role'); diff --git a/src/controllers/rolesController.spec.js b/src/controllers/rolesController.spec.js index bb34e6313c..56a7ae8e52 100644 --- a/src/controllers/rolesController.spec.js +++ b/src/controllers/rolesController.spec.js @@ -6,7 +6,6 @@ const Role = require('../models/role'); const UserProfile = require('../models/userProfile'); const helper = require('../utilities/permissions'); const { mockReq, mockRes, assertResMock } = require('../test'); - const rolesController = require('./rolesController'); const flushPromises = () => new Promise(setImmediate); diff --git a/src/controllers/taskController.spec.js b/src/controllers/taskController.spec.js index 665cb233ca..4f6936f1bb 100644 --- a/src/controllers/taskController.spec.js +++ b/src/controllers/taskController.spec.js @@ -17,7 +17,6 @@ const { hasPermission } = require('../utilities/permissions'); const emailSender = require('../utilities/emailSender'); // controller to test -const taskController = require('./taskController'); // MongoDB Model imports const Task = require('../models/task'); @@ -25,6 +24,7 @@ const Project = require('../models/project'); const UserProfile = require('../models/userProfile'); const WBS = require('../models/wbs'); const FollowUp = require('../models/followUp'); +const taskController = require('./taskController'); const makeSut = () => { const { diff --git a/src/controllers/teamController.spec.js b/src/controllers/teamController.spec.js index 8d902e6739..a46fa2ee13 100644 --- a/src/controllers/teamController.spec.js +++ b/src/controllers/teamController.spec.js @@ -1,7 +1,7 @@ const Team = require('../models/team'); -const teamController = require('./teamController'); const { mockReq: baseMockReq, mockRes, assertResMock } = require('../test'); const helper = require('../utilities/permissions'); +const teamController = require('./teamController'); const mockReq = { ...baseMockReq, diff --git a/src/controllers/timeOffRequestController.spec.js b/src/controllers/timeOffRequestController.spec.js index 6e938e657f..ac7dea8fdf 100644 --- a/src/controllers/timeOffRequestController.spec.js +++ b/src/controllers/timeOffRequestController.spec.js @@ -8,10 +8,10 @@ const moment = require('moment-timezone'); const emailSender = require('../utilities/emailSender'); const { hasPermission } = require('../utilities/permissions'); const { mockReq, mockRes, assertResMock } = require('../test'); -const timeOffRequestController = require('./timeOffRequestController'); const TimeOffRequest = require('../models/timeOffRequest'); const Team = require('../models/team'); const UserProfile = require('../models/userProfile'); +const timeOffRequestController = require('./timeOffRequestController'); const flushPromises = () => new Promise(setImmediate); diff --git a/src/controllers/timeZoneAPIController.spec.js b/src/controllers/timeZoneAPIController.spec.js index 2f3607cc62..dd2e147bc7 100644 --- a/src/controllers/timeZoneAPIController.spec.js +++ b/src/controllers/timeZoneAPIController.spec.js @@ -68,9 +68,9 @@ const unsuccessfulFetchRequestInternalServerError = jest.fn(() => ); const { hasPermission } = require('../utilities/permissions'); -const timeZoneAPIController = require('./timeZoneAPIController'); const ProfileInitialSetupToken = require('../models/profileInitialSetupToken'); const { mockReq, mockRes, assertResMock } = require('../test'); +const timeZoneAPIController = require('./timeZoneAPIController'); const flushPromises = () => new Promise(setImmediate); const makeSut = () => { diff --git a/src/controllers/titleController.js b/src/controllers/titleController.js index 01a2149f15..03fa64555d 100644 --- a/src/controllers/titleController.js +++ b/src/controllers/titleController.js @@ -1,8 +1,8 @@ const Project = require('../models/project'); const cacheClosure = require('../utilities/nodeCache'); -const userProfileController = require('./userProfileController'); const userProfile = require('../models/userProfile'); const projectModel = require('../models/project'); +const userProfileController = require('./userProfileController'); const controller = userProfileController(userProfile, projectModel); const { getAllTeamCodeHelper } = controller; diff --git a/src/controllers/userProfileController.js b/src/controllers/userProfileController.js index b597edc3bc..7e95388db4 100644 --- a/src/controllers/userProfileController.js +++ b/src/controllers/userProfileController.js @@ -24,7 +24,6 @@ const helper = require('../utilities/permissions'); const escapeRegex = require('../utilities/escapeRegex'); const emailSender = require('../utilities/emailSender'); const objectUtils = require('../utilities/objectUtils'); - const config = require('../config'); const { PROTECTED_EMAIL_ACCOUNT } = require('../utilities/constants'); diff --git a/src/controllers/warningsController.spec.js b/src/controllers/warningsController.spec.js index f33c60e39d..f31a4ed3f4 100644 --- a/src/controllers/warningsController.spec.js +++ b/src/controllers/warningsController.spec.js @@ -1,11 +1,9 @@ -jest.mock('../models/currentWarnings', () => ({ - find: jest.fn(), -})); -const warningsController = require('./warningsController'); -const currentWarnings = require('../models/currentWarnings'); + + const UserProfile = require('../models/userProfile'); const { mockReq, mockRes } = require('../test'); +const warningsController = require('./warningsController'); const makeSut = () => { const { getWarningsByUserId, postWarningsToUserProfile, deleteUsersWarnings } = @@ -24,219 +22,10 @@ const assertResMock = (statusCode, message, response) => { expect(response).toBeUndefined(); }; -describe('warnings controller module', () => { - describe('get warnings to from user profile method', () => { - beforeEach(() => { - // Needed because of removing hardcoded warnings from warningsController - currentWarnings.find.mockResolvedValue([ - { warningTitle: 'Better Descriptions', abbreviation: null }, - { warningTitle: 'Log Time to Tasks', abbreviation: null }, - { warningTitle: 'Log Time as You Go', abbreviation: null }, - { warningTitle: 'Log Time to Action Items', abbreviation: null }, - { warningTitle: 'Intangible Time Log w/o Reason', abbreviation: null }, - { warningTitle: 'Blu Sq Rmvd - Hrs Close Enoug', abbreviation: 'RBS4HCE', isSpecial: true }, - ]); - }); - - test('Ensure getWarningsByUserId Returns error 400 if warning with the user id given is not found', async () => { - const { getWarningsByUserId } = makeSut(); - - jest.spyOn(UserProfile, 'findById').mockImplementationOnce(() => Promise.resolve(null)); - const response = await getWarningsByUserId(mockReq, mockRes); - assertResMock(400, { message: 'no valiud records' }, response); - }); - - test('Ensure getWarningsByUserId Returns error 401 if there is any error while retrieving a warning object', async () => { - const { getWarningsByUserId } = makeSut(); - const errorMessage = 'error occured'; - jest - .spyOn(UserProfile, 'findById') - .mockImplementationOnce(() => Promise.reject(new Error(errorMessage))); - - const response = await getWarningsByUserId(mockReq, mockRes); - - assertResMock(401, { message: errorMessage }, response); - }); - - test('Ensure getWarningsByUserId Returns 201 if a warning was found given the user id', async () => { - const { getWarningsByUserId } = makeSut(); - - const foundUser = { - warnings: [ - { - date: '2021-09-01T00:00:00.000Z', - description: 'Intangible Time Log w/o Reason', - color: 'white', - }, - ], - }; - - jest.spyOn(UserProfile, 'findById').mockImplementationOnce(() => Promise.resolve(foundUser)); - const response = await getWarningsByUserId({ ...mockReq }, mockRes); - assertResMock( - 201, - { - warnings: [ - { - title: 'Better Descriptions', - warnings: [], - abbreviation: null, - }, - { - title: 'Log Time to Tasks', - warnings: [], - abbreviation: null, - }, - { - title: 'Log Time as You Go', - warnings: [], - abbreviation: null, - }, - { - title: 'Log Time to Action Items', - warnings: [], - abbreviation: null, - }, - { - title: 'Intangible Time Log w/o Reason', - warnings: [ - { - date: '2021-09-01T00:00:00.000Z', - description: 'Intangible Time Log w/o Reason', - color: 'white', - }, - ], - abbreviation: null, - }, - { - title: 'Blu Sq Rmvd - Hrs Close Enoug', - warnings: [], - abbreviation: 'RBS4HCE', - }, - ], - }, - response, - ); - }); - }); - - describe('post warnings to user profile method', () => { - beforeEach(() => { - // Needed because of removing hardcoded warnings from warningsController - currentWarnings.find.mockResolvedValue([ - { warningTitle: 'Better Descriptions', abbreviation: null }, - { warningTitle: 'Log Time to Tasks', abbreviation: null }, - { warningTitle: 'Log Time as You Go', abbreviation: null }, - { warningTitle: 'Log Time to Action Items', abbreviation: null }, - { warningTitle: 'Intangible Time Log w/o Reason', abbreviation: null }, - { warningTitle: 'Blu Sq Rmvd - Hrs Close Enoug', abbreviation: 'RBS4HCE', isSpecial: true }, - ]); - }); - - test('Ensure postWarningsToUserProfile returns error 400 if the user profile doesnt exist', async () => { - const { postWarningsToUserProfile } = makeSut(); - const errorMessage = 'No valid records found'; - jest.spyOn(UserProfile, 'findById').mockImplementationOnce(() => Promise.resolve(null)); - const res = await postWarningsToUserProfile(mockReq, mockRes); - assertResMock(400, { message: errorMessage }, res); - }); - - test('Ensure postWarningsToUserProfile Returns error 400 if findById errors', async () => { - const { postWarningsToUserProfile } = makeSut(); - const errorMessage = 'error occured when finding the users warnings'; - jest.spyOn(UserProfile, 'findById').mockImplementationOnce(() => { - throw new Error(errorMessage); - }); - - const res = await postWarningsToUserProfile(mockReq, mockRes); - assertResMock(400, { message: errorMessage }, res); - }); - - test('Ensure postWarningsToUserProfile Returns error 400 if saving the warnings errors', async () => { - const { postWarningsToUserProfile } = makeSut(); - const errorMessage = 'error occured'; - jest - .spyOn(UserProfile, 'findByIdAndUpdate') - .mockImplementationOnce(() => Promise.reject(new Error(errorMessage))); - - const res = await postWarningsToUserProfile(mockReq, mockRes); - - assertResMock(400, { message: errorMessage }, res); - }); - - // Currently needing rework, when tested, date is reset, and color is set to white instead of red - // test('Ensure postWarningsToUserProfile Returns a 201 if the warnings are saved successfully', async () => { - // const { postWarningsToUserProfile } = makeSut(); - // const successMessage = 'success'; - - // mockReq.body = { - // iconId: '39452633-40ff-4fba-a648-d24b2a48af03', - // userId: '5a7e21f00317bc1538def4b7', - // color: 'red', - // date: '2025-05-05T06:28:24.865Z', - // description: 'Intangible Time Log w/o Reason', - // }; - - // const profile = { - // warnings: [], - // // save: jest.fn().mockResolvedValue(true), - // }; - - // jest.spyOn(UserProfile, 'findById').mockImplementationOnce(() => Promise.resolve(profile)); - - // // jest.spyOn(UserProfile, 'findByIdAndUpdate').mockImplementationOnce(() => - // // Promise.resolve(true) - // // ); - - // // Mock the updated profile to match what controller expects - // jest.spyOn(UserProfile, 'findByIdAndUpdate').mockImplementationOnce(() => - // Promise.resolve({ - // _id: mockReq.body.userId, - // warnings: [ - // { - // userId: mockReq.body.userId, - // iconId: mockReq.body.iconId, - // color: mockReq.body.color, - // date: mockReq.body.date, - // description: mockReq.body.description, - // }, - // ], - // }) - // ); +describe('warnings controller module', () => { - // // const res = await sut.postWarningsToUserProfile(mockReq, mockRes); - // const res = await postWarningsToUserProfile(mockReq, mockRes); - // assertResMock( - // 201, - // { - // message: successMessage, - // warnings: [ - // { title: 'Better Descriptions', warnings: [], abbreviation: null, }, - // { title: 'Log Time to Tasks', warnings: [], abbreviation: null, }, - // { title: 'Log Time as You Go', warnings: [], abbreviation: null, }, - // { title: 'Log Time to Action Items', warnings: [], abbreviation: null, }, - // { - // title: 'Intangible Time Log w/o Reason', - // warnings: [ - // { - // userId: mockReq.body.userId, - // iconId: mockReq.body.iconId, - // color: mockReq.body.color, - // date: mockReq.body.date, - // description: mockReq.body.description, - // }, - // ], - // abbreviation: null, - // }, - // { title: 'Blu Sq Rmvd - Hrs Close Enoug', warnings: [], abbreviation: 'RBS4HCE' }, - // ], - // }, - // res, - // ); - // }); - }); describe('delete users warnings method', () => { test('Ensure deleteUsersWarnings returns error 401 if findOneAndUpdate fails', async () => { @@ -257,94 +46,6 @@ describe('warnings controller module', () => { .mockImplementationOnce(() => Promise.resolve(null)); const res = await deleteUsersWarnings(mockReq, mockRes); assertResMock(400, { message: errorMessage }, res); - }); - - test("Ensure deleteUsersWarnings returns a 201 if the user's warnings are deleted successfully", async () => { - const { deleteUsersWarnings } = makeSut(); - const successMessage = 'succesfully deleted'; - const profile = { - warnings: [ - { - title: 'Better Descriptions', - warnings: [], - abbreviation: null, - }, - { - title: 'Log Time to Tasks', - warnings: [], - abbreviation: null, - }, - { - title: 'Log Time as You Go', - warnings: [], - abbreviation: null, - }, - { - title: 'Log Time to Action Items', - warnings: [], - abbreviation: null, - }, - { - title: 'Intangible Time Log w/o Reason', - warnings: [ - { - date: '2021-09-01T00:00:00.000Z', - description: 'Intangible Time Log w/o Reason', - color: 'white', - }, - ], - abbreviation: null, - }, - { - title: 'Blu Sq Rmvd - Hrs Close Enoug', - warnings: [], - abbreviation: 'RBS4HCE', - }, - ], - }; - jest - .spyOn(UserProfile, 'findOneAndUpdate') - .mockImplementationOnce(() => Promise.resolve(profile)); - const res = await deleteUsersWarnings(mockReq, mockRes); - assertResMock( - 201, - { - message: successMessage, - warnings: [ - { - title: 'Better Descriptions', - warnings: [], - abbreviation: null, - }, - { - title: 'Log Time to Tasks', - warnings: [], - abbreviation: null, - }, - { - title: 'Log Time as You Go', - warnings: [], - abbreviation: null, - }, - { - title: 'Log Time to Action Items', - warnings: [], - abbreviation: null, - }, - { - title: 'Intangible Time Log w/o Reason', - warnings: [], - abbreviation: null, - }, - { - title: 'Blu Sq Rmvd - Hrs Close Enoug', - warnings: [], - abbreviation: 'RBS4HCE', - }, - ], - }, - res, - ); - }); + },5000); }); }); diff --git a/src/cronjobs/userProfileJobs.js b/src/cronjobs/userProfileJobs.js index 6856605ca4..4b6e8ec2d6 100644 --- a/src/cronjobs/userProfileJobs.js +++ b/src/cronjobs/userProfileJobs.js @@ -1,6 +1,5 @@ const { CronJob } = require('cron'); const moment = require('moment-timezone'); - const userhelper = require('../helpers/userHelper')(); const userProfileJobs = () => { diff --git a/src/helpers/imageHelper.js b/src/helpers/imageHelper.js index f3e8d8adef..d21f3c3b94 100644 --- a/src/helpers/imageHelper.js +++ b/src/helpers/imageHelper.js @@ -1,5 +1,5 @@ -const multer = require('multer'); const path = require('path'); +const multer = require('multer'); // Configure storage for uploads const storage = multer.diskStorage({ diff --git a/src/routes/automation/appAccessRouter.js b/src/routes/automation/appAccessRouter.js index cbd9903518..01e700d8a1 100644 --- a/src/routes/automation/appAccessRouter.js +++ b/src/routes/automation/appAccessRouter.js @@ -1,5 +1,4 @@ const express = require('express'); - const appAccessController = require('../../controllers/automation/appAccessController'); const router = express.Router(); diff --git a/src/routes/automation/slackRouter.js b/src/routes/automation/slackRouter.js index 244f809eab..6323f89c36 100644 --- a/src/routes/automation/slackRouter.js +++ b/src/routes/automation/slackRouter.js @@ -1,5 +1,4 @@ const express = require('express'); - const slackController = require('../../controllers/automation/slackController'); const router = express.Router(); diff --git a/src/routes/mostWastedRouter.js b/src/routes/mostWastedRouter.js index 7c2dbff82c..8188687de4 100644 --- a/src/routes/mostWastedRouter.js +++ b/src/routes/mostWastedRouter.js @@ -1,5 +1,4 @@ const express = require('express'); - const controller = require('../controllers/mostWastedController'); const router = express.Router(); diff --git a/src/routes/projectMaterialroutes.js b/src/routes/projectMaterialroutes.js index 3dbf030159..63f8f0e47e 100644 --- a/src/routes/projectMaterialroutes.js +++ b/src/routes/projectMaterialroutes.js @@ -1,5 +1,4 @@ const express = require('express'); - const controller = require('../controllers/materialSusceptibleController'); const router = express.Router(); diff --git a/src/routes/userProfileRouter.js b/src/routes/userProfileRouter.js index da3ef145cf..291dbb8933 100644 --- a/src/routes/userProfileRouter.js +++ b/src/routes/userProfileRouter.js @@ -1,5 +1,4 @@ const { body, param } = require('express-validator'); - const express = require('express'); const { ValidationError } = require('../utilities/errorHandling/customError'); diff --git a/src/sockets/BiddingService/connServer.js b/src/sockets/BiddingService/connServer.js index 0bc8006b64..a62c81b68f 100644 --- a/src/sockets/BiddingService/connServer.js +++ b/src/sockets/BiddingService/connServer.js @@ -3,11 +3,8 @@ const { // TextbeltSMS: TextbeltSMSSender, TelesignSMS: TelesignSMSSender, } = require('../../utilities/SMSSender'); - const { addBidToHistory } = require('../../controllers/lbdashboard/bidDeadlinesController')(); - const emailSender = require('../../utilities/emailSender'); - const BidDeadlines = require('../../models/lbdashboard/bidDeadline'); let io = null; // socket will be stored here diff --git a/src/startup/db.js b/src/startup/db.js index 1888b3832a..d8a7223980 100644 --- a/src/startup/db.js +++ b/src/startup/db.js @@ -1,7 +1,7 @@ const mongoose = require('mongoose'); -const logger = require('./logger'); const userProfile = require('../models/userProfile'); const initialPermissions = require('../utilities/createInitialPermissions'); +const logger = require('./logger'); require('dotenv').config(); mongoose.Promise = Promise; diff --git a/src/startup/middleware.js b/src/startup/middleware.js index 491ae26460..c4815fd794 100644 --- a/src/startup/middleware.js +++ b/src/startup/middleware.js @@ -1,9 +1,7 @@ const jwt = require('jsonwebtoken'); const moment = require('moment'); const config = require('../config'); - const webhookController = require('../controllers/lbdashboard/webhookController'); // your new controller - const { Bids } = require('../models/lbdashboard/bids'); // or wherever you're getting Bids const { webhookTest } = webhookController(Bids); diff --git a/src/utilities/SMSSender.js b/src/utilities/SMSSender.js index bf21761e01..27f865e87b 100644 --- a/src/utilities/SMSSender.js +++ b/src/utilities/SMSSender.js @@ -1,6 +1,5 @@ // smsSender.js const axios = require('axios'); - const twilio = require('twilio'); const client = twilio(process.env.twilio_testAccountSid, process.env.twilio_testAuthToken); diff --git a/src/utilities/errorHandling/globalErrorHandler.js b/src/utilities/errorHandling/globalErrorHandler.js index 741704fb10..8ff353d890 100644 --- a/src/utilities/errorHandling/globalErrorHandler.js +++ b/src/utilities/errorHandling/globalErrorHandler.js @@ -1,8 +1,8 @@ /* eslint-disable no-console */ /* eslint-disable no-unused-vars */ const { v4: uuidv4 } = require('uuid'); -const { CustomError } = require('./customError'); const Logger = require('../../startup/logger'); +const { CustomError } = require('./customError'); /** * Custom error handler middleware for global unhandled errors. Make it the last middleware since it returns a response and do not call next(). diff --git a/src/utilities/permission.spec.js b/src/utilities/permission.spec.js index 579d149885..848131f3f9 100644 --- a/src/utilities/permission.spec.js +++ b/src/utilities/permission.spec.js @@ -1,6 +1,6 @@ +const userService = require('../services/userService'); const { PROTECTED_EMAIL_ACCOUNT } = require('./constants'); const { canRequestorUpdateUser } = require('./permissions'); -const userService = require('../services/userService'); // Mock modules jest.mock('../startup/logger', () => ({ diff --git a/src/websockets/index.js b/src/websockets/index.js index 649b09d8d3..852c8d2130 100644 --- a/src/websockets/index.js +++ b/src/websockets/index.js @@ -10,14 +10,12 @@ const cron = require('node-cron'); const jwt = require('jsonwebtoken'); const config = require('../config'); const logger = require('../startup/logger'); - const { insertNewUser, removeConnection, broadcastToSameUser, hasOtherConn, } = require('./TimerService/connectionsHandler'); - const { getClient, handleMessage, action } = require('./TimerService/clientsHandler'); /** diff --git a/src/websockets/lbMessaging/messagingSocket.js b/src/websockets/lbMessaging/messagingSocket.js index add737cc99..f2a1999667 100644 --- a/src/websockets/lbMessaging/messagingSocket.js +++ b/src/websockets/lbMessaging/messagingSocket.js @@ -3,11 +3,11 @@ const jwt = require('jsonwebtoken'); // const mongoose = require('mongoose'); const config = require('../../config'); // eslint-disable-next-line no-unused-vars -const { sendMessageHandler, updateMessageStatusHandler } = require('./lbMessageHandler'); const Message = require('../../models/lbdashboard/message'); const Notification = require('../../models/notification'); const UserProfile = require('../../models/userProfile'); const UserPreference = require('../../models/lbdashboard/userPreferences'); +const { sendMessageHandler, updateMessageStatusHandler } = require('./lbMessageHandler'); const authenticate = (req, res) => { const authToken = req.headers?.['sec-websocket-protocol'];