[Tests] Drive item views from a playback

QtTesting's own `currentChanged` command aborts on a one-element row list, so
pqWidgetTestEventPlayer drives views itself:

- selectRow selects a row through the selection model, the whole row, without a
  mouse event
- clickRow left-clicks the centre of a cell, so the view's own handlers run
- doubleClickRow double-clicks it, for views whose double click acts

A tree addresses a row by the path of rows leading to it ("2/0" is the first
child of the third top-level row), and a click opens a collapsed path first.
Rows are model rows, so a filtered or sorted model counts the rows it shows.

Asserting what a command did needs QtTesting's check players, which the XML
source never reached: it marked every event an action, so `modelRowCount` was
rejected as unknown. An event now carries `type="check"` to be played as a
check.

Testing/item_view_test.xml drives the grouped settings navigation through
selectRow and clickRow and asserts the page stack followed.
Testing/deck_editor_double_click_test.xml proves the difference between the two
clicks: a single click on a card database row only selects it, a double click
adds the card to the deck.
This commit is contained in:
BruebachL 2026-11-09 10:25:53 +01:00 • committed by Lukas Brübach
parent 3b379618c3
commit 52511b8a73
7 changed files with 279 additions and 3 deletions

View file

@ -3,12 +3,17 @@
#include "pqWidgetEventPlayer.h"
class QAbstractItemView;
class QModelIndex;
/**
* Widget-level commands for the UI tests.
*
* pqCockatriceEventPlayer handles cards and zones inside the game scene. This
* player covers the rest of the client: capturing a widget as an image,
* dumping the paths QtTesting addresses widgets by, and sizing the window.
* dumping the paths QtTesting addresses widgets by, sizing the window, and
* driving item views, whose selection QtTesting's own `currentChanged` command
* cannot handle.
*
* Commands:
* screenshot "<path>"
@ -20,6 +25,17 @@
* addresses it by, for writing a test
* resize "WIDTHxHEIGHT"
* resizes the addressed widget's top-level window
* selectRow "row[/row...][,column]"
* selects that row of an item view, the whole row, without a mouse event
* clickRow "row[/row...][,column]"
* left-clicks the centre of that cell, so the view's own handlers run
* doubleClickRow "row[/row...][,column]"
* double-clicks it, for rows that act on double click
*
* A tree addresses a row by the path of rows leading to it: "2/0" is the first
* child of the third top-level row. A click opens a collapsed path first.
* Rows are model rows of the addressed view, so a filtered or sorted model
* counts the rows it shows.
*/
class pqWidgetTestEventPlayer : public pqWidgetEventPlayer
{
@ -37,7 +53,15 @@ private:
bool playScreenshot(QObject *object, const QString &arguments);
bool playDumpTree(QObject *object, const QString &arguments);
bool playResize(QObject *object, const QString &arguments);
bool playSelectRow(QObject *object, const QString &arguments);
bool playClickRow(QObject *object, const QString &arguments, bool doubleClick);
/** @brief The item view the event is addressed at, following a viewport to its view. */
static QAbstractItemView *itemViewFor(QObject *object);
/** @brief Resolves "row[,column]" to a valid model index of @p view. */
static bool resolveCell(QAbstractItemView *view, const QString &arguments, QModelIndex &index);
/** @brief Sends the mouse events a real click on @p index produces. */
static bool clickCell(QAbstractItemView *view, const QModelIndex &index, bool doubleClick);
/** @brief Expands $NAME / ${NAME} and creates the file's parent directory. */
static bool resolveOutputPath(const QString &command, const QString &path, QString &resolved);
};