feat(Microsoft SharePoint Node): New node (#13727)

This commit is contained in:
feelgood-interface
2025-05-16 09:55:10 +02:00
committed by GitHub
parent 64b3fa3d17
commit 954b66218f
57 changed files with 6284 additions and 12 deletions

View File

@@ -1,25 +1,14 @@
import type { Icon, ICredentialType, INodeProperties } from 'n8n-workflow';
import type { ICredentialType, INodeProperties } from 'n8n-workflow';
export class MicrosoftSharePointOAuth2Api implements ICredentialType {
name = 'microsoftSharePointOAuth2Api';
extends = ['microsoftOAuth2Api'];
icon: Icon = {
light: 'file:icons/SharePoint.svg',
dark: 'file:icons/SharePoint.svg',
};
displayName = 'Microsoft SharePoint OAuth2 API';
documentationUrl = 'microsoft';
httpRequestNode = {
name: 'Microsoft SharePoint',
docsUrl: 'https://learn.microsoft.com/en-us/sharepoint/dev/apis/sharepoint-rest-graph',
apiBaseUrlPlaceholder: 'https://{subdomain}.sharepoint.com/_api/v2.0/',
};
properties: INodeProperties[] = [
{
displayName: 'Scope',

View File

@@ -0,0 +1,68 @@
import type { INodeType, INodeTypeDescription } from 'n8n-workflow';
import { NodeConnectionTypes } from 'n8n-workflow';
import { file, item, list } from './descriptions';
import { listSearch, resourceMapping } from './methods';
export class MicrosoftSharePoint implements INodeType {
description: INodeTypeDescription = {
displayName: 'Microsoft SharePoint',
name: 'microsoftSharePoint',
icon: {
light: 'file:microsoftSharePoint.svg',
dark: 'file:microsoftSharePoint.svg',
},
group: ['transform'],
version: 1,
subtitle: '={{ $parameter["operation"] + ": " + $parameter["resource"] }}',
description: 'Interact with Microsoft SharePoint API',
defaults: {
name: 'Microsoft SharePoint',
},
usableAsTool: true,
inputs: [NodeConnectionTypes.Main],
outputs: [NodeConnectionTypes.Main],
credentials: [
{
name: 'microsoftSharePointOAuth2Api',
required: true,
},
],
requestDefaults: {
baseURL: '=https://{{ $credentials.subdomain }}.sharepoint.com/_api/v2.0/',
ignoreHttpStatusErrors: true,
},
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'File',
value: 'file',
},
{
name: 'Item',
value: 'item',
},
{
name: 'List',
value: 'list',
},
],
default: 'file',
},
...file.description,
...item.description,
...list.description,
],
};
methods = {
listSearch,
resourceMapping,
};
}

View File

@@ -0,0 +1,18 @@
{
"node": "n8n-nodes-base.microsoftSharePoint",
"nodeVersion": "1.0",
"codexVersion": "1.0",
"categories": ["ECM"],
"resources": {
"credentialDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/credentials/microsoft/"
}
],
"primaryDocumentation": [
{
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.microsoftsharepoint/"
}
]
}
}

View File

@@ -0,0 +1,156 @@
import type { INodeProperties } from 'n8n-workflow';
export const untilFolderSelected = { folder: [''] };
export const untilItemSelected = { item: [''] };
export const untilListSelected = { list: [''] };
export const untilSiteSelected = { site: [''] };
export const fileRLC: INodeProperties = {
displayName: 'File',
name: 'file',
default: {
mode: 'list',
value: '',
},
description: 'Select the file to download',
modes: [
{
displayName: 'From List',
name: 'list',
type: 'list',
typeOptions: {
searchListMethod: 'getFiles',
searchable: true,
},
},
{
displayName: 'By ID',
name: 'id',
placeholder: 'e.g. mysite',
type: 'string',
},
],
placeholder: 'eg. my-file.pdf',
required: true,
type: 'resourceLocator',
};
export const folderRLC: INodeProperties = {
displayName: 'Parent Folder',
name: 'folder',
default: {
mode: 'list',
value: '',
},
description: 'Select the folder to update the file in',
modes: [
{
displayName: 'From List',
name: 'list',
type: 'list',
typeOptions: {
searchListMethod: 'getFolders',
searchable: true,
},
},
{
displayName: 'By ID',
name: 'id',
placeholder: 'e.g. myfolder',
type: 'string',
},
],
placeholder: '/ (Library root)',
required: true,
type: 'resourceLocator',
};
export const itemRLC: INodeProperties = {
displayName: 'Item',
name: 'item',
default: {
mode: 'list',
value: '',
},
description: 'Select the item you want to delete',
modes: [
{
displayName: 'From List',
name: 'list',
type: 'list',
typeOptions: {
searchListMethod: 'getItems',
searchable: true,
},
},
{
displayName: 'By ID',
name: 'id',
placeholder: 'e.g. 1',
type: 'string',
},
],
required: true,
type: 'resourceLocator',
};
export const listRLC: INodeProperties = {
displayName: 'List',
name: 'list',
default: {
mode: 'list',
value: '',
},
description: 'Select the list you want to retrieve',
modes: [
{
displayName: 'From List',
name: 'list',
type: 'list',
typeOptions: {
searchListMethod: 'getLists',
searchable: true,
},
},
{
displayName: 'By ID',
name: 'id',
placeholder: 'e.g. mylist',
type: 'string',
},
],
required: true,
type: 'resourceLocator',
};
export const siteRLC: INodeProperties = {
displayName: 'Site',
name: 'site',
default: {
mode: 'list',
value: '',
},
description: 'Select the site to retrieve folders from',
modes: [
{
displayName: 'From List',
name: 'list',
type: 'list',
typeOptions: {
searchListMethod: 'getSites',
searchable: true,
},
},
{
displayName: 'By ID',
name: 'id',
placeholder: 'e.g. mysite',
type: 'string',
},
],
required: true,
type: 'resourceLocator',
};

View File

@@ -0,0 +1,74 @@
import type { INodeProperties } from 'n8n-workflow';
import * as download from './download.operation';
import * as update from './update.operation';
import * as upload from './upload.operation';
import { downloadFilePostReceive, handleErrorPostReceive } from '../../helpers/utils';
export const description: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['file'],
},
},
options: [
{
name: 'Download',
value: 'download',
description: 'Download a file',
routing: {
request: {
method: 'GET',
url: '=/sites/{{ $parameter["site"] }}/drive/items/{{ $parameter["file"] }}/content',
json: false,
encoding: 'arraybuffer',
},
output: {
postReceive: [handleErrorPostReceive, downloadFilePostReceive],
},
},
action: 'Download file',
},
{
name: 'Update',
value: 'update',
description: 'Update a file',
routing: {
request: {
method: 'PATCH',
url: '=/sites/{{ $parameter["site"] }}/drive/items/{{ $parameter["file"] }}',
},
output: {
postReceive: [handleErrorPostReceive],
},
},
action: 'Update file',
},
{
name: 'Upload',
value: 'upload',
description: 'Upload an existing file',
routing: {
request: {
method: 'PUT',
url: '=/sites/{{ $parameter["site"] }}/drive/items/{{ $parameter["folder"] }}:/{{ $parameter["fileName"] }}:/content',
},
output: {
postReceive: [handleErrorPostReceive],
},
},
action: 'Upload file',
},
],
default: 'download',
},
...download.description,
...update.description,
...upload.description,
];

View File

@@ -0,0 +1,44 @@
import { updateDisplayOptions, type INodeProperties } from 'n8n-workflow';
import {
fileRLC,
folderRLC,
siteRLC,
untilFolderSelected,
untilSiteSelected,
} from '../common.descriptions';
const properties: INodeProperties[] = [
{
...siteRLC,
description: 'Select the site to retrieve folders from',
},
{
...folderRLC,
description: 'Select the folder to download the file from',
displayOptions: {
hide: {
...untilSiteSelected,
},
},
},
{
...fileRLC,
description: 'Select the file to download',
displayOptions: {
hide: {
...untilSiteSelected,
...untilFolderSelected,
},
},
},
];
const displayOptions = {
show: {
resource: ['file'],
operation: ['download'],
},
};
export const description = updateDisplayOptions(displayOptions, properties);

View File

@@ -0,0 +1,122 @@
import {
updateDisplayOptions,
type IExecuteSingleFunctions,
type IN8nHttpFullResponse,
type INodeExecutionData,
type INodeProperties,
} from 'n8n-workflow';
import { microsoftSharePointApiRequest } from '../../transport';
import {
fileRLC,
folderRLC,
siteRLC,
untilFolderSelected,
untilSiteSelected,
} from '../common.descriptions';
const properties: INodeProperties[] = [
{
...siteRLC,
description: 'Select the site to retrieve folders from',
},
{
...folderRLC,
description: 'Select the folder to update the file in',
displayOptions: {
hide: {
...untilSiteSelected,
},
},
},
{
...fileRLC,
description: 'Select the file to update',
displayOptions: {
hide: {
...untilSiteSelected,
...untilFolderSelected,
},
},
},
{
displayName: 'Updated File Name',
name: 'fileName',
default: '',
description: 'If not specified, the original file name will be used',
placeholder: 'e.g. My New File',
routing: {
send: {
property: 'name',
type: 'body',
value: '={{ $value }}',
},
},
type: 'string',
},
{
displayName: 'Change File Content',
name: 'changeFileContent',
default: false,
description: 'Whether to update the file contents',
placeholder: 'e.g. My New File',
required: true,
type: 'boolean',
},
{
displayName: 'Updated File Contents',
name: 'fileContents',
default: '',
description:
'Find the name of input field containing the binary data to update the file in the Input panel on the left, in the Binary tab',
displayOptions: {
show: {
changeFileContent: [true],
},
},
hint: 'The name of the input field containing the binary file data to update the file',
placeholder: 'data',
required: true,
routing: {
output: {
postReceive: [
async function (
this: IExecuteSingleFunctions,
items: INodeExecutionData[],
_response: IN8nHttpFullResponse,
): Promise<INodeExecutionData[]> {
for (const item of items) {
const site = this.getNodeParameter('site', undefined, {
extractValue: true,
}) as string;
const file = this.getNodeParameter('file', undefined, {
extractValue: true,
}) as string;
const binaryProperty = this.getNodeParameter('fileContents') as string;
this.helpers.assertBinaryData(binaryProperty);
const binaryDataBuffer = await this.helpers.getBinaryDataBuffer(binaryProperty);
const response = await microsoftSharePointApiRequest.call(
this,
'PUT',
`/sites/${site}/drive/items/${file}/content`,
binaryDataBuffer,
);
item.json = response;
}
return items;
},
],
},
},
type: 'string',
},
];
const displayOptions = {
show: {
resource: ['file'],
operation: ['update'],
},
};
export const description = updateDisplayOptions(displayOptions, properties);

View File

@@ -0,0 +1,54 @@
import { updateDisplayOptions, type INodeProperties } from 'n8n-workflow';
import { uploadFilePreSend } from '../../helpers/utils';
import { folderRLC, siteRLC, untilSiteSelected } from '../common.descriptions';
const properties: INodeProperties[] = [
{
...siteRLC,
description: 'Select the site to retrieve folders from',
},
{
...folderRLC,
description: 'Select the folder to upload the file to',
displayOptions: {
hide: {
...untilSiteSelected,
},
},
},
{
displayName: 'File Name',
name: 'fileName',
default: '',
description: 'The name of the file being uploaded',
placeholder: 'e.g. My New File',
required: true,
type: 'string',
},
{
displayName: 'File Contents',
name: 'fileContents',
default: '',
description:
'Find the name of input field containing the binary data to upload the file in the Input panel on the left, in the Binary tab',
hint: 'The name of the input field containing the binary file data to update the file',
placeholder: 'data',
required: true,
routing: {
send: {
preSend: [uploadFilePreSend],
},
},
type: 'string',
},
];
const displayOptions = {
show: {
resource: ['file'],
operation: ['upload'],
},
};
export const description = updateDisplayOptions(displayOptions, properties);

View File

@@ -0,0 +1,3 @@
export * as file from './file/File.resource';
export * as item from './item/Item.resource';
export * as list from './list/List.resource';

View File

@@ -0,0 +1,141 @@
import type { INodeProperties } from 'n8n-workflow';
import * as create from './create.operation';
import * as del from './delete.operation';
import * as get from './get.operation';
import * as getAll from './getAll.operation';
import * as update from './update.operation';
import * as upsert from './upsert.operation';
import { handleErrorPostReceive, simplifyItemPostReceive } from '../../helpers/utils';
export const description: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['item'],
},
},
options: [
{
name: 'Create',
value: 'create',
description: 'Create an item in an existing list',
routing: {
request: {
method: 'POST',
url: '=/sites/{{ $parameter["site"] }}/lists/{{ $parameter["list"] }}/items',
},
output: {
postReceive: [handleErrorPostReceive],
},
},
action: 'Create item in a list',
},
{
name: 'Create or Update',
value: 'upsert',
description: 'Create a new record, or update the current one if it already exists (upsert)',
routing: {
request: {
method: 'POST',
url: '=/sites/{{ $parameter["site"] }}/lists/{{ $parameter["list"] }}/items',
},
output: {
postReceive: [handleErrorPostReceive],
},
},
action: 'Create or update item (upsert)',
},
{
name: 'Delete',
value: 'delete',
description: 'Delete an item from a list',
routing: {
request: {
method: 'DELETE',
url: '=/sites/{{ $parameter["site"] }}/lists/{{ $parameter["list"] }}/items/{{ $parameter["item"] }}',
},
output: {
postReceive: [
handleErrorPostReceive,
{
type: 'set',
properties: {
value: '={{ { "deleted": true } }}',
},
},
],
},
},
action: 'Delete an item',
},
{
name: 'Get',
value: 'get',
description: 'Retrieve an item from a list',
routing: {
request: {
ignoreHttpStatusErrors: true,
method: 'GET',
url: '=/sites/{{ $parameter["site"] }}/lists/{{ $parameter["list"] }}/items/{{ $parameter["item"] }}',
},
output: {
postReceive: [handleErrorPostReceive, simplifyItemPostReceive],
},
},
action: 'Get an item',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Get specific items in a list or list many items',
routing: {
request: {
method: 'GET',
url: '=/sites/{{ $parameter["site"] }}/lists/{{ $parameter["list"] }}/items',
},
output: {
postReceive: [
handleErrorPostReceive,
{
type: 'rootProperty',
properties: {
property: 'value',
},
},
simplifyItemPostReceive,
],
},
},
action: 'Get many items',
},
{
name: 'Update',
value: 'update',
description: 'Update an item in an existing list',
routing: {
request: {
method: 'PATCH',
url: '=/sites/{{ $parameter["site"] }}/lists/{{ $parameter["list"] }}/items',
},
output: {
postReceive: [handleErrorPostReceive],
},
},
action: 'Update item in a list',
},
],
default: 'getAll',
},
...create.description,
...del.description,
...get.description,
...getAll.description,
...update.description,
...upsert.description,
];

View File

@@ -0,0 +1,77 @@
import { updateDisplayOptions, type INodeProperties } from 'n8n-workflow';
import { itemColumnsPreSend } from '../../helpers/utils';
import { listRLC, siteRLC, untilListSelected, untilSiteSelected } from '../common.descriptions';
const properties: INodeProperties[] = [
{
...siteRLC,
description: 'Select the site to retrieve lists from',
},
{
...listRLC,
description: 'Select the list you want to create an item in',
displayOptions: {
hide: {
...untilSiteSelected,
},
},
},
{
displayName:
'Due to API restrictions, the following column types cannot be updated: Hyperlink, Location, Metadata',
name: 'noticeUnsupportedFields',
displayOptions: {
hide: {
...untilSiteSelected,
...untilListSelected,
},
},
type: 'notice',
default: '',
},
{
displayName: 'Columns',
name: 'columns',
default: {
mappingMode: 'defineBelow',
value: null,
},
displayOptions: {
hide: {
...untilSiteSelected,
...untilListSelected,
},
},
noDataExpression: true,
required: true,
routing: {
send: {
preSend: [itemColumnsPreSend],
},
},
type: 'resourceMapper',
typeOptions: {
loadOptionsDependsOn: ['site.value', 'list.value'],
resourceMapper: {
resourceMapperMethod: 'getMappingColumns',
mode: 'add',
fieldWords: {
singular: 'column',
plural: 'columns',
},
addAllFields: true,
multiKeyMatch: false,
},
},
},
];
const displayOptions = {
show: {
resource: ['item'],
operation: ['create'],
},
};
export const description = updateDisplayOptions(displayOptions, properties);

View File

@@ -0,0 +1,44 @@
import { updateDisplayOptions, type INodeProperties } from 'n8n-workflow';
import {
itemRLC,
listRLC,
siteRLC,
untilListSelected,
untilSiteSelected,
} from '../common.descriptions';
const properties: INodeProperties[] = [
{
...siteRLC,
description: 'Select the site to retrieve lists from',
},
{
...listRLC,
description: 'Select the list you want to delete an item in',
displayOptions: {
hide: {
...untilSiteSelected,
},
},
},
{
...itemRLC,
description: 'Select the item you want to delete',
displayOptions: {
hide: {
...untilSiteSelected,
...untilListSelected,
},
},
},
];
const displayOptions = {
show: {
resource: ['item'],
operation: ['delete'],
},
};
export const description = updateDisplayOptions(displayOptions, properties);

View File

@@ -0,0 +1,69 @@
import type { IExecuteSingleFunctions, IHttpRequestOptions, INodeProperties } from 'n8n-workflow';
import { updateDisplayOptions } from 'n8n-workflow';
import {
itemRLC,
listRLC,
siteRLC,
untilListSelected,
untilSiteSelected,
} from '../common.descriptions';
const properties: INodeProperties[] = [
{
...siteRLC,
description: 'Select the site to retrieve lists from',
},
{
...listRLC,
description: 'Select the list you want to retrieve an item from',
displayOptions: {
hide: {
...untilSiteSelected,
},
},
},
{
...itemRLC,
description: 'Select the item you want to get',
displayOptions: {
hide: {
...untilSiteSelected,
...untilListSelected,
},
},
},
{
displayName: 'Simplify',
name: 'simplify',
default: true,
routing: {
send: {
preSend: [
async function (
this: IExecuteSingleFunctions,
requestOptions: IHttpRequestOptions,
): Promise<IHttpRequestOptions> {
const simplify = this.getNodeParameter('simplify', false) as boolean;
if (simplify) {
requestOptions.qs ??= {};
requestOptions.qs.$select = 'id,createdDateTime,lastModifiedDateTime,webUrl';
requestOptions.qs.$expand = 'fields(select=Title)';
}
return requestOptions;
},
],
},
},
type: 'boolean',
},
];
const displayOptions = {
show: {
resource: ['item'],
operation: ['get'],
},
};
export const description = updateDisplayOptions(displayOptions, properties);

View File

