How to mock an external enum setting in Jasmine - angularjs

I'm testing an AngularJS service with Jasmine. The service calls a function in another service using an enum from another module as a parameter.
public getSavedColumns = (): ng.IPromise<GridColumn[]> => {
return this.productSettingsService.readProjectSetting(
psfc.ApplicationId.Calculator, this.getColumnStorageProperty())
.then(response => { /**/ });
};
psfc.ApplicationId is an enum in another module:
export enum ApplicationId {
Calculator = 2636
}
The Jasmine tests fail with the error:
TypeError 'undefined' is not an object (evaluating 'psfc.ApplicationId.Calculator')
I thought I could mock the enum in the test, but it doesn't change the outcome.
beforeEach(() => {
angular.mock.module('pw_psfc',
$provide => {
$provide.constant('psfc.ApplicationId.Calculator', 0);
});
});

I was able to solve my problem by including the file with the exported enum in the karma configuration. Five months is a pretty slow learning curve, but I'm getting there! =~)

Related

Angular JS $injector - get dependencies

I need to get the instances of my Services/Factory in my Angular JS application. For that reason I would want to use $injector so as to get instances and not depend on DI. I tried to create a wrapper method over $injector which is a seperate js file so that any other modules can call this helper method and get necessary instances. I know this is not straight forward but still wanted to try.
For this my code looks like
//helper.js file
export default function returnInstances(service) {
const app = angular.module('moduleName');
let instance;
app.run(() => {
injector = angular.injector(['ng', 'moduleName']);
instance = injector.get(service);
});
return instance;
}
// some other file
const instance = returnInstances('serviceName');
As expected this does not work. So I was wondering if anything like this is possible.
const helper = {
init: (injector) => this.injector = injector;
get: (name) => this.injector.get(name);
}
export default helper;
And in file where you bootstrap your module:
app.run((['$injector'], $injector) => helper.init($injector));
angular.bootstrap(...
And then u can use it.

'angular is not defined' in mocha tests

I'm trying to test a controller function which does a very basic task, some snippets below
I import an enum from a custom module I made
import { CurrentUser, Right } from "habenero-identity";
In the controller, I then have the following function
entercanAddModem = () => {
this.user.hasRight(Right.AddModem);
};
When i try to test this with:
#test
canAddModemCallsUserHasRight() {
this.user = { hasRight: sinon.spy() };
var sut = this.sut();
sut.canAddModem();
}
It tells me Right.AddModem is undefined
When I try to stub the Right Enum with
sinon.stub(Right, "AddModem").returns(14);
I get the error
`D:\Repos\Complete\node_modules\angular\index.js:2
module.exports = angular;
^
source-map-support.js:445
ReferenceError: angular is not defined`
IN the habenero-identity module
i tried the angularcontext module, I tried importing angular, i tried putting it on the global variable...nothing works

How to call toHaveBeenCalledWith with multiple parameters?

Hi I am developing web application in Angular JS. I am writing unit test cases using Jasmine framework. I am trying to mock some services. I am not able to call service with multiple parameters. Below is my unit test code.
it('update is allowed false', async(() => {
let service = fixture.debugElement.injector.get(UserOnboardEndpointMock);
spyOn(service, 'updateUser').and.callThrough();
fixture.whenStable().then(() => {
expect(service.updateUser).toHaveBeenCalledWith(jasmine.any(true,"101"));
})
}));
Below is my service.
updateUser<T>(event: boolean, userid: string): Observable<T>{
var updateUserResult = { result: true } as any;
return Observable.of<T>(updateUserResult);
}
I have tried as below to call service but nothing worked out.
expect(service.updateUser).toHaveBeenCalledWith(true,"101");
expect(service.updateUser).toHaveBeenCalledWith([true]["101"]);
Can someone help me to call my mock services? Any help would be appreciated. Thank you
Since jest 23.0 there is .toHaveBeenNthCalledWith(nthCall, arg1, arg2, ....) https://facebook.github.io/jest/docs/en/expect.html#tohavebeennthcalledwithnthcall-arg1-arg2-
So you could make an assertion like:
expect(service.updateUser).toHaveBeenNthCalledWith(1, true,"101");

Unit Testing Component in AngularJS 1.5 and Typescript

Working on converting some old broken AngularJS unit tests to TypeScript and came across this error:
Error: [$injector:unpr] Unknown provider: myComponentDirectiveProvider <- myComponentDirective
In every example of AngularJS unit testing I've seen, they have a main module with everything on it, and they inject that main module into the unit test with angular.mock.module('theWholeStinkingApp'). That is nice for a little tutorial, but I'm dealing with a very large application with hundreds of components and dozens of services. Not to mention filters and other directives. It doesn't work to just inject the whole app into a unit test. Nor do I think it's a good idea to start up the whole app just to unit test a component (kind of defeats the purpose of unit testing when you have to include everything you own in every test).
For testing services I can just create my module in the test in a beforeEach like this, so I'm mocking dependencies, but injecting the real service I want to test:
angular.mock.module(($provide) => {
$provide.service('firstDependency', FirstDependencyMock);
$provide.service('secondDependency', SecondDependencyMock);
$provide.service('serviceIWantToTest', ServiceIWantToTest);
});
I can't figure out how to do this and inject a Component. Any help would be appreciated.
Please keep in mind, I do not want to have to angular.mock.module('theWholeApp') to get this working. I just want to create a mock module and attach my component to it.
Here's a slimmed down version of what I'm doing.
Component looks something like this
angular.module('theWholeApp', [])
.component('myComponent', {
controller: MyComponentController, // class is defined elsewhere
templateUrl: 'path/to/my/template.html'
)
... // 100+ other components;
Here's the test:
describe('MyComponent', () => {
beforeEach(() => {
// angular.mock.module('theWholeApp'); This is not an option.
// Creating a mock module with just the dependencies I need for this test
angular.mock.module(($provide) => {
$provide.service('firstDependency', FirstDependencyMock);
$provide.service('secondDependency', SecondDependencyMock);
});
// Tried adding this to register the controller, but it doesn't help.
angular.mock.module(($controllerProvider) => {
$controllerProvider.register('MyComponentController', MyComponentController);
});
angular.mock.inject(($injector) => {
$rootScope = $injector.get('$rootScope');
$componentController = $injector.get('$componentController');
firstDependency= $injector.get('firstDependency');
secondDependency= $injector.get('secondDependency');
$scope = $rootScope.$new();
});
});
describe('doSomething', () => {
it('exists', () => {
controller = $componentController('myComponent', {$scope});
expect(controller.doSomething).toBeDefined();
});
});
});
Obviously, this isn't the live code, just a representation. Hopefully I got all the made up names right. The point is, I want to create a mock module and add my component to it so a call to $componentController('myComponent', {$scope}) works.
Thanks!
Alright, the answer I came up with is deceptively simple, but I've never seen it done anywhere. If anyone can tell me why it's a bad idea and suggest something better, I'm all for it.
The answer is to just create the module you want then immediately add it to the test.
describe('MyComponent', () => {
// Create a new module with the things you need.
// Putting it outside the "beforeEach" because it only needs to be created once.
angular.module('myComponentTestModule', [])
.component('myComponent', {
controller: MyComponentController, // class is defined elsewhere
templateUrl: 'path/to/my/template.html'
)
.service('firstDependency', FirstDependencyMock)
.service('secondDependency', SecondDependencyMock);
beforeEach(() => {
// Add the new module to the test suite
angular.mock.module('myComponentTestModule');
angular.mock.inject(($injector) => {
$rootScope = $injector.get('$rootScope');
$componentController = $injector.get('$componentController');
firstDependency= $injector.get('firstDependency');
secondDependency= $injector.get('secondDependency');
$scope = $rootScope.$new();
});
});
describe('doSomething', () => {
it('exists', () => {
controller = $componentController('myComponent', {$scope});
expect(controller.doSomething).toBeDefined();
});
});
});

Injected Dependency is undefined in Unit Test

I'm new to Angular and I'm not quite sure exactly how dependency injection works. My problem is that I have Service A which depends on Service B, but when I inject Service A into my test Service B becomes undefined.
I have seen Injecting dependent services when unit testing AngularJS services but that problem is a bit different than mine.
This Injected Dependencies become undefined in angular service is very similar to my issue but I couldn't translate the JS.
I have also changed my variable names and simplified the code to remove irrelevant lines.
Service.ts
export class ServiceA {
constructor(private $resource: ng.resource.IResourceService, private ServiceBInstance: ServiceB){
}
ServiceAMethod() {
var resources = ServiceBInstance.property; //ServiceBInstance is undefined here
}
}
factory.$inject = [
'$resource'
'ServiceBModule'
];
function factory($resource: ng.resource.IResourceService, ServiceBInstance: ServiceB): IServiceA {
return new ServiceA($resource, ServiceBInstance);
}
angular
.module('ServiceAModule')
.factory('ServiceA',
factory);
Spec.ts
describe('ServiceB', (): void => {
beforeEach((): void => {
angular.mock.module(
'ServiceAModule',
'ServiceBmodule',
'ngResource'
);
});
describe('ServiceAMethod', (): void => {
it("should...", inject(
['ServiceA', (ServiceAInstance: ServiceA): void => {
ServiceAInstance.ServiceAMethod(); //Problem Here
}]));
});
});
The problem I'm having is that when I call ServiceAMethod I get an error which states "TypeError: Cannot read property 'property' of undefined". The weird thing is that $resource is never undefined but my ServiceB is always undefined.
I thought that when I inject ServiceA into my test it should automatically also inject all of its dependencies.
Also note that I am not mocking ServiceB on purpose.
Update
I've also tried to inject an instance of my ServiceB into the it but when I print out the variable it also states that is it undefined, and when I try to to do the code below into the beforeEach
inject(function (_ServiceBInstance_: ServiceB) {
console.log(_ServiceBInstance_);
});
I get and Unknown Provider error.
Ok so after hours of searching I finally found the answer. I forgot to include a file which included Angular's .config method
When creating the provider make sure that you also call .config, here's an example:
angular
.module('ServiceBModule')
.config(['ServiceBProvider', (ServiceBClass) => { //Very Important
//Code here
}])
.provider('ServiceB', ServiceB);

Resources