Home > Software design >  Date Unit test passed locally but failed in Gitlab CD/CI pipeline
Date Unit test passed locally but failed in Gitlab CD/CI pipeline

Time:02-14

For date validation, I used luxon for my app. For each function I have made unit test. My unit test passed locally but when I deployed my code in gitlab, Most of my test failed. The expected result is so different than received. I don't understand what's the wrong. This my CD/CI pipeline images. Image-1, image-2, Image-3 and there are more. Basically all my test failed

My all test passed in code-sandbox

These are my all functions:

import {
  DateTime
} from 'luxon'

export const DEFAULT_DATE_FORMAT = 'd.M.yyyy'
export const SHORT_TIME_FORMAT = 'HH:mm'
export const ISO_DATE_FORMAT = 'yyyy-MM-dd'
export const DATE_TIME_FORMAT = 'd.M.yyyy HH:mm'
export const DATE_MONTH_FORMAT = 'd.M'

export const WEEKDAYS = [
  'SUNDAY',
  'MONDAY',
  'TUESDAY',
  'WEDNESDAY',
  'THURSDAY',
  'FRIDAY',
  'SATURDAY',
]

export const dateToStrings = (date: string | number | Date): DateTime =>
  DateTime.fromISO(new Date(date).toISOString())

export const formatDateTime = (date: string | number | Date): string =>
  dateToStrings(date).toFormat(DATE_TIME_FORMAT)
export const formatDateMonthYear = (date: string | number | Date): string =>
  dateToStrings(date).toFormat(DEFAULT_DATE_FORMAT)

export const formatTime = (date: string | number | Date): string =>
  dateToStrings(date).toFormat(SHORT_TIME_FORMAT)

export const NextDayFormatYearMonthDate = (date: string | number | Date): string =>
  dateToStrings(date).plus({
    days: 1
  }).toFormat(ISO_DATE_FORMAT)

export const PreviousDayFormatYearMonthDate = (date: string | number | Date): string =>
  dateToStrings(date).plus({
    days: -1
  }).toFormat(ISO_DATE_FORMAT)

export const dateDifference = (date: string | number | Date): number => {
  const diff = dateToStrings(date).diff(DateTime.now(), 'days').toObject()

  return Math.abs(Math.ceil(diff.days as number))
}

export const formatYearMonthDate = (date: Date | string | undefined): string => {
  if (!date) {
    //  if date is undefined, return empty string
    return ''
  } else {
    return dateToStrings(date).toFormat(ISO_DATE_FORMAT)
  }
}
export const weekNumber = (date: string | Date): number =>
  dateToStrings(date).startOf('week').weekNumber

export const nextWeek = (date: string | Date): string =>
  dateToStrings(date).startOf('week').plus({
    days: 7
  }).toFormat(ISO_DATE_FORMAT)

export const previousWeek = (date: string | Date): string =>
  dateToStrings(date).startOf('week').plus({
    days: -7
  }).toFormat(ISO_DATE_FORMAT)
export const firstDateOfWeek = (date: string | Date): string =>
  dateToStrings(date).startOf('week').toFormat(ISO_DATE_FORMAT)

export const lastDateOfWeek = (date: string | Date): string =>
  dateToStrings(date).startOf('week').plus({
    days: 6
  }).toFormat(ISO_DATE_FORMAT)

export const firstMondayOfTheWeekWithGMT = (date: Date): Date =>
  dateToStrings(date).startOf('week').toJSDate()

export const formatDateMonth = (date: string | Date): string =>
  dateToStrings(date).toFormat(DATE_MONTH_FORMAT)

export const shortDateString = (date: Date): string => {
  const shortForm = dateToStrings(date).setLocale('fi').toFormat('EEE')
  return shortForm.length > 1 ? `${shortForm.charAt(0).toUpperCase()}${shortForm.slice(1)}` : ''
}

export const hasSameDay = (date1: Date, date2: Date): boolean =>
  dateToStrings(date1).hasSame(dateToStrings(date2), 'day')

export const isToday = (date: string | number | Date): boolean => {
  return dateToStrings(date).toISODate() === DateTime.local().toISODate()
}

export const compareDays = (
  date1: Date | string | number,
  date2: Date | string | number,
): number => {
  const compareWithDay = dateToStrings(date1).diff(dateToStrings(date2), ['days']).toObject()

  return Math.abs(Math.ceil(compareWithDay.days as number))
}

This is my all tests

