Header Logo

A Vue 3 Developer’s Guide to Testing iframe-Embedded AI Avatars in CI

A Vue 3 Developer’s Guide to Testing iframe-Embedded AI Avatars in CI

Vue 3 CI testing for iframe-embedded AI avatars: unit, integration, and Playwright smoke tests for sessions, origins, and lifecycle.

Introduction


Testing iframe-embedded realtime avatars in CI is awkward for the same reason it is for any WebRTC-backed UI: the interesting behavior lives across frame boundaries, network timing, browser media APIs, and asynchronous state changes. A unit test can tell you that you rendered an <iframe>. It cannot tell you whether the embedded avatar actually connects, loads with the right origin restrictions, or survives a full conversation flow without timing out.


What you want in CI is not a perfect simulation of production. You want a reliable, repeatable set of checks that answer practical questions:


  • Does the embed load in the browser?

  • Does the session initialize with the expected configuration?

  • Are origin restrictions and rate limits enforced?

  • Does the avatar remain reachable long enough for a basic interaction?

  • Do your app-level assumptions about events, prompts, and session lifecycle still hold?


This post focuses on a testing strategy for Vue 3 applications that embed an AI avatar via iframe, with an emphasis on what to cover in automated CI and what to leave to a smaller set of browser-side smoke tests. The goal is to make your avatar integration testable without turning your pipeline into a flaky media lab.


Start with the right test boundary


The first mistake teams make is trying to test the iframe internals from the parent app. If the avatar is customer-managed and served from a separate origin, the browser’s same-origin policy is doing its job: your Vue app should not poke into the embedded document. Treat the iframe as an external system with a stable contract.


That contract should be tested at three layers:


  1. Vue component unit tests for the wrapper you own.

  2. Integration tests that mount the component and assert the iframe is configured correctly.

  3. Browser E2E smoke tests that verify the iframe actually loads and reaches a known state in a real browser.


This split matters because each layer catches different failures. Unit tests catch regressions in props, computed URL generation, and event wiring. Browser tests catch CSP issues, bad allowlists, broken session creation, and media startup failures.


Test the wrapper, not the avatar internals


In Vue 3, your iframe embed should usually be a thin component that accepts a small number of props and translates them into a URL or src configuration. Keep that component deterministic so it is easy to test.


A minimal wrapper might look like this:


<script setup lang="ts">

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

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

</template>


That is intentionally boring. Boring is testable. In Vue Test Utils, you can assert that the src, allow, and metadata props are set correctly without needing real media access.


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

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

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

})


The key is to test the contract your app controls. Do not mock browser media behavior inside a unit test and pretend that proves the embed works. It does not.


Make session creation a separate, testable step


For production embeds, the iframe often points at a session-specific URL or loads configuration that was created earlier on the server. That separation is useful: your frontend never needs an API key, and the server can enforce allowlists, voice selection, custom instructions, and usage limits before the user ever sees the embed.


In CI, test the session-creation path independently from the browser path. If your backend calls an API to mint a session, verify that request shape and error handling with fast API tests. Then test the frontend against a known-good session payload.


A simple curl-based sanity check is often enough to validate auth and payload shape against the REST API:


curl https://api.protoface.com/v1/sessions \
}'
curl https://api.protoface.com/v1/sessions \
}'
curl https://api.protoface.com/v1/sessions \
}'


The exact fields depend on the endpoint and docs, but the testing pattern is the important part: keep session provisioning deterministic, and assert that failures are handled before the iframe render path even begins.


For teams using the Python SDK, the same idea applies. You can write a small integration test that creates or inspects avatars and sessions programmatically, then feed those IDs into your frontend test fixtures.


from protoface import Client

assert session.id
from protoface import Client

assert session.id
from protoface import Client

assert session.id


Again, the real method names and fields live in the docs; the point is to move all privileged setup out of the browser and into a controlled, testable server-side step.


Use browser E2E tests for the iframe lifecycle


Once the wrapper and provisioning paths are covered, add one or two browser-level tests that prove the whole thing loads in a real browser. Playwright is a good fit because it handles iframe selectors and lets you wait for network or DOM state without fragile sleeps.


A practical smoke test should check:


  • The iframe appears after your Vue route loads.

  • The iframe navigates to the expected embed origin.

  • The parent app handles the “ready” state if your embed emits one through postMessage.

  • Basic UI controls do not break when the iframe is present.


What you should not do is try to assert lip sync or speech quality in CI. Those are product-quality concerns, but they are not stable automated-test assertions. If you need a multimedia regression test, keep it to a narrow “connect and receive media” check.


Example Playwright test:


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

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

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

})


If the embed is cross-origin and emits status through postMessage, add a narrow listener in your Vue app and assert on that event instead of reaching into the iframe. That keeps your code aligned with the browser security model and makes the contract explicit.


Watch the failure modes that actually break CI


Most iframe-avatar failures in CI are not bugs in the avatar service itself. They are integration mismatches:


  • Origin allowlist mismatch: the parent site origin is not listed for the embed, so the iframe refuses to initialize.

  • Missing permissions: the iframe does not get microphone or autoplay permission, which prevents media startup.

  • Bad session configuration: the backend created a session with the wrong avatar, instructions, or voice.

  • Timing assumptions: tests wait for a fixed delay instead of a real readiness signal.

  • Rate-limit behavior: test runs exhaust a short-lived session or hit per-IP limits when reusing environments.


Design your tests around these failures. For example, if your embed has a ready state, assert that state explicitly. If it does not, use a deterministic DOM marker or a well-defined message from the iframe. If a session should fail on a disallowed origin, test that failure in a negative-path browser test rather than hoping to infer it from a blank frame.


Also, keep CI environments predictable. Reusing the same ephemeral preview URL across many jobs can trip per-IP or duration rate limits. Prefer one session per job, short-lived fixtures, and cleanup hooks that delete or expire test resources when possible.


Where Protoface fits naturally


This is exactly the kind of problem a customer-managed iframe flow is meant to solve. With Protoface, the embed is configured server-side, the browser never sees an API key, and the platform handles the session boundary you want to exercise in tests. That makes the frontend contract simpler: your Vue app only needs to render the iframe and react to a small set of lifecycle signals, while your backend or test fixture owns the privileged setup.


For implementation details, keep the docs close at hand: docs.protoface.com. If you are looking for a reference implementation of the browser-side wrapper or server-side session setup, the quickstart repos linked from the docs are a better starting point than inventing your own protocol.


A practical CI checklist


If you want a minimal, high-signal pipeline, start here:


  1. Unit test the Vue wrapper for the iframe src, permissions, and props mapping.

  2. Integration test session provisioning in isolation from the browser.

  3. Run one browser smoke test that loads the page and confirms the iframe becomes visible.

  4. Assert on an explicit readiness signal, not a timeout.

  5. Keep one negative-path test for allowlist or permission failure.


That gives you coverage where it matters without overfitting to network timing or media internals.


Conclusion


Testing iframe-embedded AI avatars in CI is mostly about respecting boundaries. Test your Vue wrapper directly, keep session creation server-side, and use a small number of real browser smoke tests to confirm the iframe loads and reaches a known state. Do not try to unit test WebRTC; do not try to reach into a cross-origin embed.


If you keep the contract small and explicit, these tests stay stable even as the avatar implementation evolves. For protocol details, payload shapes, and current examples, start with the documentation at 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.