@@ -0,0 +1,186 @@
import type { IExecuteSingleFunctions, IHttpRequestOptions, INodeProperties } from 'n8n-workflow';
import { updateDisplayOptions } from 'n8n-workflow';
import { itemGetAllFieldsPreSend } from '../../helpers/utils';
import { listRLC, siteRLC, untilSiteSelected } from '../common.descriptions';
const properties: INodeProperties[] = [
{
...siteRLC,
description: 'Select the site to retrieve lists from',
},
{
...listRLC,
description: 'Select the list you want to search for items in',
displayOptions: {
hide: {
...untilSiteSelected,
},
},
},
{
displayName: 'Filter by Formula',
name: 'filter',
default: '',
description:
'The formula will be evaluated for each record. <a href="https://learn.microsoft.com/en-us/graph/filter-query-parameter">More info</a>.',
hint: 'If empty, all the items will be returned',
placeholder: "e.g. fields/Title eq 'item1'",
routing: {
send: {
property: '$filter',
type: 'query',
value: '={{ $value ? $value : undefined }}',
},
},
type: 'string',
},
{
displayName: 'Return All',
name: 'returnAll',
default: false,
description: 'Whether to return all results or only up to a given limit',
routing: {
send: {
paginate: '={{ $value }}',
},
operations: {
pagination: {
type: 'generic',
properties: {
continue: '={{ !!$response.body?.["@odata.nextLink"] }}',
request: {
url: '={{ $response.body?.["@odata.nextLink"] ?? $request.url }}',
qs: {
$select:
'={{ !!$response.body?.["@odata.nextLink"] ? undefined : $request.qs?.$select }}',
},
},
},
},
},
},
type: 'boolean',
},
{
displayName: 'Limit',
name: 'limit',
default: 50,
description: 'Max number of results to return',
displayOptions: {
show: {
returnAll: [false],
},
},
routing: {
send: {
property: '$top',
type: 'query',
value: '={{ $value }}',
},
},
type: 'number',
typeOptions: {
minValue: 1,
},
validateType: 'number',
},
{
displayName: 'Options',
name: 'options',
default: {},
options: [
{
displayName: 'Fields',
name: 'fields',
default: [],
description: 'The fields you want to include in the output',
displayOptions: {
hide: {
'/simplify': [true],
},
},
options: [
{
name: 'Content Type',
value: 'contentType',
},
{
name: 'Created At',
value: 'createdDateTime',
},
{
name: 'Created By',
value: 'createdBy',
},
{
name: 'Fields',
value: 'fields',
},
{
name: 'ID',
value: 'id',
},
{
name: 'Last Modified At',
value: 'lastModifiedDateTime',
},
{
name: 'Last Modified By',
value: 'lastModifiedBy',
},
{
name: 'Parent Reference',
value: 'parentReference',
},
{
name: 'Web URL',
value: 'webUrl',
},
],
routing: {
send: {
preSend: [itemGetAllFieldsPreSend],
},
},
type: 'multiOptions',
},
],
placeholder: 'Add option',
type: 'collection',
},
{
displayName: 'Simplify',
name: 'simplify',
default: true,
routing: {
send: {
preSend: [
async function (
this: IExecuteSingleFunctions,
requestOptions: IHttpRequestOptions,
): Promise<IHttpRequestOptions> {
const simplify = this.getNodeParameter('simplify', false) as boolean;
if (simplify) {
requestOptions.qs ??= {};
requestOptions.qs.$select = 'id,createdDateTime,lastModifiedDateTime,webUrl';
requestOptions.qs.$expand = 'fields(select=Title)';
}
return requestOptions;
},
],
},
},
type: 'boolean',
},
];
const displayOptions = {
show: {
resource: ['item'],
operation: ['getAll'],
},
};
export const description = updateDisplayOptions(displayOptions, properties);

View File

@@ -0,0 +1,77 @@
import { updateDisplayOptions, type INodeProperties } from 'n8n-workflow';
import { itemColumnsPreSend } from '../../helpers/utils';
import { listRLC, siteRLC, untilListSelected, untilSiteSelected } from '../common.descriptions';
const properties: INodeProperties[] = [
{
...siteRLC,
description: 'Select the site to retrieve lists from',
},
{
...listRLC,
description: 'Select the list you want to update an item in',
displayOptions: {
hide: {
...untilSiteSelected,
},
},
},
{
displayName:
'Due to API restrictions, the following column types cannot be updated: Hyperlink, Location, Metadata',
name: 'noticeUnsupportedFields',
displayOptions: {
hide: {
...untilSiteSelected,
...untilListSelected,
},
},
type: 'notice',
default: '',
},
{
displayName: 'Columns',
name: 'columns',
default: {
mappingMode: 'defineBelow',
value: null,
},
displayOptions: {
hide: {
...untilSiteSelected,
...untilListSelected,
},
},
noDataExpression: true,
required: true,
routing: {
send: {
preSend: [itemColumnsPreSend],
},
},
type: 'resourceMapper',
typeOptions: {
loadOptionsDependsOn: ['site.value', 'list.value'],
resourceMapper: {
resourceMapperMethod: 'getMappingColumns',
mode: 'update',
fieldWords: {
singular: 'column',
plural: 'columns',
},
addAllFields: true,
multiKeyMatch: false,
},
},
},
];
const displayOptions = {
show: {
resource: ['item'],
operation: ['update'],
},
};
export const description = updateDisplayOptions(displayOptions, properties);

View File

@@ -0,0 +1,77 @@
import { updateDisplayOptions, type INodeProperties } from 'n8n-workflow';
import { itemColumnsPreSend } from '../../helpers/utils';
import { listRLC, siteRLC, untilListSelected, untilSiteSelected } from '../common.descriptions';
const properties: INodeProperties[] = [
{
...siteRLC,
description: 'Select the site to retrieve lists from',
},
{
...listRLC,
description: 'Select the list you want to create or update an item in',
displayOptions: {
hide: {
...untilSiteSelected,
},
},
},
{
displayName:
'Due to API restrictions, the following column types cannot be updated: Hyperlink, Location, Metadata',
name: 'noticeUnsupportedFields',
displayOptions: {
hide: {
...untilSiteSelected,
...untilListSelected,
},
},
type: 'notice',
default: '',
},
{
displayName: 'Columns',
name: 'columns',
default: {
mappingMode: 'defineBelow',
value: null,
},
displayOptions: {
hide: {
...untilSiteSelected,
...untilListSelected,
},
},
noDataExpression: true,
required: true,
routing: {
send: {
preSend: [itemColumnsPreSend],
},
},
type: 'resourceMapper',
typeOptions: {
loadOptionsDependsOn: ['site.value', 'list.value'],
resourceMapper: {
resourceMapperMethod: 'getMappingColumns',
mode: 'upsert',
fieldWords: {
singular: 'column',
plural: 'columns',
},
addAllFields: true,
multiKeyMatch: false,
},
},
},
];
const displayOptions = {
show: {
resource: ['item'],
operation: ['upsert'],
},
};
export const description = updateDisplayOptions(displayOptions, properties);

View File

@@ -0,0 +1,65 @@
import type { INodeProperties } from 'n8n-workflow';
import * as get from './get.operation';
import * as getAll from './getAll.operation';
import { handleErrorPostReceive, simplifyListPostReceive } from '../../helpers/utils';
export const description: INodeProperties[] = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['list'],
},
},
options: [
{
name: 'Get',
value: 'get',
description: 'Retrieve details of a single list',
routing: {
request: {
ignoreHttpStatusErrors: true,
method: 'GET',
url: '=/sites/{{ $parameter["site"] }}/lists/{{ $parameter["list"] }}',
},
output: {
postReceive: [handleErrorPostReceive, simplifyListPostReceive],
},
},
action: 'Get list',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Retrieve a list of',
routing: {
request: {
method: 'GET',
url: '=/sites/{{ $parameter["site"] }}/lists',
},
output: {
postReceive: [
handleErrorPostReceive,
{
type: 'rootProperty',
properties: {
property: 'value',
},
},
simplifyListPostReceive,
],
},
},
action: 'Get many lists',
},
],
default: 'getAll',
},
...get.description,
...getAll.description,
];

View File

@@ -0,0 +1,42 @@
import { updateDisplayOptions, type INodeProperties } from 'n8n-workflow';
import { listRLC, siteRLC, untilSiteSelected } from '../common.descriptions';
const properties: INodeProperties[] = [
{
...siteRLC,
description: 'Select the site to retrieve lists from',
},
{
...listRLC,
description: 'Select the list you want to retrieve',
displayOptions: {
hide: {
...untilSiteSelected,
},
},
},
{
displayName: 'Simplify',
name: 'simplify',
default: true,
routing: {
send: {
property: '$select',
type: 'query',
value:
'={{ $value ? "id,name,displayName,description,createdDateTime,lastModifiedDateTime,webUrl" : undefined }}',
},
},
type: 'boolean',
},
];
const displayOptions = {
show: {
resource: ['list'],
operation: ['get'],
},
};
export const description = updateDisplayOptions(displayOptions, properties);

View File

@@ -0,0 +1,83 @@
import { updateDisplayOptions, type INodeProperties } from 'n8n-workflow';
import { siteRLC } from '../common.descriptions';
const properties: INodeProperties[] = [
{
...siteRLC,
description: 'Select the site to retrieve lists from',
},
{
displayName: 'Return All',
name: 'returnAll',
default: false,
description: 'Whether to return all results or only up to a given limit',
routing: {
send: {
paginate: '={{ $value }}',
},
operations: {
pagination: {
type: 'generic',
properties: {
continue: '={{ !!$response.body?.["@odata.nextLink"] }}',
request: {
url: '={{ $response.body?.["@odata.nextLink"] ?? $request.url }}',
qs: {
$select:
'={{ !!$response.body?.["@odata.nextLink"] ? undefined : $request.qs?.$select }}',
},
},
},
},
},
},
type: 'boolean',
},
{
displayName: 'Limit',
name: 'limit',
default: 50,
description: 'Max number of results to return',
displayOptions: {
show: {
returnAll: [false],
},
},
routing: {
send: {
property: '$top',
type: 'query',
value: '={{ $value }}',
},
},
type: 'number',
typeOptions: {
minValue: 1,
},
validateType: 'number',
},
{
displayName: 'Simplify',
name: 'simplify',
default: true,
routing: {
send: {
property: '$select',
type: 'query',
value:
'={{ $value ? "id,name,displayName,description,createdDateTime,lastModifiedDateTime,webUrl" : undefined }}',
},
},
type: 'boolean',
},
];
const displayOptions = {
show: {
resource: ['list'],
operation: ['getAll'],
},
};
export const description = updateDisplayOptions(displayOptions, properties);

View File

@@ -0,0 +1,46 @@
import type { IDataObject } from 'n8n-workflow';
export interface IListColumnType {
id: string;
hidden: boolean;
name: string;
displayName: string;
readOnly: boolean;
required: boolean;
type: string;
enforceUniqueValues: boolean;
choice?: {
choices: string[];
};
}
export interface IDriveItem {
id: string;
name: string;
file?: IDataObject;
folder?: IDataObject;
}
export interface IListItem {
id: string;
fields: {
Title: string;
};
}
export interface IList {
id: string;
displayName: string;
}
export interface ISite {
id: string;
title: string;
}
export interface IErrorResponse {
error: {
code: string;
message: string;
};
}

View File

@@ -0,0 +1,277 @@
import type {
IDataObject,
IExecuteSingleFunctions,
IHttpRequestOptions,
IN8nHttpFullResponse,
INodeExecutionData,
JsonObject,
ResourceMapperValue,
} from 'n8n-workflow';
import { jsonParse, NodeApiError, NodeOperationError } from 'n8n-workflow';
import type { IErrorResponse } from './interfaces';
import { microsoftSharePointApiRequest } from '../transport';
export async function simplifyItemPostReceive(
this: IExecuteSingleFunctions,
items: INodeExecutionData[],
_response: IN8nHttpFullResponse,
): Promise<INodeExecutionData[]> {
if (items.length === 0) {
return items;
}
const simplify = this.getNodeParameter('simplify') as boolean;
if (simplify) {
for (const item of items) {
delete item.json['@odata.context'];
delete item.json['@odata.etag'];
delete item.json['fields@odata.navigationLink'];
delete (item.json.fields as IDataObject)?.['@odata.etag'];
}
}
return items;
}
export async function simplifyListPostReceive(
this: IExecuteSingleFunctions,
items: INodeExecutionData[],
_response: IN8nHttpFullResponse,
): Promise<INodeExecutionData[]> {
if (items.length === 0) {
return items;
}
const simplify = this.getNodeParameter('simplify') as boolean;
if (simplify) {
for (const item of items) {
delete item.json['@odata.context'];
delete item.json['@odata.etag'];
}
}
return items;
}
export async function downloadFilePostReceive(
this: IExecuteSingleFunctions,
_items: INodeExecutionData[],
response: IN8nHttpFullResponse,
): Promise<INodeExecutionData[]> {
let fileName: string | undefined;
if (response.headers['content-disposition']) {
let fileNameMatch = /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(
response.headers['content-disposition'] as string,
);
fileName =
fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined;
if (fileName) {
fileName = decodeURIComponent(fileName);
} else {
fileNameMatch = /filename="?([^"]*?)"?(;|$)/g.exec(
response.headers['content-disposition'] as string,
);
fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined;
}
}
const newItem: INodeExecutionData = {
json: {},
binary: {
data: await this.helpers.prepareBinaryData(
response.body as Buffer,
fileName,
response.headers['content-type'] as string,
),
},
};
return [newItem];
}
export async function uploadFilePreSend(
this: IExecuteSingleFunctions,
requestOptions: IHttpRequestOptions,
): Promise<IHttpRequestOptions> {
const binaryProperty = this.getNodeParameter('fileContents') as string;
this.helpers.assertBinaryData(binaryProperty);
const binaryDataBuffer = await this.helpers.getBinaryDataBuffer(binaryProperty);
requestOptions.body = binaryDataBuffer;
return requestOptions;
}
export async function itemGetAllFieldsPreSend(
this: IExecuteSingleFunctions,
requestOptions: IHttpRequestOptions,
): Promise<IHttpRequestOptions> {
const fields = this.getNodeParameter('options.fields') as string[];
requestOptions.qs ??= {};
if (fields.some((x) => x === 'fields')) {
requestOptions.qs.$expand = 'fields';
}
requestOptions.qs.$select = fields.map((x) => x);
return requestOptions;
}
export async function itemColumnsPreSend(
this: IExecuteSingleFunctions,
requestOptions: IHttpRequestOptions,
): Promise<IHttpRequestOptions> {
const mapperValue = this.getNodeParameter('columns') as ResourceMapperValue;
const operation = this.getNodeParameter('operation') as string;
if (['upsert', 'update'].includes(operation) && mapperValue.matchingColumns?.length > 0) {
if (!mapperValue.matchingColumns.includes('id')) {
const site = this.getNodeParameter('site', undefined, { extractValue: true }) as string;
const list = this.getNodeParameter('list', undefined, { extractValue: true }) as string;
const response = await microsoftSharePointApiRequest.call(
this,
'GET',
`/sites/${site}/lists/${list}/items`,
{},
{
$filter: mapperValue.matchingColumns
.map((x) => `fields/${x} eq '${mapperValue.value![x]}'`)
.join(' and'),
},
{
Prefer: 'HonorNonIndexedQueriesWarningMayFailRandomly',
},
);
if (response.value?.length === 1) {
mapperValue.matchingColumns.push('id');
mapperValue.value ??= {};
mapperValue.value.id = response.value[0].id;
}
}
if (operation === 'upsert') {
if (mapperValue.matchingColumns.includes('id')) {
if (!mapperValue.value?.id) {
throw new NodeOperationError(
this.getNode(),
"The column(s) don't match any existing item",
{
description: 'Double-check the value(s) for the columns to match and try again',
},
);
}
requestOptions.url += '/' + mapperValue.value.id;
delete mapperValue.value.id;
requestOptions.method = 'PATCH';
}
} else if (operation === 'update') {
if (mapperValue.matchingColumns.includes('id') && mapperValue.value?.id) {
requestOptions.url += '/' + mapperValue.value.id;
delete mapperValue.value.id;
} else {
throw new NodeOperationError(
this.getNode(),
"The column(s) don't match any existing item",
{
description: 'Double-check the value(s) for the columns to match and try again',
},
);
}
}
}
const fields = {} as IDataObject;
for (const [key, value] of Object.entries(mapperValue.value ?? {})) {
if (mapperValue.schema.find((x) => x.id === key)?.type === 'url') {
fields[key] = {
Description: value,
Url: value,
};
} else {
fields[key] = value;
}
}
requestOptions.body ??= {};
(requestOptions.body as IDataObject).fields = fields;
return requestOptions;
}
export async function handleErrorPostReceive(
this: IExecuteSingleFunctions,
data: INodeExecutionData[],
response: IN8nHttpFullResponse,
): Promise<INodeExecutionData[]> {
if (String(response.statusCode).startsWith('4') || String(response.statusCode).startsWith('5')) {
const resource = this.getNodeParameter('resource') as string;
const operation = this.getNodeParameter('operation') as string;
if (resource === 'file' && operation === 'download' && Buffer.isBuffer(response.body)) {
response.body = jsonParse((response.body as Buffer).toString());
}
const error = (response.body as IErrorResponse)?.error ?? {};
if (resource === 'file') {
if (operation === 'download') {
} else if (operation === 'update') {
} else if (operation === 'upload') {
}
} else if (resource === 'item') {
if (operation === 'create') {
if (error.code === 'invalidRequest') {
if (
error.message ===
'One or more fields with unique constraints already has the provided value.'
) {
throw new NodeApiError(this.getNode(), response as unknown as JsonObject, {
message: 'One or more fields with unique constraints already has the provided value',
description: "Double-check the value(s) in 'Values to Send' and try again",
});
} else {
throw new NodeApiError(this.getNode(), response as unknown as JsonObject, {
message: error.message,
description: "Double-check the value(s) in 'Values to Send' and try again",
});
}
}
} else if (operation === 'delete') {
} else if (operation === 'get') {
} else if (operation === 'getAll') {
} else if (operation === 'update') {
if (error.code === 'invalidRequest') {
throw new NodeApiError(this.getNode(), response as unknown as JsonObject, {
message: error.message,
description: "Double-check the value(s) in 'Values to Update' and try again",
});
}
} else if (operation === 'upsert') {
if (error.code === 'invalidRequest') {
throw new NodeApiError(this.getNode(), response as unknown as JsonObject, {
message: error.message,
description: "Double-check the value(s) in 'Values to Send' and try again",
});
}
}
} else if (resource === 'list') {
if (operation === 'get') {
} else if (operation === 'getAll') {
}
}
if (error.code === 'itemNotFound') {
if (error.message.includes('list item')) {
throw new NodeApiError(this.getNode(), response as unknown as JsonObject, {
message: "The required item doesn't match any existing one",
description: "Double-check the value in the parameter 'Item' and try again",
});
} else if (error.message.includes('list')) {
throw new NodeApiError(this.getNode(), response as unknown as JsonObject, {
message: "The required list doesn't match any existing one",
description: "Double-check the value in the parameter 'List' and try again",
});
}
}
throw new NodeApiError(this.getNode(), response as unknown as JsonObject);
}
return data;
}

View File

@@ -0,0 +1,2 @@
export * as listSearch from './listSearch';
export * as resourceMapping from './resourceMapping';

View File

