diff --git a/packages/nodes-base/nodes/Google/Sheet/GoogleSheetsTrigger.node.ts b/packages/nodes-base/nodes/Google/Sheet/GoogleSheetsTrigger.node.ts index 1558b7fd19..8993760e57 100644 --- a/packages/nodes-base/nodes/Google/Sheet/GoogleSheetsTrigger.node.ts +++ b/packages/nodes-base/nodes/Google/Sheet/GoogleSheetsTrigger.node.ts @@ -7,7 +7,7 @@ import type { } from 'n8n-workflow'; import { NodeConnectionType, NodeOperationError } from 'n8n-workflow'; -import { GOOGLE_DRIVE_FILE_URL_REGEX } from '../constants'; +import { GOOGLE_DRIVE_FILE_URL_REGEX, GOOGLE_SHEETS_SHEET_URL_REGEX } from '../constants'; import { apiRequest } from './v2/transport'; import { sheetsSearch, spreadSheetsSearch } from './v2/methods/listSearch'; import { GoogleSheet } from './v2/helpers/GoogleSheet'; @@ -137,15 +137,13 @@ export class GoogleSheetsTrigger implements INodeType { type: 'string', extractValue: { type: 'regex', - regex: - 'https:\\/\\/docs\\.google\\.com/spreadsheets\\/d\\/[0-9a-zA-Z\\-_]+\\/edit\\#gid=([0-9]+)', + regex: GOOGLE_SHEETS_SHEET_URL_REGEX, }, validation: [ { type: 'regex', properties: { - regex: - 'https:\\/\\/docs\\.google\\.com/spreadsheets\\/d\\/[0-9a-zA-Z\\-_]+\\/edit\\#gid=([0-9]+)', + regex: GOOGLE_SHEETS_SHEET_URL_REGEX, errorMessage: 'Not a valid Sheet URL', }, }, diff --git a/packages/nodes-base/nodes/Google/Sheet/test/v2/utils/utils.test.ts b/packages/nodes-base/nodes/Google/Sheet/test/v2/utils/utils.test.ts index 033f7249f8..c725d03bb9 100644 --- a/packages/nodes-base/nodes/Google/Sheet/test/v2/utils/utils.test.ts +++ b/packages/nodes-base/nodes/Google/Sheet/test/v2/utils/utils.test.ts @@ -1,9 +1,16 @@ -import type { IExecuteFunctions, INode, ResourceMapperField } from 'n8n-workflow'; +import { + NodeOperationError, + type IExecuteFunctions, + type INode, + type ResourceMapperField, +} from 'n8n-workflow'; + import { GoogleSheet } from '../../../v2/helpers/GoogleSheet'; import { addRowNumber, autoMapInputData, checkForSchemaChanges, + getSpreadsheetId, prepareSheetData, removeEmptyColumns, removeEmptyRows, @@ -11,6 +18,8 @@ import { trimToFirstEmptyRow, } from '../../../v2/helpers/GoogleSheets.utils'; +import { GOOGLE_SHEETS_SHEET_URL_REGEX } from '../../../../constants'; + describe('Test Google Sheets, addRowNumber', () => { it('should add row nomber', () => { const data = [ @@ -444,3 +453,73 @@ describe('Test Google Sheets, checkForSchemaChanges', () => { ).toThrow("Column names were updated after the node's setup"); }); }); + +describe('Test Google Sheets, getSpreadsheetId', () => { + let mockNode: INode; + + beforeEach(() => { + mockNode = { name: 'Google Sheets' } as INode; + jest.clearAllMocks(); + }); + + it('should throw an error if value is empty', () => { + expect(() => getSpreadsheetId(mockNode, 'url', '')).toThrow(NodeOperationError); + }); + + it('should return the ID from a valid URL', () => { + const url = + 'https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit#gid=0'; + const result = getSpreadsheetId(mockNode, 'url', url); + expect(result).toBe('1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms'); + }); + + it('should return an empty string for an invalid URL', () => { + const url = 'https://docs.google.com/spreadsheets/d/'; + const result = getSpreadsheetId(mockNode, 'url', url); + expect(result).toBe(''); + }); + + it('should return the value for documentIdType byId or byList', () => { + const value = '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms'; + expect(getSpreadsheetId(mockNode, 'id', value)).toBe(value); + expect(getSpreadsheetId(mockNode, 'list', value)).toBe(value); + }); +}); + +describe('Test Google Sheets, Google Sheets Sheet URL Regex', () => { + const regex = new RegExp(GOOGLE_SHEETS_SHEET_URL_REGEX); + + it('should match a valid Google Sheets URL', () => { + const urls = [ + 'https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit#gid=0', + 'https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit#gid=123456', + 'https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit?gid=654321#gid=654321', + ]; + for (const url of urls) { + expect(regex.test(url)).toBe(true); + } + }); + + it('should not match an invalid Google Sheets URL', () => { + const url = 'https://docs.google.com/spreadsheets/d/'; + expect(regex.test(url)).toBe(false); + }); + + it('should not match a URL that does not match the pattern', () => { + const url = + 'https://example.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit#gid=0'; + expect(regex.test(url)).toBe(false); + }); + + it('should extract the gid from a valid Google Sheets URL', () => { + const urls = [ + 'https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit#gid=12345', + 'https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit?gid=12345#gid=12345', + ]; + for (const url of urls) { + const match = url.match(regex); + expect(match).not.toBeNull(); + expect(match?.[1]).toBe('12345'); + } + }); +}); diff --git a/packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/Sheet.resource.ts b/packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/Sheet.resource.ts index 3cb7866aa5..d46e72811a 100644 --- a/packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/Sheet.resource.ts +++ b/packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/Sheet.resource.ts @@ -1,5 +1,5 @@ import type { INodeProperties } from 'n8n-workflow'; -import { GOOGLE_DRIVE_FILE_URL_REGEX } from '../../../../constants'; +import { GOOGLE_DRIVE_FILE_URL_REGEX, GOOGLE_SHEETS_SHEET_URL_REGEX } from '../../../../constants'; import * as append from './append.operation'; import * as appendOrUpdate from './appendOrUpdate.operation'; import * as clear from './clear.operation'; @@ -156,15 +156,13 @@ export const descriptions: INodeProperties[] = [ type: 'string', extractValue: { type: 'regex', - regex: - 'https:\\/\\/docs\\.google.com\\/spreadsheets\\/d\\/[0-9a-zA-Z\\-_]+.*\\#gid=([0-9]+)', + regex: GOOGLE_SHEETS_SHEET_URL_REGEX, }, validation: [ { type: 'regex', properties: { - regex: - 'https:\\/\\/docs\\.google.com\\/spreadsheets\\/d\\/[0-9a-zA-Z\\-_]+.*\\#gid=([0-9]+)', + regex: GOOGLE_SHEETS_SHEET_URL_REGEX, errorMessage: 'Not a valid Sheet URL', }, }, diff --git a/packages/nodes-base/nodes/Google/constants.ts b/packages/nodes-base/nodes/Google/constants.ts index 374cb345b5..e0cd0555c9 100644 --- a/packages/nodes-base/nodes/Google/constants.ts +++ b/packages/nodes-base/nodes/Google/constants.ts @@ -3,3 +3,6 @@ export const GOOGLE_DRIVE_FILE_URL_REGEX = export const GOOGLE_DRIVE_FOLDER_URL_REGEX = 'https:\\/\\/drive\\.google\\.com(?:\\/.*|)\\/folders\\/([0-9a-zA-Z\\-_]+)(?:\\/.*|)'; + +export const GOOGLE_SHEETS_SHEET_URL_REGEX = + 'https:\\/\\/docs\\.google\\.com\\/spreadsheets\\/d\\/[0-9a-zA-Z\\-_]+.*\\#gid=([0-9]+)';