CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-jasmine-node

DOM-less simple JavaScript BDD testing framework for Node.js

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

advanced-features.mddocs/

Advanced Features

Advanced functionality including RequireJS support, CoffeeScript integration, file watching, helper file loading, and programmatic test execution.

Capabilities

Programmatic Test Execution

Execute test suites programmatically with full configuration control.

/**
 * Execute specs in specified folders with comprehensive options
 * @param options - Execution configuration object
 */
function executeSpecsInFolder(options: ExecutionOptions): void;

interface ExecutionOptions {
  /** Array of directories containing spec files */
  specFolders: string[];
  /** Callback function when test execution completes */
  onComplete?: (passed: boolean) => void;
  /** Enable verbose output with detailed progress */
  isVerbose?: boolean;
  /** Enable colored terminal output */
  showColors?: boolean;
  /** Enable TeamCity reporter output */
  teamcity?: boolean;
  /** Enable RequireJS for spec loading (boolean or setup file path) */
  useRequireJs?: boolean | string;
  /** Regular expression for matching spec files */
  regExpSpec?: RegExp;
  /** JUnit XML report configuration */
  junitreport?: JUnitReportConfig;
  /** Include stack traces in error output */
  includeStackTrace?: boolean;
  /** Enable Growl desktop notifications */
  growl?: boolean;
}

interface JUnitReportConfig {
  /** Enable JUnit XML report generation */
  report: boolean;
  /** Directory path for saving XML reports */
  savePath: string;
  /** Use dot notation for nested describe blocks */
  useDotNotation?: boolean;
  /** Consolidate all results into single XML file */
  consolidate?: boolean;
}

Usage Examples:

const jasmine = require("jasmine-node");

// Basic programmatic execution
jasmine.executeSpecsInFolder({
  specFolders: ['spec/', 'test/unit/'],
  onComplete: function(passed) {
    console.log("Tests " + (passed ? "PASSED" : "FAILED"));
    process.exit(passed ? 0 : 1);
  }
});

// Advanced configuration
jasmine.executeSpecsInFolder({
  specFolders: ['spec/'],
  isVerbose: true,
  showColors: true,
  includeStackTrace: true,
  regExpSpec: /spec\.(js|coffee)$/i,
  junitreport: {
    report: true,
    savePath: './test-reports/',
    useDotNotation: true,
    consolidate: true
  },
  growl: true,
  onComplete: function(passed) {
    if (!passed) {
      console.error("Test failures detected!");
      process.exit(1);
    }
  }
});

// RequireJS integration
jasmine.executeSpecsInFolder({
  specFolders: ['spec/'],
  useRequireJs: true,  // Use default RequireJS setup
  onComplete: function(passed) {
    process.exit(passed ? 0 : 1);
  }
});

// Custom RequireJS setup file
jasmine.executeSpecsInFolder({
  specFolders: ['spec/'],
  useRequireJs: './test/requirejs-config.js',
  onComplete: function(passed) {
    process.exit(passed ? 0 : 1);
  }
});

Helper File Loading

Automatically load helper functions and setup code before executing specs.

/**
 * Load helper files from a directory matching a pattern
 * @param folder - Directory path containing helper files
 * @param matcher - Regular expression for matching helper files
 */
function loadHelpersInFolder(folder: string, matcher?: RegExp): void;

Usage Examples:

const jasmine = require("jasmine-node");

// Load all JavaScript helper files
jasmine.loadHelpersInFolder('./spec/helpers/');

// Load helpers with custom pattern
jasmine.loadHelpersInFolder('./test/support/', /helper\.(js|coffee)$/i);

// Multiple helper directories
jasmine.loadHelpersInFolder('./spec/helpers/');
jasmine.loadHelpersInFolder('./spec/fixtures/');
jasmine.loadHelpersInFolder('./spec/matchers/');

// Example helper file: spec/helpers/customMatchers.js
module.exports = {
  toBeWithinRange: function(min, max) {
    return this.actual >= min && this.actual <= max;
  },
  toHaveProperty: function(propertyName) {
    return this.actual.hasOwnProperty(propertyName);
  }
};

// Example helper file: spec/helpers/testSetup.js
module.exports = {
  setupDatabase: function() {
    // Database setup code
    global.testDb = new MockDatabase();
  },
  
  cleanupDatabase: function() {
    // Database cleanup code
    if (global.testDb) {
      global.testDb.close();
      global.testDb = null;
    }
  }
};

RequireJS Integration

Advanced module loading support for AMD-style projects using RequireJS. jasmine-node provides a specialized runner that executes specs in isolated contexts with proper RequireJS module resolution.