@@ -0,0 +1,252 @@
import type {
IDataObject,
ILoadOptionsFunctions,
INodeListSearchItems,
INodeListSearchResult,
} from 'n8n-workflow';
import type { IDriveItem, IList, IListItem, ISite } from '../helpers/interfaces';
import { microsoftSharePointApiRequest } from '../transport';
export async function getFiles(
this: ILoadOptionsFunctions,
filter?: string,
paginationToken?: string,
): Promise<INodeListSearchResult> {
const site = this.getNodeParameter('site', undefined, { extractValue: true }) as string;
const folder = this.getNodeParameter('folder', undefined, { extractValue: true }) as string;
let response: any;
if (paginationToken) {
response = await microsoftSharePointApiRequest.call(
this,
'GET',
`/sites/${site}/drive/items/${folder}/children`,
{},
undefined,
undefined,
paginationToken,
);
} else {
// File filter not supported
// https://learn.microsoft.com/en-us/onedrive/developer/rest-api/concepts/filtering-results?view=odsp-graph-online#filterable-properties
const qs: IDataObject = {
$select: 'id,name,file',
};
if (filter) {
qs.$filter = `name eq '${filter}'`;
}
response = await microsoftSharePointApiRequest.call(
this,
'GET',
`/sites/${site}/drive/items/${folder}/children`,
{},
qs,
);
}
const items: IDriveItem[] = response.value;
const results: INodeListSearchItems[] = items
.filter((x) => x.file)
.map((g) => ({
name: g.name,
value: g.id,
}))
.sort((a, b) =>
a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }),
);
return { results, paginationToken: response['@odata.nextLink'] };
}
export async function getFolders(
this: ILoadOptionsFunctions,
filter?: string,
paginationToken?: string,
): Promise<INodeListSearchResult> {
const site = this.getNodeParameter('site', undefined, { extractValue: true }) as string;
let response: any;
if (paginationToken) {
response = await microsoftSharePointApiRequest.call(
this,
'GET',
`/sites/${site}/drive/items`,
{},
undefined,
undefined,
paginationToken,
);
} else {
const qs: IDataObject = {
$select: 'id,name,folder',
// Folder filter not supported, but filter is still required
// https://learn.microsoft.com/en-us/onedrive/developer/rest-api/concepts/filtering-results?view=odsp-graph-online#filterable-properties
$filter: 'folder ne null',
};
if (filter) {
qs.$filter = `name eq '${filter}'`;
}
response = await microsoftSharePointApiRequest.call(
this,
'GET',
`/sites/${site}/drive/items`,
{},
qs,
);
}
const items: IDriveItem[] = response.value;
const results: INodeListSearchItems[] = items
.filter((x) => x.folder)
.map((g) => ({
name: g.name,
value: g.id,
}))
.sort((a, b) =>
a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }),
);
return { results, paginationToken: response['@odata.nextLink'] };
}
export async function getItems(
this: ILoadOptionsFunctions,
filter?: string,
paginationToken?: string,
): Promise<INodeListSearchResult> {
const site = this.getNodeParameter('site', undefined, { extractValue: true }) as string;
const list = this.getNodeParameter('list', undefined, { extractValue: true }) as string;
let response: any;
if (paginationToken) {
response = await microsoftSharePointApiRequest.call(
this,
'GET',
`/sites/${site}/lists/${list}/items`,
{},
undefined,
undefined,
paginationToken,
);
} else {
const qs: IDataObject = {
$expand: 'fields(select=Title)',
$select: 'id,fields',
};
if (filter) {
qs.$filter = `fields/Title eq '${filter}'`;
}
response = await microsoftSharePointApiRequest.call(
this,
'GET',
`/sites/${site}/lists/${list}/items`,
{},
qs,
);
}
const items: IListItem[] = response.value;
const results: INodeListSearchItems[] = items
.map((g) => ({
name: g.fields.Title ?? g.id,
value: g.id,
}))
.sort((a, b) =>
a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }),
);
return { results, paginationToken: response['@odata.nextLink'] };
}
export async function getLists(
this: ILoadOptionsFunctions,
filter?: string,
paginationToken?: string,
): Promise<INodeListSearchResult> {
const site = this.getNodeParameter('site', undefined, { extractValue: true }) as string;
let response: any;
if (paginationToken) {
response = await microsoftSharePointApiRequest.call(
this,
'GET',
`/sites/${site}/lists`,
{},
undefined,
undefined,
paginationToken,
);
} else {
const qs: IDataObject = {
$select: 'id,displayName',
};
if (filter) {
qs.$filter = `displayName eq '${filter}'`;
}
response = await microsoftSharePointApiRequest.call(
this,
'GET',
`/sites/${site}/lists`,
{},
qs,
);
}
const lists: IList[] = response.value;
const results: INodeListSearchItems[] = lists
.map((g) => ({
name: g.displayName,
value: g.id,
}))
.sort((a, b) =>
a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }),
);
return { results, paginationToken: response['@odata.nextLink'] };
}
export async function getSites(
this: ILoadOptionsFunctions,
filter?: string,
paginationToken?: string,
): Promise<INodeListSearchResult> {
let response: any;
if (paginationToken) {
response = await microsoftSharePointApiRequest.call(
this,
'GET',
'/sites',
{},
undefined,
undefined,
paginationToken,
);
} else {
const qs: IDataObject = {
$select: 'id,title',
$search: '*',
};
if (filter) {
qs.$search = filter;
}
response = await microsoftSharePointApiRequest.call(this, 'GET', '/sites', {}, qs);
}
const sites: ISite[] = response.value;
const results: INodeListSearchItems[] = sites
.map((g) => ({
name: g.title,
value: g.id,
}))
.sort((a, b) =>
a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }),
);
return { results, paginationToken: response['@odata.nextLink'] };
}

View File

@@ -0,0 +1,95 @@
import type {
FieldType,
ILoadOptionsFunctions,
ResourceMapperField,
ResourceMapperFields,
} from 'n8n-workflow';
import type { IListColumnType } from '../helpers/interfaces';
import { microsoftSharePointApiRequest } from '../transport';
const unsupportedFields = ['geoLocation', 'location', 'term', 'url'];
const fieldTypeMapping: Partial<Record<FieldType, string[]>> = {
string: ['text', 'user', 'lookup'],
// unknownFutureValue: rating
number: ['number', 'currency', 'unknownFutureValue'],
boolean: ['boolean'],
dateTime: ['dateTime'],
object: ['thumbnail'],
options: ['choice'],
};
function mapType(column: IListColumnType): FieldType | undefined {
if (unsupportedFields.includes(column.type)) {
return undefined;
}
let mappedType: FieldType = 'string';
for (const t of Object.keys(fieldTypeMapping)) {
const postgresTypes = fieldTypeMapping[t as FieldType];
if (postgresTypes?.includes(column.type)) {
mappedType = t as FieldType;
}
}
return mappedType;
}
export async function getMappingColumns(
this: ILoadOptionsFunctions,
): Promise<ResourceMapperFields> {
const site = this.getNodeParameter('site', undefined, { extractValue: true }) as string;
const list = this.getNodeParameter('list', undefined, { extractValue: true }) as string;
const operation = this.getNodeParameter('operation') as string;
const response = await microsoftSharePointApiRequest.call(
this,
'GET',
`/sites/${site}/lists/${list}/contentTypes`,
{},
{ expand: 'columns' },
);
const columns: IListColumnType[] = response.value[0].columns;
const fields: ResourceMapperField[] = [];
for (const column of columns.filter((x) => !x.hidden && !x.readOnly)) {
const fieldType = mapType(column);
const field = {
id: column.name,
canBeUsedToMatch: column.enforceUniqueValues && column.required,
defaultMatch: false,
display: true,
displayName: column.displayName,
readOnly: column.readOnly || !fieldType,
required: column.required,
type: fieldType,
} as ResourceMapperField;
if (field.type === 'options') {
field.options = [];
if (Array.isArray(column.choice?.choices)) {
for (const choice of column.choice.choices) {
field.options.push({
name: choice,
value: choice,
});
}
}
}
fields.push(field);
}
if (operation === 'update') {
fields.push({
id: 'id',
canBeUsedToMatch: true,
defaultMatch: false,
display: true,
displayName: 'ID',
readOnly: true,
required: true,
type: 'string',
});
}
return { fields };
}

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -0,0 +1,27 @@
export const credentials = {
microsoftSharePointOAuth2Api: {
grantType: 'authorizationCode',
authUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
accessTokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
clientId: 'CLIENT_ID',
clientSecret: 'CLIENT_SECRET',
scope: 'openid offline_access https://mydomain.sharepoint.com/.default',
authQueryParameters: 'response_mode=query',
authentication: 'body',
oauthTokenData: {
token_type: 'Bearer',
scope:
'https://mydomain.sharepoint.com/Sites.Manage.All https://mydomain.sharepoint.com/Sites.Read.All https://mydomain.sharepoint.com/Sites.ReadWrite.All https://mydomain.sharepoint.com/Sites.Selected https://mydomain.sharepoint.com/User.Read https://mydomain.sharepoint.com/.default',
expires_in: 4763,
ext_expires_in: 4763,
access_token: 'ACCESSTOKEN',
refresh_token: 'REFRESHTOKEN',
id_token: 'IDTOKEN',
callbackQueryString: {
session_state: 'SESSIONSTATE',
},
},
subdomain: 'mydomain',
baseUrl: 'https://mydomain.sharepoint.com/_api/v2.0',
},
};

View File

@@ -0,0 +1,36 @@
import { CredentialsHelper } from '@nodes-testing/credentials-helper';
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Microsoft SharePoint Node', () => {
const { baseUrl } = credentials.microsoftSharePointOAuth2Api;
jest.spyOn(CredentialsHelper.prototype, 'getParentTypes').mockReturnValueOnce(['oAuth2Api']);
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['oauth2.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/sites/site1/lists/list1?%24select=id%2Cname%2CdisplayName%2Cdescription%2CcreatedDateTime%2ClastModifiedDateTime%2CwebUrl',
statusCode: 200,
requestHeaders: { Authorization: 'Bearer ACCESSTOKEN' },
responseBody: {
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#lists/$entity',
'@odata.etag': '"58a279af-1f06-4392-a5ed-2b37fa1d6c1d,5"',
createdDateTime: '2025-03-12T19:38:40Z',
description: 'My List 1',
id: '58a279af-1f06-4392-a5ed-2b37fa1d6c1d',
lastModifiedDateTime: '2025-03-12T22:18:18Z',
name: 'list1',
webUrl: 'https://mydomain.sharepoint.com/sites/site1/Lists/name%20list',
displayName: 'list1',
},
},
],
},
});
});

View File

@@ -0,0 +1,70 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "d8d29d0a-bb31-4094-a252-8008932f5425",
"name": "When clicking Test workflow"
},
{
"parameters": {
"resource": "list",
"operation": "get",
"site": {
"__rl": true,
"value": "site1",
"mode": "list",
"cachedResultName": "site1"
},
"list": {
"__rl": true,
"value": "list1",
"mode": "list",
"cachedResultName": "list1"
},
"requestOptions": {}
},
"type": "n8n-nodes-base.microsoftSharePoint",
"typeVersion": 1,
"position": [200, 0],
"id": "0e19be10-9d94-4654-89e9-432daa8102cb",
"name": "Microsoft SharePoint",
"credentials": {
"microsoftSharePointOAuth2Api": {
"id": "cXXnMCWyk397M5qJ",
"name": "Microsoft SharePoint account"
}
}
}
],
"connections": {
"When clicking Test workflow": {
"main": [
[
{
"node": "Microsoft SharePoint",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {
"Microsoft SharePoint": [
{
"json": {
"createdDateTime": "2025-03-12T19:38:40Z",
"description": "My List 1",
"id": "58a279af-1f06-4392-a5ed-2b37fa1d6c1d",
"lastModifiedDateTime": "2025-03-12T22:18:18Z",
"name": "list1",
"webUrl": "https://mydomain.sharepoint.com/sites/site1/Lists/name%20list",
"displayName": "list1"
}
}
]
}
}

View File

@@ -0,0 +1,28 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Microsoft SharePoint Node', () => {
const { baseUrl } = credentials.microsoftSharePointOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['download.workflow.json'],
assertBinaryData: true,
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/sites/site1/drive/items/item1/content',
statusCode: 200,
responseBody: {},
responseHeaders: {
'content-type': 'application/json',
'content-disposition':
"attachment; filename*=UTF-8''weird%20file%20%E2%82%AC%20name.json",
},
},
],
},
});
});

View File

@@ -0,0 +1,76 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "37ab6212-d506-4b53-b63e-14b6a2a05907",
"name": "When clicking Test workflow"
},
{
"parameters": {
"site": {
"__rl": true,
"value": "site1",
"mode": "list",
"cachedResultName": "site1"
},
"folder": {
"__rl": true,
"value": "folder1",
"mode": "list",
"cachedResultName": "folder1"
},
"file": {
"__rl": true,
"value": "item1",
"mode": "list",
"cachedResultName": "file.json"
},
"requestOptions": {}
},
"type": "n8n-nodes-base.microsoftSharePoint",
"typeVersion": 1,
"position": [220, 0],
"id": "f9037af8-4f52-4f9f-b8ae-de860f890792",
"name": "Microsoft SharePoint",
"credentials": {
"microsoftSharePointOAuth2Api": {
"id": "cXXnMCWyk397M5qJ",
"name": "Microsoft SharePoint account"
}
}
}
],
"connections": {
"When clicking Test workflow": {
"main": [
[
{
"node": "Microsoft SharePoint",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {
"Microsoft SharePoint": [
{
"binary": {
"data": {
"data": "e30=",
"fileExtension": "json",
"fileSize": "2 B",
"fileType": "json",
"mimeType": "application/json",
"fileName": "weird file € name.json"
}
},
"json": {}
}
]
}
}

View File

@@ -0,0 +1,148 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Microsoft SharePoint Node', () => {
const { baseUrl } = credentials.microsoftSharePointOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['update.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'patch',
path: '/sites/site1/drive/items/item1',
statusCode: 200,
responseBody: {
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#items/$entity',
'@content.downloadUrl':
'https://mydomain.sharepoint.com/sites/site1/_layouts/15/download.aspx?UniqueId=d86f89ab-378e-43bc-8d46-18d2f52bd603',
createdBy: {
application: {
id: 'b9c26603-3c9b-4050-b848-27dfab0a52fa',
displayName: 'sharepoint-n8n-test',
},
user: {
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
displayName: 'John Doe',
},
},
createdDateTime: '2025-03-13T19:23:53Z',
eTag: '"{D86F89AB-378E-43BC-8D46-18D2F52BD603},3"',
id: '01SPEVVYFLRFX5RDRXXRBY2RQY2L2SXVQD',
lastModifiedBy: {
application: {
id: 'b9c26603-3c9b-4050-b848-27dfab0a52fa',
displayName: 'sharepoint-n8n-test',
},
user: {
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
displayName: 'John Doe',
},
},
lastModifiedDateTime: '2025-03-24T19:48:25Z',
name: 'file2.json',
parentReference: {
driveType: 'documentLibrary',
driveId: 'b!HXyh83lynUOhdUenWLZcmP1mvjoj7J9Gq8YzLjqVv3W_vPrVy_93T7lzoXbjRjzK',
id: '01SPEVVYBKV2ZKHGJASRA2HC7MOGBMUMAA',
name: 'folder1',
path: '/drive/root:/folder1',
siteId: 'f3a17c1d-7279-439d-a175-47a758b65c98',
},
webUrl:
'https://mydomain.sharepoint.com/sites/site1/Shared%20Documents/folder1/file2.json',
cTag: '"c:{D86F89AB-378E-43BC-8D46-18D2F52BD603},2"',
file: {
hashes: {
quickXorHash: 'jY7BcIP9Th3EZ4PMCLrv4DnQTY4=',
},
irmEffectivelyEnabled: false,
irmEnabled: false,
mimeType: 'application/json',
},
fileSystemInfo: {
createdDateTime: '2025-03-13T19:23:53Z',
lastModifiedDateTime: '2025-03-24T19:48:25Z',
},
shared: {
effectiveRoles: ['write'],
scope: 'users',
},
size: 37,
},
},
{
method: 'put',
path: '/sites/site1/drive/items/item1/content',
statusCode: 200,
responseBody: {
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#items/$entity',
'@content.downloadUrl':
'https://mydomain.sharepoint.com/sites/site1/_layouts/15/download.aspx?UniqueId=d86f89ab-378e-43bc-8d46-18d2f52bd603',
createdBy: {
application: {
id: 'b9c26603-3c9b-4050-b848-27dfab0a52fa',
displayName: 'sharepoint-n8n-test',
},
user: {
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
displayName: 'John Doe',
},
},
createdDateTime: '2025-03-13T19:23:53Z',
eTag: '"{D86F89AB-378E-43BC-8D46-18D2F52BD603},3"',
id: '01SPEVVYFLRFX5RDRXXRBY2RQY2L2SXVQD',
lastModifiedBy: {
application: {
id: 'b9c26603-3c9b-4050-b848-27dfab0a52fa',
displayName: 'sharepoint-n8n-test',
},
user: {
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
displayName: 'John Doe',
},
},
lastModifiedDateTime: '2025-03-24T19:48:35Z',
name: 'file2.json',
parentReference: {
driveType: 'documentLibrary',
driveId: 'b!HXyh83lynUOhdUenWLZcmP1mvjoj7J9Gq8YzLjqVv3W_vPrVy_93T7lzoXbjRjzK',
id: '01SPEVVYBKV2ZKHGJASRA2HC7MOGBMUMAA',
name: 'folder1',
path: '/drive/root:/folder1',
siteId: 'f3a17c1d-7279-439d-a175-47a758b65c98',
},
webUrl:
'https://mydomain.sharepoint.com/sites/site1/Shared%20Documents/folder1/file2.json',
cTag: '"c:{D86F89AB-378E-43BC-8D46-18D2F52BD603},2"',
file: {
hashes: {
quickXorHash: 'jY7BcIP9Th3EZ4PMCLrv4DnQTY4=',
},
irmEffectivelyEnabled: false,
irmEnabled: false,
mimeType: 'application/json',
},
fileSystemInfo: {
createdDateTime: '2025-03-13T19:23:53Z',
lastModifiedDateTime: '2025-03-24T19:48:25Z',
},
shared: {
effectiveRoles: ['write'],
scope: 'users',
},
size: 37,
},
},
],
},
});
});

View File

