diff --git a/packages/@n8n/eslint-config/src/configs/base.ts b/packages/@n8n/eslint-config/src/configs/base.ts index b83cc25d488..51c408fede7 100644 --- a/packages/@n8n/eslint-config/src/configs/base.ts +++ b/packages/@n8n/eslint-config/src/configs/base.ts @@ -414,6 +414,7 @@ export const baseConfig = tseslint.config( 'n8n-local-rules/no-plain-errors': 'off', '@typescript-eslint/unbound-method': 'off', 'n8n-local-rules/no-skipped-tests': process.env.NODE_ENV === 'development' ? 'warn' : 'error', + 'n8n-local-rules/no-error-instance-in-to-throw': 'error', }, }, ); diff --git a/packages/@n8n/eslint-config/src/rules/index.ts b/packages/@n8n/eslint-config/src/rules/index.ts index ff21b614d49..a8fd5f7bd7a 100644 --- a/packages/@n8n/eslint-config/src/rules/index.ts +++ b/packages/@n8n/eslint-config/src/rules/index.ts @@ -17,6 +17,7 @@ import { NoArgumentSpreadRule } from './no-argument-spread.js'; import { NoInternalPackageImportRule } from './no-internal-package-import.js'; import { NoImportEnterpriseEditionRule } from './no-import-enterprise-edition.js'; import { NoTypeOnlyImportInDiRule } from './no-type-only-import-in-di.js'; +import { NoErrorInstanceInToThrowRule } from './no-error-instance-in-to-throw.js'; export const rules = { 'no-uncaught-json-parse': NoUncaughtJsonParseRule, @@ -37,4 +38,5 @@ export const rules = { 'no-internal-package-import': NoInternalPackageImportRule, 'no-import-enterprise-edition': NoImportEnterpriseEditionRule, 'no-type-only-import-in-di': NoTypeOnlyImportInDiRule, + 'no-error-instance-in-to-throw': NoErrorInstanceInToThrowRule, } satisfies Record; diff --git a/packages/@n8n/eslint-config/src/rules/no-error-instance-in-to-throw.test.ts b/packages/@n8n/eslint-config/src/rules/no-error-instance-in-to-throw.test.ts new file mode 100644 index 00000000000..7da2620b797 --- /dev/null +++ b/packages/@n8n/eslint-config/src/rules/no-error-instance-in-to-throw.test.ts @@ -0,0 +1,45 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; +import { NoErrorInstanceInToThrowRule } from './no-error-instance-in-to-throw.js'; + +const ruleTester = new RuleTester(); + +ruleTester.run('no-error-instance-in-to-throw', NoErrorInstanceInToThrowRule, { + valid: [ + // Passing a class reference is fine + { code: 'expect(() => foo()).toThrow(NodeOperationError)' }, + // Passing a string is fine + { code: "expect(() => foo()).toThrow('expected message')" }, + // Passing a regex is fine + { code: 'expect(() => foo()).toThrow(/expected/)' }, + // No argument is fine + { code: 'expect(() => foo()).toThrow()' }, + // Async with class reference is fine + { code: 'await expect(foo()).rejects.toThrow(NodeOperationError)' }, + // Async with string is fine + { code: "await expect(foo()).rejects.toThrow('expected message')" }, + // NewExpression not inside toThrow is fine + { code: 'const err = new Error("test")' }, + ], + invalid: [ + { + code: "expect(() => foo()).toThrow(new Error('bad'))", + errors: [{ messageId: 'noErrorInstance', data: { className: 'Error' } }], + }, + { + code: "expect(() => foo()).toThrow(new NodeOperationError(node, 'bad'))", + errors: [{ messageId: 'noErrorInstance', data: { className: 'NodeOperationError' } }], + }, + { + code: "await expect(foo()).rejects.toThrow(new Error('bad'))", + errors: [{ messageId: 'noErrorInstance', data: { className: 'Error' } }], + }, + { + code: "await expect(foo()).rejects.toThrow(new NodeOperationError(node, 'message'))", + errors: [{ messageId: 'noErrorInstance', data: { className: 'NodeOperationError' } }], + }, + { + code: 'expect(() => foo()).toThrow(new TypeError())', + errors: [{ messageId: 'noErrorInstance', data: { className: 'TypeError' } }], + }, + ], +}); diff --git a/packages/@n8n/eslint-config/src/rules/no-error-instance-in-to-throw.ts b/packages/@n8n/eslint-config/src/rules/no-error-instance-in-to-throw.ts new file mode 100644 index 00000000000..03c33e9fc44 --- /dev/null +++ b/packages/@n8n/eslint-config/src/rules/no-error-instance-in-to-throw.ts @@ -0,0 +1,52 @@ +import { ESLintUtils, TSESTree } from '@typescript-eslint/utils'; + +export const NoErrorInstanceInToThrowRule = ESLintUtils.RuleCreator.withoutDocs({ + meta: { + type: 'problem', + docs: { + description: + 'Disallow passing error instances to `.toThrow()`. Jest compares by reference, not message, making assertions flaky. Pass the error class and message string separately instead.', + }, + messages: { + noErrorInstance: + "Do not pass an error instance to `.toThrow()`. Use `.toThrow({{className}})` for type checking and `.toThrow('message')` for message matching.", + }, + schema: [], + }, + defaultOptions: [], + create(context) { + return { + CallExpression(node) { + // Match: expect(...).toThrow(new Foo(...)) + // Match: expect(...).rejects.toThrow(new Foo(...)) + if ( + node.callee.type !== TSESTree.AST_NODE_TYPES.MemberExpression || + node.callee.property.type !== TSESTree.AST_NODE_TYPES.Identifier || + node.callee.property.name !== 'toThrow' + ) { + return; + } + + // Must have exactly one argument that is a NewExpression + if ( + node.arguments.length !== 1 || + node.arguments[0].type !== TSESTree.AST_NODE_TYPES.NewExpression + ) { + return; + } + + const newExpr = node.arguments[0]; + const className = + newExpr.callee.type === TSESTree.AST_NODE_TYPES.Identifier + ? newExpr.callee.name + : 'ErrorClass'; + + context.report({ + messageId: 'noErrorInstance', + node: node.arguments[0], + data: { className }, + }); + }, + }; + }, +}); diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/GoogleGemini.node.test.ts b/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/GoogleGemini.node.test.ts index f7a70fd50f7..de580182169 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/GoogleGemini.node.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/GoogleGemini.node.test.ts @@ -2128,11 +2128,9 @@ describe('GoogleGemini Node', () => { }); executeFunctionsMock.getNode.mockReturnValue({ name: 'Google Gemini' } as INode); - await expect(video.generate.execute.call(executeFunctionsMock, 0)).rejects.toThrow( - new NodeOperationError(executeFunctionsMock.getNode(), 'Failed to generate video', { - description: 'Error generating video', - }), - ); + const promise = video.generate.execute.call(executeFunctionsMock, 0); + await expect(promise).rejects.toThrow(NodeOperationError); + await expect(promise).rejects.toThrow('Failed to generate video'); }); it('should throw error for non-Veo model', async () => { @@ -2149,14 +2147,10 @@ describe('GoogleGemini Node', () => { executeFunctionsMock.getNode.mockReturnValue({ name: 'Google Gemini' } as INode); - await expect(video.generate.execute.call(executeFunctionsMock, 0)).rejects.toThrow( - new NodeOperationError( - executeFunctionsMock.getNode(), - 'Model models/gemini-2.0-flash is not supported for video generation. Please use a Veo model', - { - description: 'Video generation is only supported by Veo models', - }, - ), + const promise = video.generate.execute.call(executeFunctionsMock, 0); + await expect(promise).rejects.toThrow(NodeOperationError); + await expect(promise).rejects.toThrow( + 'Model models/gemini-2.0-flash is not supported for video generation. Please use a Veo model', ); }); diff --git a/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/helpers/utils.test.ts b/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/helpers/utils.test.ts index bcdfbaf1e55..afee790047e 100644 --- a/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/helpers/utils.test.ts +++ b/packages/@n8n/nodes-langchain/nodes/vendors/GoogleGemini/helpers/utils.test.ts @@ -282,11 +282,9 @@ describe('GoogleGemini -> utils', () => { mockExecuteFunctions.getNode.mockReturnValue({ name: 'Google Gemini' } as any); - await expect(uploadFile.call(mockExecuteFunctions, fileContent, mimeType)).rejects.toThrow( - new NodeOperationError(mockExecuteFunctions.getNode(), 'Upload failed', { - description: 'Error uploading file', - }), - ); + const promise = uploadFile.call(mockExecuteFunctions, fileContent, mimeType); + await expect(promise).rejects.toThrow(NodeOperationError); + await expect(promise).rejects.toThrow('Upload failed'); }); }); @@ -463,17 +461,14 @@ describe('GoogleGemini -> utils', () => { mockExecuteFunctions.getNodeParameter.mockReturnValue(''); mockExecuteFunctions.getNode.mockReturnValue({ name: 'Google Gemini' } as any); - await expect( - transferFile.call(mockExecuteFunctions, 0, undefined, 'application/octet-stream'), - ).rejects.toThrow( - new NodeOperationError( - mockExecuteFunctions.getNode(), - 'Binary property name or download URL is required', - { - description: 'Error uploading file', - }, - ), + const promise = transferFile.call( + mockExecuteFunctions, + 0, + undefined, + 'application/octet-stream', ); + await expect(promise).rejects.toThrow(NodeOperationError); + await expect(promise).rejects.toThrow('Binary property name or download URL is required'); }); it('should throw error when upload URL is not received', async () => { @@ -495,16 +490,14 @@ describe('GoogleGemini -> utils', () => { mockExecuteFunctions.getNode.mockReturnValue({ name: 'Google Gemini' } as any); - await expect( - transferFile.call( - mockExecuteFunctions, - 0, - 'https://example.com/file.pdf', - 'application/octet-stream', - ), - ).rejects.toThrow( - new NodeOperationError(mockExecuteFunctions.getNode(), 'Failed to get upload URL'), + const promise = transferFile.call( + mockExecuteFunctions, + 0, + 'https://example.com/file.pdf', + 'application/octet-stream', ); + await expect(promise).rejects.toThrow(NodeOperationError); + await expect(promise).rejects.toThrow('Failed to get upload URL'); }); it('should poll until file is active and throw error on failure', async () => { @@ -552,18 +545,14 @@ describe('GoogleGemini -> utils', () => { mockExecuteFunctions.getNode.mockReturnValue({ name: 'Google Gemini' } as any); - await expect( - transferFile.call( - mockExecuteFunctions, - 0, - 'https://example.com/file.pdf', - 'application/octet-stream', - ), - ).rejects.toThrow( - new NodeOperationError(mockExecuteFunctions.getNode(), 'Processing failed', { - description: 'Error uploading file', - }), + const promise = transferFile.call( + mockExecuteFunctions, + 0, + 'https://example.com/file.pdf', + 'application/octet-stream', ); + await expect(promise).rejects.toThrow(NodeOperationError); + await expect(promise).rejects.toThrow('Processing failed'); }); }); @@ -881,19 +870,15 @@ describe('GoogleGemini -> utils', () => { mockExecuteFunctions.getNode.mockReturnValue({ name: 'Google Gemini' } as any); - await expect( - uploadToFileSearchStore.call( - mockExecuteFunctions, - 0, - fileSearchStoreName, - displayName, - 'https://example.com/file.pdf', - ), - ).rejects.toThrow( - new NodeOperationError(mockExecuteFunctions.getNode(), 'Upload failed', { - description: 'Error uploading file to File Search store', - }), + const promise = uploadToFileSearchStore.call( + mockExecuteFunctions, + 0, + fileSearchStoreName, + displayName, + 'https://example.com/file.pdf', ); + await expect(promise).rejects.toThrow(NodeOperationError); + await expect(promise).rejects.toThrow('Upload failed'); }); it('should throw error when binary property name is missing', async () => { @@ -903,17 +888,14 @@ describe('GoogleGemini -> utils', () => { mockExecuteFunctions.getNodeParameter.mockReturnValue(''); mockExecuteFunctions.getNode.mockReturnValue({ name: 'Google Gemini' } as any); - await expect( - uploadToFileSearchStore.call(mockExecuteFunctions, 0, fileSearchStoreName, displayName), - ).rejects.toThrow( - new NodeOperationError( - mockExecuteFunctions.getNode(), - 'Binary property name or download URL is required', - { - description: 'Error uploading file', - }, - ), + const promise = uploadToFileSearchStore.call( + mockExecuteFunctions, + 0, + fileSearchStoreName, + displayName, ); + await expect(promise).rejects.toThrow(NodeOperationError); + await expect(promise).rejects.toThrow('Binary property name or download URL is required'); }); it('should return undefined when response is missing', async () => { diff --git a/packages/@n8n/task-runner/src/js-task-runner/__tests__/require-resolver.test.ts b/packages/@n8n/task-runner/src/js-task-runner/__tests__/require-resolver.test.ts index 36061b9cc77..bc3000f11ed 100644 --- a/packages/@n8n/task-runner/src/js-task-runner/__tests__/require-resolver.test.ts +++ b/packages/@n8n/task-runner/src/js-task-runner/__tests__/require-resolver.test.ts @@ -1,6 +1,5 @@ import { ExecutionError } from '@/js-task-runner/errors/execution-error'; -import { DisallowedModuleError } from '../errors/disallowed-module.error'; import { createRequireResolver, type RequireResolverOpts } from '../require-resolver'; describe('require resolver', () => { @@ -45,9 +44,8 @@ describe('require resolver', () => { it('should throw when requiring non-allowlisted external modules', () => { const resolver = createRequireResolver(defaultOpts); - expect(() => resolver('express')).toThrow( - new ExecutionError(new DisallowedModuleError('express')), - ); + expect(() => resolver('express')).toThrow(ExecutionError); + expect(() => resolver('express')).toThrow('express'); }); it('should allow all external modules when allowedExternalModules is "*"', () => { diff --git a/packages/cli/src/auth/handlers/__tests__/email.auth-handler.test.ts b/packages/cli/src/auth/handlers/__tests__/email.auth-handler.test.ts index b7712fcaaa4..ec133c431e6 100644 --- a/packages/cli/src/auth/handlers/__tests__/email.auth-handler.test.ts +++ b/packages/cli/src/auth/handlers/__tests__/email.auth-handler.test.ts @@ -114,8 +114,10 @@ describe('EmailAuthHandler', () => { userRepository.findOne.mockResolvedValue(user); globalConfig.sso.ldap.loginEnabled = false; - await expect(handler.handleLogin(email, password)).rejects.toThrow( - new AuthError('Reset your password to gain access to the instance.'), + const promise = handler.handleLogin(email, password); + await expect(promise).rejects.toThrow(AuthError); + await expect(promise).rejects.toThrow( + 'Reset your password to gain access to the instance.', ); expect(eventService.emit).toHaveBeenCalledWith('login-failed-due-to-ldap-disabled', { diff --git a/packages/cli/src/controllers/__tests__/auth.controller.test.ts b/packages/cli/src/controllers/__tests__/auth.controller.test.ts index 1c776ccaa87..efecbd86b0f 100644 --- a/packages/cli/src/controllers/__tests__/auth.controller.test.ts +++ b/packages/cli/src/controllers/__tests__/auth.controller.test.ts @@ -256,10 +256,10 @@ describe('AuthController', () => { }); const res = mock(); - await expect(authController.resolveSignupToken(req, res, payload)).rejects.toThrow( - new BadRequestError( - 'Invite links are not supported on this system, please use single sign on instead.', - ), + const promise = authController.resolveSignupToken(req, res, payload); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow( + 'Invite links are not supported on this system, please use single sign on instead.', ); }); @@ -295,9 +295,9 @@ describe('AuthController', () => { }); jest.spyOn(license, 'isWithinUsersLimit').mockReturnValue(false); - await expect(authController.resolveSignupToken(req, res, payload)).rejects.toThrow( - new ForbiddenError(RESPONSE_ERROR_MESSAGES.USERS_QUOTA_REACHED), - ); + const promise = authController.resolveSignupToken(req, res, payload); + await expect(promise).rejects.toThrow(ForbiddenError); + await expect(promise).rejects.toThrow(RESPONSE_ERROR_MESSAGES.USERS_QUOTA_REACHED); }); it('throws a BadRequestError if the users are not found', async () => { @@ -333,9 +333,9 @@ describe('AuthController', () => { jest.spyOn(license, 'isWithinUsersLimit').mockReturnValue(true); jest.spyOn(userRepository, 'findManyByIds').mockResolvedValue([]); - await expect(authController.resolveSignupToken(req, res, payload)).rejects.toThrow( - new BadRequestError('Invalid invite URL'), - ); + const promise = authController.resolveSignupToken(req, res, payload); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('Invalid invite URL'); }); it('throws a BadRequestError if the invitee already has a password', async () => { @@ -380,8 +380,10 @@ describe('AuthController', () => { }), ]); - await expect(authController.resolveSignupToken(req, res, payload)).rejects.toThrow( - new BadRequestError('The invitation was likely either deleted or already claimed'), + const promise = authController.resolveSignupToken(req, res, payload); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow( + 'The invitation was likely either deleted or already claimed', ); }); @@ -429,9 +431,9 @@ describe('AuthController', () => { }), ]); - await expect(authController.resolveSignupToken(req, res, payload)).rejects.toThrow( - new BadRequestError('Invalid request'), - ); + const promise = authController.resolveSignupToken(req, res, payload); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('Invalid request'); }); it('returns the inviter if the invitation is valid', async () => { @@ -578,9 +580,9 @@ describe('AuthController', () => { .spyOn(userService, 'getInvitationIdsFromPayload') .mockRejectedValue(new BadRequestError('Invalid invite URL')); - await expect(authController.resolveSignupToken(req, res, payload)).rejects.toThrow( - new BadRequestError('Invalid invite URL'), - ); + const promise = authController.resolveSignupToken(req, res, payload); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('Invalid invite URL'); }); it('throws BadRequestError if JWT token payload is missing inviterId or inviteeId', async () => { @@ -612,9 +614,9 @@ describe('AuthController', () => { .spyOn(userService, 'getInvitationIdsFromPayload') .mockRejectedValue(new BadRequestError('Invalid invite URL')); - await expect(authController.resolveSignupToken(req, res, payload)).rejects.toThrow( - new BadRequestError('Invalid invite URL'), - ); + const promise = authController.resolveSignupToken(req, res, payload); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('Invalid invite URL'); }); it('throws BadRequestError if token is missing', async () => { @@ -642,9 +644,9 @@ describe('AuthController', () => { }); const res = mock(); - await expect(authController.resolveSignupToken(req, res, payload)).rejects.toThrow( - new BadRequestError('Token is required'), - ); + const promise = authController.resolveSignupToken(req, res, payload); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('Token is required'); }); }); }); diff --git a/packages/cli/src/controllers/__tests__/invitation.controller.test.ts b/packages/cli/src/controllers/__tests__/invitation.controller.test.ts index 6577879bae3..f5e322d03a6 100644 --- a/packages/cli/src/controllers/__tests__/invitation.controller.test.ts +++ b/packages/cli/src/controllers/__tests__/invitation.controller.test.ts @@ -76,10 +76,10 @@ describe('InvitationController', () => { const req = mock({ user }); const res = mock(); - await expect(invitationController.inviteUser(req, res, payload)).rejects.toThrow( - new BadRequestError( - 'SSO is enabled, so users are managed by the Identity Provider and cannot be added through invites', - ), + const promise = invitationController.inviteUser(req, res, payload); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow( + 'SSO is enabled, so users are managed by the Identity Provider and cannot be added through invites', ); }); @@ -103,9 +103,9 @@ describe('InvitationController', () => { const req = mock({ user }); const res = mock(); - await expect(invitationController.inviteUser(req, res, payload)).rejects.toThrow( - new ForbiddenError(RESPONSE_ERROR_MESSAGES.USERS_QUOTA_REACHED), - ); + const promise = invitationController.inviteUser(req, res, payload); + await expect(promise).rejects.toThrow(ForbiddenError); + await expect(promise).rejects.toThrow(RESPONSE_ERROR_MESSAGES.USERS_QUOTA_REACHED); }); it('throws a BadRequestError if the owner account is not set up', async () => { @@ -129,8 +129,10 @@ describe('InvitationController', () => { const req = mock({ user }); const res = mock(); - await expect(invitationController.inviteUser(req, res, payload)).rejects.toThrow( - new BadRequestError('You must set up your own account before inviting others'), + const promise = invitationController.inviteUser(req, res, payload); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow( + 'You must set up your own account before inviting others', ); }); @@ -163,10 +165,10 @@ describe('InvitationController', () => { const req = mock({ user }); const res = mock(); - await expect(invitationController.inviteUser(req, res, payload)).rejects.toThrow( - new ForbiddenError( - 'Cannot invite admin user without advanced permissions. Please upgrade to a license that includes this feature.', - ), + const promise = invitationController.inviteUser(req, res, payload); + await expect(promise).rejects.toThrow(ForbiddenError); + await expect(promise).rejects.toThrow( + 'Cannot invite admin user without advanced permissions. Please upgrade to a license that includes this feature.', ); }); @@ -244,12 +246,10 @@ describe('InvitationController', () => { }); const res = mock(); - await expect( - invitationController.acceptInvitationWithToken(req, res, payload), - ).rejects.toThrow( - new BadRequestError( - 'Invite links are not supported on this system, please use single sign on instead.', - ), + const promise = invitationController.acceptInvitationWithToken(req, res, payload); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow( + 'Invite links are not supported on this system, please use single sign on instead.', ); }); @@ -269,9 +269,9 @@ describe('InvitationController', () => { }); const res = mock(); - await expect( - invitationController.acceptInvitationWithToken(req, res, payload), - ).rejects.toThrow(new BadRequestError('Token is required')); + const promise = invitationController.acceptInvitationWithToken(req, res, payload); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('Token is required'); }); it('accepts the invitation successfully with JWT token', async () => { @@ -365,9 +365,9 @@ describe('InvitationController', () => { }); const res = mock(); - await expect( - invitationController.acceptInvitationWithToken(req, res, payload), - ).rejects.toThrow(new BadRequestError('Invalid payload or URL')); + const promise = invitationController.acceptInvitationWithToken(req, res, payload); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('Invalid payload or URL'); }); it('throws a BadRequestError if invitee already has a password', async () => { @@ -408,9 +408,9 @@ describe('InvitationController', () => { }); const res = mock(); - await expect( - invitationController.acceptInvitationWithToken(req, res, payload), - ).rejects.toThrow(new BadRequestError('This invite has been accepted already')); + const promise = invitationController.acceptInvitationWithToken(req, res, payload); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('This invite has been accepted already'); }); }); }); diff --git a/packages/cli/src/modules/agents/integrations/platforms/__tests__/telegram-integration.test.ts b/packages/cli/src/modules/agents/integrations/platforms/__tests__/telegram-integration.test.ts index 5f0cf353ae4..48297ee4dda 100644 --- a/packages/cli/src/modules/agents/integrations/platforms/__tests__/telegram-integration.test.ts +++ b/packages/cli/src/modules/agents/integrations/platforms/__tests__/telegram-integration.test.ts @@ -80,8 +80,10 @@ describe('TelegramIntegration.onBeforeConnect', () => { makeAgent('agent-other', 'Agent Other', [{ type: 'telegram', credentialId: 'cred-1' }]), ]); - await expect(integration.onBeforeConnect(makeContext())).rejects.toThrow( - new ConflictError('Telegram credential is already connected to agent "Agent Other"'), + const promise = integration.onBeforeConnect(makeContext()); + await expect(promise).rejects.toThrow(ConflictError); + await expect(promise).rejects.toThrow( + 'Telegram credential is already connected to agent "Agent Other"', ); // Telegram API must not be called once the DB already indicates a conflict. expect(fetchSpy).not.toHaveBeenCalled(); @@ -119,8 +121,10 @@ describe('TelegramIntegration.onBeforeConnect', () => { makeAgent('agent-b', 'Beta', [{ type: 'telegram', credentialId: 'cred-1' }]), ]); - await expect(integration.onBeforeConnect(makeContext())).rejects.toThrow( - new ConflictError('Telegram credential is already connected to agent "Alpha"'), + const promise = integration.onBeforeConnect(makeContext()); + await expect(promise).rejects.toThrow(ConflictError); + await expect(promise).rejects.toThrow( + 'Telegram credential is already connected to agent "Alpha"', ); }); diff --git a/packages/cli/src/modules/chat-hub/__tests__/chat-hub-credentials.service.test.ts b/packages/cli/src/modules/chat-hub/__tests__/chat-hub-credentials.service.test.ts index 30392cc5ead..a79e286d678 100644 --- a/packages/cli/src/modules/chat-hub/__tests__/chat-hub-credentials.service.test.ts +++ b/packages/cli/src/modules/chat-hub/__tests__/chat-hub-credentials.service.test.ts @@ -62,9 +62,9 @@ describe('ChatHubCredentialsService', () => { it('should throw ForbiddenError when user does not have access to the credential', async () => { credentialsFinderService.findCredentialForUser.mockResolvedValue(null); - await expect(service.ensureCredentialAccess(mockUser, CREDENTIAL_ID)).rejects.toThrow( - new ForbiddenError("You don't have access to the provided credentials"), - ); + const promise = service.ensureCredentialAccess(mockUser, CREDENTIAL_ID); + await expect(promise).rejects.toThrow(ForbiddenError); + await expect(promise).rejects.toThrow("You don't have access to the provided credentials"); }); }); @@ -90,9 +90,9 @@ describe('ChatHubCredentialsService', () => { it('should throw ForbiddenError when no personal project is found', async () => { projectRepository.getPersonalProjectForUser.mockResolvedValue(null); - await expect(service.findPersonalProject(mockUser, mockTrx)).rejects.toThrow( - new ForbiddenError('Missing personal project'), - ); + const promise = service.findPersonalProject(mockUser, mockTrx); + await expect(promise).rejects.toThrow(ForbiddenError); + await expect(promise).rejects.toThrow('Missing personal project'); expect(projectRepository.getPersonalProjectForUser).toHaveBeenCalledWith( mockUser.id, @@ -138,10 +138,14 @@ describe('ChatHubCredentialsService', () => { openAiApi: { id: CREDENTIAL_ID, name: 'OpenAI Credentials' }, }; - await expect( - service.findWorkflowCredentialAndProject('anthropic', mockCredentials, 'workflow-123'), - ).rejects.toThrow( - new BadRequestError('No credentials provided for the selected model provider'), + const promise = service.findWorkflowCredentialAndProject( + 'anthropic', + mockCredentials, + 'workflow-123', + ); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow( + 'No credentials provided for the selected model provider', ); }); @@ -160,9 +164,13 @@ describe('ChatHubCredentialsService', () => { credentialsService.findAllCredentialIdsForWorkflow.mockResolvedValue([]); credentialsService.findAllGlobalCredentialIds.mockResolvedValue([]); - await expect( - service.findWorkflowCredentialAndProject('openai', mockCredentials, 'workflow-123'), - ).rejects.toThrow(new ForbiddenError("You don't have access to the provided credentials")); + const promise = service.findWorkflowCredentialAndProject( + 'openai', + mockCredentials, + 'workflow-123', + ); + await expect(promise).rejects.toThrow(ForbiddenError); + await expect(promise).rejects.toThrow("You don't have access to the provided credentials"); }); }); }); diff --git a/packages/cli/src/modules/community-packages/__tests__/community-packages.service.test.ts b/packages/cli/src/modules/community-packages/__tests__/community-packages.service.test.ts index dcdd7443eb8..a5950577315 100644 --- a/packages/cli/src/modules/community-packages/__tests__/community-packages.service.test.ts +++ b/packages/cli/src/modules/community-packages/__tests__/community-packages.service.test.ts @@ -492,14 +492,12 @@ describe('CommunityPackagesService', () => { license.isCustomNpmRegistryEnabled.mockReturnValue(false); // ACT & ASSERT - await expect( - communityPackagesService.updatePackage( - installedPackageForUpdateTest.packageName, - installedPackageForUpdateTest, - ), - ).rejects.toThrow( - new FeatureNotLicensedError(LICENSE_FEATURES.COMMUNITY_NODES_CUSTOM_REGISTRY), + const promise = communityPackagesService.updatePackage( + installedPackageForUpdateTest.packageName, + installedPackageForUpdateTest, ); + await expect(promise).rejects.toThrow(FeatureNotLicensedError); + await expect(promise).rejects.toThrow(LICENSE_FEATURES.COMMUNITY_NODES_CUSTOM_REGISTRY); }); }); diff --git a/packages/cli/src/modules/community-packages/__tests__/npm-utils.test.ts b/packages/cli/src/modules/community-packages/__tests__/npm-utils.test.ts index d2de8cb4066..f16206ee814 100644 --- a/packages/cli/src/modules/community-packages/__tests__/npm-utils.test.ts +++ b/packages/cli/src/modules/community-packages/__tests__/npm-utils.test.ts @@ -137,9 +137,9 @@ describe('executeNpmCommand', () => { new Error('npm ERR! 404 Not Found - GET https://registry.npmjs.org/nonexistent-package'), ); - await expect(executeNpmCommand(['install', 'nonexistent-package'])).rejects.toThrow( - new UnexpectedError(RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND), - ); + const promise = executeNpmCommand(['install', 'nonexistent-package']); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow(RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND); }); it('should throw UnexpectedError for package not found (E404)', async () => { @@ -149,25 +149,25 @@ describe('executeNpmCommand', () => { ), ); - await expect(executeNpmCommand(['view', 'nonexistent-package'])).rejects.toThrow( - new UnexpectedError(RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND), - ); + const promise = executeNpmCommand(['view', 'nonexistent-package']); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow(RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND); }); it('should throw UnexpectedError for package not found (404 Not Found)', async () => { mockAsyncExec.mockRejectedValue(new Error('404 Not Found - package does not exist')); - await expect(executeNpmCommand(['install', 'nonexistent-package'])).rejects.toThrow( - new UnexpectedError(RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND), - ); + const promise = executeNpmCommand(['install', 'nonexistent-package']); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow(RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND); }); it('should throw UnexpectedError for no version available', async () => { mockAsyncExec.mockRejectedValue(new Error('No valid versions available for package')); - await expect(executeNpmCommand(['install', 'some-package'])).rejects.toThrow( - new UnexpectedError(RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND), - ); + const promise = executeNpmCommand(['install', 'some-package']); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow(RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND); }); it('should throw UnexpectedError for package version not found', async () => { @@ -175,9 +175,9 @@ describe('executeNpmCommand', () => { new Error(`${NPM_COMMAND_TOKENS.NPM_PACKAGE_VERSION_NOT_FOUND_ERROR} package@1.2.3`), ); - await expect(executeNpmCommand(['install', 'package@1.2.3'])).rejects.toThrow( - new UnexpectedError(RESPONSE_ERROR_MESSAGES.PACKAGE_VERSION_NOT_FOUND), - ); + const promise = executeNpmCommand(['install', 'package@1.2.3']); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow(RESPONSE_ERROR_MESSAGES.PACKAGE_VERSION_NOT_FOUND); }); it('should throw UnexpectedError for disk full (ENOSPC)', async () => { @@ -185,36 +185,36 @@ describe('executeNpmCommand', () => { new Error(`${NPM_COMMAND_TOKENS.NPM_DISK_NO_SPACE}: no space left on device`), ); - await expect(executeNpmCommand(['install', 'some-package'])).rejects.toThrow( - new UnexpectedError(RESPONSE_ERROR_MESSAGES.DISK_IS_FULL), - ); + const promise = executeNpmCommand(['install', 'some-package']); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow(RESPONSE_ERROR_MESSAGES.DISK_IS_FULL); }); it('should throw UnexpectedError for insufficient disk space', async () => { mockAsyncExec.mockRejectedValue(new Error('Error: insufficient space on device')); - await expect(executeNpmCommand(['install', 'large-package'])).rejects.toThrow( - new UnexpectedError(RESPONSE_ERROR_MESSAGES.DISK_IS_FULL), - ); + const promise = executeNpmCommand(['install', 'large-package']); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow(RESPONSE_ERROR_MESSAGES.DISK_IS_FULL); }); it('should throw UnexpectedError for DNS getaddrinfo errors', async () => { mockAsyncExec.mockRejectedValue(new Error('getaddrinfo ENOTFOUND registry.npmjs.org')); - await expect(executeNpmCommand(['install', 'some-package'])).rejects.toThrow( - new UnexpectedError( - 'Network error: Unable to reach npm registry. Please check your internet connection.', - ), + const promise = executeNpmCommand(['install', 'some-package']); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow( + 'Network error: Unable to reach npm registry. Please check your internet connection.', ); }); it('should throw UnexpectedError for DNS ENOTFOUND errors', async () => { mockAsyncExec.mockRejectedValue(new Error('ENOTFOUND registry.npmjs.org')); - await expect(executeNpmCommand(['install', 'some-package'])).rejects.toThrow( - new UnexpectedError( - 'Network error: Unable to reach npm registry. Please check your internet connection.', - ), + const promise = executeNpmCommand(['install', 'some-package']); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow( + 'Network error: Unable to reach npm registry. Please check your internet connection.', ); }); @@ -266,17 +266,17 @@ describe('executeNpmCommand', () => { it('should handle errors normally when doNotHandleError is false', async () => { mockAsyncExec.mockRejectedValue(new Error('npm ERR! 404 Not Found')); - await expect( - executeNpmCommand(['install', 'nonexistent'], { doNotHandleError: false }), - ).rejects.toThrow(new UnexpectedError(RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND)); + const promise = executeNpmCommand(['install', 'nonexistent'], { doNotHandleError: false }); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow(RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND); }); it('should handle errors normally when doNotHandleError is undefined (default)', async () => { mockAsyncExec.mockRejectedValue(new Error('npm ERR! 404 Not Found')); - await expect(executeNpmCommand(['install', 'nonexistent'])).rejects.toThrow( - new UnexpectedError(RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND), - ); + const promise = executeNpmCommand(['install', 'nonexistent']); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow(RESPONSE_ERROR_MESSAGES.PACKAGE_NOT_FOUND); }); }); @@ -417,9 +417,9 @@ describe('executeNpmCommand', () => { it('should handle non-Error objects being thrown', async () => { mockAsyncExec.mockRejectedValue('string error'); - await expect(executeNpmCommand(['install', 'some-package'])).rejects.toThrow( - new UnexpectedError('Failed to execute npm command'), - ); + const promise = executeNpmCommand(['install', 'some-package']); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow('Failed to execute npm command'); }); it('should handle errors with no message', async () => { @@ -645,10 +645,10 @@ describe('verifyIntegrity', () => { mockAsyncExec.mockRejectedValue(new Error('CLI command failed')); - await expect(verifyIntegrity(packageName, version, registryUrl, integrity)).rejects.toThrow( - new UnexpectedError( - 'Checksum verification failed. Try restarting n8n and attempting the installation again.', - ), + const promise = verifyIntegrity(packageName, version, registryUrl, integrity); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow( + 'Checksum verification failed. Try restarting n8n and attempting the installation again.', ); }); @@ -659,10 +659,10 @@ describe('verifyIntegrity', () => { mockAsyncExec.mockRejectedValue(new Error('getaddrinfo ENOTFOUND registry.npmjs.org')); - await expect(verifyIntegrity(packageName, version, registryUrl, integrity)).rejects.toThrow( - new UnexpectedError( - 'Checksum verification failed. Please check your network connection and try again.', - ), + const promise = verifyIntegrity(packageName, version, registryUrl, integrity); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow( + 'Checksum verification failed. Please check your network connection and try again.', ); }); @@ -673,10 +673,10 @@ describe('verifyIntegrity', () => { mockAsyncExec.mockRejectedValue(new Error('ENOTFOUND registry.npmjs.org')); - await expect(verifyIntegrity(packageName, version, registryUrl, integrity)).rejects.toThrow( - new UnexpectedError( - 'Checksum verification failed. Please check your network connection and try again.', - ), + const promise = verifyIntegrity(packageName, version, registryUrl, integrity); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow( + 'Checksum verification failed. Please check your network connection and try again.', ); }); @@ -721,10 +721,10 @@ describe('verifyIntegrity', () => { stderr: '', }); - await expect(verifyIntegrity(packageName, version, registryUrl, integrity)).rejects.toThrow( - new UnexpectedError( - 'Checksum verification failed. Try restarting n8n and attempting the installation again.', - ), + const promise = verifyIntegrity(packageName, version, registryUrl, integrity); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow( + 'Checksum verification failed. Try restarting n8n and attempting the installation again.', ); expect(mockAsyncExec).toHaveBeenCalledTimes(1); @@ -766,10 +766,10 @@ describe('verifyIntegrity', () => { mockAsyncExec.mockRejectedValue(new Error('getaddrinfo ENOTFOUND registry.npmjs.org')); - await expect(verifyIntegrity(packageName, version, registryUrl, integrity)).rejects.toThrow( - new UnexpectedError( - 'Checksum verification failed. Please check your network connection and try again.', - ), + const promise = verifyIntegrity(packageName, version, registryUrl, integrity); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow( + 'Checksum verification failed. Please check your network connection and try again.', ); expect(mockAsyncExec).toHaveBeenCalledTimes(1); @@ -784,10 +784,10 @@ describe('verifyIntegrity', () => { new Error('npm ERR! 404 Not Found - GET https://registry.npmjs.org/nonexistent-package'), ); - await expect(verifyIntegrity(packageName, version, registryUrl, integrity)).rejects.toThrow( - new UnexpectedError( - 'Checksum verification failed. Please check your network connection and try again.', - ), + const promise = verifyIntegrity(packageName, version, registryUrl, integrity); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow( + 'Checksum verification failed. Please check your network connection and try again.', ); expect(mockAsyncExec).toHaveBeenCalledTimes(1); @@ -800,10 +800,10 @@ describe('verifyIntegrity', () => { mockAsyncExec.mockRejectedValue(new Error('Some other error')); - await expect(verifyIntegrity(packageName, version, registryUrl, integrity)).rejects.toThrow( - new UnexpectedError( - 'Checksum verification failed. Try restarting n8n and attempting the installation again.', - ), + const promise = verifyIntegrity(packageName, version, registryUrl, integrity); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow( + 'Checksum verification failed. Try restarting n8n and attempting the installation again.', ); expect(mockAsyncExec).toHaveBeenCalledTimes(1); @@ -845,9 +845,9 @@ describe('checkIfVersionExistsOrThrow', () => { mockAsyncExec.mockRejectedValue(new Error('E404 Not Found')); - await expect(checkIfVersionExistsOrThrow(packageName, version, registryUrl)).rejects.toThrow( - new UnexpectedError('Package version does not exist'), - ); + const promise1 = checkIfVersionExistsOrThrow(packageName, version, registryUrl); + await expect(promise1).rejects.toThrow(UnexpectedError); + await expect(promise1).rejects.toThrow('Package version does not exist'); }); it('should throw UnexpectedError with proper message on 404 when CLI fallback fails', async () => { @@ -857,9 +857,9 @@ describe('checkIfVersionExistsOrThrow', () => { mockAsyncExec.mockRejectedValue(new Error('Some error')); - await expect(checkIfVersionExistsOrThrow(packageName, version, registryUrl)).rejects.toThrow( - new UnexpectedError('Failed to check package version existence'), - ); + const promise = checkIfVersionExistsOrThrow(packageName, version, registryUrl); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow('Failed to check package version existence'); }); it('should throw UnexpectedError for network failures when CLI fallback fails', async () => { @@ -869,9 +869,9 @@ describe('checkIfVersionExistsOrThrow', () => { mockAsyncExec.mockRejectedValue(new Error('CLI network failure')); - await expect(checkIfVersionExistsOrThrow(packageName, version, registryUrl)).rejects.toThrow( - new UnexpectedError('Failed to check package version existence'), - ); + const promise = checkIfVersionExistsOrThrow(packageName, version, registryUrl); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow('Failed to check package version existence'); }); it('should throw UnexpectedError for server errors (500) when CLI fallback fails', async () => { @@ -893,10 +893,10 @@ describe('checkIfVersionExistsOrThrow', () => { mockAsyncExec.mockRejectedValue(new Error('getaddrinfo ENOTFOUND registry.npmjs.org')); - await expect(checkIfVersionExistsOrThrow(packageName, version, registryUrl)).rejects.toThrow( - new UnexpectedError( - 'The community nodes service is temporarily unreachable. Please try again later.', - ), + const promise = checkIfVersionExistsOrThrow(packageName, version, registryUrl); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow( + 'The community nodes service is temporarily unreachable. Please try again later.', ); }); @@ -907,10 +907,10 @@ describe('checkIfVersionExistsOrThrow', () => { mockAsyncExec.mockRejectedValue(new Error('ENOTFOUND registry.npmjs.org')); - await expect(checkIfVersionExistsOrThrow(packageName, version, registryUrl)).rejects.toThrow( - new UnexpectedError( - 'The community nodes service is temporarily unreachable. Please try again later.', - ), + const promise = checkIfVersionExistsOrThrow(packageName, version, registryUrl); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow( + 'The community nodes service is temporarily unreachable. Please try again later.', ); }); @@ -959,9 +959,9 @@ describe('checkIfVersionExistsOrThrow', () => { mockAsyncExec.mockResolvedValue({ stdout: 'null', stderr: '' }); - await expect(checkIfVersionExistsOrThrow(packageName, version, registryUrl)).rejects.toThrow( - new UnexpectedError('Failed to check package version existence'), - ); + const promise = checkIfVersionExistsOrThrow(packageName, version, registryUrl); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow('Failed to check package version existence'); }); it('should reject CLI output that is not valid semver', async () => { @@ -991,9 +991,9 @@ describe('checkIfVersionExistsOrThrow', () => { new Error('E404 Not Found - GET https://registry.npmjs.org/nonexistent-package'), ); - await expect(checkIfVersionExistsOrThrow(packageName, version, registryUrl)).rejects.toThrow( - new UnexpectedError('Package version does not exist'), - ); + const promise = checkIfVersionExistsOrThrow(packageName, version, registryUrl); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow('Package version does not exist'); expect(mockAsyncExec).toHaveBeenCalledTimes(1); }); @@ -1005,10 +1005,10 @@ describe('checkIfVersionExistsOrThrow', () => { mockAsyncExec.mockRejectedValue(new Error('getaddrinfo ENOTFOUND registry.npmjs.org')); - await expect(checkIfVersionExistsOrThrow(packageName, version, registryUrl)).rejects.toThrow( - new UnexpectedError( - 'The community nodes service is temporarily unreachable. Please try again later.', - ), + const promise = checkIfVersionExistsOrThrow(packageName, version, registryUrl); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow( + 'The community nodes service is temporarily unreachable. Please try again later.', ); expect(mockAsyncExec).toHaveBeenCalledTimes(1); @@ -1021,10 +1021,10 @@ describe('checkIfVersionExistsOrThrow', () => { mockAsyncExec.mockRejectedValue(new Error('npm ERR! 500 Internal Server Error')); - await expect(checkIfVersionExistsOrThrow(packageName, version, registryUrl)).rejects.toThrow( - new UnexpectedError( - 'The community nodes service is temporarily unreachable. Please try again later.', - ), + const promise = checkIfVersionExistsOrThrow(packageName, version, registryUrl); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow( + 'The community nodes service is temporarily unreachable. Please try again later.', ); expect(mockAsyncExec).toHaveBeenCalledTimes(1); @@ -1037,9 +1037,9 @@ describe('checkIfVersionExistsOrThrow', () => { mockAsyncExec.mockRejectedValue(new Error('Some other error')); - await expect(checkIfVersionExistsOrThrow(packageName, version, registryUrl)).rejects.toThrow( - new UnexpectedError('Failed to check package version existence'), - ); + const promise = checkIfVersionExistsOrThrow(packageName, version, registryUrl); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow('Failed to check package version existence'); expect(mockAsyncExec).toHaveBeenCalledTimes(1); }); diff --git a/packages/cli/src/modules/data-table/__tests__/data-table-filters.integration.test.ts b/packages/cli/src/modules/data-table/__tests__/data-table-filters.integration.test.ts index e2e0b9f1f5b..a6201c3d5b5 100644 --- a/packages/cli/src/modules/data-table/__tests__/data-table-filters.integration.test.ts +++ b/packages/cli/src/modules/data-table/__tests__/data-table-filters.integration.test.ts @@ -577,10 +577,9 @@ describe('dataTable filters', () => { }); // ASSERT + await expect(result).rejects.toThrow(DataTableValidationError); await expect(result).rejects.toThrow( - new DataTableValidationError( - `${condition.toUpperCase()} filter value cannot be null or undefined`, - ), + `${condition.toUpperCase()} filter value cannot be null or undefined`, ); }); @@ -610,10 +609,9 @@ describe('dataTable filters', () => { }); // ASSERT + await expect(result).rejects.toThrow(DataTableValidationError); await expect(result).rejects.toThrow( - new DataTableValidationError( - `${condition.toUpperCase()} filter value must be a string`, - ), + `${condition.toUpperCase()} filter value must be a string`, ); }); }, @@ -1364,10 +1362,9 @@ describe('dataTable filters', () => { }); // ASSERT + await expect(result).rejects.toThrow(DataTableValidationError); await expect(result).rejects.toThrow( - new DataTableValidationError( - `${condition.toUpperCase()} filter value cannot be null or undefined`, - ), + `${condition.toUpperCase()} filter value cannot be null or undefined`, ); }); diff --git a/packages/cli/src/modules/data-table/__tests__/data-table.service.integration.test.ts b/packages/cli/src/modules/data-table/__tests__/data-table.service.integration.test.ts index 781f25a13c0..dd888d26d75 100644 --- a/packages/cli/src/modules/data-table/__tests__/data-table.service.integration.test.ts +++ b/packages/cli/src/modules/data-table/__tests__/data-table.service.integration.test.ts @@ -1292,9 +1292,8 @@ describe('dataTable', () => { ); // ASSERT - await expect(result).rejects.toThrow( - new DataTableValidationError("unknown column name 'cWrong'"), - ); + await expect(result).rejects.toThrow(DataTableValidationError); + await expect(result).rejects.toThrow("unknown column name 'cWrong'"); }); it('inserts rows with partial data (some columns missing)', async () => { @@ -1380,9 +1379,8 @@ describe('dataTable', () => { ); // ASSERT - await expect(result).rejects.toThrow( - new DataTableValidationError("unknown column name 'cWrong'"), - ); + await expect(result).rejects.toThrow(DataTableValidationError); + await expect(result).rejects.toThrow("unknown column name 'cWrong'"); }); it('rejects an invalid date string to date column', async () => { @@ -2372,10 +2370,9 @@ describe('dataTable', () => { filter: undefined as any, }); + await expect(result).rejects.toThrow(DataTableValidationError); await expect(result).rejects.toThrow( - new DataTableValidationError( - 'Filter is required for delete operations to prevent accidental deletion of all data', - ), + 'Filter is required for delete operations to prevent accidental deletion of all data', ); }); @@ -2398,10 +2395,9 @@ describe('dataTable', () => { filter: { type: 'and', filters: [] }, }); + await expect(result).rejects.toThrow(DataTableValidationError); await expect(result).rejects.toThrow( - new DataTableValidationError( - 'Filter is required for delete operations to prevent accidental deletion of all data', - ), + 'Filter is required for delete operations to prevent accidental deletion of all data', ); }); @@ -2950,9 +2946,8 @@ describe('dataTable', () => { }); // ASSERT - await expect(result).rejects.toThrow( - new DataTableValidationError('Filter must not be empty'), - ); + await expect(result).rejects.toThrow(DataTableValidationError); + await expect(result).rejects.toThrow('Filter must not be empty'); const { data } = await dataTableService.getManyRowsAndCount(dataTableId, project1.id, {}); expect(data).toEqual([ @@ -2982,9 +2977,8 @@ describe('dataTable', () => { }); // ASSERT - await expect(result).rejects.toThrow( - new DataTableValidationError('Data columns must not be empty'), - ); + await expect(result).rejects.toThrow(DataTableValidationError); + await expect(result).rejects.toThrow('Data columns must not be empty'); const { data } = await dataTableService.getManyRowsAndCount(dataTableId, project1.id, {}); expect(data).toEqual([ diff --git a/packages/cli/src/modules/sso-oidc/__tests__/oidc.service.ee.test.ts b/packages/cli/src/modules/sso-oidc/__tests__/oidc.service.ee.test.ts index 8c6dbcb1da8..1c81d4eec53 100644 --- a/packages/cli/src/modules/sso-oidc/__tests__/oidc.service.ee.test.ts +++ b/packages/cli/src/modules/sso-oidc/__tests__/oidc.service.ee.test.ts @@ -356,9 +356,9 @@ describe('OidcService', () => { const storedState = oidcService.generateState().signed; const storedNonce = oidcService.generateNonce().signed; - await expect(oidcService.loginUser(callbackUrl, storedState, storedNonce)).rejects.toThrow( - new BadRequestError('Invalid authorization code'), - ); + const promise = oidcService.loginUser(callbackUrl, storedState, storedNonce); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('Invalid authorization code'); }); it('throws an error if claims() throws an error', async () => { @@ -377,9 +377,9 @@ describe('OidcService', () => { const storedState = oidcService.generateState().signed; const storedNonce = oidcService.generateNonce().signed; - await expect(oidcService.loginUser(callbackUrl, storedState, storedNonce)).rejects.toThrow( - new BadRequestError('Invalid token'), - ); + const promise = oidcService.loginUser(callbackUrl, storedState, storedNonce); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('Invalid token'); }); it('should throw an error if there are no claims', async () => { @@ -398,9 +398,9 @@ describe('OidcService', () => { const storedState = oidcService.generateState().signed; const storedNonce = oidcService.generateNonce().signed; - await expect(oidcService.loginUser(callbackUrl, storedState, storedNonce)).rejects.toThrow( - new ForbiddenError('No claims found in the OIDC token'), - ); + const promise = oidcService.loginUser(callbackUrl, storedState, storedNonce); + await expect(promise).rejects.toThrow(ForbiddenError); + await expect(promise).rejects.toThrow('No claims found in the OIDC token'); }); it('throws an error if fetchUserInfo throws an error', async () => { @@ -420,9 +420,9 @@ describe('OidcService', () => { const storedState = oidcService.generateState().signed; const storedNonce = oidcService.generateNonce().signed; - await expect(oidcService.loginUser(callbackUrl, storedState, storedNonce)).rejects.toThrow( - new BadRequestError('Invalid token'), - ); + const promise = oidcService.loginUser(callbackUrl, storedState, storedNonce); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('Invalid token'); }); it('throws an error if there is no email', async () => { @@ -442,9 +442,9 @@ describe('OidcService', () => { const storedState = oidcService.generateState().signed; const storedNonce = oidcService.generateNonce().signed; - await expect(oidcService.loginUser(callbackUrl, storedState, storedNonce)).rejects.toThrow( - new BadRequestError('An email is required'), - ); + const promise = oidcService.loginUser(callbackUrl, storedState, storedNonce); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('An email is required'); }); it('throws an error if the email is invalid', async () => { @@ -466,9 +466,9 @@ describe('OidcService', () => { const storedState = oidcService.generateState().signed; const storedNonce = oidcService.generateNonce().signed; - await expect(oidcService.loginUser(callbackUrl, storedState, storedNonce)).rejects.toThrow( - new BadRequestError('Invalid email format'), - ); + const promise = oidcService.loginUser(callbackUrl, storedState, storedNonce); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('Invalid email format'); }); it('should return the user if the auth identity already exists', async () => { diff --git a/packages/cli/src/push/__tests__/index.test.ts b/packages/cli/src/push/__tests__/index.test.ts index ca760ad3daf..1678a635d81 100644 --- a/packages/cli/src/push/__tests__/index.test.ts +++ b/packages/cli/src/push/__tests__/index.test.ts @@ -178,9 +178,8 @@ describe('Push', () => { req.headers['x-forwarded-host'] = xForwardedHost; if (backendName === 'sse') { - expect(() => push.handleRequest(req, res)).toThrow( - new BadRequestError('Invalid origin!'), - ); + expect(() => push.handleRequest(req, res)).toThrow(BadRequestError); + expect(() => push.handleRequest(req, res)).toThrow('Invalid origin!'); } else { push.handleRequest(req, res); expect(ws.send).toHaveBeenCalledWith('Invalid origin!'); @@ -274,9 +273,8 @@ describe('Push', () => { } else { // Expected behavior: connection should be rejected if (backendName === 'sse') { - expect(() => push.handleRequest(req, res)).toThrow( - new BadRequestError('Invalid origin!'), - ); + expect(() => push.handleRequest(req, res)).toThrow(BadRequestError); + expect(() => push.handleRequest(req, res)).toThrow('Invalid origin!'); } else { push.handleRequest(req, res); expect(ws.send).toHaveBeenCalledWith('Invalid origin!'); @@ -291,8 +289,9 @@ describe('Push', () => { req.query = { pushRef: '' }; if (backendName === 'sse') { + expect(() => push.handleRequest(req, res)).toThrow(BadRequestError); expect(() => push.handleRequest(req, res)).toThrow( - new BadRequestError('The query parameter "pushRef" is missing!'), + 'The query parameter "pushRef" is missing!', ); } else { push.handleRequest(req, mock()); diff --git a/packages/cli/test/integration/saml/saml.api.test.ts b/packages/cli/test/integration/saml/saml.api.test.ts index 7a17d6f1bc9..66579d4ebab 100644 --- a/packages/cli/test/integration/saml/saml.api.test.ts +++ b/packages/cli/test/integration/saml/saml.api.test.ts @@ -776,9 +776,9 @@ describe('SAML email validation', () => { const mockRequest = {} as express.Request; - await expect(samlService.handleSamlLogin(mockRequest, 'post')).rejects.toThrow( - new BadRequestError('Invalid email format'), - ); + const promise = samlService.handleSamlLogin(mockRequest, 'post'); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('Invalid email format'); }); test.each([['not-an-email'], ['@missinglocal.com'], ['missing@.com'], ['spaces in@email.com']])( @@ -797,9 +797,9 @@ describe('SAML email validation', () => { const mockRequest = {} as express.Request; - await expect(samlService.handleSamlLogin(mockRequest, 'post')).rejects.toThrow( - new BadRequestError('Invalid email format'), - ); + const promise = samlService.handleSamlLogin(mockRequest, 'post'); + await expect(promise).rejects.toThrow(BadRequestError); + await expect(promise).rejects.toThrow('Invalid email format'); }, ); diff --git a/packages/cli/test/migration/migration-test-helpers.test.ts b/packages/cli/test/migration/migration-test-helpers.test.ts index 3458c7e2f42..0bf0225a49c 100644 --- a/packages/cli/test/migration/migration-test-helpers.test.ts +++ b/packages/cli/test/migration/migration-test-helpers.test.ts @@ -47,9 +47,9 @@ describe('Migration Test Helpers', () => { describe('initDbUpToMigration', () => { it('should throw error if migration not found', async () => { - await expect(initDbUpToMigration('NonExistentMigration')).rejects.toThrow( - new UnexpectedError('Migration "NonExistentMigration" not found'), - ); + const promise = initDbUpToMigration('NonExistentMigration'); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow('Migration "NonExistentMigration" not found'); }); it('should stop before specified migration', async () => { @@ -72,9 +72,9 @@ describe('Migration Test Helpers', () => { describe('runSingleMigration', () => { it('should throw error if migration not found', async () => { - await expect(runSingleMigration('NonExistentMigration')).rejects.toThrow( - new UnexpectedError('Migration "NonExistentMigration" not found'), - ); + const promise = runSingleMigration('NonExistentMigration'); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow('Migration "NonExistentMigration" not found'); }); it('should run specific migration', async () => { diff --git a/packages/core/src/binary-data/__tests__/utils.test.ts b/packages/core/src/binary-data/__tests__/utils.test.ts index 2c3cc7d57f4..ece7739e0f5 100644 --- a/packages/core/src/binary-data/__tests__/utils.test.ts +++ b/packages/core/src/binary-data/__tests__/utils.test.ts @@ -27,9 +27,9 @@ describe('BinaryData/utils', () => { it('should throw on invalid compressed Readable streams', async () => { const gunzip = createGunzip(); const body = Readable.from(Buffer.from('0001f8b080000000000000000', 'hex')).pipe(gunzip); - await expect(binaryToBuffer(body)).rejects.toThrow( - new UnexpectedError('Failed to decompress response'), - ); + const promise = binaryToBuffer(body); + await expect(promise).rejects.toThrow(UnexpectedError); + await expect(promise).rejects.toThrow('Failed to decompress response'); }); }); }); diff --git a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/normalize-items.test.ts b/packages/core/src/execution-engine/node-execution-context/utils/__tests__/normalize-items.test.ts index 88fc089f7c7..d66101a3265 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/normalize-items.test.ts +++ b/packages/core/src/execution-engine/node-execution-context/utils/__tests__/normalize-items.test.ts @@ -104,7 +104,8 @@ describe('normalizeItems', () => { }, ]; test.each(errorTests)('$description', ({ input }) => { - expect(() => normalizeItems(input)).toThrow(new ApplicationError('Inconsistent item format')); + expect(() => normalizeItems(input)).toThrow(ApplicationError); + expect(() => normalizeItems(input)).toThrow('Inconsistent item format'); }); }); }); diff --git a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/validate-value-against-schema.test.ts b/packages/core/src/execution-engine/node-execution-context/utils/__tests__/validate-value-against-schema.test.ts index 60d4ca53673..1037bedd92d 100644 --- a/packages/core/src/execution-engine/node-execution-context/utils/__tests__/validate-value-against-schema.test.ts +++ b/packages/core/src/execution-engine/node-execution-context/utils/__tests__/validate-value-against-schema.test.ts @@ -458,7 +458,10 @@ describe('validateValueAgainstSchema', () => { expect(() => validateValueAgainstSchema(node, nodeType, value, parameterName, 0, 0), - ).toThrow(new ExpressionError("Invalid input for 'count' [item 0]")); + ).toThrow(ExpressionError); + expect(() => + validateValueAgainstSchema(node, nodeType, value, parameterName, 0, 0), + ).toThrow("Invalid input for 'count' [item 0]"); }); }); }); diff --git a/packages/nodes-base/nodes/Amqp/Amqp.node.test.ts b/packages/nodes-base/nodes/Amqp/Amqp.node.test.ts index a936f456004..519fabcdde6 100644 --- a/packages/nodes-base/nodes/Amqp/Amqp.node.test.ts +++ b/packages/nodes-base/nodes/Amqp/Amqp.node.test.ts @@ -73,9 +73,9 @@ describe('AMQP Node', () => { it('should throw error when sink is empty', async () => { executeFunctions.getNodeParameter.calledWith('sink', 0).mockReturnValue(''); - await expect(new Amqp().execute.call(executeFunctions)).rejects.toThrow( - new NodeOperationError(executeFunctions.getNode(), 'Queue or Topic required!'), - ); + const promise = new Amqp().execute.call(executeFunctions); + await expect(promise).rejects.toThrow(NodeOperationError); + await expect(promise).rejects.toThrow('Queue or Topic required!'); }); it('should send message successfully', async () => { diff --git a/packages/nodes-base/nodes/Aws/IAM/test/helpers/errorHandler.test.ts b/packages/nodes-base/nodes/Aws/IAM/test/helpers/errorHandler.test.ts index 624a95607d0..bfca99388ab 100644 --- a/packages/nodes-base/nodes/Aws/IAM/test/helpers/errorHandler.test.ts +++ b/packages/nodes-base/nodes/Aws/IAM/test/helpers/errorHandler.test.ts @@ -34,12 +34,9 @@ describe('handleError', () => { Error: { Code: 'EntityAlreadyExists', Message: 'User "existingUserName" already exists' }, } as JsonObject; - await expect(handleError.call(mockExecuteSingleFunctions, data, response)).rejects.toThrow( - new NodeApiError(mockExecuteSingleFunctions.getNode(), response.body as JsonObject, { - message: 'User "existingUserName" already exists', - description: ERROR_DESCRIPTIONS.EntityAlreadyExists.User, - }), - ); + const promise = handleError.call(mockExecuteSingleFunctions, data, response); + await expect(promise).rejects.toThrow(NodeApiError); + await expect(promise).rejects.toThrow('User "existingUserName" already exists'); }); test('should throw NodeApiError for NoSuchEntity with user not found', async () => { @@ -66,12 +63,9 @@ describe('handleError', () => { response.statusCode = 400; response.body = { Error: { Code: 'BadRequest', Message: 'Invalid request' } } as JsonObject; - await expect(handleError.call(mockExecuteSingleFunctions, data, response)).rejects.toThrow( - new NodeApiError(mockExecuteSingleFunctions.getNode(), response.body as JsonObject, { - message: 'BadRequest', - description: 'Invalid request', - }), - ); + const promise = handleError.call(mockExecuteSingleFunctions, data, response); + await expect(promise).rejects.toThrow(NodeApiError); + await expect(promise).rejects.toThrow('BadRequest'); }); test('should throw NodeApiError for EntityAlreadyExists with group conflict', async () => { @@ -84,12 +78,9 @@ describe('handleError', () => { Error: { Code: 'EntityAlreadyExists', Message: 'Group "existingGroupName" already exists' }, } as JsonObject; - await expect(handleError.call(mockExecuteSingleFunctions, data, response)).rejects.toThrow( - new NodeApiError(mockExecuteSingleFunctions.getNode(), response.body as JsonObject, { - message: 'Group "existingGroupName" already exists', - description: ERROR_DESCRIPTIONS.EntityAlreadyExists.Group, - }), - ); + const promise = handleError.call(mockExecuteSingleFunctions, data, response); + await expect(promise).rejects.toThrow(NodeApiError); + await expect(promise).rejects.toThrow('Group "existingGroupName" already exists'); }); test('should throw NodeApiError for NoSuchEntity with group not found', async () => { @@ -102,12 +93,9 @@ describe('handleError', () => { Error: { Code: 'NoSuchEntity', Message: 'Group "nonExistentGroup" does not exist' }, } as JsonObject; - await expect(handleError.call(mockExecuteSingleFunctions, data, response)).rejects.toThrow( - new NodeApiError(mockExecuteSingleFunctions.getNode(), response.body as JsonObject, { - message: 'Group "nonExistentGroup" does not exist', - description: ERROR_DESCRIPTIONS.NoSuchEntity.Group, - }), - ); + const promise = handleError.call(mockExecuteSingleFunctions, data, response); + await expect(promise).rejects.toThrow(NodeApiError); + await expect(promise).rejects.toThrow('Group "nonExistentGroup" does not exist'); }); test('should throw NodeApiError for DeleteConflict', async () => { @@ -120,11 +108,8 @@ describe('handleError', () => { Error: { Code: 'DeleteConflict', Message: 'User "userIngroup" is in a group' }, } as JsonObject; - await expect(handleError.call(mockExecuteSingleFunctions, data, response)).rejects.toThrow( - new NodeApiError(mockExecuteSingleFunctions.getNode(), response.body as JsonObject, { - message: 'User "userIngroup" is in a group', - description: 'This entity is still in use. Remove users from the group before deleting.', - }), - ); + const promise = handleError.call(mockExecuteSingleFunctions, data, response); + await expect(promise).rejects.toThrow(NodeApiError); + await expect(promise).rejects.toThrow('User "userIngroup" is in a group'); }); }); diff --git a/packages/nodes-base/nodes/Evaluation/test/metricHandlers.test.ts b/packages/nodes-base/nodes/Evaluation/test/metricHandlers.test.ts index 24b082e076c..8fdca31d625 100644 --- a/packages/nodes-base/nodes/Evaluation/test/metricHandlers.test.ts +++ b/packages/nodes-base/nodes/Evaluation/test/metricHandlers.test.ts @@ -252,12 +252,9 @@ describe('metricHandlers', () => { return undefined; }); - await expect(metricHandlers.toolsUsed.call(mockExecuteFunctions, 0)).rejects.toThrow( - new NodeOperationError(mockNode, 'Intermediate steps missing', { - description: - "Make sure to enable returning intermediate steps in your agent node's options, then map them in here", - }), - ); + const promise = metricHandlers.toolsUsed.call(mockExecuteFunctions, 0); + await expect(promise).rejects.toThrow(NodeOperationError); + await expect(promise).rejects.toThrow('Intermediate steps missing'); }); it('should throw error for empty object intermediate steps', async () => { diff --git a/packages/nodes-base/nodes/Google/Sheet/test/v2/methods/listSearch.test.ts b/packages/nodes-base/nodes/Google/Sheet/test/v2/methods/listSearch.test.ts index 61f2286b6c5..db987a948ab 100644 --- a/packages/nodes-base/nodes/Google/Sheet/test/v2/methods/listSearch.test.ts +++ b/packages/nodes-base/nodes/Google/Sheet/test/v2/methods/listSearch.test.ts @@ -231,11 +231,9 @@ describe('Google Sheets Search Functions', () => { (apiRequest.call as jest.Mock).mockResolvedValue(undefined); - await expect( - sheetsSearch.call(mockLoadOptionsFunctions as ILoadOptionsFunctions), - ).rejects.toThrow( - new NodeOperationError(mockLoadOptionsFunctions.getNode(), 'No data got returned'), - ); + const promise = sheetsSearch.call(mockLoadOptionsFunctions as ILoadOptionsFunctions); + await expect(promise).rejects.toThrow(NodeOperationError); + await expect(promise).rejects.toThrow('No data got returned'); }); it('should filter out non-GRID type sheets', async () => { diff --git a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/helpers/errorHandler.test.ts b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/helpers/errorHandler.test.ts index ac58a0bcac9..cfcd665824a 100644 --- a/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/helpers/errorHandler.test.ts +++ b/packages/nodes-base/nodes/Microsoft/AzureCosmosDb/test/helpers/errorHandler.test.ts @@ -28,12 +28,9 @@ describe('handleError', () => { response.statusCode = 409; response.body = { code: 'Conflict', message: 'Container already exists' } as JsonObject; - await expect(handleError.call(mockExecuteSingleFunctions, data, response)).rejects.toThrow( - new NodeApiError(mockExecuteSingleFunctions.getNode(), response.body as JsonObject, { - message: ErrorMap.Container.Conflict.getMessage('container'), - description: ErrorMap.Container.Conflict.description, - }), - ); + const promise = handleError.call(mockExecuteSingleFunctions, data, response); + await expect(promise).rejects.toThrow(NodeApiError); + await expect(promise).rejects.toThrow(ErrorMap.Container.Conflict.getMessage('container')); }); test('should throw NodeApiError for container not found', async () => { @@ -42,12 +39,9 @@ describe('handleError', () => { response.statusCode = 404; response.body = { code: 'NotFound', message: 'Container not found' } as JsonObject; - await expect(handleError.call(mockExecuteSingleFunctions, data, response)).rejects.toThrow( - new NodeApiError(mockExecuteSingleFunctions.getNode(), response.body as JsonObject, { - message: ErrorMap.Container.NotFound.getMessage('container'), - description: ErrorMap.Container.NotFound.description, - }), - ); + const promise = handleError.call(mockExecuteSingleFunctions, data, response); + await expect(promise).rejects.toThrow(NodeApiError); + await expect(promise).rejects.toThrow(ErrorMap.Container.NotFound.getMessage('container')); }); test('should throw NodeApiError for item not found', async () => { @@ -56,12 +50,9 @@ describe('handleError', () => { response.statusCode = 404; response.body = { code: 'NotFound', message: 'Item not found' } as JsonObject; - await expect(handleError.call(mockExecuteSingleFunctions, data, response)).rejects.toThrow( - new NodeApiError(mockExecuteSingleFunctions.getNode(), response.body as JsonObject, { - message: ErrorMap.Item.NotFound.getMessage('item'), - description: ErrorMap.Item.NotFound.description, - }), - ); + const promise = handleError.call(mockExecuteSingleFunctions, data, response); + await expect(promise).rejects.toThrow(NodeApiError); + await expect(promise).rejects.toThrow(ErrorMap.Item.NotFound.getMessage('item')); }); test('should throw generic error if no specific mapping exists', async () => { @@ -70,12 +61,9 @@ describe('handleError', () => { response.statusCode = 400; response.body = { code: 'BadRequest', message: 'Invalid request' } as JsonObject; - await expect(handleError.call(mockExecuteSingleFunctions, data, response)).rejects.toThrow( - new NodeApiError(mockExecuteSingleFunctions.getNode(), response.body as JsonObject, { - message: 'BadRequest', - description: 'Invalid request', - }), - ); + const promise = handleError.call(mockExecuteSingleFunctions, data, response); + await expect(promise).rejects.toThrow(NodeApiError); + await expect(promise).rejects.toThrow('BadRequest'); }); test('should handle error details correctly when match is successful', async () => { @@ -119,25 +107,13 @@ describe('handleError', () => { } if (errorDetails && errorDetails.length > 0) { - await expect( - handleError.call(mockExecuteSingleFunctions, data, { - statusCode: 500, - body: { code: 'InternalServerError', message: errorMessage }, - headers: {}, - }), - ).rejects.toThrow( - new NodeApiError( - mockExecuteSingleFunctions.getNode(), - { - code: 'InternalServerError', - message: errorMessage, - } as JsonObject, - { - message: 'InternalServerError', - description: errorDetails.join('\n'), - }, - ), - ); + const promise = handleError.call(mockExecuteSingleFunctions, data, { + statusCode: 500, + body: { code: 'InternalServerError', message: errorMessage }, + headers: {}, + }); + await expect(promise).rejects.toThrow(NodeApiError); + await expect(promise).rejects.toThrow('InternalServerError'); } }); @@ -153,25 +129,13 @@ describe('handleError', () => { } if (errorDetails && errorDetails.length > 0) { - await expect( - handleError.call(mockExecuteSingleFunctions, data, { - statusCode: 500, - body: { code: 'InternalServerError', message: errorMessage }, - headers: {}, - }), - ).rejects.toThrow( - new NodeApiError( - mockExecuteSingleFunctions.getNode(), - { - code: 'InternalServerError', - message: errorMessage, - } as JsonObject, - { - message: 'InternalServerError', - description: 'Internal Server Error', - }, - ), - ); + const promise = handleError.call(mockExecuteSingleFunctions, data, { + statusCode: 500, + body: { code: 'InternalServerError', message: errorMessage }, + headers: {}, + }); + await expect(promise).rejects.toThrow(NodeApiError); + await expect(promise).rejects.toThrow('InternalServerError'); } }); }); diff --git a/packages/workflow/test/ExpressionExtensions/string-extensions.test.ts b/packages/workflow/test/ExpressionExtensions/string-extensions.test.ts index e1506ece5c4..052a9a1d3e7 100644 --- a/packages/workflow/test/ExpressionExtensions/string-extensions.test.ts +++ b/packages/workflow/test/ExpressionExtensions/string-extensions.test.ts @@ -289,8 +289,9 @@ describe('Data Transformation Functions', () => { ); vi.useFakeTimers({ now: new Date() }); + expect(() => evaluate('={{ "hi".toDateTime() }}')).toThrow(ExpressionExtensionError); expect(() => evaluate('={{ "hi".toDateTime() }}')).toThrow( - new ExpressionExtensionError('cannot convert to Luxon DateTime'), + 'cannot convert to Luxon DateTime', ); vi.useRealTimers(); });