feat(uploader): extend JSON selectors (#6193)
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
- Minor: Made filters searchable in the Settings dialog search bar. (#5890)
|
- Minor: Made filters searchable in the Settings dialog search bar. (#5890)
|
||||||
- Minor: Updated emojis to Unicode 16.0. (#6155)
|
- Minor: Updated emojis to Unicode 16.0. (#6155)
|
||||||
- Minor: Allow disabling of double-click tab renaming through setting. (#6163, #6184)
|
- Minor: Allow disabling of double-click tab renaming through setting. (#6163, #6184)
|
||||||
|
- Minor: The JSON selector in the upload response can now query arrays using their indices like `foo.0`. (#6193)
|
||||||
- Minor: Added hotkey Action for opening account selector. (#6192)
|
- Minor: Added hotkey Action for opening account selector. (#6192)
|
||||||
- Bugfix: Don't create native messaging manifest file if browser directory doesn't exist. (#6116)
|
- Bugfix: Don't create native messaging manifest file if browser directory doesn't exist. (#6116)
|
||||||
- Bugfix: Fixed scrolling now working on inputs in the settings. (#6128)
|
- Bugfix: Fixed scrolling now working on inputs in the settings. (#6128)
|
||||||
|
|||||||
@@ -42,6 +42,25 @@ QJsonArray NetworkResult::parseJsonArray() const
|
|||||||
return jsonDoc.array();
|
return jsonDoc.array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QJsonValue NetworkResult::parseJsonValue() const
|
||||||
|
{
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||||
|
return QJsonValue::fromJson(this->data_);
|
||||||
|
#else
|
||||||
|
QJsonDocument jsonDoc(QJsonDocument::fromJson(this->data_));
|
||||||
|
if (jsonDoc.isArray())
|
||||||
|
{
|
||||||
|
return jsonDoc.array();
|
||||||
|
}
|
||||||
|
if (jsonDoc.isObject())
|
||||||
|
{
|
||||||
|
return jsonDoc.object();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {}; // undefined
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
rapidjson::Document NetworkResult::parseRapidJson() const
|
rapidjson::Document NetworkResult::parseRapidJson() const
|
||||||
{
|
{
|
||||||
rapidjson::Document ret(rapidjson::kObjectType);
|
rapidjson::Document ret(rapidjson::kObjectType);
|
||||||
|
|||||||
@@ -23,6 +23,13 @@ public:
|
|||||||
/// Parses the result as json and returns the root as an array.
|
/// Parses the result as json and returns the root as an array.
|
||||||
/// Returns empty object if parsing failed.
|
/// Returns empty object if parsing failed.
|
||||||
QJsonArray parseJsonArray() const;
|
QJsonArray parseJsonArray() const;
|
||||||
|
|
||||||
|
/// Parses the result as json and returns the root as a generic value.
|
||||||
|
/// Returns empty object if parsing failed.
|
||||||
|
///
|
||||||
|
/// In Qt 6.9+, this will parse scalar values as well.
|
||||||
|
QJsonValue parseJsonValue() const;
|
||||||
|
|
||||||
/// Parses the result as json and returns the document.
|
/// Parses the result as json and returns the document.
|
||||||
rapidjson::Document parseRapidJson() const;
|
rapidjson::Document parseRapidJson() const;
|
||||||
const QByteArray &getData() const;
|
const QByteArray &getData() const;
|
||||||
|
|||||||
@@ -44,8 +44,57 @@ std::optional<QByteArray> convertToPng(const QImage &image)
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace chatterino::imageuploader::detail {
|
||||||
|
|
||||||
|
// extracting link to either image or its deletion from response body
|
||||||
|
QString getJSONValue(QJsonValue responseJson, QStringView jsonPattern)
|
||||||
|
{
|
||||||
|
for (auto key : jsonPattern.tokenize(u'.'))
|
||||||
|
{
|
||||||
|
if (responseJson.isObject())
|
||||||
|
{
|
||||||
|
responseJson = responseJson[key];
|
||||||
|
}
|
||||||
|
else if (responseJson.isArray())
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
auto idx = key.toLongLong(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
responseJson = responseJson[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we reached a scalar value, no need to continue
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return responseJson.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString getLinkFromResponse(const NetworkResult &response, QString pattern)
|
||||||
|
{
|
||||||
|
QRegularExpression regExp("{(.+)}",
|
||||||
|
QRegularExpression::InvertedGreedinessOption);
|
||||||
|
auto match = regExp.match(pattern);
|
||||||
|
|
||||||
|
auto jsonRoot = response.parseJsonValue();
|
||||||
|
while (match.hasMatch())
|
||||||
|
{
|
||||||
|
pattern.replace(match.captured(0),
|
||||||
|
getJSONValue(jsonRoot, match.capturedView(1)));
|
||||||
|
match = regExp.match(pattern);
|
||||||
|
}
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino::imageuploader::detail
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
|
using namespace imageuploader::detail;
|
||||||
|
|
||||||
// logging information on successful uploads to a json file
|
// logging information on successful uploads to a json file
|
||||||
void ImageUploader::logToFile(const QString &originalFilePath,
|
void ImageUploader::logToFile(const QString &originalFilePath,
|
||||||
const QString &imageLink,
|
const QString &imageLink,
|
||||||
@@ -97,31 +146,6 @@ void ImageUploader::logToFile(const QString &originalFilePath,
|
|||||||
logSaveFile.commit();
|
logSaveFile.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// extracting link to either image or its deletion from response body
|
|
||||||
QString getJSONValue(QJsonValue responseJson, QString jsonPattern)
|
|
||||||
{
|
|
||||||
for (const QString &key : jsonPattern.split("."))
|
|
||||||
{
|
|
||||||
responseJson = responseJson[key];
|
|
||||||
}
|
|
||||||
return responseJson.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString getLinkFromResponse(NetworkResult response, QString pattern)
|
|
||||||
{
|
|
||||||
QRegularExpression regExp("{(.+)}",
|
|
||||||
QRegularExpression::InvertedGreedinessOption);
|
|
||||||
auto match = regExp.match(pattern);
|
|
||||||
|
|
||||||
while (match.hasMatch())
|
|
||||||
{
|
|
||||||
pattern.replace(match.captured(0),
|
|
||||||
getJSONValue(response.parseJson(), match.captured(1)));
|
|
||||||
match = regExp.match(pattern);
|
|
||||||
}
|
|
||||||
return pattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImageUploader::sendImageUploadRequest(RawImageData imageData,
|
void ImageUploader::sendImageUploadRequest(RawImageData imageData,
|
||||||
ChannelPtr channel,
|
ChannelPtr channel,
|
||||||
QPointer<ResizingTextEdit> textEdit)
|
QPointer<ResizingTextEdit> textEdit)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QStringView>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
@@ -14,6 +15,33 @@ class Channel;
|
|||||||
class NetworkResult;
|
class NetworkResult;
|
||||||
using ChannelPtr = std::shared_ptr<Channel>;
|
using ChannelPtr = std::shared_ptr<Channel>;
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
|
|
||||||
|
namespace chatterino::imageuploader::detail {
|
||||||
|
|
||||||
|
/// Traverses the JSON value with a pattern where each key is separated by dots.
|
||||||
|
///
|
||||||
|
/// If the pattern doesn't match, an empty string is returned.
|
||||||
|
///
|
||||||
|
/// **Example**:
|
||||||
|
///
|
||||||
|
/// - JSON: `{"foo": {"bar": [1, "baz"]}}`
|
||||||
|
/// - pattern: `foo.bar.1`
|
||||||
|
/// - return value: `"baz"`
|
||||||
|
QString getJSONValue(QJsonValue responseJson, QStringView jsonPattern);
|
||||||
|
|
||||||
|
/// Interpolates `pattern` with the JSON response.
|
||||||
|
/// **Example**:
|
||||||
|
///
|
||||||
|
/// - response: `{"foo": {"bar": [1, "baz", "qox"]}}`
|
||||||
|
/// - pattern: `https://example.com/{foo.bar.1}.{foo.bar.2}`
|
||||||
|
/// - return value: `"https://example.com/baz.qox"`
|
||||||
|
QString getLinkFromResponse(const NetworkResult &response, QString pattern);
|
||||||
|
|
||||||
|
} // namespace chatterino::imageuploader::detail
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
struct RawImageData {
|
struct RawImageData {
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
QString format;
|
QString format;
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ set(test_SOURCES
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/src/EventSubMessages.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/EventSubMessages.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/WebSocketPool.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/WebSocketPool.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/NativeMessaging.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/NativeMessaging.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/src/ImageUploader.cpp
|
||||||
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/lib/Snapshot.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/lib/Snapshot.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/lib/Snapshot.hpp
|
${CMAKE_CURRENT_LIST_DIR}/src/lib/Snapshot.hpp
|
||||||
|
|||||||
@@ -0,0 +1,261 @@
|
|||||||
|
#include "singletons/ImageUploader.hpp"
|
||||||
|
|
||||||
|
#include "common/network/NetworkResult.hpp"
|
||||||
|
#include "Test.hpp"
|
||||||
|
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace chatterino::imageuploader::detail {
|
||||||
|
|
||||||
|
TEST(ImageUploaderDetail_GetJsonValue, object)
|
||||||
|
{
|
||||||
|
const char *json = R"({
|
||||||
|
"foo": "bar",
|
||||||
|
"baz": {
|
||||||
|
"qox": {
|
||||||
|
"a": 1,
|
||||||
|
"b": "bb",
|
||||||
|
"c": null,
|
||||||
|
"d": true,
|
||||||
|
"1": "one"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
auto jv = QJsonDocument::fromJson(json).object();
|
||||||
|
ASSERT_FALSE(jv.empty());
|
||||||
|
|
||||||
|
std::vector<std::pair<QString, QString>> cases{
|
||||||
|
{"foo", "bar"},
|
||||||
|
{"something", ""},
|
||||||
|
{"0", ""},
|
||||||
|
{"baz", ""},
|
||||||
|
{"baz.qox", ""},
|
||||||
|
{"baz.something", ""},
|
||||||
|
{"baz.qox.a", ""},
|
||||||
|
{"baz.qox.a.b", ""},
|
||||||
|
{"baz.qox.a.b.c", ""},
|
||||||
|
{"baz.qox.b", "bb"},
|
||||||
|
{"baz.qox.b.1", "bb"},
|
||||||
|
{"baz.qox.b.a.whatever", "bb"},
|
||||||
|
{"baz.qox.c", ""},
|
||||||
|
{"baz.qox.c.b", ""},
|
||||||
|
{"baz.qox.c.d.e", ""},
|
||||||
|
{"baz.qox.d", ""},
|
||||||
|
{"baz.qox.d.f", ""},
|
||||||
|
{"baz.qox.1", "one"},
|
||||||
|
{"baz.qox.1.2", "one"},
|
||||||
|
{"baz.qox.2", ""},
|
||||||
|
{"baz.qox.2.4", ""},
|
||||||
|
{"baz.qox.something", ""},
|
||||||
|
{"baz.qox.something.else", ""},
|
||||||
|
{"baz.qox.something.else.no", ""},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto &[pattern, exp] : cases)
|
||||||
|
{
|
||||||
|
ASSERT_EQ(getJSONValue(jv, pattern), exp) << pattern;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ImageUploaderDetail_GetJsonValue, array)
|
||||||
|
{
|
||||||
|
const char *json = R"([
|
||||||
|
"bar",
|
||||||
|
2,
|
||||||
|
true,
|
||||||
|
"f",
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
"qox": {
|
||||||
|
"b": "bb"
|
||||||
|
},
|
||||||
|
"nest": [
|
||||||
|
["a", "b", ["c"]],
|
||||||
|
[42, "d"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
["x"]
|
||||||
|
])";
|
||||||
|
auto jv = QJsonDocument::fromJson(json).array();
|
||||||
|
ASSERT_FALSE(jv.empty());
|
||||||
|
|
||||||
|
std::vector<std::pair<QString, QString>> cases{
|
||||||
|
{"foo", ""},
|
||||||
|
{"-1", ""},
|
||||||
|
{"0x0", ""},
|
||||||
|
{"0", "bar"},
|
||||||
|
{"0.", "bar"},
|
||||||
|
{"0.0", "bar"},
|
||||||
|
{"1", ""},
|
||||||
|
{"2", ""},
|
||||||
|
{"3", "f"},
|
||||||
|
{"4", ""},
|
||||||
|
{"5", ""},
|
||||||
|
{"5.0", ""},
|
||||||
|
{"5.qox", ""},
|
||||||
|
{"5.qox.b", "bb"},
|
||||||
|
{"5.qox.0", ""},
|
||||||
|
{"5.nest", ""},
|
||||||
|
{"5.nest.0", ""},
|
||||||
|
{"5.nest.0.0", "a"},
|
||||||
|
{"5.nest.0.1", "b"},
|
||||||
|
{"5.nest.0.2", ""},
|
||||||
|
{"5.nest.0.2.0", "c"},
|
||||||
|
{"5.nest.0.2.0.1", "c"},
|
||||||
|
{"5.nest.0.2.1", ""},
|
||||||
|
{"5.nest.0.3", ""},
|
||||||
|
{"5.nest.0.3.0", ""},
|
||||||
|
{"5.nest.0.3.0.0", ""},
|
||||||
|
{"5.nest.1", ""},
|
||||||
|
{"5.nest.1.0", ""},
|
||||||
|
{"5.nest.1.1", "d"},
|
||||||
|
{"5.nest.1.1.0", "d"},
|
||||||
|
{"5.nest.1.2", ""},
|
||||||
|
{"6.0", "x"},
|
||||||
|
{"6.zero", ""},
|
||||||
|
{"6.-1", ""},
|
||||||
|
{"6.+0", "x"},
|
||||||
|
{"7", ""},
|
||||||
|
{"7.0", ""},
|
||||||
|
{"8", ""},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto &[pattern, exp] : cases)
|
||||||
|
{
|
||||||
|
ASSERT_EQ(getJSONValue(jv, pattern), exp) << pattern;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ImageUploaderDetail_GetJsonValue, scalar)
|
||||||
|
{
|
||||||
|
ASSERT_EQ(getJSONValue({}, u""), "");
|
||||||
|
ASSERT_EQ(getJSONValue({}, u"a"), "");
|
||||||
|
ASSERT_EQ(getJSONValue({}, u"0"), "");
|
||||||
|
ASSERT_EQ(getJSONValue({}, u"a.b"), "");
|
||||||
|
|
||||||
|
ASSERT_EQ(getJSONValue(QJsonValue::Null, u""), "");
|
||||||
|
ASSERT_EQ(getJSONValue(QJsonValue::Null, u"a"), "");
|
||||||
|
ASSERT_EQ(getJSONValue(QJsonValue::Null, u"0"), "");
|
||||||
|
ASSERT_EQ(getJSONValue(QJsonValue::Null, u"a.b"), "");
|
||||||
|
|
||||||
|
ASSERT_EQ(getJSONValue(true, u""), "");
|
||||||
|
ASSERT_EQ(getJSONValue(true, u"a"), "");
|
||||||
|
ASSERT_EQ(getJSONValue(true, u"0"), "");
|
||||||
|
ASSERT_EQ(getJSONValue(true, u"a.b"), "");
|
||||||
|
|
||||||
|
ASSERT_EQ(getJSONValue(42, u""), "");
|
||||||
|
ASSERT_EQ(getJSONValue(42, u"a"), "");
|
||||||
|
ASSERT_EQ(getJSONValue(42, u"0"), "");
|
||||||
|
ASSERT_EQ(getJSONValue(42, u"a.b"), "");
|
||||||
|
|
||||||
|
ASSERT_EQ(getJSONValue("abc", u""), "abc");
|
||||||
|
ASSERT_EQ(getJSONValue("abc", u"a"), "abc");
|
||||||
|
ASSERT_EQ(getJSONValue("abc", u"0"), "abc");
|
||||||
|
ASSERT_EQ(getJSONValue("abc", u"a.b"), "abc");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ImageUploaderDetail_GetLinkFromResponse, basic)
|
||||||
|
{
|
||||||
|
const char *json = R"({
|
||||||
|
"foo": "bar",
|
||||||
|
"baz": {
|
||||||
|
"qox": {
|
||||||
|
"a": 1,
|
||||||
|
"b": "bb",
|
||||||
|
"c": null,
|
||||||
|
"d": true,
|
||||||
|
"1": "one"
|
||||||
|
},
|
||||||
|
"arr": [
|
||||||
|
["a", "b", ["c"]],
|
||||||
|
[42, "d", "baz"],
|
||||||
|
{
|
||||||
|
"a": "wow"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})";
|
||||||
|
|
||||||
|
std::vector<std::pair<QString, QString>> cases{
|
||||||
|
{"a", "a"},
|
||||||
|
{"foo", "foo"},
|
||||||
|
{"{foo}", "bar"},
|
||||||
|
{"foo{foo}", "foobar"},
|
||||||
|
{"foo.{baz.qox}", "foo."},
|
||||||
|
{"foo.{baz.qox.b}", "foo.bb"},
|
||||||
|
{"{foo", "{foo"},
|
||||||
|
{"foo}", "foo}"},
|
||||||
|
{"{}", "{}"},
|
||||||
|
{"{.}", ""},
|
||||||
|
{"f{..}g", "fg"},
|
||||||
|
{"{baz.qox.b}", "bb"},
|
||||||
|
{"{baz.qox.{baz.arr.0.1}}", "}"},
|
||||||
|
{"a{foo}b{foo}c{baz.arr.0.0}", "abarbbarca"},
|
||||||
|
{".{foo}.{foo}.{baz.arr.0.0}.", ".bar.bar.a."},
|
||||||
|
{"https://{foo}.{foo}/{baz.arr.0.0}.png", "https://bar.bar/a.png"},
|
||||||
|
};
|
||||||
|
|
||||||
|
NetworkResult res(NetworkResult::NetworkError::NoError, 200, json);
|
||||||
|
for (const auto &[pattern, exp] : cases)
|
||||||
|
{
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res, pattern), exp) << pattern;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ImageUploaderDetail_GetLinkFromResponse, scalar)
|
||||||
|
{
|
||||||
|
auto res = [](const char *json) {
|
||||||
|
return NetworkResult(NetworkResult::NetworkError::NoError, 200, json);
|
||||||
|
};
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res(R"("my string")"), "-{}-"), "-{}-");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res(R"("my string")"), "-{.}-"),
|
||||||
|
"-my string-");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res(R"("my string")"), "-{0}-"),
|
||||||
|
"-my string-");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res(R"("my string")"), "-{a}-"),
|
||||||
|
"-my string-");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res(R"("my string")"), "-{a.b}-"),
|
||||||
|
"-my string-");
|
||||||
|
#else
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res(R"("my string")"), "-{}-"), "-{}-");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res(R"("my string")"), "-{.}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res(R"("my string")"), "-{0}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res(R"("my string")"), "-{a}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res(R"("my string")"), "-{a.b}-"), "--");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("my string"), "-{}-"), "-{}-");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("my string"), "-{.}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("my string"), "-{0}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("my string"), "-{a}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("my string"), "-{a.b}-"), "--");
|
||||||
|
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("42"), "-{}-"), "-{}-");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("42"), "-{.}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("42"), "-{0}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("42"), "-{a}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("42"), "-{a.b}-"), "--");
|
||||||
|
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("true"), "-{}-"), "-{}-");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("true"), "-{.}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("true"), "-{0}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("true"), "-{a}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("true"), "-{a.b}-"), "--");
|
||||||
|
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("null"), "-{}-"), "-{}-");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("null"), "-{.}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("null"), "-{0}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("null"), "-{a}-"), "--");
|
||||||
|
ASSERT_EQ(getLinkFromResponse(res("null"), "-{a.b}-"), "--");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino::imageuploader::detail
|
||||||
Reference in New Issue
Block a user