Files
windmill/frontend/src/lib/components/flows/flowDiff.testUtils.ts
T
centdixandClaude Opus 4.5 a5363ea4ed refactor: unify flow chat tree operations (#8862)
* refactor: make flow chat code edits explicit

* refactor: centralize flow tree lookups

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: simplify flow chat tree mutations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: reuse flow tree lookup in schema map

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: remove flow lookup alias

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: reuse flow tree in previous results

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: reuse canonical flow module lookup

* fix: align rebased flow helpers

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: remove flow chat cleanup plan

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: remove flow chat helper wrappers

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: preserve non-flowmodule AI agent tools in skeleton and previous_result

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: consolidate flow module ID collectors into flowTree

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: search full flow tree in test_run_step to find special modules

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: recurse into aiagent tools in collectAllFlowModuleIds

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-20 17:50:50 +00:00

196 lines
4.5 KiB
TypeScript

import { expect } from 'vitest'
import type {
FlowValue,
FlowModule,
RawScript,
AiAgent,
Identity,
ForloopFlow,
WhileloopFlow,
BranchOne,
BranchAll
} from '$lib/gen'
import type { ExtendedOpenFlow } from './types'
import type { StateStore } from '$lib/utils'
// ============================================================================
// Module Creation Helpers
// ============================================================================
/**
* Creates a minimal RawScript module for testing
*/
export function createRawScriptModule(id: string, content: string): FlowModule {
return {
id,
value: {
type: 'rawscript',
content,
language: 'bun',
input_transforms: {}
} as RawScript
}
}
/**
* Creates a minimal Identity module (useful for type-change tests)
*/
export function createIdentityModule(id: string): FlowModule {
return {
id,
value: {
type: 'identity'
} as Identity
}
}
/**
* Creates a ForloopFlow module with nested modules
*/
export function createForloopModule(id: string, nestedModules: FlowModule[]): FlowModule {
return {
id,
value: {
type: 'forloopflow',
modules: nestedModules,
iterator: { type: 'javascript', expr: '[1,2,3]' },
skip_failures: false
} as ForloopFlow
}
}
/**
* Creates a WhileloopFlow module with nested modules
*/
export function createWhileloopModule(id: string, nestedModules: FlowModule[]): FlowModule {
return {
id,
value: {
type: 'whileloopflow',
modules: nestedModules,
skip_failures: false
} as WhileloopFlow
}
}
/**
* Creates a BranchOne module with default and conditional branches
*/
export function createBranchOneModule(
id: string,
defaultModules: FlowModule[],
branches: { expr: string; modules: FlowModule[] }[]
): FlowModule {
return {
id,
value: {
type: 'branchone',
default: defaultModules,
branches: branches.map((b) => ({ expr: b.expr, modules: b.modules }))
} as BranchOne
}
}
/**
* Creates a BranchAll module with parallel branches
*/
export function createBranchAllModule(id: string, branches: { modules: FlowModule[] }[]): FlowModule {
return {
id,
value: {
type: 'branchall',
branches: branches.map((b) => ({ modules: b.modules }))
} as BranchAll
}
}
/**
* Wraps a FlowModule as an AI agent flowmodule tool.
*/
export function createFlowModuleTool(module: FlowModule): FlowModule {
return {
id: module.id,
summary: module.summary,
value: {
tool_type: 'flowmodule',
...module.value
} as any
} as FlowModule
}
/**
* Creates an AI agent module with the provided tools.
*/
export function createAiAgentModule(id: string, tools: FlowModule[]): FlowModule {
return {
id,
value: {
type: 'aiagent',
tools,
input_transforms: {}
} as AiAgent
}
}
// ============================================================================
// Flow Creation Helpers
// ============================================================================
/**
* Creates a FlowValue with the given modules
*/
export function createFlow(modules: FlowModule[]): FlowValue {
return { modules }
}
/**
* Creates a FlowValue with optional special modules (failure_module, preprocessor_module)
*/
export function createFlowWithSpecialModules(options: {
modules?: FlowModule[]
failure_module?: FlowModule
preprocessor_module?: FlowModule
}): FlowValue {
return {
modules: options.modules ?? [],
...(options.failure_module && { failure_module: options.failure_module }),
...(options.preprocessor_module && { preprocessor_module: options.preprocessor_module })
}
}
/**
* Wraps a FlowValue in an ExtendedOpenFlow for manager tests
*/
export function createExtendedOpenFlow(
flowValue: FlowValue,
schema?: Record<string, unknown>
): ExtendedOpenFlow {
return { value: flowValue, summary: '', schema }
}
/**
* Creates a minimal StateStore for manager tests
*/
export function createFlowStore(flow: ExtendedOpenFlow): StateStore<ExtendedOpenFlow> {
return { val: flow }
}
// ============================================================================
// Utility Helpers
// ============================================================================
/**
* Deep clones an object via JSON serialization
*/
export function deepClone<T>(obj: T): T {
return JSON.parse(JSON.stringify(obj))
}
/**
* Asserts that modules appear in the exact order specified.
* Also implicitly verifies the count of modules.
*/
export function expectModuleOrder(modules: FlowModule[], expectedIds: string[]): void {
expect(modules.map((m) => m.id)).toEqual(expectedIds)
}