@@ -0,0 +1,175 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "37ab6212-d506-4b53-b63e-14b6a2a05907",
"name": "When clicking Test workflow"
},
{
"parameters": {
"operation": "update",
"site": {
"__rl": true,
"value": "site1",
"mode": "list",
"cachedResultName": "site1"
},
"folder": {
"__rl": true,
"value": "folder1",
"mode": "list",
"cachedResultName": "folder1"
},
"file": {
"__rl": true,
"value": "item1",
"mode": "list",
"cachedResultName": "file1.json"
},
"fileName": "file2.json",
"changeFileContent": true,
"fileContents": "data",
"requestOptions": {}
},
"type": "n8n-nodes-base.microsoftSharePoint",
"typeVersion": 1,
"position": [660, 0],
"id": "f9037af8-4f52-4f9f-b8ae-de860f890792",
"name": "Microsoft SharePoint",
"credentials": {
"microsoftSharePointOAuth2Api": {
"id": "cXXnMCWyk397M5qJ",
"name": "Microsoft SharePoint account"
}
}
},
{
"parameters": {
"mode": "jsonToBinary",
"convertAllData": false,
"options": {
"useRawData": true
}
},
"name": "Move Binary Data",
"type": "n8n-nodes-base.moveBinaryData",
"typeVersion": 1,
"position": [440, 0],
"id": "9cba2be3-50e0-4ae2-b7a6-2f0caefb50ef"
},
{
"parameters": {
"mode": "raw",
"jsonOutput": "{\n \"data\": {\n \"my_field_1\": \"value\",\n \"my_field_2\": 1\n }\n}\n",
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [220, 0],
"id": "fdafc0d5-58dd-4f9e-a76b-0a3cb0e9a794",
"name": "Edit Fields"
}
],
"connections": {
"When clicking Test workflow": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Move Binary Data": {
"main": [
[
{
"node": "Microsoft SharePoint",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields": {
"main": [
[
{
"node": "Move Binary Data",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {
"Microsoft SharePoint": [
{
"json": {
"@content.downloadUrl": "https://mydomain.sharepoint.com/sites/site1/_layouts/15/download.aspx?UniqueId=d86f89ab-378e-43bc-8d46-18d2f52bd603",
"@odata.context": "https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#items/$entity",
"cTag": "\"c:{D86F89AB-378E-43BC-8D46-18D2F52BD603},2\"",
"createdBy": {
"application": {
"displayName": "sharepoint-n8n-test",
"id": "b9c26603-3c9b-4050-b848-27dfab0a52fa"
},
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"createdDateTime": "2025-03-13T19:23:53Z",
"eTag": "\"{D86F89AB-378E-43BC-8D46-18D2F52BD603},3\"",
"file": {
"hashes": {
"quickXorHash": "jY7BcIP9Th3EZ4PMCLrv4DnQTY4="
},
"irmEffectivelyEnabled": false,
"irmEnabled": false,
"mimeType": "application/json"
},
"fileSystemInfo": {
"createdDateTime": "2025-03-13T19:23:53Z",
"lastModifiedDateTime": "2025-03-24T19:48:25Z"
},
"id": "01SPEVVYFLRFX5RDRXXRBY2RQY2L2SXVQD",
"lastModifiedBy": {
"application": {
"displayName": "sharepoint-n8n-test",
"id": "b9c26603-3c9b-4050-b848-27dfab0a52fa"
},
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"lastModifiedDateTime": "2025-03-24T19:48:35Z",
"name": "file2.json",
"parentReference": {
"driveId": "b!HXyh83lynUOhdUenWLZcmP1mvjoj7J9Gq8YzLjqVv3W_vPrVy_93T7lzoXbjRjzK",
"driveType": "documentLibrary",
"id": "01SPEVVYBKV2ZKHGJASRA2HC7MOGBMUMAA",
"name": "folder1",
"path": "/drive/root:/folder1",
"siteId": "f3a17c1d-7279-439d-a175-47a758b65c98"
},
"shared": {
"effectiveRoles": ["write"],
"scope": "users"
},
"size": 37,
"webUrl": "https://mydomain.sharepoint.com/sites/site1/Shared%20Documents/folder1/file2.json"
}
}
]
}
}

View File

@@ -0,0 +1,82 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Microsoft SharePoint Node', () => {
const { baseUrl } = credentials.microsoftSharePointOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['upload.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'put',
path: '/sites/site1/drive/items/folder1:/file1.json:/content',
statusCode: 201,
responseBody: {
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#items/$entity',
'@content.downloadUrl':
'https://mydomain.sharepoint.com/sites/site1/_layouts/15/download.aspx?UniqueId=d86f89ab-378e-43bc-8d46-18d2f52bd603',
createdBy: {
application: {
id: 'b9c26603-3c9b-4050-b848-27dfab0a52fa',
displayName: 'sharepoint-n8n-test',
},
user: {
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
displayName: 'John Doe',
},
},
createdDateTime: '2025-03-13T19:23:53Z',
eTag: '"{D86F89AB-378E-43BC-8D46-18D2F52BD603},3"',
id: '01SPEVVYFLRFX5RDRXXRBY2RQY2L2SXVQD',
lastModifiedBy: {
application: {
id: 'b9c26603-3c9b-4050-b848-27dfab0a52fa',
displayName: 'sharepoint-n8n-test',
},
user: {
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
displayName: 'John Doe',
},
},
lastModifiedDateTime: '2025-03-24T19:48:25Z',
name: 'file2.json',
parentReference: {
driveType: 'documentLibrary',
driveId: 'b!HXyh83lynUOhdUenWLZcmP1mvjoj7J9Gq8YzLjqVv3W_vPrVy_93T7lzoXbjRjzK',
id: '01SPEVVYBKV2ZKHGJASRA2HC7MOGBMUMAA',
name: 'folder1',
path: '/drive/root:/folder1',
siteId: 'f3a17c1d-7279-439d-a175-47a758b65c98',
},
webUrl:
'https://mydomain.sharepoint.com/sites/site1/Shared%20Documents/folder1/file1.json',
cTag: '"c:{D86F89AB-378E-43BC-8D46-18D2F52BD603},2"',
file: {
hashes: {
quickXorHash: 'jY7BcIP9Th3EZ4PMCLrv4DnQTY4=',
},
irmEffectivelyEnabled: false,
irmEnabled: false,
mimeType: 'application/json',
},
fileSystemInfo: {
createdDateTime: '2025-03-13T19:23:53Z',
lastModifiedDateTime: '2025-03-24T19:48:25Z',
},
shared: {
effectiveRoles: ['write'],
scope: 'users',
},
size: 37,
},
},
],
},
});
});

View File

@@ -0,0 +1,168 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "37ab6212-d506-4b53-b63e-14b6a2a05907",
"name": "When clicking Test workflow"
},
{
"parameters": {
"operation": "upload",
"site": {
"__rl": true,
"value": "site1",
"mode": "list",
"cachedResultName": "site1"
},
"folder": {
"__rl": true,
"value": "folder1",
"mode": "list",
"cachedResultName": "folder1"
},
"fileName": "file1.json",
"fileContents": "data",
"requestOptions": {}
},
"type": "n8n-nodes-base.microsoftSharePoint",
"typeVersion": 1,
"position": [660, 0],
"id": "f9037af8-4f52-4f9f-b8ae-de860f890792",
"name": "Microsoft SharePoint",
"credentials": {
"microsoftSharePointOAuth2Api": {
"id": "cXXnMCWyk397M5qJ",
"name": "Microsoft SharePoint account"
}
}
},
{
"parameters": {
"mode": "jsonToBinary",
"convertAllData": false,
"options": {
"useRawData": true
}
},
"name": "Move Binary Data",
"type": "n8n-nodes-base.moveBinaryData",
"typeVersion": 1,
"position": [440, 0],
"id": "9cba2be3-50e0-4ae2-b7a6-2f0caefb50ef"
},
{
"parameters": {
"mode": "raw",
"jsonOutput": "{\n \"data\": {\n \"my_field_1\": \"value\",\n \"my_field_2\": 1\n }\n}\n",
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [220, 0],
"id": "fdafc0d5-58dd-4f9e-a76b-0a3cb0e9a794",
"name": "Edit Fields"
}
],
"connections": {
"When clicking Test workflow": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Move Binary Data": {
"main": [
[
{
"node": "Microsoft SharePoint",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields": {
"main": [
[
{
"node": "Move Binary Data",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {
"Microsoft SharePoint": [
{
"json": {
"@content.downloadUrl": "https://mydomain.sharepoint.com/sites/site1/_layouts/15/download.aspx?UniqueId=d86f89ab-378e-43bc-8d46-18d2f52bd603",
"@odata.context": "https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#items/$entity",
"cTag": "\"c:{D86F89AB-378E-43BC-8D46-18D2F52BD603},2\"",
"createdBy": {
"application": {
"displayName": "sharepoint-n8n-test",
"id": "b9c26603-3c9b-4050-b848-27dfab0a52fa"
},
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"createdDateTime": "2025-03-13T19:23:53Z",
"eTag": "\"{D86F89AB-378E-43BC-8D46-18D2F52BD603},3\"",
"file": {
"hashes": {
"quickXorHash": "jY7BcIP9Th3EZ4PMCLrv4DnQTY4="
},
"irmEffectivelyEnabled": false,
"irmEnabled": false,
"mimeType": "application/json"
},
"fileSystemInfo": {
"createdDateTime": "2025-03-13T19:23:53Z",
"lastModifiedDateTime": "2025-03-24T19:48:25Z"
},
"id": "01SPEVVYFLRFX5RDRXXRBY2RQY2L2SXVQD",
"lastModifiedBy": {
"application": {
"displayName": "sharepoint-n8n-test",
"id": "b9c26603-3c9b-4050-b848-27dfab0a52fa"
},
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"lastModifiedDateTime": "2025-03-24T19:48:25Z",
"name": "file2.json",
"parentReference": {
"driveId": "b!HXyh83lynUOhdUenWLZcmP1mvjoj7J9Gq8YzLjqVv3W_vPrVy_93T7lzoXbjRjzK",
"driveType": "documentLibrary",
"id": "01SPEVVYBKV2ZKHGJASRA2HC7MOGBMUMAA",
"name": "folder1",
"path": "/drive/root:/folder1",
"siteId": "f3a17c1d-7279-439d-a175-47a758b65c98"
},
"shared": {
"effectiveRoles": ["write"],
"scope": "users"
},
"size": 37,
"webUrl": "https://mydomain.sharepoint.com/sites/site1/Shared%20Documents/folder1/file1.json"
}
}
]
}
}

View File

@@ -0,0 +1,54 @@
import type { MockProxy } from 'jest-mock-extended';
import { mock } from 'jest-mock-extended';
import type { IBinaryData, IExecuteSingleFunctions } from 'n8n-workflow';
import { downloadFilePostReceive } from '../../helpers/utils';
describe('Microsoft SharePoint Node', () => {
let executeSingleFunctions: MockProxy<IExecuteSingleFunctions>;
beforeEach(() => {
executeSingleFunctions = mock<IExecuteSingleFunctions>();
});
afterEach(() => {
jest.resetAllMocks();
});
it('should download file post receive', async () => {
const mockResponse = {
body: '',
statusCode: 200,
headers: {
'content-disposition': "attachment; filename*=UTF-8''encoded%20name.pdf",
'content-type': 'application/pdf',
},
};
const mockPrepareBinaryData = jest.fn().mockReturnValueOnce({
data: '',
mimeType: 'application/pdf',
fileName: 'encoded name.pdf',
} as IBinaryData);
executeSingleFunctions.helpers.prepareBinaryData = mockPrepareBinaryData;
const result = await downloadFilePostReceive.call(executeSingleFunctions, [], mockResponse);
expect(mockPrepareBinaryData).toHaveBeenCalledWith(
mockResponse.body,
'encoded name.pdf',
'application/pdf',
);
expect(result).toEqual([
{
json: {},
binary: {
data: {
data: '',
mimeType: 'application/pdf',
fileName: 'encoded name.pdf',
},
},
},
]);
});
});

View File

@@ -0,0 +1,107 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Microsoft SharePoint Node', () => {
const { baseUrl } = credentials.microsoftSharePointOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['create.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'post',
path: '/sites/site1/lists/list1/items',
statusCode: 201,
requestBody: {
fields: {
bool: true,
Title: 'Title 1',
choice: 'Choice 1',
datetime: '2025-03-24T00:00:00',
number: 1,
currency: 1,
LikesCount: 1,
RatingCount: 1,
AverageRating: 1,
person: '1',
lookup: '1',
image:
'{"type":"thumbnail","fileName":"file.jpg","nativeFile":{},"fieldName":"Picture","serverUrl":"https://mydomain.sharepoint.com","fieldId":"image","serverRelativeUrl":"/sites/site1/SiteAssets/Lists/list1/file.jpg","id":"image"}',
},
},
responseBody: {
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#listItems/$entity',
'@odata.etag': '"625d681e-2ce3-4c2b-a490-7c8404a31427,1"',
createdBy: {
user: {
displayName: 'John Doe',
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
},
},
createdDateTime: '2025-03-25T20:07:23Z',
eTag: '"625d681e-2ce3-4c2b-a490-7c8404a31427,1"',
id: '1',
lastModifiedBy: {
application: {
id: 'b9c26603-3c9b-4050-b848-27dfab0a52fa',
displayName: 'sharepoint-n8n-test',
},
user: {
displayName: 'John Doe',
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
},
},
lastModifiedDateTime: '2025-03-25T20:07:23Z',
parentReference: {
id: '0ead9135-9622-4b6d-b319-6b8810a6dc60',
listId: 'list1',
siteId: 'site1',
},
webUrl: 'https://mydomain.sharepoint.com/sites/n8ntest10/Lists/test/41_.000',
contentType: {
id: '0x0100362657F7588C5C438072A77E0EF184F4000272C0D1046D984B8097B3C00D199EDE',
name: 'Item',
},
'fields@odata.navigationLink': 'sites/site1/lists/list1/items/1/fields',
fields: {
'@odata.etag': '"625d681e-2ce3-4c2b-a490-7c8404a31427,1"',
Title: 'Title 1',
choice: 'Choice 1',
datetime: '2025-03-24T07:00:00Z',
number: 1,
bool: true,
currency: 1,
image:
'{"type":"thumbnail","fileName":"file.jpg","nativeFile":{},"fieldName":"Picture","serverUrl":"https://mydomain.sharepoint.com","fieldId":"image","serverRelativeUrl":"/sites/site1/SiteAssets/Lists/list1/file.jpg","id":"image"}',
AverageRating: 1,
ID: 1,
ContentType: 'Item',
Modified: '2025-03-25T20:07:23Z',
Created: '2025-03-25T20:07:23Z',
AuthorLookupId: '1',
EditorLookupId: '1',
_UIVersionString: '1.0',
Attachments: false,
Edit: '',
LinkTitleNoMenu: 'Title 1',
LinkTitle: 'Title 1',
ItemChildCount: '0',
FolderChildCount: '0',
_ComplianceFlags: '',
_ComplianceTag: '',
_ComplianceTagWrittenTime: '',
_ComplianceTagUserId: '',
AppAuthorLookupId: '1',
AppEditorLookupId: '1',
},
},
},
],
},
});
});

View File

@@ -0,0 +1,291 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "37ab6212-d506-4b53-b63e-14b6a2a05907",
"name": "When clicking Test workflow"
},
{
"parameters": {
"resource": "item",
"operation": "create",
"site": {
"__rl": true,
"value": "site1",
"mode": "list",
"cachedResultName": "site1"
},
"list": {
"__rl": true,
"value": "list1",
"mode": "list",
"cachedResultName": "list1"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"bool": true,
"Title": "Title 1",
"choice": "Choice 1",
"datetime": "2025-03-24T00:00:00",
"number": 1,
"currency": 1,
"LikesCount": 1,
"RatingCount": 1,
"AverageRating": 1,
"person": "1",
"lookup": "1",
"image": "{\"type\":\"thumbnail\",\"fileName\":\"file.jpg\",\"nativeFile\":{},\"fieldName\":\"Picture\",\"serverUrl\":\"https://mydomain.sharepoint.com\",\"fieldId\":\"image\",\"serverRelativeUrl\":\"/sites/site1/SiteAssets/Lists/list1/file.jpg\",\"id\":\"image\"}"
},
"matchingColumns": [],
"schema": [
{
"id": "Title",
"canBeUsedToMatch": true,
"defaultMatch": false,
"display": true,
"displayName": "Title",
"readOnly": false,
"required": true,
"type": "string"
},
{
"id": "choice",
"canBeUsedToMatch": false,
"defaultMatch": false,
"display": true,
"displayName": "choice",
"readOnly": false,
"required": false,
"type": "options",
"options": [
{
"name": "Choice 1",
"value": "Choice 1"
},
{
"name": "Choice 2",
"value": "Choice 2"
},
{
"name": "Choice 3",
"value": "Choice 3"
}
]
},
{
"id": "datetime",
"canBeUsedToMatch": false,
"defaultMatch": false,
"display": true,
"displayName": "datetime",
"readOnly": false,
"required": false,
"type": "dateTime"
},
{
"id": "person",
"canBeUsedToMatch": false,
"defaultMatch": false,
"display": true,
"displayName": "person",
"readOnly": false,
"required": false,
"type": "string",
"removed": false
},
{
"id": "number",
"canBeUsedToMatch": false,
"defaultMatch": false,
"display": true,
"displayName": "number",
"readOnly": false,
"required": false,
"type": "number"
},
{
"id": "bool",
"canBeUsedToMatch": false,
"defaultMatch": false,
"display": true,
"displayName": "bool",
"readOnly": false,
"required": false,
"type": "boolean"
},
{
"id": "currency",
"canBeUsedToMatch": false,
"defaultMatch": false,
"display": true,
"displayName": "currency",
"readOnly": false,
"required": false,
"type": "number",
"removed": false
},
{
"id": "image",
"canBeUsedToMatch": false,
"defaultMatch": false,
"display": true,
"displayName": "image",
"readOnly": false,
"required": false,
"type": "object",
"removed": false
},
{
"id": "lookup",
"canBeUsedToMatch": false,
"defaultMatch": false,
"display": true,
"displayName": "lookup",
"readOnly": false,
"required": false,
"type": "string",
"removed": false
},
{
"id": "AverageRating",
"canBeUsedToMatch": false,
"defaultMatch": false,
"display": true,
"displayName": "Rating (0-5)",
"readOnly": false,
"required": false,
"type": "number",
"removed": false
},
{
"id": "RatingCount",
"canBeUsedToMatch": false,
"defaultMatch": false,
"display": true,
"displayName": "Number of Ratings",
"readOnly": false,
"required": false,
"type": "number",
"removed": false
},
{
"id": "LikesCount",
"canBeUsedToMatch": false,
"defaultMatch": false,
"display": true,
"displayName": "Number of Likes",
"readOnly": false,
"required": false,
"type": "number",
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"requestOptions": {}
},
"type": "n8n-nodes-base.microsoftSharePoint",
"typeVersion": 1,
"position": [220, 0],
"id": "f9037af8-4f52-4f9f-b8ae-de860f890792",
"name": "Microsoft SharePoint",
"credentials": {
"microsoftSharePointOAuth2Api": {
"id": "cXXnMCWyk397M5qJ",
"name": "Microsoft SharePoint account"
}
}
}
],
"connections": {
"When clicking Test workflow": {
"main": [
[
{
"node": "Microsoft SharePoint",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {
"Microsoft SharePoint": [
{
"json": {
"@odata.context": "https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#listItems/$entity",
"@odata.etag": "\"625d681e-2ce3-4c2b-a490-7c8404a31427,1\"",
"createdBy": {
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"createdDateTime": "2025-03-25T20:07:23Z",
"eTag": "\"625d681e-2ce3-4c2b-a490-7c8404a31427,1\"",
"id": "1",
"lastModifiedBy": {
"application": {
"id": "b9c26603-3c9b-4050-b848-27dfab0a52fa",
"displayName": "sharepoint-n8n-test"
},
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"lastModifiedDateTime": "2025-03-25T20:07:23Z",
"parentReference": {
"id": "0ead9135-9622-4b6d-b319-6b8810a6dc60",
"listId": "list1",
"siteId": "site1"
},
"webUrl": "https://mydomain.sharepoint.com/sites/n8ntest10/Lists/test/41_.000",
"contentType": {
"id": "0x0100362657F7588C5C438072A77E0EF184F4000272C0D1046D984B8097B3C00D199EDE",
"name": "Item"
},
"fields@odata.navigationLink": "sites/site1/lists/list1/items/1/fields",
"fields": {
"@odata.etag": "\"625d681e-2ce3-4c2b-a490-7c8404a31427,1\"",
"Title": "Title 1",
"choice": "Choice 1",
"datetime": "2025-03-24T07:00:00Z",
"number": 1,
"bool": true,
"currency": 1,
"image": "{\"type\":\"thumbnail\",\"fileName\":\"file.jpg\",\"nativeFile\":{},\"fieldName\":\"Picture\",\"serverUrl\":\"https://mydomain.sharepoint.com\",\"fieldId\":\"image\",\"serverRelativeUrl\":\"/sites/site1/SiteAssets/Lists/list1/file.jpg\",\"id\":\"image\"}",
"AverageRating": 1,
"ID": 1,
"ContentType": "Item",
"Modified": "2025-03-25T20:07:23Z",
"Created": "2025-03-25T20:07:23Z",
"AuthorLookupId": "1",
"EditorLookupId": "1",
"_UIVersionString": "1.0",
"Attachments": false,
"Edit": "",
"LinkTitleNoMenu": "Title 1",
"LinkTitle": "Title 1",
"ItemChildCount": "0",
"FolderChildCount": "0",
"_ComplianceFlags": "",
"_ComplianceTag": "",
"_ComplianceTagWrittenTime": "",
"_ComplianceTagUserId": "",
"AppAuthorLookupId": "1",
"AppEditorLookupId": "1"
}
}
}
]
}
}

View File

@@ -0,0 +1,22 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Microsoft SharePoint Node', () => {
const { baseUrl } = credentials.microsoftSharePointOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['delete.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'delete',
path: '/sites/site1/lists/list1/items/item1',
statusCode: 204,
responseBody: {},
},
],
},
});
});

View File

@@ -0,0 +1,70 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "d8d29d0a-bb31-4094-a252-8008932f5425",
"name": "When clicking Test workflow"
},
{
"parameters": {
"resource": "item",
"operation": "delete",
"site": {
"__rl": true,
"value": "site1",
"mode": "list",
"cachedResultName": "site1"
},
"list": {
"__rl": true,
"value": "list1",
"mode": "list",
"cachedResultName": "list1"
},
"item": {
"__rl": true,
"value": "item1",
"mode": "list",
"cachedResultName": "item1"
},
"requestOptions": {}
},
"type": "n8n-nodes-base.microsoftSharePoint",
"typeVersion": 1,
"position": [200, 0],
"id": "0e19be10-9d94-4654-89e9-432daa8102cb",
"name": "Microsoft SharePoint",
"credentials": {
"microsoftSharePointOAuth2Api": {
"id": "cXXnMCWyk397M5qJ",
"name": "Microsoft SharePoint account"
}
}
}
],
"connections": {
"When clicking Test workflow": {
"main": [
[
{
"node": "Microsoft SharePoint",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {
"Microsoft SharePoint": [
{
"json": {
"deleted": true
}
}
]
}
}

View File

@@ -0,0 +1,82 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Microsoft SharePoint Node', () => {
const { baseUrl } = credentials.microsoftSharePointOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['get.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/sites/site1/lists/list1/items/item1?%24select=id%2CcreatedDateTime%2ClastModifiedDateTime%2CwebUrl&%24expand=fields%28select%3DTitle%29',
statusCode: 200,
responseBody: {
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#listItems/$entity',
'@odata.etag': '"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1"',
createdBy: {
user: {
displayName: 'John Doe',
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
},
},
createdDateTime: '2025-03-12T22:18:18Z',
eTag: '"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1"',
id: 'item1',
lastModifiedBy: {
application: {
id: 'b9c26603-3c9b-4050-b848-27dfab0a52fa',
displayName: 'sharepoint-n8n-test',
},
user: {
displayName: 'John Doe',
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
},
},
lastModifiedDateTime: '2025-03-12T22:18:18Z',
parentReference: {
id: '84070a73-ea24-463c-8eb2-0e9afa11c63f',
listId: 'list1',
siteId: 'site1',
},
webUrl: 'https://mydomain.sharepoint.com/sites/site1/Lists/name%20list/1_.000',
contentType: {
id: '0x010010D603DC4CF2DF4BB8A2D75DCB4BB1B30037A4993FB4DEB0439C3DC6DEC95A9DF8',
name: 'Item',
},
'fields@odata.navigationLink': 'sites/site1/lists/list1/items/item1/fields',
fields: {
'@odata.etag': '"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1"',
Title: 'Item 1',
ID: 'item1',
ContentType: 'Item',
Modified: '2025-03-12T22:18:18Z',
Created: '2025-03-12T22:18:18Z',
AuthorLookupId: '7',
EditorLookupId: '7',
_UIVersionString: '1.0',
Attachments: false,
Edit: '',
LinkTitleNoMenu: 'Item 1',
LinkTitle: 'Item 1',
ItemChildCount: '0',
FolderChildCount: '0',
_ComplianceFlags: '',
_ComplianceTag: '',
_ComplianceTagWrittenTime: '',
_ComplianceTagUserId: '',
AppAuthorLookupId: '5',
AppEditorLookupId: '5',
},
},
},
],
},
});
});

