feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ContainerModule, injectable } from 'inversify';
|
||||
import {
|
||||
type PlaygroundContext,
|
||||
type FlowNodeEntity,
|
||||
type EntityManager,
|
||||
FlowDocumentContribution,
|
||||
EntityManagerContribution,
|
||||
createFreeHistoryPlugin,
|
||||
FormModelV2,
|
||||
FlowNodeFormData,
|
||||
createNodeContainerModules,
|
||||
createNodeEntityDatas,
|
||||
FlowDocumentContainerModule,
|
||||
PlaygroundMockTools,
|
||||
Playground,
|
||||
loadPlugins,
|
||||
bindContributions,
|
||||
} from '@flowgram-adapter/free-layout-editor';
|
||||
import {
|
||||
type WorkflowDocument,
|
||||
WorkflowDocumentContainerModule,
|
||||
} from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import { createWorkflowVariablePlugins } from '../src';
|
||||
import { MockNodeRegistry } from './node.mock';
|
||||
|
||||
@injectable()
|
||||
export class MockPlaygroundContext implements PlaygroundContext {
|
||||
getNodeTemplateInfoByType() {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export class MockWorkflowForm
|
||||
implements FlowDocumentContribution, EntityManagerContribution
|
||||
{
|
||||
registerDocument(document: WorkflowDocument): void {
|
||||
document.registerNodeDatas(...createNodeEntityDatas());
|
||||
}
|
||||
|
||||
registerEntityManager(entityManager: EntityManager): void {
|
||||
const formModelFactory = (entity: FlowNodeEntity) =>
|
||||
new FormModelV2(entity);
|
||||
entityManager.registerEntityData(
|
||||
FlowNodeFormData,
|
||||
() =>
|
||||
({
|
||||
formModelFactory,
|
||||
}) as any,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const testModule = new ContainerModule(bind => {
|
||||
bindContributions(bind, MockWorkflowForm, [
|
||||
FlowDocumentContribution,
|
||||
EntityManagerContribution,
|
||||
]);
|
||||
bindContributions(bind, MockNodeRegistry, [FlowDocumentContribution]);
|
||||
});
|
||||
|
||||
export function createContainer() {
|
||||
const container = PlaygroundMockTools.createContainer([
|
||||
FlowDocumentContainerModule,
|
||||
WorkflowDocumentContainerModule,
|
||||
...createNodeContainerModules(),
|
||||
testModule,
|
||||
]);
|
||||
const playground = container.get(Playground);
|
||||
|
||||
loadPlugins(
|
||||
[
|
||||
createFreeHistoryPlugin({ enable: true, limit: 50 }),
|
||||
...createWorkflowVariablePlugins(),
|
||||
],
|
||||
container,
|
||||
);
|
||||
playground.init();
|
||||
return container;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
WorkflowNodeInputVariablesData,
|
||||
WorkflowNodeOutputVariablesData,
|
||||
WorkflowNodeRefVariablesData,
|
||||
} from 'src';
|
||||
import { loopJSON } from '__tests__/workflow.mock';
|
||||
import { createContainer } from '__tests__/create-container';
|
||||
import { WorkflowDocument } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
describe('test workflow node variables entity data', () => {
|
||||
let workflowDocument: WorkflowDocument;
|
||||
|
||||
beforeEach(async () => {
|
||||
const container = createContainer();
|
||||
workflowDocument = container.get<WorkflowDocument>(WorkflowDocument);
|
||||
|
||||
await workflowDocument.fromJSON(loopJSON);
|
||||
});
|
||||
|
||||
test('test workflow-node-input-variables-data', () => {
|
||||
const nodes = workflowDocument.getAllNodes();
|
||||
|
||||
expect(
|
||||
nodes.map(_node => {
|
||||
const data = _node.getData(WorkflowNodeInputVariablesData);
|
||||
|
||||
return [
|
||||
_node.id,
|
||||
data.inputParameters,
|
||||
data.inputVariables.map(_input => _input.refVariable?.viewType),
|
||||
];
|
||||
}),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('test workflow-node-output-variables-data', () => {
|
||||
const nodes = workflowDocument.getAllNodes();
|
||||
|
||||
expect(
|
||||
nodes.map(_node => {
|
||||
const data = _node.getData(WorkflowNodeOutputVariablesData);
|
||||
|
||||
return [
|
||||
_node.id,
|
||||
data.variables.map(
|
||||
_variable => data.getVariableByKey(_variable.key)?.viewType,
|
||||
),
|
||||
];
|
||||
}),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('test workflow-node-ref-variables-data', () => {
|
||||
const nodes = workflowDocument.getAllNodes();
|
||||
|
||||
expect(
|
||||
nodes.map(_node => {
|
||||
const data = _node.getData(WorkflowNodeRefVariablesData);
|
||||
|
||||
return [
|
||||
_node.id,
|
||||
data.refs,
|
||||
Object.values(data.refVariables).map(_ref => _ref?.viewType),
|
||||
data.hasGlobalRef,
|
||||
];
|
||||
}),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('test batchUpdateRefs', () => {
|
||||
const endNode = workflowDocument.getNode('end');
|
||||
|
||||
const data = endNode?.getData(WorkflowNodeRefVariablesData);
|
||||
|
||||
data?.batchUpdateRefs([
|
||||
{
|
||||
beforeKeyPath: ['llm_0'],
|
||||
afterKeyPath: ['llm_test'],
|
||||
},
|
||||
{
|
||||
beforeKeyPath: ['start', 'Object'],
|
||||
afterKeyPath: ['start', 'Drilldown', 'Object'],
|
||||
},
|
||||
]);
|
||||
|
||||
expect(data?.refs).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export default {};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable max-params */
|
||||
import { provideNodeOutputVariables } from 'src/form-extensions/variable-providers/provide-node-output-variables';
|
||||
import { provideNodeBatchVariables } from 'src/form-extensions/variable-providers/provide-node-batch-variables';
|
||||
import { provideMergeGroupVariables } from 'src/form-extensions/variable-providers/provide-merge-group-variables';
|
||||
import { provideLoopOutputsVariables } from 'src/form-extensions/variable-providers/provide-loop-output-variables';
|
||||
import { provideLoopInputsVariables } from 'src/form-extensions/variable-providers/provide-loop-input-variables';
|
||||
import { type VariableProviderAbilityOptions } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import {
|
||||
mockFullOutputs,
|
||||
mockRefInputs,
|
||||
mockMergeGroup,
|
||||
} from '../variable.mock';
|
||||
|
||||
const createCase = <V>(
|
||||
provider: VariableProviderAbilityOptions<V>,
|
||||
value: V,
|
||||
context: any = { node: { id: '12345' } },
|
||||
extraInfo = '',
|
||||
): {
|
||||
key: string;
|
||||
parse: (input: any, context: any) => any;
|
||||
value: V;
|
||||
context: any;
|
||||
extraInfo: string;
|
||||
} => ({
|
||||
key: provider.key || '',
|
||||
parse: provider.parse,
|
||||
value,
|
||||
context,
|
||||
extraInfo,
|
||||
});
|
||||
|
||||
describe('test variable providers', () => {
|
||||
test.each([
|
||||
createCase(provideLoopInputsVariables, {
|
||||
inputParameters: mockRefInputs,
|
||||
variableParameters: mockRefInputs,
|
||||
}),
|
||||
createCase(provideLoopOutputsVariables, mockRefInputs),
|
||||
createCase(provideMergeGroupVariables, mockMergeGroup),
|
||||
createCase(provideNodeBatchVariables, mockRefInputs, {
|
||||
node: { id: '123456' },
|
||||
formItem: { formModel: { getFormItemValueByPath: path => 'batch' } },
|
||||
}),
|
||||
createCase(provideNodeOutputVariables, mockFullOutputs),
|
||||
createCase(
|
||||
provideNodeBatchVariables,
|
||||
mockRefInputs,
|
||||
{
|
||||
node: { id: '123456' },
|
||||
formItem: {
|
||||
formModel: { getFormItemValueByPath: path => 'not_batch' },
|
||||
},
|
||||
},
|
||||
"shouldn't provide batch variables",
|
||||
),
|
||||
createCase(
|
||||
provideNodeBatchVariables,
|
||||
mockRefInputs,
|
||||
{
|
||||
node: { id: '123456' },
|
||||
formItem: {
|
||||
formModel: {
|
||||
getFormItemValueByPath: path =>
|
||||
path === '/batchMode' ? undefined : 'batch',
|
||||
},
|
||||
},
|
||||
},
|
||||
'batchMode in /inputs/batchMode',
|
||||
),
|
||||
])('test variable provider: $key $extraInfo', ({ parse, value, context }) => {
|
||||
expect(parse?.(value, context)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
86
frontend/packages/workflow/variable/__tests__/node.mock.tsx
Normal file
86
frontend/packages/workflow/variable/__tests__/node.mock.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { createEffectFromVariableProvider } from 'src/utils/variable-provider';
|
||||
import { provideNodeOutputVariables } from 'src/form-extensions/variable-providers/provide-node-output-variables';
|
||||
import { provideLoopOutputsVariables } from 'src/form-extensions/variable-providers/provide-loop-output-variables';
|
||||
import { provideLoopInputsVariables } from 'src/form-extensions/variable-providers/provide-loop-input-variables';
|
||||
import { provideMergeGroupVariablesEffect } from 'src';
|
||||
import { injectable } from 'inversify';
|
||||
import {
|
||||
type WorkflowDocument,
|
||||
type FlowDocumentContribution,
|
||||
} from '@flowgram-adapter/free-layout-editor';
|
||||
import { StandardNodeType } from '@coze-workflow/base/types';
|
||||
|
||||
@injectable()
|
||||
export class MockNodeRegistry implements FlowDocumentContribution {
|
||||
registerDocument(document: WorkflowDocument): void {
|
||||
// Register Nodes
|
||||
document.registerFlowNodes({
|
||||
type: StandardNodeType.LLM,
|
||||
formMeta: {
|
||||
render: () => <div></div>,
|
||||
effect: {
|
||||
outputs: createEffectFromVariableProvider(provideNodeOutputVariables),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
document.registerFlowNodes({
|
||||
type: StandardNodeType.Start,
|
||||
formMeta: {
|
||||
render: () => <div></div>,
|
||||
effect: {
|
||||
outputs: createEffectFromVariableProvider(provideNodeOutputVariables),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
document.registerFlowNodes({
|
||||
type: StandardNodeType.End,
|
||||
// getNodeInputParameters: () => [...allEndRefInputs, ...allConstantInputs],
|
||||
formMeta: {
|
||||
render: () => <div></div>,
|
||||
},
|
||||
});
|
||||
|
||||
document.registerFlowNodes({
|
||||
type: StandardNodeType.Loop,
|
||||
formMeta: {
|
||||
render: () => <div></div>,
|
||||
effect: {
|
||||
inputs: createEffectFromVariableProvider(provideLoopInputsVariables),
|
||||
outputs: createEffectFromVariableProvider(
|
||||
provideLoopOutputsVariables,
|
||||
),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
document.registerFlowNodes({
|
||||
type: StandardNodeType.VariableMerge,
|
||||
formMeta: {
|
||||
render: () => <div></div>,
|
||||
effect: {
|
||||
groups: provideMergeGroupVariablesEffect,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { WorkflowVariableService } from 'src';
|
||||
import { loopJSON } from '__tests__/workflow.mock';
|
||||
import { allKeyPaths } from '__tests__/variable.mock';
|
||||
import { createContainer } from '__tests__/create-container';
|
||||
import { WorkflowDocument } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
describe('test variable service', () => {
|
||||
let workflowDocument: WorkflowDocument;
|
||||
let variableService: WorkflowVariableService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const container = createContainer();
|
||||
workflowDocument = container.get<WorkflowDocument>(WorkflowDocument);
|
||||
variableService = container.get<WorkflowVariableService>(
|
||||
WorkflowVariableService,
|
||||
);
|
||||
|
||||
await workflowDocument.fromJSON(loopJSON);
|
||||
});
|
||||
|
||||
test('test get variable', () => {
|
||||
expect(
|
||||
allKeyPaths.map(_case => {
|
||||
const workflowVariable = variableService.getWorkflowVariableByKeyPath(
|
||||
_case,
|
||||
{},
|
||||
);
|
||||
|
||||
if (!workflowVariable) {
|
||||
return [variableService.getViewVariableByKeyPath(_case, {})];
|
||||
}
|
||||
|
||||
return [
|
||||
variableService.getViewVariableByKeyPath(_case, {}),
|
||||
workflowVariable.viewType,
|
||||
workflowVariable.renderType,
|
||||
workflowVariable.dtoMeta,
|
||||
workflowVariable.refExpressionDTO,
|
||||
workflowVariable.key,
|
||||
workflowVariable.parentVariables.map(_field => _field.key),
|
||||
workflowVariable.children.map(_field => _field.key),
|
||||
workflowVariable.expressionPath,
|
||||
workflowVariable.groupInfo,
|
||||
workflowVariable.node.id,
|
||||
];
|
||||
}),
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { variableUtils, WorkflowVariableService } from 'src';
|
||||
import { loopJSON } from '__tests__/workflow.mock';
|
||||
import { allConstantInputs, allEndRefInputs } from '__tests__/variable.mock';
|
||||
import { createContainer } from '__tests__/create-container';
|
||||
import { WorkflowDocument } from '@flowgram-adapter/free-layout-editor';
|
||||
import { ValueExpression } from '@coze-workflow/base';
|
||||
|
||||
import { mockFullOutputs } from './../variable.mock';
|
||||
|
||||
describe('test variable utils', () => {
|
||||
let workflowDocument: WorkflowDocument;
|
||||
let variableService: WorkflowVariableService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const container = createContainer();
|
||||
workflowDocument = container.get<WorkflowDocument>(WorkflowDocument);
|
||||
variableService = container.get<WorkflowVariableService>(
|
||||
WorkflowVariableService,
|
||||
);
|
||||
|
||||
await workflowDocument.fromJSON(loopJSON);
|
||||
});
|
||||
|
||||
test('Ref VO DTO convert', () => {
|
||||
const endNode = workflowDocument.getNode('end')!;
|
||||
|
||||
const allEndInputs = [...allEndRefInputs, ...allConstantInputs];
|
||||
|
||||
const dto = allEndInputs.map(_input =>
|
||||
variableUtils.inputValueToDTO(_input, variableService, {
|
||||
node: endNode,
|
||||
}),
|
||||
);
|
||||
expect(dto).toMatchSnapshot();
|
||||
|
||||
const voBack = dto
|
||||
.filter(Boolean)
|
||||
.map(_dto => variableUtils.inputValueToVO(_dto!, variableService));
|
||||
|
||||
const availableEndInputs = allEndInputs.filter(
|
||||
_ref => !ValueExpression.isEmpty(_ref.input),
|
||||
);
|
||||
|
||||
expect(availableEndInputs.length).toBeLessThan(allEndInputs.length);
|
||||
expect(voBack.length).toBe(availableEndInputs.length);
|
||||
voBack.forEach((_vo, idx) => {
|
||||
expect(_vo.name).toBe(availableEndInputs[idx].name);
|
||||
});
|
||||
});
|
||||
|
||||
test('Variable VO DTO convert', () => {
|
||||
const dto = mockFullOutputs.map(_output =>
|
||||
variableUtils.viewMetaToDTOMeta(_output),
|
||||
);
|
||||
|
||||
expect(dto).toMatchSnapshot();
|
||||
|
||||
const voBack = dto.map(_dto => variableUtils.dtoMetaToViewMeta(_dto));
|
||||
|
||||
voBack.forEach((_vo, idx) => {
|
||||
expect(_vo.type).toBe(mockFullOutputs[idx].type);
|
||||
expect(_vo.name).toBe(mockFullOutputs[idx].name);
|
||||
});
|
||||
});
|
||||
});
|
||||
39
frontend/packages/workflow/variable/__tests__/setup.ts
Normal file
39
frontend/packages/workflow/variable/__tests__/setup.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import 'reflect-metadata';
|
||||
vi.mock('@coze-arch/i18n', () => ({
|
||||
I18n: {
|
||||
t: vi.fn(),
|
||||
},
|
||||
}));
|
||||
vi.mock('@coze-arch/bot-flags', () => ({
|
||||
getFlags: () => ({
|
||||
'bot.automation.encapsulate': true,
|
||||
}),
|
||||
}));
|
||||
vi.mock('@coze-arch/coze-design', () => ({
|
||||
Typography: {
|
||||
Text: vi.fn(),
|
||||
},
|
||||
withField: vi.fn(),
|
||||
}));
|
||||
vi.mock('@coze-workflow/components', () => ({}));
|
||||
|
||||
vi.stubGlobal('IS_DEV_MODE', true);
|
||||
vi.stubGlobal('IS_OVERSEA', false);
|
||||
vi.stubGlobal('IS_BOE', false);
|
||||
vi.stubGlobal('REGION', 'cn');
|
||||
147
frontend/packages/workflow/variable/__tests__/variable.mock.ts
Normal file
147
frontend/packages/workflow/variable/__tests__/variable.mock.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable security/detect-object-injection */
|
||||
import { type InputItem } from 'src/form-extensions/variable-providers/common';
|
||||
import {
|
||||
ValueExpressionType,
|
||||
ViewVariableType,
|
||||
type ViewVariableMeta,
|
||||
} from 'src';
|
||||
import { type InputValueVO } from '@coze-workflow/base/types';
|
||||
|
||||
export const genInput = (name: string, keyPath: string[]): InputItem => ({
|
||||
name,
|
||||
input: {
|
||||
type: ValueExpressionType.REF,
|
||||
content: { keyPath },
|
||||
},
|
||||
});
|
||||
|
||||
export const mockKeyPaths = [
|
||||
['start', 'String'],
|
||||
['llm_0', 'Object'],
|
||||
['start', 'Object', 'Image'],
|
||||
['llm_0', 'Object', 'Number'],
|
||||
['start', 'Array<Code>'],
|
||||
['llm_0', 'Array<String>'],
|
||||
['start', 'Array<Object>', 'Number'],
|
||||
// Not existed
|
||||
['llm_0', 'Array<String>', 'Number'],
|
||||
['start', 'Object', 'Undefined'],
|
||||
[],
|
||||
];
|
||||
|
||||
export const mockMergeGroupKeyPaths = [
|
||||
['merge_0', 'test_group_1'],
|
||||
['merge_0', 'test_group_2'],
|
||||
];
|
||||
|
||||
export const mockKeyPathsInsideLoop = [
|
||||
['loop_0', 'loop_batch_llm_0__Object'],
|
||||
['loop_0', 'loop_var_llm_0__Object'],
|
||||
['loop_0', 'loop_batch_start__Array<Object>__Number'],
|
||||
['loop_0', 'loop_var_start__Array<Code>'],
|
||||
];
|
||||
|
||||
export const mockLoopOutputKeyPaths = [
|
||||
['loop_0', 'loop_output_var_string'],
|
||||
['loop_0', 'loop_output_string'],
|
||||
['loop_0', 'loop_output_image'],
|
||||
];
|
||||
|
||||
export const allKeyPaths = [
|
||||
...mockKeyPaths,
|
||||
...mockMergeGroupKeyPaths,
|
||||
...mockKeyPathsInsideLoop,
|
||||
...mockLoopOutputKeyPaths,
|
||||
];
|
||||
|
||||
export const allEndRefInputs = [
|
||||
...mockKeyPaths,
|
||||
...mockMergeGroupKeyPaths,
|
||||
...mockLoopOutputKeyPaths,
|
||||
].map(_keyPath => genInput(_keyPath.join('__'), _keyPath));
|
||||
|
||||
export const allConstantInputs: InputValueVO[] = [
|
||||
{
|
||||
name: 'test_constant_no_raw_meta',
|
||||
input: {
|
||||
type: ValueExpressionType.LITERAL,
|
||||
content: 'test_constant',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'test_constant_image_url',
|
||||
input: {
|
||||
type: ValueExpressionType.LITERAL,
|
||||
content: ['image_url'],
|
||||
rawMeta: { type: ViewVariableType.ArrayImage },
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'test_constant_array_object',
|
||||
input: {
|
||||
type: ValueExpressionType.LITERAL,
|
||||
content: [{ count: 0 }],
|
||||
rawMeta: {
|
||||
type: ViewVariableType.ArrayObject,
|
||||
children: [
|
||||
{
|
||||
key: 'count',
|
||||
name: 'count',
|
||||
type: ViewVariableType.Number,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const mockRefInputs: InputItem[] = mockKeyPaths.map(_keyPath =>
|
||||
genInput(mockKeyPaths.join('__'), _keyPath),
|
||||
);
|
||||
|
||||
export const mockRefValues = mockRefInputs.map(_input => _input.input);
|
||||
|
||||
export const mockMergeGroup = [
|
||||
{
|
||||
name: 'test_group_1',
|
||||
variables: mockRefValues,
|
||||
},
|
||||
{
|
||||
name: 'test_group_2',
|
||||
variables: mockRefValues.reverse(),
|
||||
},
|
||||
];
|
||||
|
||||
export const mockFullOutputs: ViewVariableMeta[] =
|
||||
ViewVariableType.getComplement([]).map(_type => ({
|
||||
key: ViewVariableType.LabelMap[_type],
|
||||
name: ViewVariableType.LabelMap[_type],
|
||||
type: _type,
|
||||
required: true,
|
||||
description: 'test_description',
|
||||
children: ViewVariableType.canDrilldown(_type)
|
||||
? ViewVariableType.getComplement([]).map(_childType => ({
|
||||
key: ViewVariableType.LabelMap[_childType],
|
||||
name: ViewVariableType.LabelMap[_childType],
|
||||
type: _childType,
|
||||
required: true,
|
||||
description: 'test_child_description',
|
||||
}))
|
||||
: [],
|
||||
}));
|
||||
210
frontend/packages/workflow/variable/__tests__/workflow.mock.ts
Normal file
210
frontend/packages/workflow/variable/__tests__/workflow.mock.ts
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { type WorkflowJSON } from '@flowgram-adapter/free-layout-editor';
|
||||
import { StandardNodeType } from '@coze-workflow/base/types';
|
||||
|
||||
import {
|
||||
allEndRefInputs,
|
||||
genInput,
|
||||
mockFullOutputs,
|
||||
mockRefInputs,
|
||||
mockMergeGroup,
|
||||
} from './variable.mock';
|
||||
|
||||
/**
|
||||
* start(start) -> llm_0 -> variable_merge_0 -> end(end)
|
||||
* llm_2 -> llm_0
|
||||
* llm_2 -> llm_3
|
||||
*/
|
||||
export const complexMock: WorkflowJSON = {
|
||||
nodes: [
|
||||
{
|
||||
id: 'start',
|
||||
type: StandardNodeType.Start,
|
||||
meta: {
|
||||
position: {
|
||||
x: 180,
|
||||
y: 26.700000000000017,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
outputs: mockFullOutputs,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'end',
|
||||
type: StandardNodeType.End,
|
||||
meta: {
|
||||
position: {
|
||||
x: 1674.1103135413448,
|
||||
y: 40.63341482104891,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
inputParameters: allEndRefInputs,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'llm_0',
|
||||
type: StandardNodeType.LLM,
|
||||
meta: {
|
||||
position: {
|
||||
x: 918.2411574431025,
|
||||
y: 109.52852376445134,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
inputParameters: mockRefInputs,
|
||||
outputs: mockFullOutputs,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'merge_0',
|
||||
type: StandardNodeType.VariableMerge,
|
||||
data: {
|
||||
groups: mockMergeGroup,
|
||||
},
|
||||
meta: {
|
||||
position: {
|
||||
x: 779.2423264779079,
|
||||
y: -161.54447093414998,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'llm_2',
|
||||
type: StandardNodeType.LLM,
|
||||
meta: {
|
||||
position: {
|
||||
x: -56.433897883820265,
|
||||
y: 221.56518397907752,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'llm_3',
|
||||
type: StandardNodeType.LLM,
|
||||
meta: {
|
||||
position: {
|
||||
x: 1072.169867226058,
|
||||
y: 401.6455814216276,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '156471',
|
||||
type: StandardNodeType.LLM,
|
||||
meta: {
|
||||
position: {
|
||||
x: 914.727084798963,
|
||||
y: 576.5804057333598,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
sourceNodeID: 'variable_merge_0',
|
||||
targetNodeID: 'end',
|
||||
},
|
||||
{
|
||||
sourceNodeID: 'start',
|
||||
targetNodeID: 'llm_0',
|
||||
},
|
||||
{
|
||||
sourceNodeID: 'llm_2',
|
||||
targetNodeID: 'llm_0',
|
||||
},
|
||||
{
|
||||
sourceNodeID: 'llm_0',
|
||||
targetNodeID: 'variable_merge_0',
|
||||
},
|
||||
{
|
||||
sourceNodeID: 'llm_2',
|
||||
targetNodeID: 'llm_3',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const loopJSON: WorkflowJSON = {
|
||||
nodes: [
|
||||
...complexMock.nodes,
|
||||
{
|
||||
id: 'loop_0',
|
||||
type: StandardNodeType.Loop,
|
||||
meta: {
|
||||
position: { x: 1200, y: 0 },
|
||||
},
|
||||
data: {
|
||||
inputs: {
|
||||
inputParameters: mockRefInputs.map(_input => ({
|
||||
..._input,
|
||||
name: `loop_batch_${_input.name}`,
|
||||
})),
|
||||
variableParameters: mockRefInputs.map(_input => ({
|
||||
..._input,
|
||||
name: `loop_var_${_input.name}`,
|
||||
})),
|
||||
},
|
||||
outputs: [
|
||||
genInput('loop_output_var_string', [
|
||||
'loop_0',
|
||||
'loop_var_llm_0__Object',
|
||||
]),
|
||||
genInput('loop_output_string', ['llm_in_loop_0', 'String']),
|
||||
genInput('loop_output_image', ['llm_in_loop_0', 'Object', 'Image']),
|
||||
],
|
||||
},
|
||||
blocks: [
|
||||
{
|
||||
id: 'llm_in_loop_0',
|
||||
type: StandardNodeType.LLM,
|
||||
meta: {
|
||||
position: { x: 400, y: 0 },
|
||||
},
|
||||
data: {
|
||||
outputs: mockFullOutputs,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'llm_in_loop_1',
|
||||
type: StandardNodeType.LLM,
|
||||
meta: {
|
||||
position: { x: 500, y: 0 },
|
||||
},
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
sourceNodeID: 'llm_in_loop_0',
|
||||
targetNodeID: 'llm_in_loop_1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
...complexMock.edges,
|
||||
{
|
||||
sourceNodeID: 'llm_0',
|
||||
targetNodeID: 'loop_0',
|
||||
},
|
||||
{
|
||||
sourceNodeID: 'loop_0',
|
||||
targetNodeID: 'end',
|
||||
},
|
||||
],
|
||||
};
|
||||
Reference in New Issue
Block a user