diff --git a/plugins/orchestrator-backend/src/helpers/queryBuilder.test.ts b/plugins/orchestrator-backend/src/helpers/queryBuilder.test.ts index bbda70ae37c..b53f91ca92a 100644 --- a/plugins/orchestrator-backend/src/helpers/queryBuilder.test.ts +++ b/plugins/orchestrator-backend/src/helpers/queryBuilder.test.ts @@ -1,5 +1,14 @@ +import { + FieldFilterOperatorEnum, + Filter, + IntrospectionField, + LogicalFilter, + TypeKind, + TypeName, +} from '@janus-idp/backstage-plugin-orchestrator-common'; + import { Pagination } from '../types/pagination'; -import { buildGraphQlQuery } from './queryBuilder'; +import { buildFilterCondition, buildGraphQlQuery } from './queryBuilder'; describe('buildGraphQlQuery', () => { const queryBody = 'id status'; @@ -56,3 +65,295 @@ describe('buildGraphQlQuery', () => { ); }); }); +describe('column filters', () => { + it('returns empty string when filters are null or undefined', () => { + expect(buildFilterCondition([])).toBe(''); + }); + + it('one string field', () => { + // Given + const introspectionFields: IntrospectionField[] = [ + { + name: 'name', + type: { + name: TypeName.String, + kind: TypeKind.InputObject, + ofType: null, + }, + }, + ]; + const filedFilter = { + field: 'name', + operator: FieldFilterOperatorEnum.Eq, + value: 'Hello World Workflow', + }; + const logicalFilter: Filter = filedFilter; + + // When + const result = buildFilterCondition(introspectionFields, logicalFilter); + + // Then + expect(result).toBe('name: {equal: "Hello World Workflow"}'); + }); + + it('two string field with or', () => { + // Given + const introspectionFields: IntrospectionField[] = [ + { + name: 'name', + type: { + name: TypeName.String, + kind: TypeKind.InputObject, + ofType: null, + }, + }, + { + name: 'id', + type: { + name: TypeName.String, + kind: TypeKind.InputObject, + ofType: null, + }, + }, + ]; + + const helloWorldFilter = { + field: 'name', + operator: FieldFilterOperatorEnum.Eq, + value: 'Hello World Workflow', + }; + const greetingFilter = { + field: 'id', + operator: FieldFilterOperatorEnum.Eq, + value: 'yamlgreet', + }; + + const logicalFilter: LogicalFilter = { + operator: 'OR', + filters: [helloWorldFilter, greetingFilter], + }; + // When + const result = buildFilterCondition(introspectionFields, logicalFilter); + + // Then + expect(result).toBe( + 'or: {name: {equal: "Hello World Workflow"}, id: {equal: "yamlgreet"}}', + ); + }); + + it('multiple string field with or', () => { + // Given + const introspectionFields: IntrospectionField[] = + createIntrospectionFields(5); + const stringFilters = createStringFilter(5); + + const logicalFilter: LogicalFilter = { + operator: 'OR', + filters: stringFilters, + }; + // When + const result = buildFilterCondition(introspectionFields, logicalFilter); + + // Then + expect(result).toBe( + 'or: {name_0: {equal: "value_0"}, name_1: {equal: "value_1"}, name_2: {equal: "value_2"}, name_3: {equal: "value_3"}, name_4: {equal: "value_4"}}', + ); + }); + + it('two string field with and', () => { + // Given + const introspectionFields: IntrospectionField[] = [ + { + name: 'name', + type: { + name: TypeName.String, + kind: TypeKind.InputObject, + ofType: null, + }, + }, + { + name: 'id', + type: { + name: TypeName.String, + kind: TypeKind.InputObject, + ofType: null, + }, + }, + ]; + + const helloWorldFilter = { + field: 'name', + operator: FieldFilterOperatorEnum.Eq, + value: 'Hello World Workflow', + }; + const greetingFilter = { + field: 'id', + operator: FieldFilterOperatorEnum.Eq, + value: 'yamlgreet', + }; + + const logicalFilter: LogicalFilter = { + operator: 'AND', + filters: [helloWorldFilter, greetingFilter], + }; + // When + const result = buildFilterCondition(introspectionFields, logicalFilter); + + // Then + expect(result).toBe( + 'and: {name: {equal: "Hello World Workflow"}, id: {equal: "yamlgreet"}}', + ); + }); + + it('in operator with strings', () => { + // Given + const introspectionFields: IntrospectionField[] = [ + { + name: 'name', + type: { + name: TypeName.String, + kind: TypeKind.InputObject, + ofType: null, + }, + }, + ]; + const filedFilter = { + field: 'name', + operator: FieldFilterOperatorEnum.In, + value: ['Hello World Workflow', 'Greeting Workflow'], + }; + const logicalFilter: Filter = filedFilter; + // When + const result = buildFilterCondition(introspectionFields, logicalFilter); + + // Then + expect(result).toBe( + 'name: {in: ["Hello World Workflow", "Greeting Workflow"]}', + ); + }); + + it('isNull operator true string', () => { + // Given + const introspectionFields: IntrospectionField[] = [ + { + name: 'name', + type: { + name: TypeName.String, + kind: TypeKind.InputObject, + ofType: null, + }, + }, + ]; + const filedFilter = { + field: 'name', + operator: FieldFilterOperatorEnum.IsNull, + value: 'true', + }; + const logicalFilter: Filter = filedFilter; + // When + const result = buildFilterCondition(introspectionFields, logicalFilter); + + // Then + expect(result).toBe('name: {isNull: true}'); + }); + + it('isNull operator true number', () => { + // Given + const introspectionFields: IntrospectionField[] = [ + { + name: 'name', + type: { + name: TypeName.String, + kind: TypeKind.InputObject, + ofType: null, + }, + }, + ]; + const filedFilter = { + field: 'name', + operator: FieldFilterOperatorEnum.IsNull, + value: 1, + }; + const logicalFilter: Filter = filedFilter; + // When + const result = buildFilterCondition(introspectionFields, logicalFilter); + + // Then + expect(result).toBe('name: {isNull: true}'); + }); + it('isNull operator false string', () => { + // Given + const introspectionFields: IntrospectionField[] = [ + { + name: 'name', + type: { + name: TypeName.String, + kind: TypeKind.InputObject, + ofType: null, + }, + }, + ]; + const filedFilter = { + field: 'name', + operator: FieldFilterOperatorEnum.IsNull, + value: 'false', + }; + const logicalFilter: Filter = filedFilter; + // When + const result = buildFilterCondition(introspectionFields, logicalFilter); + + // Then + expect(result).toBe('name: {isNull: false}'); + }); + + it('isNull operator false number', () => { + // Given + const introspectionFields: IntrospectionField[] = [ + { + name: 'name', + type: { + name: TypeName.String, + kind: TypeKind.InputObject, + ofType: null, + }, + }, + ]; + const filedFilter = { + field: 'name', + operator: FieldFilterOperatorEnum.IsNull, + value: 0, + }; + const logicalFilter: Filter = filedFilter; + // When + const result = buildFilterCondition(introspectionFields, logicalFilter); + + // Then + expect(result).toBe('name: {isNull: false}'); + }); + + function createStringFilter(howmany: number): Filter[] { + const filters: Filter[] = []; + for (let i = 0; i < howmany; i++) { + filters.push({ + field: `name_${i}`, + operator: FieldFilterOperatorEnum.Eq, + value: `value_${i}`, + }); + } + return filters; + } + function createIntrospectionFields(howmany: number): IntrospectionField[] { + const introspectionFields: IntrospectionField[] = []; + for (let i = 0; i < howmany; i++) { + introspectionFields.push({ + name: `name_${i}`, + type: { + name: TypeName.String, + kind: TypeKind.InputObject, + ofType: null, + }, + }); + } + return introspectionFields; + } +}); diff --git a/plugins/orchestrator-backend/src/service/DataIndexService.test.ts b/plugins/orchestrator-backend/src/service/DataIndexService.test.ts index 20c66952dab..1a876aa472d 100644 --- a/plugins/orchestrator-backend/src/service/DataIndexService.test.ts +++ b/plugins/orchestrator-backend/src/service/DataIndexService.test.ts @@ -3,14 +3,18 @@ import { LoggerService } from '@backstage/backend-plugin-api'; import { Client, OperationResult } from '@urql/core'; import { - FilterInfo, + FieldFilterOperatorEnum, + LogicalFilter, NodeInstance, ProcessInstance, + TypeKind, + TypeName, WorkflowInfo, } from '@janus-idp/backstage-plugin-orchestrator-common'; import * as graphqlUtils from '../helpers/queryBuilder'; import { Pagination } from '../types/pagination'; +import { mockProcessDefinitionArguments } from './__fixtures__/mockProcessDefinitionArgumentsData'; import { DataIndexService } from './DataIndexService'; jest.mock('../helpers/queryBuilder', () => { @@ -37,6 +41,25 @@ const mockOperationResult = (data: T, error?: any): OperationResult => ({ stale: false, }); +const filterString = + 'or: {name: {equal: "Hello World Workflow"}, id: {equal: "yamlgreet"}}'; + +const helloWorldFilter = { + field: 'name', + operator: FieldFilterOperatorEnum.Eq, + value: 'Hello World Workflow', +}; +const greetingFilter = { + field: 'id', + operator: FieldFilterOperatorEnum.Eq, + value: 'yamlgreet', +}; + +const logicalFilter: LogicalFilter = { + operator: 'OR', + filters: [helloWorldFilter, greetingFilter], +}; + const createQueryArgs = ( type: 'ProcessDefinitions' | 'ProcessInstances' | 'Jobs', queryBody: string, @@ -49,6 +72,82 @@ const createQueryArgs = ( pagination, }); +describe('fetchGraphQLSchema', () => { + type MockableClient = Pick; + const createMockClient = (): jest.Mocked => ({ + query: jest.fn(), + }); + + let loggerMock: LoggerService; + let dataIndexService: DataIndexService; + let mockClient: jest.Mocked; + + beforeEach(() => { + jest.resetAllMocks(); + jest.clearAllMocks(); + // Create a new mock client for each test + mockClient = createMockClient(); + (Client as jest.MockedClass).mockImplementation( + () => mockClient as unknown as Client, + ); + + loggerMock = { + info: jest.fn(), + debug: jest.fn(), + error: jest.fn(), + warn: jest.fn(), + child: jest.fn(), + }; + mockClient.query.mockResolvedValueOnce( + mockOperationResult(mockProcessDefinitionArguments), + ); + dataIndexService = new DataIndexService('fakeUrl', loggerMock); + }); + + it('test constructor', async () => { + const processDefinitionArguments = + await dataIndexService.processDefinitionArguments; + + expect(mockClient.query).toHaveBeenCalledTimes(1); + expect(mockClient.query).toHaveBeenCalledWith( + dataIndexService.graphQLArgumentQuery('ProcessDefinition'), + {}, + ); + + expect(processDefinitionArguments).toBeDefined(); + expect( + processDefinitionArguments.every( + val => !['and', 'or', 'not'].includes(val.name), + ), + ).toBe(true); + expect(processDefinitionArguments).toHaveLength(3); + expect( + processDefinitionArguments.some( + obj => + obj.name === 'id' && + obj.type.kind === TypeKind.InputObject && + obj.type.name === TypeName.String, + ), + ).toBe(true); + expect( + processDefinitionArguments.some( + obj => + obj.name === 'name' && + obj.type.kind === TypeKind.InputObject && + obj.type.name === TypeName.String, + ), + ).toBe(true); + expect( + processDefinitionArguments.some( + obj => + obj.name === 'version' && + obj.type.kind === TypeKind.InputObject && + obj.type.name === TypeName.String, + ), + ).toBe(true); + }); +}); + describe('fetchWorkflowInfos', () => { let loggerMock: LoggerService; let buildFilterConditionSpy: any; @@ -59,13 +158,9 @@ describe('fetchWorkflowInfos', () => { const definitionIds = ['id1', 'id2']; const processDefinitions = [{ id: 'def1' }, { id: 'def2' }]; const queryBody = 'id, name, version, type, endpoint, serviceUrl, source'; + const pagination = { limit: 10, offset: 0, order: 'ASC', sortField: 'name' }; - const filter: FilterInfo = { - fieldName: 'foo', - operator: 'equal', - fieldValue: 'bar', - }; - const filterClause = 'foo:{ equal: bar}'; + beforeEach(() => { mockClient = { query: jest.fn(), @@ -80,6 +175,9 @@ describe('fetchWorkflowInfos', () => { warn: jest.fn(), child: jest.fn(), }; + mockClient.query.mockResolvedValueOnce( + mockOperationResult(mockProcessDefinitionArguments), + ); dataIndexService = new DataIndexService('fakeUrl', loggerMock); // Set up spies on the graphql utility functions @@ -97,11 +195,7 @@ describe('fetchWorkflowInfos', () => { mockOperationResult(mockQueryResult), ); - const expectedQueryArgs = createQueryArgs( - 'ProcessDefinitions', - queryBody, - '', - ); + const expectedQueryArgs = createQueryArgs('ProcessDefinitions', queryBody); // When const result = await dataIndexService.fetchWorkflowInfos({}); @@ -111,8 +205,7 @@ describe('fetchWorkflowInfos', () => { type: 'ProcessDefinitions', queryBody, }); - expect(buildFilterConditionSpy).toHaveBeenCalledTimes(1); - expect(buildFilterConditionSpy).toHaveBeenCalledWith(undefined); + expect(buildFilterConditionSpy).not.toHaveBeenCalled(); expect(mockClient.query).toHaveBeenCalled(); expect(mockClient.query).toHaveBeenCalledWith( graphqlUtils.buildGraphQlQuery(expectedQueryArgs), @@ -147,8 +240,7 @@ describe('fetchWorkflowInfos', () => { queryBody, whereClause, }); - expect(buildFilterConditionSpy).toHaveBeenCalledTimes(1); - expect(buildFilterConditionSpy).toHaveBeenCalledWith(undefined); + expect(buildFilterConditionSpy).not.toHaveBeenCalled(); expect(mockClient.query).toHaveBeenCalled(); expect(mockClient.query).toHaveBeenCalledWith( graphqlUtils.buildGraphQlQuery(expectedQueryArgs), @@ -185,8 +277,8 @@ describe('fetchWorkflowInfos', () => { whereClause: `id: {in: ${JSON.stringify(definitionIds)}}`, pagination, }); - expect(buildFilterConditionSpy).toHaveBeenCalledTimes(1); - expect(buildFilterConditionSpy).toHaveBeenCalledWith(undefined); + expect(buildFilterConditionSpy).not.toHaveBeenCalled(); + expect(mockClient.query).toHaveBeenCalledTimes(1); expect(mockClient.query).toHaveBeenCalledWith( graphqlUtils.buildGraphQlQuery(expectedQueryArgs), @@ -206,22 +298,25 @@ describe('fetchWorkflowInfos', () => { const expectedQueryArgs = createQueryArgs( 'ProcessDefinitions', queryBody, - filterClause, + filterString, ); // When const result = await dataIndexService.fetchWorkflowInfos({ - filter: filter, + filter: logicalFilter, }); // Then expect(buildGraphQlQuerySpy).toHaveBeenCalledTimes(1); expect(buildGraphQlQuerySpy).toHaveBeenCalledWith({ type: 'ProcessDefinitions', - queryBody: 'id, name, version, type, endpoint, serviceUrl, source', - whereClause: 'foo:{ equal: bar}', + queryBody, + whereClause: filterString, }); expect(buildFilterConditionSpy).toHaveBeenCalledTimes(1); - expect(buildFilterConditionSpy).toHaveBeenCalledWith(filter); + expect(buildFilterConditionSpy).toHaveBeenCalledWith( + await dataIndexService.processDefinitionArguments, + logicalFilter, + ); expect(mockClient.query).toHaveBeenCalledTimes(1); expect(mockClient.query).toHaveBeenCalledWith( graphqlUtils.buildGraphQlQuery(expectedQueryArgs), @@ -233,7 +328,7 @@ describe('fetchWorkflowInfos', () => { it('should fetch workflow infos with definitionIds and filter', async () => { // Given - const whereClause = `and: [{id: {in: ${JSON.stringify(definitionIds)}}}, {${filterClause}}]`; + const whereClause = `and: [{id: {in: ${JSON.stringify(definitionIds)}}}, {${filterString}}]`; const mockQueryResult = { ProcessDefinitions: processDefinitions }; mockClient.query.mockResolvedValueOnce( mockOperationResult(mockQueryResult), @@ -244,10 +339,11 @@ describe('fetchWorkflowInfos', () => { queryBody, whereClause, ); + // When const result = await dataIndexService.fetchWorkflowInfos({ definitionIds, - filter, + filter: logicalFilter, }); // Then @@ -258,7 +354,10 @@ describe('fetchWorkflowInfos', () => { whereClause, }); expect(buildFilterConditionSpy).toHaveBeenCalledTimes(1); - expect(buildFilterConditionSpy).toHaveBeenCalledWith(filter); + expect(buildFilterConditionSpy).toHaveBeenCalledWith( + await dataIndexService.processDefinitionArguments, + logicalFilter, + ); expect(mockClient.query).toHaveBeenCalledTimes(1); expect(mockClient.query).toHaveBeenCalledWith( graphqlUtils.buildGraphQlQuery(expectedQueryArgs), @@ -270,7 +369,7 @@ describe('fetchWorkflowInfos', () => { it('should fetch workflow infos with definitionIds, pagination, and filter', async () => { // Given - const whereClause = `and: [{id: {in: ${JSON.stringify(definitionIds)}}}, {${filterClause}}]`; + const whereClause = `and: [{id: {in: ${JSON.stringify(definitionIds)}}}, {${filterString}}]`; const mockQueryResult = { ProcessDefinitions: processDefinitions }; mockClient.query.mockResolvedValueOnce( mockOperationResult(mockQueryResult), @@ -286,7 +385,7 @@ describe('fetchWorkflowInfos', () => { const result = await dataIndexService.fetchWorkflowInfos({ definitionIds, pagination, - filter, + filter: logicalFilter, }); // Then @@ -298,7 +397,10 @@ describe('fetchWorkflowInfos', () => { pagination, }); expect(buildFilterConditionSpy).toHaveBeenCalledTimes(1); - expect(buildFilterConditionSpy).toHaveBeenCalledWith(filter); + expect(buildFilterConditionSpy).toHaveBeenCalledWith( + await dataIndexService.processDefinitionArguments, + logicalFilter, + ); expect(mockClient.query).toHaveBeenCalledTimes(1); expect(mockClient.query).toHaveBeenCalledWith( graphqlUtils.buildGraphQlQuery(expectedQueryArgs), @@ -312,9 +414,9 @@ describe('fetchInstances', () => { let loggerMock: LoggerService; let buildFilterConditionSpy: any; let buildGraphQlQuerySpy: any; + let mockClient: jest.Mocked; let dataIndexService: DataIndexService; - let mockClient: jest.Mocked; const definitionIds = ['id1', 'id2']; const processInstances: ProcessInstance[] = [ @@ -332,12 +434,7 @@ describe('fetchInstances', () => { }, ]; const pagination = { limit: 10, offset: 0, order: 'ASC', sortField: 'name' }; - const filter: FilterInfo = { - fieldName: 'foo', - operator: 'equal', - fieldValue: 'bar', - }; - const filterClause = 'foo:{ equal: bar}'; + const processIdNotNullCondition = 'processId: {isNull: false}'; const processIdDefinitions = `processId: {in: ${JSON.stringify(definitionIds)}`; const queryBody = @@ -349,6 +446,10 @@ describe('fetchInstances', () => { } as any; (Client as jest.Mock).mockImplementation(() => mockClient); + mockClient.query.mockResolvedValueOnce( + mockOperationResult(mockProcessDefinitionArguments), + ); + const wfInfo: WorkflowInfo = { id: 'wfinfo1', source: 'workflow info source', @@ -395,8 +496,7 @@ describe('fetchInstances', () => { queryBody, whereClause, }); - expect(buildFilterConditionSpy).toHaveBeenCalledTimes(1); - expect(buildFilterConditionSpy).toHaveBeenCalledWith(undefined); + expect(buildFilterConditionSpy).not.toHaveBeenCalled(); expect(mockClient.query).toHaveBeenCalled(); expect(mockClient.query).toHaveBeenCalledWith( graphqlUtils.buildGraphQlQuery(expectedQueryArgs), @@ -433,8 +533,7 @@ describe('fetchInstances', () => { whereClause, pagination: undefined, }); - expect(buildFilterConditionSpy).toHaveBeenCalledTimes(1); - expect(buildFilterConditionSpy).toHaveBeenCalledWith(undefined); + expect(buildFilterConditionSpy).not.toHaveBeenCalled(); expect(mockClient.query).toHaveBeenCalled(); expect(mockClient.query).toHaveBeenCalledWith( graphqlUtils.buildGraphQlQuery(expectedQueryArgs), @@ -473,8 +572,8 @@ describe('fetchInstances', () => { whereClause, pagination, }); - expect(buildFilterConditionSpy).toHaveBeenCalledTimes(1); - expect(buildFilterConditionSpy).toHaveBeenCalledWith(undefined); + expect(buildFilterConditionSpy).not.toHaveBeenCalled(); + expect(mockClient.query).toHaveBeenCalledTimes(1); expect(mockClient.query).toHaveBeenCalledWith( graphqlUtils.buildGraphQlQuery(expectedQueryArgs), @@ -486,7 +585,7 @@ describe('fetchInstances', () => { it('should fetch instances with only filter', async () => { // Given - const whereClause = `and: [{${processIdNotNullCondition}}, {${filterClause}}]`; + const whereClause = `and: [{${processIdNotNullCondition}}, {${filterString}}]`; const mockQueryResult = { ProcessInstances: processInstances }; mockClient.query.mockResolvedValueOnce( mockOperationResult(mockQueryResult), @@ -499,7 +598,7 @@ describe('fetchInstances', () => { ); // When const result = await dataIndexService.fetchInstances({ - filter: filter, + filter: logicalFilter, }); // Then @@ -510,7 +609,10 @@ describe('fetchInstances', () => { whereClause, }); expect(buildFilterConditionSpy).toHaveBeenCalledTimes(1); - expect(buildFilterConditionSpy).toHaveBeenCalledWith(filter); + expect(buildFilterConditionSpy).toHaveBeenCalledWith( + await dataIndexService.processDefinitionArguments, + logicalFilter, + ); expect(mockClient.query).toHaveBeenCalledTimes(1); expect(mockClient.query).toHaveBeenCalledWith( graphqlUtils.buildGraphQlQuery(expectedQueryArgs), @@ -522,7 +624,7 @@ describe('fetchInstances', () => { it('should fetch instances with definitionIds and filter', async () => { // Given - const whereClause = `and: [{${processIdNotNullCondition}}, {${processIdDefinitions}}}, {${filterClause}}]`; + const whereClause = `and: [{${processIdNotNullCondition}}, {${processIdDefinitions}}}, {${filterString}}]`; const mockQueryResult = { ProcessInstances: processInstances }; mockClient.query.mockResolvedValueOnce( mockOperationResult(mockQueryResult), @@ -536,7 +638,7 @@ describe('fetchInstances', () => { // When const result = await dataIndexService.fetchInstances({ definitionIds, - filter, + filter: logicalFilter, }); // Then @@ -547,7 +649,10 @@ describe('fetchInstances', () => { whereClause, }); expect(buildFilterConditionSpy).toHaveBeenCalledTimes(1); - expect(buildFilterConditionSpy).toHaveBeenCalledWith(filter); + expect(buildFilterConditionSpy).toHaveBeenCalledWith( + await dataIndexService.processDefinitionArguments, + logicalFilter, + ); expect(mockClient.query).toHaveBeenCalledTimes(1); expect(mockClient.query).toHaveBeenCalledWith( graphqlUtils.buildGraphQlQuery(expectedQueryArgs), @@ -559,7 +664,7 @@ describe('fetchInstances', () => { it('should fetch instances with definitionIds, pagination, and filter', async () => { // Given - const whereClause = `and: [{${processIdNotNullCondition}}, {${processIdDefinitions}}}, {${filterClause}}]`; + const whereClause = `and: [{${processIdNotNullCondition}}, {${processIdDefinitions}}}, {${filterString}}]`; const mockQueryResult = { ProcessInstances: processInstances }; mockClient.query.mockResolvedValueOnce( mockOperationResult(mockQueryResult), @@ -575,7 +680,7 @@ describe('fetchInstances', () => { const result = await dataIndexService.fetchInstances({ definitionIds, pagination, - filter, + filter: logicalFilter, }); // Then @@ -587,7 +692,10 @@ describe('fetchInstances', () => { pagination, }); expect(buildFilterConditionSpy).toHaveBeenCalledTimes(1); - expect(buildFilterConditionSpy).toHaveBeenCalledWith(filter); + expect(buildFilterConditionSpy).toHaveBeenCalledWith( + await dataIndexService.processDefinitionArguments, + logicalFilter, + ); expect(mockClient.query).toHaveBeenCalledTimes(1); expect(mockClient.query).toHaveBeenCalledWith( graphqlUtils.buildGraphQlQuery(expectedQueryArgs), diff --git a/plugins/orchestrator-backend/src/service/__fixtures__/mockProcessDefinitionArgumentsData.ts b/plugins/orchestrator-backend/src/service/__fixtures__/mockProcessDefinitionArgumentsData.ts new file mode 100644 index 00000000000..ac577123949 --- /dev/null +++ b/plugins/orchestrator-backend/src/service/__fixtures__/mockProcessDefinitionArgumentsData.ts @@ -0,0 +1,72 @@ +export const mockProcessDefinitionArguments = { + __type: { + kind: 'INPUT_OBJECT', + name: 'ProcessDefinitionArgument', + inputFields: [ + { + name: 'and', + type: { + kind: 'LIST', + name: null, + ofType: { + kind: 'NON_NULL', + name: null, + ofType: { + kind: 'INPUT_OBJECT', + name: 'ProcessDefinitionArgument', + ofType: null, + }, + }, + }, + }, + { + name: 'or', + type: { + kind: 'LIST', + name: null, + ofType: { + kind: 'NON_NULL', + name: null, + ofType: { + kind: 'INPUT_OBJECT', + name: 'ProcessDefinitionArgument', + ofType: null, + }, + }, + }, + }, + { + name: 'not', + type: { + kind: 'INPUT_OBJECT', + name: 'ProcessDefinitionArgument', + ofType: null, + }, + }, + { + name: 'id', + type: { + kind: 'INPUT_OBJECT', + name: 'StringArgument', + ofType: null, + }, + }, + { + name: 'name', + type: { + kind: 'INPUT_OBJECT', + name: 'StringArgument', + ofType: null, + }, + }, + { + name: 'version', + type: { + kind: 'INPUT_OBJECT', + name: 'StringArgument', + ofType: null, + }, + }, + ], + }, +}; diff --git a/plugins/orchestrator-backend/src/service/__fixtures__/mockProcessInstanceArgumentsData.ts b/plugins/orchestrator-backend/src/service/__fixtures__/mockProcessInstanceArgumentsData.ts new file mode 100644 index 00000000000..61fe4207236 --- /dev/null +++ b/plugins/orchestrator-backend/src/service/__fixtures__/mockProcessInstanceArgumentsData.ts @@ -0,0 +1,200 @@ +export const mockProcessInstanceArguments = { + __type: { + kind: 'INPUT_OBJECT', + name: 'ProcessInstanceArgument', + inputFields: [ + { + name: 'and', + type: { + kind: 'LIST', + name: null, + ofType: { + kind: 'NON_NULL', + name: null, + ofType: { + kind: 'INPUT_OBJECT', + name: 'ProcessInstanceArgument', + ofType: null, + }, + }, + }, + }, + { + name: 'or', + type: { + kind: 'LIST', + name: null, + ofType: { + kind: 'NON_NULL', + name: null, + ofType: { + kind: 'INPUT_OBJECT', + name: 'ProcessInstanceArgument', + ofType: null, + }, + }, + }, + }, + { + name: 'not', + type: { + kind: 'INPUT_OBJECT', + name: 'ProcessInstanceArgument', + ofType: null, + }, + }, + { + name: 'id', + type: { + kind: 'INPUT_OBJECT', + name: 'IdArgument', + ofType: null, + }, + }, + { + name: 'processId', + type: { + kind: 'INPUT_OBJECT', + name: 'StringArgument', + ofType: null, + }, + }, + { + name: 'processName', + type: { + kind: 'INPUT_OBJECT', + name: 'StringArgument', + ofType: null, + }, + }, + { + name: 'parentProcessInstanceId', + type: { + kind: 'INPUT_OBJECT', + name: 'IdArgument', + ofType: null, + }, + }, + { + name: 'rootProcessInstanceId', + type: { + kind: 'INPUT_OBJECT', + name: 'IdArgument', + ofType: null, + }, + }, + { + name: 'rootProcessId', + type: { + kind: 'INPUT_OBJECT', + name: 'StringArgument', + ofType: null, + }, + }, + { + name: 'state', + type: { + kind: 'INPUT_OBJECT', + name: 'ProcessInstanceStateArgument', + ofType: null, + }, + }, + { + name: 'error', + type: { + kind: 'INPUT_OBJECT', + name: 'ProcessInstanceErrorArgument', + ofType: null, + }, + }, + { + name: 'nodes', + type: { + kind: 'INPUT_OBJECT', + name: 'NodeInstanceArgument', + ofType: null, + }, + }, + { + name: 'milestones', + type: { + kind: 'INPUT_OBJECT', + name: 'MilestoneArgument', + ofType: null, + }, + }, + { + name: 'endpoint', + type: { + kind: 'INPUT_OBJECT', + name: 'StringArgument', + ofType: null, + }, + }, + { + name: 'roles', + type: { + kind: 'INPUT_OBJECT', + name: 'StringArrayArgument', + ofType: null, + }, + }, + { + name: 'start', + type: { + kind: 'INPUT_OBJECT', + name: 'DateArgument', + ofType: null, + }, + }, + { + name: 'end', + type: { + kind: 'INPUT_OBJECT', + name: 'DateArgument', + ofType: null, + }, + }, + { + name: 'addons', + type: { + kind: 'INPUT_OBJECT', + name: 'StringArrayArgument', + ofType: null, + }, + }, + { + name: 'lastUpdate', + type: { + kind: 'INPUT_OBJECT', + name: 'DateArgument', + ofType: null, + }, + }, + { + name: 'businessKey', + type: { + kind: 'INPUT_OBJECT', + name: 'StringArgument', + ofType: null, + }, + }, + { + name: 'createdBy', + type: { + kind: 'INPUT_OBJECT', + name: 'StringArgument', + ofType: null, + }, + }, + { + name: 'updatedBy', + type: { + kind: 'INPUT_OBJECT', + name: 'StringArgument', + ofType: null, + }, + }, + ], + }, +}; diff --git a/plugins/orchestrator-backend/src/service/api/v2.test.ts b/plugins/orchestrator-backend/src/service/api/v2.test.ts index 3956f0ff992..5ab52c5c306 100644 --- a/plugins/orchestrator-backend/src/service/api/v2.test.ts +++ b/plugins/orchestrator-backend/src/service/api/v2.test.ts @@ -4,7 +4,6 @@ import { AssessedProcessInstanceDTO, ExecuteWorkflowResponseDTO, FieldFilterOperatorEnum, - LogicalFilterOperatorEnum, ProcessInstanceListResultDTO, SearchRequest, toWorkflowYaml, @@ -174,7 +173,7 @@ describe('getWorkflowOverview', () => { it('filter test', async () => { // Arrange - // category = "electronics" AND (price <= 1000 OR (brand IN ("Apple", "Samsung") AND brand != 'LG')) + // category = "electronics" AND (price <= 1000 OR (brand IN ("Apple", "Samsung") AND brand like 'Apple')) const mockRequest: SearchRequest = { filters: { operator: 'AND', @@ -202,8 +201,8 @@ describe('getWorkflowOverview', () => { }, { field: 'brand', - operator: FieldFilterOperatorEnum.Ne, - value: 'LG', + operator: FieldFilterOperatorEnum.Like, + value: 'Apple', }, ], },