Merge pull request #3320 from gradido/fix_contribution_test

fix(backend): fix test which will only fail at 31. of month, or 30.05
This commit is contained in:
einhornimmond 2024-06-05 08:22:42 +02:00 committed by GitHub
commit b579a2114a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 130 additions and 7 deletions

View File

@ -56,6 +56,7 @@ import { garrickOllivander } from '@/seeds/users/garrick-ollivander'
import { peterLustig } from '@/seeds/users/peter-lustig'
import { raeuberHotzenplotz } from '@/seeds/users/raeuber-hotzenplotz'
import { stephenHawking } from '@/seeds/users/stephen-hawking'
import { getFirstDayOfPreviousNMonth } from '@/util/utilities'
jest.mock('@/emails/sendEmailVariants')
@ -290,8 +291,7 @@ describe('ContributionResolver', () => {
it('throws error when creationDate 3 month behind', async () => {
jest.clearAllMocks()
const date = new Date()
date.setMonth(date.getMonth() - 3)
const date = getFirstDayOfPreviousNMonth(new Date(), 3)
const { errors: errorObjects } = await mutate({
mutation: createContribution,
variables: {
@ -584,8 +584,7 @@ describe('ContributionResolver', () => {
describe('update creation to a date that is older than 3 months', () => {
it('throws an error', async () => {
jest.clearAllMocks()
const date = new Date()
date.setMonth(date.getMonth() - 3)
const date = getFirstDayOfPreviousNMonth(new Date(), 3)
const { errors: errorObjects } = await mutate({
mutation: updateContribution,
variables: {

View File

@ -10,7 +10,7 @@ import { login, createContribution, adminCreateContribution } from '@/seeds/grap
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
import { peterLustig } from '@/seeds/users/peter-lustig'
import { getUserCreation } from './creations'
import { getOpenCreations, getUserCreation } from './creations'
let mutate: ApolloServerTestClient['mutate'], con: Connection
let testEnv: {
@ -270,4 +270,49 @@ describe('util/creation', () => {
})
})
})
describe('getOpenCreations', () => {
beforeAll(() => {
// enable Fake timers
jest.useFakeTimers()
// jest.setSystemTime(new Date('2022-01-01T00:00:00Z'))
})
afterAll(() => {
// disable Fake timers and set time back to system time
jest.useRealTimers()
})
it('test default case', async () => {
jest.setSystemTime(new Date('2022-01-10T00:00:00Z'))
const creationDates = await getOpenCreations(user.id, 0)
expect(creationDates).toEqual(
expect.arrayContaining([
expect.objectContaining({ month: 10 }),
expect.objectContaining({ month: 11 }),
expect.objectContaining({ month: 0 }),
]),
)
})
it('test edge case with february', async () => {
jest.setSystemTime(new Date('2022-05-31T00:00:00Z'))
const creationDates = await getOpenCreations(user.id, 0)
expect(creationDates).toEqual(
expect.arrayContaining([
expect.objectContaining({ month: 2 }),
expect.objectContaining({ month: 3 }),
expect.objectContaining({ month: 4 }),
]),
)
})
it('test edge case with july', async () => {
jest.setSystemTime(new Date('2022-07-31T00:00:00Z'))
const creationDates = await getOpenCreations(user.id, 0)
expect(creationDates).toEqual(
expect.arrayContaining([
expect.objectContaining({ month: 4 }),
expect.objectContaining({ month: 5 }),
expect.objectContaining({ month: 6 }),
]),
)
})
})
})

View File

@ -10,6 +10,7 @@ import { OpenCreation } from '@model/OpenCreation'
import { FULL_CREATION_AVAILABLE, MAX_CREATION_AMOUNT } from '@/graphql/resolver/const/const'
import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger'
import { getFirstDayOfPreviousNMonth } from '@/util/utilities'
interface CreationMap {
id: number
@ -115,8 +116,8 @@ const getCreationDates = (timezoneOffset: number): Date[] => {
`getCreationMonths -- offset: ${timezoneOffset} -- clientNow: ${clientNow.toISOString()}`,
)
return [
new Date(clientNow.getFullYear(), clientNow.getMonth() - 2, 1),
new Date(clientNow.getFullYear(), clientNow.getMonth() - 1, 1),
getFirstDayOfPreviousNMonth(clientNow, 2),
getFirstDayOfPreviousNMonth(clientNow, 1),
clientNow,
]
}

View File

@ -0,0 +1,59 @@
import { getFirstDayOfPreviousNMonth } from './utilities' // Adjust the path as necessary
describe('getFirstDayOfPreviousNMonth', () => {
test('should calculate 3 months prior to March 31, 2024', () => {
const startDate = new Date(2024, 2, 31) // March 31, 2024 (month is 0-indexed)
const monthsAgo = 3
const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo)
expect(result).toEqual(new Date(2023, 11, 1)) // December 1, 2023
})
test('should handle end of month correctly, January 31, 2024', () => {
const startDate = new Date(2024, 0, 31) // January 31, 2024
const monthsAgo = 1
const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo)
expect(result).toEqual(new Date(2023, 11, 1)) // December 1, 2023
})
test('should handle leap year, March 1, 2024', () => {
const startDate = new Date(2024, 2, 1) // March 1, 2024
const monthsAgo = 1
const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo)
expect(result).toEqual(new Date(2024, 1, 1)) // February 1, 2024
})
test('should handle leap year, February 29, 2024', () => {
const startDate = new Date(2024, 1, 29) // February 29, 2024 (leap year)
const monthsAgo = 12
const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo)
expect(result).toEqual(new Date(2023, 1, 1)) // February 1, 2023
})
test('should handle end of year transition, January 1, 2024', () => {
const startDate = new Date(2024, 0, 1) // January 1, 2024
const monthsAgo = 1
const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo)
expect(result).toEqual(new Date(2023, 11, 1)) // December 1, 2023
})
test('should handle a large number of months ago, December 15, 2024', () => {
const startDate = new Date(2024, 11, 15) // December 15, 2024
const monthsAgo = 24
const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo)
expect(result).toEqual(new Date(2022, 11, 1)) // December 1, 2022
})
test('should handle start of month correctly, February 1, 2024', () => {
const startDate = new Date(2024, 1, 1) // February 1, 2024
const monthsAgo = 1
const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo)
expect(result).toEqual(new Date(2024, 0, 1)) // January 1, 2024
})
test('should handle middle of month correctly, February 14, 2024', () => {
const startDate = new Date(2024, 1, 14) // February 14, 2024
const monthsAgo = 3
const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo)
expect(result).toEqual(new Date(2023, 10, 1)) // November 1, 2023
})
})

View File

@ -33,3 +33,22 @@ export function resetInterface<T extends Record<string, any>>(obj: T): T {
export const ensureUrlEndsWithSlash = (url: string): string => {
return url.endsWith('/') ? url : url.concat('/')
}
/**
* Calculates the date representing the first day of the month, a specified number of months prior to a given date.
*
* This function was created to address an issue with using `Date.prototype.setMonth`.
* When calculating previous months, `setMonth` can produce incorrect results at the end of months.
* For example, subtracting 3 months from May 31st using `setMonth` would result in March instead of February.
* This function ensures the correct month is calculated by setting the day to the 1st before performing the month subtraction.
*
* @param {Date} startDate - The starting date from which to calculate the previous months.
* @param {number} monthsAgo - The number of months to go back from the startDate.
* @returns {Date} A new Date object set to the first day of the month, `monthsAgo` months before the `startDate`.
*
* @example
* // Calculate the date for the first day of the month, 3 months prior to March 15, 2024
* const date = getFirstDayOfPreviousNMonth(new Date(2024, 4, 31), 3);
* console.log(date); // Output: Fri Feb 01 2024 00:00:00 GMT+0000 (Coordinated Universal Time)
*/
export const getFirstDayOfPreviousNMonth = (startDate: Date, monthsAgo: number): Date =>
new Date(startDate.getFullYear(), startDate.getMonth() - monthsAgo, 1)