Thanks for the input so far. Sharing where I’ve landed on testing the embedded admin UI specifically, plus a few sharper follow-ups.
The biggest realization: most of my list — filling forms, required-field validation, error messages, dropdowns/checkboxes, success/error notifications — is actually covered far more reliably by component/integration tests than by full Playwright browser tests. The embedded app is just a React (Polaris) app, so I render the page/form components with Testing Library, drive them, and assert inline Polaris errors, control state, and the action results directly. These are fast, deterministic, and run on every PR.
To make that work outside the Admin shell, I mock the App Bridge shopify global (toast, save bar, modal, idToken) once in a shared setup file — those surfaces don’t exist outside the iframe, so mocking them lets the components run headless.
Where I do use Playwright (a thin layer): a real end-to-end smoke of a representative workflow against a dev store — load the embedded page, fill the form, save, then assert the result via the Admin GraphQL API rather than scraping the embedded DOM. Verifying persisted data through the API is much less flaky than asserting on App Bridge toasts or Polaris-rendered markup.
On the iframe/App Bridge specifics:
- Everything renders in a cross-origin iframe, so in-browser tests have to scope to the app frame, and App Bridge drives navigation/save-bar behavior that races assertions.
- For auth, I avoid driving the full Admin login each run — establish an authenticated session once and reuse it, rather than going through
admin.shopify.com every time.
- App Bridge toasts are imperative/ephemeral, so I assert the underlying state change instead of trying to catch the toast.
Fixtures: seeded and reset through the Admin API, resetting only what each test dirtied (resetting everything per test rate-limited the store quickly).
Remaining questions I’d love input on:
- Auth — what’s your cleanest way to get an authenticated Playwright session against the embedded app without re-driving the Admin login + iframe each run? Reusing
storageState, or stubbing the session-token exchange?
- Contextual save bar — how are you reliably triggering and asserting an App Bridge save (save bar → action → confirmation) in a real browser test?
- Polaris controls —
Select, Combobox, Checkbox etc. render custom markup; are you targeting them by role, or adding data-testids?
- Notifications — do you assert App Bridge toasts in-browser at all, or always fall back to asserting state?
- Where’s your line between component/integration coverage and full embedded browser E2E?
Thanks again — happy to compare notes on any of these.