/**
 * Execute specs using RequireJS module loading in isolated VM contexts
 * @param specCollection - Collection of spec files to execute
 * @param done - Completion callback function
 * @param jasmineEnv - Jasmine environment instance
 * @param setupFile - Optional RequireJS configuration file path (defaults to built-in template)
 */
function executeJsRunner(
  specCollection: SpecCollection,
  done: (passed: boolean) => void,
  jasmineEnv: jasmine.Env,
  setupFile?: string
): void;

// RequireJS configuration object for setup files
interface RequireJSConfig {
  /** Base URL for module resolution */
  baseUrl?: string;
  /** Path mappings for module names */
  paths?: { [key: string]: string };
  /** Shim configuration for non-AMD modules */
  shim?: { [key: string]: any };
  /** Dependencies to load before executing */
  deps?: string[];
  /** Callback function after configuration */
  callback?: () => void;
}

The RequireJS runner creates isolated VM contexts for each spec file, ensuring proper module isolation while maintaining access to Jasmine globals (describe, it, expect, etc.). It uses a wrapper template that sets up RequireJS within each context and handles both JavaScript and CoffeeScript spec files.

Usage Examples:

// RequireJS setup file: test/requirejs-config.js
require.config({
  baseUrl: '../lib',
  paths: {
    'jquery': '../node_modules/jquery/dist/jquery',
    'underscore': '../node_modules/underscore/underscore',
    'backbone': '../node_modules/backbone/backbone'
  },
  shim: {
    'backbone': {
      deps: ['underscore', 'jquery'],
      exports: 'Backbone'
    }
  }
});

// RequireJS spec file example: spec/modelSpec.js
define(['models/user', 'backbone'], function(User, Backbone) {
  describe("User Model", function() {
    it("should create a user instance", function() {
      const user = new User({name: "John", email: "john@example.com"});
      expect(user.get('name')).toBe("John");
    });

    it("should validate email format", function() {
      const user = new User({name: "John", email: "invalid-email"});
      expect(user.isValid()).toBe(false);
    });
  });
});

// Command line usage with RequireJS
// jasmine-node --runWithRequireJs --requireJsSetup ./test/requirejs-config.js spec/

CoffeeScript Support

Full support for CoffeeScript and Literate CoffeeScript test files.

# CoffeeScript spec file example: spec/calculatorSpec.coffee
describe "Calculator", ->
  calculator = null
  
  beforeEach ->
    calculator = new Calculator()
  
  it "should add two numbers", ->
    result = calculator.add(2, 3)
    expect(result).toEqual(5)
  
  it "should handle async operations", (done) ->
    calculator.asyncAdd 2, 3, (result) ->
      expect(result).toEqual(5)
      done()

# Literate CoffeeScript spec file example: spec/userSpec.litcoffee
# User Model Specifications
# 
# This file contains specifications for the User model,
# demonstrating various user operations and validations.

    describe "User Model", ->
      
## User Creation

When creating a new user, we need to ensure all required
fields are properly validated and stored.

      it "should create user with valid data", ->
        user = new User(name: "Alice", email: "alice@example.com")
        expect(user.isValid()).toBe(true)
        
## Email Validation

The user model should validate email addresses using
standard email format validation.

      it "should reject invalid email formats", ->
        user = new User(name: "Bob", email: "invalid-email")
        expect(user.isValid()).toBe(false)

File Watching and Auto-Testing

Automatically re-run tests when source files or spec files change using the built-in autotest module.

/**
 * Start file watching for automatic test execution
 * @param loadpaths - Directories containing spec files  
 * @param watchFolders - Additional directories to watch for changes
 * @param patterns - File patterns to watch
 */
function start(loadpaths: string[], watchFolders: string[], patterns: string[]): void;

The autotest module uses the gaze library internally to watch for file changes and automatically re-runs the test suite when changes are detected. It maintains state about the last test run result and only shows output for subsequent runs.

Usage Examples:

const autotest = require("jasmine-node/lib/jasmine-node/autotest");

// Basic auto-testing - watches spec files only
autotest.start(['spec/'], [], ['**/*.js']);

// Watch additional directories for source changes
autotest.start(
  ['spec/', 'test/'],           // Spec directories to load tests from
  ['lib/', 'src/', 'app/'],     // Additional directories to watch for changes
  ['**/*.js', '**/*.coffee']    // File patterns to monitor
);

// Custom patterns for different file types
autotest.start(
  ['spec/'],
  ['lib/', 'config/'],
  ['**/*.js', '**/*.json', '**/*.coffee']
);

// Single file watching (useful for focused testing)
autotest.start(['spec/userSpec.js'], ['lib/user.js'], ['**/*.js']);

Spec Collection Management

Programmatically manage and filter spec files for execution using the built-in spec-collection module.

