From 7381c28af00148b329690021b921267a48a6eaa3 Mon Sep 17 00:00:00 2001 From: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:02:26 +0000 Subject: [PATCH] fix(YouTube Node): Issue in published before and after dates filters (#11741) --- .../nodes/Google/GenericFunctions.ts | 33 ++++++++++++---- .../nodes/Google/YouTube/YouTube.node.ts | 24 +++--------- .../YouTube/test/GenericFunctions.test.ts | 38 +++++++++++++++++++ 3 files changed, 69 insertions(+), 26 deletions(-) create mode 100644 packages/nodes-base/nodes/Google/YouTube/test/GenericFunctions.test.ts diff --git a/packages/nodes-base/nodes/Google/GenericFunctions.ts b/packages/nodes-base/nodes/Google/GenericFunctions.ts index 2c4781e552..4a893ded00 100644 --- a/packages/nodes-base/nodes/Google/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Google/GenericFunctions.ts @@ -1,16 +1,18 @@ -import type { - IExecuteFunctions, - ILoadOptionsFunctions, - ICredentialTestFunctions, - IDataObject, - IPollFunctions, - IRequestOptions, +import { + type IExecuteFunctions, + type ILoadOptionsFunctions, + type ICredentialTestFunctions, + type IDataObject, + type IPollFunctions, + type IRequestOptions, + NodeOperationError, } from 'n8n-workflow'; import moment from 'moment-timezone'; import * as jwt from 'jsonwebtoken'; import { formatPrivateKey } from '@utils/utilities'; +import { DateTime } from 'luxon'; const googleServiceAccountScopes = { bigquery: ['https://www.googleapis.com/auth/bigquery'], @@ -110,3 +112,20 @@ export async function getGoogleAccessToken( return await this.helpers.request(options); } + +export function validateAndSetDate( + filter: IDataObject, + key: string, + timezone: string, + context: IExecuteFunctions, +) { + const date = DateTime.fromISO(filter[key] as string); + if (date.isValid) { + filter[key] = date.setZone(timezone).toISO(); + } else { + throw new NodeOperationError( + context.getNode(), + `The value "${filter[key] as string}" is not a valid DateTime.`, + ); + } +} diff --git a/packages/nodes-base/nodes/Google/YouTube/YouTube.node.ts b/packages/nodes-base/nodes/Google/YouTube/YouTube.node.ts index 07de1d36fa..663ec61896 100644 --- a/packages/nodes-base/nodes/Google/YouTube/YouTube.node.ts +++ b/packages/nodes-base/nodes/Google/YouTube/YouTube.node.ts @@ -10,7 +10,6 @@ import type { } from 'n8n-workflow'; import { NodeConnectionType, BINARY_ENCODING, NodeOperationError } from 'n8n-workflow'; -import { DateTime } from 'luxon'; import { googleApiRequest, googleApiRequestAllItems } from './GenericFunctions'; import { channelFields, channelOperations } from './ChannelDescription'; @@ -24,6 +23,7 @@ import { videoFields, videoOperations } from './VideoDescription'; import { videoCategoryFields, videoCategoryOperations } from './VideoCategoryDescription'; import { isoCountryCodes } from '@utils/ISOCountryCodes'; +import { validateAndSetDate } from '../GenericFunctions'; const UPLOAD_CHUNK_SIZE = 1024 * 1024; @@ -763,27 +763,13 @@ export class YouTube implements INodeType { qs.type = 'video'; qs.forMine = true; + if (filters.publishedAfter) { - const publishedAfter = DateTime.fromISO(filters.publishedAfter as string); - if (publishedAfter.isValid) { - filters.publishedAfter = publishedAfter.setZone(this.getTimezone()).toISO(); - } else { - throw new NodeOperationError( - this.getNode(), - `The value "${filters.publishedAfter as string}" is not a valid DateTime.`, - ); - } + validateAndSetDate(filters, 'publishedAfter', this.getTimezone(), this); } + if (filters.publishedBefore) { - const publishedBefore = DateTime.fromISO(filters.publishedBefore as string); - if (publishedBefore.isValid) { - filters.publishedAfter = publishedBefore.setZone(this.getTimezone()).toISO(); - } else { - throw new NodeOperationError( - this.getNode(), - `The value "${filters.publishedBefore as string}" is not a valid DateTime.`, - ); - } + validateAndSetDate(filters, 'publishedBefore', this.getTimezone(), this); } Object.assign(qs, options, filters); diff --git a/packages/nodes-base/nodes/Google/YouTube/test/GenericFunctions.test.ts b/packages/nodes-base/nodes/Google/YouTube/test/GenericFunctions.test.ts new file mode 100644 index 0000000000..d56e1b452b --- /dev/null +++ b/packages/nodes-base/nodes/Google/YouTube/test/GenericFunctions.test.ts @@ -0,0 +1,38 @@ +import { DateTime } from 'luxon'; +import { NodeOperationError, type IExecuteFunctions } from 'n8n-workflow'; + +import { validateAndSetDate } from '../../GenericFunctions'; + +const mockContext = { + getNode: jest.fn().mockReturnValue('Youtube'), +} as unknown as IExecuteFunctions; + +describe('validateAndSetDate', () => { + const timezone = 'America/New_York'; + let filter: { [key: string]: string }; + + beforeEach(() => { + filter = {}; + }); + + it('should convert a valid ISO date and set it with the specified timezone', () => { + filter.publishedAfter = '2023-10-05T10:00:00.000Z'; + validateAndSetDate(filter, 'publishedAfter', timezone, mockContext); + + expect(filter.publishedAfter).toBe( + DateTime.fromISO('2023-10-05T10:00:00.000Z').setZone(timezone).toISO(), + ); + }); + + it('should throw NodeOperationError for an invalid date', () => { + filter.publishedAfter = 'invalid-date'; + + expect(() => validateAndSetDate(filter, 'publishedAfter', timezone, mockContext)).toThrow( + NodeOperationError, + ); + + expect(() => validateAndSetDate(filter, 'publishedAfter', timezone, mockContext)).toThrow( + `The value "${filter.publishedAfter}" is not a valid DateTime.`, + ); + }); +});