Files
Dawson Blackhouse 91c53144a1 feat: initial commit
2026-01-10 23:40:52 -05:00

488 lines
14 KiB
JavaScript

/**
* CONTROLLER TEST TEMPLATE
*
* Comprehensive Jasmine/Jest test template for AngularJS controllers.
* Demonstrates best practices for controller testing including:
* - Setup and teardown
* - Scope initialization
* - Method testing
* - Event handling
* - HTTP interactions
* - Error handling
*
* Usage:
* 1. Replace 'UserController' with your controller name
* 2. Replace test method names with actual controller methods
* 3. Add specific test cases for your controller logic
* 4. Keep test structure for maintainability
*/
// ============================================================================
// JASMINE VERSION
// ============================================================================
describe("UserController (Jasmine)", function () {
var $controller, $scope, $q, $httpBackend, $timeout;
var UserService, AuthService;
var UserController;
/**
* Load the application module and define the controller
*/
beforeEach(module("myApp"));
/**
* Setup test dependencies using $provide to mock services
*/
beforeEach(
module(function ($provide) {
// Mock UserService
$provide.value("UserService", {
getUsers: jasmine.createSpy("getUsers").and.returnValue([]),
getUserById: jasmine.createSpy("getUserById").and.returnValue(null),
saveUser: jasmine.createSpy("saveUser").and.returnValue(true),
deleteUser: jasmine.createSpy("deleteUser").and.returnValue(true),
});
// Mock AuthService
$provide.value("AuthService", {
isAuthenticated: jasmine
.createSpy("isAuthenticated")
.and.returnValue(true),
getCurrentUser: jasmine.createSpy("getCurrentUser").and.returnValue({
id: 1,
name: "Current User",
}),
logout: jasmine.createSpy("logout"),
});
})
);
/**
* Inject and initialize test fixtures
*/
beforeEach(inject(function (
_$controller_,
_$rootScope_,
_$q_,
_$httpBackend_,
_$timeout_,
_UserService_,
_AuthService_
) {
$controller = _$controller_;
$scope = _$rootScope_.$new();
$q = _$q_;
$httpBackend = _$httpBackend_;
$timeout = _$timeout_;
UserService = _UserService_;
AuthService = _AuthService_;
// Create controller instance
UserController = $controller("UserController", {
$scope: $scope,
UserService: UserService,
AuthService: AuthService,
});
}));
/**
* Clean up after each test
*/
afterEach(function () {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
// ==========================================================================
// INITIALIZATION TESTS
// ==========================================================================
describe("Controller Initialization", function () {
it("should initialize with default values", function () {
expect(UserController).toBeDefined();
expect($scope.users).toBeDefined();
expect($scope.loading).toBe(false);
expect($scope.error).toBeNull();
});
it("should load users on initialization", function () {
UserService.getUsers.and.returnValue([
{ id: 1, name: "User 1" },
{ id: 2, name: "User 2" },
]);
var result = UserController.loadUsers();
expect(UserService.getUsers).toHaveBeenCalled();
expect($scope.users).toBeDefined();
});
it("should check authentication on initialization", function () {
expect(AuthService.isAuthenticated).toHaveBeenCalled();
expect($scope.currentUser).toBeDefined();
});
});
// ==========================================================================
// METHOD TESTS
// ==========================================================================
describe("UserController.loadUsers()", function () {
it("should fetch users from service", function () {
var mockUsers = [
{ id: 1, name: "John", email: "john@example.com" },
{ id: 2, name: "Jane", email: "jane@example.com" },
];
UserService.getUsers.and.returnValue(mockUsers);
UserController.loadUsers();
expect(UserService.getUsers).toHaveBeenCalled();
expect($scope.users).toEqual(mockUsers);
expect($scope.error).toBeNull();
});
it("should set loading state during fetch", function () {
var deferred = $q.defer();
UserService.getUsers.and.returnValue(deferred.promise);
$scope.loading = false;
UserController.loadUsers();
expect($scope.loading).toBe(true);
deferred.resolve([]);
$scope.$apply();
expect($scope.loading).toBe(false);
});
it("should handle loading errors gracefully", function () {
var deferred = $q.defer();
UserService.getUsers.and.returnValue(deferred.promise);
UserController.loadUsers();
deferred.reject("API Error");
$scope.$apply();
expect($scope.error).toBe("API Error");
expect($scope.users).toEqual([]);
});
});
describe("UserController.selectUser()", function () {
it("should set selected user", function () {
var user = { id: 1, name: "John" };
$scope.selectedUser = null;
UserController.selectUser(user);
expect($scope.selectedUser).toEqual(user);
});
it("should fetch user details", function () {
var user = { id: 1, name: "John" };
UserService.getUserById.and.returnValue(user);
UserController.selectUser(user);
expect(UserService.getUserById).toHaveBeenCalledWith(1);
expect($scope.selectedUser).toEqual(user);
});
it("should handle null user", function () {
UserController.selectUser(null);
expect($scope.selectedUser).toBeNull();
});
});
describe("UserController.saveUser()", function () {
it("should save user data", function () {
$scope.user = { id: 1, name: "John", email: "john@example.com" };
UserService.saveUser.and.returnValue(true);
UserController.saveUser();
expect(UserService.saveUser).toHaveBeenCalledWith($scope.user);
});
it("should clear form after successful save", function () {
$scope.user = { id: 1, name: "John" };
UserService.saveUser.and.returnValue(true);
UserController.saveUser();
expect($scope.user).toEqual({});
expect($scope.error).toBeNull();
});
it("should display error on save failure", function () {
$scope.user = { id: 1, name: "John" };
UserService.saveUser.and.returnValue(false);
UserController.saveUser();
expect($scope.error).toBe("Failed to save user");
});
it("should validate required fields before save", function () {
$scope.user = { name: "", email: "" };
UserController.saveUser();
expect(UserService.saveUser).not.toHaveBeenCalled();
expect($scope.error).toBeDefined();
});
});
describe("UserController.deleteUser()", function () {
it("should delete user with confirmation", function () {
$scope.selectedUser = { id: 1, name: "John" };
spyOn(window, "confirm").and.returnValue(true);
UserController.deleteUser();
expect(window.confirm).toHaveBeenCalled();
expect(UserService.deleteUser).toHaveBeenCalledWith(1);
});
it("should not delete without confirmation", function () {
$scope.selectedUser = { id: 1, name: "John" };
spyOn(window, "confirm").and.returnValue(false);
UserController.deleteUser();
expect(UserService.deleteUser).not.toHaveBeenCalled();
});
it("should refresh list after successful delete", function () {
$scope.selectedUser = { id: 1, name: "John" };
$scope.users = [
{ id: 1, name: "John" },
{ id: 2, name: "Jane" },
];
spyOn(window, "confirm").and.returnValue(true);
UserService.deleteUser.and.returnValue(true);
UserController.deleteUser();
expect($scope.users.length).toBeLessThan(2);
expect($scope.selectedUser).toBeNull();
});
});
// ==========================================================================
// EVENT HANDLING TESTS
// ==========================================================================
describe("UserController Event Handling", function () {
it("should handle user:updated event", function () {
var updatedUser = { id: 1, name: "Updated User" };
spyOn(UserController, "loadUsers");
$scope.$broadcast("user:updated", updatedUser);
expect(UserController.loadUsers).toHaveBeenCalled();
});
it("should handle user:deleted event", function () {
$scope.selectedUser = { id: 1, name: "John" };
$scope.$broadcast("user:deleted", 1);
expect($scope.selectedUser).toBeNull();
});
it("should emit event when user is selected", function () {
spyOn($scope, "$emit");
var user = { id: 1, name: "John" };
UserController.selectUser(user);
expect($scope.$emit).toHaveBeenCalledWith("user:selected", user);
});
});
// ==========================================================================
// SCOPE TESTS
// ==========================================================================
describe("UserController Scope Methods", function () {
it("should expose controller methods on scope", function () {
expect($scope.loadUsers).toBeDefined();
expect($scope.selectUser).toBeDefined();
expect($scope.saveUser).toBeDefined();
expect($scope.deleteUser).toBeDefined();
});
it("should initialize scope properties", function () {
expect($scope.users).toBeDefined();
expect($scope.selectedUser).toBeDefined();
expect($scope.loading).toBeDefined();
expect($scope.error).toBeDefined();
});
});
// ==========================================================================
// EDGE CASES AND ERROR HANDLING
// ==========================================================================
describe("Error Handling", function () {
it("should handle undefined user service", function () {
expect(function () {
UserController.loadUsers();
}).not.toThrow();
});
it("should handle null response data", function () {
UserService.getUsers.and.returnValue(null);
UserController.loadUsers();
expect($scope.users).toEqual(null);
});
it("should handle empty user list", function () {
UserService.getUsers.and.returnValue([]);
UserController.loadUsers();
expect($scope.users.length).toBe(0);
});
it("should handle malformed user data", function () {
UserService.getUsers.and.returnValue([
{ id: 1 }, // Missing name
{ name: "Jane" }, // Missing id
]);
UserController.loadUsers();
expect($scope.users.length).toBe(2);
});
});
// ==========================================================================
// ASYNC OPERATIONS
// ==========================================================================
describe("Async Operations", function () {
it("should handle promise resolution", function () {
var deferred = $q.defer();
UserService.getUsers.and.returnValue(deferred.promise);
UserController.loadUsers();
var result = [{ id: 1, name: "John" }];
deferred.resolve(result);
$scope.$apply(); // Trigger digest cycle
expect($scope.users).toEqual(result);
});
it("should handle promise rejection", function () {
var deferred = $q.defer();
UserService.getUsers.and.returnValue(deferred.promise);
UserController.loadUsers();
deferred.reject("Network error");
$scope.$apply();
expect($scope.error).toBe("Network error");
});
it("should handle $timeout operations", function () {
$scope.message = "";
UserController.showMessage("Welcome!");
expect($scope.message).toBe("Welcome!");
$timeout.flush();
expect($scope.message).toBe("");
});
});
});
// ============================================================================
// JEST VERSION
// ============================================================================
describe("UserController (Jest)", () => {
let controller;
let scope;
let userService;
let authService;
beforeEach(() => {
// Mock services
userService = {
getUsers: jest.fn().mockReturnValue([]),
getUserById: jest.fn().mockReturnValue(null),
saveUser: jest.fn().mockReturnValue(true),
deleteUser: jest.fn().mockReturnValue(true),
};
authService = {
isAuthenticated: jest.fn().mockReturnValue(true),
getCurrentUser: jest
.fn()
.mockReturnValue({ id: 1, name: "Current User" }),
logout: jest.fn(),
};
// Create mock scope
scope = {
users: [],
selectedUser: null,
loading: false,
error: null,
};
// Controller logic would be extracted and tested here
controller = {
loadUsers: jest.fn(),
selectUser: jest.fn(),
saveUser: jest.fn(),
deleteUser: jest.fn(),
};
});
describe("Initialization", () => {
test("should initialize with default values", () => {
expect(controller).toBeDefined();
expect(scope.loading).toBe(false);
expect(scope.error).toBeNull();
});
test("should load users on initialization", () => {
userService.getUsers.mockReturnValue([
{ id: 1, name: "User 1" },
{ id: 2, name: "User 2" },
]);
expect(userService.getUsers).toBeDefined();
});
});
describe("Methods", () => {
test("should call loadUsers", () => {
controller.loadUsers();
expect(controller.loadUsers).toHaveBeenCalled();
});
test("should call selectUser with user data", () => {
const user = { id: 1, name: "John" };
controller.selectUser(user);
expect(controller.selectUser).toHaveBeenCalledWith(user);
});
});
describe("Error Handling", () => {
test("should handle errors gracefully", () => {
expect(() => {
controller.loadUsers();
}).not.toThrow();
});
test("should handle null responses", () => {
userService.getUsers.mockReturnValue(null);
expect(userService.getUsers()).toBeNull();
});
});
});