diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fcc7c6ed1f..d8ca18d282 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,3 +15,5 @@ jobs: - uses: ./.github/actions/yarn-install # Should be an 8GB machine as per https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners - run: yarn test + # We could add different timezones here that we need to run our tests in + - run: TZ=America/Los_Angeles yarn test -- --timeZoneDependentTestsOnly diff --git a/packages/features/calendars/lib/getAvailableDatesInMonth.test.ts b/packages/features/calendars/lib/getAvailableDatesInMonth.timezone.test.ts similarity index 53% rename from packages/features/calendars/lib/getAvailableDatesInMonth.test.ts rename to packages/features/calendars/lib/getAvailableDatesInMonth.timezone.test.ts index 10e8fdc147..c8475e3311 100644 --- a/packages/features/calendars/lib/getAvailableDatesInMonth.test.ts +++ b/packages/features/calendars/lib/getAvailableDatesInMonth.timezone.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, test } from "vitest"; +import { describe, expect, test, vi } from "vitest"; import { getAvailableDatesInMonth } from "@calcom/features/calendars/lib/getAvailableDatesInMonth"; import { daysInMonth, yyyymmdd } from "@calcom/lib/date-fns"; @@ -8,7 +8,7 @@ describe("Test Suite: Date Picker", () => { // *) Use right amount of days in given month. (28, 30, 31) test("it returns the right amount of days in a given month", () => { const currentDate = new Date(); - const nextMonthDate = new Date(Date.UTC(currentDate.getFullYear(), currentDate.getMonth() + 1)); + const nextMonthDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1); const result = getAvailableDatesInMonth({ browsingDate: nextMonthDate, @@ -35,5 +35,33 @@ describe("Test Suite: Date Picker", () => { expect(result).toHaveLength(1); }); + + test("it translates correctly regardless of system time", () => { + { + // test a date in negative UTC offset + vi.useFakeTimers().setSystemTime(new Date("2023-10-24T13:27:00.000-07:00")); + + const currentDate = new Date(); + const result = getAvailableDatesInMonth({ + browsingDate: currentDate, + }); + + expect(result).toHaveLength(daysInMonth(currentDate) - currentDate.getDate() + 1); + } + { + // test a date in positive UTC offset + vi.useFakeTimers().setSystemTime(new Date("2023-10-24T13:27:00.000+07:00")); + + const currentDate = new Date(); + const result = getAvailableDatesInMonth({ + browsingDate: currentDate, + }); + + expect(result).toHaveLength(daysInMonth(currentDate) - currentDate.getDate() + 1); + } + // Undo the forced time we applied earlier, reset to system default. + vi.setSystemTime(vi.getRealSystemTime()); + vi.useRealTimers(); + }); }); }); diff --git a/packages/features/calendars/lib/getAvailableDatesInMonth.ts b/packages/features/calendars/lib/getAvailableDatesInMonth.ts index 8fbace876b..8e50ef9793 100644 --- a/packages/features/calendars/lib/getAvailableDatesInMonth.ts +++ b/packages/features/calendars/lib/getAvailableDatesInMonth.ts @@ -5,7 +5,7 @@ import { daysInMonth, yyyymmdd } from "@calcom/lib/date-fns"; // *) Dates in the past are not available. // *) Use right amount of days in given month. (28, 30, 31) export function getAvailableDatesInMonth({ - browsingDate, // pass as UTC + browsingDate, minDate = new Date(), includedDates, }: { @@ -15,12 +15,14 @@ export function getAvailableDatesInMonth({ }) { const dates = []; const lastDateOfMonth = new Date( - Date.UTC(browsingDate.getFullYear(), browsingDate.getMonth(), daysInMonth(browsingDate)) + browsingDate.getFullYear(), + browsingDate.getMonth(), + daysInMonth(browsingDate) ); for ( let date = browsingDate > minDate ? browsingDate : minDate; date <= lastDateOfMonth; - date = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate() + 1)) + date = new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1) ) { // intersect included dates if (includedDates && !includedDates.includes(yyyymmdd(date))) { diff --git a/vitest.workspace.ts b/vitest.workspace.ts index 587aeb8cbf..20d12799fb 100644 --- a/vitest.workspace.ts +++ b/vitest.workspace.ts @@ -1,6 +1,13 @@ import { defineWorkspace } from "vitest/config"; const packagedEmbedTestsOnly = process.argv.includes("--packaged-embed-tests-only"); +const timeZoneDependentTestsOnly = process.argv.includes("--timeZoneDependentTestsOnly"); +// eslint-disable-next-line turbo/no-undeclared-env-vars +const envTZ = process.env.TZ; +if (timeZoneDependentTestsOnly && !envTZ) { + throw new Error("TZ environment variable is not set"); +} + // defineWorkspace provides a nice type hinting DX const workspaces = packagedEmbedTestsOnly ? [ @@ -11,6 +18,19 @@ const workspaces = packagedEmbedTestsOnly }, }, ] + : // It doesn't seem to be possible to fake timezone per test, so we rerun the entire suite with different TZ. See https://github.com/vitest-dev/vitest/issues/1575#issuecomment-1439286286 + timeZoneDependentTestsOnly + ? [ + { + test: { + name: `TimezoneDependentTests:${envTZ}`, + include: ["packages/**/*.timezone.test.ts", "apps/**/*.timezone.test.ts"], + // TODO: Ignore the api until tests are fixed + exclude: ["**/node_modules/**/*", "packages/embeds/**/*"], + setupFiles: ["setupVitest.ts"], + }, + }, + ] : [ { test: { @@ -20,6 +40,7 @@ const workspaces = packagedEmbedTestsOnly setupFiles: ["setupVitest.ts"], }, }, + { test: { name: "@calcom/closecom",