View File

@@ -0,0 +1,123 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "d8d29d0a-bb31-4094-a252-8008932f5425",
"name": "When clicking Test workflow"
},
{
"parameters": {
"resource": "item",
"operation": "get",
"site": {
"__rl": true,
"value": "site1",
"mode": "list",
"cachedResultName": "site1"
},
"list": {
"__rl": true,
"value": "list1",
"mode": "list",
"cachedResultName": "list1"
},
"item": {
"__rl": true,
"value": "item1",
"mode": "list",
"cachedResultName": "item1"
},
"requestOptions": {}
},
"type": "n8n-nodes-base.microsoftSharePoint",
"typeVersion": 1,
"position": [200, 0],
"id": "0e19be10-9d94-4654-89e9-432daa8102cb",
"name": "Microsoft SharePoint",
"credentials": {
"microsoftSharePointOAuth2Api": {
"id": "cXXnMCWyk397M5qJ",
"name": "Microsoft SharePoint account"
}
}
}
],
"connections": {
"When clicking Test workflow": {
"main": [
[
{
"node": "Microsoft SharePoint",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {
"Microsoft SharePoint": [
{
"json": {
"createdBy": {
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"createdDateTime": "2025-03-12T22:18:18Z",
"eTag": "\"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1\"",
"id": "item1",
"lastModifiedBy": {
"application": {
"id": "b9c26603-3c9b-4050-b848-27dfab0a52fa",
"displayName": "sharepoint-n8n-test"
},
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"lastModifiedDateTime": "2025-03-12T22:18:18Z",
"parentReference": {
"id": "84070a73-ea24-463c-8eb2-0e9afa11c63f",
"listId": "list1",
"siteId": "site1"
},
"webUrl": "https://mydomain.sharepoint.com/sites/site1/Lists/name%20list/1_.000",
"contentType": {
"id": "0x010010D603DC4CF2DF4BB8A2D75DCB4BB1B30037A4993FB4DEB0439C3DC6DEC95A9DF8",
"name": "Item"
},
"fields": {
"Title": "Item 1",
"ID": "item1",
"ContentType": "Item",
"Modified": "2025-03-12T22:18:18Z",
"Created": "2025-03-12T22:18:18Z",
"AuthorLookupId": "7",
"EditorLookupId": "7",
"_UIVersionString": "1.0",
"Attachments": false,
"Edit": "",
"LinkTitleNoMenu": "Item 1",
"LinkTitle": "Item 1",
"ItemChildCount": "0",
"FolderChildCount": "0",
"_ComplianceFlags": "",
"_ComplianceTag": "",
"_ComplianceTagWrittenTime": "",
"_ComplianceTagUserId": "",
"AppAuthorLookupId": "5",
"AppEditorLookupId": "5"
}
}
}
]
}
}

View File

@@ -0,0 +1,158 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Microsoft SharePoint Node', () => {
const { baseUrl } = credentials.microsoftSharePointOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['getAll.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/sites/site1/lists/list1/items?%24select%5B0%5D=contentType&%24select%5B1%5D=createdDateTime&%24select%5B2%5D=createdBy&%24select%5B3%5D=fields&%24select%5B4%5D=id&%24select%5B5%5D=lastModifiedDateTime&%24select%5B6%5D=lastModifiedBy&%24select%5B7%5D=parentReference&%24select%5B8%5D=webUrl',
statusCode: 200,
responseBody: {
value: [
{
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#listItems/$entity',
'@odata.etag': '"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1"',
createdBy: {
user: {
displayName: 'John Doe',
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
},
},
createdDateTime: '2025-03-12T22:18:18Z',
eTag: '"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1"',
id: 'item1',
lastModifiedBy: {
application: {
id: 'b9c26603-3c9b-4050-b848-27dfab0a52fa',
displayName: 'sharepoint-n8n-test',
},
user: {
displayName: 'John Doe',
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
},
},
lastModifiedDateTime: '2025-03-12T22:18:18Z',
parentReference: {
id: '84070a73-ea24-463c-8eb2-0e9afa11c63f',
listId: 'list1',
siteId: 'site1',
},
webUrl: 'https://mydomain.sharepoint.com/sites/site1/Lists/name%20list/1_.000',
contentType: {
id: '0x010010D603DC4CF2DF4BB8A2D75DCB4BB1B30037A4993FB4DEB0439C3DC6DEC95A9DF8',
name: 'Item',
},
'fields@odata.navigationLink': 'sites/site1/lists/list1/items/item1/fields',
fields: {
'@odata.etag': '"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1"',
Title: 'Item 1',
ID: 'item1',
ContentType: 'Item',
Modified: '2025-03-12T22:18:18Z',
Created: '2025-03-12T22:18:18Z',
AuthorLookupId: '7',
EditorLookupId: '7',
_UIVersionString: '1.0',
Attachments: false,
Edit: '',
LinkTitleNoMenu: 'Item 1',
LinkTitle: 'Item 1',
ItemChildCount: '0',
FolderChildCount: '0',
_ComplianceFlags: '',
_ComplianceTag: '',
_ComplianceTagWrittenTime: '',
_ComplianceTagUserId: '',
AppAuthorLookupId: '5',
AppEditorLookupId: '5',
},
},
],
'@odata.nextLink':
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27site1%27)/lists(%27list1%27)/items?%24skiptoken=UGFnZWQ9VFJVRSZwX0lEPTE&%24top=1&%24expand=fields&%24select%5b0%5d=contentType&%24select%5b1%5d=createdDateTime&%24select%5b2%5d=createdBy&%24select%5b3%5d=fields&%24select%5b4%5d=id&%24select%5b5%5d=lastModifiedDateTime&%24select%5b6%5d=lastModifiedBy&%24select%5b7%5d=parentReference&%24select%5b8%5d=webUrl',
},
},
{
method: 'get',
path: '/sites(%27site1%27)/lists(%27list1%27)/items?%24skiptoken=UGFnZWQ9VFJVRSZwX0lEPTE&%24top=1&%24expand=fields&%24select%5b0%5d=contentType&%24select%5b1%5d=createdDateTime&%24select%5b2%5d=createdBy&%24select%5b3%5d=fields&%24select%5b4%5d=id&%24select%5b5%5d=lastModifiedDateTime&%24select%5b6%5d=lastModifiedBy&%24select%5b7%5d=parentReference&%24select%5b8%5d=webUrl',
statusCode: 200,
responseBody: {
value: [
{
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#listItems/$entity',
'@odata.etag': '"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1"',
createdBy: {
user: {
displayName: 'John Doe',
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
},
},
createdDateTime: '2025-03-12T22:18:18Z',
eTag: '"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1"',
id: 'item2',
lastModifiedBy: {
application: {
id: 'b9c26603-3c9b-4050-b848-27dfab0a52fa',
displayName: 'sharepoint-n8n-test',
},
user: {
displayName: 'John Doe',
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
},
},
lastModifiedDateTime: '2025-03-12T22:18:18Z',
parentReference: {
id: '84070a73-ea24-463c-8eb2-0e9afa11c63f',
listId: 'list1',
siteId: 'site1',
},
webUrl: 'https://mydomain.sharepoint.com/sites/site1/Lists/name%20list/1_.000',
contentType: {
id: '0x010010D603DC4CF2DF4BB8A2D75DCB4BB1B30037A4993FB4DEB0439C3DC6DEC95A9DF8',
name: 'Item',
},
'fields@odata.navigationLink': 'sites/site1/lists/list1/items/item1/fields',
fields: {
'@odata.etag': '"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1"',
Title: 'Item 2',
ID: 'item2',
ContentType: 'Item',
Modified: '2025-03-12T22:18:18Z',
Created: '2025-03-12T22:18:18Z',
AuthorLookupId: '7',
EditorLookupId: '7',
_UIVersionString: '1.0',
Attachments: false,
Edit: '',
LinkTitleNoMenu: 'Item 2',
LinkTitle: 'Item 2',
ItemChildCount: '0',
FolderChildCount: '0',
_ComplianceFlags: '',
_ComplianceTag: '',
_ComplianceTagWrittenTime: '',
_ComplianceTagUserId: '',
AppAuthorLookupId: '5',
AppEditorLookupId: '5',
},
},
],
},
},
],
},
});
});

View File

@@ -0,0 +1,198 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "d8d29d0a-bb31-4094-a252-8008932f5425",
"name": "When clicking Test workflow"
},
{
"parameters": {
"resource": "item",
"site": {
"__rl": true,
"value": "site1",
"mode": "list",
"cachedResultName": "site1"
},
"list": {
"__rl": true,
"value": "list1",
"mode": "list",
"cachedResultName": "list1"
},
"filter": "fields/Title eq 'item1'",
"returnAll": true,
"options": {
"fields": [
"contentType",
"createdDateTime",
"createdBy",
"fields",
"id",
"lastModifiedDateTime",
"lastModifiedBy",
"parentReference",
"webUrl"
]
},
"simplify": false,
"requestOptions": {}
},
"type": "n8n-nodes-base.microsoftSharePoint",
"typeVersion": 1,
"position": [200, 0],
"id": "0e19be10-9d94-4654-89e9-432daa8102cb",
"name": "Microsoft SharePoint",
"credentials": {
"microsoftSharePointOAuth2Api": {
"id": "cXXnMCWyk397M5qJ",
"name": "Microsoft SharePoint account"
}
}
}
],
"connections": {
"When clicking Test workflow": {
"main": [
[
{
"node": "Microsoft SharePoint",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {
"Microsoft SharePoint": [
{
"json": {
"@odata.context": "https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#listItems/$entity",
"@odata.etag": "\"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1\"",
"createdBy": {
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"createdDateTime": "2025-03-12T22:18:18Z",
"eTag": "\"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1\"",
"id": "item1",
"lastModifiedBy": {
"application": {
"id": "b9c26603-3c9b-4050-b848-27dfab0a52fa",
"displayName": "sharepoint-n8n-test"
},
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"lastModifiedDateTime": "2025-03-12T22:18:18Z",
"parentReference": {
"id": "84070a73-ea24-463c-8eb2-0e9afa11c63f",
"listId": "list1",
"siteId": "site1"
},
"webUrl": "https://mydomain.sharepoint.com/sites/site1/Lists/name%20list/1_.000",
"contentType": {
"id": "0x010010D603DC4CF2DF4BB8A2D75DCB4BB1B30037A4993FB4DEB0439C3DC6DEC95A9DF8",
"name": "Item"
},
"fields@odata.navigationLink": "sites/site1/lists/list1/items/item1/fields",
"fields": {
"@odata.etag": "\"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1\"",
"Title": "Item 1",
"ID": "item1",
"ContentType": "Item",
"Modified": "2025-03-12T22:18:18Z",
"Created": "2025-03-12T22:18:18Z",
"AuthorLookupId": "7",
"EditorLookupId": "7",
"_UIVersionString": "1.0",
"Attachments": false,
"Edit": "",
"LinkTitleNoMenu": "Item 1",
"LinkTitle": "Item 1",
"ItemChildCount": "0",
"FolderChildCount": "0",
"_ComplianceFlags": "",
"_ComplianceTag": "",
"_ComplianceTagWrittenTime": "",
"_ComplianceTagUserId": "",
"AppAuthorLookupId": "5",
"AppEditorLookupId": "5"
}
}
},
{
"json": {
"@odata.context": "https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#listItems/$entity",
"@odata.etag": "\"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1\"",
"createdBy": {
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"createdDateTime": "2025-03-12T22:18:18Z",
"eTag": "\"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1\"",
"id": "item2",
"lastModifiedBy": {
"application": {
"id": "b9c26603-3c9b-4050-b848-27dfab0a52fa",
"displayName": "sharepoint-n8n-test"
},
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"lastModifiedDateTime": "2025-03-12T22:18:18Z",
"parentReference": {
"id": "84070a73-ea24-463c-8eb2-0e9afa11c63f",
"listId": "list1",
"siteId": "site1"
},
"webUrl": "https://mydomain.sharepoint.com/sites/site1/Lists/name%20list/1_.000",
"contentType": {
"id": "0x010010D603DC4CF2DF4BB8A2D75DCB4BB1B30037A4993FB4DEB0439C3DC6DEC95A9DF8",
"name": "Item"
},
"fields@odata.navigationLink": "sites/site1/lists/list1/items/item1/fields",
"fields": {
"@odata.etag": "\"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1\"",
"Title": "Item 2",
"ID": "item2",
"ContentType": "Item",
"Modified": "2025-03-12T22:18:18Z",
"Created": "2025-03-12T22:18:18Z",
"AuthorLookupId": "7",
"EditorLookupId": "7",
"_UIVersionString": "1.0",
"Attachments": false,
"Edit": "",
"LinkTitleNoMenu": "Item 2",
"LinkTitle": "Item 2",
"ItemChildCount": "0",
"FolderChildCount": "0",
"_ComplianceFlags": "",
"_ComplianceTag": "",
"_ComplianceTagWrittenTime": "",
"_ComplianceTagUserId": "",
"AppAuthorLookupId": "5",
"AppEditorLookupId": "5"
}
}
}
]
}
}

View File

@@ -0,0 +1,55 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Microsoft SharePoint Node', () => {
const { baseUrl } = credentials.microsoftSharePointOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['getAllLimitSimplify.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/sites/site1/lists/list1/items?%24top=2&%24select=id%2CcreatedDateTime%2ClastModifiedDateTime%2CwebUrl&%24expand=fields%28select%3DTitle%29',
statusCode: 200,
responseBody: {
value: [
{
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#listItems/$entity',
'@odata.etag': '"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1"',
createdDateTime: '2025-03-12T22:18:18Z',
id: 'item1',
lastModifiedDateTime: '2025-03-12T22:18:18Z',
webUrl: 'https://mydomain.sharepoint.com/sites/site1/Lists/name%20list/1_.000',
'fields@odata.navigationLink': 'sites/site1/lists/list1/items/item1/fields',
fields: {
'@odata.etag': '"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1"',
Title: 'Item 1',
},
},
{
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#listItems/$entity',
'@odata.etag': '"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1"',
createdDateTime: '2025-03-12T22:18:18Z',
id: 'item2',
lastModifiedDateTime: '2025-03-12T22:18:18Z',
webUrl: 'https://mydomain.sharepoint.com/sites/site1/Lists/name%20list/1_.000',
'fields@odata.navigationLink': 'sites/site1/lists/list1/items/item1/fields',
fields: {
'@odata.etag': '"07bfcdd5-450d-48ce-8dc3-04f7f59edc5f,1"',
Title: 'Item 2',
},
},
],
'@odata.nextLink':
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27site1%27)/lists(%27list1%27)/items?%24skiptoken=UGFnZWQ9VFJVRSZwX0lEPTE&%24top=1&%24expand=fields&%24select%5b0%5d=contentType&%24select%5b1%5d=createdDateTime&%24select%5b2%5d=createdBy&%24select%5b3%5d=fields&%24select%5b4%5d=id&%24select%5b5%5d=lastModifiedDateTime&%24select%5b6%5d=lastModifiedBy&%24select%5b7%5d=parentReference&%24select%5b8%5d=webUrl',
},
},
],
},
});
});

View File

@@ -0,0 +1,82 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "d8d29d0a-bb31-4094-a252-8008932f5425",
"name": "When clicking Test workflow"
},
{
"parameters": {
"resource": "item",
"site": {
"__rl": true,
"value": "site1",
"mode": "list",
"cachedResultName": "site1"
},
"list": {
"__rl": true,
"value": "list1",
"mode": "list",
"cachedResultName": "list1"
},
"limit": 2,
"options": {},
"requestOptions": {}
},
"type": "n8n-nodes-base.microsoftSharePoint",
"typeVersion": 1,
"position": [200, 0],
"id": "0e19be10-9d94-4654-89e9-432daa8102cb",
"name": "Microsoft SharePoint",
"credentials": {
"microsoftSharePointOAuth2Api": {
"id": "cXXnMCWyk397M5qJ",
"name": "Microsoft SharePoint account"
}
}
}
],
"connections": {
"When clicking Test workflow": {
"main": [
[
{
"node": "Microsoft SharePoint",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {
"Microsoft SharePoint": [
{
"json": {
"createdDateTime": "2025-03-12T22:18:18Z",
"id": "item1",
"lastModifiedDateTime": "2025-03-12T22:18:18Z",
"webUrl": "https://mydomain.sharepoint.com/sites/site1/Lists/name%20list/1_.000",
"fields": {
"Title": "Item 1"
}
}
},
{
"json": {
"createdDateTime": "2025-03-12T22:18:18Z",
"id": "item2",
"lastModifiedDateTime": "2025-03-12T22:18:18Z",
"webUrl": "https://mydomain.sharepoint.com/sites/site1/Lists/name%20list/1_.000",
"fields": {
"Title": "Item 2"
}
}
}
]
}
}

View File

@@ -0,0 +1,87 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Microsoft SharePoint Node', () => {
const { baseUrl } = credentials.microsoftSharePointOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['update.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'patch',
path: '/sites/site1/lists/list1/items/item1',
statusCode: 200,
requestBody: {
fields: {
Title: 'Title 2',
},
},
responseBody: {
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#listItems/$entity',
'@odata.etag': '"cc40561f-3d3b-4cfb-b8a9-8af9d71de3f0,2"',
createdBy: {
user: {
displayName: 'John Doe',
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
},
},
createdDateTime: '2025-03-25T12:26:12Z',
eTag: '"cc40561f-3d3b-4cfb-b8a9-8af9d71de3f0,2"',
id: 'item1',
lastModifiedBy: {
application: {
id: 'b9c26603-3c9b-4050-b848-27dfab0a52fa',
displayName: 'sharepoint-n8n-test',
},
user: {
displayName: 'John Doe',
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
},
},
lastModifiedDateTime: '2025-03-25T12:26:46Z',
parentReference: {
id: '84070a73-ea24-463c-8eb2-0e9afa11c63f',
listId: 'list1',
siteId: 'site1',
},
webUrl: 'https://mydomain.sharepoint.com/sites/site1/Lists/name%20list/3_.000',
contentType: {
id: '0x010010D603DC4CF2DF4BB8A2D75DCB4BB1B30037A4993FB4DEB0439C3DC6DEC95A9DF8',
name: 'Item',
},
'fields@odata.navigationLink': 'sites/site1/lists/list1/items/item1/fields',
fields: {
'@odata.etag': '"cc40561f-3d3b-4cfb-b8a9-8af9d71de3f0,2"',
Title: 'Title 2',
ID: 'item1',
ContentType: 'Item',
Modified: '2025-03-25T12:26:46Z',
Created: '2025-03-25T12:26:12Z',
AuthorLookupId: '7',
EditorLookupId: '7',
_UIVersionString: '2.0',
Attachments: false,
Edit: '',
LinkTitleNoMenu: 'Title 2',
LinkTitle: 'Title 2',
ItemChildCount: '0',
FolderChildCount: '0',
_ComplianceFlags: '',
_ComplianceTag: '',
_ComplianceTagWrittenTime: '',
_ComplianceTagUserId: '',
AppAuthorLookupId: '5',
AppEditorLookupId: '5',
},
},
},
],
},
});
});

