mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
test: add more input completion tests (#5604)
This commit is contained in:
parent
ef4be6cdac
commit
ef3c51a4e2
2
.github/workflows/test-macos.yml
vendored
2
.github/workflows/test-macos.yml
vendored
|
@ -94,5 +94,5 @@ jobs:
|
|||
cd ../pubsub-server-test
|
||||
./server 127.0.0.1:9050 &
|
||||
cd ../build-test
|
||||
ctest --repeat until-pass:4 --output-on-failure --exclude-regex ClassicEmoteNameFiltering
|
||||
ctest --repeat until-pass:4 --output-on-failure
|
||||
working-directory: build-test
|
||||
|
|
2
.github/workflows/test-windows.yml
vendored
2
.github/workflows/test-windows.yml
vendored
|
@ -150,7 +150,7 @@ jobs:
|
|||
cd ..\pubsub-server-test
|
||||
.\server.exe 127.0.0.1:9050 &
|
||||
cd ..\build-test
|
||||
ctest --repeat until-pass:4 --output-on-failure --exclude-regex ClassicEmoteNameFiltering
|
||||
ctest --repeat until-pass:4 --output-on-failure
|
||||
working-directory: build-test
|
||||
|
||||
- name: Clean Conan cache
|
||||
|
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
|
@ -88,7 +88,7 @@ jobs:
|
|||
cd ../pubsub-server-test
|
||||
./server 127.0.0.1:9050 &
|
||||
cd ../build-test
|
||||
ctest --repeat until-pass:4 --output-on-failure --exclude-regex ClassicEmoteNameFiltering
|
||||
ctest --repeat until-pass:4 --output-on-failure
|
||||
working-directory: build-test
|
||||
|
||||
- name: Upload coverage reports to Codecov
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
- Dev: The timer for `StreamerMode` is now destroyed on the correct thread. (#5571)
|
||||
- Dev: Cleanup some parts of the `magic_enum` adaptation for Qt. (#5587)
|
||||
- Dev: Refactored `static`s in headers to only be present once in the final app. (#5588)
|
||||
- Dev: Added more tests for input completion. (#5604)
|
||||
- Dev: Refactored legacy Unicode zero-width-joiner replacement. (#5594)
|
||||
- Dev: The JSON output when copying a message (<kbd>SHIFT</kbd> + right-click) is now more extensive. (#5600)
|
||||
- Dev: Twitch messages are now sent using Twitch's Helix API instead of IRC by default. (#5607)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "controllers/accounts/AccountController.hpp"
|
||||
#include "controllers/completion/strategies/ClassicEmoteStrategy.hpp"
|
||||
#include "controllers/completion/strategies/ClassicUserStrategy.hpp"
|
||||
#include "controllers/completion/strategies/SmartEmoteStrategy.hpp"
|
||||
#include "controllers/completion/strategies/Strategy.hpp"
|
||||
#include "messages/Emote.hpp"
|
||||
#include "mocks/BaseApplication.hpp"
|
||||
|
@ -84,7 +85,30 @@ public:
|
|||
SeventvEmotes seventvEmotes;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
void containsRoughly(std::span<EmoteItem> span, const std::set<QString> &values)
|
||||
{
|
||||
for (const auto &v : values)
|
||||
{
|
||||
bool found = false;
|
||||
for (const auto &actualValue : span)
|
||||
{
|
||||
if (actualValue.displayName == v)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_TRUE(found) << v << " was not found in the span";
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] bool allEmoji(std::span<EmoteItem> span)
|
||||
{
|
||||
return std::ranges::all_of(span, [](const auto &it) {
|
||||
return it.isEmoji && it.providerName == u"Emoji";
|
||||
});
|
||||
}
|
||||
|
||||
EmotePtr namedEmote(const EmoteName &name)
|
||||
{
|
||||
|
@ -104,7 +128,7 @@ void addEmote(EmoteMap &map, const QString &name)
|
|||
map.insert(std::pair<EmoteName, EmotePtr>(eName, namedEmote(eName)));
|
||||
}
|
||||
|
||||
static QString DEFAULT_SETTINGS = R"!(
|
||||
const QString DEFAULT_SETTINGS = R"!(
|
||||
{
|
||||
"accounts": {
|
||||
"uid117166826": {
|
||||
|
@ -117,6 +141,8 @@ static QString DEFAULT_SETTINGS = R"!(
|
|||
}
|
||||
})!";
|
||||
|
||||
} // namespace
|
||||
|
||||
class InputCompletionTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
|
@ -164,6 +190,7 @@ private:
|
|||
addEmote(*bttvEmotes, ":-)");
|
||||
addEmote(*bttvEmotes, "B-)");
|
||||
addEmote(*bttvEmotes, "Clap");
|
||||
addEmote(*bttvEmotes, ":tf:");
|
||||
this->mockApplication->bttvEmotes.setEmotes(std::move(bttvEmotes));
|
||||
|
||||
auto ffzEmotes = std::make_shared<EmoteMap>();
|
||||
|
@ -175,51 +202,57 @@ private:
|
|||
auto seventvEmotes = std::make_shared<EmoteMap>();
|
||||
addEmote(*seventvEmotes, "Clap");
|
||||
addEmote(*seventvEmotes, "Clap2");
|
||||
addEmote(*seventvEmotes, "pajaW");
|
||||
addEmote(*seventvEmotes, "PAJAW");
|
||||
this->mockApplication->seventvEmotes.setGlobalEmotes(
|
||||
std::move(seventvEmotes));
|
||||
}
|
||||
|
||||
protected:
|
||||
auto queryClassicEmoteCompletion(const QString &fullQuery)
|
||||
template <typename T>
|
||||
auto queryEmoteCompletion(const QString &fullQuery)
|
||||
{
|
||||
EmoteSource source(this->channelPtr.get(),
|
||||
std::make_unique<ClassicEmoteStrategy>());
|
||||
EmoteSource source(this->channelPtr.get(), std::make_unique<T>());
|
||||
source.update(fullQuery);
|
||||
|
||||
std::vector<EmoteItem> out(source.output());
|
||||
return out;
|
||||
}
|
||||
|
||||
auto queryClassicTabCompletion(const QString &fullQuery, bool isFirstWord)
|
||||
template <typename T>
|
||||
auto queryTabCompletion(const QString &fullQuery, bool isFirstWord)
|
||||
{
|
||||
EmoteSource source(this->channelPtr.get(),
|
||||
std::make_unique<ClassicTabEmoteStrategy>());
|
||||
EmoteSource source(this->channelPtr.get(), std::make_unique<T>());
|
||||
source.update(fullQuery);
|
||||
|
||||
QStringList m;
|
||||
source.addToStringList(m, 0, isFirstWord);
|
||||
return m;
|
||||
}
|
||||
|
||||
auto queryClassicEmoteCompletion(const QString &fullQuery)
|
||||
{
|
||||
return queryEmoteCompletion<ClassicEmoteStrategy>(fullQuery);
|
||||
}
|
||||
|
||||
auto queryClassicTabCompletion(const QString &fullQuery, bool isFirstWord)
|
||||
{
|
||||
return queryTabCompletion<ClassicTabEmoteStrategy>(fullQuery,
|
||||
isFirstWord);
|
||||
}
|
||||
|
||||
auto querySmartEmoteCompletion(const QString &fullQuery)
|
||||
{
|
||||
return queryEmoteCompletion<SmartEmoteStrategy>(fullQuery);
|
||||
}
|
||||
|
||||
auto querySmartTabCompletion(const QString &fullQuery, bool isFirstWord)
|
||||
{
|
||||
return queryTabCompletion<SmartTabEmoteStrategy>(fullQuery,
|
||||
isFirstWord);
|
||||
}
|
||||
};
|
||||
|
||||
void containsRoughly(std::span<EmoteItem> span, std::set<QString> values)
|
||||
{
|
||||
for (const auto &v : values)
|
||||
{
|
||||
bool found = false;
|
||||
for (const auto &actualValue : span)
|
||||
{
|
||||
if (actualValue.displayName == v)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_TRUE(found) << v << " was not found in the span";
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(InputCompletionTest, ClassicEmoteNameFiltering)
|
||||
{
|
||||
// The completion doesn't guarantee an ordering for a specific category of emotes.
|
||||
|
@ -230,9 +263,9 @@ TEST_F(InputCompletionTest, ClassicEmoteNameFiltering)
|
|||
auto completion = queryClassicEmoteCompletion(":feels");
|
||||
ASSERT_EQ(completion.size(), 3);
|
||||
// all these matches are BTTV global emotes
|
||||
ASSERT_EQ(completion[0].displayName, "FeelsBirthdayMan");
|
||||
ASSERT_EQ(completion[1].displayName, "FeelsBadMan");
|
||||
ASSERT_EQ(completion[2].displayName, "FeelsGoodMan");
|
||||
// these are in no specific order
|
||||
containsRoughly(completion,
|
||||
{"FeelsBirthdayMan", "FeelsBadMan", "FeelsGoodMan"});
|
||||
|
||||
completion = queryClassicEmoteCompletion(":)");
|
||||
ASSERT_EQ(completion.size(), 3);
|
||||
|
@ -299,6 +332,30 @@ TEST_F(InputCompletionTest, ClassicEmoteProviderOrdering)
|
|||
ASSERT_EQ(completion[4].providerName, "Emoji");
|
||||
}
|
||||
|
||||
TEST_F(InputCompletionTest, ClassicEmoteCase)
|
||||
{
|
||||
auto completion = queryClassicEmoteCompletion(":pajaw");
|
||||
ASSERT_EQ(completion.size(), 2);
|
||||
// there's no order here
|
||||
containsRoughly(completion, {"pajaW", "PAJAW"});
|
||||
|
||||
completion = queryClassicEmoteCompletion(":PA");
|
||||
ASSERT_GT(completion.size(), 3);
|
||||
containsRoughly({completion.begin(), 2}, {"pajaW", "PAJAW"});
|
||||
containsRoughly({completion.begin() + 2, completion.end()}, {"parking"});
|
||||
ASSERT_TRUE(allEmoji({completion.begin() + 2, completion.end()}));
|
||||
|
||||
completion = queryClassicEmoteCompletion(":Pajaw");
|
||||
ASSERT_EQ(completion.size(), 2);
|
||||
containsRoughly(completion, {"pajaW", "PAJAW"});
|
||||
|
||||
completion = queryClassicEmoteCompletion(":NOTHING");
|
||||
ASSERT_EQ(completion.size(), 0);
|
||||
|
||||
completion = queryClassicEmoteCompletion(":nothing");
|
||||
ASSERT_EQ(completion.size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(InputCompletionTest, ClassicTabCompletionEmote)
|
||||
{
|
||||
auto completion = queryClassicTabCompletion(":feels", false);
|
||||
|
@ -328,7 +385,13 @@ TEST_F(InputCompletionTest, ClassicTabCompletionEmote)
|
|||
|
||||
TEST_F(InputCompletionTest, ClassicTabCompletionEmoji)
|
||||
{
|
||||
auto completion = queryClassicTabCompletion(":cla", false);
|
||||
auto completion = queryClassicTabCompletion(":tf", false);
|
||||
ASSERT_EQ(completion.size(), 0);
|
||||
|
||||
completion = queryClassicTabCompletion(":)", false);
|
||||
ASSERT_EQ(completion.size(), 0);
|
||||
|
||||
completion = queryClassicTabCompletion(":cla", false);
|
||||
ASSERT_EQ(completion.size(), 8);
|
||||
ASSERT_EQ(completion[0], ":clap: ");
|
||||
ASSERT_EQ(completion[1], ":clap_tone1: ");
|
||||
|
@ -339,3 +402,177 @@ TEST_F(InputCompletionTest, ClassicTabCompletionEmoji)
|
|||
ASSERT_EQ(completion[6], ":clapper: ");
|
||||
ASSERT_EQ(completion[7], ":classical_building: ");
|
||||
}
|
||||
|
||||
TEST_F(InputCompletionTest, ClassicTabCompletionCase)
|
||||
{
|
||||
auto completion = queryClassicTabCompletion("pajaw", false);
|
||||
ASSERT_EQ(completion.size(), 2);
|
||||
ASSERT_EQ(completion[0], "pajaW ");
|
||||
ASSERT_EQ(completion[1], "PAJAW ");
|
||||
|
||||
completion = queryClassicTabCompletion("PA", false);
|
||||
ASSERT_EQ(completion.size(), 2);
|
||||
ASSERT_EQ(completion[0], "pajaW ");
|
||||
ASSERT_EQ(completion[1], "PAJAW ");
|
||||
|
||||
completion = queryClassicTabCompletion("Pajaw", false);
|
||||
ASSERT_EQ(completion.size(), 2);
|
||||
ASSERT_EQ(completion[0], "pajaW ");
|
||||
ASSERT_EQ(completion[1], "PAJAW ");
|
||||
|
||||
completion = queryClassicTabCompletion("NOTHING", false);
|
||||
ASSERT_EQ(completion.size(), 0);
|
||||
|
||||
completion = queryClassicTabCompletion("nothing", false);
|
||||
ASSERT_EQ(completion.size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(InputCompletionTest, SmartEmoteNameFiltering)
|
||||
{
|
||||
auto completion = querySmartEmoteCompletion(":feels");
|
||||
ASSERT_EQ(completion.size(), 3);
|
||||
ASSERT_EQ(completion[0].displayName, "FeelsBadMan");
|
||||
ASSERT_EQ(completion[1].displayName, "FeelsGoodMan");
|
||||
ASSERT_EQ(completion[2].displayName, "FeelsBirthdayMan");
|
||||
|
||||
completion = querySmartEmoteCompletion(":)");
|
||||
ASSERT_EQ(completion.size(), 3);
|
||||
ASSERT_EQ(completion[0].displayName, ":)");
|
||||
ASSERT_EQ(completion[1].displayName, ":-)");
|
||||
ASSERT_EQ(completion[2].displayName, "B-)");
|
||||
|
||||
completion = querySmartEmoteCompletion(":cat");
|
||||
ASSERT_TRUE(completion.size() >= 4);
|
||||
ASSERT_EQ(completion[0].displayName, "cat");
|
||||
ASSERT_EQ(completion[1].displayName, "cat2");
|
||||
ASSERT_EQ(completion[2].displayName, "CatBag");
|
||||
ASSERT_EQ(completion[3].displayName, "joy_cat");
|
||||
}
|
||||
|
||||
TEST_F(InputCompletionTest, SmartEmoteExactNameMatching)
|
||||
{
|
||||
auto completion = querySmartEmoteCompletion(":sal");
|
||||
ASSERT_TRUE(completion.size() >= 4);
|
||||
ASSERT_EQ(completion[0].displayName, "salt");
|
||||
ASSERT_EQ(completion[1].displayName, "SaltyCorn");
|
||||
ASSERT_EQ(completion[2].displayName, "green_salad");
|
||||
ASSERT_EQ(completion[3].displayName, "saluting_face");
|
||||
|
||||
completion = querySmartEmoteCompletion(":salt");
|
||||
ASSERT_TRUE(completion.size() >= 2);
|
||||
ASSERT_EQ(completion[0].displayName, "salt");
|
||||
ASSERT_EQ(completion[1].displayName, "SaltyCorn");
|
||||
}
|
||||
|
||||
TEST_F(InputCompletionTest, SmartEmoteProviderOrdering)
|
||||
{
|
||||
auto completion = querySmartEmoteCompletion(":clap");
|
||||
ASSERT_TRUE(completion.size() >= 6);
|
||||
ASSERT_EQ(completion[0].displayName, "clap");
|
||||
ASSERT_EQ(completion[0].providerName, "Emoji");
|
||||
ASSERT_EQ(completion[1].displayName, "Clap");
|
||||
ASSERT_EQ(completion[1].providerName, "Global BetterTTV");
|
||||
ASSERT_EQ(completion[2].displayName, "Clap");
|
||||
ASSERT_EQ(completion[2].providerName, "Global 7TV");
|
||||
ASSERT_EQ(completion[3].displayName, "Clap2");
|
||||
ASSERT_EQ(completion[3].providerName, "Global 7TV");
|
||||
ASSERT_EQ(completion[4].displayName, "clapper");
|
||||
ASSERT_EQ(completion[4].providerName, "Emoji");
|
||||
ASSERT_EQ(completion[5].displayName, "clap_tone1");
|
||||
ASSERT_EQ(completion[5].providerName, "Emoji");
|
||||
}
|
||||
|
||||
TEST_F(InputCompletionTest, SmartEmoteCase)
|
||||
{
|
||||
auto completion = querySmartEmoteCompletion(":pajaw");
|
||||
ASSERT_EQ(completion.size(), 2);
|
||||
ASSERT_EQ(completion[0].displayName, "pajaW");
|
||||
ASSERT_EQ(completion[1].displayName, "PAJAW");
|
||||
|
||||
completion = querySmartEmoteCompletion(":PA");
|
||||
ASSERT_EQ(completion.size(), 1);
|
||||
ASSERT_EQ(completion[0].displayName, "PAJAW");
|
||||
|
||||
completion = querySmartEmoteCompletion(":Pajaw");
|
||||
ASSERT_EQ(completion.size(), 2);
|
||||
ASSERT_EQ(completion[0].displayName, "PAJAW");
|
||||
ASSERT_EQ(completion[1].displayName, "pajaW");
|
||||
|
||||
completion = querySmartEmoteCompletion(":NOTHING");
|
||||
ASSERT_EQ(completion.size(), 0);
|
||||
|
||||
completion = querySmartEmoteCompletion(":nothing");
|
||||
ASSERT_EQ(completion.size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(InputCompletionTest, SmartTabCompletionEmote)
|
||||
{
|
||||
auto completion = querySmartTabCompletion(":feels", false);
|
||||
ASSERT_EQ(completion.size(), 0); // : prefix matters here
|
||||
|
||||
// no : prefix defaults to emote completion
|
||||
completion = querySmartTabCompletion("feels", false);
|
||||
ASSERT_EQ(completion.size(), 3);
|
||||
ASSERT_EQ(completion[0], "FeelsBadMan ");
|
||||
ASSERT_EQ(completion[1], "FeelsGoodMan ");
|
||||
ASSERT_EQ(completion[2], "FeelsBirthdayMan ");
|
||||
|
||||
// no : prefix, emote completion. Duplicate Clap should be removed
|
||||
completion = querySmartTabCompletion("cla", false);
|
||||
ASSERT_EQ(completion.size(), 3);
|
||||
ASSERT_EQ(completion[0], "Clap ");
|
||||
ASSERT_EQ(completion[1], "Clap ");
|
||||
ASSERT_EQ(completion[2], "Clap2 ");
|
||||
|
||||
completion = querySmartTabCompletion("peepoHappy", false);
|
||||
ASSERT_EQ(completion.size(), 0);
|
||||
|
||||
completion = querySmartTabCompletion("Aware", false);
|
||||
ASSERT_EQ(completion.size(), 1);
|
||||
ASSERT_EQ(completion[0], "Aware ");
|
||||
}
|
||||
|
||||
TEST_F(InputCompletionTest, SmartTabCompletionEmoji)
|
||||
{
|
||||
auto completion = querySmartTabCompletion(":tf", false);
|
||||
ASSERT_EQ(completion.size(), 0);
|
||||
// ASSERT_EQ(completion[0], ":tf: ");
|
||||
|
||||
completion = querySmartTabCompletion(":)", false);
|
||||
ASSERT_EQ(completion.size(), 0);
|
||||
// ASSERT_EQ(completion[0], ":) ");
|
||||
|
||||
completion = querySmartTabCompletion(":cla", false);
|
||||
ASSERT_EQ(completion.size(), 8);
|
||||
ASSERT_EQ(completion[0], ":clap: ");
|
||||
ASSERT_EQ(completion[1], ":clapper: ");
|
||||
ASSERT_EQ(completion[2], ":clap_tone1: ");
|
||||
ASSERT_EQ(completion[3], ":clap_tone2: ");
|
||||
ASSERT_EQ(completion[4], ":clap_tone3: ");
|
||||
ASSERT_EQ(completion[5], ":clap_tone4: ");
|
||||
ASSERT_EQ(completion[6], ":clap_tone5: ");
|
||||
ASSERT_EQ(completion[7], ":classical_building: ");
|
||||
}
|
||||
|
||||
TEST_F(InputCompletionTest, SmartTabCompletionCase)
|
||||
{
|
||||
auto completion = querySmartTabCompletion("pajaw", false);
|
||||
ASSERT_EQ(completion.size(), 2);
|
||||
ASSERT_EQ(completion[0], "pajaW ");
|
||||
ASSERT_EQ(completion[1], "PAJAW ");
|
||||
|
||||
completion = querySmartTabCompletion("PA", false);
|
||||
ASSERT_EQ(completion.size(), 1);
|
||||
ASSERT_EQ(completion[0], "PAJAW ");
|
||||
|
||||
completion = querySmartTabCompletion("Pajaw", false);
|
||||
ASSERT_EQ(completion.size(), 2);
|
||||
ASSERT_EQ(completion[0], "PAJAW ");
|
||||
ASSERT_EQ(completion[1], "pajaW ");
|
||||
|
||||
completion = querySmartTabCompletion("NOTHING", false);
|
||||
ASSERT_EQ(completion.size(), 0);
|
||||
|
||||
completion = querySmartTabCompletion("nothing", false);
|
||||
ASSERT_EQ(completion.size(), 0);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue