Loading...

Blog

🕵️ Pixels, Not Elements: Automating Flutter CanvasKit

The Website That Wouldn’t Let Us Inspect It and Can NOT Automate It For Regression Test

Introduction

How one hidden button turned an “impossible” Flutter site into a fully automatable one.

It started like any other automation kickoff. A new client, a fresh website, and a clear goal: automate the core user flows. We opened the site, right-clicked the login button, chose Inspect, and waited for DevTools to point us to our first locator.

Instead, the entire page lit up in blue.

We tried the email field. Whole page. The “Forgot password?” link. Whole page. No <button>, no <input>, nothing to hold on to. For a QA team, a website with no locators is a website you cannot automate.


🔍 The Mystery Behind the Blue Screen

A little digging gave us the answer. The site was built with Flutter Web, using its CanvasKit renderer.

Most websites are built from HTML elements that browsers and testing tools can read one by one. CanvasKit plays by different rules. It paints the entire interface as pixels onto a single canvas, the way a game or a drawing app would. To the browser, that login form wasn’t a form at all. It was a picture of a form.

That explained everything. The inspector could only ever select one thing, the canvas, and tools like Selenium, WebdriverIO and Playwright were just as blind as we were.

🔑 The Hidden Key

Here’s the twist. Flutter quietly keeps a second map of every screen, called the semantics tree. It describes each button, text field and link so that screen readers can understand the app. To save performance, Flutter keeps it switched off until someone asks for it.

And Flutter leaves a way to ask. Every page carries an invisible “Enable accessibility” button. We opened the browser’s Console tab and pressed it with a single line:

document.querySelector('flt-semantics-placeholder').click();

The page came alive. Flutter laid an invisible layer of elements over the canvas, one for every widget on the screen, each carrying a role and an aria-label. Text fields turned into real inputs. We right-clicked the login button again, and this time DevTools showed us exactly the login button.

⚙️ From Console Trick to Test Suite

A console trick is nice. An automated one is better. We added the same line to our tests using the framework’s execute-script feature:

Once it ran, locators like “the button labelled Log in” worked just like they would on any ordinary website.

đź’ˇ Lessons We Learned Along the Way

📜 The Takeaway

A Flutter CanvasKit website isn’t impossible to automate. It just draws pixels instead of elements. Switch on its accessibility layer, and you get a complete map of the screen to test against.

What looked like a dead end on day one became one of our favourite reminders in QA: when the obvious path is blocked, look for the one built for accessibility.

Ayush
SDET, Span Technoverse
Ayush, SDET at Span Technoverse