Kyaw Siesein
Kyaw Siesein

Reputation: 725

Unit testing of a function with conditional statement

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

Answers (2)

Aung Baw
Aung Baw

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

Dinesh Pandiyan
Dinesh Pandiyan

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

Related Questions