mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-31 16:57:08 +02:00
feat(core): Add startDate and endDate filter query to insights endpoints (#19954)
This commit is contained in:
parent
efbd4a3392
commit
7c3e1c9e01
|
|
@ -13,8 +13,39 @@ describe('InsightsDateFilterDto', () => {
|
|||
request: {
|
||||
dateRange: 'week', // Using a valid option from the provided list
|
||||
},
|
||||
parsedResult: {},
|
||||
},
|
||||
{
|
||||
name: 'valid startDate and endDate (as strings)',
|
||||
request: {
|
||||
startDate: '2025-01-01',
|
||||
endDate: '2025-01-31',
|
||||
},
|
||||
parsedResult: {
|
||||
dateRange: 'week',
|
||||
startDate: new Date('2025-01-01'),
|
||||
endDate: new Date('2025-01-31'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'valid startDate and endDate (as ISO strings)',
|
||||
request: {
|
||||
startDate: '2025-01-01T00:00:00Z',
|
||||
endDate: '2025-01-31T23:59:59Z',
|
||||
},
|
||||
parsedResult: {
|
||||
startDate: new Date('2025-01-01T00:00:00Z'),
|
||||
endDate: new Date('2025-01-31T23:59:59Z'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'valid startDate and endDate (as timestamps)',
|
||||
request: {
|
||||
startDate: new Date('2025-01-01').getTime(),
|
||||
endDate: new Date('2025-01-31').getTime(),
|
||||
},
|
||||
parsedResult: {
|
||||
startDate: new Date('2025-01-01'),
|
||||
endDate: new Date('2025-01-31'),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -37,31 +68,74 @@ describe('InsightsDateFilterDto', () => {
|
|||
|
||||
describe('Invalid requests', () => {
|
||||
test.each([
|
||||
{
|
||||
name: 'invalid startDate format',
|
||||
request: {
|
||||
startDate: '2025-13-01', // Invalid month
|
||||
endDate: '2025-13-31', // Invalid month
|
||||
},
|
||||
expectedErrorPaths: ['startDate', 'endDate'],
|
||||
},
|
||||
{
|
||||
name: 'startDate is an invalid timestamp',
|
||||
request: {
|
||||
startDate: NaN,
|
||||
},
|
||||
expectedErrorPaths: ['startDate'],
|
||||
},
|
||||
{
|
||||
name: 'endDate is an invalid timestamp',
|
||||
request: {
|
||||
endDate: NaN,
|
||||
projectId: 'validProjectId',
|
||||
},
|
||||
expectedErrorPaths: ['endDate'],
|
||||
},
|
||||
{
|
||||
name: 'startDate is an invalid ISO string',
|
||||
request: {
|
||||
startDate: 'invalid--date',
|
||||
},
|
||||
expectedErrorPaths: ['startDate'],
|
||||
},
|
||||
{
|
||||
name: 'endDate is an invalid ISO string',
|
||||
request: {
|
||||
startDate: '2025-01-01',
|
||||
endDate: 'not-a-date',
|
||||
},
|
||||
expectedErrorPaths: ['endDate'],
|
||||
},
|
||||
{
|
||||
name: 'invalid dateRange value',
|
||||
request: {
|
||||
dateRange: 'invalid-value',
|
||||
},
|
||||
expectedErrorPath: ['dateRange'],
|
||||
expectedErrorPaths: ['dateRange'],
|
||||
},
|
||||
{
|
||||
name: 'invalid projectId value',
|
||||
request: {
|
||||
projectId: 10,
|
||||
},
|
||||
expectedErrorPath: ['projectId'],
|
||||
expectedErrorPaths: ['projectId'],
|
||||
},
|
||||
])('should fail validation for $name', ({ request, expectedErrorPath }) => {
|
||||
{
|
||||
name: 'all fields invalid',
|
||||
request: {
|
||||
dateRange: 'invalid-value',
|
||||
startDate: '2025-13-01', // Invalid month
|
||||
endDate: 'not-a-date',
|
||||
projectId: 10,
|
||||
},
|
||||
expectedErrorPaths: ['dateRange', 'startDate', 'endDate', 'projectId'],
|
||||
},
|
||||
])('should fail validation for $name', ({ request, expectedErrorPaths }) => {
|
||||
const result = InsightsDateFilterDto.safeParse(request);
|
||||
const issuesPaths = new Set(result.error?.issues.map((issue) => issue.path[0]));
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
|
||||
if (expectedErrorPath && !result.success) {
|
||||
if (Array.isArray(expectedErrorPath)) {
|
||||
const errorPaths = result.error.issues[0].path;
|
||||
expect(errorPaths).toContain(expectedErrorPath[0]);
|
||||
}
|
||||
}
|
||||
expect(new Set(issuesPaths)).toEqual(new Set(expectedErrorPaths));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -86,6 +86,39 @@ describe('ListInsightsWorkflowQueryDto', () => {
|
|||
projectId: '2gQLpmP5V4wOY627',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'valid startDate and endDate (as strings)',
|
||||
request: {
|
||||
startDate: '2025-01-01',
|
||||
endDate: '2025-01-31',
|
||||
},
|
||||
parsedResult: {
|
||||
startDate: new Date('2025-01-01'),
|
||||
endDate: new Date('2025-01-31'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'valid startDate and endDate (as ISO strings)',
|
||||
request: {
|
||||
startDate: '2025-01-01T00:00:00Z',
|
||||
endDate: '2025-01-31T23:59:59Z',
|
||||
},
|
||||
parsedResult: {
|
||||
startDate: new Date('2025-01-01T00:00:00Z'),
|
||||
endDate: new Date('2025-01-31T23:59:59Z'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'valid startDate and endDate (as timestamps)',
|
||||
request: {
|
||||
startDate: new Date('2025-01-01').getTime(),
|
||||
endDate: new Date('2025-01-31').getTime(),
|
||||
},
|
||||
parsedResult: {
|
||||
startDate: new Date('2025-01-01'),
|
||||
endDate: new Date('2025-01-31'),
|
||||
},
|
||||
},
|
||||
])('should validate $name', ({ request, parsedResult }) => {
|
||||
const result = ListInsightsWorkflowQueryDto.safeParse(request);
|
||||
expect(result.success).toBe(true);
|
||||
|
|
@ -103,7 +136,7 @@ describe('ListInsightsWorkflowQueryDto', () => {
|
|||
skip: 'not-a-number',
|
||||
take: '10',
|
||||
},
|
||||
expectedErrorPath: ['skip'],
|
||||
expectedErrorPaths: ['skip'],
|
||||
},
|
||||
{
|
||||
name: 'invalid take format',
|
||||
|
|
@ -111,33 +144,77 @@ describe('ListInsightsWorkflowQueryDto', () => {
|
|||
skip: '0',
|
||||
take: 'not-a-number',
|
||||
},
|
||||
expectedErrorPath: ['take'],
|
||||
expectedErrorPaths: ['take'],
|
||||
},
|
||||
{
|
||||
name: 'invalid sortBy value',
|
||||
request: {
|
||||
sortBy: 'invalid-value',
|
||||
},
|
||||
expectedErrorPath: ['sortBy'],
|
||||
expectedErrorPaths: ['sortBy'],
|
||||
},
|
||||
{
|
||||
name: 'invalid projectId value',
|
||||
request: {
|
||||
projectId: 10,
|
||||
},
|
||||
expectedErrorPath: ['projectId'],
|
||||
expectedErrorPaths: ['projectId'],
|
||||
},
|
||||
])('should fail validation for $name', ({ request, expectedErrorPath }) => {
|
||||
{
|
||||
name: 'invalid startDate format',
|
||||
request: {
|
||||
startDate: '2025-13-01', // Invalid month
|
||||
endDate: '2025-13-31', // Invalid month
|
||||
},
|
||||
expectedErrorPaths: ['startDate', 'endDate'],
|
||||
},
|
||||
{
|
||||
name: 'startDate is an invalid timestamp',
|
||||
request: {
|
||||
startDate: NaN,
|
||||
},
|
||||
expectedErrorPaths: ['startDate'],
|
||||
},
|
||||
{
|
||||
name: 'endDate is an invalid timestamp',
|
||||
request: {
|
||||
endDate: NaN,
|
||||
projectId: 'validProjectId',
|
||||
},
|
||||
expectedErrorPaths: ['endDate'],
|
||||
},
|
||||
{
|
||||
name: 'startDate is an invalid ISO string',
|
||||
request: {
|
||||
startDate: 'invalid--date',
|
||||
},
|
||||
expectedErrorPaths: ['startDate'],
|
||||
},
|
||||
{
|
||||
name: 'endDate is an invalid ISO string',
|
||||
request: {
|
||||
startDate: '2025-01-01',
|
||||
endDate: 'not-a-date',
|
||||
},
|
||||
expectedErrorPaths: ['endDate'],
|
||||
},
|
||||
{
|
||||
name: 'all fields invalid',
|
||||
request: {
|
||||
sortBy: 'invalid-value',
|
||||
startDate: '2025-13-01', // Invalid month
|
||||
endDate: 'not-a-date',
|
||||
projectId: 10,
|
||||
},
|
||||
expectedErrorPaths: ['sortBy', 'startDate', 'endDate', 'projectId'],
|
||||
},
|
||||
])('should fail validation for $name', ({ request, expectedErrorPaths }) => {
|
||||
const result = ListInsightsWorkflowQueryDto.safeParse(request);
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
const issuesPaths = new Set(result.error?.issues.map((issue) => issue.path[0]));
|
||||
|
||||
if (expectedErrorPath && !result.success) {
|
||||
if (Array.isArray(expectedErrorPath)) {
|
||||
const errorPaths = result.error.issues[0].path;
|
||||
expect(errorPaths).toContain(expectedErrorPath[0]);
|
||||
}
|
||||
}
|
||||
expect(result.success).toBe(false);
|
||||
expect(new Set(issuesPaths)).toEqual(new Set(expectedErrorPaths));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,5 +10,7 @@ const dateRange = z.enum(VALID_DATE_RANGE_OPTIONS).optional();
|
|||
|
||||
export class InsightsDateFilterDto extends Z.class({
|
||||
dateRange,
|
||||
startDate: z.coerce.date().optional(),
|
||||
endDate: z.coerce.date().optional(),
|
||||
projectId: z.string().optional(),
|
||||
}) {}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ export class ListInsightsWorkflowQueryDto extends Z.class({
|
|||
...paginationSchema,
|
||||
take: createTakeValidator(MAX_ITEMS_PER_PAGE),
|
||||
dateRange: InsightsDateFilterDto.shape.dateRange,
|
||||
startDate: z.coerce.date().optional(),
|
||||
endDate: z.coerce.date().optional(),
|
||||
sortBy: sortByValidator,
|
||||
projectId: z.string().optional(),
|
||||
}) {}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user