Essential testing utilities for module configuration, dependency injection, debugging, browser event simulation, and other testing helpers provided by Angular Mocks.
Global module function for configuring dependency injection in tests:
/**
* Configure modules for dependency injection in tests
* @param {...(string|Function|Object)} modules - Module names, configuration functions, or value objects
* @returns {Function|*} Configuration function or immediate execution result
*/
module(...modules);
/**
* Use shared injector across all tests in describe block
* Enables use of beforeAll/before hooks for shared setup
*/
module.sharedInjector();Global inject function for injecting dependencies into test functions:
/**
* Inject dependencies into test functions
* @param {...Function} functions - Functions to inject dependencies into
* @returns {Function|*} Injection function or immediate execution result
*/
inject(...functions);
/**
* Enable or disable strict dependency injection
* @param {boolean} value - Whether to enable strict DI (optional, defaults to true)
* @returns {Function|*} Configuration function or immediate execution result
*/
inject.strictDi(value?);Global function for triggering native browser events on DOM elements:
/**
* Trigger a native browser event on an element
* @param {Element|jQuery} element - DOM element or jQuery/jqLite wrapper
* @param {string} eventType - Event type (optional, auto-detected if not provided)
* @param {Object} eventData - Additional event data (optional)
* @returns {void}
*/
browserTrigger(element, eventType?, eventData?);
/**
* Event data object for configuring triggered events
*/
interface BrowserEventData {
/** Whether the event bubbles */
bubbles?: boolean;
/** Whether the event can be cancelled */
cancelable?: boolean;
/** Character code for keyboard events */
charcode?: number;
/** Composition data for CompositionEvents */
data?: string;
/** Elapsed time for transition/animation events */
elapsedTime?: number;
/** Key code for keyboard events */
keycode?: number;
/** Modifier keys array (ctrl, alt, shift, meta) */
keys?: string[];
/** Related target for mouse events */
relatedTarget?: Element;
/** Which key for keyboard events */
which?: number;
}Utilities for debugging and inspecting objects in tests:
/**
* Serialize an object for debugging purposes
* @param {*} object - Object to serialize and inspect
* @returns {string} String representation of the object
*/
angular.mock.dump(object);Service for instantiating component controllers in isolation:
/**
* Create a component controller for testing
* @param {string} componentName - Name of the component
* @param {Object} locals - Local dependencies to inject (optional)
* @param {Object} bindings - Component bindings (optional)
* @param {string} ident - Controller identifier (optional)
* @returns {*} Component controller instance
*/
$componentController(componentName, locals?, bindings?, ident?);Mock Date class with timezone support for testing:
/**
* Mock Date class with timezone offset
* @param {number} offset - Timezone offset in hours
* @param {number|string|Date} timestamp - Timestamp to create date from
* @constructor
*/
function TzDate(offset, timestamp);
// TzDate inherits all Date.prototype methods
interface TzDate extends Date {
constructor(offset: number, timestamp: number | string | Date);
}Mock animation module for testing animated components:
/**
* Mock ngAnimate module (angular.mock.animate)
* Provides mocked animation services with testing utilities
*/
angular.module('ngAnimateMock', ['ng']);
/**
* Animation mock service with testing methods
*/
interface AnimateMock {
/**
* Flush pending animations
*/
flush(): void;
/**
* Close and flush all animations, throwing if any are pending
*/
closeAndFlush(): void;
}Module Configuration:
describe('MyService', function() {
// Load application module
beforeEach(module('myApp'));
// Load additional modules
beforeEach(module('ngRoute', 'ngAnimate'));
// Module with inline configuration
beforeEach(module(function($provide) {
$provide.value('apiEndpoint', 'http://test-api.com');
}));
// Module with value object
beforeEach(module({
config1: 'value1',
config2: 'value2'
}));
it('should use configured values', inject(function(apiEndpoint, config1) {
expect(apiEndpoint).toBe('http://test-api.com');
expect(config1).toBe('value1');
}));
});Shared Injector:
describe('ExpensiveSetup', function() {
var MyService, expensiveData;
module.sharedInjector();
beforeAll(module('myApp'));
beforeAll(inject(function(_MyService_) {
MyService = _MyService_;
expensiveData = MyService.performExpensiveCalculation();
}));
it('should have calculated data', function() {
expect(expensiveData).toBeDefined();
expect(expensiveData.result).toBe(42);
});
it('should reuse the same service instance', function() {
expect(MyService.getCalculatedData()).toBe(expensiveData);
});
});Dependency Injection:
describe('Service Integration', function() {
beforeEach(module('myApp'));
it('should inject multiple services', inject(function($http, $q, MyService) {
expect($http).toBeDefined();
expect($q).toBeDefined();
expect(MyService).toBeDefined();
}));
// Using underscore wrapping to avoid variable name conflicts
it('should support underscore wrapping', function() {
var MyService;
inject(function(_MyService_) {
MyService = _MyService_;
});
expect(MyService).toBeDefined();
});
});Browser Event Simulation:
describe('Button Click Handler', function() {
var element, $scope;
beforeEach(module('myApp'));
beforeEach(inject(function($compile, $rootScope) {
$scope = $rootScope.$new();
$scope.clickCount = 0;
$scope.handleClick = function() {
$scope.clickCount++;
};
element = $compile('<button ng-click="handleClick()">Click me</button>')($scope);
$scope.$digest();
}));
it('should handle click events', function() {
browserTrigger(element, 'click');
expect($scope.clickCount).toBe(1);
});
it('should handle keyboard events', function() {
browserTrigger(element, 'keydown', {
keycode: 13, // Enter key
keys: ['ctrl'] // With Ctrl modifier
});
// Assert expected behavior
});
});Component Controller Testing:
describe('UserProfileComponent', function() {
var $componentController;
beforeEach(module('myApp'));
beforeEach(inject(function(_$componentController_) {
$componentController = _$componentController_;
}));
it('should initialize component with bindings', function() {
var bindings = {
user: {id: 1, name: 'John Doe'},
onSave: jasmine.createSpy('onSave')
};
var ctrl = $componentController('userProfile', null, bindings);
expect(ctrl.user).toBe(bindings.user);
expect(ctrl.onSave).toBe(bindings.onSave);
// Test component methods
ctrl.save();
expect(bindings.onSave).toHaveBeenCalled();
});
});Object Debugging:
describe('Complex Data Processing', function() {
it('should process complex objects', inject(function(DataProcessor) {
var complexObject = {
nested: {
array: [1, 2, {deep: 'value'}],
fn: function() { return 'test'; }
}
};
var result = DataProcessor.process(complexObject);
// Use dump for debugging complex objects
console.log('Input:', angular.mock.dump(complexObject));
console.log('Result:', angular.mock.dump(result));
expect(result).toBeDefined();
}));
});Date Mocking:
describe('Timezone-dependent Service', function() {
it('should handle different timezones', function() {
// Create dates in different timezones
var utcDate = new angular.mock.TzDate(0, '2023-01-01T12:00:00Z');
var estDate = new angular.mock.TzDate(-5, '2023-01-01T12:00:00Z');
expect(utcDate.getHours()).toBe(12);
expect(estDate.getHours()).toBe(7); // 5 hours behind UTC
});
});Animation Testing:
describe('Animated Component', function() {
var $animate;
beforeEach(module('myApp', 'ngAnimateMock'));
beforeEach(inject(function(_$animate_) {
$animate = _$animate_;
}));
it('should handle animations', function() {
var element = angular.element('<div class="animated"></div>');
$animate.addClass(element, 'fade-in');
// Flush pending animations
$animate.flush();
expect(element.hasClass('fade-in')).toBe(true);
});
});// Module Configuration Types
type ModuleConfig = string | Function | Object;
// Injection Function Type
type InjectionFunction = (...args: any[]) => void;
// Component Controller Locals
interface ComponentLocals {
[key: string]: any;
}
// Component Bindings
interface ComponentBindings {
[key: string]: any;
}
// Browser Event Configuration
interface BrowserEventConfig {
bubbles?: boolean;
cancelable?: boolean;
charcode?: number;
data?: string;
elapsedTime?: number;
keycode?: number;
keys?: string[];
relatedTarget?: Element;
which?: number;
}