Files
windmill/frontend/src/lib/schema.test.ts
T
AlexRV12andClaude Opus 5 fb82f36e6d fix: pre-fill the test panel JSON args editor and align its placeholder (#10871)
* fix: pre-fill the test panel JSON args editor and align its placeholder

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

* fix: reseed the JSON args editor when the preprocessor tab is selected

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

* fix: seed schema defaults and own-property args in the JSON payload

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

* fix: follow the schema in an untouched JSON payload, ignore same-tab clicks

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

* fix: latch JSON editor ownership from Monaco, drop the late remounts

The pristine check read the bound `code` value, which trails the buffer by
SimpleEditor's 200ms debounce — a reseed arriving in that window overwrote text
already typed. Latch ownership from Monaco's own change event instead, via a new
undebounced `input` event guarded so `setCode`'s `setValue` does not read as an
edit.

Both `.then(() => argsRender++)` bumps are gone: the arg views now remount at the
tab transition only, and follow the schema in through `initialCode` when
inference resolves, so a remount can no longer land on an in-progress payload.

`FlowPreviewContent.selectInput` overwrote the editor on select but not on
deselect, leaving the abandoned input's payload over reverted args.

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 18:51:08 +02:00

63 lines
2.5 KiB
TypeScript

import { describe, it, expect } from 'vitest'
import { argsToJsonPayload } from './schema'
import type { Schema } from './common'
const schemaOf = (...names: string[]): Schema =>
({
$schema: undefined,
type: 'object',
properties: Object.fromEntries(names.map((n) => [n, { type: 'string' }])),
required: []
}) as Schema
describe('argsToJsonPayload', () => {
it('spells out every schema property in schema order, unset ones as null', () => {
// `0`, `false` and `''` are values, not gaps: only a missing arg becomes `null`.
expect(argsToJsonPayload(schemaOf('a', 'b', 'c'), { c: 0, a: false })).toBe(
JSON.stringify({ a: false, b: null, c: 0 }, null, '\t')
)
})
it('keeps args the schema does not declare, after the declared ones', () => {
expect(argsToJsonPayload(schemaOf('a'), { z: 9, a: 1 })).toBe(
JSON.stringify({ a: 1, z: 9 }, null, '\t')
)
})
it('falls back to the schema default for an absent arg, but not over an explicit null', () => {
// `args` only carries defaults once a `SchemaForm` has mounted for that schema, and the
// JSON view alone never mounts one — seeding `null` there would commit `null` over the
// argument's default on the first keystroke.
const schema = schemaOf('a', 'b')
schema.properties.a.default = 'hi'
schema.properties.b.default = 42
expect(argsToJsonPayload(schema, {})).toBe(JSON.stringify({ a: 'hi', b: 42 }, null, '\t'))
expect(argsToJsonPayload(schema, { a: null })).toBe(
JSON.stringify({ a: null, b: 42 }, null, '\t')
)
})
it('keeps declared args named after Object.prototype members', () => {
// A plain `nargs[key]` read returns the inherited function for an unset `constructor`,
// and `JSON.stringify` drops function-valued properties — the argument would vanish.
expect(argsToJsonPayload(schemaOf('constructor', 'toString', 'ok'), {})).toBe(
JSON.stringify({ constructor: null, toString: null, ok: null }, null, '\t')
)
})
it('keeps undeclared args named after Object.prototype members', () => {
// On a plain `{}` accumulator, `'constructor' in payload` is true before anything is
// assigned to it.
expect(argsToJsonPayload(undefined, { constructor: 'x', toString: 'y', ok: 1 })).toBe(
JSON.stringify({ constructor: 'x', toString: 'y', ok: 1 }, null, '\t')
)
})
it('handles a missing schema or missing args', () => {
expect(argsToJsonPayload(undefined, undefined)).toBe('{}')
expect(argsToJsonPayload(schemaOf('a'), undefined)).toBe(
JSON.stringify({ a: null }, null, '\t')
)
})
})