Skip to content

Commit

Permalink
refactor(core): Update dynamic node parameter endpoints to use DTOs
Browse files Browse the repository at this point in the history
  • Loading branch information
netroy committed Dec 26, 2024
1 parent 7b2630d commit 46a8d59
Show file tree
Hide file tree
Showing 19 changed files with 804 additions and 171 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { ActionResultRequestDto } from '../action-result-request.dto';

describe('ActionResultRequestDto', () => {
const baseValidRequest = {
path: '/test/path',
nodeTypeAndVersion: { name: 'TestNode', version: 1 },
handler: 'testHandler',
currentNodeParameters: {},
};

describe('Valid requests', () => {
test.each([
{
name: 'minimal valid request',
request: baseValidRequest,
},
{
name: 'request with payload',
request: {
...baseValidRequest,
payload: { key: 'value' },
},
},
{
name: 'request with credentials',
request: {
...baseValidRequest,
credentials: { testCredential: { id: 'cred1', name: 'Test Cred' } },
},
},
{
name: 'request with current node parameters',
request: {
...baseValidRequest,
currentNodeParameters: { param1: 'value1' },
},
},
])('should validate $name', ({ request }) => {
const result = ActionResultRequestDto.safeParse(request);
expect(result.success).toBe(true);
});
});

describe('Invalid requests', () => {
test.each([
{
name: 'missing path',
request: {
nodeTypeAndVersion: { name: 'TestNode', version: 1 },
handler: 'testHandler',
},
expectedErrorPath: ['path'],
},
{
name: 'missing handler',
request: {
path: '/test/path',
currentNodeParameters: {},
nodeTypeAndVersion: { name: 'TestNode', version: 1 },
},
expectedErrorPath: ['handler'],
},
{
name: 'invalid node version',
request: {
...baseValidRequest,
nodeTypeAndVersion: { name: 'TestNode', version: 0 },
},
expectedErrorPath: ['nodeTypeAndVersion', 'version'],
},
])('should fail validation for $name', ({ request, expectedErrorPath }) => {
const result = ActionResultRequestDto.safeParse(request);

expect(result.success).toBe(false);

if (expectedErrorPath) {
expect(result.error?.issues[0].path).toEqual(expectedErrorPath);
}
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { OptionsRequestDto } from '../options-request.dto';

describe('OptionsRequestDto', () => {
const baseValidRequest = {
path: '/test/path',
nodeTypeAndVersion: { name: 'TestNode', version: 1 },
currentNodeParameters: {},
};

describe('Valid requests', () => {
test.each([
{
name: 'minimal valid request',
request: baseValidRequest,
},
{
name: 'request with method name',
request: {
...baseValidRequest,
methodName: 'testMethod',
},
},
{
name: 'request with load options',
request: {
...baseValidRequest,
loadOptions: {
routing: {
operations: { someOperation: 'test' },
output: { someOutput: 'test' },
request: { someRequest: 'test' },
},
},
},
},
{
name: 'request with credentials',
request: {
...baseValidRequest,
credentials: { testCredential: { id: 'cred1', name: 'Test Cred' } },
},
},
{
name: 'request with current node parameters',
request: {
...baseValidRequest,
currentNodeParameters: { param1: 'value1' },
},
},
])('should validate $name', ({ request }) => {
const result = OptionsRequestDto.safeParse(request);
expect(result.success).toBe(true);
});
});

describe('Invalid requests', () => {
test.each([
{
name: 'missing path',
request: {
nodeTypeAndVersion: { name: 'TestNode', version: 1 },
},
expectedErrorPath: ['path'],
},
{
name: 'missing node type and version',
request: {
path: '/test/path',
},
expectedErrorPath: ['nodeTypeAndVersion'],
},
{
name: 'invalid node version',
request: {
...baseValidRequest,
nodeTypeAndVersion: { name: 'TestNode', version: 0 },
},
expectedErrorPath: ['nodeTypeAndVersion', 'version'],
},
])('should fail validation for $name', ({ request, expectedErrorPath }) => {
const result = OptionsRequestDto.safeParse(request);

expect(result.success).toBe(false);

if (expectedErrorPath) {
expect(result.error?.issues[0].path).toEqual(expectedErrorPath);
}
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { ResourceLocatorRequestDto } from '../resource-locator-request.dto';

describe('ResourceLocatorRequestDto', () => {
const baseValidRequest = {
path: '/test/path',
nodeTypeAndVersion: { name: 'TestNode', version: 1 },
methodName: 'testMethod',
currentNodeParameters: {},
};

describe('Valid requests', () => {
test.each([
{
name: 'minimal valid request',
request: baseValidRequest,
},
{
name: 'request with filter',
request: {
...baseValidRequest,
filter: 'testFilter',
},
},
{
name: 'request with pagination token',
request: {
...baseValidRequest,
paginationToken: 'token123',
},
},
{
name: 'request with credentials',
request: {
...baseValidRequest,
credentials: { testCredential: { id: 'cred1', name: 'Test Cred' } },
},
},
{
name: 'request with current node parameters',
request: {
...baseValidRequest,
currentNodeParameters: { param1: 'value1' },
},
},
])('should validate $name', ({ request }) => {
const result = ResourceLocatorRequestDto.safeParse(request);
expect(result.success).toBe(true);
});
});

describe('Invalid requests', () => {
test.each([
{
name: 'missing path',
request: {
nodeTypeAndVersion: { name: 'TestNode', version: 1 },
methodName: 'testMethod',
},
expectedErrorPath: ['path'],
},
{
name: 'missing method name',
request: {
path: '/test/path',
nodeTypeAndVersion: { name: 'TestNode', version: 1 },
currentNodeParameters: {},
},
expectedErrorPath: ['methodName'],
},
{
name: 'invalid node version',
request: {
...baseValidRequest,
nodeTypeAndVersion: { name: 'TestNode', version: 0 },
},
expectedErrorPath: ['nodeTypeAndVersion', 'version'],
},
])('should fail validation for $name', ({ request, expectedErrorPath }) => {
const result = ResourceLocatorRequestDto.safeParse(request);

expect(result.success).toBe(false);

if (expectedErrorPath) {
expect(result.error?.issues[0].path).toEqual(expectedErrorPath);
}
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { ResourceMapperFieldsRequestDto } from '../resource-mapper-fields-request.dto';

describe('ResourceMapperFieldsRequestDto', () => {
const baseValidRequest = {
path: '/test/path',
nodeTypeAndVersion: { name: 'TestNode', version: 1 },
methodName: 'testMethod',
currentNodeParameters: {},
};

describe('Valid requests', () => {
test.each([
{
name: 'minimal valid request',
request: baseValidRequest,
},
{
name: 'request with credentials',
request: {
...baseValidRequest,
credentials: { testCredential: { id: 'cred1', name: 'Test Cred' } },
},
},
{
name: 'request with current node parameters',
request: {
...baseValidRequest,
currentNodeParameters: { param1: 'value1' },
},
},
])('should validate $name', ({ request }) => {
const result = ResourceMapperFieldsRequestDto.safeParse(request);
expect(result.success).toBe(true);
});
});

describe('Invalid requests', () => {
test.each([
{
name: 'missing path',
request: {
nodeTypeAndVersion: { name: 'TestNode', version: 1 },
methodName: 'testMethod',
},
expectedErrorPath: ['path'],
},
{
name: 'missing method name',
request: {
path: '/test/path',
nodeTypeAndVersion: { name: 'TestNode', version: 1 },
currentNodeParameters: {},
},
expectedErrorPath: ['methodName'],
},
{
name: 'invalid node version',
request: {
...baseValidRequest,
nodeTypeAndVersion: { name: 'TestNode', version: 0 },
},
expectedErrorPath: ['nodeTypeAndVersion', 'version'],
},
])('should fail validation for $name', ({ request, expectedErrorPath }) => {
const result = ResourceMapperFieldsRequestDto.safeParse(request);

expect(result.success).toBe(false);

if (expectedErrorPath) {
expect(result.error?.issues[0].path).toEqual(expectedErrorPath);
}
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { IDataObject } from 'n8n-workflow';
import { z } from 'zod';

import { BaseDynamicParametersRequestDto } from './base-dynamic-parameters-request.dto';

export class ActionResultRequestDto extends BaseDynamicParametersRequestDto.extend({
handler: z.string(),
payload: z
.union([z.object({}).catchall(z.any()) satisfies z.ZodType<IDataObject>, z.string()])
.optional(),
}) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { INodeCredentials, INodeParameters, INodeTypeNameVersion } from 'n8n-workflow';
import { z } from 'zod';
import { Z } from 'zod-class';

export class BaseDynamicParametersRequestDto extends Z.class({
path: z.string(),
nodeTypeAndVersion: z.object({
name: z.string(),
version: z.number().int().min(1),
}) satisfies z.ZodType<INodeTypeNameVersion>,
currentNodeParameters: z.record(z.string(), z.any()) satisfies z.ZodType<INodeParameters>,
methodName: z.string().optional(),
credentials: z.record(z.string(), z.any()).optional() satisfies z.ZodType<
INodeCredentials | undefined
>,
}) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { ILoadOptions } from 'n8n-workflow';
import { z } from 'zod';

import { BaseDynamicParametersRequestDto } from './base-dynamic-parameters-request.dto';

export class OptionsRequestDto extends BaseDynamicParametersRequestDto.extend({
loadOptions: z
.object({
routing: z
.object({
operations: z.any().optional(),
output: z.any().optional(),
request: z.any().optional(),
})
.optional(),
})
.optional() as z.ZodType<ILoadOptions | undefined>,
}) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { z } from 'zod';

import { BaseDynamicParametersRequestDto } from './base-dynamic-parameters-request.dto';

export class ResourceLocatorRequestDto extends BaseDynamicParametersRequestDto.extend({
methodName: z.string(),
filter: z.string().optional(),
paginationToken: z.string().optional(),
}) {}
Loading

0 comments on commit 46a8d59

Please sign in to comment.