Cockatrice/cockatrice/src/interface/pq_widget_test_event_player.h
BruebachL 52511b8a73 [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.
2026-11-09 14:21:27 +01:00

69 lines
3 KiB
C++

#ifndef PQ_WIDGET_TEST_EVENT_PLAYER_H
#define PQ_WIDGET_TEST_EVENT_PLAYER_H
#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, sizing the window, and
* driving item views, whose selection QtTesting's own `currentChanged` command
* cannot handle.
*
* Commands:
* screenshot "<path>"
* grabs the addressed widget and saves it as an image. Parent directories
* are created, and $NAME / ${NAME} in the path expand from the
* environment, so the runner decides where captures land
* dumpTree "<path>"
* writes the addressed widget's subtree with the paths QtTesting
* 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
{
Q_OBJECT
typedef pqWidgetEventPlayer Superclass;
public:
explicit pqWidgetTestEventPlayer(QObject *parent = nullptr);
using Superclass::playEvent;
bool playEvent(QObject *object, const QString &command, const QString &arguments, bool &error) override;
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);
};
#endif // PQ_WIDGET_TEST_EVENT_PLAYER_H