import {
  formatDateTime,
  formatDateMonthYear,
  formatTime,
  NextDayFormatYearMonthDate,
  PreviousDayFormatYearMonthDate,
  dateDifference,
  formatYearMonthDate,
  weekNumber,
  nextWeek,
  previousWeek,
  firstDateOfWeek,
  lastDateOfWeek,
  formatDateMonth,
  shortDateString,
  compareDays,
  DATE_MONTH_FORMAT,
  DEFAULT_DATE_FORMAT,
  SHORT_TIME_FORMAT,
  ISO_DATE_FORMAT,
  DATE_TIME_FORMAT,
} from 'utils/date'
import { DateTime } from 'luxon'

const toDateString = 'Mon Feb 07 2022 00:00:00 GMT 0200 (Eastern European Standard Time)'
const toISOString = '2018-05-01T13:44:48.708709Z'
const today = new Date()
const tomorrow = new Date(today.getTime()   24 * 60 * 60 * 1000)
const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000)

describe('formatDateTime', () => {
  it('Should return format date time when date is string', () => {
    expect(formatDateTime('2022-02-11T06:44:57 00:00')).toBe('7.2.2022 00:00')
  })

  it('Should return format date time when date is toISOString', () => {
    expect(formatDateTime(toISOString)).toBe('1.5.2018 16:44')
  })
  it('Should return format date time when date is today', () => {
    expect(formatDateTime(today)).toBe(
      DateTime.fromISO(new Date().toISOString()).toFormat(DATE_TIME_FORMAT),
    )
  })
})

describe('formatDateMonthYear', () => {
  it('Should return format date when date is string', () => {
    expect(formatDateMonthYear(toDateString)).toBe('7.2.2022')
  })

  it('Should return format date when date is ISO String', () => {
    expect(formatDateMonthYear(toISOString)).toBe('1.5.2018')
  })

  it('Should return format date when date is today', () => {
    expect(formatDateMonthYear(today)).toBe(
      DateTime.fromISO(new Date().toISOString()).toFormat(DEFAULT_DATE_FORMAT),
    )
  })
})

describe('formatTime', () => {
  it('Should return 00:00 when there is no time', () => {
    expect(formatTime(toDateString)).toBe('00:00')
  })

  it('Should return format time', () => {
    expect(formatTime(toISOString)).toBe('16:44')
  })

  it('Should return format time when date is today', () => {
    expect(formatTime(today)).toBe(
      DateTime.fromISO(new Date().toISOString()).toFormat(SHORT_TIME_FORMAT),
    )
  })
})

describe('NextDayFormatYearMonthDate ', () => {
  it('Should return next day format year when date is string', () => {
    expect(NextDayFormatYearMonthDate(toDateString)).toBe('2022-02-08')
  })

  it('Should return next day format year when date is ISOString', () => {
    expect(NextDayFormatYearMonthDate(toISOString)).toBe('2018-05-02')
  })
  it('Should return next day format year when date is today', () => {
    expect(NextDayFormatYearMonthDate(today)).toBe(
      DateTime.fromISO(new Date().toISOString()).plus({ days: 1 }).toFormat(ISO_DATE_FORMAT),
    )
  })
})

describe('PreviousDayFormatYearMonthDate', () => {
  it('Should return next day format year when date is string', () => {
    expect(PreviousDayFormatYearMonthDate(toDateString)).toBe('2022-02-06')
  })

  it('Should return next day format year when date is ISOString', () => {
    expect(PreviousDayFormatYearMonthDate(toISOString)).toBe('2018-04-30')
  })
  it('Should return next day format year when date is today', () => {
    expect(PreviousDayFormatYearMonthDate(today)).toBe(
      DateTime.fromISO(new Date().toISOString()).plus({ days: -1 }).toFormat(ISO_DATE_FORMAT),
    )
  })
})

describe('dateDifference', () => {
  it('Should return 0 when date is today', () => {
    expect(dateDifference(today)).toBe(0)
  })

  it('Should return 1 when date is not today', () => {
    expect(dateDifference(tomorrow)).toBe(1)
  })

  it('Should return 1 when date is not today', () => {
    expect(dateDifference(yesterday)).toBe(1)
  })
})

