Skip to content

Commit

Permalink
test: add more input completion tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Nerixyz committed Sep 25, 2024
1 parent c4df31a commit 1fb4c08
Showing 1 changed file with 264 additions and 27 deletions.
291 changes: 264 additions & 27 deletions tests/src/InputCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -84,7 +85,30 @@ class MockApplication : public mock::BaseApplication
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)
{
Expand All @@ -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": {
Expand All @@ -117,6 +141,8 @@ static QString DEFAULT_SETTINGS = R"!(
}
})!";

} // namespace

class InputCompletionTest : public ::testing::Test
{
protected:
Expand Down Expand Up @@ -164,6 +190,7 @@ class InputCompletionTest : public ::testing::Test
addEmote(*bttvEmotes, ":-)");
addEmote(*bttvEmotes, "B-)");
addEmote(*bttvEmotes, "Clap");
addEmote(*bttvEmotes, ":tf:");
this->mockApplication->bttvEmotes.setEmotes(std::move(bttvEmotes));

auto ffzEmotes = std::make_shared<EmoteMap>();
Expand All @@ -175,50 +202,56 @@ class InputCompletionTest : public ::testing::Test
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;
}
};

void containsRoughly(std::span<EmoteItem> span, std::set<QString> values)
{
for (const auto &v : values)
auto queryClassicEmoteCompletion(const QString &fullQuery)
{
bool found = false;
for (const auto &actualValue : span)
{
if (actualValue.displayName == v)
{
found = true;
break;
}
}
return queryEmoteCompletion<ClassicEmoteStrategy>(fullQuery);
}

ASSERT_TRUE(found) << v << " was not found in the span";
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);
}
};

TEST_F(InputCompletionTest, ClassicEmoteNameFiltering)
{
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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: ");
Expand All @@ -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);
}

0 comments on commit 1fb4c08

Please sign in to comment.