Mocking google.maps.LatLng in jest - unit-testing

I am using heatmap layer for google maps, and while mapping data for heatmap, i am using constructor new google.maps.LatLng(lat, lng), and everything works file. In index.html file i have loaded //maps.googleapis.com/maps/api... and i guess that is where i get global google object with which i can call that constructor.
So the real issue is when I try to write unit test for that using Jest.
I get the message that google is not defined in global.
I tried to mock global.google in the setup for the tests but couldn't get it done.

use https://www.npmjs.com/package/#googlemaps/jest-mocks.
import { initialize } from "#googlemaps/jest-mocks";
beforeEach(() => {
initialize();
});
// Your tests

Related

Mocking PDFtron webviewer with jest in react application

Hi I am new to unit testing and I am trying to mock the 'annotationManager' of the PDFtron webviewer
I am using this below code in my test file
jest.mock('#pdftron/webviewer', () =>({
annotationManager: {
getAnnotationsList: jest.fn().mockReturnValue([]),
deleteAnnotations: jest.fn()
},
}));
In the code, I'm getting the list of annotations using 'getAnnotationsList' function and deleting it using 'deleteAnnotations' function.
In the log of the unit tests, I'm getting this following error
'cannot read the properties of undefined (reading 'getAnnotationsList')
Is this the correct way to doing things or am I missing something?
are you able to share an example of a test you are writing where you need to mock the annotation manager? Depending on how you are using the WebViewer package, mocking the annotation manager can be different. If you prefer to reach out to Apryse directly you can also reach out to them via their support form

ReferenceError: ga is not defined [Ionic 2.2 Unit Testing With Karma]

