Search code examples
reactjsreact-nativedatetimejestjsluxon

Testing with luxon DateTime


I have the following that I want to test, using Luxon:

import { DateTime } from 'luxon'

export const calculateAge = (birthDate: DateTime) => {
  let dateDifference = Math.abs(birthDate.diffNow('years').years)
  if (dateDifference < 1) {
    dateDifference = Math.abs(birthDate.diffNow('months').months)
  }

  return String(Math.floor(dateDifference))
}

I am new to React Native and using Jest to test but so far the 'it' block of my test looks like:

  it('calls the calculates age function', () => {
    jest.spyOn(calculateAge, calculateAge('1950-02-02'))

    expect(calculateAge).toHaveBeenCalled()
  })

I get the following error:

TypeError: birthDate.diffNow is not a function

Does anyone know how I can test this?


Solution

  • You generally only need to spy on passed callbacks to check if they were, in fact, called. Here you are testing a function, so you definitely do not want to mock or spy on it.

    export const calculateAge = (birthDate: DateTime) => {
      let dateDifference = Math.abs(birthDate.diffNow('years').years)
      if (dateDifference < 1) {
        dateDifference = Math.abs(birthDate.diffNow('months').months)
      }
    
      return String(Math.floor(dateDifference))
    }
    

    Regarding the TypeError: birthDate.diffNow is not a function error, this is because calculateAge is expecting a Luxon DateTime object and you were passing a String object.

    For testing you will want to mock the javascript date/time so you can reliably compare against a static date in your tests, otherwise the now time would always be different each test run.

    import { advanceTo, clear } from 'jest-date-mock';
    
    ...
    
    afterAll(() => {
      clear(); // clear jest date mock
    });
    
    it('should compute diff in years', () => {
      // Set "now" time
      advanceTo(DateTime.fromISO('2021-08-08T01:20:13-0700').toJSDate());
    
      expect(calculateAge(DateTime.fromISO('2020-08-07T00:00:00-0700'))).toEqual('1');
    });
    
    it('should compute diff in months', () => {
      // Set "now" time
      advanceTo(DateTime.fromISO('2021-08-08T01:20:13-0700').toJSDate());
    
      expect(calculateAge(DateTime.fromISO('2020-08-09T00:00:00-0700'))).toEqual('11');
    });
    

    You can think of other interesting test/boundary cases.