Learn comprehensive testing strategies and debugging techniques for JavaScript applications.
Learn comprehensive testing strategies and debugging techniques for JavaScript applications.
Master unit testing with Jest framework for reliable JavaScript applications
Content by: Kriyansh Khunt
MERN Stack Developer
Jest is a JavaScript testing framework that provides a complete testing solution with built-in mocking, assertions, and test runners.
// Basic Jest test
describe('Calculator', () => {
test('adds 1 + 2 to equal 3', () => {
expect(1 + 2).toBe(3);
});
test('multiplies 3 * 4 to equal 12', () => {
expect(3 * 4).toBe(12);
});
});// Function to test
function add(a, b) {
return a + b;
}
function divide(a, b) {
if (b === 0) throw new Error('Division by zero');
return a / b;
}
// Tests
describe('Math Functions', () => {
test('add function works correctly', () => {
expect(add(2, 3)).toBe(5);
expect(add(-1, 1)).toBe(0);
expect(add(0, 0)).toBe(0);
});
test('divide function handles division by zero', () => {
expect(() => divide(5, 0)).toThrow('Division by zero');
expect(divide(10, 2)).toBe(5);
});
});// Mock functions
const mockCallback = jest.fn();
mockCallback('test');
expect(mockCallback).toHaveBeenCalledWith('test');
// Mock modules
jest.mock('./api', () => ({
fetchUser: jest.fn(() => Promise.resolve({ id: 1, name: 'John' }))
}));// Testing async functions
async function fetchData() {
const response = await fetch('/api/data');
return response.json();
}
test('fetchData returns data', async () => {
const data = await fetchData();
expect(data).toBeDefined();
});// UserService.js
class UserService {
constructor(apiClient) {
this.apiClient = apiClient;
}
async getUser(id) {
if (!id) throw new Error('User ID is required');
return await this.apiClient.fetchUser(id);
}
async createUser(userData) {
if (!userData.name) throw new Error('Name is required');
return await this.apiClient.createUser(userData);
}
}
// UserService.test.js
describe('UserService', () => {
let userService;
let mockApiClient;
beforeEach(() => {
mockApiClient = {
fetchUser: jest.fn(),
createUser: jest.fn()
};
userService = new UserService(mockApiClient);
});
describe('getUser', () => {
test('should fetch user successfully', async () => {
const mockUser = { id: 1, name: 'John' };
mockApiClient.fetchUser.mockResolvedValue(mockUser);
const result = await userService.getUser(1);
expect(mockApiClient.fetchUser).toHaveBeenCalledWith(1);
expect(result).toEqual(mockUser);
});
test('should throw error for invalid ID', async () => {
await expect(userService.getUser(null)).rejects.toThrow('User ID is required');
});
});
});Test your understanding of this topic:
Master debugging techniques and tools for JavaScript applications
Content by: Praveen Kumar
MERN Stack Developer
Learn to use browser developer tools for effective debugging and performance analysis.
// Console debugging methods
console.log('Basic logging');
console.warn('Warning message');
console.error('Error message');
console.table([{name: 'John', age: 30}, {name: 'Jane', age: 25}]);
// Debugging with breakpoints
function processData(data) {
debugger; // Breakpoint
const result = data.map(item => {
console.log('Processing item:', item);
return item * 2;
});
return result;
}// Try-catch blocks
try {
const result = riskyOperation();
console.log('Success:', result);
} catch (error) {
console.error('Error occurred:', error.message);
console.error('Stack trace:', error.stack);
}
// Custom error classes
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = 'ValidationError';
this.field = field;
}
}// Performance timing
console.time('operation');
// Your code here
console.timeEnd('operation');
// Memory usage
console.log('Memory usage:', performance.memory);
// Profiling
function profileFunction(fn, ...args) {
const start = performance.now();
const result = fn(...args);
const end = performance.now();
console.log(`Function took ${end - start} milliseconds`);
return result;
}// Fetch debugging
fetch('/api/data')
.then(response => {
console.log('Response status:', response.status);
console.log('Response headers:', response.headers);
return response.json();
})
.then(data => console.log('Data:', data))
.catch(error => console.error('Fetch error:', error));// Advanced debugging toolkit
class Debugger {
constructor() {
this.logs = [];
this.performance = [];
}
log(level, message, data = null) {
const logEntry = {
timestamp: new Date().toISOString(),
level,
message,
data,
stack: new Error().stack
};
this.logs.push(logEntry);
console[level](message, data);
}
measure(name, fn) {
const start = performance.now();
const result = fn();
const end = performance.now();
this.performance.push({ name, duration: end - start });
return result;
}
getReport() {
return {
logs: this.logs,
performance: this.performance,
summary: {
totalLogs: this.logs.length,
averagePerformance: this.performance.reduce((acc, p) => acc + p.duration, 0) / this.performance.length
}
};
}
}Test your understanding of this topic:
Learn to use code quality tools for maintaining clean, consistent JavaScript code
Content by: Sachin Patel
Node.js Developer
ESLint helps identify and fix problems in JavaScript code, ensuring consistency and catching potential errors.
// .eslintrc.js
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended',
'@typescript-eslint/recommended'
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module'
},
rules: {
'no-console': 'warn',
'no-unused-vars': 'error',
'prefer-const': 'error',
'no-var': 'error'
}
};// .prettierrc
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 80,
"tabWidth": 2
}// package.json
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": ["eslint --fix", "prettier --write"]
}
}// jest.config.js
module.exports = {
collectCoverage: true,
coverageDirectory: 'coverage',
coverageReporters: ['text', 'lcov', 'html'],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80
}
}
};// quality-check.js
const { execSync } = require('child_process');
class QualityChecker {
static runLinting() {
try {
execSync('npx eslint src/ --ext .js,.jsx', { stdio: 'inherit' });
console.log('โ
Linting passed');
return true;
} catch (error) {
console.error('โ Linting failed');
return false;
}
}
static runTests() {
try {
execSync('npm test -- --coverage', { stdio: 'inherit' });
console.log('โ
Tests passed');
return true;
} catch (error) {
console.error('โ Tests failed');
return false;
}
}
static formatCode() {
try {
execSync('npx prettier --write src/', { stdio: 'inherit' });
console.log('โ
Code formatted');
return true;
} catch (error) {
console.error('โ Formatting failed');
return false;
}
}
static runAll() {
const results = {
formatting: this.formatCode(),
linting: this.runLinting(),
testing: this.runTests()
};
const allPassed = Object.values(results).every(Boolean);
console.log(allPassed ? '๐ All quality checks passed!' : '๐ฅ Some quality checks failed!');
return allPassed;
}
}Test your understanding of this topic:
Learn to monitor and optimize JavaScript application performance
Content by: Parth Patel
Node.js Developer
Monitor key performance indicators to ensure optimal user experience and application efficiency.
// Measuring Core Web Vitals
function measureWebVitals() {
// Largest Contentful Paint (LCP)
new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
const lastEntry = entries[entries.length - 1];
console.log('LCP:', lastEntry.startTime);
}).observe({ entryTypes: ['largest-contentful-paint'] });
// First Input Delay (FID)
new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
entries.forEach(entry => {
console.log('FID:', entry.processingStart - entry.startTime);
});
}).observe({ entryTypes: ['first-input'] });
// Cumulative Layout Shift (CLS)
let clsValue = 0;
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
clsValue += entry.value;
}
}
console.log('CLS:', clsValue);
}).observe({ entryTypes: ['layout-shift'] });
}// Memory usage monitoring
function monitorMemory() {
if (performance.memory) {
const memory = performance.memory;
console.log('Memory Usage:', {
used: Math.round(memory.usedJSHeapSize / 1024 / 1024) + ' MB',
total: Math.round(memory.totalJSHeapSize / 1024 / 1024) + ' MB',
limit: Math.round(memory.jsHeapSizeLimit / 1024 / 1024) + ' MB'
});
}
}
// Memory leak detection
class MemoryLeakDetector {
constructor() {
this.initialMemory = performance.memory?.usedJSHeapSize || 0;
this.interval = setInterval(() => this.checkMemory(), 5000);
}
checkMemory() {
const currentMemory = performance.memory?.usedJSHeapSize || 0;
const increase = currentMemory - this.initialMemory;
if (increase > 10 * 1024 * 1024) { // 10MB increase
console.warn('Potential memory leak detected!');
}
}
stop() {
clearInterval(this.interval);
}
}// Performance profiling
class PerformanceProfiler {
constructor() {
this.marks = new Map();
}
start(name) {
performance.mark(`${name}-start`);
this.marks.set(name, performance.now());
}
end(name) {
const startTime = this.marks.get(name);
if (startTime) {
const duration = performance.now() - startTime;
console.log(`${name} took ${duration.toFixed(2)}ms`);
this.marks.delete(name);
}
}
measure(name, fn) {
this.start(name);
const result = fn();
this.end(name);
return result;
}
}// webpack-bundle-analyzer
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false,
reportFilename: 'bundle-report.html'
})
]
};// Performance Dashboard
class PerformanceDashboard {
constructor() {
this.metrics = {
pageLoad: 0,
memoryUsage: 0,
errors: 0,
apiCalls: 0
};
this.init();
}
init() {
this.measurePageLoad();
this.trackMemoryUsage();
this.trackErrors();
this.trackApiCalls();
this.renderDashboard();
}
measurePageLoad() {
window.addEventListener('load', () => {
this.metrics.pageLoad = performance.now();
this.updateDashboard();
});
}
trackMemoryUsage() {
setInterval(() => {
if (performance.memory) {
this.metrics.memoryUsage = performance.memory.usedJSHeapSize;
this.updateDashboard();
}
}, 1000);
}
trackErrors() {
window.addEventListener('error', () => {
this.metrics.errors++;
this.updateDashboard();
});
}
trackApiCalls() {
const originalFetch = window.fetch;
window.fetch = (...args) => {
this.metrics.apiCalls++;
this.updateDashboard();
return originalFetch.apply(this, args);
};
}
renderDashboard() {
const dashboard = document.createElement('div');
dashboard.id = 'perf-dashboard';
dashboard.style.cssText = `
position: fixed;
top: 10px;
right: 10px;
background: #000;
color: #fff;
padding: 10px;
border-radius: 5px;
font-family: monospace;
z-index: 9999;
`;
document.body.appendChild(dashboard);
}
updateDashboard() {
const dashboard = document.getElementById('perf-dashboard');
if (dashboard) {
dashboard.innerHTML = `
<div>Page Load: ${this.metrics.pageLoad.toFixed(2)}ms</div>
<div>Memory: ${Math.round(this.metrics.memoryUsage / 1024 / 1024)}MB</div>
<div>Errors: ${this.metrics.errors}</div>
<div>API Calls: ${this.metrics.apiCalls}</div>
`;
}
}
}Test your understanding of this topic:
Continue your learning journey and master the next set of concepts.
Continue to Module 11