fix(Microsoft SQL Node): Handle connection errors correctly with continueOnFail (#15962)

This commit is contained in:
Elias Meire
2025-06-04 13:58:17 +02:00
committed by GitHub
parent 30d75db9e3
commit 4c9198df37
2 changed files with 98 additions and 4 deletions

View File

@@ -247,13 +247,24 @@ export class MicrosoftSql implements INodeType {
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const credentials = await this.getCredentials('microsoftSql');
const pool = configurePool(credentials);
await pool.connect();
let responseData: IDataObject | IDataObject[] = [];
let returnData: INodeExecutionData[] = [];
const items = this.getInputData();
const pairedItem = generatePairedItemData(items.length);
const pool = configurePool(credentials);
try {
await pool.connect();
} catch (error) {
void pool.close();
if (this.continueOnFail()) {
return [[{ json: { error: error.message }, pairedItem }]];
} else {
throw error;
}
}
const operation = this.getNodeParameter('operation', 0);
const nodeVersion = this.getNode().typeVersion;

View File

@@ -0,0 +1,83 @@
import { mock } from 'jest-mock-extended';
import * as mssql from 'mssql';
import { constructExecutionMetaData, returnJsonArray } from 'n8n-core';
import type { IExecuteFunctions } from 'n8n-workflow';
import { MicrosoftSql } from '../MicrosoftSql.node';
jest.mock('mssql');
function getMockedExecuteFunctions(overrides: Partial<IExecuteFunctions> = {}) {
return mock<IExecuteFunctions>({
getCredentials: jest.fn().mockResolvedValue({
server: 'localhost',
database: 'testdb',
user: 'testuser',
password: 'testpass',
port: 1433,
tls: false,
allowUnauthorizedCerts: true,
tdsVersion: '7_4',
connectTimeout: 1000,
requestTimeout: 10000,
}),
getInputData: jest.fn().mockReturnValue([{ json: {} }]),
getNode: jest.fn().mockReturnValue({ typeVersion: 1 }),
continueOnFail: jest.fn().mockReturnValue(true),
helpers: {
constructExecutionMetaData,
returnJsonArray,
},
evaluateExpression: jest.fn((_val) => _val),
...overrides,
});
}
describe('MicrosoftSql Node', () => {
let mockedConnectionPool: jest.MockedClass<typeof mssql.ConnectionPool>;
beforeEach(() => {
mockedConnectionPool = mssql.ConnectionPool as jest.MockedClass<typeof mssql.ConnectionPool>;
});
test('handles connection error with continueOnFail', async () => {
const fakeError = new Error('Connection failed');
mockedConnectionPool.mockReturnValue(
mock<mssql.ConnectionPool>({
connect: jest.fn().mockRejectedValue(fakeError),
close: jest.fn(),
}),
);
const node = new MicrosoftSql();
const context = getMockedExecuteFunctions();
const result = await node.execute.call(context);
expect(result).toEqual([[{ json: { error: 'Connection failed' }, pairedItem: [{ item: 0 }] }]]);
});
test('executes query on happy path', async () => {
const queryResult = { recordsets: [[{ value: 1 }]] };
const mockRequest = { query: jest.fn().mockResolvedValue(queryResult) };
const mockPool = mock<mssql.ConnectionPool>({
connect: jest.fn().mockResolvedValue(undefined),
close: jest.fn(),
request: jest.fn().mockReturnValue(mockRequest),
});
mockedConnectionPool.mockReturnValue(mockPool);
const node = new MicrosoftSql();
const context = getMockedExecuteFunctions({
getNodeParameter: jest
.fn()
.mockReturnValueOnce('executeQuery')
.mockReturnValueOnce('SELECT 1 AS value'),
});
const result = await node.execute.call(context);
expect(result).toEqual([[{ json: { value: 1 }, pairedItem: [{ item: 0 }] }]]);
expect(mockRequest.query).toHaveBeenCalledWith('SELECT 1 AS value');
expect(mockPool.close).toHaveBeenCalled();
});
});