View File

@@ -0,0 +1,154 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "d8d29d0a-bb31-4094-a252-8008932f5425",
"name": "When clicking Test workflow"
},
{
"parameters": {
"resource": "item",
"operation": "update",
"site": {
"__rl": true,
"value": "site1",
"mode": "list",
"cachedResultName": "site1"
},
"list": {
"__rl": true,
"value": "list1",
"mode": "list",
"cachedResultName": "list1"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"Title": "Title 2",
"id": "item1"
},
"matchingColumns": ["id"],
"schema": [
{
"id": "Title",
"canBeUsedToMatch": false,
"defaultMatch": false,
"display": true,
"displayName": "Title",
"readOnly": false,
"required": false,
"type": "string"
},
{
"id": "id",
"canBeUsedToMatch": true,
"defaultMatch": false,
"display": true,
"displayName": "ID",
"readOnly": true,
"required": true,
"type": "string",
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"requestOptions": {}
},
"type": "n8n-nodes-base.microsoftSharePoint",
"typeVersion": 1,
"position": [200, 0],
"id": "0e19be10-9d94-4654-89e9-432daa8102cb",
"name": "Microsoft SharePoint",
"credentials": {
"microsoftSharePointOAuth2Api": {
"id": "cXXnMCWyk397M5qJ",
"name": "Microsoft SharePoint account"
}
}
}
],
"connections": {
"When clicking Test workflow": {
"main": [
[
{
"node": "Microsoft SharePoint",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {
"Microsoft SharePoint": [
{
"json": {
"@odata.context": "https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#listItems/$entity",
"@odata.etag": "\"cc40561f-3d3b-4cfb-b8a9-8af9d71de3f0,2\"",
"createdBy": {
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"createdDateTime": "2025-03-25T12:26:12Z",
"eTag": "\"cc40561f-3d3b-4cfb-b8a9-8af9d71de3f0,2\"",
"id": "item1",
"lastModifiedBy": {
"application": {
"id": "b9c26603-3c9b-4050-b848-27dfab0a52fa",
"displayName": "sharepoint-n8n-test"
},
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"lastModifiedDateTime": "2025-03-25T12:26:46Z",
"parentReference": {
"id": "84070a73-ea24-463c-8eb2-0e9afa11c63f",
"listId": "list1",
"siteId": "site1"
},
"webUrl": "https://mydomain.sharepoint.com/sites/site1/Lists/name%20list/3_.000",
"contentType": {
"id": "0x010010D603DC4CF2DF4BB8A2D75DCB4BB1B30037A4993FB4DEB0439C3DC6DEC95A9DF8",
"name": "Item"
},
"fields@odata.navigationLink": "sites/site1/lists/list1/items/item1/fields",
"fields": {
"@odata.etag": "\"cc40561f-3d3b-4cfb-b8a9-8af9d71de3f0,2\"",
"Title": "Title 2",
"ID": "item1",
"ContentType": "Item",
"Modified": "2025-03-25T12:26:46Z",
"Created": "2025-03-25T12:26:12Z",
"AuthorLookupId": "7",
"EditorLookupId": "7",
"_UIVersionString": "2.0",
"Attachments": false,
"Edit": "",
"LinkTitleNoMenu": "Title 2",
"LinkTitle": "Title 2",
"ItemChildCount": "0",
"FolderChildCount": "0",
"_ComplianceFlags": "",
"_ComplianceTag": "",
"_ComplianceTagWrittenTime": "",
"_ComplianceTagUserId": "",
"AppAuthorLookupId": "5",
"AppEditorLookupId": "5"
}
}
}
]
}
}

View File

@@ -0,0 +1,136 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Microsoft SharePoint Node', () => {
const { baseUrl } = credentials.microsoftSharePointOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['upsert.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/sites/site1/lists/list1/items?%24filter=fields%2FTitle%20eq%20%27Title%201%27',
statusCode: 200,
requestHeaders: {
Prefer: 'HonorNonIndexedQueriesWarningMayFailRandomly',
},
responseBody: {
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#listItems',
value: [
{
'@odata.etag': '"0ea4148a-f8e5-4f2f-a815-2e2be693b164,2"',
createdBy: {
user: {
displayName: 'John Doe',
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
},
},
createdDateTime: '2025-03-25T12:48:45Z',
eTag: '"0ea4148a-f8e5-4f2f-a815-2e2be693b164,2"',
id: 'item1',
lastModifiedBy: {
application: {
id: 'b9c26603-3c9b-4050-b848-27dfab0a52fa',
displayName: 'sharepoint-n8n-test',
},
user: {
displayName: 'John Doe',
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
},
},
lastModifiedDateTime: '2025-03-25T13:01:45Z',
parentReference: {
id: '0ead9135-9622-4b6d-b319-6b8810a6dc60',
listId: 'list1',
siteId: 'site1',
},
webUrl: 'https://mydomain.sharepoint.com/sites/site1/Lists/test/19_.000',
contentType: {
id: '0x0100362657F7588C5C438072A77E0EF184F4000272C0D1046D984B8097B3C00D199EDE',
name: 'Item',
},
},
],
},
},
{
method: 'patch',
path: '/sites/site1/lists/list1/items/item1',
statusCode: 200,
requestBody: {
fields: {
Title: 'Title 1',
},
},
responseBody: {
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#listItems/$entity',
'@odata.etag': '"cc40561f-3d3b-4cfb-b8a9-8af9d71de3f0,2"',
createdBy: {
user: {
displayName: 'John Doe',
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
},
},
createdDateTime: '2025-03-25T12:26:12Z',
eTag: '"cc40561f-3d3b-4cfb-b8a9-8af9d71de3f0,2"',
id: 'item1',
lastModifiedBy: {
application: {
id: 'b9c26603-3c9b-4050-b848-27dfab0a52fa',
displayName: 'sharepoint-n8n-test',
},
user: {
displayName: 'John Doe',
email: 'john@doe.onmicrosoft.com',
id: '5f7afebb-121d-4664-882b-a09fe6584ce0',
},
},
lastModifiedDateTime: '2025-03-25T12:26:46Z',
parentReference: {
id: '84070a73-ea24-463c-8eb2-0e9afa11c63f',
listId: 'list1',
siteId: 'site1',
},
webUrl: 'https://mydomain.sharepoint.com/sites/site1/Lists/name%20list/3_.000',
contentType: {
id: '0x010010D603DC4CF2DF4BB8A2D75DCB4BB1B30037A4993FB4DEB0439C3DC6DEC95A9DF8',
name: 'Item',
},
'fields@odata.navigationLink': 'sites/site1/lists/list1/items/item1/fields',
fields: {
'@odata.etag': '"cc40561f-3d3b-4cfb-b8a9-8af9d71de3f0,2"',
Title: 'Title 1',
ID: 'item1',
ContentType: 'Item',
Modified: '2025-03-25T12:26:46Z',
Created: '2025-03-25T12:26:12Z',
AuthorLookupId: '7',
EditorLookupId: '7',
_UIVersionString: '2.0',
Attachments: false,
Edit: '',
LinkTitleNoMenu: 'Title 1',
LinkTitle: 'Title 1',
ItemChildCount: '0',
FolderChildCount: '0',
_ComplianceFlags: '',
_ComplianceTag: '',
_ComplianceTagWrittenTime: '',
_ComplianceTagUserId: '',
AppAuthorLookupId: '5',
AppEditorLookupId: '5',
},
},
},
],
},
});
});

View File

@@ -0,0 +1,143 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "d8d29d0a-bb31-4094-a252-8008932f5425",
"name": "When clicking Test workflow"
},
{
"parameters": {
"resource": "item",
"operation": "upsert",
"site": {
"__rl": true,
"value": "site1",
"mode": "list",
"cachedResultName": "site1"
},
"list": {
"__rl": true,
"value": "list1",
"mode": "list",
"cachedResultName": "list1"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"Title": "Title 1"
},
"matchingColumns": ["Title"],
"schema": [
{
"id": "Title",
"canBeUsedToMatch": true,
"defaultMatch": false,
"display": true,
"displayName": "Title",
"readOnly": false,
"required": true,
"type": "string",
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"requestOptions": {}
},
"type": "n8n-nodes-base.microsoftSharePoint",
"typeVersion": 1,
"position": [200, 0],
"id": "0e19be10-9d94-4654-89e9-432daa8102cb",
"name": "Microsoft SharePoint",
"credentials": {
"microsoftSharePointOAuth2Api": {
"id": "cXXnMCWyk397M5qJ",
"name": "Microsoft SharePoint account"
}
}
}
],
"connections": {
"When clicking Test workflow": {
"main": [
[
{
"node": "Microsoft SharePoint",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {
"Microsoft SharePoint": [
{
"json": {
"@odata.context": "https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#listItems/$entity",
"@odata.etag": "\"cc40561f-3d3b-4cfb-b8a9-8af9d71de3f0,2\"",
"createdBy": {
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"createdDateTime": "2025-03-25T12:26:12Z",
"eTag": "\"cc40561f-3d3b-4cfb-b8a9-8af9d71de3f0,2\"",
"id": "item1",
"lastModifiedBy": {
"application": {
"id": "b9c26603-3c9b-4050-b848-27dfab0a52fa",
"displayName": "sharepoint-n8n-test"
},
"user": {
"displayName": "John Doe",
"email": "john@doe.onmicrosoft.com",
"id": "5f7afebb-121d-4664-882b-a09fe6584ce0"
}
},
"lastModifiedDateTime": "2025-03-25T12:26:46Z",
"parentReference": {
"id": "84070a73-ea24-463c-8eb2-0e9afa11c63f",
"listId": "list1",
"siteId": "site1"
},
"webUrl": "https://mydomain.sharepoint.com/sites/site1/Lists/name%20list/3_.000",
"contentType": {
"id": "0x010010D603DC4CF2DF4BB8A2D75DCB4BB1B30037A4993FB4DEB0439C3DC6DEC95A9DF8",
"name": "Item"
},
"fields@odata.navigationLink": "sites/site1/lists/list1/items/item1/fields",
"fields": {
"@odata.etag": "\"cc40561f-3d3b-4cfb-b8a9-8af9d71de3f0,2\"",
"Title": "Title 1",
"ID": "item1",
"ContentType": "Item",
"Modified": "2025-03-25T12:26:46Z",
"Created": "2025-03-25T12:26:12Z",
"AuthorLookupId": "7",
"EditorLookupId": "7",
"_UIVersionString": "2.0",
"Attachments": false,
"Edit": "",
"LinkTitleNoMenu": "Title 1",
"LinkTitle": "Title 1",
"ItemChildCount": "0",
"FolderChildCount": "0",
"_ComplianceFlags": "",
"_ComplianceTag": "",
"_ComplianceTagWrittenTime": "",
"_ComplianceTagUserId": "",
"AppAuthorLookupId": "5",
"AppEditorLookupId": "5"
}
}
}
]
}
}

View File

@@ -0,0 +1,33 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Microsoft SharePoint Node', () => {
const { baseUrl } = credentials.microsoftSharePointOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['get.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/sites/site1/lists/list1?%24select=id%2Cname%2CdisplayName%2Cdescription%2CcreatedDateTime%2ClastModifiedDateTime%2CwebUrl',
statusCode: 200,
responseBody: {
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#lists/$entity',
'@odata.etag': '"58a279af-1f06-4392-a5ed-2b37fa1d6c1d,5"',
createdDateTime: '2025-03-12T19:38:40Z',
description: 'My List 1',
id: '58a279af-1f06-4392-a5ed-2b37fa1d6c1d',
lastModifiedDateTime: '2025-03-12T22:18:18Z',
name: 'list1',
webUrl: 'https://mydomain.sharepoint.com/sites/site1/Lists/name%20list',
displayName: 'list1',
},
},
],
},
});
});

View File

