fix: Infinite loop in timezones on the negative side of UTC (#12063)
* fix: Infinite loop in timezones on the negative side of UTC * Update packages/features/calendars/lib/getAvailableDatesInMonth.test.ts * Revert back to real system time after test * Handle all dates as local time, given this all happens in the browserpull/12084/head
parent
327159c2ae
commit
efc7be0b6b
|
@ -15,3 +15,5 @@ jobs:
|
||||||
- uses: ./.github/actions/yarn-install
|
- 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
|
# Should be an 8GB machine as per https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners
|
||||||
- run: yarn test
|
- 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
|
||||||
|
|
|
@ -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 { getAvailableDatesInMonth } from "@calcom/features/calendars/lib/getAvailableDatesInMonth";
|
||||||
import { daysInMonth, yyyymmdd } from "@calcom/lib/date-fns";
|
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)
|
// *) Use right amount of days in given month. (28, 30, 31)
|
||||||
test("it returns the right amount of days in a given month", () => {
|
test("it returns the right amount of days in a given month", () => {
|
||||||
const currentDate = new Date();
|
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({
|
const result = getAvailableDatesInMonth({
|
||||||
browsingDate: nextMonthDate,
|
browsingDate: nextMonthDate,
|
||||||
|
@ -35,5 +35,33 @@ describe("Test Suite: Date Picker", () => {
|
||||||
|
|
||||||
expect(result).toHaveLength(1);
|
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();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -5,7 +5,7 @@ import { daysInMonth, yyyymmdd } from "@calcom/lib/date-fns";
|
||||||
// *) Dates in the past are not available.
|
// *) Dates in the past are not available.
|
||||||
// *) Use right amount of days in given month. (28, 30, 31)
|
// *) Use right amount of days in given month. (28, 30, 31)
|
||||||
export function getAvailableDatesInMonth({
|
export function getAvailableDatesInMonth({
|
||||||
browsingDate, // pass as UTC
|
browsingDate,
|
||||||
minDate = new Date(),
|
minDate = new Date(),
|
||||||
includedDates,
|
includedDates,
|
||||||
}: {
|
}: {
|
||||||
|
@ -15,12 +15,14 @@ export function getAvailableDatesInMonth({
|
||||||
}) {
|
}) {
|
||||||
const dates = [];
|
const dates = [];
|
||||||
const lastDateOfMonth = new Date(
|
const lastDateOfMonth = new Date(
|
||||||
Date.UTC(browsingDate.getFullYear(), browsingDate.getMonth(), daysInMonth(browsingDate))
|
browsingDate.getFullYear(),
|
||||||
|
browsingDate.getMonth(),
|
||||||
|
daysInMonth(browsingDate)
|
||||||
);
|
);
|
||||||
for (
|
for (
|
||||||
let date = browsingDate > minDate ? browsingDate : minDate;
|
let date = browsingDate > minDate ? browsingDate : minDate;
|
||||||
date <= lastDateOfMonth;
|
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
|
// intersect included dates
|
||||||
if (includedDates && !includedDates.includes(yyyymmdd(date))) {
|
if (includedDates && !includedDates.includes(yyyymmdd(date))) {
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
import { defineWorkspace } from "vitest/config";
|
import { defineWorkspace } from "vitest/config";
|
||||||
|
|
||||||
const packagedEmbedTestsOnly = process.argv.includes("--packaged-embed-tests-only");
|
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
|
// defineWorkspace provides a nice type hinting DX
|
||||||
const workspaces = packagedEmbedTestsOnly
|
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: {
|
test: {
|
||||||
|
@ -20,6 +40,7 @@ const workspaces = packagedEmbedTestsOnly
|
||||||
setupFiles: ["setupVitest.ts"],
|
setupFiles: ["setupVitest.ts"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
test: {
|
test: {
|
||||||
name: "@calcom/closecom",
|
name: "@calcom/closecom",
|
||||||
|
|
Loading…
Reference in New Issue