Skip to main content

Pages in the IE WebBrowser control

Some line-of-business applications show part of their interface as a web page through the WebBrowser control: Internet Explorer's engine (MSHTML, "Trident"), embedded by a Windows Forms application (System.Windows.Forms.WebBrowser). Windows 11 still ships the engine, though Internet Explorer itself is retired. SPART-Desk reads and drives such a page through UI Automation, as it does any other window: the same locators, actions and assertions. This page says what the engine reports, what it does in its own way, and what the host must do.

import { Desktop, expectDesk } from "@spartaficial/spart-desk";

await using desktop = await Desktop.create();
const app = await desktop.launch({ executable: "C:/Program Files/Contoso/Orders.exe" });
const main = app.window();

await main.getByLabel("Name").fill("Ada");
await main.getByLabel("Colour").selectOption("Blue");
await main.getByRole("tab", { name: "Second", exact: true }).click();
await main.getByRole("treeitem", { name: "Fruit", exact: true }).expand();
const bob = await main.table("People").row().where("Name").equals("Bob").find();
await bob.click();
await expectDesk(main.getByRole("status")).toHaveText("Person: Bob");

A page is a scope of its own, found by its address and title as any page is: main.webPage(), currentUrl() (here file://C:\…), currentTitle(), expectDesk(page).toHaveUrl(…). It is the pane named after the page's title under the engine's window; an open drop-down's popup, a window of the same class, is never taken for a page. A frame (an <iframe>, a frameset's <frame>) is a page inside it, the same pair of panes without a window of its own: page.webPage({ url: /orders\.html$/ }).

What the tree holds​

  • The window chain is the host's window, Shell Embedding, Shell DocObject View, and the page's own window, Internet Explorer_Server, named after the page's address. Everything in the page lies under it.
  • MSHTML answers through Windows' MSAA proxy (the framework is InternetExplorer). Fields, drop-downs, check boxes, radio buttons, buttons, links and ARIA roles (tree, tree item, list box, option, tab, menu, status) come with their roles, names, values and states; an element's HTML id is its AutomationId.
  • A page in IE11's document mode and one in the control's default mode, IE7's, read alike: a form in IE7's mode is filled, chosen in, checked and submitted, and its status read back, as in IE11's.

What SPART-Desk does about what MSHTML reports in its own way:

  • An ARIA tree item is named after every line of text under it, its sub-items' too, hidden ones among them ("Food Fruit Apple Banana Bread"). It is named by the one text it holds itself, which that name starts with, so getByRole("treeitem", { name: "Fruit" }) is the one item.
  • A tab, a menu item or a tree item that has no Invoke pattern is clicked. MSHTML takes such a control's SelectionItem and ExpandCollapse patterns by changing only what it reports: the tab reads selected and the menu expanded while the page's script heard nothing, so no other page shows and no menu opens. Its Invoke is the element's click(), which the page hears; a native radio button's selection and a native drop-down's expansion are the page's own, and keep going through their patterns, in the background.
  • An HTML table reports each cell inside a row of its own. The rows of one cell that lie side by side are the cells of one row, so table() reads its rows by their columns.

Behaviour of the IE engine​

  • Pointer events. The WebBrowser control keeps a page in its legacy input mode unless the host opts out (FEATURE_NINPUT_LEGACYMODE), which few hosts do: the page hears mouse events only. A finger's and a pen's tap reach it as the left mouse button, the middle button as the middle one; the back and forward buttons reach no page.
  • A spin box. IE11 shows an <input type="number"> as a plain text field.
  • A fieldset as a group. IE11 reports a <fieldset> as nothing: its legend is a text beside the radio buttons, and no group holds them. A locator that asks for the group by the legend's text fails saying so.
  • HTML headings and landmarks. <h1>–<h6>, <nav>, <main>, <header>, <footer>, <aside> and <section> are texts, or not reported. Only what an ARIA role names has a role of its own: role="heading", with no level, and role="search".

What a host must do​

  • Ask for IE11's document mode for a page written for it: <meta http-equiv="X-UA-Compatible" content="IE=edge"> first in the page's <head>, or the host's FEATURE_BROWSER_EMULATION setting. Without either, the control shows the page in IE7's mode, which runs no addEventListener, no textContent and much else a modern page uses.
  • Nothing else for SPART-Desk: no setting, no injected script, no DOM access.