Skip to content

feat(e2e): real media generation e2e tests#447

Open
AlemTuzlak wants to merge 7 commits intomainfrom
worktree-jazzy-bubbling-dove
Open

feat(e2e): real media generation e2e tests#447
AlemTuzlak wants to merge 7 commits intomainfrom
worktree-jazzy-bubbling-dove

Conversation

@AlemTuzlak
Copy link
Copy Markdown
Contributor

@AlemTuzlak AlemTuzlak commented Apr 13, 2026

Summary

  • Replace fake chat-routed media generation e2e tests with real tests that exercise dedicated media generation APIs (image, TTS, transcription, video) via aimock's multimodal endpoint support
  • Each media type tested with 3 transport modes: SSE (fetchServerSentEvents), HTTP stream (fetchHttpStream), and direct fetcher (createServerFn)
  • Add dedicated UI components (ImageGenUI, TTSUI, TranscriptionUI, VideoGenUI) using the useGenerateImage, useGenerateSpeech, useTranscription, useGenerateVideo hooks
  • Add new API routes for each media type (SSE + HTTP stream variants) plus video generation endpoint
  • Fix provider support matrix to only list providers with actual media adapters

What changed

Infrastructure:

  • Updated aimock to latest with multimodal support
  • Added video-gen feature type
  • Created media-providers.ts adapter factory (image/tts/transcription/video)
  • Fixed feature-support.ts provider sets (removed fake all-provider sets)

API Routes:

  • Rewrote api.image.ts, api.tts.ts, api.transcription.ts with proper adapter usage
  • Created HTTP stream variants (api.*.stream.ts) using toHttpResponse
  • Created api.video.ts + stream variant
  • All routes read from body.data (connection adapter format)

UI:

  • 4 new media generation components with mode prop (sse/http-stream/fetcher)
  • $feature.tsx branches on MEDIA_FEATURES set to render correct UI
  • Server functions via createServerFn for fetcher transport

