Docs

README

Module 20: Testing & Debugging

Master the art of writing reliable, testable code and efficiently debugging JavaScript applications.

╔═══════════════════════════════════════════════════════════════════════════════╗
β•‘                                                                               β•‘
β•‘      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β•‘
β•‘      β”‚                   TESTING & DEBUGGING                           β”‚      β•‘
β•‘      β”‚                                                                 β”‚      β•‘
β•‘      β”‚   "Code without tests is broken by design." - Jacob Kaplan-Moss β”‚      β•‘
β•‘      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β•‘
β•‘                                                                               β•‘
β•‘    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β•‘
β•‘    β”‚    TEST     β”‚    β”‚   DEBUG     β”‚    β”‚   PROFILE   β”‚    β”‚   MONITOR   β”‚   β•‘
β•‘    β”‚   ───────   β”‚    β”‚   ───────   β”‚    β”‚   ───────   β”‚    β”‚   ───────   β”‚   β•‘
β•‘    β”‚  Unit       β”‚    β”‚  DevTools   β”‚    β”‚  Memory     β”‚    β”‚  Logs       β”‚   β•‘
β•‘    β”‚  Integrationβ”‚    β”‚  Breakpointsβ”‚    β”‚  CPU        β”‚    β”‚  Errors     β”‚   β•‘
β•‘    β”‚  E2E        β”‚    β”‚  Console    β”‚    β”‚  Network    β”‚    β”‚  Metrics    β”‚   β•‘
β•‘    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β•‘
β•‘                                                                               β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

πŸ“‹ Module Overview

This module transforms you from a developer who hopes code works into one who knows it works. Learn professional testing practices, master debugging tools, and build confidence in your code.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    THE TESTING MINDSET                                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  Without Tests:                        With Tests:                          β”‚
β”‚  ──────────────                        ───────────                          β”‚
β”‚                                                                             β”‚
β”‚  function add(a, b) {                  function add(a, b) {                 β”‚
β”‚    return a + b;                         return a + b;                      β”‚
β”‚  }                                     }                                    β”‚
β”‚  // "I think it works"                                                      β”‚
β”‚                                        test('adds numbers', () => {         β”‚
β”‚                                          expect(add(2, 3)).toBe(5);         β”‚
β”‚                                          expect(add(-1, 1)).toBe(0);        β”‚
β”‚                                          expect(add(0, 0)).toBe(0);         β”‚
β”‚                                        });                                  β”‚
β”‚                                        // "I KNOW it works"                 β”‚
β”‚                                                                             β”‚
β”‚  Benefits:                                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  βœ… Catch bugs before production                                    β”‚    β”‚
β”‚  β”‚  βœ… Refactor with confidence                                        β”‚    β”‚
β”‚  β”‚  βœ… Document expected behavior                                       β”‚    β”‚
β”‚  β”‚  βœ… Faster development in the long run                              β”‚    β”‚
β”‚  β”‚  βœ… Better code design (testable = modular)                         β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“š Module Structure

20.1 Unit Testing Fundamentals

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      UNIT TESTING BASICS                                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  The AAA Pattern:                                                           β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  test('user can update their name', () => {                         β”‚    β”‚
β”‚  β”‚    // ARRANGE - Set up the test data                                β”‚    β”‚
β”‚  β”‚    const user = new User('Alice');                                  β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚    // ACT - Perform the action being tested                         β”‚    β”‚
β”‚  β”‚    user.setName('Bob');                                             β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚    // ASSERT - Verify the expected outcome                          β”‚    β”‚
β”‚  β”‚    expect(user.name).toBe('Bob');                                   β”‚    β”‚
β”‚  β”‚  });                                                                β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                             β”‚
β”‚  Test Doubles:                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  TYPE          PURPOSE                     EXAMPLE                  β”‚    β”‚
β”‚  β”‚  ────          ───────                     ───────                  β”‚    β”‚
β”‚  β”‚  Dummy         Fill parameter slots        () => {}                 β”‚    β”‚
β”‚  β”‚  Stub          Return canned values        () => 42                 β”‚    β”‚
β”‚  β”‚  Spy           Record interactions         jest.fn()                β”‚    β”‚
β”‚  β”‚  Mock          Verify expectations         jest.mock('./module')    β”‚    β”‚
β”‚  β”‚  Fake          Working implementation      In-memory database       β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • β€’Testing principles - Why, what, and how to test
  • β€’Test structure - Arrange-Act-Assert pattern
  • β€’Test doubles - Mocks, stubs, spies, fakes
  • β€’Code coverage - Measuring test completeness

