chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @vitest-environment jsdom
|
||||
*/
|
||||
import { act } from 'react'
|
||||
import { createRoot, type Root } from 'react-dom/client'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { useSmoothText } from '@/hooks/use-smooth-text'
|
||||
|
||||
interface ProbeProps {
|
||||
content: string
|
||||
isStreaming: boolean
|
||||
snapOnNonAppend?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimal dependency-free hook harness (the repo has no `@testing-library/react`). Mounts the hook in
|
||||
* a real React root under jsdom so effects and refs run exactly as in the app. Fake timers keep the
|
||||
* paced reveal from advancing, so each assertion observes the synchronous reveal decision only.
|
||||
*/
|
||||
function renderSmoothText(initial: ProbeProps) {
|
||||
;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true
|
||||
const container = document.createElement('div')
|
||||
const root: Root = createRoot(container)
|
||||
const props = { ...initial }
|
||||
let latest = ''
|
||||
|
||||
function Probe(p: ProbeProps) {
|
||||
latest = useSmoothText(p.content, p.isStreaming, { snapOnNonAppend: p.snapOnNonAppend })
|
||||
return null
|
||||
}
|
||||
|
||||
const render = () =>
|
||||
act(() => {
|
||||
root.render(<Probe {...props} />)
|
||||
})
|
||||
render()
|
||||
|
||||
return {
|
||||
value: () => latest,
|
||||
rerender: (next: Partial<ProbeProps>) => {
|
||||
Object.assign(props, next)
|
||||
render()
|
||||
},
|
||||
unmount: () => act(() => root.unmount()),
|
||||
}
|
||||
}
|
||||
|
||||
const LONG = `# Existing Document\n\n${'Lorem ipsum dolor sit amet, '.repeat(8)}`
|
||||
|
||||
describe('useSmoothText — streaming that begins on an already-open document', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers()
|
||||
})
|
||||
afterEach(() => {
|
||||
vi.clearAllTimers()
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
it('reveals a pre-existing document in full when an edit stream starts (no full-file replay)', () => {
|
||||
// The editor mounts showing a static file (no stream yet).
|
||||
const h = renderSmoothText({ content: '', isStreaming: false, snapOnNonAppend: true })
|
||||
expect(h.value()).toBe('')
|
||||
|
||||
// The agent begins editing it: the first streamed value carries the whole existing document.
|
||||
// It must appear instantly, not replay word-by-word from the first character.
|
||||
h.rerender({ content: LONG, isStreaming: true })
|
||||
expect(h.value()).toBe(LONG)
|
||||
h.unmount()
|
||||
})
|
||||
|
||||
it('still animates a brand-new file from the start (short content stays below the threshold)', () => {
|
||||
// A create stream mounts already-streaming with a tiny first chunk → begins empty and paces in.
|
||||
const h = renderSmoothText({ content: '# New file', isStreaming: true, snapOnNonAppend: true })
|
||||
expect(h.value()).toBe('')
|
||||
h.unmount()
|
||||
})
|
||||
|
||||
it('shows content that is already large at mount in full (mount-time skip, unchanged)', () => {
|
||||
const h = renderSmoothText({ content: LONG, isStreaming: true, snapOnNonAppend: true })
|
||||
expect(h.value()).toBe(LONG)
|
||||
h.unmount()
|
||||
})
|
||||
|
||||
it('does not pre-reveal for chat (mounts already streaming with a small first chunk)', () => {
|
||||
// Chat (no snapOnNonAppend) mounts streaming; the not-streaming→streaming edge never occurs, so
|
||||
// the new transition skip cannot fire and ordinary paced reveal is preserved.
|
||||
const h = renderSmoothText({ content: 'Hello', isStreaming: true })
|
||||
expect(h.value()).toBe('')
|
||||
h.unmount()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user