mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-13 16:02:59 +00:00
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
93 lines
3.3 KiB
TypeScript
93 lines
3.3 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { assetsOnlyView, upstreamDeletion, type AssetUpstream } from './assetsOnlyView'
|
|
|
|
const node = (id: string, type: string, data: any = {}) => ({ id, type, data })
|
|
const edge = (source: string, target: string, kind: string) => ({
|
|
id: `${kind}:${source}->${target}`,
|
|
source,
|
|
target,
|
|
kind
|
|
})
|
|
|
|
describe('assetsOnlyView', () => {
|
|
const nodes = [
|
|
node('asset:ducklake:raw', 'asset'),
|
|
node('asset:ducklake:clean', 'asset'),
|
|
node('asset:ducklake:report', 'asset'),
|
|
node('script:f/p/clean', 'runnable'),
|
|
node('script:f/p/report', 'runnable'),
|
|
node('script:f/p/other', 'runnable'),
|
|
node('trigger:schedule:f/p/daily', 'trigger', { kind: 'schedule', schedule: '0 0 4 * * *' })
|
|
]
|
|
const edges = [
|
|
edge('trigger:schedule:f/p/daily', 'script:f/p/clean', 'trigger-native'),
|
|
edge('asset:ducklake:raw', 'script:f/p/clean', 'lineage-read'),
|
|
edge('script:f/p/clean', 'asset:ducklake:clean', 'lineage-write'),
|
|
// read-modify-write: no self edge
|
|
edge('asset:ducklake:clean', 'script:f/p/clean', 'lineage-read'),
|
|
edge('asset:ducklake:clean', 'script:f/p/report', 'trigger-asset'),
|
|
edge('asset:ducklake:clean', 'script:f/p/report', 'lineage-read'),
|
|
edge('script:f/p/report', 'asset:ducklake:report', 'lineage-write'),
|
|
edge('script:f/p/other', 'asset:ducklake:report', 'lineage-write')
|
|
]
|
|
const v = assetsOnlyView(nodes, edges)
|
|
|
|
it('joins each script input to its outputs, once', () => {
|
|
expect(v.edges.map((e) => `${e.source} -> ${e.target}`).sort()).toEqual([
|
|
'asset:ducklake:clean -> asset:ducklake:report',
|
|
'asset:ducklake:raw -> asset:ducklake:clean'
|
|
])
|
|
expect([...v.nodeIds].sort()).toEqual([
|
|
'asset:ducklake:clean',
|
|
'asset:ducklake:raw',
|
|
'asset:ducklake:report'
|
|
])
|
|
})
|
|
|
|
it('names the single producer and its trigger, or marks the asset ambiguous', () => {
|
|
expect(v.upstream.get('asset:ducklake:raw')).toBeUndefined()
|
|
expect(v.upstream.get('asset:ducklake:clean')).toMatchObject({
|
|
multiple: false,
|
|
runnableId: 'script:f/p/clean',
|
|
trigger: { kind: 'schedule', data: { schedule: '0 0 4 * * *' } }
|
|
})
|
|
expect(v.upstream.get('asset:ducklake:report')).toEqual({ multiple: true })
|
|
})
|
|
})
|
|
|
|
describe('upstreamDeletion', () => {
|
|
const script = { runnable_kind: 'script', path: 'f/p/a' }
|
|
const schedule = (targets: string[]) => ({
|
|
kind: 'schedule',
|
|
nodeId: 'trigger:schedule:f/p/a_schedule',
|
|
data: { ref: 'f/p/a_schedule', runnable_paths: targets }
|
|
})
|
|
const own = (trigger?: any): AssetUpstream & { multiple: false } => ({
|
|
multiple: false,
|
|
runnableId: 'script:f/p/a',
|
|
trigger
|
|
})
|
|
|
|
it('deletes the script and a trigger that fires only it', () => {
|
|
const u = own(schedule(['f/p/a']))
|
|
expect(upstreamDeletion(u, script, new Map([['asset:x', u]]))).toEqual({
|
|
script: { path: 'f/p/a', unsaved: false },
|
|
trigger: { kind: 'schedule', path: 'f/p/a_schedule', draft: false }
|
|
})
|
|
})
|
|
|
|
it('keeps a trigger that fires other scripts', () => {
|
|
const u = own(schedule(['f/p/a', 'f/p/b']))
|
|
expect(upstreamDeletion(u, script, new Map([['asset:x', u]]))?.trigger).toBeUndefined()
|
|
})
|
|
|
|
it('deletes nothing when the script builds another asset too', () => {
|
|
const u = own(schedule(['f/p/a']))
|
|
const all = new Map([
|
|
['asset:x', u],
|
|
['asset:y', u]
|
|
])
|
|
expect(upstreamDeletion(u, script, all)).toBeUndefined()
|
|
})
|
|
})
|