Test group and PM bottom following with long messages and historical sends

This commit is contained in:
evgeny committed 2026-11-03 00:18:32 +01:00
1 parent 0da3c3a677
commit be4798a595
2 files changed
+76 -1

No files matched your search

-1
View File
@@ -1061,7 +1061,6 @@ void MessageList::refresh(bool outgoing) {
m_localNicks = m_db->getLocalNicknames(m_currentChannelId);
QScrollBar* sb = m_view->verticalScrollBar();
const bool wasAtBottom = nearHistoryBottom();
bool added = false;
+76
View File
@@ -23,6 +23,9 @@
#include <QClipboard>
#include <QImage>
#include <QLabel>
#include <QScrollBar>
#include <QJsonArray>
#include <QJsonDocument>
#include <QDir>
#include <QRadioButton>
#include <future>
@@ -128,6 +131,79 @@ static int inCore(std::function<int(UTUN_INSTANCE*)> operation) {
class GroupEditTest : public QObject {
Q_OBJECT
private slots:
void newMessageScroll_data() {
QTest::addColumn<bool>("dm"); QTest::addColumn<QString>("scenario");
for (bool dm : {false, true}) for (const QString& scenario : {"bottom", "near", "boundary", "far", "own", "unchanged"})
QTest::newRow(qPrintable(QString("%1-%2").arg(dm ? "pm" : "group", scenario))) << dm << scenario;
}
void newMessageScroll() {
QFETCH(bool, dm); QFETCH(QString, scenario);
SendCore core; QVERIFY(core.start());
auto* history = core.history.data(); history->resize(500, 420); history->show();
auto* view = history->findChild<ChatView*>(); QVERIFY(view);
auto* model = qobject_cast<QStandardItemModel*>(view->model()); QVERIFY(model);
QJsonArray messages; QString conversation; quint64 generation = 0;
if (dm) {
SC_MYKEYS peer{}; uint8_t ed[32]; QCOMPARE(sc_generate_keypair(&peer), 0);
QCOMPARE(sc_derive_ed25519_pubkey(peer.private_key, ed), 0);
QCOMPARE(dm_start(core.instance, sc_derive_node_id_from_pubkey(peer.public_key), peer.public_key, ed, "Scroll peer", nullptr), 0);
const auto conversations = core.db.getDmConversations(); QCOMPARE(conversations.size(), 1);
conversation = conversations.first().convId; generation = conversations.first().generation;
history->loadChannel("dm:" + conversation);
}
const auto append = [&](int seq, const QString& text, bool outgoing = false) {
if (dm) {
messages.append(QJsonObject{{"seq", seq}, {"ts", seq * 1000}, {"dir", outgoing ? 1 : 0},
{"author", QString::number(core.instance->node_id)}, {"data", text}, {"content_type", "text/plain"}});
return true;
}
const auto bytes = text.toUtf8(); chat_msg_submit request{};
snprintf(request.channel_id, sizeof(request.channel_id), "%s", qPrintable(core.channel));
strcpy(request.content_type, "text/plain"); request.data = (uint8_t*)bytes.constData(); request.data_len = bytes.size();
request.timestamp = 1000000 + seq * 1000;
return chat_core_submit_message(core.instance, &request) == 0;
};
const auto snapshot = [&] {
QByteArray packet; packet.append(char(conversation.toUtf8().size())); packet.append(conversation.toUtf8());
packet.append(reinterpret_cast<const char*>(&generation), sizeof(generation));
packet.append(QJsonDocument(messages).toJson(QJsonDocument::Compact)); history->onDmMessages((const uint8_t*)packet.constData(), packet.size());
};
for (int i = 1; i <= 60; ++i) QVERIFY(append(i, QString("message %1\nsecond line").arg(i)));
if (dm) snapshot(); else history->loadChannel(core.channel);
QTest::qWait(30); view->doItemsLayout(); view->scrollToBottom();
auto* scrollbar = view->verticalScrollBar(); const int line = view->fontMetrics().lineSpacing();
QVERIFY(scrollbar->maximum() > 30 * line);
if (!dm && scenario == "own") {
auto* delegate = qobject_cast<MessageDelegate*>(view->itemDelegate()); QVERIFY(delegate);
delegate->replyRequested(model->index(0, 0).data(MsgMessageKeyRole).toString());
QCoreApplication::processEvents();
}
const int distance = scenario == "bottom" ? 0 : scenario == "boundary" ? 10 * line :
scenario == "far" || scenario == "own" ? 30 * line : 5 * line;
scrollbar->setValue(scrollbar->maximum() - distance); const int previous = scrollbar->value();
const QString text = "```cpp\n" + QString("int value = 1;\n").repeated(30) + "```";
if (scenario != "unchanged") {
if (!dm && scenario == "own") {
core.editor()->setPlainText(text); QVERIFY(core.send()); core.pump();
QCOMPARE(scrollbar->value(), scrollbar->maximum());
} else QVERIFY(append(61, text, scenario == "own"));
}
if (dm) snapshot(); else history->refresh();
QCoreApplication::processEvents(); view->doItemsLayout();
const bool follow = scenario != "far" && scenario != "unchanged";
if (follow) QCOMPARE(scrollbar->value(), scrollbar->maximum());
else QCOMPARE(scrollbar->value(), previous);
GUI_DEBUG("scroll verified: dm=%d scenario=%s previous=%d current=%d maximum=%d", dm, qPrintable(scenario), previous,
scrollbar->value(), scrollbar->maximum());
// Отложенная прокрутка предыдущего канала не должна сдвинуть новую историю.
if (scenario == "near") {
if (dm) { QVERIFY(append(62, "next")); snapshot(); }
else { QVERIFY(append(62, "next")); history->refresh(); }
history->loadChannel(QString());
QCoreApplication::processEvents(); QCOMPARE(model->rowCount(), 0);
}
}
void clipboardImageCommitsThroughCore_data() {
QTest::addColumn<bool>("dm"); QTest::addColumn<bool>("jpeg"); QTest::addColumn<bool>("manual");
QTest::newRow("png-group-reply") << false << false << false;