Header Logo

Building Reliable CI Checks for a Vue 3 AI Avatar Stream

Building Reliable CI Checks for a Vue 3 AI Avatar Stream

CI strategies for Vue 3 AI avatar streams: mock state, verify media lifecycle, autoplay, and teardown with Playwright.

Introduction


Reliable CI for a realtime avatar stream is not the same as “the app boots.” A Vue 3 front end that plays a lip-synced avatar has a few failure modes that conventional unit tests miss: a stream starts but never renders video, the element mounts before the media pipeline is ready, autoplay gets blocked, state transitions race with WebRTC negotiation, or a refactor breaks the handshake between your UI and the session backend.


This post is about building CI checks that catch those regressions early. By the end, you should have a practical testing strategy for a Vue 3 avatar component: what to test in pure JavaScript, what to mock, what to verify with browser-level checks, and where to draw the line before tests become flaky and expensive.


Start by separating UI logic from media behavior


The biggest mistake is trying to test “the stream” as one thing. In practice, your Vue component usually has three responsibilities:


  • Collect or receive session data: avatar/session IDs, stream URL, token, or embed config.

  • Control the media element lifecycle: mount, attach stream, handle play/pause, teardown.

  • Reflect connection state in the UI: connecting, live, reconnecting, failed.


Keep those responsibilities isolated. Most CI value comes from testing the state machine and lifecycle code in ordinary component tests, not from trying to simulate a full realtime avatar session in every run.


A useful pattern is to wrap stream initialization in a composable or service, then keep the Vue component thin:


<script setup lang="ts">

</script>
<script setup lang="ts">

</script>
<script setup lang="ts">

</script>


That split makes your CI checks straightforward: test that the component calls the right lifecycle hooks, transitions through the right states, and cleans up when unmounted. Then separately test the media attachment path with browser automation.


Test the state machine, not the network


For Vue 3, component tests with Vitest and Vue Test Utils are enough to validate most regressions. Mock the session fetch and the attach function. Verify that:


  • the UI enters “connecting” while the session is being prepared,

  • the video element is present before attachment,

  • an error state is rendered when initialization fails,

  • teardown is called on unmount.


Example:


import { mount } from '@vue/test-utils'

})
import { mount } from '@vue/test-utils'

})
import { mount } from '@vue/test-utils'

})


The important part is not the exact code; it’s the boundary. Mock the transport and the avatar backend. Your CI should not depend on external availability for the basic UI contract.


Use browser-level checks for autoplay, rendering, and teardown


Once you trust the component logic, add one or two end-to-end checks with Playwright or a similar browser runner. This is where realtime media actually breaks.


Why browser tests matter:


  • Autoplay rules: browsers may block unmuted playback unless initiated by user gesture or permitted by policy.

  • Media element wiring: a stream can be valid but never attached to the correct video tag.

  • CSS/layout regressions: your video may be live but hidden, zero-sized, or covered by another layer.

  • Unmount cleanup: live media tracks and connections need to close when navigating away.


Keep these tests deterministic. Use a mocked or prerecorded media source if your implementation supports it, or point the test at a controlled staging session. Assert on visible state and browser events, not on pixels unless you truly need visual regression.


import { test, expect } from '@playwright/test'

})
import { test, expect } from '@playwright/test'

})
import { test, expect } from '@playwright/test'

})


If the avatar uses an embedded player or iframe, also test parent-origin gating and sandbox assumptions. A misconfigured allowlist can work locally and fail in production, or worse, broaden access beyond the intended origin.


Design CI checks around failure modes you actually ship


Good CI is mostly about catching real production regressions with minimal noise. For realtime avatar streaming, the recurring failure modes are predictable:


  1. Session bootstrap drift: your backend returns a shape the front end no longer understands.

  2. Transport mismatch: the video element is connected to the wrong stream or is recreated too often.

  3. Lifecycle bugs: reconnect logic survives route changes but leaks the old session.

  4. Policy failures: autoplay, CORS, origin allowlists, and iframe restrictions differ across environments.


To keep the suite stable:


  • Stub the avatar/session creation path in unit/component tests.

  • Use one browser test to cover render, attachment, and teardown.

  • Pin browser versions in CI so media behavior doesn’t drift under you.

  • Run media tests separately from pure UI tests so a flaky environment doesn’t block all feedback.


If you need confidence in configuration changes, add contract tests around the JSON you fetch from your backend. This is especially useful if the front end depends on a session descriptor, rate limit metadata, or embed settings. Even a small schema mismatch can break a live stream at runtime.


Where Protoface fits


If your Vue app is consuming a Protoface session or embed, the cleanest approach is to treat Protoface as the session/media provider and keep your CI focused on your integration points. For server-side creation or inspection of sessions, the REST API and Python SDK are the relevant surfaces; for browser delivery, customer-managed iframe embeds reduce the amount of media wiring you need in the app itself.


For example, you can smoke-test the REST path in a scripted CI job without touching the UI:


curl -sS https://api.protoface.com/v1/sessions \
curl -sS https://api.protoface.com/v1/sessions \
curl -sS https://api.protoface.com/v1/sessions \


And if your backend creates or verifies session state in Python, the SDK keeps that logic out of the front end. Exact method names and fields are documented in the API reference, so use the docs as the source of truth rather than hard-coding assumptions: docs.protoface.com.


Practical CI setup that holds up


A pragmatic pipeline usually looks like this:


  • Fast lane: Vitest/component tests for state transitions, mock fetches, and teardown.

  • Browser lane: one or two Playwright tests for autoplay/render/unmount behavior.

  • Integration lane: optional backend smoke tests against staging or mocked API responses.


Keep the browser lane narrow. The goal is not to reproduce every realtime edge case in CI; it’s to detect the classes of breakage that pure JavaScript tests cannot see. If a test requires a live human voice, a long-running session, or a real network path to be trustworthy, it probably belongs in a scheduled environment test rather than every pull request.


For implementations that use the LiveKit-based path, the plugin repo is a useful reference for integration shape and examples: github.com/protoface-ai/protoface-plugin-pipecat. Even if your app is a Vue client, studying the plugin helps you understand what needs to be stable across the session boundary and what can safely stay mocked in front-end CI.


Conclusion


Reliable CI for a Vue 3 avatar stream comes from testing the right layer at the right cost. Mock the backend and media attachment for component tests, use browser automation for real playback and cleanup behavior, and keep your integration surface narrow enough that failures are actionable. That combination catches the regressions that matter without turning your pipeline into a flaky realtime lab.


If you’re wiring this up now, start with the docs, build a thin session wrapper in your app, and add one browser test that proves a live avatar can mount, render, and unmount cleanly. From there, expand only where your own failure history justifies it: docs.protoface.com.

Add a face to your AI.

No credit card needed.

Add a face to your AI.

No credit card needed.

Add a face to your AI.

No credit card needed.