describe('formatYearMonthDate', () => {
  it('Should return format date when date is string', () => {
    expect(formatYearMonthDate(toDateString)).toBe('2022-02-07')
  })

  it('Should return format date when date is ISO String', () => {
    expect(formatYearMonthDate(toISOString)).toBe('2018-05-01')
  })

  it('Should return format date when date is today', () => {
    expect(formatYearMonthDate(today)).toBe(
      DateTime.fromISO(new Date().toISOString()).toFormat(ISO_DATE_FORMAT),
    )
  })

  it('Should return empty string when date is undefined', () => {
    expect(formatYearMonthDate(undefined)).toBe('')
  })
})

describe('weekNumber', () => {
  it('Should return week number when date is string', () => {
    expect(weekNumber(toDateString)).toBe(6)
  })

  it('Should return week number when date is ISO String', () => {
    expect(weekNumber(toISOString)).toBe(18)
  })

  it('Should return week number when date is today', () => {
    expect(weekNumber(today)).toBe(DateTime.fromISO(new Date().toISOString()).weekNumber)
  })
})

describe('nextWeek', () => {
  it('Should return next week date when date is string', () => {
    expect(nextWeek(toDateString)).toBe('2022-02-14')
  })

  it('Should return next week date when date is ISO String', () => {
    expect(nextWeek(toISOString)).toBe('2018-05-07')
  })
})

describe('previousWeek', () => {
  it('Should return previous week date when date is string', () => {
    expect(previousWeek(toDateString)).toBe('2022-01-31')
  })

  it('Should return previous week date when date is ISO String', () => {
    expect(previousWeek(toISOString)).toBe('2018-04-23')
  })
})

describe('firstDateOfWeek', () => {
  it('Should return first date of the week when date is string', () => {
    expect(firstDateOfWeek(toDateString)).toBe('2022-02-07')
  })

  it('Should return first date of the week when date is ISO String', () => {
    expect(firstDateOfWeek(toISOString)).toBe('2018-04-30')
  })
})

describe('lastDateOfWeek', () => {
  it('Should return first date of the week when date is string', () => {
    expect(lastDateOfWeek(toDateString)).toBe('2022-02-13')
  })

  it('Should return first date of the week when date is ISO String', () => {
    expect(lastDateOfWeek(toISOString)).toBe('2018-05-06')
  })
})

describe('formatDateMonth', () => {
  it('Should return format date month when date is string', () => {
    expect(formatDateMonth(toDateString)).toBe('7.2')
  })

  it('Should return format date month when date is ISO String', () => {
    expect(formatDateMonth(toISOString)).toBe('1.5')
  })

  it('Should return format date month when date is today', () => {
    expect(formatDateMonth(today)).toBe(
      DateTime.fromISO(new Date().toISOString()).toFormat(DATE_MONTH_FORMAT),
    )
  })
})

describe('shortDateString', () => {
  it('Should return first two letters Finnish weekdays when date is string', () => {
    expect(shortDateString(new Date(toDateString))).toBe('Ma')
  })

  it('Should return first two letters Finnish weekdays when date is ISO String', () => {
    expect(shortDateString(new Date(toISOString))).toBe('Ti')
  })
})

describe('compareDays', () => {
  it('Should return 0 if the dates are same', () => {
    expect(compareDays(new Date(toDateString), new Date(toDateString))).toBe(0)
  })

  it('Should return 0 if the dates are same', () => {
    expect(compareDays(new Date(toDateString), new Date(toISOString))).toBe(1378)
  })

  it('Should return 0 if the dates are string', () => {
    expect(compareDays(toDateString, toISOString)).toBe(1378)
  })
})

CodePudding user response:

The difference has to do with the timezone of your local computer and the timezone of the GitLab runner. The GitLab runners use UTC timezone.

Take this case for example:

const toDateString = 'Mon Feb 07 2022 00:00:00 GMT 0200 (Eastern European Standard Time)'
// ...
describe('formatTime', () => {
  it('Should return 00:00 when there is no time', () => {
    expect(formatTime(toDateString)).toBe('00:00')
  })

In your unit test results:

Expected: "00:00"
Received: "22:00"

This would pass if your local timezone is UTC 2, but would fail if your timezone is UTC. Mon Feb 07 2022 00:00:00 GMT 0200 is Sun Feb 06 2022 22:00:00 in UTC time.

From the luxon docs: (emphasis added)

A DateTime comprises of:

[...]
A time zone. Each instance is considered in the context of a specific zone (by default the local system's zone).
[...]

You'll probably want to normalize your tests to use a particular timezone. See this question for hints on how to change the timezone of the datetime objects.

  • Related