Tests:

  • 15 new test cases across 4 media types x 3 transport modes
  • Programmatic fixture registration for transcription/video (aimock JSON fixtures don't set match.endpoint)
  • Test helpers: fillPrompt, fillTextInput, clickGenerate, waitForGenerationComplete

Test plan

  • pnpm --filter @tanstack/ai-e2e test:e2e -- --grep "image-gen|tts|transcription|video-gen" — 15/15 pass (11 first-try, 4 flaky on retry)
  • pnpm --filter @tanstack/ai-e2e test:e2e -- --grep "chat" — 12/12 pass, no regressions
  • pnpm --filter @tanstack/ai-e2e build — builds successfully

Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added media generation UIs and workflows: image, TTS (audio), transcription, and video with playback/display.
    • Support for three delivery modes: SSE, HTTP streaming, and direct fetch.
  • Updates

    • Provider support restricted (OpenAI for audio/transcription/video; OpenAI and Grok for images).
    • Expanded e2e tests and updated test fixtures/matchers to cover all media features and modes.

- Update aimock to latest (multimodal endpoint support)
- Add video-gen to Feature type, ALL_FEATURES, and feature configs
- Fix feature-support provider sets: image-gen (openai, grok),
  tts/transcription/video-gen (openai only). Remove fake chat-routed sets
- Add media-providers.ts with adapter factories for all 4 media types
  (image, tts, transcription, video) following the existing providers.ts pattern
- Rewrite api.image.ts, api.tts.ts, api.transcription.ts to use
  media-providers adapters with testId/aimockPort support
- Create HTTP stream variants (api.*.stream.ts) using toHttpResponse
- Create api.video.ts + api.video.stream.ts for video generation
- All routes read from body.data (connection adapter format)
- Add server-functions.ts with createServerFn wrappers for fetcher
  transport mode. Video fetcher handles full create+poll lifecycle.
- Create ImageGenUI, TTSUI, TranscriptionUI, VideoGenUI components
  with mode prop (sse | http-stream | fetcher) for transport selection
- Wire media features into $feature.tsx with MEDIA_FEATURES set
- Rewrite fixtures: image-gen uses data URI url, tts uses base64 audio,
  transcription uses audio.mpeg filename match
- Register transcription/video fixtures programmatically in global-setup
  (aimock JSON loader doesn't set match.endpoint needed by these routes)
- Video fixture includes id + status for OpenAI SDK compatibility
- Add mode param to featureUrl helper for transport selection
- Add fillPrompt, fillTextInput, clickGenerate, waitForGenerationComplete
  helpers with React hydration wait and pressSequentially fallback
- Rewrite image-gen, tts, transcription specs with 3 transport modes
  (sse, http-stream, fetcher) per provider
- Create video-gen spec with 3 transport modes (60s timeout for polling)
@AlemTuzlak AlemTuzlak requested a review from a team April 13, 2026 17:31
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 01e3834f-b7ba-4329-bac1-2569826cde3c

📥 Commits

Reviewing files that changed from the base of the PR and between 6e88b46 and 2de2804.

📒 Files selected for processing (2)
  • testing/e2e/global-setup.ts
  • testing/e2e/tests/helpers.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • testing/e2e/global-setup.ts
  • testing/e2e/tests/helpers.ts

📝 Walkthrough

Walkthrough

Refactors E2E media testing: adds media UIs, adapter factories, server functions and API routes (SSE/HTTP-stream/fetcher), new video-gen feature and fixtures, updates route tree and tests, and restricts provider support for media features.

Changes

Cohort / File(s) Summary
Fixture Updates
testing/e2e/fixtures/transcription/basic.json, testing/e2e/fixtures/tts/basic.json, testing/e2e/fixtures/video-gen/basic.json
Changed transcription and TTS fixture matching and response shapes; added video-gen fixture with video.url and duration.
Global Setup
testing/e2e/global-setup.ts
Skip additional fixture dirs via allowlist and register media fixtures programmatically (registerMediaFixtures(mock)), setting endpoints and job metadata.
Media UI Components
testing/e2e/src/components/ImageGenUI.tsx, testing/e2e/src/components/TTSUI.tsx, testing/e2e/src/components/TranscriptionUI.tsx, testing/e2e/src/components/VideoGenUI.tsx
Added four exported React test UIs handling prompt/text/audio, modes (sse/http-stream/fetcher), generation control, status, and result rendering with testids.
Feature Support & Types
testing/e2e/src/lib/feature-support.ts, testing/e2e/src/lib/features.ts, testing/e2e/src/lib/types.ts
Restricted provider matrix for media features, added video-gen feature, and introduced `Mode = 'sse'
Media Provider Adapters
testing/e2e/src/lib/media-providers.ts
Added factory helpers: createImageAdapter, createTTSAdapter, createTranscriptionAdapter, createVideoAdapter with aimock base URL, test headers, and provider dispatch.
Server Functions
testing/e2e/src/lib/server-functions.ts
Added generateImageFn, generateSpeechFn, generateTranscriptionFn, generateVideoFn server handlers that validate input, ensure LLMock, create adapters, and call TanStack AI generators (video retrieves job status).
API Stream Routes
testing/e2e/src/routes/api.image.stream.ts, .../api.tts.stream.ts, .../api.transcription.stream.ts, .../api.video.stream.ts
Added POST /api/*/stream handlers: ensure LLMock, use AbortController, normalize body, create adapters, call generators with stream: true, return streaming HTTP responses.
API SSE Routes
testing/e2e/src/routes/api.image.ts, .../api.tts.ts, .../api.transcription.ts, .../api.video.ts
Refactored SSE handlers to use shared create*Adapter, support body.data ?? body, pass abortController, include optional testId/aimockPort, and remove hard-coded unsupported-provider branches.
Route Tree & Feature Page
testing/e2e/src/routeTree.gen.ts, testing/e2e/src/routes/$provider/$feature.tsx
Generated new /api/video and */stream routes; $feature route now parses mode, routes media features to MediaFeature which renders the appropriate media UI.
Test Helpers
testing/e2e/tests/helpers.ts
featureUrl accepts optional mode; added fillPrompt, fillTextInput, clickGenerate, and waitForGenerationComplete helpers with improved interactions/assertions.
E2E Tests / Matrix
testing/e2e/tests/image-gen.spec.ts, tts.spec.ts, transcription.spec.ts, video-gen.spec.ts, test-matrix.ts
Rewrote tests to run per-provider and per-mode (sse/http-stream/fetcher) using new UIs and helpers; added video-gen tests; restricted provider support in test matrix.

Sequence Diagram

sequenceDiagram
    participant UI as Media UI
    participant Client as Client Mode
    participant ServerFn as Server Function
    participant Adapter as Media Adapter
    participant Provider as Provider API
    participant LLMock as LLMock Server

    UI->>Client: user fills input & clicks Generate
    Client->>ServerFn: POST /api/<feature> (SSE/stream) or call server fn
    ServerFn->>LLMock: ensureLLMock()
    ServerFn->>Adapter: create<Feature>Adapter(provider, aimockPort, testId)
    Adapter->>Provider: initialize client (base URL + headers)
    ServerFn->>Provider: generate<Feature>(adapter, params, stream?)
    Provider-->>LLMock: request matched to fixture
    LLMock-->>Provider: fixture response (image/audio/text/video)
    Provider-->>ServerFn: stream/return result
    ServerFn-->>Client: stream/response
    Client-->>UI: render result (data-testid)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~55 minutes

Poem

🐰 I hopped through fixtures, adapters, and streams,

sse, http, fetcher—bright testing dreams.
Images, speech, transcribe, and video too,
Providers narrowed, new routes in view.
Tests now dance — a rabbit's joyful cue.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(e2e): real media generation e2e tests' clearly summarizes the main change: replacing fake chat-routed media tests with real dedicated media generation API tests.
Description check ✅ Passed The PR description is well-structured with clear sections (Summary, What changed, Test plan) covering the objectives, implementation details, and testing approach, though it lacks explicit checklist completion and changeset documentation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-jazzy-bubbling-dove

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 13, 2026

🚀 Changeset Version Preview

No changeset entries found. Merging this PR will not cause a version bump for any packages.

@nx-cloud
Copy link
Copy Markdown

nx-cloud bot commented Apr 13, 2026

View your CI Pipeline Execution ↗ for commit 2de2804

Command Status Duration Result
nx run-many --targets=build --exclude=examples/** ✅ Succeeded 2s View ↗

☁️ Nx Cloud last updated this comment at 2026-04-13 18:04:10 UTC

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 13, 2026

Open in StackBlitz

@tanstack/ai

npm i https://pkg.pr.new/@tanstack/ai@447

@tanstack/ai-anthropic

npm i https://pkg.pr.new/@tanstack/ai-anthropic@447

@tanstack/ai-client

npm i https://pkg.pr.new/@tanstack/ai-client@447

@tanstack/ai-code-mode

npm i https://pkg.pr.new/@tanstack/ai-code-mode@447

@tanstack/ai-code-mode-skills

npm i https://pkg.pr.new/@tanstack/ai-code-mode-skills@447

@tanstack/ai-devtools-core

npm i https://pkg.pr.new/@tanstack/ai-devtools-core@447

@tanstack/ai-elevenlabs

npm i https://pkg.pr.new/@tanstack/ai-elevenlabs@447

@tanstack/ai-event-client

npm i https://pkg.pr.new/@tanstack/ai-event-client@447

@tanstack/ai-fal

npm i https://pkg.pr.new/@tanstack/ai-fal@447

@tanstack/ai-gemini

npm i https://pkg.pr.new/@tanstack/ai-gemini@447

@tanstack/ai-grok

npm i https://pkg.pr.new/@tanstack/ai-grok@447

@tanstack/ai-groq

npm i https://pkg.pr.new/@tanstack/ai-groq@447

@tanstack/ai-isolate-cloudflare

npm i https://pkg.pr.new/@tanstack/ai-isolate-cloudflare@447

@tanstack/ai-isolate-node

npm i https://pkg.pr.new/@tanstack/ai-isolate-node@447

@tanstack/ai-isolate-quickjs

npm i https://pkg.pr.new/@tanstack/ai-isolate-quickjs@447

@tanstack/ai-ollama

npm i https://pkg.pr.new/@tanstack/ai-ollama@447

@tanstack/ai-openai

npm i https://pkg.pr.new/@tanstack/ai-openai@447

@tanstack/ai-openrouter

npm i https://pkg.pr.new/@tanstack/ai-openrouter@447

@tanstack/ai-preact

npm i https://pkg.pr.new/@tanstack/ai-preact@447

@tanstack/ai-react

npm i https://pkg.pr.new/@tanstack/ai-react@447

@tanstack/ai-react-ui

npm i https://pkg.pr.new/@tanstack/ai-react-ui@447

@tanstack/ai-solid

npm i https://pkg.pr.new/@tanstack/ai-solid@447

@tanstack/ai-solid-ui

npm i https://pkg.pr.new/@tanstack/ai-solid-ui@447

@tanstack/ai-svelte

npm i https://pkg.pr.new/@tanstack/ai-svelte@447

@tanstack/ai-vue

npm i https://pkg.pr.new/@tanstack/ai-vue@447

@tanstack/ai-vue-ui

npm i https://pkg.pr.new/@tanstack/ai-vue-ui@447

@tanstack/preact-ai-devtools

npm i https://pkg.pr.new/@tanstack/preact-ai-devtools@447

@tanstack/react-ai-devtools

npm i https://pkg.pr.new/@tanstack/react-ai-devtools@447

@tanstack/solid-ai-devtools

npm i https://pkg.pr.new/@tanstack/solid-ai-devtools@447

commit: 2de2804

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
testing/e2e/src/routes/$provider/$feature.tsx (1)

17-25: ⚠️ Potential issue | 🟠 Major

Reject unknown mode values at the route boundary.

search.mode is cast straight to Mode. A typo then flows into the media UIs, whose fallback branch uses the fetcher transport, so a transport-specific test can pass while exercising the wrong path.

🛠️ Proposed fix
     return {
       testId: typeof search.testId === 'string' ? search.testId : undefined,
       aimockPort: port != null && !isNaN(port) ? port : undefined,
-      mode: typeof search.mode === 'string' ? (search.mode as Mode) : undefined,
+      mode:
+        search.mode === 'sse' ||
+        search.mode === 'http-stream' ||
+        search.mode === 'fetcher'
+          ? search.mode
+          : undefined,
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testing/e2e/src/routes/`$provider/$feature.tsx around lines 17 - 25, The
validateSearch function currently casts search.mode directly to Mode, allowing
typos to pass through; update validateSearch to explicitly validate that
search.mode is a string and one of the allowed Mode values before casting (e.g.,
check membership against Object.values(Mode) or a Mode whitelist) and return
undefined for any unknown/invalid mode so the route boundary rejects unexpected
mode values; adjust the mode assignment in validateSearch accordingly.
🧹 Nitpick comments (7)
testing/e2e/src/routes/api.image.stream.ts (1)

3-4: Fix import order per ESLint.

Type imports should precede value imports.

Proposed fix
-import { createImageAdapter } from '@/lib/media-providers'
 import type { Provider } from '@/lib/types'
+import { createImageAdapter } from '@/lib/media-providers'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testing/e2e/src/routes/api.image.stream.ts` around lines 3 - 4, ESLint
flagged the import order: the type import "Provider" should come before the
value import "createImageAdapter"; reorder the two imports so the type import
(import type { Provider } from '@/lib/types') appears above the value import
(import { createImageAdapter } from '@/lib/media-providers') to satisfy the rule
and keep symbols Provider and createImageAdapter correctly referenced.
testing/e2e/src/routes/api.tts.stream.ts (1)

3-4: Fix import order per ESLint.

Type imports should precede value imports.

Proposed fix
-import { createTTSAdapter } from '@/lib/media-providers'
 import type { Provider } from '@/lib/types'
+import { createTTSAdapter } from '@/lib/media-providers'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testing/e2e/src/routes/api.tts.stream.ts` around lines 3 - 4, The import
order violates ESLint: move the type-only import for Provider before the value
import createTTSAdapter; specifically, ensure the import "type { Provider }"
appears above the import "{ createTTSAdapter }" so type imports precede value
imports (update the import statements near createTTSAdapter and Provider
accordingly).
testing/e2e/src/routes/api.transcription.ts (1)

3-4: Fix import order per ESLint.

Type imports should precede value imports for consistency.

Proposed fix
-import { createTranscriptionAdapter } from '@/lib/media-providers'
 import type { Provider } from '@/lib/types'
+import { createTranscriptionAdapter } from '@/lib/media-providers'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testing/e2e/src/routes/api.transcription.ts` around lines 3 - 4, The import
order violates ESLint: place the type-only import before value imports;
specifically, move the type import "Provider" so the line "import type {
Provider } from '@/lib/types'" appears above the value import "import {
createTranscriptionAdapter } from '@/lib/media-providers'". Ensure "import type"
is used (it already is) and run lint/format to confirm the corrected order.
testing/e2e/src/routes/api.tts.ts (1)

3-4: Fix import order per ESLint.

Type imports should precede value imports.

Proposed fix
-import { createTTSAdapter } from '@/lib/media-providers'
 import type { Provider } from '@/lib/types'
+import { createTTSAdapter } from '@/lib/media-providers'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testing/e2e/src/routes/api.tts.ts` around lines 3 - 4, Imports are out of
order per ESLint: move the type import of Provider to come before the value
import createTTSAdapter; specifically, swap the two import lines so "import type
{ Provider } from '@/lib/types'" appears above "import { createTTSAdapter } from
'@/lib/media-providers'". Ensure you use the "import type" form for Provider and
keep the existing module specifiers and names unchanged.
testing/e2e/src/lib/server-functions.ts (1)

9-15: Fix import ordering per ESLint rules.

The type import from @/lib/types should come before the value import from @/lib/media-providers.

🔧 Proposed fix
+import type { Provider } from '@/lib/types'
 import {
   createImageAdapter,
   createTTSAdapter,
   createTranscriptionAdapter,
   createVideoAdapter,
 } from '@/lib/media-providers'
-import type { Provider } from '@/lib/types'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testing/e2e/src/lib/server-functions.ts` around lines 9 - 15, Reorder the
imports so the type-only import comes before value imports: move the `import
type { Provider } from '@/lib/types'` line to appear above the `import {
createImageAdapter, createTTSAdapter, createTranscriptionAdapter,
createVideoAdapter } from '@/lib/media-providers'` statement in
testing/e2e/src/lib/server-functions.ts to satisfy ESLint import ordering rules.
testing/e2e/src/components/TranscriptionUI.tsx (1)

1-8: Fix import ordering per ESLint rules.

Static analysis flags two import order issues:

  1. fetchServerSentEvents should come before fetchHttpStream alphabetically
  2. Type import @/lib/types should come before value import @/lib/server-functions
🔧 Proposed fix
 import {
   useTranscription,
-  fetchServerSentEvents,
   fetchHttpStream,
+  fetchServerSentEvents,
 } from '@tanstack/ai-react'
-import { generateTranscriptionFn } from '@/lib/server-functions'
 import type { TranscriptionResult } from '@tanstack/ai'
 import type { Mode, Provider } from '@/lib/types'
+import { generateTranscriptionFn } from '@/lib/server-functions'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testing/e2e/src/components/TranscriptionUI.tsx` around lines 1 - 8, Reorder
the imports to satisfy ESLint: within the '@tanstack/ai-react' import place
fetchServerSentEvents before fetchHttpStream (alphabetical), and move the
type-only import of Mode and Provider from '@/lib/types' to appear before the
value import generateTranscriptionFn from '@/lib/server-functions'; keep
TranscriptionResult with its type import from '@tanstack/ai' unchanged. Ensure
the import statements maintain their existing specifiers and only change
ordering.
testing/e2e/tests/helpers.ts (1)

142-166: Consider extracting shared input-filling logic.

fillPrompt and fillTextInput are nearly identical, differing only in the test-id selector. For E2E test helpers this duplication is acceptable, but if more similar helpers emerge, consider a shared helper:

async function fillInput(page: Page, testId: string, text: string, buttonTestId = 'generate-button') { ... }

This is a minor suggestion given the E2E test context.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testing/e2e/tests/helpers.ts` around lines 142 - 166, fillPrompt and
fillTextInput duplicate the same input-filling logic with only the test-id
differing; extract the shared behavior into a single helper (e.g., fillInput)
that takes Page, testId (and optional buttonTestId) and performs click, fill,
dispatchEvent('input'), checks the generate-button disabled state and falls back
to clear + pressSequentially when needed; then replace fillPrompt and
fillTextInput to call fillInput (or remove them and update callers) so the logic
in functions fillPrompt and fillTextInput is consolidated and reused.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@testing/e2e/src/components/TranscriptionUI.tsx`:
- Around line 80-84: The UI currently reads the wrong property (result.text) in
TranscriptionUI; update the rendering to use the correct path
result.transcription.text (or safer optional chaining
result?.transcription?.text) and adjust the conditional so the component only
renders when transcription text exists (referencing the TranscriptionUI
component and the result variable/prop).

In `@testing/e2e/src/routes/api.video.stream.ts`:
- Around line 21-35: createVideoAdapter() can throw before the try/catch,
causing framework-level 500s instead of the JSON error shape; move the adapter
construction into the guarded path so any error from createVideoAdapter is
caught and returned as the JSON error response. Specifically, inside the route
where createVideoAdapter(provider, aimockPort, testId) is used, instantiate the
adapter within the try block that calls generateVideo(...) and
toHttpResponse(...), and apply the same change to the other new media routes
that follow this pattern so all adapter creation errors are handled by the
existing catch.

---

Outside diff comments:
In `@testing/e2e/src/routes/`$provider/$feature.tsx:
- Around line 17-25: The validateSearch function currently casts search.mode
directly to Mode, allowing typos to pass through; update validateSearch to
explicitly validate that search.mode is a string and one of the allowed Mode
values before casting (e.g., check membership against Object.values(Mode) or a
Mode whitelist) and return undefined for any unknown/invalid mode so the route
boundary rejects unexpected mode values; adjust the mode assignment in
validateSearch accordingly.

---

Nitpick comments:
In `@testing/e2e/src/components/TranscriptionUI.tsx`:
- Around line 1-8: Reorder the imports to satisfy ESLint: within the
'@tanstack/ai-react' import place fetchServerSentEvents before fetchHttpStream
(alphabetical), and move the type-only import of Mode and Provider from
'@/lib/types' to appear before the value import generateTranscriptionFn from
'@/lib/server-functions'; keep TranscriptionResult with its type import from
'@tanstack/ai' unchanged. Ensure the import statements maintain their existing
specifiers and only change ordering.

In `@testing/e2e/src/lib/server-functions.ts`:
- Around line 9-15: Reorder the imports so the type-only import comes before
value imports: move the `import type { Provider } from '@/lib/types'` line to
appear above the `import { createImageAdapter, createTTSAdapter,
createTranscriptionAdapter, createVideoAdapter } from '@/lib/media-providers'`
statement in testing/e2e/src/lib/server-functions.ts to satisfy ESLint import
ordering rules.

In `@testing/e2e/src/routes/api.image.stream.ts`:
- Around line 3-4: ESLint flagged the import order: the type import "Provider"
should come before the value import "createImageAdapter"; reorder the two
imports so the type import (import type { Provider } from '@/lib/types') appears
above the value import (import { createImageAdapter } from
'@/lib/media-providers') to satisfy the rule and keep symbols Provider and
createImageAdapter correctly referenced.

In `@testing/e2e/src/routes/api.transcription.ts`:
- Around line 3-4: The import order violates ESLint: place the type-only import
before value imports; specifically, move the type import "Provider" so the line
"import type { Provider } from '@/lib/types'" appears above the value import
"import { createTranscriptionAdapter } from '@/lib/media-providers'". Ensure
"import type" is used (it already is) and run lint/format to confirm the
corrected order.

In `@testing/e2e/src/routes/api.tts.stream.ts`:
- Around line 3-4: The import order violates ESLint: move the type-only import
for Provider before the value import createTTSAdapter; specifically, ensure the
import "type { Provider }" appears above the import "{ createTTSAdapter }" so
type imports precede value imports (update the import statements near
createTTSAdapter and Provider accordingly).

In `@testing/e2e/src/routes/api.tts.ts`:
- Around line 3-4: Imports are out of order per ESLint: move the type import of
Provider to come before the value import createTTSAdapter; specifically, swap
the two import lines so "import type { Provider } from '@/lib/types'" appears
above "import { createTTSAdapter } from '@/lib/media-providers'". Ensure you use
the "import type" form for Provider and keep the existing module specifiers and
names unchanged.

In `@testing/e2e/tests/helpers.ts`:
- Around line 142-166: fillPrompt and fillTextInput duplicate the same
input-filling logic with only the test-id differing; extract the shared behavior
into a single helper (e.g., fillInput) that takes Page, testId (and optional
buttonTestId) and performs click, fill, dispatchEvent('input'), checks the
generate-button disabled state and falls back to clear + pressSequentially when
needed; then replace fillPrompt and fillTextInput to call fillInput (or remove
them and update callers) so the logic in functions fillPrompt and fillTextInput
is consolidated and reused.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 666d6af6-2060-4aaf-89e8-9228d9d1d04b

📥 Commits

Reviewing files that changed from the base of the PR and between e832506 and 6e88b46.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (30)
  • testing/e2e/fixtures/image-gen/basic.json
  • testing/e2e/fixtures/transcription/basic.json
  • testing/e2e/fixtures/tts/basic.json
  • testing/e2e/fixtures/video-gen/basic.json
  • testing/e2e/global-setup.ts
  • testing/e2e/src/components/ImageGenUI.tsx
  • testing/e2e/src/components/TTSUI.tsx
  • testing/e2e/src/components/TranscriptionUI.tsx
  • testing/e2e/src/components/VideoGenUI.tsx
  • testing/e2e/src/lib/feature-support.ts
  • testing/e2e/src/lib/features.ts
  • testing/e2e/src/lib/media-providers.ts
  • testing/e2e/src/lib/server-functions.ts
  • testing/e2e/src/lib/types.ts
  • testing/e2e/src/routeTree.gen.ts
  • testing/e2e/src/routes/$provider/$feature.tsx
  • testing/e2e/src/routes/api.image.stream.ts
  • testing/e2e/src/routes/api.image.ts
  • testing/e2e/src/routes/api.transcription.stream.ts
  • testing/e2e/src/routes/api.transcription.ts
  • testing/e2e/src/routes/api.tts.stream.ts
  • testing/e2e/src/routes/api.tts.ts
  • testing/e2e/src/routes/api.video.stream.ts
  • testing/e2e/src/routes/api.video.ts
  • testing/e2e/tests/helpers.ts
  • testing/e2e/tests/image-gen.spec.ts
  • testing/e2e/tests/test-matrix.ts
  • testing/e2e/tests/transcription.spec.ts
  • testing/e2e/tests/tts.spec.ts
  • testing/e2e/tests/video-gen.spec.ts

Comment on lines +80 to +84
{result && (
<p data-testid="transcription-text" className="text-gray-200">
{result.text}
</p>
)}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Bug: Incorrect property path for transcription text.

According to the TranscriptionResult type (see packages/typescript/ai/src/types.ts:1107-1120), the transcribed text is at result.transcription.text, not result.text. This will cause a runtime error or display undefined.

🐛 Proposed fix
       {result && (
         <p data-testid="transcription-text" className="text-gray-200">
-          {result.text}
+          {result.transcription.text}
         </p>
       )}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{result && (
<p data-testid="transcription-text" className="text-gray-200">
{result.text}
</p>
)}
{result && (
<p data-testid="transcription-text" className="text-gray-200">
{result.transcription.text}
</p>
)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testing/e2e/src/components/TranscriptionUI.tsx` around lines 80 - 84, The UI
currently reads the wrong property (result.text) in TranscriptionUI; update the
rendering to use the correct path result.transcription.text (or safer optional
chaining result?.transcription?.text) and adjust the conditional so the
component only renders when transcription text exists (referencing the
TranscriptionUI component and the result variable/prop).

Comment on lines +21 to +35
const adapter = createVideoAdapter(provider, aimockPort, testId)

try {
const stream = generateVideo({
adapter,
prompt,
stream: true,
pollingInterval: 500,
})
return toHttpResponse(stream, { abortController })
} catch (error: any) {
return new Response(JSON.stringify({ error: error.message }), {
status: 500,
headers: { 'Content-Type': 'application/json' },
})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Move adapter construction into the guarded path.

createVideoAdapter() can throw before the try runs. When that happens, this route skips the JSON error response and surfaces a framework-level 500 instead of the shape the client hooks expect. The same pattern is repeated in the other new media routes.

🛠️ Proposed fix
-        const adapter = createVideoAdapter(provider, aimockPort, testId)
-
         try {
+          const adapter = createVideoAdapter(provider, aimockPort, testId)
           const stream = generateVideo({
             adapter,
             prompt,
             stream: true,
             pollingInterval: 500,
           })
           return toHttpResponse(stream, { abortController })
-        } catch (error: any) {
-          return new Response(JSON.stringify({ error: error.message }), {
+        } catch (error) {
+          const message =
+            error instanceof Error ? error.message : 'Unknown error'
+          return new Response(JSON.stringify({ error: message }), {
             status: 500,
             headers: { 'Content-Type': 'application/json' },
           })
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const adapter = createVideoAdapter(provider, aimockPort, testId)
try {
const stream = generateVideo({
adapter,
prompt,
stream: true,
pollingInterval: 500,
})
return toHttpResponse(stream, { abortController })
} catch (error: any) {
return new Response(JSON.stringify({ error: error.message }), {
status: 500,
headers: { 'Content-Type': 'application/json' },
})
try {
const adapter = createVideoAdapter(provider, aimockPort, testId)
const stream = generateVideo({
adapter,
prompt,
stream: true,
pollingInterval: 500,
})
return toHttpResponse(stream, { abortController })
} catch (error) {
const message =
error instanceof Error ? error.message : 'Unknown error'
return new Response(JSON.stringify({ error: message }), {
status: 500,
headers: { 'Content-Type': 'application/json' },
})
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@testing/e2e/src/routes/api.video.stream.ts` around lines 21 - 35,
createVideoAdapter() can throw before the try/catch, causing framework-level
500s instead of the JSON error shape; move the adapter construction into the
guarded path so any error from createVideoAdapter is caught and returned as the
JSON error response. Specifically, inside the route where
createVideoAdapter(provider, aimockPort, testId) is used, instantiate the
adapter within the try block that calls generateVideo(...) and
toHttpResponse(...), and apply the same change to the other new media routes
that follow this pattern so all adapter creation errors are handled by the
existing catch.

AlemTuzlak and others added 2 commits April 13, 2026 19:56
- Replace allowlist approach in global-setup with exclusion list to avoid
  missing fixture directories (caused one-shot-text and text-tool-text
  failures in CI)
- Fix clickGenerate helper: wait for networkidle then verify the click
  actually triggered React by checking status leaves idle, with retry
  if hydration wasn't complete (fixes transcription idle state issue)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant