diff --git a/packages/nodes-base/nodes/Google/Calendar/CalendarDescription.ts b/packages/nodes-base/nodes/Google/Calendar/CalendarDescription.ts
index f172f976c8..d768222003 100644
--- a/packages/nodes-base/nodes/Google/Calendar/CalendarDescription.ts
+++ b/packages/nodes-base/nodes/Google/Calendar/CalendarDescription.ts
@@ -86,8 +86,9 @@ export const calendarFields: INodeProperties[] = [
resource: ['calendar'],
},
},
- default: '',
- description: 'Start of the interval, if not specified will default to now',
+ default: '={{ $now.toISO() }}',
+ description:
+ 'Start of the interval, use expression to set a date, or switch to fixed mode to choose date from widget',
},
{
displayName: 'End Time',
@@ -100,8 +101,9 @@ export const calendarFields: INodeProperties[] = [
resource: ['calendar'],
},
},
- default: '',
- description: 'End of the interval, if not specified will default to Start Time plus 1 hour',
+ default: "={{ $now.plus(1, 'hour').toISO() }}",
+ description:
+ 'End of the interval, use expression to set a date, or switch to fixed mode to choose date from widget',
},
{
displayName: 'Options',
diff --git a/packages/nodes-base/nodes/Google/Calendar/EventDescription.ts b/packages/nodes-base/nodes/Google/Calendar/EventDescription.ts
index d32e55cdf4..65e92bf909 100644
--- a/packages/nodes-base/nodes/Google/Calendar/EventDescription.ts
+++ b/packages/nodes-base/nodes/Google/Calendar/EventDescription.ts
@@ -114,8 +114,9 @@ export const eventFields: INodeProperties[] = [
resource: ['event'],
},
},
- default: '',
- description: 'Start time of the event, if not specified will default to now',
+ default: '={{ $now.toISO() }}',
+ description:
+ 'Start time of the event, use expression to set a date, or switch to fixed mode to choose date from widget',
},
{
displayName: 'End',
@@ -128,8 +129,9 @@ export const eventFields: INodeProperties[] = [
resource: ['event'],
},
},
- default: '',
- description: 'End time of the event, if not specified will default to start time plus 1 hour',
+ default: "={{ $now.plus(1, 'hour').toISO() }}",
+ description:
+ 'End time of the event, use expression to set a date, or switch to fixed mode to choose date from widget',
},
{
displayName: 'Use Default Reminders',
diff --git a/packages/nodes-base/nodes/Google/Calendar/GenericFunctions.ts b/packages/nodes-base/nodes/Google/Calendar/GenericFunctions.ts
index f440efaee9..2ca092d4f8 100644
--- a/packages/nodes-base/nodes/Google/Calendar/GenericFunctions.ts
+++ b/packages/nodes-base/nodes/Google/Calendar/GenericFunctions.ts
@@ -1,3 +1,4 @@
+import { DateTime } from 'luxon';
import moment from 'moment-timezone';
import type {
IDataObject,
@@ -193,3 +194,8 @@ export function addTimezoneToDate(date: string, timezone: string) {
if (hasTimezone(date)) return date;
return moment.tz(date, timezone).utc().format();
}
+
+export function dateTimeToIso(date: T): string {
+ if (date instanceof DateTime) return date.toISO();
+ return date as string;
+}
diff --git a/packages/nodes-base/nodes/Google/Calendar/GoogleCalendar.node.ts b/packages/nodes-base/nodes/Google/Calendar/GoogleCalendar.node.ts
index ef1c5ad689..edc4498a89 100644
--- a/packages/nodes-base/nodes/Google/Calendar/GoogleCalendar.node.ts
+++ b/packages/nodes-base/nodes/Google/Calendar/GoogleCalendar.node.ts
@@ -18,6 +18,7 @@ import type { IEvent } from './EventInterface';
import {
addNextOccurrence,
addTimezoneToDate,
+ dateTimeToIso,
encodeURIComponentOnce,
getCalendars,
getTimezones,
@@ -148,10 +149,8 @@ export class GoogleCalendar implements INodeType {
const calendarId = decodeURIComponent(
this.getNodeParameter('calendar', i, '', { extractValue: true }) as string,
);
- const timeMin = (this.getNodeParameter('timeMin', i) as string) || moment().format();
- const timeMax =
- (this.getNodeParameter('timeMax', i) as string) ||
- moment(timeMin).add(1, 'hour').format();
+ const timeMin = dateTimeToIso(this.getNodeParameter('timeMin', i));
+ const timeMax = dateTimeToIso(this.getNodeParameter('timeMax', i));
const options = this.getNodeParameter('options', i);
const outputFormat = options.outputFormat || 'availability';
const tz = this.getNodeParameter('options.timezone', i, '', {
@@ -202,9 +201,8 @@ export class GoogleCalendar implements INodeType {
const calendarId = encodeURIComponentOnce(
this.getNodeParameter('calendar', i, '', { extractValue: true }) as string,
);
- const start = (this.getNodeParameter('start', i) as string) || moment().format();
- const end =
- (this.getNodeParameter('end', i) as string) || moment(start).add(1, 'hour').format();
+ const start = dateTimeToIso(this.getNodeParameter('start', i));
+ const end = dateTimeToIso(this.getNodeParameter('end', i));
const useDefaultReminders = this.getNodeParameter('useDefaultReminders', i) as boolean;
const additionalFields = this.getNodeParameter('additionalFields', i);
diff --git a/packages/nodes-base/nodes/Google/Calendar/test/node/calendar.availability.test.ts b/packages/nodes-base/nodes/Google/Calendar/test/node/calendar.availability.test.ts
deleted file mode 100644
index 8e75ef2c7a..0000000000
--- a/packages/nodes-base/nodes/Google/Calendar/test/node/calendar.availability.test.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import type { MockProxy } from 'jest-mock-extended';
-import { mock } from 'jest-mock-extended';
-import type { INode, IExecuteFunctions } from 'n8n-workflow';
-
-import * as genericFunctions from '../../GenericFunctions';
-import { GoogleCalendar } from '../../GoogleCalendar.node';
-
-let googleApiRequestArgs: any[] = [];
-const CALENDAR_ID = 'myCalendar';
-
-jest.mock('../../GenericFunctions', () => ({
- getTimezones: jest.fn(),
- googleApiRequest: jest.fn(async (...args: any[]) => {
- googleApiRequestArgs = args;
- return { calendars: { [CALENDAR_ID]: { busy: [] } } };
- }),
- googleApiRequestAllItems: jest.fn(),
- addTimezoneToDate: jest.fn(),
- addNextOccurrence: jest.fn(),
- encodeURIComponentOnce: jest.fn(),
-}));
-
-describe('RespondToWebhook Node', () => {
- let googleCalendar: GoogleCalendar;
- let mockExecuteFunctions: MockProxy;
-
- beforeEach(() => {
- googleCalendar = new GoogleCalendar();
- mockExecuteFunctions = mock({
- getInputData: jest.fn(),
- getNode: jest.fn(),
- getNodeParameter: jest.fn(),
- getTimezone: jest.fn(),
- helpers: {
- constructExecutionMetaData: jest.fn().mockReturnValue([]),
- },
- });
- });
-
- afterEach(() => {
- googleApiRequestArgs = [];
- jest.clearAllMocks();
- });
-
- describe('Google Calendar > Calendar > Availability', () => {
- it('should not have invalid timeMin and timeMax date', async () => {
- //pre loop setup
- mockExecuteFunctions.getInputData.mockReturnValue([{ json: {} }]);
- mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('calendar');
- mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('availability');
- mockExecuteFunctions.getTimezone.mockReturnValueOnce('Europe/Berlin');
- mockExecuteFunctions.getNode.mockReturnValue(mock({ typeVersion: 1.1 }));
- //operation
- mockExecuteFunctions.getNodeParameter.mockReturnValueOnce(CALENDAR_ID); // calendar
- mockExecuteFunctions.getNodeParameter.mockReturnValueOnce(''); // timeMin, not set
- mockExecuteFunctions.getNodeParameter.mockReturnValueOnce(''); // timeMax, not set
- mockExecuteFunctions.getNodeParameter.mockReturnValueOnce({}); // options
- mockExecuteFunctions.getNodeParameter.mockReturnValueOnce(''); // options.timezone, default to timezone
-
- await googleCalendar.execute.call(mockExecuteFunctions);
-
- expect(genericFunctions.googleApiRequest).toHaveBeenCalledTimes(1);
-
- const body = googleApiRequestArgs[2] as {
- timeMin: string;
- timeMax: string;
- };
-
- expect(body).toBeDefined();
- expect(body.timeMin).not.toEqual('Invalid Date');
- expect(body.timeMax).not.toEqual('Invalid Date');
- });
- });
-});
diff --git a/packages/nodes-base/nodes/Google/Calendar/test/node/event.create.test.ts b/packages/nodes-base/nodes/Google/Calendar/test/node/event.create.test.ts
deleted file mode 100644
index 4641e75182..0000000000
--- a/packages/nodes-base/nodes/Google/Calendar/test/node/event.create.test.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import type { MockProxy } from 'jest-mock-extended';
-import { mock } from 'jest-mock-extended';
-import type { INode, IExecuteFunctions } from 'n8n-workflow';
-
-import * as genericFunctions from '../../GenericFunctions';
-import { GoogleCalendar } from '../../GoogleCalendar.node';
-
-let googleApiRequestArgs: any[] = [];
-
-jest.mock('../../GenericFunctions', () => ({
- getTimezones: jest.fn(),
- googleApiRequest: jest.fn(async (...args: any[]) => {
- googleApiRequestArgs = args;
- return {};
- }),
- googleApiRequestAllItems: jest.fn(),
- addTimezoneToDate: jest.fn(),
- addNextOccurrence: jest.fn(),
- encodeURIComponentOnce: jest.fn(),
-}));
-
-describe('RespondToWebhook Node', () => {
- let googleCalendar: GoogleCalendar;
- let mockExecuteFunctions: MockProxy;
-
- beforeEach(() => {
- googleCalendar = new GoogleCalendar();
- mockExecuteFunctions = mock({
- getInputData: jest.fn(),
- getNode: jest.fn(),
- getNodeParameter: jest.fn(),
- getTimezone: jest.fn(),
- helpers: {
- constructExecutionMetaData: jest.fn().mockReturnValue([]),
- },
- });
- });
-
- afterEach(() => {
- googleApiRequestArgs = [];
- jest.clearAllMocks();
- });
-
- describe('Google Calendar > Event > Create', () => {
- it('should not have invalid start and end date', async () => {
- //pre loop setup
- mockExecuteFunctions.getInputData.mockReturnValue([{ json: {} }]);
- mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('event');
- mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('create');
- mockExecuteFunctions.getTimezone.mockReturnValueOnce('Europe/Berlin');
- mockExecuteFunctions.getNode.mockReturnValue(mock({ typeVersion: 1.1 }));
- //operation
- mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('myCalendar');
- mockExecuteFunctions.getNodeParameter.mockReturnValueOnce(''); // start, not set
- mockExecuteFunctions.getNodeParameter.mockReturnValueOnce(''); // end, not set
- mockExecuteFunctions.getNodeParameter.mockReturnValueOnce(true); // useDefaultReminders
- mockExecuteFunctions.getNodeParameter.mockReturnValueOnce({}); // additionalFields
-
- await googleCalendar.execute.call(mockExecuteFunctions);
-
- expect(genericFunctions.googleApiRequest).toHaveBeenCalledTimes(1);
-
- const body = googleApiRequestArgs[2] as {
- start: { dateTime: string };
- end: { dateTime: string };
- };
-
- expect(body).toBeDefined();
- expect(body.start.dateTime).not.toEqual('Invalid Date');
- expect(body.end.dateTime).not.toEqual('Invalid Date');
- });
- });
-});