or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

grunt-contrib-nodeunit

grunt-contrib-nodeunit is a Grunt plugin that provides integration with the nodeunit-x testing framework for running server-side JavaScript unit tests. It offers enhanced error formatting, custom reporting options, and proper handling of edge cases like incomplete tests.

Package Information

  • Package Name: grunt-contrib-nodeunit
  • Package Type: npm (Grunt plugin)
  • Language: JavaScript
  • Installation: npm install grunt-contrib-nodeunit --save-dev

Core Imports

// Load the plugin in your Gruntfile
grunt.loadNpmTasks('grunt-contrib-nodeunit');

The plugin automatically registers the nodeunit task when loaded.

Basic Usage

// Basic Gruntfile.js configuration
module.exports = function(grunt) {
  grunt.initConfig({
    nodeunit: {
      all: ['test/*_test.js']
    }
  });

  grunt.loadNpmTasks('grunt-contrib-nodeunit');
  grunt.registerTask('test', ['nodeunit']);
};

Run tests with:

grunt nodeunit
# or
grunt nodeunit:all

Architecture

grunt-contrib-nodeunit is built as a standard Grunt plugin with the following key components:

  • Plugin Registration: Exports a function that receives the grunt instance for task registration
  • Custom Reporter: Implements a specialized grunt reporter in nodeunit.reporters.grunt
  • Enhanced Error Handling: Provides better error formatting through betterErrors and cleanStack functions
  • Configuration Integration: Automatically loads nodeunit defaults from nodeunit.json files
  • Stdout Management: Hooks into process.stdout.write for output capture when using reporterOutput
/**
 * Main plugin export function
 * @param grunt - The Grunt instance
 */
module.exports = function(grunt: any): void;

Capabilities

Nodeunit Task

The main task provided by this plugin for running nodeunit tests with enhanced reporting.

// Task configuration
nodeunit: {
  // Target name (e.g., 'all', 'unit', 'integration')
  [targetName]: [
    // Array of file patterns
    'test/*_test.js',
    'test/**/*_test.js'
  ],
  options: {
    // Optional task options
    reporter: string,           // Default: 'grunt'
    reporterOutput: string,     // Default: false
    reporterOptions: object     // Default: {}
  }
}

Task Options

All options are configured within the options object of the task configuration.

interface NodeunitTaskOptions {
  /** 
   * Reporter to use for test output
   * Built-in options: 'grunt' (default), 'default', 'verbose', 'tap', 'junit'
   * Default: 'grunt'
   */
  reporter?: string;

  /** 
   * File path where reporter output should be saved
   * When false, output goes to console only
   * Default: false
   */
  reporterOutput?: string | false;

  /** 
   * Options passed to the selected reporter
   * Varies by reporter type
   * Default: {}
   */
  reporterOptions?: {
    /** Output directory for junit reporter */
    output?: string;
    [key: string]: any;
  };
}

File Patterns

The task accepts standard Grunt file pattern formats:

// Single files
nodeunit: {
  single: ['test/specific_test.js']
}

// Wildcards (all files ending in _test.js in test directory)
nodeunit: {
  wildcard: ['test/*_test.js']
}

// Recursive (all _test.js files in test directory and subdirectories)
nodeunit: {
  recursive: ['test/**/*_test.js']
}

// Multiple patterns
nodeunit: {
  multiple: [
    'test/unit/*_test.js',
    'test/integration/*_test.js'
  ]
}

Reporter Types

The plugin supports any reporter available in the nodeunit-x package. If an invalid reporter is specified, the task will fail with an error. The most commonly used reporters include:

Grunt Reporter (Default)

Custom reporter that integrates with Grunt's logging system, providing enhanced error formatting with colored output, better stack traces, and proper integration with Grunt's verbose mode.

The Grunt reporter provides several enhancements over standard nodeunit reporters:

  • Enhanced Error Formatting: Uses util.inspect with color support and 10-level depth for better object visualization
  • Stack Trace Cleaning: Automatically removes nodeunit internal calls unless --stack flag is used
  • Muted Logging: Temporarily mutes grunt output during test execution to prevent interference
  • Unfinished Test Detection: Tracks tests that don't call test.done() and provides helpful error messages
  • Process Exit Handling: Monitors process exit events to catch incomplete tests that would otherwise crash Grunt
nodeunit: {
  all: ['test/*_test.js'],
  options: {
    reporter: 'grunt'  // This is the default
  }
}

TAP Reporter

Test Anything Protocol output format, useful for CI/CD integration.

nodeunit: {
  all: ['test/*_test.js'],
  options: {
    reporter: 'tap',
    reporterOutput: 'test-results.tap'
  }
}

JUnit Reporter

XML output compatible with JUnit, ideal for CI systems that parse JUnit reports.

nodeunit: {
  all: ['test/*_test.js'],
  options: {
    reporter: 'junit',
    reporterOptions: {
      output: 'test-results'  // Directory for XML files
    }
  }
}

Default and Verbose Reporters

