Skip to content
omar edited this page Oct 12, 2022 · 17 revisions

What is ImGuiTestRef?

Most functions in the ImGuiTestContext API are taking a ImGuiTestRef argument in order to refer to an item/widget.

void ItemClick(ImGuiTestRef ref, ImGuiMouseButton button = 0);

Typical usage:

ctx->ItemClick("Button");

A ImGuiTestRef can hold either the path to an item, either a precomputed item identifier (ImGuiID which is hash of an absolute path).
Using named paths is greatly convenient and open many possibilities. The structure itself is pretty lightweight and straightforward (see its definition).

Basic Usage

Consider this GUI code:

ImGui::Begin("Window");
ImGui::Button("Button");
if (ImGui::TreeNode("Node"))
{
    ImGui::Checkbox("Checkbox", &b);
    ImGui::TreePop();
}
ImGui::End();

Different ways to access the button and checkbox with named paths:

ctx->ItemClick("//Window/Button");        // Absolute path to the button
ctx->ItemCheck("//Window/Node/Checkbox"); // Absolute path to the checkbox

Single forward slashes / are used as a natural delimitation for items in a path.

Fun Fact! Because the underlying identifiers used by Dear ImGui are hashes of concatenated data, the single forward slashes are technically unnecessary (but absolutely recommended for readability):

ctx->ItemCheck("//WindowNodeCheckbox");   // Also works! (but not recommended: it is bizarre and harder to read!)

In case you need to refer to item containing a slash in their name, you'll need to escape it using a backslash \. Note that in the majority of programming languages, backslashes in literal strings themselves needs to be escaped, therefore needing two:

ctx->ItemClick("A\\/B");                  // Click item called "A/B"

Using SetRef() to set a Base Reference

In order to simplify testing code, it is common to use SetRef() to set Base Reference:

ctx->SetRef("//Window");
ctx->ItemClick("Button");                 // Relative path (from base provided to SetRef() call) to the button
ctx->ItemCheck("Node/Checkbox");          // Relative path (from base provided to SetRef() call) to the checkbox

Using // to ignore the Base Reference

By using a leading // in a named paths, the value set in SetRef() is ignored.

Consider this GUI code:

ImGui::Begin("Window 1");
ImGui::Button("Button 1");
if (ImGui::TreeNode("Node"))
{
    ImGui::Checkbox("Checkbox", &b);
    ImGui::TreePop();
}
ImGui::End();

ImGui::Begin("Window 2");
ImGui::Button("Button 2");
ImGui::End();

And this test code:

// Default base reference is null so we can omit leading `//`
ctx->ItemClick("Window 1/Button 1");   // OK (relative path assuming SetRef() value is 0)
ctx->ItemClick("Window 2/Button 2");   // OK (relative path assuming SetRef() value is 0)

ctx->ItemClick("//Window 1/Button 1"); // OK (absolute path)
ctx->ItemClick("//Window 2/Button 2"); // OK (absolute path)

ctx->SetRef("Window 1");
ctx->ItemClick("Button 1");            // OK (relative path)
ctx->ItemClick("Button 2");            // NOT OK (relative path will lead to "//Window 1/Button 2" which doesn't exist)
ctx->ItemClick("//Window 1/Button 1"); // OK (absolute path, unnecessary here but works)
ctx->ItemClick("//Window 2/Button 2"); // OK (absolute path)

Using SetRef() with composite paths

As a special measure, all values passed to SetRef() are always considered absolute reference, never relative.
So those two statements are always equivalent:

ctx->SetRef("Window");
ctx->SetRef("//Window");

The value passed to SetRef() doesn't necessarily has to be a window:

ctx->SetRef("Window/Node");
ctx->ItemCheck("Checkbox");

And this bizarre/unnatural example illustrate a property of the hashing:

ctx->SetRef("Window/Node/Chec");
ctx->ItemCheck("kbox");      // Click "Window/Node/Checkbox": Strongly discouraged!

(As a future extension, we may add support for trailing ../ sequences to move up one level in the Base Reference)