Spaces:
Paused
Paused
Download __tests__/unit/utils.test.js from imkrish/campverse-backend: direct link, hf CLI and curl.
- Browser
- Download file 12.8 kB
-
https://huggingface.co/spaces/imkrish/campverse-backend/resolve/main/__tests__/unit/utils.test.js
- Command line
-
hf download hf://spaces/imkrish/campverse-backend/__tests__/unit/utils.test.js
-
curl -L -o utils.test.js https://huggingface.co/spaces/imkrish/campverse-backend/resolve/main/__tests__/unit/utils.test.js
12.8 kB
| // Utility Functions Unit Tests | |
| const crypto = require('crypto'); | |
| describe('Utility Functions Unit Tests', () => { | |
| describe('Email Validation', () => { | |
| it('should validate academic email domains', () => { | |
| const isAcademicEmail = (email) => { | |
| return ( | |
| /@[\w.-]+\.(ac|edu)\.in$/i.test(email) || | |
| /@[\w.-]+\.edu$/i.test(email) | |
| ); | |
| }; | |
| // Valid academic emails | |
| expect(isAcademicEmail('student@university.edu')).toBe(true); | |
| expect(isAcademicEmail('user@college.ac.in')).toBe(true); | |
| expect(isAcademicEmail('test@institute.edu.in')).toBe(true); | |
| expect(isAcademicEmail('admin@university.ac.in')).toBe(true); | |
| // Invalid academic emails | |
| expect(isAcademicEmail('user@gmail.com')).toBe(false); | |
| expect(isAcademicEmail('test@yahoo.com')).toBe(false); | |
| expect(isAcademicEmail('admin@company.com')).toBe(false); | |
| expect(isAcademicEmail('student@university.org')).toBe(false); | |
| }); | |
| it('should extract domain from email', () => { | |
| const extractDomain = (email) => { | |
| return email.split('@')[1].toLowerCase(); | |
| }; | |
| expect(extractDomain('user@example.com')).toBe('example.com'); | |
| expect(extractDomain('test@university.edu')).toBe('university.edu'); | |
| expect(extractDomain('admin@company.co.in')).toBe('company.co.in'); | |
| }); | |
| }); | |
| describe('Password Security', () => { | |
| it('should validate password strength', () => { | |
| const { validatePassword } = require('../../Utils/passwordUtils'); | |
| // Strong passwords - must have uppercase, lowercase, number, and special char | |
| expect(validatePassword('Password123!')).toBe(true); | |
| expect(validatePassword('MyPass1@')).toBe(true); | |
| expect(validatePassword('Secure123$')).toBe(true); | |
| expect(validatePassword('#B2ec402ac')).toBe(true); // # is now allowed | |
| expect(validatePassword('Test123#hash')).toBe(true); // # special char | |
| expect(validatePassword('MyPass1()')).toBe(true); // parentheses allowed | |
| expect(validatePassword('Secure1-test')).toBe(true); // hyphen allowed | |
| // Weak passwords | |
| expect(validatePassword('pass')).toBe(false); // too short | |
| expect(validatePassword('password')).toBe(false); // no uppercase, number, or special char | |
| expect(validatePassword('Password')).toBe(false); // no number or special char | |
| expect(validatePassword('Password123')).toBe(false); // no special char | |
| expect(validatePassword('123456')).toBe(false); // no letters | |
| expect(validatePassword('')).toBe(false); // empty | |
| }); | |
| it('should generate secure random strings', () => { | |
| const generateRandomString = (length) => { | |
| return crypto.randomBytes(length).toString('hex'); | |
| }; | |
| const result1 = generateRandomString(16); | |
| const result2 = generateRandomString(16); | |
| expect(result1).toHaveLength(32); // 16 bytes = 32 hex chars | |
| expect(result2).toHaveLength(32); | |
| expect(result1).not.toBe(result2); // should be different | |
| }); | |
| }); | |
| describe('Date and Time Utilities', () => { | |
| it('should check if date is in the future', () => { | |
| const isFutureDate = (date) => { | |
| return new Date(date) > new Date(); | |
| }; | |
| const futureDate = new Date(); | |
| futureDate.setDate(futureDate.getDate() + 1); | |
| const pastDate = new Date(); | |
| pastDate.setDate(pastDate.getDate() - 1); | |
| expect(isFutureDate(futureDate)).toBe(true); | |
| expect(isFutureDate(pastDate)).toBe(false); | |
| expect(isFutureDate(new Date())).toBe(false); // current time | |
| }); | |
| it('should format date for display', () => { | |
| const formatDate = (date) => { | |
| return new Date(date).toLocaleDateString('en-US', { | |
| year: 'numeric', | |
| month: 'long', | |
| day: 'numeric', | |
| }); | |
| }; | |
| const testDate = new Date('2024-01-15'); | |
| const formatted = formatDate(testDate); | |
| expect(formatted).toContain('January'); | |
| expect(formatted).toContain('15'); | |
| expect(formatted).toContain('2024'); | |
| }); | |
| it('should calculate time difference', () => { | |
| const getTimeDifference = (date1, date2) => { | |
| const diff = Math.abs(new Date(date1) - new Date(date2)); | |
| return Math.floor(diff / (1000 * 60 * 60 * 24)); // days | |
| }; | |
| const date1 = new Date('2024-01-01'); | |
| const date2 = new Date('2024-01-05'); | |
| expect(getTimeDifference(date1, date2)).toBe(4); | |
| expect(getTimeDifference(date2, date1)).toBe(4); // should be absolute | |
| }); | |
| }); | |
| describe('String Utilities', () => { | |
| it('should sanitize input to prevent XSS', () => { | |
| const sanitizeInput = (input) => { | |
| return input | |
| .replace(/[<>]/g, '') // Remove < and > characters | |
| .trim() | |
| .substring(0, 1000); // Limit length | |
| }; | |
| // Test XSS prevention | |
| const maliciousInput = '<script>alert("xss")</script>'; | |
| const sanitized = sanitizeInput(maliciousInput); | |
| expect(sanitized).toBe('scriptalert("xss")/script'); | |
| expect(sanitized).not.toContain('<'); | |
| expect(sanitized).not.toContain('>'); | |
| }); | |
| it('should generate slugs', () => { | |
| const generateSlug = (text) => { | |
| return text | |
| .toLowerCase() | |
| .replace(/[^a-z0-9\s-]/g, '') | |
| .replace(/\s+/g, '-') | |
| .replace(/-+/g, '-') | |
| .trim('-'); | |
| }; | |
| expect(generateSlug('Hello World')).toBe('hello-world'); | |
| expect(generateSlug('Event Title!@#')).toBe('event-title'); | |
| expect(generateSlug('Multiple Spaces')).toBe('multiple-spaces'); | |
| expect(generateSlug('Special---Characters')).toBe('special-characters'); | |
| }); | |
| it('should truncate text', () => { | |
| const truncateText = (text, maxLength, suffix = '...') => { | |
| if (text.length <= maxLength) return text; | |
| return text.substring(0, maxLength - suffix.length) + suffix; | |
| }; | |
| expect(truncateText('Hello World', 5)).toBe('He...'); | |
| expect(truncateText('Short', 10)).toBe('Short'); | |
| expect(truncateText('Very Long Text That Should Be Truncated', 20)).toBe( | |
| 'Very Long Text Th...', | |
| ); | |
| }); | |
| }); | |
| describe('Array Utilities', () => { | |
| it('should remove duplicates from array', () => { | |
| const removeDuplicates = (arr) => { | |
| return [...new Set(arr)]; | |
| }; | |
| expect(removeDuplicates([1, 2, 2, 3, 3, 4])).toEqual([1, 2, 3, 4]); | |
| expect(removeDuplicates(['a', 'b', 'a', 'c'])).toEqual(['a', 'b', 'c']); | |
| expect(removeDuplicates([])).toEqual([]); | |
| }); | |
| it('should shuffle array', () => { | |
| const shuffleArray = (arr) => { | |
| const shuffled = [...arr]; | |
| for (let i = shuffled.length - 1; i > 0; i--) { | |
| const j = Math.floor(Math.random() * (i + 1)); | |
| [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; | |
| } | |
| return shuffled; | |
| }; | |
| const original = [1, 2, 3, 4, 5]; | |
| const shuffled = shuffleArray(original); | |
| expect(shuffled).toHaveLength(original.length); | |
| expect(shuffled.sort()).toEqual(original.sort()); | |
| }); | |
| it('should group array by property', () => { | |
| const groupBy = (arr, key) => { | |
| return arr.reduce((groups, item) => { | |
| const group = item[key]; | |
| groups[group] = groups[group] || []; | |
| groups[group].push(item); | |
| return groups; | |
| }, {}); | |
| }; | |
| const users = [ | |
| { name: 'John', role: 'user' }, | |
| { name: 'Jane', role: 'admin' }, | |
| { name: 'Bob', role: 'user' }, | |
| ]; | |
| const grouped = groupBy(users, 'role'); | |
| expect(grouped.user).toHaveLength(2); | |
| expect(grouped.admin).toHaveLength(1); | |
| expect(grouped.user[0].name).toBe('John'); | |
| expect(grouped.admin[0].name).toBe('Jane'); | |
| }); | |
| }); | |
| describe('Object Utilities', () => { | |
| it('should deep clone objects', () => { | |
| const deepClone = (obj) => { | |
| return JSON.parse(JSON.stringify(obj)); | |
| }; | |
| const original = { | |
| name: 'John', | |
| age: 30, | |
| address: { | |
| city: 'New York', | |
| country: 'USA', | |
| }, | |
| hobbies: ['reading', 'gaming'], | |
| }; | |
| const cloned = deepClone(original); | |
| expect(cloned).toEqual(original); | |
| expect(cloned).not.toBe(original); // different reference | |
| expect(cloned.address).not.toBe(original.address); // nested objects also cloned | |
| }); | |
| it('should merge objects deeply', () => { | |
| const deepMerge = (target, source) => { | |
| const result = { ...target }; | |
| for (const key in source) { | |
| if ( | |
| source[key] && | |
| typeof source[key] === 'object' && | |
| !Array.isArray(source[key]) | |
| ) { | |
| result[key] = deepMerge(result[key] || {}, source[key]); | |
| } else { | |
| result[key] = source[key]; | |
| } | |
| } | |
| return result; | |
| }; | |
| const obj1 = { a: 1, b: { c: 2, d: 3 } }; | |
| const obj2 = { b: { d: 4, e: 5 }, f: 6 }; | |
| const merged = deepMerge(obj1, obj2); | |
| expect(merged).toEqual({ | |
| a: 1, | |
| b: { c: 2, d: 4, e: 5 }, | |
| f: 6, | |
| }); | |
| }); | |
| it('should pick specific properties', () => { | |
| const pick = (obj, keys) => { | |
| return keys.reduce((result, key) => { | |
| if (Object.prototype.hasOwnProperty.call(obj, key)) { | |
| result[key] = obj[key]; | |
| } | |
| return result; | |
| }, {}); | |
| }; | |
| const user = { | |
| id: 1, | |
| name: 'John', | |
| email: 'john@example.com', | |
| password: 'hashed', | |
| role: 'user', | |
| }; | |
| const publicUser = pick(user, ['id', 'name', 'email', 'role']); | |
| expect(publicUser).toEqual({ | |
| id: 1, | |
| name: 'John', | |
| email: 'john@example.com', | |
| role: 'user', | |
| }); | |
| expect(publicUser.password).toBeUndefined(); | |
| }); | |
| }); | |
| describe('Validation Utilities', () => { | |
| it('should validate phone numbers', () => { | |
| const validatePhone = (phone) => { | |
| const phoneRegex = /^[0-9]{10}$/; | |
| return phoneRegex.test(phone); | |
| }; | |
| expect(validatePhone('1234567890')).toBe(true); | |
| expect(validatePhone('9876543210')).toBe(true); | |
| expect(validatePhone('123456789')).toBe(false); // too short | |
| expect(validatePhone('12345678901')).toBe(false); // too long | |
| expect(validatePhone('123456789a')).toBe(false); // contains letter | |
| }); | |
| it('should validate URLs', () => { | |
| const validateURL = (url) => { | |
| try { | |
| new URL(url); | |
| return true; | |
| } catch { | |
| return false; | |
| } | |
| }; | |
| expect(validateURL('https://example.com')).toBe(true); | |
| expect(validateURL('http://localhost:3000')).toBe(true); | |
| expect(validateURL('ftp://files.example.com')).toBe(true); | |
| expect(validateURL('not-a-url')).toBe(false); | |
| expect(validateURL('')).toBe(false); | |
| }); | |
| it('should validate file extensions', () => { | |
| const validateFileExtension = (filename, allowedExtensions) => { | |
| const extension = filename.split('.').pop().toLowerCase(); | |
| return allowedExtensions.includes(extension); | |
| }; | |
| const allowedExtensions = ['jpg', 'jpeg', 'png', 'gif']; | |
| expect(validateFileExtension('image.jpg', allowedExtensions)).toBe(true); | |
| expect(validateFileExtension('photo.PNG', allowedExtensions)).toBe(true); | |
| expect(validateFileExtension('document.pdf', allowedExtensions)).toBe( | |
| false, | |
| ); | |
| expect(validateFileExtension('script.js', allowedExtensions)).toBe(false); | |
| }); | |
| }); | |
| describe('Math Utilities', () => { | |
| it('should calculate percentage', () => { | |
| const calculatePercentage = (value, total) => { | |
| return Math.round((value / total) * 100); | |
| }; | |
| expect(calculatePercentage(50, 100)).toBe(50); | |
| expect(calculatePercentage(25, 50)).toBe(50); | |
| expect(calculatePercentage(0, 100)).toBe(0); | |
| expect(calculatePercentage(100, 100)).toBe(100); | |
| }); | |
| it('should generate random number in range', () => { | |
| const randomInRange = (min, max) => { | |
| return Math.floor(Math.random() * (max - min + 1)) + min; | |
| }; | |
| const result = randomInRange(1, 10); | |
| expect(result).toBeGreaterThanOrEqual(1); | |
| expect(result).toBeLessThanOrEqual(10); | |
| expect(Number.isInteger(result)).toBe(true); | |
| }); | |
| it('should round to decimal places', () => { | |
| const roundToDecimal = (number, decimals) => { | |
| return ( | |
| Math.round(number * Math.pow(10, decimals)) / Math.pow(10, decimals) | |
| ); | |
| }; | |
| expect(roundToDecimal(3.14159, 2)).toBe(3.14); | |
| expect(roundToDecimal(2.71828, 3)).toBe(2.718); | |
| expect(roundToDecimal(10.5, 0)).toBe(11); | |
| }); | |
| }); | |
| }); | |