chore: test crud actions

This commit is contained in:
Cedric Ziel 2024-12-09 23:54:47 +01:00
parent efb5307f63
commit 1e00961f7b
7 changed files with 846 additions and 1 deletions

View file

@ -0,0 +1,143 @@
import { constructExecutionMetaData, returnJsonArray } from 'n8n-core';
import type {
IExecuteFunctions,
IHookFunctions,
ILoadOptionsFunctions,
INode,
INodeExecutionData,
} from 'n8n-workflow';
import nock from 'nock';
import { Baserow } from '../../../Baserow.node';
import { baserowApiRequest, getTableFields } from '../../../GenericFunctions';
import type { GetAllAdditionalOptions } from '../../../types';
jest.mock('../../../GenericFunctions', () => {
const originalModule: { [key: string]: any } = jest.requireActual('../../../GenericFunctions');
return {
...originalModule,
baserowApiRequest: jest.fn().mockResolvedValue({
size: 2147483647,
mime_type: 'string',
is_image: true,
image_width: 32767,
image_height: 32767,
uploaded_at: '2019-08-24T14:15:22Z',
url: 'http://example.com',
thumbnails: {
property1: null,
property2: null,
},
name: 'string',
original_name: 'string',
}),
getJwtToken: jest.fn().mockResolvedValue('jwt'),
};
});
describe('Baserow Node', () => {
beforeAll(() => {
nock.disableNetConnect();
});
afterAll(() => {
nock.restore();
jest.unmock('../../../GenericFunctions');
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('resource: file', () => {
it('upload-via-url should upload a file via url', async () => {
const mockThis = {
helpers: {
returnJsonArray,
constructExecutionMetaData,
httpRequest: jest.fn().mockResolvedValue({
count: 1,
next: null,
previous: null,
results: {
id: 1,
order: '^-?\\(?:\\.\\)?$',
field_1: 'baz',
},
}),
},
getNode() {
return {
id: 'c4a5ca75-18c7-4cc8-bf7d-5d57bb7d84da',
name: 'Baserow upload-via-url',
type: 'n8n-nodes-base.Baserow',
typeVersion: 1,
position: [0, 0],
parameters: {
operation: 'upload-via-url',
resource: 'file',
tableId: 1,
rowId: 1,
},
} as INode;
},
getCredentials: jest.fn().mockResolvedValue({
username: 'user',
password: 'password',
host: 'https://my-host.com',
}),
getInputData: () => [
{
json: {},
},
],
getNodeParameter: (parameter: string) => {
switch (parameter) {
case 'resource':
return 'file';
case 'operation':
return 'upload-via-url';
case 'url':
return 'https://example.com/image.jpg';
case 'additionalOptions':
return {} as GetAllAdditionalOptions;
default:
return undefined;
}
},
continueOnFail: () => false,
} as unknown as IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions;
const node = new Baserow();
const response: INodeExecutionData[][] = await node.execute.call(mockThis);
expect(baserowApiRequest).toHaveBeenCalledTimes(1);
expect(baserowApiRequest).toHaveBeenNthCalledWith(
1,
'POST',
'/api/user-files/upload-via-url/',
'jwt',
{ url: 'https://example.com/image.jpg' },
);
expect(response).toEqual([
[
{
json: {
image_height: 32767,
image_width: 32767,
is_image: true,
mime_type: 'string',
name: 'string',
original_name: 'string',
size: 2147483647,
thumbnails: { property1: null, property2: null },
uploaded_at: '2019-08-24T14:15:22Z',
url: 'http://example.com',
},
pairedItem: { item: 0 },
},
],
]);
});
});
});

View file

@ -0,0 +1,156 @@
import { constructExecutionMetaData, returnJsonArray } from 'n8n-core';
import type {
IExecuteFunctions,
IHookFunctions,
ILoadOptionsFunctions,
INode,
INodeExecutionData,
} from 'n8n-workflow';
import nock from 'nock';
import { Baserow } from '../../../Baserow.node';
import { baserowFileUploadRequest } from '../../../GenericFunctions';
import type { GetAllAdditionalOptions } from '../../../types';
jest.mock('../../../GenericFunctions', () => {
const originalModule: { [key: string]: any } = jest.requireActual('../../../GenericFunctions');
return {
...originalModule,
baserowFileUploadRequest: jest.fn().mockResolvedValue({
size: 2147483647,
mime_type: 'string',
is_image: true,
image_width: 32767,
image_height: 32767,
uploaded_at: '2019-08-24T14:15:22Z',
url: 'http://example.com',
thumbnails: {
property1: null,
property2: null,
},
name: 'string',
original_name: 'string',
}),
getJwtToken: jest.fn().mockResolvedValue('jwt'),
};
});
describe('Baserow Node', () => {
beforeAll(() => {
nock.disableNetConnect();
});
afterAll(() => {
nock.restore();
jest.unmock('../../../GenericFunctions');
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('resource: file', () => {
it('upload should upload a file', async () => {
const buffer = Buffer.from('test');
const mockThis = {
helpers: {
returnJsonArray,
constructExecutionMetaData,
assertBinaryData: jest
.fn()
.mockReturnValue({ fileName: 'test.png', mimeType: 'image/png' }),
getBinaryDataBuffer: jest.fn().mockResolvedValue(buffer),
httpRequest: jest.fn().mockResolvedValue({
count: 1,
next: null,
previous: null,
results: {
id: 1,
order: '^-?\\(?:\\.\\)?$',
field_1: 'baz',
},
}),
},
getNode() {
return {
id: 'c4a5ca75-18c7-4cc8-bf7d-5d57bb7d84da',
name: 'Baserow upload',
type: 'n8n-nodes-base.Baserow',
typeVersion: 1,
position: [0, 0],
parameters: {
operation: 'upload',
resource: 'file',
},
} as INode;
},
getCredentials: jest.fn().mockResolvedValue({
username: 'user',
password: 'password',
host: 'https://my-host.com',
}),
getInputData: () => [
{
json: {},
},
],
getNodeParameter: (parameter: string) => {
switch (parameter) {
case 'resource':
return 'file';
case 'operation':
return 'upload';
case 'url':
return 'https://example.com/image.jpg';
case 'additionalOptions':
return {} as GetAllAdditionalOptions;
case 'binaryPropertyName':
return 'data';
default:
return undefined;
}
},
continueOnFail: () => false,
} as unknown as IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions;
const node = new Baserow();
const response: INodeExecutionData[][] = await node.execute.call(mockThis);
expect(mockThis.helpers.assertBinaryData).toHaveBeenCalledTimes(1);
expect(mockThis.helpers.getBinaryDataBuffer).toHaveBeenCalledTimes(1);
expect(baserowFileUploadRequest).toHaveBeenCalledTimes(1);
expect(baserowFileUploadRequest).toHaveBeenNthCalledWith(
1,
'jwt',
buffer,
'test.png',
'image/png',
);
expect(response).toEqual([
[
{
json: {
size: 2147483647,
mime_type: 'string',
is_image: true,
image_width: 32767,
image_height: 32767,
uploaded_at: '2019-08-24T14:15:22Z',
url: 'http://example.com',
thumbnails: {
property1: null,
property2: null,
},
name: 'string',
original_name: 'string',
},
pairedItem: { item: 0 },
},
],
]);
});
});
});

View file

@ -0,0 +1,140 @@
import { constructExecutionMetaData, returnJsonArray } from 'n8n-core';
import type {
IExecuteFunctions,
IHookFunctions,
ILoadOptionsFunctions,
INode,
INodeExecutionData,
} from 'n8n-workflow';
import nock from 'nock';
import { Baserow } from '../../../Baserow.node';
import { baserowApiRequest, getTableFields } from '../../../GenericFunctions';
import type { GetAllAdditionalOptions } from '../../../types';
jest.mock('../../../GenericFunctions', () => {
const originalModule: { [key: string]: any } = jest.requireActual('../../../GenericFunctions');
return {
...originalModule,
baserowApiRequest: jest.fn().mockResolvedValue({
id: 1,
field_1: 'baz',
}),
getJwtToken: jest.fn().mockResolvedValue('jwt'),
getTableFields: jest.fn().mockResolvedValue([
{
id: '1',
name: 'my_field_name',
},
]),
};
});
describe('Baserow Node', () => {
beforeAll(() => {
nock.disableNetConnect();
});
afterAll(() => {
nock.restore();
jest.unmock('../../../GenericFunctions');
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('resource: row', () => {
it('create should create a record', async () => {
const mockThis = {
helpers: {
returnJsonArray,
constructExecutionMetaData,
httpRequest: jest.fn().mockResolvedValue({
count: 1,
next: null,
previous: null,
results: {
id: 1,
order: '^-?\\(?:\\.\\)?$',
field_1: 'baz',
},
}),
},
getNode() {
return {
id: 'c4a5ca75-18c7-4cc8-bf7d-5d57bb7d84da',
name: 'Baserow get',
type: 'n8n-nodes-base.Baserow',
typeVersion: 1,
position: [0, 0],
parameters: {
operation: 'create',
resource: 'row',
tableId: 1,
rowId: 1,
},
} as INode;
},
getCredentials: jest.fn().mockResolvedValue({
username: 'user',
password: 'password',
host: 'https://my-host.com',
}),
getInputData: () => [
{
json: {
my_field_name: 'new value',
},
},
],
getNodeParameter: (parameter: string) => {
switch (parameter) {
case 'resource':
return 'row';
case 'operation':
return 'create';
case 'tableId':
return 1;
case 'dataToSend':
return 'autoMapInputData';
case 'inputsToIgnore':
return '';
case 'additionalOptions':
return {} as GetAllAdditionalOptions;
default:
return undefined;
}
},
continueOnFail: () => false,
} as unknown as IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions;
const node = new Baserow();
const response: INodeExecutionData[][] = await node.execute.call(mockThis);
expect(getTableFields).toHaveBeenCalledTimes(1);
expect(baserowApiRequest).toHaveBeenCalledTimes(1);
expect(baserowApiRequest).toHaveBeenNthCalledWith(
1,
'POST',
'/api/database/rows/table/1/',
'jwt',
{ field_1: 'new value' },
);
expect(response).toEqual([
[
{
json: {
id: 1,
my_field_name: 'baz',
},
pairedItem: {
item: 0,
},
},
],
]);
});
});
});

View file

@ -0,0 +1,125 @@
import { constructExecutionMetaData, returnJsonArray } from 'n8n-core';
import type {
IExecuteFunctions,
IHookFunctions,
ILoadOptionsFunctions,
INode,
INodeExecutionData,
} from 'n8n-workflow';
import nock from 'nock';
import { Baserow } from '../../../Baserow.node';
import { baserowApiRequest, getTableFields } from '../../../GenericFunctions';
import type { GetAllAdditionalOptions } from '../../../types';
jest.mock('../../../GenericFunctions', () => {
const originalModule: { [key: string]: any } = jest.requireActual('../../../GenericFunctions');
return {
...originalModule,
baserowApiRequest: jest.fn().mockResolvedValue({
id: 1,
order: '^-?\\(?:\\.\\)?$',
field_1: 'baz',
}),
getJwtToken: jest.fn().mockResolvedValue('jwt'),
getTableFields: jest.fn().mockResolvedValue([
{
id: '1',
name: 'my_field_name',
},
]),
};
});
describe('Baserow Node', () => {
beforeAll(() => {
nock.disableNetConnect();
});
afterAll(() => {
nock.restore();
jest.unmock('../../../GenericFunctions');
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('resource: row', () => {
it('delete should delete a record', async () => {
const mockThis = {
helpers: {
returnJsonArray,
constructExecutionMetaData,
},
getNode() {
return {
id: 'c4a5ca75-18c7-4cc8-bf7d-5d57bb7d84da',
name: 'Baserow delete',
type: 'n8n-nodes-base.Baserow',
typeVersion: 1,
position: [0, 0],
parameters: {
operation: 'delete',
resource: 'row',
tableId: 1,
rowId: 1,
},
} as INode;
},
getCredentials: jest.fn().mockResolvedValue({
username: 'user',
password: 'password',
host: 'https://my-host.com',
}),
getInputData: () => [
{
json: {},
},
],
getNodeParameter: (parameter: string) => {
switch (parameter) {
case 'resource':
return 'row';
case 'operation':
return 'delete';
case 'tableId':
return 1;
case 'rowId':
return 1;
case 'additionalOptions':
return {} as GetAllAdditionalOptions;
default:
return undefined;
}
},
continueOnFail: () => false,
} as unknown as IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions;
const node = new Baserow();
const response: INodeExecutionData[][] = await node.execute.call(mockThis);
expect(getTableFields).toHaveBeenCalledTimes(1);
expect(baserowApiRequest).toHaveBeenCalledTimes(1);
expect(baserowApiRequest).toHaveBeenNthCalledWith(
1,
'DELETE',
'/api/database/rows/table/1/1/',
'jwt',
);
expect(response).toEqual([
[
{
json: {
success: true,
},
pairedItem: {
item: 0,
},
},
],
]);
});
});
});

View file

@ -0,0 +1,137 @@
import { constructExecutionMetaData, returnJsonArray } from 'n8n-core';
import type {
IExecuteFunctions,
IHookFunctions,
ILoadOptionsFunctions,
INode,
INodeExecutionData,
} from 'n8n-workflow';
import nock from 'nock';
import { Baserow } from '../../../Baserow.node';
import { baserowApiRequest, getTableFields } from '../../../GenericFunctions';
import type { GetAllAdditionalOptions } from '../../../types';
jest.mock('../../../GenericFunctions', () => {
const originalModule: { [key: string]: any } = jest.requireActual('../../../GenericFunctions');
return {
...originalModule,
baserowApiRequest: jest.fn().mockResolvedValue({
id: 1,
order: '^-?\\(?:\\.\\)?$',
field_1: 'baz',
}),
getJwtToken: jest.fn().mockResolvedValue('jwt'),
getTableFields: jest.fn().mockResolvedValue([
{
id: '1',
name: 'my_field_name',
},
]),
};
});
describe('Baserow Node', () => {
beforeAll(() => {
nock.disableNetConnect();
});
afterAll(() => {
nock.restore();
jest.unmock('../../../GenericFunctions');
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('resource: row', () => {
it('get should fetch a record', async () => {
const mockThis = {
helpers: {
returnJsonArray,
constructExecutionMetaData,
httpRequest: jest.fn().mockResolvedValue({
count: 1,
next: null,
previous: null,
results: {
id: 1,
order: '^-?\\(?:\\.\\)?$',
field_1: 'baz',
},
}),
},
getNode() {
return {
id: 'c4a5ca75-18c7-4cc8-bf7d-5d57bb7d84da',
name: 'Baserow get',
type: 'n8n-nodes-base.Baserow',
typeVersion: 1,
position: [0, 0],
parameters: {
operation: 'get',
resource: 'row',
tableId: 1,
rowId: 1,
},
} as INode;
},
getCredentials: jest.fn().mockResolvedValue({
username: 'user',
password: 'password',
host: 'https://my-host.com',
}),
getInputData: () => [
{
json: {},
},
],
getNodeParameter: (parameter: string) => {
switch (parameter) {
case 'resource':
return 'row';
case 'operation':
return 'get';
case 'tableId':
return 1;
case 'rowId':
return 1;
case 'additionalOptions':
return {} as GetAllAdditionalOptions;
default:
return undefined;
}
},
continueOnFail: () => false,
} as unknown as IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions;
const node = new Baserow();
const response: INodeExecutionData[][] = await node.execute.call(mockThis);
expect(getTableFields).toHaveBeenCalledTimes(1);
expect(baserowApiRequest).toHaveBeenCalledTimes(1);
expect(baserowApiRequest).toHaveBeenNthCalledWith(
1,
'GET',
'/api/database/rows/table/1/1/',
'jwt',
);
expect(response).toEqual([
[
{
json: {
id: 1,
order: '^-?\\(?:\\.\\)?$',
my_field_name: 'baz',
},
pairedItem: {
item: 0,
},
},
],
]);
});
});
});

View file

@ -62,7 +62,7 @@ describe('Baserow Node', () => {
getNode() {
return {
id: 'c4a5ca75-18c7-4cc8-bf7d-5d57bb7d84da',
name: 'Baserow Upload',
name: 'Baserow getAll',
type: 'n8n-nodes-base.Baserow',
typeVersion: 1,
position: [0, 0],

View file

@ -0,0 +1,144 @@
import { constructExecutionMetaData, returnJsonArray } from 'n8n-core';
import type {
IExecuteFunctions,
IHookFunctions,
ILoadOptionsFunctions,
INode,
INodeExecutionData,
} from 'n8n-workflow';
import nock from 'nock';
import { Baserow } from '../../../Baserow.node';
import { baserowApiRequest, getTableFields } from '../../../GenericFunctions';
import type { GetAllAdditionalOptions } from '../../../types';
jest.mock('../../../GenericFunctions', () => {
const originalModule: { [key: string]: any } = jest.requireActual('../../../GenericFunctions');
return {
...originalModule,
baserowApiRequest: jest.fn().mockResolvedValue({
id: 1,
order: '^-?\\(?:\\.\\)?$',
field_1: 'changed',
}),
getJwtToken: jest.fn().mockResolvedValue('jwt'),
getTableFields: jest.fn().mockResolvedValue([
{
id: '1',
name: 'my_field_name',
},
]),
};
});
describe('Baserow Node', () => {
beforeAll(() => {
nock.disableNetConnect();
});
afterAll(() => {
nock.restore();
jest.unmock('../../../GenericFunctions');
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('resource: row', () => {
it('update should update a record', async () => {
const mockThis = {
helpers: {
returnJsonArray,
constructExecutionMetaData,
httpRequest: jest.fn().mockResolvedValue({
count: 1,
next: null,
previous: null,
results: {
id: 1,
order: '^-?\\(?:\\.\\)?$',
field_1: 'baz',
},
}),
},
getNode() {
return {
id: 'c4a5ca75-18c7-4cc8-bf7d-5d57bb7d84da',
name: 'Baserow get',
type: 'n8n-nodes-base.Baserow',
typeVersion: 1,
position: [0, 0],
parameters: {
operation: 'update',
resource: 'row',
tableId: 1,
rowId: 1,
},
} as INode;
},
getCredentials: jest.fn().mockResolvedValue({
username: 'user',
password: 'password',
host: 'https://my-host.com',
}),
getInputData: () => [
{
json: {
my_field_name: 'changed',
},
},
],
getNodeParameter: (parameter: string) => {
switch (parameter) {
case 'resource':
return 'row';
case 'operation':
return 'update';
case 'tableId':
return 1;
case 'rowId':
return 1;
case 'dataToSend':
return 'autoMapInputData';
case 'inputsToIgnore':
return '';
case 'additionalOptions':
return {} as GetAllAdditionalOptions;
default:
return undefined;
}
},
continueOnFail: () => false,
} as unknown as IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions;
const node = new Baserow();
const response: INodeExecutionData[][] = await node.execute.call(mockThis);
expect(getTableFields).toHaveBeenCalledTimes(1);
expect(baserowApiRequest).toHaveBeenCalledTimes(1);
expect(baserowApiRequest).toHaveBeenNthCalledWith(
1,
'PATCH',
'/api/database/rows/table/1/1/',
'jwt',
{ field_1: 'changed' },
);
expect(response).toEqual([
[
{
json: {
id: 1,
order: '^-?\\(?:\\.\\)?$',
my_field_name: 'changed',
},
pairedItem: {
item: 0,
},
},
],
]);
});
});
});