Files
home-information/docs/dev/frontend/javascript-testing.md
Tony C f5032b72e0 Docs updates for new first-time user flows (#191)
* New Getting Started page, moved and revised content into Editing page.
2025-09-17 00:09:29 +00:00

4.1 KiB

JavaScript Testing

This document describes the approach for testing JavaScript modules in the Home Information application.

Overview

JavaScript testing uses QUnit framework with a local-first approach that requires no build tools or external dependencies. Tests focus on business logic functions rather than DOM manipulation or framework internals.

Philosophy

  • Local-first: All dependencies vendored locally, no CDN requirements
  • Lightweight: QUnit framework only, no complex build pipeline
  • Manual execution: Tests run in browser via simple HTML files
  • Business logic focus: Test core functions, algorithms, and state management
  • Real browser testing: Actual browser environment catches issues that mocks miss

Framework Choice: QUnit

Selected for:

  • Minimal setup (just HTML + script tags)
  • No build tools required
  • Django-compatible static file serving
  • Comprehensive async testing support
  • Small footprint (~25KB minified)

Test Structure

/src/hi/static/tests/
├── test-all.html          # Master test runner (recommended)
├── test-{module}.html     # Individual module runners
├── test-{module}.js       # Test cases for each module
└── qunit/                 # QUnit framework (vendored)

Running Tests

Primary workflow:

open src/hi/static/tests/test-all.html

Via Django server:

src/manage.py runserver
# Navigate to: http://127.0.0.1:8411/static/tests/test-all.html

Example Implementation

The auto-view.js module demonstrates the complete testing approach:

  • Source: /src/hi/static/js/auto-view.js
  • Tests: /src/hi/static/tests/test-auto-view.js
  • Individual runner: /src/hi/static/tests/test-auto-view.html

Key test patterns demonstrated:

  • Time-dependent logic testing with Date.now() mocking
  • Throttling behavior with async timing tests
  • Feature detection and caching verification
  • State management transitions
  • Context preservation in callbacks

Testing Best Practices

Focus Areas (High Value)

  • Complex algorithms and timing logic
  • State management and transitions
  • Feature detection and caching
  • Integration between module functions
  • Edge cases and boundary conditions

Avoid Testing (Low Value)

  • jQuery DOM manipulation internals
  • Browser event system mechanics
  • Simple property getters/setters
  • Framework-provided functionality

Mocking Strategy

  • Mock system boundaries: Date.now(), window properties, external APIs
  • Use real objects: Prefer actual module instances over mocks
  • Minimal mocking: Only mock what's necessary for isolation

Adding New Module Tests

  1. Create test file: test-{module}.js following QUnit patterns:

    QUnit.module('ModuleName.functionName', function(hooks) {
        QUnit.test('description of test', function(assert) {
            // Arrange, Act, Assert
            const result = ModuleName.functionName(input);
            assert.equal(result, expected, 'Function returns expected value');
        });
    });
    
  2. Update master runner: Add to test-all.html:

    <!-- In source modules section -->
    <script src="../js/module-name.js"></script>
    
    <!-- In test modules section -->  
    <script src="test-{module}.js"></script>
    
  3. Optional: Create individual runner test-{module}.html for focused debugging

Integration with Development Workflow

  • Manual execution: Part of JavaScript development process
  • PR checklist: Include "JavaScript tests passing" verification
  • No CI automation: Lightweight approach prioritizes simplicity
  • Browser compatibility: Test in target browsers (Firefox, Chrome)

Future Considerations

  • Additional modules can reuse the established pattern
  • Test coverage expansion as JavaScript complexity grows
  • Potential automation if testing frequency increases significantly
  • Maintain local-first philosophy for any framework additions

This approach balances comprehensive testing coverage with development simplicity, providing confidence in JavaScript functionality without complex tooling overhead.