20.2 Testing with Jest

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      JEST FRAMEWORK                                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  Matchers Cheat Sheet:                                                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  // Equality                                                        β”‚    β”‚
β”‚  β”‚  expect(x).toBe(y)           // Strict equality (===)               β”‚    β”‚
β”‚  β”‚  expect(x).toEqual(y)        // Deep equality                       β”‚    β”‚
β”‚  β”‚  expect(x).toStrictEqual(y)  // Deep + undefined properties         β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  // Truthiness                                                      β”‚    β”‚
β”‚  β”‚  expect(x).toBeTruthy()                                             β”‚    β”‚
β”‚  β”‚  expect(x).toBeFalsy()                                              β”‚    β”‚
β”‚  β”‚  expect(x).toBeNull()                                               β”‚    β”‚
β”‚  β”‚  expect(x).toBeUndefined()                                          β”‚    β”‚
β”‚  β”‚  expect(x).toBeDefined()                                            β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  // Numbers                                                         β”‚    β”‚
β”‚  β”‚  expect(x).toBeGreaterThan(y)                                       β”‚    β”‚
β”‚  β”‚  expect(x).toBeLessThan(y)                                          β”‚    β”‚
β”‚  β”‚  expect(x).toBeCloseTo(y)    // For floating point                  β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  // Strings                                                         β”‚    β”‚
β”‚  β”‚  expect(x).toMatch(/pattern/)                                       β”‚    β”‚
β”‚  β”‚  expect(x).toContain('substring')                                   β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  // Arrays/Iterables                                                β”‚    β”‚
β”‚  β”‚  expect(arr).toContain(item)                                        β”‚    β”‚
β”‚  β”‚  expect(arr).toHaveLength(n)                                        β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  // Objects                                                         β”‚    β”‚
β”‚  β”‚  expect(obj).toHaveProperty('key', value)                           β”‚    β”‚
β”‚  β”‚  expect(obj).toMatchObject(partialObj)                              β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  // Exceptions                                                      β”‚    β”‚
β”‚  β”‚  expect(() => fn()).toThrow()                                       β”‚    β”‚
β”‚  β”‚  expect(() => fn()).toThrow(ErrorType)                              β”‚    β”‚
β”‚  β”‚  expect(() => fn()).toThrow('message')                              β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  // Negation                                                        β”‚    β”‚
β”‚  β”‚  expect(x).not.toBe(y)                                              β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                             β”‚
β”‚  Async Testing:                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  // With async/await                                                β”‚    β”‚
β”‚  β”‚  test('async test', async () => {                                   β”‚    β”‚
β”‚  β”‚    const data = await fetchData();                                  β”‚    β”‚
β”‚  β”‚    expect(data).toBe('result');                                     β”‚    β”‚
β”‚  β”‚  });                                                                β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  // With resolves/rejects                                           β”‚    β”‚
β”‚  β”‚  test('promise resolves', () => {                                   β”‚    β”‚
β”‚  β”‚    return expect(fetchData()).resolves.toBe('result');              β”‚    β”‚
β”‚  β”‚  });                                                                β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  test('promise rejects', () => {                                    β”‚    β”‚
β”‚  β”‚    return expect(badFetch()).rejects.toThrow('error');              β”‚    β”‚
β”‚  β”‚  });                                                                β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • β€’Jest configuration - Setup and customization
  • β€’Matchers and assertions - Complete matcher reference
  • β€’Async testing - Testing promises and async/await
  • β€’Mocking - Mock functions and modules