/**
 * Load spec files from directories using file pattern matching
 * @param loadpaths - Array of directory paths to search
 * @param matcher - Regular expression for matching spec files
 */
function load(loadpaths: string[], matcher: RegExp): void;

/**
 * Get loaded spec files sorted alphabetically by path
 * @returns Array of spec file objects with utility methods
 */
function getSpecs(): SpecFile[];

interface SpecFile {
  /** Full file system path to spec file */
  path(): string;
  /** Relative path from root directory (with leading slash removed) */
  relativePath(): string;
  /** Directory containing the spec file (with forward slashes) */
  directory(): string;
  /** Relative directory path (with forward slashes) */
  relativeDirectory(): string;
  /** Filename only without path */
  filename(): string;
}

The spec-collection module uses the walkdir library to recursively search directories for test files. It automatically excludes node_modules directories and sorts results alphabetically to ensure deterministic test execution order.

Usage Examples:

const specCollection = require("jasmine-node/lib/jasmine-node/spec-collection");

// Load specs with default pattern
specCollection.load(['spec/', 'test/'], /spec\.(js|coffee)$/i);

// Get loaded specs
const specs = specCollection.getSpecs();
specs.forEach(function(spec) {
  console.log("Found spec:", spec.relativePath());
  console.log("Directory:", spec.directory());
  console.log("Filename:", spec.filename());
});

// Custom filtering
specCollection.load(['spec/'], /integration.*spec\.js$/i);
const integrationSpecs = specCollection.getSpecs();

// Multiple pattern loading
specCollection.load(['spec/unit/'], /spec\.js$/i);
const unitSpecs = specCollection.getSpecs();

specCollection.load(['spec/e2e/'], /e2e.*spec\.js$/i);
const e2eSpecs = specCollection.getSpecs();

Environment Configuration

Configure the global test environment and default behaviors.

/**
 * Global jasmine environment access
 */
declare namespace jasmine {
  /** Default timeout for asynchronous operations */
  var defaultTimeoutInterval: number;
  
  /** Get the global object (window in browser, global in Node.js) */
  function getGlobal(): any;
  
  /** Get current Jasmine environment */
  function getEnv(): jasmine.Env;
  
  /** Reference to setTimeout for async operations */
  var setTimeout: (fn: Function, delay: number) => any;
  
  /** Reference to setInterval for async operations */
  var setInterval: (fn: Function, delay: number) => any;
}

Usage Examples:

const jasmine = require("jasmine-node");

// Configure default timeout for all async tests
jasmine.getEnv().defaultTimeoutInterval = 10000; // 10 seconds

// Set up global test environment
const testEnv = jasmine.getEnv();

// Add custom global functions
jasmine.getGlobal().customHelper = function() {
  return "test helper function";
};

// Configure multiple reporters
testEnv.addReporter(new jasmine.TerminalReporter({ color: true }));
testEnv.addReporter(new jasmine.JUnitXmlReporter('./reports/'));

// Custom environment setup
testEnv.beforeEach(function() {
  // Global setup before each test
  jasmine.getGlobal().testStartTime = Date.now();
});

testEnv.afterEach(function() {
  // Global cleanup after each test
  const duration = Date.now() - jasmine.getGlobal().testStartTime;
  if (duration > 1000) {
    console.warn("Slow test detected:", duration + "ms");
  }
});

// Execute with custom environment
testEnv.execute();

Exception Handling

Advanced error handling and global exception capture.

/**
 * Configure global exception handling for tests
 */
interface ExceptionHandling {
  /** Capture uncaught exceptions and continue testing */
  captureExceptions: boolean;
  /** Custom exception handler function */
  exceptionHandler?: (error: Error) => void;
  /** Force exit after test completion */
  forceExit: boolean;
}

Usage Examples:

// Global exception handling setup
process.on('uncaughtException', function(error) {
  console.error("Uncaught exception in tests:", error);
  process.exit(1);
});

// Custom exception handler
const handleTestException = function(error) {
  console.error("Test exception:", error.message);
  console.error("Stack:", error.stack);
  
  // Log to file or external service
  require('fs').appendFileSync('./test-errors.log', 
    new Date().toISOString() + ': ' + error.stack + '\n'
  );
};

// Integration with jasmine-node CLI options
jasmine.executeSpecsInFolder({
  specFolders: ['spec/'],
  captureExceptions: true,
  forceExit: true,
  onComplete: function(passed) {
    if (!passed) {
      handleTestException(new Error("Tests failed"));
    }
    process.exit(passed ? 0 : 1);
  }
});

docs

advanced-features.md

cli-usage.md

index.md

reporters.md

test-writing.md

tile.json