@@ -0,0 +1,70 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "d8d29d0a-bb31-4094-a252-8008932f5425",
"name": "When clicking Test workflow"
},
{
"parameters": {
"resource": "list",
"operation": "get",
"site": {
"__rl": true,
"value": "site1",
"mode": "list",
"cachedResultName": "site1"
},
"list": {
"__rl": true,
"value": "list1",
"mode": "list",
"cachedResultName": "list1"
},
"requestOptions": {}
},
"type": "n8n-nodes-base.microsoftSharePoint",
"typeVersion": 1,
"position": [200, 0],
"id": "0e19be10-9d94-4654-89e9-432daa8102cb",
"name": "Microsoft SharePoint",
"credentials": {
"microsoftSharePointOAuth2Api": {
"id": "cXXnMCWyk397M5qJ",
"name": "Microsoft SharePoint account"
}
}
}
],
"connections": {
"When clicking Test workflow": {
"main": [
[
{
"node": "Microsoft SharePoint",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {
"Microsoft SharePoint": [
{
"json": {
"createdDateTime": "2025-03-12T19:38:40Z",
"description": "My List 1",
"id": "58a279af-1f06-4392-a5ed-2b37fa1d6c1d",
"lastModifiedDateTime": "2025-03-12T22:18:18Z",
"name": "list1",
"webUrl": "https://mydomain.sharepoint.com/sites/site1/Lists/name%20list",
"displayName": "list1"
}
}
]
}
}

View File

@@ -0,0 +1,60 @@
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
import { credentials } from '../credentials';
describe('Microsoft SharePoint Node', () => {
const { baseUrl } = credentials.microsoftSharePointOAuth2Api;
new NodeTestHarness().setupTests({
credentials,
workflowFiles: ['getAll.workflow.json'],
nock: {
baseUrl,
mocks: [
{
method: 'get',
path: '/sites/site1/lists?%24select=id%2Cname%2CdisplayName%2Cdescription%2CcreatedDateTime%2ClastModifiedDateTime%2CwebUrl',
statusCode: 200,
responseBody: {
value: [
{
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#lists/$entity',
'@odata.etag': '"58a279af-1f06-4392-a5ed-2b37fa1d6c1d,5"',
createdDateTime: '2025-03-12T19:38:40Z',
description: 'My List 1',
id: '58a279af-1f06-4392-a5ed-2b37fa1d6c1d',
lastModifiedDateTime: '2025-03-12T22:18:18Z',
name: 'list1',
webUrl: 'https://mydomain.sharepoint.com/sites/site1/Lists/name%20list',
displayName: 'list1',
},
],
'@odata.nextLink':
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/lists?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB&%24top=1&%24select=id%2cname%2cdisplayName%2cdescription%2ccreatedDateTime%2clastModifiedDateTime%2cwebUrl',
},
},
{
method: 'get',
path: '/sites(%27mydomain.sharepoint.com,site1%27)/lists?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB&%24top=1&%24select=id%2cname%2cdisplayName%2cdescription%2ccreatedDateTime%2clastModifiedDateTime%2cwebUrl',
statusCode: 200,
responseBody: {
value: [
{
'@odata.context':
'https://mydomain.sharepoint.com/sites/site1/_api/v2.0/$metadata#lists/$entity',
'@odata.etag': '"58a279af-1f06-4392-a5ed-2b37fa1d6c1d,5"',
createdDateTime: '2025-03-12T19:38:40Z',
description: 'My List 2',
id: '58a279af-1f06-4392-a5ed-2b37fa1d6c1d',
lastModifiedDateTime: '2025-03-12T22:18:18Z',
name: 'list2',
webUrl: 'https://mydomain.sharepoint.com/sites/site1/Lists/name%20list',
displayName: 'list2',
},
],
},
},
],
},
});
});

View File

@@ -0,0 +1,76 @@
{
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [0, 0],
"id": "d8d29d0a-bb31-4094-a252-8008932f5425",
"name": "When clicking Test workflow"
},
{
"parameters": {
"resource": "list",
"operation": "getAll",
"site": {
"__rl": true,
"value": "site1",
"mode": "list",
"cachedResultName": "site1"
},
"returnAll": true,
"requestOptions": {}
},
"type": "n8n-nodes-base.microsoftSharePoint",
"typeVersion": 1,
"position": [200, 0],
"id": "0e19be10-9d94-4654-89e9-432daa8102cb",
"name": "Microsoft SharePoint",
"credentials": {
"microsoftSharePointOAuth2Api": {
"id": "cXXnMCWyk397M5qJ",
"name": "Microsoft SharePoint account"
}
}
}
],
"connections": {
"When clicking Test workflow": {
"main": [
[
{
"node": "Microsoft SharePoint",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {
"Microsoft SharePoint": [
{
"json": {
"createdDateTime": "2025-03-12T19:38:40Z",
"description": "My List 1",
"id": "58a279af-1f06-4392-a5ed-2b37fa1d6c1d",
"lastModifiedDateTime": "2025-03-12T22:18:18Z",
"name": "list1",
"webUrl": "https://mydomain.sharepoint.com/sites/site1/Lists/name%20list",
"displayName": "list1"
}
},
{
"json": {
"createdDateTime": "2025-03-12T19:38:40Z",
"description": "My List 2",
"id": "58a279af-1f06-4392-a5ed-2b37fa1d6c1d",
"lastModifiedDateTime": "2025-03-12T22:18:18Z",
"name": "list2",
"webUrl": "https://mydomain.sharepoint.com/sites/site1/Lists/name%20list",
"displayName": "list2"
}
}
]
}
}

View File

@@ -0,0 +1,476 @@
import type { MockProxy } from 'jest-mock-extended';
import { mock } from 'jest-mock-extended';
import type { ILoadOptionsFunctions } from 'n8n-workflow';
import { MicrosoftSharePoint } from '../../MicrosoftSharePoint.node';
import { credentials } from '../credentials';
describe('Microsoft SharePoint Node', () => {
describe('List search', () => {
let loadOptionsFunctions: MockProxy<ILoadOptionsFunctions>;
let mockRequestWithAuthentication: jest.Mock;
let node: MicrosoftSharePoint;
beforeEach(() => {
loadOptionsFunctions = mock<ILoadOptionsFunctions>();
mockRequestWithAuthentication = jest.fn();
loadOptionsFunctions.helpers.httpRequestWithAuthentication = mockRequestWithAuthentication;
loadOptionsFunctions.getCredentials.mockResolvedValue(
credentials.microsoftSharePointOAuth2Api,
);
node = new MicrosoftSharePoint();
});
afterEach(() => {
jest.resetAllMocks();
});
it('should list search files', async () => {
const mockResponse = {
'@odata.nextLink':
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/items?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
value: [
{
'@odata.etag': '"{70EC0A2F-6C3E-425F-BBE2-1D4E758F90EE},1"',
id: '01SPEVVYBPBLWHAPTML5BLXYQ5JZ2Y7EHO',
name: 'Folder1',
},
{
'@odata.etag': '"{10F06786-5AAF-434A-8A4E-3ED44DE4A987},6"',
id: '01SPEVVYEGM7YBBL22JJBYUTR62RG6JKMH',
name: 'file2.jpg',
file: {
hashes: {
quickXorHash: 'uFgaWYgAVo55sg4DIR9BTMzlmH8=',
},
irmEffectivelyEnabled: false,
irmEnabled: false,
mimeType: 'image/jpeg',
},
},
{
'@odata.etag': '"{0EC452E0-D0F7-4ECF-87D7-B738F865313B},1"',
id: '01SPEVVYHAKLCA556QZ5HIPV5XHD4GKMJ3',
name: 'file1.txt',
file: {
hashes: {
quickXorHash: 'AAAAAAAAAAAAAAAAAAAAAAAAAAA=',
},
irmEffectivelyEnabled: false,
irmEnabled: false,
mimeType: 'text/plain',
},
},
],
};
mockRequestWithAuthentication.mockReturnValue(mockResponse);
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('site');
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('folder');
const listSearchResult = await node.methods.listSearch.getFiles.call(
loadOptionsFunctions,
'file',
);
expect(mockRequestWithAuthentication).toHaveBeenCalledTimes(1);
expect(mockRequestWithAuthentication.mock.calls[0][1]).toMatchObject({
qs: {
$filter: "name eq 'file'",
},
});
expect(listSearchResult).toEqual({
results: [
{ name: 'file1.txt', value: '01SPEVVYHAKLCA556QZ5HIPV5XHD4GKMJ3' },
{ name: 'file2.jpg', value: '01SPEVVYEGM7YBBL22JJBYUTR62RG6JKMH' },
],
paginationToken:
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/items?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
});
});
it('should list search files with pagination', async () => {
const mockResponse = {
value: [
{
'@odata.etag': '"{0EC452E0-D0F7-4ECF-87D7-B738F865313B},1"',
id: '01SPEVVYHAKLCA556QZ5HIPV5XHD4GKMJ3',
name: 'file1.txt',
file: {
hashes: {
quickXorHash: 'AAAAAAAAAAAAAAAAAAAAAAAAAAA=',
},
irmEffectivelyEnabled: false,
irmEnabled: false,
mimeType: 'text/plain',
},
},
],
};
mockRequestWithAuthentication.mockReturnValue(mockResponse);
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('site');
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('folder');
const listSearchResult = await node.methods.listSearch.getFiles.call(
loadOptionsFunctions,
undefined,
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/items?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
);
expect(mockRequestWithAuthentication).toHaveBeenCalledTimes(1);
expect(mockRequestWithAuthentication.mock.calls[0][1]).toMatchObject({
url: 'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/items?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
});
expect(listSearchResult).toEqual({
results: [{ name: 'file1.txt', value: '01SPEVVYHAKLCA556QZ5HIPV5XHD4GKMJ3' }],
});
});
it('should list search folders', async () => {
const mockResponse = {
'@odata.nextLink':
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/items?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
value: [
{
'@odata.etag': '"{529A466D-D708-4857-B771-24F467546A2A},1"',
id: '01SPEVVYDNI2NFECGXK5ELO4JE6RTVI2RK',
name: 'Folder2',
folder: {
childCount: 1,
view: {},
},
},
{
'@odata.etag': '"{A3B2AE2A-2099-4194-A38B-EC7182CA3000},1"',
id: '01SPEVVYBKV2ZKHGJASRA2HC7MOGBMUMAA',
name: 'Folder1',
folder: {
childCount: 7,
view: {},
},
},
{
'@odata.etag': '"{A6EF0C5E-0248-482A-AD79-0EFDB6622473},1"',
id: '01SPEVVYC6BTX2MSACFJEK26IO7W3GEJDT',
name: 'file.txt',
},
],
};
mockRequestWithAuthentication.mockReturnValue(mockResponse);
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('site');
const listSearchResult = await node.methods.listSearch.getFolders.call(
loadOptionsFunctions,
'folder',
);
expect(mockRequestWithAuthentication).toHaveBeenCalledTimes(1);
expect(mockRequestWithAuthentication.mock.calls[0][1]).toMatchObject({
qs: {
$filter: "name eq 'folder'",
},
});
expect(listSearchResult).toEqual({
results: [
{
name: 'Folder1',
value: '01SPEVVYBKV2ZKHGJASRA2HC7MOGBMUMAA',
},
{
name: 'Folder2',
value: '01SPEVVYDNI2NFECGXK5ELO4JE6RTVI2RK',
},
],
paginationToken:
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/items?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
});
});
it('should list search folders with pagination', async () => {
const mockResponse = {
value: [
{
'@odata.etag': '"{A3B2AE2A-2099-4194-A38B-EC7182CA3000},1"',
id: '01SPEVVYBKV2ZKHGJASRA2HC7MOGBMUMAA',
name: 'Folder1',
folder: {
childCount: 7,
view: {},
},
},
],
};
mockRequestWithAuthentication.mockReturnValue(mockResponse);
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('site');
const listSearchResult = await node.methods.listSearch.getFolders.call(
loadOptionsFunctions,
undefined,
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/items?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
);
expect(mockRequestWithAuthentication).toHaveBeenCalledTimes(1);
expect(mockRequestWithAuthentication.mock.calls[0][1]).toMatchObject({
url: 'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/items?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
});
expect(listSearchResult).toEqual({
results: [
{
name: 'Folder1',
value: '01SPEVVYBKV2ZKHGJASRA2HC7MOGBMUMAA',
},
],
});
});
it('should list search items', async () => {
const mockResponse = {
'@odata.nextLink':
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/listItems?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
value: [
{
'@odata.etag': '"98af0386-66bd-4524-a653-80be05e0f14d,2"',
id: '2',
'fields@odata.navigationLink': 'fields',
fields: {
'@odata.etag': '"98af0386-66bd-4524-a653-80be05e0f14d,2"',
Title: 'Title 2',
},
},
{
'@odata.etag': '"0ea4148a-f8e5-4f2f-a815-2e2be693b164,4"',
id: '1',
'fields@odata.navigationLink': 'fields',
fields: {
'@odata.etag': '"0ea4148a-f8e5-4f2f-a815-2e2be693b164,4"',
Title: 'Title 1',
},
},
],
};
mockRequestWithAuthentication.mockReturnValue(mockResponse);
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('site');
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('list');
const listSearchResult = await node.methods.listSearch.getItems.call(
loadOptionsFunctions,
'Title',
);
expect(mockRequestWithAuthentication).toHaveBeenCalledTimes(1);
expect(mockRequestWithAuthentication.mock.calls[0][1]).toMatchObject({
qs: {
$filter: "fields/Title eq 'Title'",
},
});
expect(listSearchResult).toEqual({
results: [
{
name: 'Title 1',
value: '1',
},
{
name: 'Title 2',
value: '2',
},
],
paginationToken:
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/listItems?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
});
});
it('should list search items with pagination', async () => {
const mockResponse = {
value: [
{
'@odata.etag': '"0ea4148a-f8e5-4f2f-a815-2e2be693b164,4"',
id: '1',
'fields@odata.navigationLink': 'fields',
fields: {
'@odata.etag': '"0ea4148a-f8e5-4f2f-a815-2e2be693b164,4"',
},
},
],
};
mockRequestWithAuthentication.mockReturnValue(mockResponse);
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('site');
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('list');
const listSearchResult = await node.methods.listSearch.getItems.call(
loadOptionsFunctions,
undefined,
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/listItems?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
);
expect(mockRequestWithAuthentication).toHaveBeenCalledTimes(1);
expect(mockRequestWithAuthentication.mock.calls[0][1]).toMatchObject({
url: 'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/listItems?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
});
expect(listSearchResult).toEqual({
results: [
{
name: '1',
value: '1',
},
],
});
});
it('should list search lists', async () => {
const mockResponse = {
'@odata.nextLink':
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/lists?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
value: [
{
'@odata.etag': '"58a279af-1f06-4392-a5ed-2b37fa1d6c1d,5"',
id: '58a279af-1f06-4392-a5ed-2b37fa1d6c1d',
displayName: 'List 2',
},
{
'@odata.etag': '"23af565a-da89-48f0-ae5f-2d4a7244b446,0"',
id: '23af565a-da89-48f0-ae5f-2d4a7244b446',
displayName: 'List 1',
},
],
};
mockRequestWithAuthentication.mockReturnValue(mockResponse);
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('site');
const listSearchResult = await node.methods.listSearch.getLists.call(
loadOptionsFunctions,
'List',
);
expect(mockRequestWithAuthentication).toHaveBeenCalledTimes(1);
expect(mockRequestWithAuthentication.mock.calls[0][1]).toMatchObject({
qs: {
$filter: "displayName eq 'List'",
},
});
expect(listSearchResult).toEqual({
results: [
{
name: 'List 1',
value: '23af565a-da89-48f0-ae5f-2d4a7244b446',
},
{
name: 'List 2',
value: '58a279af-1f06-4392-a5ed-2b37fa1d6c1d',
},
],
paginationToken:
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/lists?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
});
});
it('should list search lists with pagination', async () => {
const mockResponse = {
value: [
{
'@odata.etag': '"23af565a-da89-48f0-ae5f-2d4a7244b446,0"',
id: '23af565a-da89-48f0-ae5f-2d4a7244b446',
displayName: 'List 1',
},
],
};
mockRequestWithAuthentication.mockReturnValue(mockResponse);
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('site');
const listSearchResult = await node.methods.listSearch.getLists.call(
loadOptionsFunctions,
undefined,
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/lists?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
);
expect(mockRequestWithAuthentication).toHaveBeenCalledTimes(1);
expect(mockRequestWithAuthentication.mock.calls[0][1]).toMatchObject({
url: 'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/lists?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
});
expect(listSearchResult).toEqual({
results: [
{
name: 'List 1',
value: '23af565a-da89-48f0-ae5f-2d4a7244b446',
},
],
});
});
it('should list search sites', async () => {
const mockResponse = {
'@odata.nextLink':
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/sites?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
value: [
{
id: 'mydomain.sharepoint.com,cf38a104-c767-48c7-93d0-c093e3909c78,3abe66fd-ec23-469f-abc6-332e3a95bf75',
title: 'Site 2',
},
{
id: 'mydomain.sharepoint.com,3286a459-bc45-4aab-8200-b9ba7edcca96,3abe66fd-ec23-469f-abc6-332e3a95bf75',
title: 'Site 1',
},
],
};
mockRequestWithAuthentication.mockReturnValue(mockResponse);
const listSearchResult = await node.methods.listSearch.getSites.call(
loadOptionsFunctions,
'Site',
);
expect(mockRequestWithAuthentication).toHaveBeenCalledTimes(1);
expect(mockRequestWithAuthentication.mock.calls[0][1]).toMatchObject({
qs: {
$search: 'Site',
},
});
expect(listSearchResult).toEqual({
results: [
{
name: 'Site 1',
value:
'mydomain.sharepoint.com,3286a459-bc45-4aab-8200-b9ba7edcca96,3abe66fd-ec23-469f-abc6-332e3a95bf75',
},
{
name: 'Site 2',
value:
'mydomain.sharepoint.com,cf38a104-c767-48c7-93d0-c093e3909c78,3abe66fd-ec23-469f-abc6-332e3a95bf75',
},
],
paginationToken:
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/sites?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
});
});
it('should list search sites and pagination', async () => {
const mockResponse = {
value: [
{
id: 'mydomain.sharepoint.com,3286a459-bc45-4aab-8200-b9ba7edcca96,3abe66fd-ec23-469f-abc6-332e3a95bf75',
title: 'Site 1',
},
],
};
mockRequestWithAuthentication.mockReturnValue(mockResponse);
const listSearchResult = await node.methods.listSearch.getSites.call(
loadOptionsFunctions,
undefined,
'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/sites?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
);
expect(mockRequestWithAuthentication).toHaveBeenCalledTimes(1);
expect(mockRequestWithAuthentication.mock.calls[0][1]).toMatchObject({
url: 'https://mydomain.sharepoint.com/_api/v2.0/sites(%27mydomain.sharepoint.com,site1%27)/sites?%24skiptoken=aWQ9MjFFQkEzOUMtMkU3My00NzgwLUFBQzEtMTVDNzlDMTk4QjlB',
});
expect(listSearchResult).toEqual({
results: [
{
name: 'Site 1',
value:
'mydomain.sharepoint.com,3286a459-bc45-4aab-8200-b9ba7edcca96,3abe66fd-ec23-469f-abc6-332e3a95bf75',
},
],
});
});
});
});

View File

@@ -0,0 +1,886 @@
import type { MockProxy } from 'jest-mock-extended';
import { mock } from 'jest-mock-extended';
import type { ILoadOptionsFunctions } from 'n8n-workflow';
import { getMappingColumns } from '../../methods/resourceMapping';
describe('Microsoft SharePoint Node', () => {
describe('Resource mapping', () => {
let loadOptionsFunctions: MockProxy<ILoadOptionsFunctions>;
beforeEach(() => {
loadOptionsFunctions = mock<ILoadOptionsFunctions>();
});
afterEach(() => {
jest.resetAllMocks();
});
it('should map columns', async () => {
loadOptionsFunctions.getCredentials.mockResolvedValue({});
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('site');
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('list');
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('create');
const mockResponse = {
value: [
{
'@odata.etag': '"0"',
id: '0x0100362657F7588C5C438072A77E0EF184F4000272C0D1046D984B8097B3C00D199EDE',
description: 'Create a new list item.',
eTag: '"0"',
group: 'List Content Types',
hidden: false,
name: 'Item',
parentId: '0x01',
readOnly: false,
sealed: false,
columns: [
{
displayName: 'Title',
'@odata.etag': '"1"',
columnGroup: 'Custom Columns',
customFormatter: '',
description: 'Description Title',
enforceUniqueValues: true,
eTag: '"1"',
hidden: false,
id: 'fa564e0f-0c70-4ab9-b863-0177e6ddd247',
indexed: true,
isDeletable: false,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'Title',
readOnly: false,
required: true,
type: 'text',
default: '',
text: {
allowMultipleLines: false,
appendChangesToExistingText: false,
autoHyperLink: true,
linesForEditing: 0,
maxLength: 255,
},
validation: {
defaultLanguage: 'en-US',
descriptions: [
{
languageTag: 'en-US',
},
],
},
},
{
displayName: 'Othertitle',
'@odata.etag': '"0"',
columnGroup: 'Custom Columns',
description: 'Descriptio Othertitle',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: '82642ec8-ef9b-478f-acf9-31f7d45fbc31',
indexed: false,
isDeletable: false,
isReorderable: false,
isSealed: false,
propagateChanges: false,
name: 'LinkTitle',
readOnly: true,
type: 'unknownFutureValue',
default: '',
},
{
displayName: 'Choice',
'@odata.etag': '"2"',
columnGroup: 'Custom Columns',
customFormatter:
'{"elmType":"div","style":{"flex-wrap":"wrap","display":"flex"},"children":[{"elmType":"div","style":{"box-sizing":"border-box","padding":"4px 8px 5px 8px","overflow":"hidden","text-overflow":"ellipsis","display":"flex","border-radius":"16px","height":"24px","align-items":"center","white-space":"nowrap","margin":"4px 4px 4px 4px"},"attributes":{"class":{"operator":":","operands":[{"operator":"==","operands":["[$choice]","Choice 1"]},"sp-css-backgroundColor-BgCornflowerBlue sp-css-color-CornflowerBlueFont",{"operator":":","operands":[{"operator":"==","operands":["[$choice]","Choice 2"]},"sp-css-backgroundColor-BgMintGreen sp-css-color-MintGreenFont",{"operator":":","operands":[{"operator":"==","operands":["[$choice]","Choice 3"]},"sp-css-backgroundColor-BgGold sp-css-color-GoldFont",{"operator":":","operands":[{"operator":"==","operands":["[$choice]",""]},"","sp-field-borderAllRegular sp-field-borderAllSolid sp-css-borderColor-neutralSecondary"]}]}]}]}},"children":[{"elmType":"span","style":{"overflow":"hidden","text-overflow":"ellipsis","padding":"0 3px"},"txtContent":"[$choice]","attributes":{"class":{"operator":":","operands":[{"operator":"==","operands":["[$choice]","Choice 1"]},"sp-css-color-CornflowerBlueFont",{"operator":":","operands":[{"operator":"==","operands":["[$choice]","Choice 2"]},"sp-css-color-MintGreenFont",{"operator":":","operands":[{"operator":"==","operands":["[$choice]","Choice 3"]},"sp-css-color-GoldFont",{"operator":":","operands":[{"operator":"==","operands":["[$choice]",""]},"",""]}]}]}]}}}]}],"templateId":"BgColorChoicePill"}',
description: 'Description Choice',
enforceUniqueValues: false,
eTag: '"2"',
hidden: false,
id: '21d4577a-e5f2-461d-a9cf-f7956c502f4e',
indexed: false,
isDeletable: true,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'choice',
readOnly: false,
type: 'choice',
default: '',
choice: {
allowTextEntry: false,
choices: ['Choice 1', 'Choice 2', 'Choice 3'],
displayAs: 'dropDownMenu',
},
validation: {
defaultLanguage: 'en-US',
descriptions: [
{
languageTag: 'en-US',
},
],
},
},
{
displayName: 'Datetime',
'@odata.etag': '"0"',
columnGroup: 'Custom Columns',
description: 'Description Datetime',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: '7e2cf00a-1df6-4c1c-8ea9-d92ef3c7760e',
indexed: false,
isDeletable: true,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'datetime',
readOnly: false,
type: 'dateTime',
default: '',
dateTime: {
displayAs: 'standard',
format: 'dateOnly',
},
validation: {
defaultLanguage: 'en-US',
descriptions: [
{
languageTag: 'en-US',
},
],
},
},
{
displayName: 'Person',
'@odata.etag': '"0"',
columnGroup: 'Custom Columns',
description: 'Description Person',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: '574f4483-ec83-41a0-b772-67b331695c56',
indexed: false,
isDeletable: true,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'person',
readOnly: false,
type: 'user',
default: '',
personOrGroup: {
allowMultipleSelection: false,
displayAs: 'nameWithPresence',
format: 'peopleOnly',
hasPrefix: false,
noLookupFieldHeader: false,
},
},
{
displayName: 'Number',
'@odata.etag': '"2"',
columnGroup: 'Custom Columns',
description: 'Description Number',
enforceUniqueValues: false,
eTag: '"2"',
hidden: false,
id: 'c69c2fc9-b6fd-4a08-8750-a293b7c888a3',
indexed: false,
isDeletable: true,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'number',
readOnly: false,
type: 'number',
default: 0,
number: {
decimalPlaces: 'automatic',
displayAs: 'number',
maximum: 1.7976931348623157e308,
minimum: -1.7976931348623157e308,
},
validation: {
defaultLanguage: 'en-US',
descriptions: [
{
languageTag: 'en-US',
},
],
},
},
{
displayName: 'Bool',
'@odata.etag': '"0"',
columnGroup: 'Custom Columns',
description: 'Whether Description Bool',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: '955880c3-8c95-4609-93ef-cdbd2deef1b2',
indexed: false,
isDeletable: true,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'bool',
readOnly: false,
type: 'boolean',
default: false,
boolean: {},
defaultValue: {
value: '1',
},
},
{
displayName: 'Hyperlink',
'@odata.etag': '"2"',
columnGroup: 'Custom Columns',
description: 'Description Hyperlink',
enforceUniqueValues: false,
eTag: '"2"',
hidden: false,
id: 'a6352b41-95e7-4cbf-9184-aae4fe92d865',
indexed: false,
isDeletable: true,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'hyperlink',
readOnly: false,
type: 'url',
default: '',
hyperlinkOrPicture: {
isPicture: false,
},
},
{
displayName: 'Currency',
'@odata.etag': '"0"',
columnGroup: 'Custom Columns',
description: 'Description Currency',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: '40d9b8f9-05e0-4105-bc35-0c969eeb0096',
indexed: false,
isDeletable: true,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'currency',
readOnly: false,
type: 'currency',
default: '',
currency: {
decimalPlaces: 'automatic',
displayAs: 'number',
locale: 'en-US',
maximum: 1.7976931348623157e308,
minimum: -1.7976931348623157e308,
},
validation: {
defaultLanguage: 'en-US',
descriptions: [
{
languageTag: 'en-US',
},
],
},
},
{
displayName: 'Location',
'@odata.etag': '"0"',
columnGroup: 'Custom Columns',
description: 'Description Location',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: '5bfb0a2c-04ed-4a59-ae6e-de0d97c8352b',
indexed: false,
isDeletable: true,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'location',
readOnly: false,
type: 'location',
default: '',
location: {},
},
{
displayName: 'location: Country/Region',
'@odata.etag': '"0"',
columnGroup: 'Custom Columns',
description: 'Description Location: Country/Region',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: 'db61a63e-558b-4e41-b895-2da2f40a7a23',
indexed: false,
isDeletable: true,
isReorderable: false,
isSealed: true,
propagateChanges: false,
name: 'CountryOrRegion',
readOnly: true,
type: 'text',
default: '',
text: {
allowMultipleLines: false,
appendChangesToExistingText: false,
autoHyperLink: false,
linesForEditing: 0,
maxLength: 255,
},
validation: {
defaultLanguage: 'en-US',
descriptions: [
{
languageTag: 'en-US',
},
],
},
},
{
displayName: 'location: State',
'@odata.etag': '"0"',
columnGroup: 'Custom Columns',
description: 'Description Location: State',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: 'c24ae779-ee80-4e8c-b291-c716f1fdce66',
indexed: false,
isDeletable: true,
isReorderable: false,
isSealed: true,
propagateChanges: false,
name: 'State',
readOnly: true,
type: 'text',
default: '',
text: {
allowMultipleLines: false,
appendChangesToExistingText: false,
autoHyperLink: false,
linesForEditing: 0,
maxLength: 255,
},
validation: {
defaultLanguage: 'en-US',
descriptions: [
{
languageTag: 'en-US',
},
],
},
},
{
displayName: 'location: City',
'@odata.etag': '"0"',
columnGroup: 'Custom Columns',
description: 'Description Location: City',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: '7fb3c8e7-8a8c-4488-a768-4db6922b53f4',
indexed: false,
isDeletable: true,
isReorderable: false,
isSealed: true,
propagateChanges: false,
name: 'City',
readOnly: true,
type: 'text',
default: '',
text: {
allowMultipleLines: false,
appendChangesToExistingText: false,
autoHyperLink: false,
linesForEditing: 0,
maxLength: 255,
},
validation: {
defaultLanguage: 'en-US',
descriptions: [
{
languageTag: 'en-US',
},
],
},
},
{
displayName: 'location: Postal Code',
'@odata.etag': '"0"',
columnGroup: 'Custom Columns',
description: 'Description Location: Postal Code',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: '1fa93efa-579f-48cb-b1e3-f2a8fdb615fe',
indexed: false,
isDeletable: true,
isReorderable: false,
isSealed: true,
propagateChanges: false,
name: 'PostalCode',
readOnly: true,
type: 'text',
default: '',
text: {
allowMultipleLines: false,
appendChangesToExistingText: false,
autoHyperLink: false,
linesForEditing: 0,
maxLength: 255,
},
validation: {
defaultLanguage: 'en-US',
descriptions: [
{
languageTag: 'en-US',
},
],
},
},
{
displayName: 'location: Street',
'@odata.etag': '"0"',
columnGroup: 'Custom Columns',
description: 'Description Location: Street',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: '1ce8048e-a619-40fb-86b2-c5963c0a7526',
indexed: false,
isDeletable: true,
isReorderable: false,
isSealed: true,
propagateChanges: false,
name: 'Street',
readOnly: true,
type: 'text',
default: '',
text: {
allowMultipleLines: false,
appendChangesToExistingText: false,
autoHyperLink: false,
linesForEditing: 0,
maxLength: 255,
},
validation: {
defaultLanguage: 'en-US',
descriptions: [
{
languageTag: 'en-US',
},
],
},
},
{
displayName: 'location: Coordinates',
'@odata.etag': '"0"',
columnGroup: 'Custom Columns',
description: 'Description Location: Coordinates',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: '079b0670-2a3d-4a71-abe5-c0023a66879d',
indexed: false,
isDeletable: true,
isReorderable: false,
isSealed: true,
propagateChanges: false,
name: 'GeoLoc',
readOnly: true,
type: 'geolocation',
default: '',
geolocation: {},
},
{
displayName: 'location: Name',
'@odata.etag': '"0"',
columnGroup: 'Custom Columns',
description: 'Description Location: Name',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: '73a8bcce-484b-4fd6-84be-47ef648c9c45',
indexed: false,
isDeletable: true,
isReorderable: false,
isSealed: true,
propagateChanges: false,
name: 'DispName',
readOnly: true,
type: 'text',
default: '',
text: {
allowMultipleLines: false,
appendChangesToExistingText: false,
autoHyperLink: false,
linesForEditing: 0,
maxLength: 255,
},
validation: {
defaultLanguage: 'en-US',
descriptions: [
{
languageTag: 'en-US',
},
],
},
},
{
displayName: 'Image',
'@odata.etag': '"0"',
columnGroup: 'Custom Columns',
description: 'Description Location: Image',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: '2a485bec-bab9-493b-9214-2be0b8566a25',
indexed: false,
isDeletable: true,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'image',
readOnly: false,
type: 'thumbnail',
default: '',
thumbnail: {},
},
{
displayName: 'Metadata',
'@odata.etag': '"2"',
columnGroup: 'Custom Columns',
customFormatter: '',
description: 'Description Location: Metadata',
enforceUniqueValues: false,
eTag: '"2"',
hidden: false,
id: '2d8cb8ec-4a8f-43ae-87fa-e832b4631f0d',
indexed: false,
isDeletable: true,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'metadata',
readOnly: false,
staticName: 'metadata',
type: 'term',
default: '',
defaultValue: {
value: '',
},
term: {
allowMultipleValues: false,
showFullyQualifiedName: false,
},
},
{
displayName: 'Lookup',
'@odata.etag': '"2"',
columnGroup: 'Custom Columns',
description: 'Description Lookup',
enforceUniqueValues: false,
eTag: '"2"',
hidden: false,
id: '44bdab3a-ac89-4b40-acfd-707510f93719',
indexed: false,
isDeletable: true,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'lookup',
readOnly: false,
type: 'lookup',
default: '',
lookup: {
allowMultipleValues: false,
allowUnlimitedLength: false,
columnName: 'Title',
displayFormUrl:
'https://mydomain.sharepoint.com/sites/n8ntest10/_layouts/15/listform.aspx?PageType=4&ListId=58a279af-1f06-4392-a5ed-2b37fa1d6c1d',
listId: '58a279af-1f06-4392-a5ed-2b37fa1d6c1d',
},
},
{
displayName: 'Rating (0-5)',
'@odata.etag': '"1"',
columnGroup: 'Content Feedback',
description: 'Average value of all the ratings that have been submitted',
enforceUniqueValues: false,
eTag: '"1"',
hidden: false,
id: '5a14d1ab-1513-48c7-97b3-657a5ba6c742',
indexed: false,
isDeletable: true,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'AverageRating',
readOnly: false,
type: 'unknownFutureValue',
default: '',
},
{
displayName: 'Number of Ratings',
'@odata.etag': '"0"',
columnGroup: 'Content Feedback',
description: 'Number of ratings submitted',
enforceUniqueValues: false,
eTag: '"0"',
hidden: false,
id: 'b1996002-9167-45e5-a4df-b2c41c6723c7',
indexed: false,
isDeletable: true,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'RatingCount',
readOnly: false,
type: 'unknownFutureValue',
default: '',
},
{
displayName: 'Number of Likes',
'@odata.etag': '"1"',
columnGroup: 'Content Feedback',
description: 'Description Number of Likes',
enforceUniqueValues: false,
eTag: '"1"',
hidden: false,
id: '6e4d832b-f610-41a8-b3e0-239608efda41',
indexed: false,
isDeletable: true,
isReorderable: true,
isSealed: false,
propagateChanges: false,
name: 'LikesCount',
readOnly: false,
type: 'unknownFutureValue',
default: '',
},
],
},
],
};
loadOptionsFunctions.helpers.httpRequestWithAuthentication = jest
.fn()
.mockReturnValue(mockResponse);
const fields = await getMappingColumns.call(loadOptionsFunctions);
expect(fields).toEqual({
fields: [
{
id: 'Title',
canBeUsedToMatch: true,
defaultMatch: false,
display: true,
displayName: 'Title',
readOnly: false,
required: true,
type: 'string',
},
{
id: 'choice',
canBeUsedToMatch: false,
defaultMatch: false,
display: true,
displayName: 'Choice',
readOnly: false,
required: undefined,
type: 'options',
options: [
{
name: 'Choice 1',
value: 'Choice 1',
},
{
name: 'Choice 2',
value: 'Choice 2',
},
{
name: 'Choice 3',
value: 'Choice 3',
},
],
},
{
id: 'datetime',
canBeUsedToMatch: false,
defaultMatch: false,
display: true,
displayName: 'Datetime',
readOnly: false,
required: undefined,
type: 'dateTime',
},
{
id: 'person',
canBeUsedToMatch: false,
defaultMatch: false,
display: true,
displayName: 'Person',
readOnly: false,
required: undefined,
type: 'string',
},
{
id: 'number',
canBeUsedToMatch: false,
defaultMatch: false,
display: true,
displayName: 'Number',
readOnly: false,
required: undefined,
type: 'number',
},
{
id: 'bool',
canBeUsedToMatch: false,
defaultMatch: false,
display: true,
displayName: 'Bool',
readOnly: false,
required: undefined,
type: 'boolean',
},
{
id: 'hyperlink',
canBeUsedToMatch: false,
defaultMatch: false,
display: true,
displayName: 'Hyperlink',
readOnly: true,
required: undefined,
type: undefined,
},
{
id: 'currency',
canBeUsedToMatch: false,
defaultMatch: false,
display: true,
displayName: 'Currency',
readOnly: false,
required: undefined,
type: 'number',
},
{
id: 'location',
canBeUsedToMatch: false,
defaultMatch: false,
display: true,
displayName: 'Location',
readOnly: true,
required: undefined,
type: undefined,
},
{
id: 'image',
canBeUsedToMatch: false,
defaultMatch: false,
display: true,
displayName: 'Image',
readOnly: false,
required: undefined,
type: 'object',
},
{
id: 'metadata',
canBeUsedToMatch: false,
defaultMatch: false,
display: true,
displayName: 'Metadata',
readOnly: true,
required: undefined,
type: undefined,
},
{
id: 'lookup',
canBeUsedToMatch: false,
defaultMatch: false,
display: true,
displayName: 'Lookup',
readOnly: false,
required: undefined,
type: 'string',
},
{
id: 'AverageRating',
canBeUsedToMatch: false,
defaultMatch: false,
display: true,
displayName: 'Rating (0-5)',
readOnly: false,
required: undefined,
type: 'number',
},
{
id: 'RatingCount',
canBeUsedToMatch: false,
defaultMatch: false,
display: true,
displayName: 'Number of Ratings',
readOnly: false,
required: undefined,
type: 'number',
},
{
id: 'LikesCount',
canBeUsedToMatch: false,
defaultMatch: false,
display: true,
displayName: 'Number of Likes',
readOnly: false,
required: undefined,
type: 'number',
},
],
});
});
it('should map columns with id for update', async () => {
loadOptionsFunctions.getCredentials.mockResolvedValue({});
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('site');
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('list');
loadOptionsFunctions.getNodeParameter.mockReturnValueOnce('update');
const mockResponse = {
value: [
{
columns: [],
},
],
};
loadOptionsFunctions.helpers.httpRequestWithAuthentication = jest
.fn()
.mockReturnValue(mockResponse);
const fields = await getMappingColumns.call(loadOptionsFunctions);
expect(fields).toEqual({
fields: [
{
id: 'id',
canBeUsedToMatch: true,
defaultMatch: false,
display: true,
displayName: 'ID',
readOnly: true,
required: true,
type: 'string',
},
],
});
});
});
});

View File

@@ -0,0 +1,37 @@
import type {
IDataObject,
IExecuteFunctions,
IExecuteSingleFunctions,
IHttpRequestMethods,
IHttpRequestOptions,
ILoadOptionsFunctions,
} from 'n8n-workflow';
export async function microsoftSharePointApiRequest(
this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
method: IHttpRequestMethods,
endpoint: string,
body: IDataObject | Buffer = {},
qs?: IDataObject,
headers?: IDataObject,
url?: string,
): Promise<any> {
const credentials: { subdomain: string } = await this.getCredentials(
'microsoftSharePointOAuth2Api',
);
const options: IHttpRequestOptions = {
method,
url: url ?? `https://${credentials.subdomain}.sharepoint.com/_api/v2.0${endpoint}`,
json: true,
headers,
body,
qs,
};
return await this.helpers.httpRequestWithAuthentication.call(
this,
'microsoftSharePointOAuth2Api',
options,
);
}

View File

@@ -652,6 +652,7 @@
"dist/nodes/Microsoft/OneDrive/MicrosoftOneDriveTrigger.node.js",
"dist/nodes/Microsoft/Outlook/MicrosoftOutlook.node.js",
"dist/nodes/Microsoft/Outlook/MicrosoftOutlookTrigger.node.js",
"dist/nodes/Microsoft/SharePoint/MicrosoftSharePoint.node.js",
"dist/nodes/Microsoft/Sql/MicrosoftSql.node.js",
"dist/nodes/Microsoft/Storage/AzureStorage.node.js",
"dist/nodes/Microsoft/Teams/MicrosoftTeams.node.js",