20.3 Testing DOM and Browser Code

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      DOM TESTING                                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  Testing Library Philosophy:                                                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  "The more your tests resemble the way your software is used,       β”‚    β”‚
β”‚  β”‚   the more confidence they can give you."                           β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  Query Priority (most to least preferred):                          β”‚    β”‚
β”‚  β”‚  ────────────────────────────────────────                           β”‚    β”‚
β”‚  β”‚  1. getByRole       ← Accessible to everyone                        β”‚    β”‚
β”‚  β”‚  2. getByLabelText  ← Form fields                                   β”‚    β”‚
β”‚  β”‚  3. getByPlaceholderText                                            β”‚    β”‚
β”‚  β”‚  4. getByText       ← Non-interactive elements                      β”‚    β”‚
β”‚  β”‚  5. getByDisplayValue ← Current form values                         β”‚    β”‚
β”‚  β”‚  6. getByAltText    ← Images                                        β”‚    β”‚
β”‚  β”‚  7. getByTitle                                                      β”‚    β”‚
β”‚  β”‚  8. getByTestId     ← Last resort                                   β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                             β”‚
β”‚  Example:                                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  import { render, screen, fireEvent } from '@testing-library/dom';  β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  test('button click updates text', () => {                          β”‚    β”‚
β”‚  β”‚    // Render                                                        β”‚    β”‚
β”‚  β”‚    render(`<button>Click me</button><span></span>`);                 β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚    // Query                                                         β”‚    β”‚
β”‚  β”‚    const button = screen.getByRole('button', { name: /click me/i });β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚    // Interact                                                      β”‚    β”‚
β”‚  β”‚    fireEvent.click(button);                                         β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚    // Assert                                                        β”‚    β”‚
β”‚  β”‚    expect(screen.getByText('Clicked!')).toBeInTheDocument();        β”‚    β”‚
β”‚  β”‚  });                                                                β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • β€’DOM testing utilities - JSDOM, Testing Library
  • β€’Event simulation - Click, input, keyboard events
  • β€’Async UI updates - waitFor, findBy queries
  • β€’Component testing - Testing UI components

20.4 Debugging Techniques

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      DEBUGGING TOOLKIT                                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  Console Methods:                                                           β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  console.log(obj)         // Basic output                           β”‚    β”‚
β”‚  β”‚  console.dir(obj)         // Interactive object tree                β”‚    β”‚
β”‚  β”‚  console.table(arr)       // Tabular format                         β”‚    β”‚
β”‚  β”‚  console.group('name')    // Group related logs                     β”‚    β”‚
β”‚  β”‚  console.groupEnd()                                                 β”‚    β”‚
β”‚  β”‚  console.time('label')    // Start timer                            β”‚    β”‚
β”‚  β”‚  console.timeEnd('label') // End timer, show duration               β”‚    β”‚
β”‚  β”‚  console.trace()          // Show call stack                        β”‚    β”‚
β”‚  β”‚  console.assert(cond)     // Log if condition is false              β”‚    β”‚
β”‚  β”‚  console.count('label')   // Count invocations                      β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                             β”‚
β”‚  Breakpoint Types:                                                          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  Line Breakpoint     β”‚ Click line number in Sources panel           β”‚    β”‚
β”‚  β”‚  Conditional         β”‚ Right-click β†’ Add conditional breakpoint     β”‚    β”‚
β”‚  β”‚  Logpoint           β”‚ Right-click β†’ Add logpoint (no pause)        β”‚    β”‚
β”‚  β”‚  DOM Breakpoint      β”‚ Elements β†’ Right-click β†’ Break on...         β”‚    β”‚
β”‚  β”‚  XHR Breakpoint      β”‚ Sources β†’ XHR Breakpoints                    β”‚    β”‚
β”‚  β”‚  Event Breakpoint    β”‚ Sources β†’ Event Listener Breakpoints         β”‚    β”‚
β”‚  β”‚  Exception           β”‚ Sources β†’ Pause on exceptions                β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                             β”‚
β”‚  Stepping Controls:                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  β–Ά Resume         β”‚ Continue until next breakpoint                 β”‚    β”‚
β”‚  β”‚  ‡ Step Over      β”‚ Execute current line, move to next             β”‚    β”‚
β”‚  β”‚  – Step Into      β”‚ Enter function call                            β”‚    β”‚
β”‚  β”‚  ‴ Step Out       β”‚ Complete current function, return to caller    β”‚    β”‚
β”‚  β”‚  ⟲ Restart        β”‚ Restart the current call frame                 β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • β€’Browser DevTools - Full feature mastery
  • β€’Console methods - Beyond console.log
  • β€’Breakpoints - Strategic debugging
  • β€’Performance profiling - Finding bottlenecks

