Unit Test [Jasmin] how to cover function with find method and indexOf? - unit-testing

I need help with cover function on jasmine. I have an array, an array can contain many objects
const providers =[
{
countries: ["GB"],
network: "Test GB",
link: "https://test.com"
},
]
I have a function myFunc..
myFunc: function () {
var country = this.userCountry;
this.provider = providers.find(function(provider) {
return provider.countries.indexOf(userCountry) > -1;
}) || this.config.watchButton.defaultProvider;
}
Also i wrote some unit test, but without some
describe("[TEST] smyFunc method...", function () {
var country;
beforeEach(function () {
spyOn(baseMethods, 'setProviderData');
baseMethods.config = {
watchButton: {
provider: {
countries: ["GB"],
network: "Test GB",
link: "https://test.com"
},
default: {
network: "Test default",
link: "https://default.com"
}
}
};
});
it('[TEST] If country expist in provider.', function () {
country = 'GB';
baseMethods.myFunc();
expect($.fn.provider, 'find').toBe(provider);
});
});
How should I write a test with the find and indexOf methods for tests? I will be grateful for any advice

Related

how can I write unit test case for Google Directives

google.directives.ts:->
getPlaceAutocomplete(addresstext: ElementRef) {
const autocomplete = new google.maps.places.Autocomplete(addresstext.nativeElement,
{
componentRestrictions: { country: 'US' },
fields: ['address_components', 'geometry'],
types: ['address']
});
google.maps.event.addListener(autocomplete, 'place_changed', () => {
const place = autocomplete.getPlace();
this.googleAutocompleteSubject.next(place);
});
how can I write test case for google directive?

(Apollo client v3) useLazyQuery custom hook testing

I was struggling with a test issue for my custom useLazyQuery hook. My first test is passing but the second one is failing. What am doing wrong for the second test?
Here is the useLazyFetchCoin.tsx
export const useLazyFetchCoin = () => {
const [coins, setCoins] = useState<ICoin[]>([]);
useEffect(() => {
const coins = localStorage.getItem('coinsInfo');
if (coins) {
setCoins(JSON.parse(coins));
}
}, []);
const [getData, { loading, error }] = useLazyQuery(GET_COIN_PRICE_QUERY, {
fetchPolicy: 'network-only',
notifyOnNetworkStatusChange: true,
onCompleted: (data) => {
const hasSameCoin = coins.some((f) => f.id === data.markets[0]?.id);
if (data.markets.length && !hasSameCoin) {
const allCoins = [...coins, data.markets[0]];
setCoins(allCoins);
localStorage.setItem('coinsInfo', JSON.stringify(allCoins));
} else if (data.markets.length <= 0) {
alertNotification('Coin not found !', Notification.ERROR);
}
if (hasSameCoin) {
alertNotification('This coin already exists on your list !', Notification.WARNING);
}
}
});
return { coins, setCoins, getData, loading, error };
};
Here is the test file
describe('useLazyFetchCoin custom hook', () => {
const QueryMock = [
{
request: {
query: GET_COIN_PRICE_QUERY,
variables: { code: 'BNB' }
},
result: {
data: {
markets: [
{
id: 'binance_bnb_eur',
baseSymbol: 'BNB',
ticker: {
lastPrice: '414.90000000'
}
}
]
}
}
}
];
const QueryWrongCodeMock = [
{
request: {
query: GET_COIN_PRICE_QUERY,
variables: { code: 'asd' }
},
result: {
data: {
markets: []
}
}
}
];
function getHookWrapper(mocks: any, code: string) {
const wrapper = ({ children }: any) => (
<MockedProvider mocks={mocks} addTypename={false}>
{children}
</MockedProvider>
);
const { result, waitForNextUpdate } = renderHook(() => useLazyFetchCoin(), {
wrapper
});
expect(typeof result.current.coins).toBe('object');
expect(result.current.loading).toBeFalsy();
expect(result.current.error).toBeUndefined();
// call the lazy function
act(() => {
result.current.getData({
variables: { code }
});
});
return { result, waitForNextUpdate };
}
it('should return an array of coins', async () => {
// Working correctly
const { result, waitForNextUpdate } = getHookWrapper(QueryMock, 'BNB');
await waitForNextUpdate();
expect(result.current.loading).toBeFalsy();
expect(result.current.coins[0]).toEqual({
id: 'binance_bnb_eur',
baseSymbol: 'BNB',
ticker: {
lastPrice: '414.90000000'
}
});
});
it('should return an empty array when requesting a wrong code', async () => {
// Not working
const { result, waitForNextUpdate } = getHookWrapper(QueryWrongCodeMock, 'asd');
await waitForNextUpdate();
expect(result.current.loading).toBeFalsy();
expect(result.current.coins[0]).toEqual([]);
});
});
I got this error message for the second test.
Expected: []
Received: {"baseSymbol": "BNB", "id": "binance_bnb_eur", "ticker": {"lastPrice": "414.90000000"}}
I don't get it because I'm using different queries for each test.
Also, the second test should receive an empty array when you pass a wrong code such as 'asd'.
How can write a proper test for it?
I fixed the problem. When I was changing the order test, It worked correctly.
I added a clear mock function for it.
clear mock

Unit testing the instance of Sequelize Model

I have the following code:
async save(id: string) {
const person = await PersonModel.findOne({
where: { id: id },
});
if (!person) {
await PersonModel.create({
id: '2345',
name: 'John Doe',
age: 25
});
return;
}
await person.increment({ age: 15 });
}
Now, I wanted to test person.increment() in which the age will be added with 15. I have the following code to escape the condition that will create a new record for the model.
const findOneFake = sinon.spy(() => {
return {}; //returns empty object or true
});
const proxy = (proxyquire('./path/to/file.ts', {
'./path/to/PersonModel.ts': {
default: {
findOne: findOneFake
}
}
})).default;
beforeEach(async () => {
await save();
});
it('should increment age with 15');
How am I going to do that? What do I do to test it? I can use sinon.fake() to PersonModel.create or PersonModel.update but I am troubled testing the instance of a Sequelize Model.

Redux reducer unit test

And I'm trying to make unit-test for redux reducer. But i'm struggling with receiving the same expected and equal results.
const initState = {};
export default function (state = initState, action) {
const newState = { ...state };
switch (action.type) {
case CREATE_TYPE:
return {
...state,
[action.customType.id]: {
...action.customType
}
};
default:
return state;
}
}
My test. Seems that problem in customType: { id: 'test-id' }
describe('reducer', () => {
it('should return the initial state', () => {
const state = reducer(undefined, { type: 'unknown' });
expect(state).toEqual({});
});
it('should handle CREATE_TYPE', () => {
expect(reducer({ test: true }, {
type: CREATE_TYPE,
customType: { id: 'test-id' },
id: 'test-id'
})).toEqual({
'test-id': 'test-type',
'test': true
});
});
});
Often it helps to spell everything out.
That way you can clearly understand what your expected outcome needs to be.
it('should handle CREATE_TYPE', () => {
const initialState = { test: true };
const customType = { id: 'test-id' };
const action = {
type: CREATE_TYPE,
customType: customType,
id: customType.id
};
const result = reducer(initialState, action);
const expectedResult = {
test: true,
[customType.id]: customType
};
expect(result).toEqual(expectedResult);
});
It then becomes easier to see exactly where the issue lies.
You are exprecting back from your reducer :
{
...state,
[action.customType.id]: {
...action.customType
}
which if you send
{
type: CREATE_TYPE,
customType: { id: 'test-id' },
id: 'test-id'
}
Will equate itself to :
{
...state,
'test-id' : { id: 'test-id' }
}
and you are evaluating it equal to
{
...state,
'test-id': 'test-type'
}
I don't know how you are expecting to format your state via your reducer - but the way your reducer is set up now will not provide the state you are expecting. I don't know what you are expecting because i don't see the node or value 'test-type' anywhere else in your provided code. It looks like you just have some syntactical errors maybe?

Decouple Knockout dependencies in Jasmine unit tests

I am introducing javascript unit tests to my company's application. I've worked predominantly with AngularJS, but their framework of choice is Knockout. The code is relatively modular in design (thanks to Knockout), so I assumed it would be easy to add unit tests around the code (much like Angular is).
However, there is a further complication: the system uses require.js as an IoC container. Also, my test runner is Chutzpah, which is headless/in the Visual Studio Test Explorer. I have tried to mock out the dependencies using SquireJS, but I run into a snag when trying to instantiate the ViewModel: it wants certain dependencies that are set up in the Component and inherited. I try to load the component, which has further dependencies, and so on and so on. Below I have a dumbed-down version of the setup that outlines the point. What is the best way to instantiate this view model so that I can mock out the dependencies with Squire and run my tests?
Component
define(function (require) {
var Boiler = require('Boiler'),
BaseViewModel = require('../../../../core/baseClasses/BaseViewModel'),
viewTemplate = require('text!./view.html'),
viewModel = require('./viewModel'),
nls = require('i18n!./nls/resources');
var Component = function (initializingParameters) {
//...blah blah blah setup things
};
return Component;
});
ViewModel
define(function (require) {
var Constants = require('../../../../core/constants');
var momDate = moment().format('MMM DD, YYYY');
var Utils = require("../../../../model/utils");
var utils = new Utils();
var otherComponentUtils = require("../../../otherModule/otherComponent/OtherComponentUtils");
var otherComponentUtils = new OtherComponentUtils();
var ViewModel = function (globalContext, moduleContext, dataContext, domElement) {
var Self = this;
Self.super(moduleContext, dataContext, resPickerContext);
var constants = new Constants();
var utils = require("../../../../model/utils");
var Utils = new utils();
Self.Items = ko.observableArray().extend({ throttle: 500 });
//a bunch more Knockout object setup
Self.GetAuthorizationTypesArray = function (itemId) {
dataContext.dataRequestHandler(dataContext.serviceConstants.GetTransactionTypes, { ItemId: itemId },
function (data) {
if (data != null && data.length !== 0) {
Self.TransactionTypeArray(data);
var transactionTypeArray = Self.TransactionTypeArray();
if (transactionTypeArray.length) {
var paymentInfo = Self.PaymentInfo();
if (paymentInfo !== null && paymentInfo !== undefined && paymentInfo.IsSpecial) {
var childThing = Self.ChildThing();
dataContext.dataRequestHandler(dataContext.serviceConstants.GetChild, { ChildId: childThing.ChildId, SpecialId: childThing.SpecialID }, function (data) {
var child = data[0];
var specialTypeId = child.ListId;
if (specialTypeId === 13)
Self.BigThing.Type(1);
else
Self.BigThing.Type(2);
}, Self.ShowError);
}
}
}
},
Self.ShowError);
}
return ViewModel;
});
chutzpah.json
{
"Framework": "jasmine",
"TestHarnessReferenceMode": "AMD",
"TestHarnessLocationMode": "SettingsFileAdjacent",
"RootReferencePathMode": "SettingsFileDirectory",
"References": [
{ "Path": "../../myWebApp/Scripts/libs/assets/plugins/jquery-1.10.2.min.js" },
{ "Path": "../../myWebApp/scripts/libs/moment/moment.min.js" },
{ "Path": "../../myWebApp/Scripts/libs/require/require.js" },
{ "Path": "unittest.main.js" }
],
"Tests": [
{
"Path": "app",
"Includes": [ "*.tests.js" ]
}
]
}
unittest.main.js
"use strict";
require.config({
paths: {
'jasmine': ['jasmine/jasmine'],
'jasmine-html': ['jasmine/jasmine-html'],
'jasmine-boot': ['jasmine/boot'],
squire: 'Squire'
},
shim: {
'jasmine-html': {
deps : ['jasmine']
},
'jasmine-boot': {
deps : ['jasmine', 'jasmine-html']
},
'squire': {
exports: 'squire'
}
},
config: {
text: {
useXhr: function (url, protocol, hostname, port) { return true },
//Valid values are 'node', 'xhr', or 'rhino'
env: 'xhr'
}
},
waitSeconds: 0
});
viewModel.tests.js
define(function (require) {
var testTargetPath = '../../myWebApp/Scripts/app/modules/thisModule/myViewModel';
describe('My View Model', function () {
var mockDataContext;
var mockResponseData;
var injector;
var viewModel;
beforeEach(function () {
var Squire = require('Squire');
injector = new Squire();
});
beforeEach(function () {
mockResponseData = {};
mockDataContext = {
dataRequestHandler: function (url, data, onSuccess) {
onSuccess(mockResponseData[url]);
},
serviceConstants: {
GetTransactionTypes: 'getTransactionTypes',
GetChild: 'getNewPolicy'
}
};
injector.mock("dataContext", mockDataContext);
});
beforeEach(function (done) {
injector.require([testTargetPath], function (ViewModel) {
viewModel = new ViewModel();
done();
});
});
it('gets authorization type array', function () {
spyOn(mockDataContext, 'dataRequestHandler').and.callThrough();
mockResponseData = {
'getTransactionTypes': [
{ name: 'auth type 1', TransactionTypeId: 90210 },
{ name: 'auth type 2', TransactionTypeId: 42 },
]
};
viewModel.GetAuthorizationTypesArray(9266);
expect(mockDataContext.dataRequestHandler).toHaveBeenCalledWith('getTransactionTypes', { ItemId: 9266 });
expect(viewModel.TransactionTypeArray()).toBe(mockResponseData);
});
});
});
To be specific, in the ViewModel, when the tests run, it complains that super is undefined.
Alright, turns out there were a number of issues I had to deal with:
At first I thought the failing on super was because of an ES6
compatibility issue (since PhantomJS only supports ES5). However,
it turns out that the project is not using ES6, but
inheritance.js, which manually builds the super dependencies.
That setup is done within the component section of Knockout in our
solution, so I replicated it within the unit tests.
I was not properly setting up Squire to inject my dependencies, and
corrected that.
I did not make any changes to my component or view model, and my Chutzpah configuration stayed the same. However, unittest.main.js was updated, as were my tests:
unittest.main.js
"use strict";
require.config({
paths: {
'jasmine': ['jasmine/jasmine'],
'jasmine-html': ['jasmine/jasmine-html'],
'jasmine-boot': ['jasmine/boot'],
squire: 'Squire',
"baseViewModel": '../../myWebApp/Scripts/app/core/baseClasses/BaseViewModel'
},
shim: {
'jasmine-html': {
deps : ['jasmine']
},
'jasmine-boot': {
deps : ['jasmine', 'jasmine-html']
},
'squire': {
exports: 'squire'
}
},
config: {
text: {
useXhr: function (url, protocol, hostname, port) { return true },
//Valid values are 'node', 'xhr', or 'rhino'
env: 'xhr'
}
},
waitSeconds: 0
});
viewModel.tests.js
define(function (require) {
var testTargetPath = '../../myWebApp/Scripts/app/modules/thisModule/myViewModel';
describe('View Model', function () {
var mockGlobalContext;
var mockModuleContext;
var mockDataContext;
var mockResponseData;
var injector;
var viewModel;
var mockUtils;
beforeEach(function () {
var Squire = require('Squire');
injector = new Squire();
});
beforeEach(function () {
mockResponseData = {};
mockGlobalContext = {};
mockUtils = {};
mockModuleContext = {};
mockDataContext = {
dataRequestHandler: function (url, data, onSuccess) {
onSuccess(mockResponseData[url]);
},
serviceConstants: {
GetTransactionTypes: 'getTransactionTypes',
GetChild: 'getNewPolicy'
}
};
injector.mock("../../../../model/utils", function () { return mockUtils; });
spyOn(mockDataContext, 'dataRequestHandler').and.callThrough();
});
beforeEach(function (done) {
injector.require([testTargetPath], function (ViewModel) {
var BaseViewModel = require('baseViewModel');
BaseObject.Create(ViewModel, BaseViewModel, [mockGlobalContext, mockModuleContext, mockDataContext]);
viewModel = new ViewModel(mockGlobalContext, mockModuleContext, mockDataContext);
done();
});
});
it('gets authorization type array', function () {
mockResponseData = {
'getGatewayTransactionTypes': [
{ name: 'auth type 1', TransactionTypeId: 90210 },
{ name: 'auth type 2', TransactionTypeId: 42 },
]
};
viewModel.GetAuthorizationTypesArray(9266);
expect(mockDataContext.dataRequestHandler).toHaveBeenCalledWith('getGatewayTransactionTypes', { ItemId: 9266 }, jasmine.any(Function), viewModel.ShowError);
expect(viewModel.TransactionTypeArray()).toEqual(mockResponseData['getGatewayTransactionTypes']);
});
});
});
With these changes, the test runs successfully and passes.