I'm adding unit tests to an Ionic 2.2.0 app I manage, but my Components crash at test-time when they encounter Google Analytics code. I'm using Ionic's official unit testing example as a basis, and my current progress can be seen on our public repo.
My project uses Google Analytics, which is added to the HTML and downloaded at runtime (because we have different keys for development vs production).
The code that initializes Analytics is in my main.ts, and it sets a global variable ga, which is subsequently available throughout the application.
I'm beginning the tests for the app's first page, which uses Analytics. When I run the tests, I'm met with the following error
Component should be created FAILED
ReferenceError: ga is not defined
at new MyBusesComponent (webpack:///src/pages/my-buses/my-buses.component.ts:33:6 <- karma-test-shim.js:138419:9)
at new Wrapper_MyBusesComponent (/DynamicTestModule/MyBusesComponent/wrapper.ngfactory.js:7:18)
at CompiledTemplate.proxyViewClass.View_MyBusesComponent_Host0.createInternal (/DynamicTestModule/MyBusesComponent/host.ngfactory.js:15:32)
........
This is because main.ts doesn't seem to be loaded or executed, and I assume TestBed is doing that purposefully. It's certainly better that I don't have the actual Google Analytics object, but the Component does need a function called ga.
My question, therefore, is as follows: how can I create Google Analytics' ga variable in my test configuration such that it's passed through to my components at test-time?
I've tried exporting a function from my mocks file and adding it to either the imports or providers arrays in my spec file, but to no avail.
I appreciate any advice! Feel free to check my code at our repo I linked to above and ask any followups you need. Thanks!
You declare the var ga but that is just to make TypeScript happy. At runtime, the ga is made global from some external script. But this script is not included in the test.
What you could do is just add the (mock) function to the window for the tests. You could probably do this in your karma-test-shim.js.
window.ga = function() {}
Or if you wanted to test that the component is calling the function with the correct arguments, you could just add the function separately in each test that uses the function. For example
beforeEach(() => {
(<any>window).ga = jasmine.createSpy('ga');
});
afterEach(() => {
(<any>window).ga = undefined;
})
Then in your test
it('..', () => {
const fixture = TestBed.creatComponent(MyBusesComponent);
expect(window.ga.calls.allArgs()).toEqual([
['set', 'page', '/my-buses.html'],
['send', 'pageview']
]);
})
Since you're making multiple calls to ga in the constructor, the Spy.calls will get the argument of all each call and put them in separate arrays.

Faking a module in angular 2 test

I have a function in angular 2 service which I would like to test.
service.ts
upload(){
let file = new Transfer();
file.upload(myfile).then( // my callback );
}
I would like to mock Transfer in my test using jasmine. I tried this in my
sevice.spec.ts
import { TransferMock as Transfer } from '../mocks/mocks' to mock it. But it is not working. This is how my test is instantiated .
describe('authentication service' , () => {
beforeEach(() => {
auth = new Service(<any>new HttpMock(), <any>new StorageMock())
});
it('initialize authentication',() => {
expect(auth).not.toEqual(null);
auth.upload('file'); //it fails here
});
})
edit
Transfer is not injected in the service. Only one function uses Transfer . So not injecting can reduce the initial loading time of the app i guess(would be happy to know other opinions) . So I would like to know if there is anyway to mock if its constructed this way ?
edit
Although I had accepted Martin's answer as it is the best practice, it has one issue which can happen when you use ionic-native plugins.If the plugin doesnt have browser support it can fail. In this case it happened when I inject it, with error FileTransfer is not defined . So I am back again, looking for suggestions.
In order to provide a mock for a class in a test, you need to inject the class in your implementation.
In your ngModule add Transfer to your providers. Then simply inject it into your service.
Then in your test you can use { provide: Transfer, useClass: TransferMock } in your TestBed providers.
Update
The primary purpose of Dependency Injection is to make code testable and to allow mocking - faking - stubbing of services.
Update
With Dependancy Injection you can configure a different set of providers for different environments.
For example, if you are running your application in the browser, and in a native mobile environment you can swap out your configuration.
In your module you could have something like this:
const TRANSFER_PROVIDER: any;
if (environment.browser) {
TRANSFER_PROVIDER = Transfer;
} else {
TRANSFER_PROVIDER = { provide: Transfer, useClass: NativeTransfer }
}
...
providers: [ TRANSFER_PROVIDER ]
NativeTransfer could be a simple stub that does nothing but prevent errors, or it could let the user know that this feature is not supported in their browser.

load json file for jasmine test with angular.js

I have mock data in an external json file that I want to have available for Jasmine unit tests in Angular.js. Unfortunately I am not approved to run node.js in my dev environment, so the usual karma examples don't apply to me.
I have tried:
beforeEach(inject(function ($injector, $http) {
console.log('this gets called');
$http.get('/mockData/surveySetup.json').success(function (data) {
console.log('this never gets called');
}).error(function () {
console.log('this never gets called');
});
}));
The console.log outside of the $http.get gets called, but the ones inside $http.get never fire, and I don't see a call to the json file in chrome's network tab.
What can I do to load this file to use in my tests? At the end of the day I just need to have access to the data in the .json file so I can refer to it in my unit tests.
Thanks in advance.
I found that I needed to convert my .json file to an Angular service (actually an Angular constant worked for my purposes). Then my external file was easy to grab in my tests, like so:
var setupData = $injector.get('SetupData');
$httpBackend.whenGET('/surveySetup').respond(setupData);
$httpBackend.flush();
Not sure what exactly are going to achieve but usually you can configure this by using $httpBackend which can be configured to mock the actual requests from any of your code (you may also need to setup with your URL syntax in this case but anyway this the common case for the unit tests. In this case you don't need to read the JSON file you can just provide the JS object inside of the $httpBackend configuration for that URL and when this URL is to be invoked $httpBackend will return the specified object. Look at: $httpBackend

How do I get a resource from an Angular.js module for a jasmine test

I have a module that contains resources for a project, and the code looks like this:
editor_services.js
var editorServices = angular.module('editorServices', ['ngResource']);
editorServices.factory('Project', ['$resource', '$http',function($resource, $http){
//...etc
now I would like to write tests for a controller that expects a project resource as an argument. How can I get an instance of the project resource that is created by this factory out of the editorServices variable?
Here is a working example how one would test Resources (or http) in angular
http://plnkr.co/edit/kK5fDFIVpyZTInH1c6Vh?p=preview
The basic setup is:
load angular-mocks.js in your test. This replaces the $httpBackend with mock version. See: http://docs.angularjs.org/api/ngMock.$httpBackend
In your test call $httpBackend.expect() to create expectation to be mocked out.
When you want to simulate server response call $httpBackend.flush()
There is a caveat that normal .toEqual() from jasmine dose not work with $resource so you have to create custom matcher like so:
beforeEach(function() {
this.addMatchers({
// we need to use toEqualData because the Resource hase extra properties
// which make simple .toEqual not work.
toEqualData: function(expect) {
return angular.equals(expect, this.actual);
}
});
});