Browse Source

Verify invitation title delivery and one-line full-link actions

master
evgeny 1 week ago
parent
commit
f70d5c7460
  1. 9
      tests/test_dm_invite.c
  2. 55
      tools/chatgui/tests/test_invite_links.cpp

9
tests/test_dm_invite.c

@ -172,6 +172,8 @@ int main(void) {
chat_core_create_channel_auto(nodes[0], "target");
CHECK(!scalar(nodes[0], "SELECT channel_id FROM channels WHERE name='target'", &target), "create different target group");
CHECK(target != source && !message_count(), "initial empty PM");
CHECK(sqlite3_exec(nodes[0]->topo_sqlite_db, "UPDATE channels SET name='target \"группа\"\n<>&' WHERE name='target'",
NULL, NULL, NULL) == SQLITE_OK, "group title with Unicode, quotes and newline");
char target_id[64]; snprintf(target_id, sizeof(target_id), "%llu", (unsigned long long)target);
for (int i = 0; i < 5; i++) {
char text[64]; snprintf(text, sizeof(text), "history before invitation %d", i);
@ -215,6 +217,13 @@ int main(void) {
if (!dm_list_messages_json(nodes[1], conv, 10, 0, messages, sizeof(messages), &length)) link = strstr(messages, "utun://");
} while (!link && get_time_tb() < deadline);
CHECK(link, "invite delivered to B over source group's UDP route");
CHECK(strstr(messages, "\"ct\":\"invite\"") &&
strstr(messages, "\"tags\":{\"group_name\":\"target \\\"группа\\\"\\n<>&\"}"),
"encrypted group name survives delivery and JSON escaping without sender-language text");
char outgoing[8192]; size_t outgoing_len = 0;
CHECK(!dm_list_messages_json(nodes[0], conv, 10, 0, outgoing, sizeof(outgoing), &outgoing_len) &&
strstr(outgoing, "\"tags\":{\"group_name\":\"target \\\"группа\\\"\\n<>&\"}"),
"sender and recipient receive the same group-name tag");
char* end = strchr(link, '"'); CHECK(end, "complete invite text in PM"); *end = '\0';
struct InviteData received; char error[128];
CHECK(!invite_link_decode(link, strlen(link), &received, error, sizeof(error)) && received.channelId == target,

55
tools/chatgui/tests/test_invite_links.cpp

@ -4,6 +4,7 @@
#include "../src/accountdelegate.h"
#include <QtTest>
#include <QStandardItemModel>
#include <QClipboard>
extern "C" {
#include "chat/invite_link.h"
}
@ -11,6 +12,60 @@ extern "C" {
class InviteLinksTest : public QObject {
Q_OBJECT
private slots:
void compactInvitationUsesFullLinkForClickAndCopy() {
struct InviteData invite = {};
invite.channelId = 42; invite.join_key = 123; invite.pubkey[0] = 1; invite.addrCount = 8;
for (auto& address : invite.addrs) { address.family = 6; address.proto = INVITE_PROTO_TCP; address.port = 443; }
char buffer[1024];
QVERIFY(invite_link_encode(&invite, nullptr, buffer, sizeof(buffer)) > 0);
const QString link = QString::fromUtf8(buffer);
const QString text = QStringLiteral("Приглашение в группу «Группа»\n") + link;
for (int width : {240, 480}) {
QStandardItemModel model;
auto* message = new QStandardItem;
message->setData(text, MsgTextRole); message->setData(link, MsgInviteLinkRole);
message->setData(QStringLiteral("text/plain"), MsgContentTypeRole); message->setData(true, MsgIsOutgoingRole);
model.appendRow(message);
ChatView view; MessageDelegate delegate;
view.setModel(&model); view.setItemDelegate(&delegate); view.resize(width, 300);
view.setInviteHitTest([&](const QModelIndex& index, const QPoint& point) {
QStyleOptionViewItem option; option.initFrom(&view); option.widget = &view; option.rect = view.visualRect(index);
return delegate.inviteLinkAt(option, index, point);
});
view.show(); QTest::qWait(30);
const QModelIndex index = model.index(0, 0);
QStyleOptionViewItem option; option.initFrom(&view); option.widget = &view; option.rect = view.visualRect(index);
QPoint firstPoint, lastPoint;
QSet<int> rows;
for (int y = 0; y < option.rect.height(); ++y) {
for (int x = 0; x < view.viewport()->width(); x += 2) {
const QString hit = delegate.inviteLinkAt(option, index, QPoint(x, y));
if (hit.isEmpty()) continue;
QCOMPARE(hit, link);
rows.insert(y);
if (firstPoint.isNull()) firstPoint = QPoint(x, y);
lastPoint = QPoint(x, y);
}
}
QVERIFY(!firstPoint.isNull());
QVERIFY(rows.size() <= QFontMetrics(option.font).height() + 1);
QVERIFY(option.rect.height() < 160);
QSignalSpy clicked(&view, &ChatView::inviteLinkActivated);
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, lastPoint);
QCOMPARE(clicked.count(), 1); QCOMPARE(clicked.last().first().toString(), link);
QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, firstPoint);
QMouseEvent drag(QEvent::MouseMove, lastPoint, view.viewport()->mapToGlobal(lastPoint),
Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
QApplication::sendEvent(view.viewport(), &drag);
QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, lastPoint);
QTest::qWait(20);
QCOMPARE(clicked.count(), 1);
view.copySelection();
QCOMPARE(QApplication::clipboard()->text(), link);
QCOMPARE(index.data(MsgTextRole).toString(), text);
}
}
void wrappedLinksPreserveTheirCompleteText() {
struct InviteData invite = {};
invite.channelId = 42; invite.join_key = 123; invite.pubkey[0] = 1; invite.addrCount = 8;

Loading…
Cancel
Save