20.5 Error Handling & Logging

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      ERROR MANAGEMENT                                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  Error Handling Strategy:                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚         User Action                                                 β”‚    β”‚
β”‚  β”‚              β”‚                                                      β”‚    β”‚
β”‚  β”‚              β–Ό                                                      β”‚    β”‚
β”‚  β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                              β”‚    β”‚
β”‚  β”‚    β”‚   Try Operation β”‚                                              β”‚    β”‚
β”‚  β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                              β”‚    β”‚
β”‚  β”‚              β”‚                                                      β”‚    β”‚
β”‚  β”‚         Success? ──────► βœ“ Continue normal flow                    β”‚    β”‚
β”‚  β”‚              β”‚                                                      β”‚    β”‚
β”‚  β”‚              β–Ό Error                                                β”‚    β”‚
β”‚  β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                              β”‚    β”‚
β”‚  β”‚    β”‚  Catch & Log    β”‚ ──► Send to error tracking service           β”‚    β”‚
β”‚  β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                              β”‚    β”‚
β”‚  β”‚              β”‚                                                      β”‚    β”‚
β”‚  β”‚              β–Ό                                                      β”‚    β”‚
β”‚  β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                              β”‚    β”‚
β”‚  β”‚    β”‚ Can Recover?    β”‚ ──► Try fallback / retry                     β”‚    β”‚
β”‚  β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                              β”‚    β”‚
β”‚  β”‚              β”‚ No                                                   β”‚    β”‚
β”‚  β”‚              β–Ό                                                      β”‚    β”‚
β”‚  β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                              β”‚    β”‚
β”‚  β”‚    β”‚ Graceful Error  β”‚ ──► Show user-friendly message               β”‚    β”‚
β”‚  β”‚    β”‚ UI              β”‚                                              β”‚    β”‚
β”‚  β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                              β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                             β”‚
β”‚  Logging Levels:                                                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  ERROR   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  Critical failures, needs attention          β”‚    β”‚
β”‚  β”‚  WARN    β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ      Potential issues, degraded performance      β”‚    β”‚
β”‚  β”‚  INFO    β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ          Normal operations, milestones               β”‚    β”‚
β”‚  β”‚  DEBUG   β–ˆβ–ˆβ–ˆ            Detailed diagnostic information             β”‚    β”‚
β”‚  β”‚  TRACE   β–ˆ              Very detailed execution trace               β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β”‚  Production: ERROR, WARN, (INFO)                                    β”‚    β”‚
β”‚  β”‚  Development: All levels                                            β”‚    β”‚
β”‚  β”‚                                                                     β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • β€’Structured error handling - Consistent patterns
  • β€’Logging strategies - Development vs production
  • β€’Error tracking - Sentry, LogRocket, etc.
  • β€’Production debugging - Source maps and monitoring

