mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
feat(Google Chat Node): Updates (#12827)
Co-authored-by: Dana <152518854+dana-gill@users.noreply.github.com>
This commit is contained in:
parent
de49c23971
commit
e146ad021a
|
@ -0,0 +1,26 @@
|
|||
import type { ICredentialType, INodeProperties } from 'n8n-workflow';
|
||||
|
||||
const scopes = [
|
||||
'https://www.googleapis.com/auth/chat.spaces',
|
||||
'https://www.googleapis.com/auth/chat.messages',
|
||||
'https://www.googleapis.com/auth/chat.memberships',
|
||||
];
|
||||
|
||||
export class GoogleChatOAuth2Api implements ICredentialType {
|
||||
name = 'googleChatOAuth2Api';
|
||||
|
||||
extends = ['googleOAuth2Api'];
|
||||
|
||||
displayName = 'Chat OAuth2 API';
|
||||
|
||||
documentationUrl = 'google/oauth-single-service';
|
||||
|
||||
properties: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Scope',
|
||||
name: 'scope',
|
||||
type: 'hidden',
|
||||
default: scopes.join(' '),
|
||||
},
|
||||
];
|
||||
}
|
|
@ -9,48 +9,70 @@ import type {
|
|||
} from 'n8n-workflow';
|
||||
import { NodeApiError } from 'n8n-workflow';
|
||||
|
||||
import { getSendAndWaitConfig } from '../../../utils/sendAndWait/utils';
|
||||
import { getGoogleAccessToken } from '../GenericFunctions';
|
||||
|
||||
async function googleServiceAccountApiRequest(
|
||||
this: IExecuteFunctions | ILoadOptionsFunctions,
|
||||
options: IRequestOptions,
|
||||
noCredentials = false,
|
||||
): Promise<any> {
|
||||
if (noCredentials) {
|
||||
return await this.helpers.request(options);
|
||||
}
|
||||
|
||||
const credentials = await this.getCredentials('googleApi');
|
||||
|
||||
const { access_token } = await getGoogleAccessToken.call(this, credentials, 'chat');
|
||||
options.headers!.Authorization = `Bearer ${access_token}`;
|
||||
|
||||
return await this.helpers.request(options);
|
||||
}
|
||||
|
||||
export async function googleApiRequest(
|
||||
this: IExecuteFunctions | ILoadOptionsFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
resource: string,
|
||||
|
||||
body: any = {},
|
||||
body: IDataObject = {},
|
||||
qs: IDataObject = {},
|
||||
uri?: string,
|
||||
noCredentials = false,
|
||||
encoding?: null | undefined,
|
||||
): Promise<any> {
|
||||
) {
|
||||
const options: IRequestOptions = {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
method,
|
||||
body,
|
||||
qs,
|
||||
uri: uri || `https://chat.googleapis.com${resource}`,
|
||||
qsStringifyOptions: {
|
||||
arrayFormat: 'repeat',
|
||||
},
|
||||
json: true,
|
||||
};
|
||||
|
||||
if (Object.keys(body as IDataObject).length === 0) {
|
||||
delete options.body;
|
||||
}
|
||||
|
||||
if (encoding === null) {
|
||||
options.encoding = null;
|
||||
}
|
||||
|
||||
let responseData: IDataObject | undefined;
|
||||
try {
|
||||
if (noCredentials) {
|
||||
responseData = await this.helpers.request(options);
|
||||
} else {
|
||||
const credentials = await this.getCredentials('googleApi');
|
||||
if (Object.keys(body).length === 0) {
|
||||
delete options.body;
|
||||
}
|
||||
|
||||
const { access_token } = await getGoogleAccessToken.call(this, credentials, 'chat');
|
||||
options.headers!.Authorization = `Bearer ${access_token}`;
|
||||
responseData = await this.helpers.request(options);
|
||||
let responseData;
|
||||
|
||||
try {
|
||||
if (noCredentials || this.getNodeParameter('authentication', 0) === 'serviceAccount') {
|
||||
responseData = await googleServiceAccountApiRequest.call(this, options, noCredentials);
|
||||
} else {
|
||||
responseData = await this.helpers.requestWithAuthentication.call(
|
||||
this,
|
||||
'googleChatOAuth2Api',
|
||||
options,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.code === 'ERR_OSSL_PEM_NO_START_LINE') {
|
||||
|
@ -59,6 +81,7 @@ export async function googleApiRequest(
|
|||
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
|
||||
if (Object.keys(responseData as IDataObject).length !== 0) {
|
||||
return responseData;
|
||||
} else {
|
||||
|
@ -134,3 +157,26 @@ export function getPagingParameters(resource: string, operation = 'getAll') {
|
|||
];
|
||||
return pagingParameters;
|
||||
}
|
||||
|
||||
export function createSendAndWaitMessageBody(context: IExecuteFunctions) {
|
||||
const config = getSendAndWaitConfig(context);
|
||||
|
||||
const instanceId = context.getInstanceId();
|
||||
const attributionText = '_This_ _message_ _was_ _sent_ _automatically_ _with_';
|
||||
const link = `https://n8n.io/?utm_source=n8n-internal&utm_medium=powered_by&utm_campaign=${encodeURIComponent(
|
||||
'n8n-nodes-base.telegram',
|
||||
)}${instanceId ? '_' + instanceId : ''}`;
|
||||
const attribution = `${attributionText} _<${link}|n8n>_`;
|
||||
|
||||
const buttons: string[] = config.options.map(
|
||||
(option) => `*<${`${config.url}?approved=${option.value}`}|${option.label}>*`,
|
||||
);
|
||||
|
||||
const text = `${config.message}\n\n\n${buttons.join(' ')}\n\n${attribution}`;
|
||||
|
||||
const body = {
|
||||
text,
|
||||
};
|
||||
|
||||
return body;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
"node": "n8n-nodes-base.googleChat",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Communication"],
|
||||
"categories": ["Communication", "HILT"],
|
||||
"subcategories": {
|
||||
"HILT": ["Human in the Loop"]
|
||||
},
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@ import type {
|
|||
INodeTypeDescription,
|
||||
IRequestOptions,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeConnectionType, NodeOperationError } from 'n8n-workflow';
|
||||
import { NodeConnectionType, NodeOperationError, SEND_AND_WAIT_OPERATION } from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
// attachmentFields,
|
||||
|
@ -27,10 +27,22 @@ import {
|
|||
messageFields,
|
||||
messageOperations,
|
||||
spaceFields,
|
||||
spaceIdProperty,
|
||||
spaceOperations,
|
||||
} from './descriptions';
|
||||
import { googleApiRequest, googleApiRequestAllItems, validateJSON } from './GenericFunctions';
|
||||
import {
|
||||
createSendAndWaitMessageBody,
|
||||
googleApiRequest,
|
||||
googleApiRequestAllItems,
|
||||
validateJSON,
|
||||
} from './GenericFunctions';
|
||||
import type { IMessage, IMessageUi } from './MessageInterface';
|
||||
import { sendAndWaitWebhooksDescription } from '../../../utils/sendAndWait/descriptions';
|
||||
import {
|
||||
configureWaitTillDate,
|
||||
getSendAndWaitProperties,
|
||||
sendAndWaitWebhook,
|
||||
} from '../../../utils/sendAndWait/utils';
|
||||
|
||||
export class GoogleChat implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
|
@ -46,14 +58,46 @@ export class GoogleChat implements INodeType {
|
|||
},
|
||||
inputs: [NodeConnectionType.Main],
|
||||
outputs: [NodeConnectionType.Main],
|
||||
webhooks: sendAndWaitWebhooksDescription,
|
||||
credentials: [
|
||||
{
|
||||
name: 'googleApi',
|
||||
required: true,
|
||||
testedBy: 'testGoogleTokenAuth',
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: ['serviceAccount'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'googleChatOAuth2Api',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
authentication: ['oAuth2'],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Authentication',
|
||||
name: 'authentication',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
// eslint-disable-next-line n8n-nodes-base/node-param-display-name-miscased
|
||||
name: 'OAuth2 (recommended)',
|
||||
value: 'oAuth2',
|
||||
},
|
||||
{
|
||||
name: 'Service Account',
|
||||
value: 'serviceAccount',
|
||||
},
|
||||
],
|
||||
default: 'serviceAccount',
|
||||
},
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
|
@ -100,9 +144,16 @@ export class GoogleChat implements INodeType {
|
|||
...messageFields,
|
||||
...spaceOperations,
|
||||
...spaceFields,
|
||||
...getSendAndWaitProperties([spaceIdProperty], 'message', undefined, {
|
||||
noButtonStyle: true,
|
||||
defaultApproveLabel: '✅ Approve',
|
||||
defaultDisapproveLabel: '❌ Decline',
|
||||
}).filter((p) => p.name !== 'subject'),
|
||||
],
|
||||
};
|
||||
|
||||
webhook = sendAndWaitWebhook;
|
||||
|
||||
methods = {
|
||||
loadOptions: {
|
||||
// Get all the spaces to display them to user so that they can
|
||||
|
@ -196,6 +247,19 @@ export class GoogleChat implements INodeType {
|
|||
let responseData;
|
||||
const resource = this.getNodeParameter('resource', 0);
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
|
||||
if (resource === 'message' && operation === SEND_AND_WAIT_OPERATION) {
|
||||
const spaceId = this.getNodeParameter('spaceId', 0) as string;
|
||||
const body = createSendAndWaitMessageBody(this);
|
||||
|
||||
await googleApiRequest.call(this, 'POST', `/v1/${spaceId}/messages`, body);
|
||||
|
||||
const waitTill = configureWaitTillDate(this);
|
||||
|
||||
await this.putExecutionToWait(waitTill);
|
||||
return [this.getInputData()];
|
||||
}
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
try {
|
||||
if (resource === 'media') {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { INodeProperties } from 'n8n-workflow';
|
||||
import { SEND_AND_WAIT_OPERATION, type INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const messageOperations: INodeProperties[] = [
|
||||
{
|
||||
|
@ -30,6 +30,12 @@ export const messageOperations: INodeProperties[] = [
|
|||
description: 'Get a message',
|
||||
action: 'Get a message',
|
||||
},
|
||||
{
|
||||
name: 'Send and Wait for Response',
|
||||
value: SEND_AND_WAIT_OPERATION,
|
||||
description: 'Send a message and wait for response',
|
||||
action: 'Send message and wait for response',
|
||||
},
|
||||
{
|
||||
name: 'Update',
|
||||
value: 'update',
|
||||
|
@ -41,27 +47,31 @@ export const messageOperations: INodeProperties[] = [
|
|||
},
|
||||
];
|
||||
|
||||
export const spaceIdProperty: INodeProperties = {
|
||||
displayName: 'Space Name or ID',
|
||||
name: 'spaceId',
|
||||
type: 'options',
|
||||
required: true,
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getSpaces',
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'Space resource name, in the form "spaces/*". Example: spaces/AAAAMpdlehY. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
};
|
||||
|
||||
export const messageFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* message:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Space Name or ID',
|
||||
name: 'spaceId',
|
||||
type: 'options',
|
||||
required: true,
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getSpaces',
|
||||
},
|
||||
...spaceIdProperty,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['message'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'Space resource name, in the form "spaces/*". Example: spaces/AAAAMpdlehY. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'JSON Parameters',
|
||||
|
|
|
@ -1 +1,19 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 479.4 499.98"><path d="M121.24 275.69v-162.5h-71a37.86 37.86 0 0 0-37.8 37.9V487c0 16.9 20.4 25.3 32.3 13.4l78.1-78.1h222.4a37.77 37.77 0 0 0 37.8-37.8v-71h-223.9a37.86 37.86 0 0 1-37.9-37.81" style="fill:#00ac47" transform="translate(-12.44 -5.99)"/><path d="M454 6H159.14a37.77 37.77 0 0 0-37.8 37.8v69.4h223.9A37.77 37.77 0 0 1 383 151v162.4h71a37.77 37.77 0 0 0 37.8-37.8V43.79A37.77 37.77 0 0 0 454 6" style="fill:#5bb974" transform="translate(-12.44 -5.99)"/><path d="M345.24 113.19h-224v162.4a37.77 37.77 0 0 0 37.8 37.8h223.9v-162.3a37.71 37.71 0 0 0-37.7-37.9" style="fill:#00832d" transform="translate(-12.44 -5.99)"/></svg>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0.00 0.00 311.00 320.00">
|
||||
<g stroke-width="2.00" fill="none" stroke-linecap="butt">
|
||||
<path stroke="#7e916f" vector-effect="non-scaling-stroke" d=" M 76.37 0.51 L 76.38 76.98"/>
|
||||
<path stroke="#1375eb" vector-effect="non-scaling-stroke" d=" M 76.38 76.98 L 0.00 76.96"/>
|
||||
<path stroke="#f3801d" vector-effect="non-scaling-stroke" d=" M 235.08 1.09 Q 234.92 1.15 234.81 1.22 Q 234.64 1.31 234.64 1.50 L 234.62 77.01"/>
|
||||
<path stroke="#7eb426" vector-effect="non-scaling-stroke" d=" M 234.62 77.01 Q 234.60 77.01 234.57 77.01"/>
|
||||
<path stroke="#91a080" vector-effect="non-scaling-stroke" d=" M 76.41 77.01 Q 76.40 77.00 76.38 76.98"/>
|
||||
<path stroke="#75783e" vector-effect="non-scaling-stroke" d=" M 310.53 76.77 L 234.62 77.01"/>
|
||||
<path stroke="#138495" vector-effect="non-scaling-stroke" d=" M 76.43 182.69 L 0.00 182.67"/>
|
||||
<path stroke="#00983a" vector-effect="non-scaling-stroke" d=" M 76.44 259.13 L 76.43 220.85"/>
|
||||
</g>
|
||||
<path fill="#0066da" d=" M 76.37 0.51 L 76.38 76.98 L 0.00 76.96 L 0.00 20.77 Q 0.85 14.81 3.53 10.76 Q 10.14 0.74 22.75 0.67 Q 49.41 0.53 76.37 0.51 Z"/>
|
||||
<path fill="#fbbc04" d=" M 76.37 0.51 L 233.79 0.53 A 1.61 1.57 -26.7 0 1 234.71 0.82 L 235.08 1.09 Q 234.92 1.15 234.81 1.22 Q 234.64 1.31 234.64 1.50 L 234.62 77.01 Q 234.60 77.01 234.57 77.01 L 76.41 77.01 Q 76.40 77.00 76.38 76.98 L 76.37 0.51 Z"/>
|
||||
<path fill="#ea4335" d=" M 235.08 1.09 L 310.53 76.77 L 234.62 77.01 L 234.64 1.50 Q 234.64 1.31 234.81 1.22 Q 234.92 1.15 235.08 1.09 Z"/>
|
||||
<path fill="#2684fc" d=" M 0.00 76.96 L 76.38 76.98 Q 76.40 77.00 76.41 77.01 L 76.43 182.69 L 0.00 182.67 L 0.00 76.96 Z"/>
|
||||
<path fill="#00ac47" d=" M 310.53 76.77 L 311.00 77.11 L 311.00 239.01 Q 308.34 253.54 295.94 257.78 Q 291.52 259.30 282.91 259.28 Q 227.02 259.19 169.99 259.11 Q 161.71 259.10 153.19 259.23 Q 152.72 259.24 152.39 259.57 Q 124.49 287.34 96.39 315.59 C 93.52 318.48 90.27 320.09 86.15 319.48 Q 80.39 318.63 77.66 313.54 Q 76.51 311.38 76.49 305.66 Q 76.42 282.47 76.44 259.13 L 76.43 220.85 L 114.21 183.07 A 1.79 1.77 22.3 0 1 115.47 182.55 L 233.77 182.59 A 0.83 0.83 0.0 0 0 234.60 181.76 L 234.57 77.01 Q 234.60 77.01 234.62 77.01 L 310.53 76.77 Z"/>
|
||||
<path fill="#00832d" d=" M 76.43 182.69 L 76.43 220.85 L 76.44 259.13 Q 52.47 259.27 28.91 259.22 Q 19.09 259.20 14.76 257.68 Q 2.62 253.44 0.00 238.88 L 0.00 182.67 L 76.43 182.69 Z"/>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 707 B After Width: | Height: | Size: 2.5 KiB |
|
@ -0,0 +1,97 @@
|
|||
import type { MockProxy } from 'jest-mock-extended';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import { type IExecuteFunctions } from 'n8n-workflow';
|
||||
|
||||
import * as googleHelpers from '../../GenericFunctions';
|
||||
import { googleApiRequest } from '../GenericFunctions';
|
||||
|
||||
jest.mock('../../GenericFunctions', () => ({
|
||||
...jest.requireActual('../../GenericFunctions'),
|
||||
getGoogleAccessToken: jest.fn().mockResolvedValue({ access_token: 'mock-access-token' }),
|
||||
}));
|
||||
|
||||
describe('Test GoogleChat, googleApiRequest', () => {
|
||||
let mockExecuteFunctions: MockProxy<IExecuteFunctions>;
|
||||
|
||||
beforeEach(() => {
|
||||
mockExecuteFunctions = mock<IExecuteFunctions>();
|
||||
|
||||
mockExecuteFunctions.helpers = {
|
||||
requestWithAuthentication: jest.fn().mockResolvedValue({}),
|
||||
request: jest.fn().mockResolvedValue({}),
|
||||
} as any;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should call requestWithAuthentication when authentication set to OAuth2', async () => {
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('oAuth2'); // authentication
|
||||
|
||||
const result = await googleApiRequest.call(mockExecuteFunctions, 'POST', '/test-resource', {
|
||||
text: 'test',
|
||||
});
|
||||
|
||||
expect(result).toEqual({ success: true });
|
||||
|
||||
expect(mockExecuteFunctions.helpers.requestWithAuthentication).toHaveBeenCalledTimes(1);
|
||||
expect(mockExecuteFunctions.helpers.requestWithAuthentication).toHaveBeenCalledWith(
|
||||
'googleChatOAuth2Api',
|
||||
{
|
||||
body: { text: 'test' },
|
||||
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
|
||||
json: true,
|
||||
method: 'POST',
|
||||
qs: {},
|
||||
qsStringifyOptions: { arrayFormat: 'repeat' },
|
||||
uri: 'https://chat.googleapis.com/test-resource',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('should call request when authentication set to serviceAccount', async () => {
|
||||
const mockCredentials = {
|
||||
email: 'test@example.com',
|
||||
privateKey: 'private-key',
|
||||
};
|
||||
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('serviceAccount');
|
||||
mockExecuteFunctions.getCredentials.mockResolvedValueOnce(mockCredentials);
|
||||
|
||||
const result = await googleApiRequest.call(mockExecuteFunctions, 'GET', '/test-resource');
|
||||
|
||||
expect(googleHelpers.getGoogleAccessToken).toHaveBeenCalledWith(mockCredentials, 'chat');
|
||||
expect(mockExecuteFunctions.helpers.request).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
headers: expect.objectContaining({
|
||||
Authorization: 'Bearer mock-access-token',
|
||||
}),
|
||||
}),
|
||||
);
|
||||
expect(result).toEqual({ success: true });
|
||||
});
|
||||
|
||||
it('should call request when noCredentials equals true', async () => {
|
||||
const result = await googleApiRequest.call(
|
||||
mockExecuteFunctions,
|
||||
'GET',
|
||||
'/test-resource',
|
||||
{},
|
||||
{},
|
||||
undefined,
|
||||
true,
|
||||
);
|
||||
|
||||
expect(mockExecuteFunctions.helpers.request).toHaveBeenCalledTimes(1);
|
||||
expect(mockExecuteFunctions.helpers.request).toHaveBeenCalledWith({
|
||||
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
|
||||
json: true,
|
||||
method: 'GET',
|
||||
qs: {},
|
||||
qsStringifyOptions: { arrayFormat: 'repeat' },
|
||||
uri: 'https://chat.googleapis.com/test-resource',
|
||||
});
|
||||
expect(result).toEqual({ success: true });
|
||||
});
|
||||
});
|
|
@ -0,0 +1,60 @@
|
|||
import type { MockProxy } from 'jest-mock-extended';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import { type INode, SEND_AND_WAIT_OPERATION, type IExecuteFunctions } from 'n8n-workflow';
|
||||
|
||||
import * as genericFunctions from '../../GenericFunctions';
|
||||
import { GoogleChat } from '../../GoogleChat.node';
|
||||
|
||||
jest.mock('../../GenericFunctions', () => {
|
||||
const originalModule = jest.requireActual('../../GenericFunctions');
|
||||
return {
|
||||
...originalModule,
|
||||
googleApiRequest: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
describe('Test GoogleChat, message => sendAndWait', () => {
|
||||
let googleChat: GoogleChat;
|
||||
let mockExecuteFunctions: MockProxy<IExecuteFunctions>;
|
||||
|
||||
beforeEach(() => {
|
||||
googleChat = new GoogleChat();
|
||||
mockExecuteFunctions = mock<IExecuteFunctions>();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should send message and put execution to wait', async () => {
|
||||
const items = [{ json: { data: 'test' } }];
|
||||
//node
|
||||
mockExecuteFunctions.getInputData.mockReturnValue(items);
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('message');
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce(SEND_AND_WAIT_OPERATION);
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('spaceID');
|
||||
mockExecuteFunctions.getNode.mockReturnValue(mock<INode>());
|
||||
mockExecuteFunctions.getInstanceId.mockReturnValue('instanceId');
|
||||
|
||||
//getSendAndWaitConfig
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('my message');
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('my subject');
|
||||
mockExecuteFunctions.evaluateExpression.mockReturnValueOnce('http://localhost/waiting-webhook');
|
||||
mockExecuteFunctions.evaluateExpression.mockReturnValueOnce('nodeID');
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce({});
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce('approval');
|
||||
|
||||
// configureWaitTillDate
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValueOnce({}); //options.limitWaitTime.values
|
||||
|
||||
const result = await googleChat.execute.call(mockExecuteFunctions);
|
||||
|
||||
expect(result).toEqual([items]);
|
||||
expect(genericFunctions.googleApiRequest).toHaveBeenCalledTimes(1);
|
||||
expect(mockExecuteFunctions.putExecutionToWait).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(genericFunctions.googleApiRequest).toHaveBeenCalledWith('POST', '/v1/spaceID/messages', {
|
||||
text: 'my message\n\n\n*<http://localhost/waiting-webhook/nodeID?approved=true|Approve>*\n\n_This_ _message_ _was_ _sent_ _automatically_ _with_ _<https://n8n.io/?utm_source=n8n-internal&utm_medium=powered_by&utm_campaign=n8n-nodes-base.telegram_instanceId|n8n>_',
|
||||
});
|
||||
});
|
||||
});
|
|
@ -132,6 +132,7 @@
|
|||
"dist/credentials/GoogleBigQueryOAuth2Api.credentials.js",
|
||||
"dist/credentials/GoogleBooksOAuth2Api.credentials.js",
|
||||
"dist/credentials/GoogleCalendarOAuth2Api.credentials.js",
|
||||
"dist/credentials/GoogleChatOAuth2Api.credentials.js",
|
||||
"dist/credentials/GoogleCloudNaturalLanguageOAuth2Api.credentials.js",
|
||||
"dist/credentials/GoogleCloudStorageOAuth2Api.credentials.js",
|
||||
"dist/credentials/GoogleContactsOAuth2Api.credentials.js",
|
||||
|
|
Loading…
Reference in a new issue