adding monkeytype
Some checks failed
Mark Stale PRs / stale (push) Has been cancelled

This commit is contained in:
Benjamin Falch
2026-04-23 13:53:44 +02:00
parent e214a2fd35
commit 2bc741fb78
1930 changed files with 7590652 additions and 0 deletions

View File

@@ -0,0 +1,404 @@
import { describe, it, expect, beforeAll, afterEach } from "vitest";
import { Mode, Mode2 } from "@monkeytype/schemas/shared";
import * as DailyLeaderboards from "../../../src/utils/daily-leaderboards";
import { cleanupKeys, redisSetup } from "../redis";
import { Language } from "@monkeytype/schemas/languages";
import { RedisDailyLeaderboardEntry } from "@monkeytype/schemas/leaderboards";
import { ObjectId } from "mongodb";
import { Configuration } from "@monkeytype/schemas/configuration";
const dailyLeaderboardsConfig: Configuration["dailyLeaderboards"] = {
enabled: true,
maxResults: 10,
leaderboardExpirationTimeInDays: 1,
validModeRules: [
{
language: "(english|spanish)",
mode: "time",
mode2: "(15|60)",
},
{
language: "french",
mode: "words",
mode2: "\\d+",
},
],
topResultsToAnnounce: 3,
xpRewardBrackets: [],
scheduleRewardsModeRules: [],
};
describe("Daily Leaderboards", () => {
beforeAll(async () => {
await redisSetup();
});
afterEach(async () => {
await cleanupKeys(DailyLeaderboards.__testing.namespace);
});
describe("should properly handle valid and invalid modes", () => {
const testCases: {
language: Language;
mode: Mode;
mode2: Mode2<any>;
expected: boolean;
}[] = [
{
language: "english",
mode: "time",
mode2: "60",
expected: true,
},
{
language: "spanish",
mode: "time",
mode2: "15",
expected: true,
},
{
language: "english",
mode: "time",
mode2: "600",
expected: false,
},
{
language: "spanish",
mode: "words",
mode2: "150",
expected: false,
},
{
language: "french",
mode: "time",
mode2: "600",
expected: false,
},
{
language: "french",
mode: "words",
mode2: "100",
expected: true,
},
];
it.for(testCases)(
`language=$language, mode=$mode mode2=$mode2 expect $expected`,
({ language, mode, mode2, expected }) => {
const result = DailyLeaderboards.getDailyLeaderboard(
language,
mode,
mode2 as any,
dailyLeaderboardsConfig,
);
expect(!!result).toBe(expected);
},
);
});
describe("DailyLeaderboard class", () => {
// oxlint-disable-next-line no-non-null-assertion
const lb = DailyLeaderboards.getDailyLeaderboard(
"english",
"time",
"60",
dailyLeaderboardsConfig,
)!;
describe("addResult", () => {
it("adds best result for user", async () => {
//GIVEN
const uid = new ObjectId().toHexString();
await givenResult({ uid, wpm: 50 });
const bestResult = await givenResult({ uid, wpm: 55 });
await givenResult({ uid, wpm: 53 });
const user2 = await givenResult({ wpm: 20 });
//WHEN
const results = await lb.getResults(
0,
5,
dailyLeaderboardsConfig,
true,
);
//THEN
expect(results).toEqual({
count: 2,
minWpm: 20,
entries: [
{ rank: 1, ...bestResult },
{ rank: 2, ...user2 },
],
});
});
it("limits max amount of results", async () => {
//GIVEN
const maxResults = dailyLeaderboardsConfig.maxResults;
const bob = await givenResult({ wpm: 10 });
await Promise.all(
new Array(maxResults - 1)
.fill(0)
.map(() => givenResult({ wpm: 20 + Math.random() * 100 })),
);
expect(
await lb.getResults(0, 5, dailyLeaderboardsConfig, true),
).toEqual(expect.objectContaining({ count: maxResults }));
expect(await lb.getRank(bob.uid, dailyLeaderboardsConfig)).toEqual({
rank: maxResults,
...bob,
});
//WHEN
await givenResult({ wpm: 11 });
//THEN
//max count is still the same, but bob is no longer on the leaderboard
expect(
await lb.getResults(0, 5, dailyLeaderboardsConfig, true),
).toEqual(expect.objectContaining({ count: maxResults }));
expect(await lb.getRank(bob.uid, dailyLeaderboardsConfig)).toBeNull();
});
});
describe("getResults", () => {
it("gets result", async () => {
//GIVEN
const user1 = await givenResult({ wpm: 50, isPremium: true });
const user2 = await givenResult({ wpm: 60 });
const user3 = await givenResult({ wpm: 40 });
//WHEN
const results = await lb.getResults(
0,
5,
dailyLeaderboardsConfig,
true,
);
//THEN
expect(results).toEqual({
count: 3,
minWpm: 40,
entries: [
{ rank: 1, ...user2 },
{ rank: 2, ...user1 },
{ rank: 3, ...user3 },
],
});
});
it("gets result for page", async () => {
//GIVEN
const user4 = await givenResult({ wpm: 45 });
const _user5 = await givenResult({ wpm: 20 });
const _user1 = await givenResult({ wpm: 50 });
const _user2 = await givenResult({ wpm: 60 });
const user3 = await givenResult({ wpm: 40 });
//WHEN
const results = await lb.getResults(
1,
2,
dailyLeaderboardsConfig,
true,
);
//THEN
expect(results).toEqual({
count: 5,
minWpm: 20,
entries: [
{ rank: 3, ...user4 },
{ rank: 4, ...user3 },
],
});
});
it("gets result without premium", async () => {
//GIVEN
const user1 = await givenResult({ wpm: 50, isPremium: true });
const user2 = await givenResult({ wpm: 60 });
const user3 = await givenResult({ wpm: 40, isPremium: true });
//WHEN
const results = await lb.getResults(
0,
5,
dailyLeaderboardsConfig,
false,
);
//THEN
expect(results).toEqual({
count: 3,
minWpm: 40,
entries: [
{ rank: 1, ...user2, isPremium: undefined },
{ rank: 2, ...user1, isPremium: undefined },
{ rank: 3, ...user3, isPremium: undefined },
],
});
});
it("should get for friends only", async () => {
//GIVEN
const _user1 = await givenResult({ wpm: 90 });
const user2 = await givenResult({ wpm: 80 });
const _user3 = await givenResult({ wpm: 70 });
const user4 = await givenResult({ wpm: 60 });
const _user5 = await givenResult({ wpm: 50 });
//WHEN
const results = await lb.getResults(
0,
5,
dailyLeaderboardsConfig,
true,
[user2.uid, user4.uid, new ObjectId().toHexString()],
);
//THEN
expect(results).toEqual({
count: 2,
minWpm: 60,
entries: [
{ rank: 2, friendsRank: 1, ...user2 },
{ rank: 4, friendsRank: 2, ...user4 },
],
});
});
it("should get for friends only with page", async () => {
//GIVEN
const user1 = await givenResult({ wpm: 105 });
const user2 = await givenResult({ wpm: 100 });
const _user3 = await givenResult({ wpm: 95 });
const user4 = await givenResult({ wpm: 90 });
const _user5 = await givenResult({ wpm: 70 });
//WHEN
const results = await lb.getResults(
1,
2,
dailyLeaderboardsConfig,
true,
[user1.uid, user2.uid, user4.uid, new ObjectId().toHexString()],
);
//THEN
expect(results).toEqual({
count: 3,
minWpm: 90,
entries: [{ rank: 4, friendsRank: 3, ...user4 }],
});
});
it("should return empty list if no friends", async () => {
//GIVEN
//WHEN
const results = await lb.getResults(
0,
5,
dailyLeaderboardsConfig,
true,
[],
);
//THEN
expect(results).toEqual({
count: 0,
minWpm: 0,
entries: [],
});
});
});
describe("getRank", () => {
it("gets rank", async () => {
//GIVEN
const user1 = await givenResult({ wpm: 50 });
const user2 = await givenResult({ wpm: 60 });
//WHEN / THEN
expect(await lb.getRank(user1.uid, dailyLeaderboardsConfig)).toEqual({
rank: 2,
...user1,
});
expect(await lb.getRank(user2.uid, dailyLeaderboardsConfig)).toEqual({
rank: 1,
...user2,
});
});
it("should return null for unknown user", async () => {
expect(await lb.getRank("decoy", dailyLeaderboardsConfig)).toBeNull();
expect(
await lb.getRank("decoy", dailyLeaderboardsConfig, [
"unknown",
"unknown2",
]),
).toBeNull();
});
it("gets rank for friends", async () => {
//GIVEN
const user1 = await givenResult({ wpm: 50 });
const user2 = await givenResult({ wpm: 60 });
const _user3 = await givenResult({ wpm: 70 });
const friends = [user1.uid, user2.uid, "decoy"];
//WHEN / THEN
expect(
await lb.getRank(user2.uid, dailyLeaderboardsConfig, friends),
).toEqual({ rank: 2, friendsRank: 1, ...user2 });
expect(
await lb.getRank(user1.uid, dailyLeaderboardsConfig, friends),
).toEqual({ rank: 3, friendsRank: 2, ...user1 });
});
});
it("purgeUserFromDailyLeaderboards", async () => {
//GIVEN
const cheater = await givenResult({ wpm: 50 });
const user1 = await givenResult({ wpm: 60 });
const user2 = await givenResult({ wpm: 40 });
//WHEN
await DailyLeaderboards.purgeUserFromDailyLeaderboards(
cheater.uid,
dailyLeaderboardsConfig,
);
//THEN
expect(await lb.getRank(cheater.uid, dailyLeaderboardsConfig)).toBeNull();
expect(await lb.getResults(0, 50, dailyLeaderboardsConfig, true)).toEqual(
{
count: 2,
minWpm: 40,
entries: [
{ rank: 1, ...user1 },
{ rank: 2, ...user2 },
],
},
);
});
async function givenResult(
entry?: Partial<RedisDailyLeaderboardEntry>,
): Promise<RedisDailyLeaderboardEntry> {
const uid = new ObjectId().toHexString();
const result = {
acc: 85,
name: `User ${uid}`,
raw: 100,
wpm: 95,
timestamp: Date.now(),
uid: uid,
badgeId: 2,
consistency: 90,
discordAvatar: `${uid}Avatar`,
discordId: `${uid}DiscordId`,
isPremium: false,
...entry,
};
await lb.addResult(result, dailyLeaderboardsConfig);
return result;
}
});
});