Standard nodeunit reporters for basic console output.

nodeunit: {
  all: ['test/*_test.js'],
  options: {
    reporter: 'default'  // or 'verbose'
  }
}

Configuration Examples

Basic Configuration

Simple setup for running all test files:

grunt.initConfig({
  nodeunit: {
    all: ['test/*_test.js']
  }
});

Multiple Test Targets

Separate configurations for different test types:

grunt.initConfig({
  nodeunit: {
    unit: ['test/unit/*_test.js'],
    integration: ['test/integration/*_test.js'],
    options: {
      reporter: 'grunt'
    }
  }
});

CI/CD Integration

Configuration optimized for continuous integration:

grunt.initConfig({
  nodeunit: {
    ci: ['test/**/*_test.js'],
    options: {
      reporter: 'junit',
      reporterOptions: {
        output: 'test-results'
      }
    }
  }
});

Custom Reporter Output

Save test results to a file:

grunt.initConfig({
  nodeunit: {
    all: ['test/*_test.js'],
    options: {
      reporter: 'tap',
      reporterOutput: 'build/test-results.tap'
    }
  }
});

CLI Options

The plugin respects Grunt CLI options that affect output behavior:

grunt nodeunit --verbose  # Shows detailed test progress and enhanced error reporting
grunt nodeunit --stack    # Displays full stack traces including nodeunit internal calls
  • --verbose: Shows detailed test progress, enhanced error reporting, and full error logging
  • --stack: Displays complete stack traces including nodeunit internal calls (normally filtered out)

Configuration Loading

The plugin automatically loads default configuration from nodeunit.json files:

  • Searches for nodeunit-x/bin/nodeunit.json in node_modules directories
  • Merges found defaults with user-provided reporterOptions
  • User-provided options take precedence over automatic defaults
  • Handles different dependency installation structures automatically

Error Handling

The plugin provides enhanced error handling compared to standard nodeunit:

  • Invalid Reporter Detection: Task fails immediately if specified reporter doesn't exist in nodeunit-x
  • Incomplete Test Detection: Automatically detects tests missing test.done() calls
  • Enhanced Stack Traces: Cleaner stack traces with nodeunit internals removed (unless --stack flag used)
  • Better Error Formatting: Colored output with improved assertion error display using util.inspect
  • Directory Creation: Automatically creates output directories when using reporterOptions.output
  • Stdout Management: Properly captures and restores stdout when using reporterOutput
  • Grunt Integration: Proper error propagation to the Grunt task system

Error Codes and Exit Behavior

The plugin follows Grunt's error handling conventions:

// Error scenarios and their handling
interface ErrorHandling {
  /** Task fails when reporter doesn't exist */
  invalidReporter: Error;
  
  /** Grunt exits with code 90-99 based on number of incomplete tests */  
  incompleteTests: {
    exitCode: number; // Math.min(99, 90 + numberOfIncompleteTests)
    message: string;  // Lists all incomplete test names
  };
  
  /** Warnings for test failures (doesn't stop Grunt) */
  testFailures: {
    type: 'warning';
    message: string; // "X/Y assertions failed (Zms)"
  };
  
  /** Warnings for zero assertions */
  noAssertions: {
    type: 'warning'; 
    message: string; // "0/0 assertions ran (Zms)"
  };
}

Common Issues

Missing test.done()

Incomplete tests/setups/teardowns:
testName
A test was missing test.done(), so nodeunit exploded. Sorry!

This occurs when a test function doesn't call test.done(). Ensure all async tests call test.done():

exports.asyncTest = function(test) {
  setTimeout(function() {
    test.ok(true);
    test.done();  // Required for async tests
  }, 100);
};

Requirements

  • Node.js: >=14.0
  • Grunt: ^1.0.0 (peer dependency)
  • Testing Framework: nodeunit-x ^0.16.0 (automatically installed)

Typical Workflow

  1. Install the plugin: npm install grunt-contrib-nodeunit --save-dev
  2. Configure the task in your Gruntfile.js
  3. Write nodeunit test files (exports with test functions)
  4. Run tests: grunt nodeunit

The plugin integrates seamlessly with Grunt's task system and provides detailed feedback during test execution.

Internal Utilities

For completeness, the plugin includes several internal utility functions that enhance the testing experience:

// Internal utility functions (not directly configurable but part of the implementation)
interface InternalUtilities {
  /** Hooks into stdout for output capture */
  hook_stdout(callback: (string: string, encoding: string, fd: any) => void): () => void;
  
  /** Enhances error display with better formatting */
  betterErrors(assertion: any): any;
  
  /** Cleans stack traces for better readability */
  cleanStack(error: Error): Error;
  
  /** Custom Grunt reporter implementation */
  'nodeunit.reporters.grunt': {
    info: string;
    run: (files: string[], options: any, callback: () => void) => void;
  };
}

These utilities work together to provide the enhanced error reporting and output management that makes grunt-contrib-nodeunit more user-friendly than standard nodeunit command-line usage.