Skip to content

C++ client

Qt-native async client (QObject signals/slots). This is the reference; for a guided first test see the C++ quick start.

Linking

The distribution tarball ships a CMake package config:

cmake
find_package(vericue REQUIRED)
target_link_libraries(my_tests PRIVATE vericue::vericue-client)

Headers live under include/vericue/; the client needs Qt Core + Network.

Programming model

Every command method is non-blocking: it returns a request ID (QString) immediately, and the result arrives later on a signal. Match the ID to correlate:

cpp
#include <vericue/client.h>

vericue::VeriCueClient client;

QObject::connect(&client, &vericue::VeriCueClient::connected, [&]() {
    // Handshake done - safe to send commands.
    QString id = client.mouseClick("MainWindow/okButton");
});

QObject::connect(&client, &vericue::VeriCueClient::responseReceived,
    [](const QString &id, const QJsonObject &result) { /* success */ });

QObject::connect(&client, &vericue::VeriCueClient::errorReceived,
    [](const QString &id, int code, const QString &message) { /* command failed */ });

client.connectToServer("127.0.0.1", 4242, /*token=*/QString());

Connection API

Method / signalPurpose
connectToServer(host, port, token = {})Connect; handshake is sent automatically
disconnectFromServer()Close the connection
isConnected()true once connected and handshake completed
connected() (signal)Handshake succeeded - safe to send commands
handshakeCompleted(int version) (signal)Negotiated protocol version
disconnected() (signal)Connection closed
connectionError(QString) (signal)Transport-level failure (refused, timeout, ...)
sendRequest(method, params = {})Raw escape hatch for any protocol command

Commands

All methods return the request ID. Optional coordinates use -1 for "center of the object".

cpp
// Discovery
client.listObjects(objectName, className, root);
client.findObject(path, objectName, className);
client.getProperties(path, {"text", "enabled"});
client.getChildren(path, className);
client.getParent(path);
client.getObjectTree(root, /*depth=*/-1);

// Interaction
client.mouseClick(path, "left", "single", /*x=*/-1, /*y=*/-1);
client.typeText(path, "hello");
client.keyPress(path, "ctrl+s", /*repeat=*/1);
client.drag(path, fromX, fromY, toX, toY, "left");
client.scroll(path, /*dx=*/0, /*dy=*/-3);
client.screenshot(path);                       // empty path = first visible window
client.highlightObject(path, 2000, "red");

// Touch & gestures
client.touchTap(path, -1, -1, /*duration=*/50);
client.touchLongPress(path, -1, -1, /*duration=*/800);
client.swipe(path, fromX, fromY, toX, toY, /*duration=*/300, /*steps=*/10);
client.pinch(path, startDistance, endDistance, centerX, centerY, /*duration=*/300);
client.multiTouch(path, touchesArray);         // [{id, x, y, action}, ...]

// Model/view
client.getModelInfo(path);
client.getModelData(path, row, column, "display");

// Visual verification
client.screenshotCompare(baselineBase64, path, /*threshold=*/0.02);

// Extended automation
client.setProperty(path, "text", QJsonValue("new"));
client.invokeMethod(path, "clear");
client.waitForProperty(path, "enabled", QJsonValue(true), /*timeout=*/5000);
client.waitForSignal(path, "clicked()", /*timeout=*/5000);

// Performance
client.frameTime(path, /*durationMs=*/1000);
client.paintCount(path, /*durationMs=*/1000);
client.memorySnapshot();

// Mocking / helpers
client.emitSignal(path, "timeout()", QJsonArray{});
client.setClipboard("text");
client.getClipboard();

// Multi-window
client.listWindows();

// Recording
client.startRecording();
client.stopRecording();

Push events

Subscriptions deliver server-pushed events on the eventReceived signal (see Push events):

cpp
client.subscribeSignal(path, "clicked()");
client.subscribeProperty(path, "text");
client.subscribeDestroyed(path);
client.unsubscribe(subscriptionId);
client.listSubscriptions();

QObject::connect(&client, &vericue::VeriCueClient::eventReceived,
    [](const QString &subscriptionId, const QString &eventName,
       const QString &path, const QJsonObject &data) {
        // eventName: "signal_emitted" | "property_changed" | "object_destroyed"
    });

Subscriptions are cleaned up server-side when the connection closes.

GoogleTest fixture

vericue/gtest_fixture.h turns the async client into a synchronous test fixture - each test gets a connected client, and invoke() blocks (by pumping the event loop) until the response arrives:

cpp
#include <vericue/gtest_fixture.h>

class LoginTest : public vericue::VeriCueTest {};

TEST_F(LoginTest, OkButtonClicksSucceed) {
    // Synchronous wrappers:
    EXPECT_TRUE(click("MainWindow/okButton"));
    EXPECT_EQ(prop("MainWindow/statusLabel", "text").toString(), "Logged in");

    // Any command via invoke() - throws vericue::CommandFailed on error:
    QJsonObject r = invoke("get_properties", QJsonObject{
        {"path", "MainWindow/okButton"},
        {"properties", QJsonArray{"enabled"}},
    });
    EXPECT_TRUE(r["enabled"].toBool());
}

Fixture API: invoke(method, params, timeoutMs = 5000), click(path), prop(path, propertyName), and client() for direct access. Command failures throw vericue::CommandFailed (with .code() / .message()).

Configuration comes from environment variables:

VariableDefault
VERICUE_HOST127.0.0.1
VERICUE_PORT4242
VERICUE_TOKEN(empty)

If your build vendors GoogleTest differently, define VERICUE_GTEST_NO_INCLUDE and include gtest/gtest.h yourself before the fixture header.

Released under a commercial licence. Privacy · Terms