feat: add snapshot tests for eventsub messages (#5965)
This commit is contained in:
@@ -46,6 +46,7 @@
|
||||
- Dev: Updated `googletest` to 1.16.0. (#5942)
|
||||
- Dev: Fixed duplicate CMake configure in clean builds. (#5940)
|
||||
- Dev: BTTV emotes are now loaded as WEBP. (#5957)
|
||||
- Dev: Added snapshot tests for EventSub. (#5965)
|
||||
|
||||
## 2.5.2
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ boost::json::result_for<std::chrono::system_clock::time_point,
|
||||
|
||||
std::chrono::system_clock::time_point tp;
|
||||
std::istringstream in{*raw};
|
||||
in >> date::parse("%FT%TZ", tp);
|
||||
in >> date::parse("%FT%H:%M:%12SZ", tp);
|
||||
|
||||
return tp;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "providers/seventv/SeventvEmotes.hpp"
|
||||
#include "providers/twitch/TwitchChannel.hpp"
|
||||
#include "providers/twitch/TwitchIrcServer.hpp"
|
||||
#include "util/Twitch.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -45,8 +46,19 @@ public:
|
||||
|
||||
ChannelPtr getChannelOrEmpty(const QString &dirtyChannelName) override
|
||||
{
|
||||
assert(false && "unimplemented getChannelOrEmpty in mock irc server");
|
||||
return {};
|
||||
QString query = cleanChannelName(dirtyChannelName);
|
||||
|
||||
auto it = this->mockChannels.find(query);
|
||||
if (it == this->mockChannels.end())
|
||||
{
|
||||
return Channel::getEmpty();
|
||||
}
|
||||
auto chan = it->second.lock();
|
||||
if (!chan)
|
||||
{
|
||||
return Channel::getEmpty();
|
||||
}
|
||||
return chan;
|
||||
}
|
||||
|
||||
void addFakeMessage(const QString &data) override
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <unordered_map>
|
||||
|
||||
class TestIrcMessageHandlerP;
|
||||
class TestEventSubMessagesP;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
@@ -514,6 +515,7 @@ private:
|
||||
friend class IrcMessageHandler;
|
||||
friend class Commands_E2E_Test;
|
||||
friend class ::TestIrcMessageHandlerP;
|
||||
friend class ::TestEventSubMessagesP;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "singletons/WindowManager.hpp"
|
||||
#include "util/PostToThread.hpp"
|
||||
#include "util/RatelimitBucket.hpp"
|
||||
#include "util/Twitch.hpp"
|
||||
|
||||
#include <IrcCommand>
|
||||
#include <IrcMessage>
|
||||
@@ -1201,18 +1202,6 @@ std::shared_ptr<Channel> TwitchIrcServer::getChannelOrEmptyByID(
|
||||
return Channel::getEmpty();
|
||||
}
|
||||
|
||||
QString TwitchIrcServer::cleanChannelName(const QString &dirtyChannelName)
|
||||
{
|
||||
if (dirtyChannelName.startsWith('#'))
|
||||
{
|
||||
return dirtyChannelName.mid(1).toLower();
|
||||
}
|
||||
else
|
||||
{
|
||||
return dirtyChannelName.toLower();
|
||||
}
|
||||
}
|
||||
|
||||
bool TwitchIrcServer::prepareToSend(
|
||||
const std::shared_ptr<TwitchChannel> &channel)
|
||||
{
|
||||
@@ -1544,7 +1533,7 @@ void TwitchIrcServer::sendRawMessage(const QString &rawMessage)
|
||||
|
||||
ChannelPtr TwitchIrcServer::getOrAddChannel(const QString &dirtyChannelName)
|
||||
{
|
||||
auto channelName = this->cleanChannelName(dirtyChannelName);
|
||||
auto channelName = cleanChannelName(dirtyChannelName);
|
||||
|
||||
// try get channel
|
||||
ChannelPtr chan = this->getChannelOrEmpty(channelName);
|
||||
@@ -1594,7 +1583,7 @@ ChannelPtr TwitchIrcServer::getOrAddChannel(const QString &dirtyChannelName)
|
||||
|
||||
ChannelPtr TwitchIrcServer::getChannelOrEmpty(const QString &dirtyChannelName)
|
||||
{
|
||||
auto channelName = this->cleanChannelName(dirtyChannelName);
|
||||
auto channelName = cleanChannelName(dirtyChannelName);
|
||||
|
||||
std::lock_guard<std::mutex> lock(this->channelMutex);
|
||||
|
||||
|
||||
@@ -169,8 +169,6 @@ protected:
|
||||
|
||||
std::shared_ptr<Channel> getCustomChannel(const QString &channelname);
|
||||
|
||||
QString cleanChannelName(const QString &dirtyChannelName);
|
||||
|
||||
private:
|
||||
void onMessageSendRequested(const std::shared_ptr<TwitchChannel> &channel,
|
||||
const QString &message, bool &sent);
|
||||
|
||||
@@ -55,7 +55,10 @@ void Connection::onChannelBan(
|
||||
|
||||
BanAction action{};
|
||||
|
||||
action.timestamp = std::chrono::steady_clock::now();
|
||||
if (!getApp()->isTest())
|
||||
{
|
||||
action.timestamp = std::chrono::steady_clock::now();
|
||||
}
|
||||
action.roomID = roomID;
|
||||
action.source = ActionUser{
|
||||
.id = QString::fromStdString(payload.event.moderatorUserID),
|
||||
@@ -85,6 +88,10 @@ void Connection::onChannelBan(
|
||||
|
||||
runInGuiThread([action{std::move(action)}, chan{std::move(chan)}] {
|
||||
auto time = QDateTime::currentDateTime();
|
||||
if (getApp()->isTest())
|
||||
{
|
||||
time = QDateTime::fromSecsSinceEpoch(0).toUTC();
|
||||
}
|
||||
MessageBuilder msg(action, time);
|
||||
msg->flags.set(MessageFlag::PubSub);
|
||||
chan->addOrReplaceTimeout(msg.release(), QDateTime::currentDateTime());
|
||||
@@ -162,7 +169,11 @@ void Connection::onChannelModerate(
|
||||
return;
|
||||
}
|
||||
|
||||
const auto now = QDateTime::currentDateTime();
|
||||
auto now = QDateTime::currentDateTime();
|
||||
if (getApp()->isTest())
|
||||
{
|
||||
now = QDateTime::fromSecsSinceEpoch(0).toUTC();
|
||||
}
|
||||
|
||||
std::visit(
|
||||
[&](auto &&action) {
|
||||
|
||||
@@ -62,6 +62,16 @@ void stripChannelName(QString &channelName)
|
||||
}
|
||||
}
|
||||
|
||||
QString cleanChannelName(const QString &dirtyChannelName)
|
||||
{
|
||||
if (dirtyChannelName.startsWith('#'))
|
||||
{
|
||||
return dirtyChannelName.mid(1).toLower();
|
||||
}
|
||||
|
||||
return dirtyChannelName.toLower();
|
||||
}
|
||||
|
||||
std::pair<ParsedUserName, ParsedUserID> parseUserNameOrID(const QString &input)
|
||||
{
|
||||
if (input.startsWith("id:"))
|
||||
|
||||
@@ -16,6 +16,9 @@ void stripUserName(QString &userName);
|
||||
// stripChannelName removes any @ prefix or , suffix to make it more suitable for command use
|
||||
void stripChannelName(QString &channelName);
|
||||
|
||||
/// Strips a leading `#` and lowercases the name
|
||||
QString cleanChannelName(const QString &dirtyChannelName);
|
||||
|
||||
using ParsedUserName = QString;
|
||||
using ParsedUserID = QString;
|
||||
|
||||
|
||||
@@ -53,6 +53,8 @@ set(test_SOURCES
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/IgnoreController.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/OnceFlag.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/IncognitoBrowser.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/EventSubMessages.cpp
|
||||
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/lib/Snapshot.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/lib/Snapshot.hpp
|
||||
# Add your new file above this line!
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"input": {
|
||||
"banned_at": "2023-05-20T12:30:55.518375571Z",
|
||||
"broadcaster_user_id": "11148817",
|
||||
"broadcaster_user_login": "pajlada",
|
||||
"broadcaster_user_name": "pajlada",
|
||||
"ends_at": null,
|
||||
"is_permanent": true,
|
||||
"moderator_user_id": "29024944",
|
||||
"moderator_user_login": "CLIModerator",
|
||||
"moderator_user_name": "CLIModerator",
|
||||
"reason": "This is a test event",
|
||||
"user_id": "40389552",
|
||||
"user_login": "testFromUser",
|
||||
"user_name": "testFromUser"
|
||||
},
|
||||
"output": [
|
||||
{
|
||||
"badgeInfos": {
|
||||
},
|
||||
"badges": [
|
||||
],
|
||||
"channelName": "",
|
||||
"count": 1,
|
||||
"displayName": "",
|
||||
"elements": [
|
||||
{
|
||||
"element": {
|
||||
"color": "System",
|
||||
"flags": "Timestamp",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"0:00"
|
||||
]
|
||||
},
|
||||
"flags": "Timestamp",
|
||||
"format": "",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"time": "00:00:00",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TimestampElement"
|
||||
},
|
||||
{
|
||||
"color": "System",
|
||||
"flags": "Text",
|
||||
"link": {
|
||||
"type": "UserInfo",
|
||||
"value": "CLIModerator"
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"CLIModerator"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "System",
|
||||
"flags": "Text",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"banned"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "System",
|
||||
"flags": "Text",
|
||||
"link": {
|
||||
"type": "UserInfo",
|
||||
"value": "testFromUser"
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"testFromUser:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "System",
|
||||
"flags": "Text",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"\"This",
|
||||
"is",
|
||||
"a",
|
||||
"test",
|
||||
"event\"."
|
||||
]
|
||||
}
|
||||
],
|
||||
"flags": "System|Timeout|PubSub",
|
||||
"id": "",
|
||||
"localizedName": "",
|
||||
"loginName": "CLIModerator",
|
||||
"messageText": "CLIModerator banned testFromUser: \"This is a test event\". ",
|
||||
"searchText": "CLIModerator banned testFromUser: \"This is a test event\". ",
|
||||
"serverReceivedTime": "1970-01-01T00:00:00Z",
|
||||
"timeoutUser": "testFromUser",
|
||||
"userID": "",
|
||||
"usernameColor": "#ff000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"input": {
|
||||
"banned_at": "2023-05-20T12:30:55.518375571Z",
|
||||
"broadcaster_user_id": "11148817",
|
||||
"broadcaster_user_login": "pajlada",
|
||||
"broadcaster_user_name": "pajlada",
|
||||
"ends_at": "2023-05-20T12:40:55.518375571Z",
|
||||
"is_permanent": false,
|
||||
"moderator_user_id": "29024944",
|
||||
"moderator_user_login": "CLIModerator",
|
||||
"moderator_user_name": "CLIModerator",
|
||||
"reason": "This is a test event",
|
||||
"user_id": "40389552",
|
||||
"user_login": "testFromUser",
|
||||
"user_name": "testFromUser"
|
||||
},
|
||||
"output": [
|
||||
{
|
||||
"badgeInfos": {
|
||||
},
|
||||
"badges": [
|
||||
],
|
||||
"channelName": "",
|
||||
"count": 1,
|
||||
"displayName": "",
|
||||
"elements": [
|
||||
{
|
||||
"element": {
|
||||
"color": "System",
|
||||
"flags": "Timestamp",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"0:00"
|
||||
]
|
||||
},
|
||||
"flags": "Timestamp",
|
||||
"format": "",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"time": "00:00:00",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TimestampElement"
|
||||
},
|
||||
{
|
||||
"color": "System",
|
||||
"flags": "Text",
|
||||
"link": {
|
||||
"type": "UserInfo",
|
||||
"value": "CLIModerator"
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"CLIModerator"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "System",
|
||||
"flags": "Text",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"timed",
|
||||
"out"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "System",
|
||||
"flags": "Text",
|
||||
"link": {
|
||||
"type": "UserInfo",
|
||||
"value": "testFromUser"
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"testFromUser"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "System",
|
||||
"flags": "Text",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"for",
|
||||
"10m:",
|
||||
"\"This",
|
||||
"is",
|
||||
"a",
|
||||
"test",
|
||||
"event\"."
|
||||
]
|
||||
}
|
||||
],
|
||||
"flags": "System|Timeout|PubSub",
|
||||
"id": "",
|
||||
"localizedName": "",
|
||||
"loginName": "CLIModerator",
|
||||
"messageText": "CLIModerator timed out testFromUser for 10m: \"This is a test event\". ",
|
||||
"searchText": "CLIModerator timed out testFromUser for 10m: \"This is a test event\". ",
|
||||
"serverReceivedTime": "1970-01-01T00:00:00Z",
|
||||
"timeoutUser": "testFromUser",
|
||||
"userID": "",
|
||||
"usernameColor": "#ff000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
{
|
||||
"input": {
|
||||
"action": "warn",
|
||||
"automod_terms": null,
|
||||
"ban": null,
|
||||
"broadcaster_user_id": "11148817",
|
||||
"broadcaster_user_login": "pajlada",
|
||||
"broadcaster_user_name": "pajlada",
|
||||
"delete": null,
|
||||
"followers": null,
|
||||
"moderator_user_id": "424596340",
|
||||
"moderator_user_login": "quotrok",
|
||||
"moderator_user_name": "quotrok",
|
||||
"raid": null,
|
||||
"shared_chat_ban": null,
|
||||
"shared_chat_delete": null,
|
||||
"shared_chat_timeout": null,
|
||||
"shared_chat_unban": null,
|
||||
"shared_chat_untimeout": null,
|
||||
"slow": null,
|
||||
"source_broadcaster_user_id": "41292030",
|
||||
"source_broadcaster_user_login": "adflynn404",
|
||||
"source_broadcaster_user_name": "adflynn404",
|
||||
"timeout": null,
|
||||
"unban": null,
|
||||
"unban_request": null,
|
||||
"unmod": null,
|
||||
"unraid": null,
|
||||
"untimeout": null,
|
||||
"unvip": null,
|
||||
"vip": null,
|
||||
"warn": {
|
||||
"chat_rules_cited": null,
|
||||
"reason": "cut it out",
|
||||
"user_id": "141981764",
|
||||
"user_login": "twitchdev",
|
||||
"user_name": "TwitchDev"
|
||||
}
|
||||
},
|
||||
"output": [
|
||||
{
|
||||
"badgeInfos": {
|
||||
},
|
||||
"badges": [
|
||||
],
|
||||
"channelName": "",
|
||||
"count": 1,
|
||||
"displayName": "",
|
||||
"elements": [
|
||||
{
|
||||
"element": {
|
||||
"color": "System",
|
||||
"flags": "Timestamp",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"0:00"
|
||||
]
|
||||
},
|
||||
"flags": "Timestamp",
|
||||
"format": "",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"time": "00:00:00",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TimestampElement"
|
||||
},
|
||||
{
|
||||
"color": "Text",
|
||||
"fallbackColor": "System",
|
||||
"flags": "Text|Mention",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "MentionElement",
|
||||
"userColor": "System",
|
||||
"userLoginName": "quotrok",
|
||||
"words": [
|
||||
"quotrok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "System",
|
||||
"flags": "Text",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"has",
|
||||
"warned"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "Text",
|
||||
"fallbackColor": "System",
|
||||
"flags": "Text|Mention",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": false,
|
||||
"type": "MentionElement",
|
||||
"userColor": "System",
|
||||
"userLoginName": "twitchdev",
|
||||
"words": [
|
||||
"TwitchDev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "System",
|
||||
"flags": "Text",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
":"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "System",
|
||||
"flags": "Text",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"cut",
|
||||
"it",
|
||||
"out"
|
||||
]
|
||||
}
|
||||
],
|
||||
"flags": "System|Timeout",
|
||||
"id": "",
|
||||
"localizedName": "",
|
||||
"loginName": "quotrok",
|
||||
"messageText": "quotrok has warned twitchdev: cut it out ",
|
||||
"searchText": "quotrok has warned twitchdev: cut it out ",
|
||||
"serverReceivedTime": "1970-01-01T00:00:00Z",
|
||||
"timeoutUser": "",
|
||||
"userID": "",
|
||||
"usernameColor": "#ff000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
{
|
||||
"input": {
|
||||
"action": "warn",
|
||||
"automod_terms": null,
|
||||
"ban": null,
|
||||
"broadcaster_user_id": "11148817",
|
||||
"broadcaster_user_login": "pajlada",
|
||||
"broadcaster_user_name": "pajlada",
|
||||
"delete": null,
|
||||
"followers": null,
|
||||
"moderator_user_id": "424596340",
|
||||
"moderator_user_login": "quotrok",
|
||||
"moderator_user_name": "quotrok",
|
||||
"raid": null,
|
||||
"shared_chat_ban": null,
|
||||
"shared_chat_delete": null,
|
||||
"shared_chat_timeout": null,
|
||||
"shared_chat_unban": null,
|
||||
"shared_chat_untimeout": null,
|
||||
"slow": null,
|
||||
"source_broadcaster_user_id": "11148817",
|
||||
"source_broadcaster_user_login": "pajlada",
|
||||
"source_broadcaster_user_name": "pajlada",
|
||||
"timeout": null,
|
||||
"unban": null,
|
||||
"unban_request": null,
|
||||
"unmod": null,
|
||||
"unraid": null,
|
||||
"untimeout": null,
|
||||
"unvip": null,
|
||||
"vip": null,
|
||||
"warn": {
|
||||
"chat_rules_cited": null,
|
||||
"reason": "cut it out",
|
||||
"user_id": "141981764",
|
||||
"user_login": "twitchdev",
|
||||
"user_name": "TwitchDev"
|
||||
}
|
||||
},
|
||||
"output": [
|
||||
{
|
||||
"badgeInfos": {
|
||||
},
|
||||
"badges": [
|
||||
],
|
||||
"channelName": "",
|
||||
"count": 1,
|
||||
"displayName": "",
|
||||
"elements": [
|
||||
{
|
||||
"element": {
|
||||
"color": "System",
|
||||
"flags": "Timestamp",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"0:00"
|
||||
]
|
||||
},
|
||||
"flags": "Timestamp",
|
||||
"format": "",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"time": "00:00:00",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TimestampElement"
|
||||
},
|
||||
{
|
||||
"color": "Text",
|
||||
"fallbackColor": "System",
|
||||
"flags": "Text|Mention",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "MentionElement",
|
||||
"userColor": "System",
|
||||
"userLoginName": "quotrok",
|
||||
"words": [
|
||||
"quotrok"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "System",
|
||||
"flags": "Text",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"has",
|
||||
"warned"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "Text",
|
||||
"fallbackColor": "System",
|
||||
"flags": "Text|Mention",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": false,
|
||||
"type": "MentionElement",
|
||||
"userColor": "System",
|
||||
"userLoginName": "twitchdev",
|
||||
"words": [
|
||||
"TwitchDev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "System",
|
||||
"flags": "Text",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
":"
|
||||
]
|
||||
},
|
||||
{
|
||||
"color": "System",
|
||||
"flags": "Text",
|
||||
"link": {
|
||||
"type": "None",
|
||||
"value": ""
|
||||
},
|
||||
"style": "ChatMedium",
|
||||
"tooltip": "",
|
||||
"trailingSpace": true,
|
||||
"type": "TextElement",
|
||||
"words": [
|
||||
"cut",
|
||||
"it",
|
||||
"out"
|
||||
]
|
||||
}
|
||||
],
|
||||
"flags": "System|Timeout",
|
||||
"id": "",
|
||||
"localizedName": "",
|
||||
"loginName": "quotrok",
|
||||
"messageText": "quotrok has warned twitchdev: cut it out ",
|
||||
"searchText": "quotrok has warned twitchdev: cut it out ",
|
||||
"serverReceivedTime": "1970-01-01T00:00:00Z",
|
||||
"timeoutUser": "",
|
||||
"userID": "",
|
||||
"usernameColor": "#ff000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
#include "common/Literals.hpp"
|
||||
#include "controllers/accounts/AccountController.hpp"
|
||||
#include "lib/Snapshot.hpp"
|
||||
#include "messages/Message.hpp"
|
||||
#include "mocks/BaseApplication.hpp"
|
||||
#include "mocks/Logging.hpp"
|
||||
#include "mocks/TwitchIrcServer.hpp"
|
||||
#include "providers/twitch/eventsub/Connection.hpp"
|
||||
#include "Test.hpp"
|
||||
#include "util/QCompareCaseInsensitive.hpp"
|
||||
|
||||
#include <QString>
|
||||
|
||||
using namespace chatterino;
|
||||
using namespace literals;
|
||||
|
||||
namespace {
|
||||
|
||||
/// Controls whether snapshots will be updated (true) or verified (false)
|
||||
///
|
||||
/// In CI, all snapshots must be verified, thus the integrity tests checks for
|
||||
/// this constant.
|
||||
///
|
||||
/// When adding a test, start with `{ "input": {...} }` and set this to `true`
|
||||
/// to generate an initial snapshot. Make sure to verify the output!
|
||||
constexpr bool UPDATE_SNAPSHOTS = false;
|
||||
|
||||
const QString CATEGORY = u"EventSub"_s;
|
||||
|
||||
/// JSON for the `subscription` object in `payload`
|
||||
const std::map<QString, std::string_view, QCompareCaseInsensitive>
|
||||
SUBSCRIPTIONS{
|
||||
{
|
||||
"channel-moderate",
|
||||
R"({
|
||||
"id": "7297f7eb-3bf5-461f-8ae6-7cd7781ebce3",
|
||||
"status": "enabled",
|
||||
"type": "channel.moderate",
|
||||
"version": "2",
|
||||
"cost": 0,
|
||||
"condition": {
|
||||
"broadcaster_user_id": "11148817",
|
||||
"moderator_user_id": "11148817"
|
||||
},
|
||||
"transport": {
|
||||
"method": "websocket",
|
||||
"session_id": "AgoQUlB8aB2SSsavWVfcs5ljnBIGY2VsbC1j"
|
||||
},
|
||||
"created_at": "2024-02-23T21:12:33.771005262Z"
|
||||
})",
|
||||
},
|
||||
{
|
||||
"channel-ban",
|
||||
R"({
|
||||
"id": "4aa632e0-fca3-590b-e981-bbd12abdb3fe",
|
||||
"status": "enabled",
|
||||
"type": "channel.ban",
|
||||
"version": "1",
|
||||
"condition": { "broadcaster_user_id": "11148817" },
|
||||
"transport": { "method": "websocket", "session_id": "38de428e_b11f07be" },
|
||||
"created_at": "2023-05-20T12:30:55.518375571Z",
|
||||
"cost": 0
|
||||
})",
|
||||
},
|
||||
};
|
||||
|
||||
class MockApplication : public mock::BaseApplication
|
||||
{
|
||||
public:
|
||||
MockApplication() = default;
|
||||
|
||||
ILogging *getChatLogger() override
|
||||
{
|
||||
return &this->logging;
|
||||
}
|
||||
|
||||
ITwitchIrcServer *getTwitch() override
|
||||
{
|
||||
return &this->twitch;
|
||||
}
|
||||
|
||||
AccountController *getAccounts() override
|
||||
{
|
||||
return &this->accounts;
|
||||
}
|
||||
|
||||
mock::EmptyLogging logging;
|
||||
mock::MockTwitchIrcServer twitch;
|
||||
AccountController accounts;
|
||||
};
|
||||
|
||||
std::shared_ptr<TwitchChannel> makeMockTwitchChannel(const QString &name)
|
||||
{
|
||||
auto chan = std::make_shared<TwitchChannel>(name);
|
||||
return chan;
|
||||
}
|
||||
|
||||
boost::beast::flat_buffer makePayload(std::string_view subJson,
|
||||
const QJsonObject &event)
|
||||
{
|
||||
auto subscription =
|
||||
QJsonDocument::fromJson(
|
||||
QByteArray::fromRawData(subJson.data(),
|
||||
static_cast<qsizetype>(subJson.size())))
|
||||
.object();
|
||||
QJsonObject metadata{
|
||||
{"message_id", "e8edc592-5550-4aa5-bba6-39e31a2be435"},
|
||||
{"message_type", "notification"},
|
||||
{"message_timestamp", "2024-05-14T12:31:47.995298776Z"},
|
||||
{"subscription_type", subscription["type"]},
|
||||
{"subscription_version", subscription["version"]},
|
||||
};
|
||||
QJsonObject payload{
|
||||
{"metadata", metadata},
|
||||
{"payload",
|
||||
QJsonObject{
|
||||
{"subscription", subscription},
|
||||
{"event", event},
|
||||
}},
|
||||
};
|
||||
|
||||
auto bytes = QJsonDocument(payload).toJson();
|
||||
|
||||
boost::beast::flat_buffer buf;
|
||||
auto inner = buf.prepare(bytes.size());
|
||||
std::memcpy(inner.data(), bytes.data(), inner.size());
|
||||
buf.commit(inner.size());
|
||||
return buf;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class TestEventSubMessagesP : public ::testing::TestWithParam<QString>
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
auto param = TestEventSubMessagesP::GetParam();
|
||||
this->snapshot = testlib::Snapshot::read(CATEGORY, param);
|
||||
|
||||
this->mockApplication = std::make_unique<MockApplication>();
|
||||
|
||||
this->mainChannel = makeMockTwitchChannel("pajlada");
|
||||
this->mainChannel->setRoomId("11148817");
|
||||
|
||||
this->mockApplication->twitch.mockChannels.emplace("pajlada",
|
||||
this->mainChannel);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
this->mainChannel.reset();
|
||||
this->mockApplication.reset();
|
||||
this->snapshot.reset();
|
||||
}
|
||||
|
||||
std::shared_ptr<TwitchChannel> mainChannel;
|
||||
std::unique_ptr<MockApplication> mockApplication;
|
||||
std::unique_ptr<testlib::Snapshot> snapshot;
|
||||
};
|
||||
|
||||
TEST_P(TestEventSubMessagesP, Run)
|
||||
{
|
||||
QStringView subcategory(snapshot->name());
|
||||
subcategory = subcategory.sliced(0, subcategory.indexOf('/'));
|
||||
auto subscription = SUBSCRIPTIONS.find(subcategory);
|
||||
ASSERT_NE(subscription, SUBSCRIPTIONS.end()) << subcategory;
|
||||
|
||||
auto json = makePayload(subscription->second, snapshot->input().toObject());
|
||||
|
||||
std::unique_ptr<eventsub::lib::Listener> listener =
|
||||
std::make_unique<eventsub::Connection>();
|
||||
auto ec = eventsub::lib::handleMessage(listener, json);
|
||||
ASSERT_FALSE(ec.failed())
|
||||
<< ec.what() << ec.message() << ec.location().to_string();
|
||||
|
||||
auto messages = mainChannel->getMessageSnapshot();
|
||||
QJsonArray output;
|
||||
for (const auto &message : messages)
|
||||
{
|
||||
output.append(message->toJson());
|
||||
}
|
||||
|
||||
ASSERT_TRUE(snapshot->run(output, UPDATE_SNAPSHOTS))
|
||||
<< "Snapshot " << snapshot->name() << " failed. Expected JSON to be\n"
|
||||
<< QJsonDocument(snapshot->output().toArray()).toJson() << "\nbut got\n"
|
||||
<< QJsonDocument(output).toJson() << "\ninstead.";
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
EventSubMessages, TestEventSubMessagesP,
|
||||
testing::ValuesIn(testlib::Snapshot::discoverNested(CATEGORY)));
|
||||
|
||||
TEST(TestEventSubMessagesP, Integrity)
|
||||
{
|
||||
ASSERT_FALSE(UPDATE_SNAPSHOTS); // make sure fixtures are actually tested
|
||||
}
|
||||
@@ -175,6 +175,29 @@ QStringList Snapshot::discover(const QString &category)
|
||||
return files;
|
||||
}
|
||||
|
||||
QStringList Snapshot::discoverNested(const QString &category)
|
||||
{
|
||||
auto directories =
|
||||
baseDir(category).entryList(QDir::NoDotAndDotDot | QDir::Dirs);
|
||||
QStringList all;
|
||||
for (const auto &dir : directories)
|
||||
{
|
||||
auto d = baseDir(category);
|
||||
d.cd(dir);
|
||||
auto files = d.entryList(QDir::NoDotAndDotDot | QDir::Files);
|
||||
for (const auto &file : files)
|
||||
{
|
||||
QStringView view(file);
|
||||
if (view.endsWith(u".json"))
|
||||
{
|
||||
view = view.sliced(0, view.size() - 5);
|
||||
}
|
||||
all.append(dir % u'/' % view);
|
||||
}
|
||||
}
|
||||
return all;
|
||||
}
|
||||
|
||||
bool Snapshot::run(const QJsonValue &got, bool updateSnapshots) const
|
||||
{
|
||||
if (updateSnapshots)
|
||||
|
||||
@@ -70,6 +70,9 @@ public:
|
||||
/// Finds all tests in @a category
|
||||
static QStringList discover(const QString &category);
|
||||
|
||||
/// Finds all 1-level nested tests in @a category (category/foo/bar)
|
||||
static QStringList discoverNested(const QString &category);
|
||||
|
||||
/// @brief Runs the snapshot test
|
||||
///
|
||||
/// If @a updateSnapshots is `false`, this checks that @a got matches the
|
||||
|
||||
Reference in New Issue
Block a user