Files
windmill/frontend/src/lib/test-setup.ts
T
Guilhem 8500435e82 fix(frontend): allow same-origin redirects in isValidLogoutRedirect (#9568)
Self-hosted instances that embed their own UI (Windmill as backend, custom
app at the instance root) can't be redirected back to their app after OAuth
login: isValidLogoutRedirect rejects same-origin absolute URLs, so the login
callback falls back to a client-side goto('/') into Windmill's own dashboard.
Same-origin redirects are never open redirects (and toSameOriginRelativePath
already treats them as safe), so accept them.

Also make the test-setup window global configurable so vitest's stubGlobal
can redefine it across the window-stubbing test suites.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-16 10:25:11 +02:00

103 lines
2.3 KiB
TypeScript

/**
* Vitest setup file to mock browser globals for testing
*/
// Provides a real in-memory IndexedDB (indexedDB / IDBKeyRange / structuredClone)
// under the node test environment so the IndexedDB-backed session list and
// chat-history stores can be exercised in unit tests.
import 'fake-indexeddb/auto'
import { vi } from 'vitest'
// Mock localStorage
const localStorageMock = {
store: {} as Record<string, string>,
getItem(key: string) {
return this.store[key] ?? null
},
setItem(key: string, value: string) {
this.store[key] = value
},
removeItem(key: string) {
delete this.store[key]
},
clear() {
this.store = {}
},
get length() {
return Object.keys(this.store).length
},
key(index: number) {
return Object.keys(this.store)[index] ?? null
}
}
// Mock sessionStorage
const sessionStorageMock = {
store: {} as Record<string, string>,
getItem(key: string) {
return this.store[key] ?? null
},
setItem(key: string, value: string) {
this.store[key] = value
},
removeItem(key: string) {
delete this.store[key]
},
clear() {
this.store = {}
},
get length() {
return Object.keys(this.store).length
},
key(index: number) {
return Object.keys(this.store)[index] ?? null
}
}
// Assign to globalThis
Object.defineProperty(globalThis, 'localStorage', {
value: localStorageMock,
writable: true
})
Object.defineProperty(globalThis, 'sessionStorage', {
value: sessionStorageMock,
writable: true
})
// Some modules (e.g. svelte5Utils.useLocalStorageValue) gate browser-only
// behavior on `typeof window`. Provide a minimal window so they don't
// short-circuit during tests.
if (typeof (globalThis as any).window === 'undefined') {
Object.defineProperty(globalThis, 'window', {
value: globalThis,
writable: true,
configurable: true
})
}
vi.mock('@codingame/monaco-vscode-standalone-typescript-language-features/worker', () => ({
TypeScriptWorker: class TypeScriptWorker {
private _mockScriptSnapshot?: {
getText: (start: number, end: number) => string
getLength: () => number
}
setMockCode(t: string) {
this._mockScriptSnapshot = {
getText: (start: number, end: number) => t.substring(start, end),
getLength: () => t.length
}
}
getScriptSnapshot(_fileName: string) {
return this._mockScriptSnapshot
}
getScriptVersion(_fileName: string) {
return '1'
}
},
ts: undefined,
initialize: undefined
}))