first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,736 @@
|
||||
import { mock, mockDeep } from 'jest-mock-extended';
|
||||
import type { IExecuteFunctions, NodeParameterValueType } from 'n8n-workflow';
|
||||
|
||||
import { GoogleSheet } from '../../Google/Sheet/v2/helpers/GoogleSheet';
|
||||
import { EvaluationTrigger } from '../EvaluationTrigger/EvaluationTrigger.node.ee';
|
||||
import * as utils from '../utils/evaluationTriggerUtils';
|
||||
|
||||
describe('Evaluation Trigger Node', () => {
|
||||
const sheetName = 'Sheet5';
|
||||
const spreadsheetId = '1oqFpPgEPTGDw7BPkp1SfPXq3Cb3Hyr1SROtf-Ec4zvA';
|
||||
|
||||
let mockExecuteFunctions = mock<IExecuteFunctions>({
|
||||
getInputData: jest.fn().mockReturnValue([{ json: {} }]),
|
||||
getNode: jest.fn().mockReturnValue({ typeVersion: 4.6 }),
|
||||
});
|
||||
|
||||
let mockDataTable: { getManyRowsAndCount: jest.Mock; getColumns: jest.Mock };
|
||||
|
||||
describe('execute', () => {
|
||||
describe('without filters', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
|
||||
mockExecuteFunctions = mock<IExecuteFunctions>({
|
||||
getInputData: jest.fn().mockReturnValue([{ json: {} }]),
|
||||
getNode: jest.fn().mockReturnValue({ typeVersion: 4.6 }),
|
||||
});
|
||||
|
||||
jest.spyOn(GoogleSheet.prototype, 'spreadsheetGetSheet').mockImplementation(async () => {
|
||||
return { sheetId: 1, title: sheetName };
|
||||
});
|
||||
|
||||
// Mocks getResults() and getRowsLeft()
|
||||
jest.spyOn(GoogleSheet.prototype, 'getData').mockImplementation(async (range: string) => {
|
||||
if (range === `${sheetName}!1:1`) {
|
||||
return [['Header1', 'Header2']];
|
||||
} else if (range === `${sheetName}!2:1000`) {
|
||||
return [
|
||||
['Header1', 'Header2'],
|
||||
['Value1', 'Value2'],
|
||||
['Value3', 'Value4'],
|
||||
];
|
||||
} else if (range === `${sheetName}!2:2`) {
|
||||
// getRowsLeft with limit
|
||||
return [];
|
||||
} else if (range === sheetName) {
|
||||
return [
|
||||
['Header1', 'Header2'],
|
||||
['Value1', 'Value2'],
|
||||
['Value3', 'Value4'],
|
||||
];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('credential test for googleApi should be in methods', async () => {
|
||||
const evaluationTrigger = new EvaluationTrigger();
|
||||
expect(evaluationTrigger.methods.credentialTest.googleApiCredentialTest).toBeDefined();
|
||||
});
|
||||
|
||||
test('should return a single row from google sheet', async () => {
|
||||
mockExecuteFunctions.getNodeParameter.mockImplementation(
|
||||
(key: string, _: number, fallbackValue?: string | number | boolean | object) => {
|
||||
const mockParams: { [key: string]: unknown } = {
|
||||
source: 'googleSheets',
|
||||
options: {},
|
||||
'filtersUI.values': [],
|
||||
combineFilters: 'AND',
|
||||
documentId: {
|
||||
mode: 'id',
|
||||
value: spreadsheetId,
|
||||
},
|
||||
sheetName,
|
||||
sheetMode: 'id',
|
||||
};
|
||||
return (mockParams[key] ?? fallbackValue) as NodeParameterValueType;
|
||||
},
|
||||
);
|
||||
|
||||
const result = await new EvaluationTrigger().execute.call(mockExecuteFunctions);
|
||||
|
||||
expect(result).toEqual([
|
||||
[
|
||||
{
|
||||
json: {
|
||||
row_number: 2,
|
||||
Header1: 'Value1',
|
||||
Header2: 'Value2',
|
||||
_rowsLeft: 2,
|
||||
},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
test('should return the next row from google sheet', async () => {
|
||||
mockExecuteFunctions.getInputData.mockReturnValue([
|
||||
{
|
||||
json: {
|
||||
row_number: 2,
|
||||
Header1: 'Value1',
|
||||
Header2: 'Value2',
|
||||
_rowsLeft: 1,
|
||||
},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
input: undefined,
|
||||
},
|
||||
},
|
||||
]);
|
||||
mockExecuteFunctions.getNodeParameter.mockImplementation(
|
||||
(key: string, _: number, fallbackValue?: string | number | boolean | object) => {
|
||||
const mockParams: { [key: string]: unknown } = {
|
||||
source: 'googleSheets',
|
||||
options: {},
|
||||
'filtersUI.values': [],
|
||||
combineFilters: 'AND',
|
||||
documentId: {
|
||||
mode: 'id',
|
||||
value: spreadsheetId,
|
||||
},
|
||||
sheetName,
|
||||
sheetMode: 'id',
|
||||
};
|
||||
return (mockParams[key] ?? fallbackValue) as NodeParameterValueType;
|
||||
},
|
||||
);
|
||||
|
||||
const result = await new EvaluationTrigger().execute.call(mockExecuteFunctions);
|
||||
|
||||
expect(result).toEqual([
|
||||
[
|
||||
{
|
||||
json: {
|
||||
row_number: 3,
|
||||
Header1: 'Value3',
|
||||
Header2: 'Value4',
|
||||
_rowsLeft: 0,
|
||||
},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
test('should return the first row from google sheet if no rows left', async () => {
|
||||
mockExecuteFunctions.getInputData.mockReturnValue([
|
||||
{
|
||||
json: {
|
||||
row_number: 3,
|
||||
Header1: 'Value3',
|
||||
Header2: 'Value4',
|
||||
_rowsLeft: 0,
|
||||
},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
input: undefined,
|
||||
},
|
||||
},
|
||||
]);
|
||||
mockExecuteFunctions.getNodeParameter.mockImplementation(
|
||||
(key: string, _: number, fallbackValue?: string | number | boolean | object) => {
|
||||
const mockParams: { [key: string]: unknown } = {
|
||||
source: 'googleSheets',
|
||||
options: {},
|
||||
'filtersUI.values': [],
|
||||
combineFilters: 'AND',
|
||||
documentId: {
|
||||
mode: 'id',
|
||||
value: spreadsheetId,
|
||||
},
|
||||
sheetName,
|
||||
sheetMode: 'id',
|
||||
};
|
||||
return (mockParams[key] ?? fallbackValue) as NodeParameterValueType;
|
||||
},
|
||||
);
|
||||
|
||||
const result = await new EvaluationTrigger().execute.call(mockExecuteFunctions);
|
||||
|
||||
expect(result).toEqual([
|
||||
[
|
||||
{
|
||||
json: {
|
||||
row_number: 2,
|
||||
Header1: 'Value1',
|
||||
Header2: 'Value2',
|
||||
_rowsLeft: 2,
|
||||
},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
test('should return a single row from google sheet with limit', async () => {
|
||||
mockExecuteFunctions.getNodeParameter.mockImplementation(
|
||||
(key: string, _: number, fallbackValue?: string | number | boolean | object) => {
|
||||
const mockParams: { [key: string]: unknown } = {
|
||||
source: 'googleSheets',
|
||||
options: {},
|
||||
'filtersUI.values': [],
|
||||
combineFilters: 'AND',
|
||||
documentId: {
|
||||
mode: 'id',
|
||||
value: spreadsheetId,
|
||||
},
|
||||
sheetName,
|
||||
sheetMode: 'id',
|
||||
limitRows: true,
|
||||
maxRows: 1,
|
||||
};
|
||||
return (mockParams[key] ?? fallbackValue) as NodeParameterValueType;
|
||||
},
|
||||
);
|
||||
|
||||
const result = await new EvaluationTrigger().execute.call(mockExecuteFunctions);
|
||||
|
||||
expect(result).toEqual([
|
||||
[
|
||||
{
|
||||
json: {
|
||||
row_number: 2,
|
||||
Header1: 'Value1',
|
||||
Header2: 'Value2',
|
||||
_rowsLeft: 0,
|
||||
},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with filters', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
|
||||
mockExecuteFunctions = mock<IExecuteFunctions>({
|
||||
getInputData: jest.fn().mockReturnValue([{ json: {} }]),
|
||||
getNode: jest.fn().mockReturnValue({ typeVersion: 4.6 }),
|
||||
});
|
||||
|
||||
jest.spyOn(GoogleSheet.prototype, 'spreadsheetGetSheet').mockImplementation(async () => {
|
||||
return { sheetId: 1, title: sheetName };
|
||||
});
|
||||
});
|
||||
|
||||
test('should return a single row from google sheet using filter', async () => {
|
||||
jest
|
||||
.spyOn(GoogleSheet.prototype, 'getData')
|
||||
.mockResolvedValueOnce([
|
||||
// operationResult
|
||||
['Header1', 'Header2'],
|
||||
['Value1', 'Value2'],
|
||||
['Value3', 'Value4'],
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
// rowsLeft
|
||||
['Header1', 'Header2'],
|
||||
['Value1', 'Value2'],
|
||||
['Value3', 'Value4'],
|
||||
]);
|
||||
|
||||
mockExecuteFunctions.getNodeParameter.mockImplementation(
|
||||
(key: string, _: number, fallbackValue?: string | number | boolean | object) => {
|
||||
const mockParams: { [key: string]: unknown } = {
|
||||
source: 'googleSheets',
|
||||
limitRows: true,
|
||||
maxRows: 2,
|
||||
'filtersUI.values': [{ lookupColumn: 'Header1', lookupValue: 'Value1' }],
|
||||
options: {},
|
||||
combineFilters: 'AND',
|
||||
documentId: {
|
||||
mode: 'id',
|
||||
value: spreadsheetId,
|
||||
},
|
||||
sheetName,
|
||||
sheetMode: 'id',
|
||||
};
|
||||
return (mockParams[key] ?? fallbackValue) as NodeParameterValueType;
|
||||
},
|
||||
);
|
||||
|
||||
jest.spyOn(utils, 'getRowsLeft').mockResolvedValue(0);
|
||||
|
||||
const evaluationTrigger = new EvaluationTrigger();
|
||||
|
||||
const result = await evaluationTrigger.execute.call(mockExecuteFunctions);
|
||||
|
||||
expect(result).toEqual([
|
||||
[
|
||||
{
|
||||
json: {
|
||||
row_number: 2,
|
||||
Header1: 'Value1',
|
||||
Header2: 'Value2',
|
||||
_rowsLeft: 0,
|
||||
},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Data tables with filters', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
mockDataTable = {
|
||||
getManyRowsAndCount: jest.fn(),
|
||||
getColumns: jest.fn().mockResolvedValue([{ name: 'processed', type: 'number' }]),
|
||||
};
|
||||
|
||||
mockExecuteFunctions = mockDeep<IExecuteFunctions>({
|
||||
getNode: jest.fn().mockReturnValue({ typeVersion: 4.7 }),
|
||||
helpers: {
|
||||
getDataTableProxy: jest.fn().mockResolvedValue(mockDataTable),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('should process rows sequentially with filters when dataset changes', async () => {
|
||||
// Simulate the user's scenario: 5 rows with processed=1, updating to processed=2 after each execution
|
||||
// With each execution, one row is processed and thus no longer matches the filter
|
||||
mockDataTable.getManyRowsAndCount
|
||||
.mockResolvedValueOnce({
|
||||
data: [{ id: 1, processed: 1 }],
|
||||
count: 5,
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
data: [{ id: 2, processed: 1 }],
|
||||
count: 4,
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
data: [{ id: 3, processed: 1 }],
|
||||
count: 3,
|
||||
});
|
||||
|
||||
mockExecuteFunctions.getNodeParameter.mockImplementation(
|
||||
(key: string, _: number, fallbackValue?: string | number | boolean | object) => {
|
||||
const mockParams: { [key: string]: unknown } = {
|
||||
source: 'dataTable',
|
||||
limitRows: false,
|
||||
dataTableId: 'mockDataTableId',
|
||||
'filters.conditions': [
|
||||
{
|
||||
keyName: 'processed',
|
||||
condition: 'eq',
|
||||
keyValue: '1',
|
||||
},
|
||||
],
|
||||
matchType: 'anyCondition',
|
||||
};
|
||||
return (mockParams[key] ?? fallbackValue) as NodeParameterValueType;
|
||||
},
|
||||
);
|
||||
|
||||
const evaluationTrigger = new EvaluationTrigger();
|
||||
|
||||
// First execution - no previous data
|
||||
mockExecuteFunctions.getInputData.mockReturnValue([{ json: {} }]);
|
||||
const result1 = await evaluationTrigger.execute.call(mockExecuteFunctions);
|
||||
|
||||
expect(result1[0][0].json.row_id).toBe(1);
|
||||
expect(result1[0][0].json.row_number).toBe(0);
|
||||
expect(result1[0][0].json._rowsLeft).toBe(4);
|
||||
|
||||
// Verify first call used user filter only (no id filter yet)
|
||||
expect(mockDataTable.getManyRowsAndCount).toHaveBeenNthCalledWith(1, {
|
||||
skip: 0,
|
||||
take: 1,
|
||||
filter: {
|
||||
type: 'or',
|
||||
filters: [
|
||||
{
|
||||
columnName: 'processed',
|
||||
condition: 'eq',
|
||||
value: '1',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
// Second execution - previous row was id=1
|
||||
mockExecuteFunctions.getInputData.mockReturnValue(result1[0]);
|
||||
const result2 = await evaluationTrigger.execute.call(mockExecuteFunctions);
|
||||
|
||||
expect(result2[0][0].json.row_id).toBe(2);
|
||||
expect(result2[0][0].json.row_number).toBe(1);
|
||||
|
||||
// Verify second call includes id > 1 filter
|
||||
expect(mockDataTable.getManyRowsAndCount).toHaveBeenNthCalledWith(2, {
|
||||
skip: 0,
|
||||
take: 1,
|
||||
filter: {
|
||||
type: 'and',
|
||||
filters: [
|
||||
{
|
||||
columnName: 'processed',
|
||||
condition: 'eq',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
columnName: 'id',
|
||||
condition: 'gt',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
// Third execution - previous row was id=2
|
||||
mockExecuteFunctions.getInputData.mockReturnValue(result2[0]);
|
||||
const result3 = await evaluationTrigger.execute.call(mockExecuteFunctions);
|
||||
|
||||
expect(result3[0][0].json.row_id).toBe(3);
|
||||
expect(result3[0][0].json.row_number).toBe(2);
|
||||
|
||||
// Verify third call includes id > 2 filter
|
||||
expect(mockDataTable.getManyRowsAndCount).toHaveBeenNthCalledWith(3, {
|
||||
skip: 0,
|
||||
take: 1,
|
||||
filter: {
|
||||
type: 'and',
|
||||
filters: [
|
||||
{
|
||||
columnName: 'processed',
|
||||
condition: 'eq',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
columnName: 'id',
|
||||
condition: 'gt',
|
||||
value: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('customOperations.dataset.getRows', () => {
|
||||
describe('Data tables', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
mockDataTable = {
|
||||
getManyRowsAndCount: jest.fn().mockResolvedValue({
|
||||
data: [
|
||||
{ id: 1, field1: 'value1', field2: 'value2' },
|
||||
{ id: 2, field1: 'value3', field2: 'value4' },
|
||||
],
|
||||
}),
|
||||
getColumns: jest.fn().mockResolvedValue([
|
||||
{ name: 'field1', type: 'string' },
|
||||
{ name: 'field2', type: 'string' },
|
||||
]),
|
||||
};
|
||||
|
||||
mockExecuteFunctions = mockDeep<IExecuteFunctions>({
|
||||
getNode: jest.fn().mockReturnValue({ typeVersion: 4.7 }),
|
||||
helpers: {
|
||||
getDataTableProxy: jest.fn().mockResolvedValue(mockDataTable),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('should return the rows with limits applied, without filters', async () => {
|
||||
mockExecuteFunctions.getNodeParameter.mockImplementation(
|
||||
(key: string, _: number, fallbackValue?: string | number | boolean | object) => {
|
||||
const mockParams: { [key: string]: unknown } = {
|
||||
source: 'dataTable',
|
||||
limitRows: true,
|
||||
maxRows: 2,
|
||||
dataTableId: 'mockDataTableId',
|
||||
};
|
||||
return (mockParams[key] ?? fallbackValue) as NodeParameterValueType;
|
||||
},
|
||||
);
|
||||
|
||||
const result = await new EvaluationTrigger().customOperations.dataset.getRows.call(
|
||||
mockExecuteFunctions,
|
||||
);
|
||||
|
||||
expect(mockDataTable.getManyRowsAndCount).toHaveBeenCalledWith({
|
||||
skip: 0,
|
||||
take: 2,
|
||||
filter: { filters: [], type: 'or' },
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
[
|
||||
{
|
||||
json: {
|
||||
id: 1,
|
||||
row_id: 1,
|
||||
row_number: 0,
|
||||
field1: 'value1',
|
||||
field2: 'value2',
|
||||
},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
json: {
|
||||
id: 2,
|
||||
row_id: 2,
|
||||
row_number: 1,
|
||||
field1: 'value3',
|
||||
field2: 'value4',
|
||||
},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
test('should return the rows with limits applied, with filters', async () => {
|
||||
mockExecuteFunctions.getNodeParameter.mockImplementation(
|
||||
(key: string, _: number, fallbackValue?: string | number | boolean | object) => {
|
||||
const mockParams: { [key: string]: unknown } = {
|
||||
source: 'dataTable',
|
||||
limitRows: true,
|
||||
maxRows: 2,
|
||||
dataTableId: 'mockDataTableId',
|
||||
'filters.conditions': [
|
||||
{
|
||||
keyName: 'field1',
|
||||
condition: 'like',
|
||||
keyValue: '1',
|
||||
},
|
||||
{
|
||||
keyName: 'field2',
|
||||
condition: 'eq',
|
||||
keyValue: 'value4',
|
||||
},
|
||||
],
|
||||
};
|
||||
return (mockParams[key] ?? fallbackValue) as NodeParameterValueType;
|
||||
},
|
||||
);
|
||||
|
||||
await new EvaluationTrigger().customOperations.dataset.getRows.call(mockExecuteFunctions);
|
||||
|
||||
expect(mockDataTable.getManyRowsAndCount).toHaveBeenCalledWith({
|
||||
skip: 0,
|
||||
take: 2,
|
||||
filter: {
|
||||
filters: [
|
||||
{
|
||||
columnName: 'field1',
|
||||
condition: 'like',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
columnName: 'field2',
|
||||
condition: 'eq',
|
||||
value: 'value4',
|
||||
},
|
||||
],
|
||||
type: 'or',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Google Sheets', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
|
||||
mockExecuteFunctions = mock<IExecuteFunctions>({
|
||||
getNode: jest.fn().mockReturnValue({ typeVersion: 4.6 }),
|
||||
});
|
||||
|
||||
jest.spyOn(GoogleSheet.prototype, 'spreadsheetGetSheet').mockImplementation(async () => {
|
||||
return { sheetId: 1, title: sheetName };
|
||||
});
|
||||
|
||||
// Mocks getResults() and getRowsLeft()
|
||||
jest.spyOn(GoogleSheet.prototype, 'getData').mockImplementation(async (range: string) => {
|
||||
if (range === `${sheetName}!1:1`) {
|
||||
return [['Header1', 'Header2']];
|
||||
} else if (range === `${sheetName}!2:1000`) {
|
||||
return [
|
||||
['Header1', 'Header2'],
|
||||
['Value1', 'Value2'],
|
||||
['Value3', 'Value4'],
|
||||
];
|
||||
} else if (range === `${sheetName}!2:2`) {
|
||||
// getRowsLeft with limit
|
||||
return [];
|
||||
} else if (range === sheetName) {
|
||||
return [
|
||||
['Header1', 'Header2'],
|
||||
['Value1', 'Value2'],
|
||||
['Value3', 'Value4'],
|
||||
];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('should return the sheet with limits applied, without filters', async () => {
|
||||
mockExecuteFunctions.getNodeParameter.mockImplementation(
|
||||
(key: string, _: number, fallbackValue?: string | number | boolean | object) => {
|
||||
const mockParams: { [key: string]: unknown } = {
|
||||
source: 'googleSheets',
|
||||
options: {},
|
||||
'filtersUI.values': [],
|
||||
combineFilters: 'AND',
|
||||
documentId: {
|
||||
mode: 'id',
|
||||
value: spreadsheetId,
|
||||
},
|
||||
sheetName,
|
||||
sheetMode: 'id',
|
||||
limitRows: true,
|
||||
maxRows: 2,
|
||||
};
|
||||
return (mockParams[key] ?? fallbackValue) as NodeParameterValueType;
|
||||
},
|
||||
);
|
||||
|
||||
const result = await new EvaluationTrigger().customOperations.dataset.getRows.call(
|
||||
mockExecuteFunctions,
|
||||
);
|
||||
|
||||
expect(result).toEqual([
|
||||
[
|
||||
{
|
||||
json: {
|
||||
row_number: 2,
|
||||
Header1: 'Value1',
|
||||
Header2: 'Value2',
|
||||
},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
json: {
|
||||
row_number: 3,
|
||||
Header1: 'Value3',
|
||||
Header2: 'Value4',
|
||||
},
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
test('should return all relevant rows from google sheet using filters', async () => {
|
||||
mockExecuteFunctions.getInputData.mockReturnValue([{ json: {} }]);
|
||||
|
||||
jest
|
||||
.spyOn(GoogleSheet.prototype, 'getData')
|
||||
.mockResolvedValueOnce([
|
||||
// operationResult
|
||||
['Header1', 'Header2'],
|
||||
['Value1', 'Value2'],
|
||||
['Value3', 'Value4'],
|
||||
['Value1', 'Value4'],
|
||||
])
|
||||
.mockResolvedValueOnce([
|
||||
// rowsLeft
|
||||
['Header1', 'Header2'],
|
||||
['Value1', 'Value2'],
|
||||
['Value3', 'Value4'],
|
||||
['Value1', 'Value4'],
|
||||
]);
|
||||
|
||||
mockExecuteFunctions.getNodeParameter.mockImplementation(
|
||||
(key: string, _: number, fallbackValue?: string | number | boolean | object) => {
|
||||
const mockParams: { [key: string]: unknown } = {
|
||||
source: 'googleSheets',
|
||||
'filtersUI.values': [{ lookupColumn: 'Header1', lookupValue: 'Value1' }],
|
||||
options: {},
|
||||
combineFilters: 'AND',
|
||||
documentId: {
|
||||
mode: 'id',
|
||||
value: spreadsheetId,
|
||||
},
|
||||
sheetName,
|
||||
sheetMode: 'id',
|
||||
};
|
||||
return (mockParams[key] ?? fallbackValue) as NodeParameterValueType;
|
||||
},
|
||||
);
|
||||
|
||||
jest.spyOn(utils, 'getRowsLeft').mockResolvedValue(0);
|
||||
|
||||
const evaluationTrigger = new EvaluationTrigger();
|
||||
|
||||
const result =
|
||||
await evaluationTrigger.customOperations.dataset.getRows.call(mockExecuteFunctions);
|
||||
|
||||
expect(result).toEqual([
|
||||
[
|
||||
{
|
||||
json: { row_number: 2, Header1: 'Value1', Header2: 'Value2' },
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
json: { row_number: 4, Header1: 'Value1', Header2: 'Value4' },
|
||||
pairedItem: {
|
||||
item: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user