first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,63 @@
import * as copy from '../../../../v2/actions/file/copy.operation';
import * as transport from '../../../../v2/transport';
import { createMockExecuteFunction, driveNode } from '../helpers';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
googleApiRequest: jest.fn(async function () {
return {};
}),
};
});
describe('test GoogleDriveV2: file copy', () => {
it('should be called with', async () => {
const nodeParameters = {
operation: 'copy',
fileId: {
__rl: true,
value: 'fileIDxxxxxx',
mode: 'list',
cachedResultName: 'test01.png',
cachedResultUrl: 'https://drive.google.com/file/d/fileIDxxxxxx/view?usp=drivesdk',
},
name: 'copyImage.png',
sameFolder: false,
folderId: {
__rl: true,
value: 'folderIDxxxxxx',
mode: 'list',
cachedResultName: 'testFolder 3',
cachedResultUrl: 'https://drive.google.com/drive/folders/folderIDxxxxxx',
},
options: {
copyRequiresWriterPermission: true,
description: 'image copy',
},
};
const fakeExecuteFunction = createMockExecuteFunction(nodeParameters, driveNode);
await copy.execute.call(fakeExecuteFunction, 0);
expect(transport.googleApiRequest).toBeCalledTimes(1);
expect(transport.googleApiRequest).toBeCalledWith(
'POST',
'/drive/v3/files/fileIDxxxxxx/copy',
{
copyRequiresWriterPermission: true,
description: 'image copy',
name: 'copyImage.png',
parents: ['folderIDxxxxxx'],
},
{
supportsAllDrives: true,
corpora: 'allDrives',
includeItemsFromAllDrives: true,
spaces: 'appDataFolder, drive',
},
);
});
});
@@ -0,0 +1,94 @@
import * as createFromText from '../../../../v2/actions/file/createFromText.operation';
import * as transport from '../../../../v2/transport';
import { createMockExecuteFunction, driveNode } from '../helpers';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
googleApiRequest: jest.fn(async function () {
return { id: 42 };
}),
};
});
describe('test GoogleDriveV2: file createFromText', () => {
it('should be called with', async () => {
const nodeParameters = {
operation: 'createFromText',
content: 'hello drive!',
name: 'helloDrive.txt',
folderId: {
__rl: true,
value: 'folderIDxxxxxx',
mode: 'list',
cachedResultName: 'testFolder 3',
cachedResultUrl: 'https://drive.google.com/drive/folders/folderIDxxxxxx',
},
options: {
appPropertiesUi: {
appPropertyValues: [
{
key: 'appKey1',
value: 'appValue1',
},
],
},
propertiesUi: {
propertyValues: [
{
key: 'prop1',
value: 'value1',
},
{
key: 'prop2',
value: 'value2',
},
],
},
keepRevisionForever: true,
ocrLanguage: 'en',
useContentAsIndexableText: true,
},
};
const fakeExecuteFunction = createMockExecuteFunction(nodeParameters, driveNode);
await createFromText.execute.call(fakeExecuteFunction, 0);
expect(transport.googleApiRequest).toBeCalledTimes(2);
expect(transport.googleApiRequest).toHaveBeenCalledWith(
'POST',
'/upload/drive/v3/files',
expect.anything(), // Buffer of content goes here
{ uploadType: 'multipart', supportsAllDrives: true },
undefined,
{
headers: {
'Content-Length': 503,
'Content-Type': expect.stringMatching(/^multipart\/related; boundary=(\\S)*/),
},
},
);
expect(transport.googleApiRequest).toHaveBeenCalledWith(
'PATCH',
'/drive/v3/files/42',
{
appProperties: { appKey1: 'appValue1' },
mimeType: 'text/plain',
name: 'helloDrive.txt',
properties: { prop1: 'value1', prop2: 'value2' },
},
{
addParents: 'folderIDxxxxxx',
corpora: 'allDrives',
includeItemsFromAllDrives: true,
keepRevisionForever: true,
ocrLanguage: 'en',
spaces: 'appDataFolder, drive',
supportsAllDrives: true,
useContentAsIndexableText: true,
},
);
});
});
@@ -0,0 +1,43 @@
import * as deleteFile from '../../../../v2/actions/file/deleteFile.operation';
import * as transport from '../../../../v2/transport';
import { createMockExecuteFunction, driveNode } from '../helpers';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
googleApiRequest: jest.fn(async function () {
return {};
}),
};
});
describe('test GoogleDriveV2: file deleteFile', () => {
it('should be called with', async () => {
const nodeParameters = {
operation: 'deleteFile',
fileId: {
__rl: true,
value: 'fileIDxxxxxx',
mode: 'list',
cachedResultName: 'test.txt',
cachedResultUrl: 'https://drive.google.com/file/d/fileIDxxxxxx/view?usp=drivesdk',
},
options: {
deletePermanently: true,
},
};
const fakeExecuteFunction = createMockExecuteFunction(nodeParameters, driveNode);
await deleteFile.execute.call(fakeExecuteFunction, 0);
expect(transport.googleApiRequest).toBeCalledTimes(1);
expect(transport.googleApiRequest).toHaveBeenCalledWith(
'DELETE',
'/drive/v3/files/fileIDxxxxxx',
undefined,
{ supportsAllDrives: true },
);
});
});
@@ -0,0 +1,51 @@
import * as download from '../../../../v2/actions/file/download.operation';
import * as transport from '../../../../v2/transport';
import { createMockExecuteFunction, driveNode } from '../helpers';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
googleApiRequest: jest.fn(async function () {
return {};
}),
};
});
describe('test GoogleDriveV2: file download', () => {
it('should be called with', async () => {
const nodeParameters = {
operation: 'deleteFile',
fileId: {
__rl: true,
value: 'fileIDxxxxxx',
mode: 'list',
cachedResultName: 'test.txt',
cachedResultUrl: 'https://drive.google.com/file/d/fileIDxxxxxx/view?usp=drivesdk',
},
options: {
deletePermanently: true,
},
};
const fakeExecuteFunction = createMockExecuteFunction(nodeParameters, driveNode);
await download.execute.call(fakeExecuteFunction, 0, { json: {} });
expect(transport.googleApiRequest).toBeCalledTimes(2);
expect(transport.googleApiRequest).toHaveBeenCalledWith(
'GET',
'/drive/v3/files/fileIDxxxxxx',
{},
{ fields: 'mimeType,name', supportsTeamDrives: true, supportsAllDrives: true },
);
expect(transport.googleApiRequest).toHaveBeenCalledWith(
'GET',
'/drive/v3/files/fileIDxxxxxx',
{},
{ alt: 'media', supportsAllDrives: true },
undefined,
{ encoding: 'arraybuffer', json: false, returnFullResponse: true, useStream: true },
);
});
});
@@ -0,0 +1,73 @@
import type { IHttpRequestMethods } from 'n8n-workflow';
import * as move from '../../../../v2/actions/file/move.operation';
import * as transport from '../../../../v2/transport';
import { createMockExecuteFunction, driveNode } from '../helpers';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
googleApiRequest: jest.fn(async function (method: IHttpRequestMethods) {
if (method === 'GET') {
return {
parents: ['parentFolderIDxxxxxx'],
};
}
return {};
}),
};
});
describe('test GoogleDriveV2: file move', () => {
it('should be called with', async () => {
const nodeParameters = {
operation: 'move',
fileId: {
__rl: true,
value: 'fileIDxxxxxx',
mode: 'list',
cachedResultName: 'test.txt',
cachedResultUrl: 'https://drive.google.com/file/d/fileIDxxxxxx/view?usp=drivesdk',
},
folderId: {
__rl: true,
value: 'folderIDxxxxxx',
mode: 'list',
cachedResultName: 'testFolder1',
cachedResultUrl: 'https://drive.google.com/drive/folders/folderIDxxxxxx',
},
};
const fakeExecuteFunction = createMockExecuteFunction(nodeParameters, driveNode);
await move.execute.call(fakeExecuteFunction, 0);
expect(transport.googleApiRequest).toBeCalledTimes(2);
expect(transport.googleApiRequest).toHaveBeenCalledWith(
'GET',
'/drive/v3/files/fileIDxxxxxx',
undefined,
{
corpora: 'allDrives',
fields: 'parents',
includeItemsFromAllDrives: true,
spaces: 'appDataFolder, drive',
supportsAllDrives: true,
},
);
expect(transport.googleApiRequest).toHaveBeenCalledWith(
'PATCH',
'/drive/v3/files/fileIDxxxxxx',
undefined,
{
addParents: 'folderIDxxxxxx',
removeParents: 'parentFolderIDxxxxxx',
corpora: 'allDrives',
includeItemsFromAllDrives: true,
spaces: 'appDataFolder, drive',
supportsAllDrives: true,
},
);
});
});
@@ -0,0 +1,61 @@
import * as share from '../../../../v2/actions/file/share.operation';
import * as transport from '../../../../v2/transport';
import { createMockExecuteFunction, driveNode } from '../helpers';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
googleApiRequest: jest.fn(async function () {
return {};
}),
};
});
describe('test GoogleDriveV2: file share', () => {
it('should be called with', async () => {
const nodeParameters = {
operation: 'share',
fileId: {
__rl: true,
value: 'fileIDxxxxxx',
mode: 'list',
cachedResultName: 'test.txt',
cachedResultUrl: 'https://drive.google.com/file/d/fileIDxxxxxx/view?usp=drivesdk',
},
permissionsUi: {
permissionsValues: {
role: 'owner',
type: 'user',
emailAddress: 'user@gmail.com',
},
},
options: {
emailMessage: 'some message',
moveToNewOwnersRoot: true,
sendNotificationEmail: true,
transferOwnership: true,
useDomainAdminAccess: true,
},
};
const fakeExecuteFunction = createMockExecuteFunction(nodeParameters, driveNode);
await share.execute.call(fakeExecuteFunction, 0);
expect(transport.googleApiRequest).toBeCalledTimes(1);
expect(transport.googleApiRequest).toHaveBeenCalledWith(
'POST',
'/drive/v3/files/fileIDxxxxxx/permissions',
{ emailAddress: 'user@gmail.com', role: 'owner', type: 'user' },
{
emailMessage: 'some message',
moveToNewOwnersRoot: true,
sendNotificationEmail: true,
supportsAllDrives: true,
transferOwnership: true,
useDomainAdminAccess: true,
},
);
});
});
@@ -0,0 +1,53 @@
import * as update from '../../../../v2/actions/file/update.operation';
import * as transport from '../../../../v2/transport';
import { createMockExecuteFunction, driveNode } from '../helpers';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
googleApiRequest: jest.fn(async function () {
return {};
}),
};
});
describe('test GoogleDriveV2: file update', () => {
it('should be called with', async () => {
const nodeParameters = {
operation: 'update',
fileId: {
__rl: true,
value: 'fileIDxxxxxx',
mode: 'list',
cachedResultName: 'test.txt',
cachedResultUrl: 'https://drive.google.com/file/d/fileIDxxxxxx/view?usp=drivesdk',
},
newUpdatedFileName: 'test2.txt',
options: {
keepRevisionForever: true,
ocrLanguage: 'en',
useContentAsIndexableText: true,
fields: ['hasThumbnail', 'starred'],
},
};
const fakeExecuteFunction = createMockExecuteFunction(nodeParameters, driveNode);
await update.execute.call(fakeExecuteFunction, 0);
expect(transport.googleApiRequest).toBeCalledTimes(1);
expect(transport.googleApiRequest).toHaveBeenCalledWith(
'PATCH',
'/drive/v3/files/fileIDxxxxxx',
{ name: 'test2.txt' },
{
fields: 'hasThumbnail, starred',
keepRevisionForever: true,
ocrLanguage: 'en',
supportsAllDrives: true,
useContentAsIndexableText: true,
},
);
});
});
@@ -0,0 +1,160 @@
import type { IHttpRequestMethods } from 'n8n-workflow';
import * as upload from '../../../../v2/actions/file/upload.operation';
import * as utils from '../../../../v2/helpers/utils';
import * as transport from '../../../../v2/transport';
import { createMockExecuteFunction, createTestStream, driveNode } from '../helpers';
const fileContent = Buffer.from('Hello Drive!');
const originalFilename = 'original.txt';
const contentLength = 123;
const mimeType = 'text/plain';
jest.mock('../../../../v2/transport', () => {
const originalModule = jest.requireActual('../../../../v2/transport');
return {
...originalModule,
googleApiRequest: jest.fn(async function (method: IHttpRequestMethods) {
if (method === 'POST') {
return {
headers: { location: 'someLocation' },
};
}
return {};
}),
};
});
jest.mock('../../../../v2/helpers/utils', () => {
const originalModule = jest.requireActual('../../../../v2/helpers/utils');
return {
...originalModule,
getItemBinaryData: jest.fn(async function () {
return {
contentLength,
fileContent,
originalFilename,
mimeType,
};
}),
};
});
describe('test GoogleDriveV2: file upload', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('should upload buffers', async () => {
const name = 'newFile.txt';
const parent = 'folderIDxxxxxx';
const nodeParameters = {
name,
folderId: {
__rl: true,
value: parent,
mode: 'list',
cachedResultName: 'testFolder 3',
cachedResultUrl: 'https://drive.google.com/drive/folders/folderIDxxxxxx',
},
options: {
simplifyOutput: true,
},
};
const fakeExecuteFunction = createMockExecuteFunction(nodeParameters, driveNode);
await upload.execute.call(fakeExecuteFunction, 0);
expect(transport.googleApiRequest).toBeCalledTimes(2);
expect(transport.googleApiRequest).toHaveBeenCalledWith(
'POST',
'/upload/drive/v3/files',
expect.any(Buffer),
{ uploadType: 'multipart', supportsAllDrives: true },
undefined,
{
headers: {
'Content-Length': 498,
'Content-Type': expect.stringMatching(/^multipart\/related; boundary=(\\S)*/),
},
},
);
expect(transport.googleApiRequest).toHaveBeenCalledWith(
'PATCH',
'/drive/v3/files/undefined',
{ mimeType, name, originalFilename },
{
addParents: parent,
supportsAllDrives: true,
corpora: 'allDrives',
includeItemsFromAllDrives: true,
spaces: 'appDataFolder, drive',
},
);
expect(utils.getItemBinaryData).toBeCalledTimes(1);
expect(utils.getItemBinaryData).toHaveBeenCalled();
});
it('should stream large files in 2MB chunks', async () => {
const name = 'newFile.jpg';
const parent = 'folderIDxxxxxx';
const originalFilename = 'test.jpg';
const mimeType = 'image/jpg';
const nodeParameters = {
name,
folderId: {
__rl: true,
value: parent,
mode: 'list',
cachedResultName: 'testFolder 3',
cachedResultUrl: 'https://drive.google.com/drive/folders/folderIDxxxxxx',
},
options: {
simplifyOutput: true,
},
};
const fakeExecuteFunction = createMockExecuteFunction(nodeParameters, driveNode);
const httpRequestSpy = jest.spyOn(fakeExecuteFunction.helpers, 'httpRequest');
const fileSize = 7 * 1024 * 1024; // 7MB
jest.mocked(utils.getItemBinaryData).mockResolvedValue({
mimeType,
originalFilename,
contentLength: fileSize,
fileContent: createTestStream(fileSize),
});
await upload.execute.call(fakeExecuteFunction, 0);
// 4 chunks: 7MB = 3x2MB + 1x1MB
expect(httpRequestSpy).toHaveBeenCalledTimes(4);
expect(httpRequestSpy).toHaveBeenCalledWith(
expect.objectContaining({ body: expect.any(Buffer) }),
);
expect(transport.googleApiRequest).toBeCalledTimes(2);
expect(transport.googleApiRequest).toHaveBeenCalledWith(
'POST',
'/upload/drive/v3/files',
{ name, parents: [parent] },
{ uploadType: 'resumable', supportsAllDrives: true },
undefined,
{ returnFullResponse: true, headers: { 'X-Upload-Content-Type': 'image/jpg' } },
);
expect(transport.googleApiRequest).toHaveBeenCalledWith(
'PATCH',
'/drive/v3/files/undefined',
{ mimeType, name, originalFilename },
{
addParents: parent,
supportsAllDrives: true,
corpora: 'allDrives',
includeItemsFromAllDrives: true,
spaces: 'appDataFolder, drive',
},
);
});
});