Reputation: 725
I have a function to track analytics from google analytics. So that in my function i need to see if the code exists or not.
Analytics.js
const gaCode = process.env.REACT_APP_GA_TRACKING_CODE;
const gaCodeExists = gaCode && gaCode.Length > 0;
function trackEvent(category = "Event", name) {
if(gaCodeExists) {
GoogleAnalytics.event({
category,
action: name,
});
}
return;
}
export default {
gaCodeExists,
trackEvent
}
At first I was doing like this (which I am pretty sure I am not doing correctly).
describe('Testing analytics', () => {
beforeEach(() => {
Analytics.trackEvent(null, 'Tracking');
});
it('should not call google analytics', () => {
if (!gaCodeExists) {
const mockGoogleAnalytics = jest.fn(() => GoogleAnalytics.event);
expect(mockGoogleAnalytics.mock.calls.length).toBe(0);
}
});
})
After reading some blog posts and looking at stackover flow questions. I changed it to like this which I think I am mocking the gaCodeExists variable as below.
import constants from '../index';
import { isUsingGoogleAnalytics } from '../index';
describe('Analytics Testing', () => {
it('Should test trackEvent', () => {
constants.isUsingGoogleAnalytics = true;
expect(constants.isUsingGoogleAnalytics).toBe(true);
});
});
Now I am stuck how can I do the testing on trackEvent
function. How can I apply mock gaCodeExists variable to it? The test cases would be if the gaCodeExists
is true, expect(mockFunction).toHaveBeenCalled(1)
.
P.S: I am new to testing.
Upvotes: 2
Views: 7984
Reputation: 456
const gaCode = process.env.REACT_APP_GA_TRACKING_CODE;
const gaCodeExists = gaCode && gaCode.Length > 0;
function trackEvent(category = "Event", name, gaCodeExists) {
if(gaCodeExists) {
GoogleAnalytics.event({
category,
action: name,
})
}
}
export default {
gaCodeExists,
trackEvent
}
First change your Analytics code like this, your test file should be like following
import { UsingGoogleAnalytics } from '../index' // i don't know what this file is
import { gaCodeExistsis, trackEvent } from './Analytics'
describe('Analytics Testing', () => {
beforeEach(() => {
expect(gaCodeExists).toHaveBeenCalledWith(true)
expect(trackEvent).toEqual(jasmine.any(Function))
})
it('track event was called without params', () => {
expect(trackEvent()).toBe(1); // replace 1 with desire output without params
})
it('track event was called with params', () => {
expect(trackEvent("somecategory", "somename", gaCodeExistsis)).toBe(1); // replace 1 with desire output with params
})
});
Upvotes: 1
Reputation: 6299
Your gaCodeExists
assigns value to the variable while the js file is loaded. And trackEvent
function is not pure as it depends on a value that is outside its scope. It's advisable to make your functions pure, so you can test it the right way. Since this is a GA implementation, you can just convert gaCodeExists
to a function and mock it in your tests.
Change your gaCodeExists
to a method
const gaCodeExists = () => {
if(process && process.env && process.env.REACT_APP_GA_TRACKING_CODE) {
const gaCode = process.env.REACT_APP_GA_TRACKING_CODE;
return gaCode && gaCode.Length > 0;
}
return false;
}
Change your trackEvent
function to
function trackEvent(category = "Event", name) => {
if(gaCodeExists()) { // note this line
GoogleAnalytics.event({
category,
action: name,
});
}
return;
}
Now you can test it by mocking gaCodeExists
function
import * as analytics from "../index";
describe('Testing analytics', () => {
beforeEach(() => {
const gaMock = jest.spyOn(analytics, "gaCodeExists");
});
it('should not call google analytics', () => {
gaMock.mockImplementation(() => false);
// check what happens when it doesn't call GA
});
it('should call google analytics', () => {
gaMock.mockImplementation(() => true);
// check what happens when it calls GA
});
})
I haven't tested this code. So please double check if it's doing what it's intended to do.
Upvotes: 1