🎯 Learning Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    LEARNING PROGRESSION                                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  Week 1: Unit Testing Fundamentals                                          β”‚
β”‚  β”œβ”€β”€ Understand why testing matters                                         β”‚
β”‚  β”œβ”€β”€ Learn the AAA pattern                                                  β”‚
β”‚  β”œβ”€β”€ Practice with simple pure functions                                    β”‚
β”‚  └── Understand test doubles concepts                                       β”‚
β”‚                                                                             β”‚
β”‚  Week 2: Jest Mastery                                                       β”‚
β”‚  β”œβ”€β”€ Set up Jest in a project                                               β”‚
β”‚  β”œβ”€β”€ Learn all common matchers                                              β”‚
β”‚  β”œβ”€β”€ Test async code                                                        β”‚
β”‚  └── Mock functions and modules                                             β”‚
β”‚                                                                             β”‚
β”‚  Week 3: DOM and Integration Testing                                        β”‚
β”‚  β”œβ”€β”€ Set up Testing Library                                                 β”‚
β”‚  β”œβ”€β”€ Test UI components                                                     β”‚
β”‚  β”œβ”€β”€ Simulate user interactions                                             β”‚
β”‚  └── Write integration tests                                                β”‚
β”‚                                                                             β”‚
β”‚  Week 4: Debugging and Error Handling                                       β”‚
β”‚  β”œβ”€β”€ Master DevTools debugging                                              β”‚
β”‚  β”œβ”€β”€ Use advanced console methods                                           β”‚
β”‚  β”œβ”€β”€ Implement error tracking                                               β”‚
β”‚  └── Build logging infrastructure                                           β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”Ί Testing Pyramid

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    THE TESTING PYRAMID                                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                       β”‚
β”‚                          β•±   E2E    β•²                                       β”‚
β”‚                         β•±  (Manual)  β•²   ← FEW: Slow, expensive             β”‚
β”‚                        ╱─────────────╲     Simulate real user flows        β”‚
β”‚                       β•±  Integration  β•²                                     β”‚
β”‚                      β•±   (Automated)   β•²  ← SOME: Medium speed              β”‚
β”‚                     ╱───────────────────╲   Multiple units together        β”‚
β”‚                    β•±     Unit Tests      β•²                                  β”‚
β”‚                   β•±      (Automated)      β•² ← MANY: Fast, cheap             β”‚
β”‚                  ╱─────────────────────────╲  Single functions/modules      β”‚
β”‚                                                                             β”‚
β”‚  Unit Tests:                                                                β”‚
β”‚  β”œβ”€β”€ Test individual functions and classes                                  β”‚
β”‚  β”œβ”€β”€ Fast execution (milliseconds)                                          β”‚
β”‚  β”œβ”€β”€ Easy to write and maintain                                             β”‚
β”‚  └── Run on every save/commit                                               β”‚
β”‚                                                                             β”‚
β”‚  Integration Tests:                                                         β”‚
β”‚  β”œβ”€β”€ Test how units work together                                           β”‚
β”‚  β”œβ”€β”€ May involve database, API mocks                                        β”‚
β”‚  β”œβ”€β”€ Slower than unit tests                                                 β”‚
β”‚  └── Run before merge/deploy                                                β”‚
β”‚                                                                             β”‚
β”‚  E2E Tests:                                                                 β”‚
β”‚  β”œβ”€β”€ Test complete user flows                                               β”‚
β”‚  β”œβ”€β”€ Use real browsers (Cypress, Playwright)                                β”‚
β”‚  β”œβ”€β”€ Slowest, most expensive                                                β”‚
β”‚  └── Run before major releases                                              β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”‘ Key Concepts

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    TESTING TERMINOLOGY                                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  Term              β”‚ Description                                            β”‚
β”‚  ─────────────────│─────────────────────────────────────────────────────   β”‚
β”‚  Unit Test         β”‚ Tests a single unit (function/class) in isolation     β”‚
β”‚  Integration Test  β”‚ Tests multiple units working together                 β”‚
β”‚  E2E Test          β”‚ Tests entire application flow end-to-end              β”‚
β”‚  Test Suite        β”‚ Collection of related tests                           β”‚
β”‚  Test Case         β”‚ Single test verifying specific behavior               β”‚
β”‚  Test Runner       β”‚ Tool that executes tests (Jest, Mocha)                β”‚
β”‚  Assertion         β”‚ Statement verifying expected outcome                  β”‚
β”‚  Fixture           β”‚ Test data setup                                       β”‚
β”‚  Mock              β”‚ Simulated object with programmable behavior           β”‚
β”‚  Stub              β”‚ Mock that returns canned responses                    β”‚
β”‚  Spy               β”‚ Records function calls for verification              β”‚
β”‚  Coverage          β”‚ Percentage of code executed by tests                  β”‚
β”‚  Regression        β”‚ Bug reintroduced in previously working code           β”‚
β”‚  TDD               β”‚ Write tests before implementation                     β”‚
β”‚  BDD               β”‚ Tests written in behavioral language                  β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“‹ Prerequisites

  • β€’Strong understanding of JavaScript functions
  • β€’Familiarity with async/await
  • β€’Basic understanding of the DOM
  • β€’Experience with npm/package management

πŸ“š Section Files

