Files
windmill/chat-sdk/test/config.test.ts
T
Ruben FiszelandClaude Fable 5.1 e8c02c04cd feat: windmill-chat sdk for chat-mode flows in external frontends and raw apps (#11117)
* feat: windmill-chat sdk for chat-mode flows in external frontends and raw apps

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018aQiZNAU8g17kWkyTryS5J

* fix: keep streamed answers until persisted, finish turns after history fallback

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018aQiZNAU8g17kWkyTryS5J

* feat: ai sdk transport and assistant-ui runtime for windmill-chat

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix: finish a turn from the flow result until its answer row lands, hash chat ids without crypto.subtle

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix: judge a turn answered by a persisted assistant row, wherever it was fetched

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix: attribute a turn's answer to its own jobs, keep a local turn when switching conversations

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix: mirror local history on every change, attribute failure-handler answers to the turn

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix: new chat per token string in the React hook, idle after destroy, no reorder on view

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix: recreate the hook's chat on any credential change, namespace local history per user

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix: send the latest inputs from the React hook

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-14 22:32:45 +02:00

50 lines
2.1 KiB
TypeScript

import { afterEach, describe, expect, test } from 'bun:test'
import { resolveConfig } from '../src/config'
const g = globalThis as { process?: unknown; ctx?: unknown; location?: unknown }
const originalProcess = g.process
afterEach(() => {
g.process = originalProcess
delete g.ctx
delete g.location
})
describe('resolveConfig', () => {
test('explicit token defaults history to local; a session defaults to server', () => {
const base = { flowPath: 'f/a/b', baseUrl: 'http://wm.test/', workspace: 'ws' }
expect(resolveConfig({ ...base, token: 't' }).history).toBe('local')
expect(resolveConfig(base).history).toBe('server')
expect(resolveConfig({ ...base, token: 't', history: 'server' }).historyExplicit).toBe(true)
})
test('reads the sandboxed raw app env the wrapper injects', () => {
g.process = {
env: { WM_RAW_APP: 'true', WM_TOKEN: 'sdk-token', BASE_URL: 'http://wm.test', WM_WORKSPACE: 'ws' }
}
const config = resolveConfig({ flowPath: 'f/a/b' })
expect(config).toMatchObject({ baseUrl: 'http://wm.test', workspace: 'ws', token: 'sdk-token', history: 'server' })
})
test('keeps the raw app token off another instance', () => {
g.process = {
env: { WM_RAW_APP: 'true', WM_TOKEN: 'sdk-token', BASE_URL: 'http://wm.test', WM_WORKSPACE: 'ws' }
}
expect(resolveConfig({ flowPath: 'f/a/b', baseUrl: 'http://other.test', workspace: 'ws' }).token).toBeUndefined()
expect(resolveConfig({ flowPath: 'f/a/b', baseUrl: 'http://wm.test' }).token).toBe('sdk-token')
})
test('reads the unsandboxed raw app context and uses the page origin', () => {
g.ctx = { ctx: { username: 'admin' }, workspace: 'ws' }
g.location = { origin: 'http://wm.test' }
const config = resolveConfig({ flowPath: 'f/a/b' })
expect(config).toMatchObject({ baseUrl: 'http://wm.test', workspace: 'ws', token: undefined })
})
test('refuses an opaque origin without an SDK token', () => {
g.ctx = { workspace: 'ws' }
g.location = { origin: 'null' }
expect(() => resolveConfig({ flowPath: 'f/a/b' })).toThrow('frontend SDK scopes')
})
})