SectionTopicKey Files
20.1Unit Testing Fundamentals01-testing-principles.js, 02-test-doubles.js
20.2Testing with Jest01-matchers.js, 02-async-testing.js, 03-mocking.js
20.3DOM Testing01-dom-queries.js, 02-event-testing.js
20.4Debugging01-console-methods.js, 02-devtools-tips.js
20.5Error Handling01-error-patterns.js, 02-logging.js

⚠️ Common Pitfalls

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    TESTING PITFALLS TO AVOID                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  ❌ Testing implementation, not behavior                                    β”‚
β”‚  ─────────────────────────────────────────                                  β”‚
β”‚  // Bad: Tests internal state                                               β”‚
β”‚  expect(counter._count).toBe(1);                                            β”‚
β”‚  // Good: Tests behavior                                                    β”‚
β”‚  expect(counter.getValue()).toBe(1);                                        β”‚
β”‚                                                                             β”‚
β”‚  ❌ Tests that depend on each other                                         β”‚
β”‚  ────────────────────────────────                                           β”‚
β”‚  // Bad: Test B depends on Test A running first                             β”‚
β”‚  // Good: Each test sets up its own data                                    β”‚
β”‚                                                                             β”‚
β”‚  ❌ Not testing edge cases                                                  β”‚
β”‚  ─────────────────────────────                                              β”‚
β”‚  // Bad: Only test the happy path                                           β”‚
β”‚  // Good: Test null, empty, boundaries, errors                              β”‚
β”‚                                                                             β”‚
β”‚  ❌ Over-mocking                                                            β”‚
β”‚  ──────────────                                                             β”‚
β”‚  // Bad: Mock everything, test doesn't verify real behavior                 β”‚
β”‚  // Good: Mock external dependencies, not the unit under test               β”‚
β”‚                                                                             β”‚
β”‚  ❌ Ignoring flaky tests                                                    β”‚
β”‚  ───────────────────────                                                    β”‚
β”‚  // Bad: "It usually passes, skip it"                                       β”‚
β”‚  // Good: Fix timing issues, make tests deterministic                       β”‚
β”‚                                                                             β”‚
β”‚  ❌ 100% coverage as a goal                                                 β”‚
β”‚  ─────────────────────────                                                  β”‚
β”‚  // Bad: Write pointless tests just to hit coverage                         β”‚
β”‚  // Good: Focus on critical paths and edge cases                            β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”— Related Modules


🎯 Quick Reference

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    JEST QUICK REFERENCE                                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  // Test structure                                                          β”‚
β”‚  describe('Module', () => {                                                 β”‚
β”‚    beforeEach(() => { /* setup */ });                                       β”‚
β”‚    afterEach(() => { /* cleanup */ });                                      β”‚
β”‚                                                                             β”‚
β”‚    test('should do something', () => {                                      β”‚
β”‚      expect(result).toBe(expected);                                         β”‚
β”‚    });                                                                      β”‚
β”‚                                                                             β”‚
β”‚    test.skip('skipped test', () => {});                                     β”‚
β”‚    test.only('only this runs', () => {});                                   β”‚
β”‚  });                                                                        β”‚
β”‚                                                                             β”‚
β”‚  // Common matchers                                                         β”‚
β”‚  expect(x).toBe(y)                 // ===                                   β”‚
β”‚  expect(x).toEqual(y)              // Deep equal                            β”‚
β”‚  expect(x).toBeTruthy()            // Boolean true                          β”‚
β”‚  expect(x).toContain(item)         // Array/string contains                 β”‚
β”‚  expect(fn).toThrow()              // Function throws                       β”‚
β”‚  expect(fn).toHaveBeenCalled()     // Mock was called                       β”‚
β”‚  expect(fn).toHaveBeenCalledWith() // Mock called with args                 β”‚
β”‚                                                                             β”‚
β”‚  // Mocking                                                                 β”‚
β”‚  jest.fn()                         // Create mock function                  β”‚
β”‚  jest.mock('./module')             // Mock entire module                    β”‚
β”‚  jest.spyOn(obj, 'method')         // Spy on existing method                β”‚
β”‚                                                                             β”‚
β”‚  // Async                                                                   β”‚
β”‚  await expect(p).resolves.toBe(x)  // Promise resolves                      β”‚
β”‚  await expect(p).rejects.toThrow() // Promise rejects                       β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
README - JavaScript Tutorial | DeepML