Skip to content

Commit b203e21

Browse files
committed
remove lodash from routes, quote, result, user, apekeys
1 parent 3ac6e7a commit b203e21

File tree

8 files changed

+213
-113
lines changed

8 files changed

+213
-113
lines changed
Lines changed: 102 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,107 @@
1-
import { describe, it, expect } from "vitest";
1+
import { describe, it, expect, vi, beforeEach } from "vitest";
22
import { ObjectId } from "mongodb";
3-
import { addApeKey } from "../../../src/dal/ape-keys";
3+
import {
4+
addApeKey,
5+
DBApeKey,
6+
editApeKey,
7+
getApeKey,
8+
updateLastUsedOn,
9+
} from "../../../src/dal/ape-keys";
410

511
describe("ApeKeysDal", () => {
6-
it("should be able to add a new ape key", async () => {
7-
const apeKey = {
8-
_id: new ObjectId(),
9-
uid: "123",
10-
name: "test",
11-
hash: "12345",
12-
createdOn: Date.now(),
13-
modifiedOn: Date.now(),
14-
lastUsedOn: Date.now(),
15-
useCount: 0,
16-
enabled: true,
17-
};
18-
19-
const apeKeyId = await addApeKey(apeKey);
20-
21-
expect(apeKeyId).toBe(apeKey._id.toHexString());
12+
beforeEach(() => {
13+
vi.useFakeTimers();
14+
});
15+
16+
describe("addApeKey", () => {
17+
it("should be able to add a new ape key", async () => {
18+
const apeKey = buildApeKey();
19+
20+
const apeKeyId = await addApeKey(apeKey);
21+
22+
expect(apeKeyId).toBe(apeKey._id.toHexString());
23+
24+
const read = await getApeKey(apeKeyId);
25+
expect(read).toEqual({
26+
...apeKey,
27+
});
28+
});
29+
});
30+
31+
describe("editApeKey", () => {
32+
it("should edit name of an existing ape key", async () => {
33+
//GIVEN
34+
const apeKey = buildApeKey({ useCount: 5, enabled: true });
35+
const apeKeyId = await addApeKey(apeKey);
36+
37+
//WHEN
38+
const newName = "new name";
39+
await editApeKey(apeKey.uid, apeKeyId, newName, undefined);
40+
41+
//THENa
42+
const readAfterEdit = (await getApeKey(apeKeyId)) as DBApeKey;
43+
expect(readAfterEdit).toEqual({
44+
...apeKey,
45+
name: newName,
46+
modifiedOn: Date.now(),
47+
});
48+
});
49+
50+
it("should edit enabled of an existing ape key", async () => {
51+
//GIVEN
52+
const apeKey = buildApeKey({ useCount: 5, enabled: true });
53+
const apeKeyId = await addApeKey(apeKey);
54+
55+
//WHEN
56+
57+
await editApeKey(apeKey.uid, apeKeyId, undefined, false);
58+
59+
//THEN
60+
const readAfterEdit = (await getApeKey(apeKeyId)) as DBApeKey;
61+
expect(readAfterEdit).toEqual({
62+
...apeKey,
63+
enabled: false,
64+
modifiedOn: Date.now(),
65+
});
66+
});
67+
});
68+
69+
describe("updateLastUsedOn", () => {
70+
it("should update lastUsedOn and increment useCount when editing with lastUsedOn", async () => {
71+
//GIVEN
72+
const apeKey = buildApeKey({
73+
useCount: 5,
74+
lastUsedOn: 42,
75+
});
76+
const apeKeyId = await addApeKey(apeKey);
77+
78+
//WHEN
79+
await updateLastUsedOn(apeKey.uid, apeKeyId);
80+
await updateLastUsedOn(apeKey.uid, apeKeyId);
81+
82+
//THENa
83+
const readAfterEdit = (await getApeKey(apeKeyId)) as DBApeKey;
84+
expect(readAfterEdit).toEqual({
85+
...apeKey,
86+
modifiedOn: readAfterEdit.modifiedOn,
87+
lastUsedOn: Date.now(),
88+
useCount: 5 + 2,
89+
});
90+
});
2291
});
2392
});
93+
94+
function buildApeKey(overrides: Partial<DBApeKey> = {}): DBApeKey {
95+
return {
96+
_id: new ObjectId(),
97+
uid: "123",
98+
name: "test",
99+
hash: "12345",
100+
createdOn: Date.now(),
101+
modifiedOn: Date.now(),
102+
lastUsedOn: Date.now(),
103+
useCount: 0,
104+
enabled: true,
105+
...overrides,
106+
};
107+
}

backend/__tests__/api/controllers/result.spec.ts

Lines changed: 81 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { mockAuthenticateWithApeKey } from "../../__testData__/auth";
1010
import { enableRateLimitExpects } from "../../__testData__/rate-limit";
1111
import { DBResult } from "../../../src/utils/result";
1212
import { omit } from "../../../src/utils/misc";
13+
import { CompletedEvent } from "@monkeytype/schemas/results";
1314

1415
const { mockApp, uid, mockAuth } = setup();
1516
const configuration = Configuration.getCachedConfiguration();
@@ -588,6 +589,7 @@ describe("result controller test", () => {
588589

589590
beforeEach(async () => {
590591
await enableResultsSaving(true);
592+
await enableUsersXpGain(true);
591593

592594
[
593595
userGetMock,
@@ -611,48 +613,15 @@ describe("result controller test", () => {
611613
it("should add result", async () => {
612614
//GIVEN
613615

616+
const completedEvent = buildCompletedEvent({
617+
funbox: ["58008", "read_ahead_hard"],
618+
});
614619
//WHEN
615620
const { body } = await mockApp
616621
.post("/results")
617622
.set("Authorization", `Bearer ${uid}`)
618623
.send({
619-
result: {
620-
acc: 86,
621-
afkDuration: 5,
622-
bailedOut: false,
623-
blindMode: false,
624-
charStats: [100, 2, 3, 5],
625-
chartData: { wpm: [1, 2, 3], burst: [50, 55, 56], err: [0, 2, 0] },
626-
consistency: 23.5,
627-
difficulty: "normal",
628-
funbox: [],
629-
hash: "hash",
630-
incompleteTestSeconds: 2,
631-
incompleteTests: [{ acc: 75, seconds: 10 }],
632-
keyConsistency: 12,
633-
keyDuration: [0, 3, 5],
634-
keySpacing: [0, 2, 4],
635-
language: "english",
636-
lazyMode: false,
637-
mode: "time",
638-
mode2: "15",
639-
numbers: false,
640-
punctuation: false,
641-
rawWpm: 99,
642-
restartCount: 4,
643-
tags: ["tagOneId", "tagTwoId"],
644-
testDuration: 15.1,
645-
timestamp: 1000,
646-
uid,
647-
wpmConsistency: 55,
648-
wpm: 80,
649-
stopOnLetter: false,
650-
//new required
651-
charTotal: 5,
652-
keyOverlap: 7,
653-
lastKeyToEnd: 9,
654-
startToFirstKey: 11,
655-
},
624+
result: completedEvent,
656625
})
657626
.expect(200);
658627

@@ -662,7 +631,12 @@ describe("result controller test", () => {
662631
tagPbs: [],
663632
xp: 0,
664633
dailyXpBonus: false,
665-
xpBreakdown: {},
634+
xpBreakdown: {
635+
accPenalty: 28,
636+
base: 20,
637+
incomplete: 5,
638+
funbox: 80,
639+
},
666640
streak: 0,
667641
insertedId: insertedId.toHexString(),
668642
});
@@ -751,44 +725,9 @@ describe("result controller test", () => {
751725
.post("/results")
752726
.set("Authorization", `Bearer ${uid}`)
753727
.send({
754-
result: {
755-
acc: 86,
756-
afkDuration: 5,
757-
bailedOut: false,
758-
blindMode: false,
759-
charStats: [100, 2, 3, 5],
760-
chartData: { wpm: [1, 2, 3], burst: [50, 55, 56], err: [0, 2, 0] },
761-
consistency: 23.5,
762-
difficulty: "normal",
763-
funbox: [],
764-
hash: "hash",
765-
incompleteTestSeconds: 2,
766-
incompleteTests: [{ acc: 75, seconds: 10 }],
767-
keyConsistency: 12,
768-
keyDuration: [0, 3, 5],
769-
keySpacing: [0, 2, 4],
770-
language: "english",
771-
lazyMode: false,
772-
mode: "time",
773-
mode2: "15",
774-
numbers: false,
775-
punctuation: false,
776-
rawWpm: 99,
777-
restartCount: 4,
778-
tags: ["tagOneId", "tagTwoId"],
779-
testDuration: 15.1,
780-
timestamp: 1000,
781-
uid,
782-
wpmConsistency: 55,
783-
wpm: 80,
784-
stopOnLetter: false,
785-
//new required
786-
charTotal: 5,
787-
keyOverlap: 7,
788-
lastKeyToEnd: 9,
789-
startToFirstKey: 11,
728+
result: buildCompletedEvent({
790729
extra2: "value",
791-
},
730+
} as any),
792731
extra: "value",
793732
})
794733
.expect(422);
@@ -803,6 +742,24 @@ describe("result controller test", () => {
803742
});
804743
});
805744

745+
it("should fail wit duplicate funboxes", async () => {
746+
//GIVEN
747+
748+
//WHEN
749+
const { body } = await mockApp
750+
.post("/results")
751+
.set("Authorization", `Bearer ${uid}`)
752+
.send({
753+
result: buildCompletedEvent({
754+
funbox: ["58008", "58008"],
755+
}),
756+
})
757+
.expect(400);
758+
759+
//THEN
760+
expect(body.message).toEqual("Duplicate funboxes");
761+
});
762+
806763
// it("should fail invalid properties ", async () => {
807764
//GIVEN
808765
//WHEN
@@ -824,6 +781,47 @@ describe("result controller test", () => {
824781
});
825782
});
826783

784+
function buildCompletedEvent(result?: Partial<CompletedEvent>): CompletedEvent {
785+
return {
786+
acc: 86,
787+
afkDuration: 5,
788+
bailedOut: false,
789+
blindMode: false,
790+
charStats: [100, 2, 3, 5],
791+
chartData: { wpm: [1, 2, 3], burst: [50, 55, 56], err: [0, 2, 0] },
792+
consistency: 23.5,
793+
difficulty: "normal",
794+
funbox: [],
795+
hash: "hash",
796+
incompleteTestSeconds: 2,
797+
incompleteTests: [{ acc: 75, seconds: 10 }],
798+
keyConsistency: 12,
799+
keyDuration: [0, 3, 5],
800+
keySpacing: [0, 2, 4],
801+
language: "english",
802+
lazyMode: false,
803+
mode: "time",
804+
mode2: "15",
805+
numbers: false,
806+
punctuation: false,
807+
rawWpm: 99,
808+
restartCount: 4,
809+
tags: ["tagOneId", "tagTwoId"],
810+
testDuration: 15.1,
811+
timestamp: 1000,
812+
uid,
813+
wpmConsistency: 55,
814+
wpm: 80,
815+
stopOnLetter: false,
816+
//new required
817+
charTotal: 5,
818+
keyOverlap: 7,
819+
lastKeyToEnd: 9,
820+
startToFirstKey: 11,
821+
...result,
822+
};
823+
}
824+
827825
async function enablePremiumFeatures(enabled: boolean): Promise<void> {
828826
const mockConfig = await configuration;
829827
mockConfig.users.premium = { ...mockConfig.users.premium, enabled };
@@ -884,3 +882,11 @@ async function enableResultsSaving(enabled: boolean): Promise<void> {
884882
mockConfig
885883
);
886884
}
885+
async function enableUsersXpGain(enabled: boolean): Promise<void> {
886+
const mockConfig = await configuration;
887+
mockConfig.users.xp = { ...mockConfig.users.xp, enabled, funboxBonus: 1 };
888+
889+
vi.spyOn(Configuration, "getCachedConfiguration").mockResolvedValue(
890+
mockConfig
891+
);
892+
}

backend/__tests__/api/controllers/user.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3388,7 +3388,7 @@ describe("user controller test", () => {
33883388
await enableInbox(true);
33893389
});
33903390

3391-
it("shold get inbox", async () => {
3391+
it("should get inbox", async () => {
33923392
//GIVEN
33933393
const mailOne: MonkeyMail = {
33943394
id: randomUUID(),

backend/src/api/controllers/quote.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import _ from "lodash";
21
import { v4 as uuidv4 } from "uuid";
32
import { getPartialUser, updateQuoteRatings } from "../../dal/user";
43
import * as ReportDAL from "../../dal/report";
@@ -126,7 +125,10 @@ export async function submitRating(
126125
shouldUpdateRating
127126
);
128127

129-
_.setWith(userQuoteRatings, `[${language}][${quoteId}]`, rating, Object);
128+
if (!userQuoteRatings[language]) {
129+
userQuoteRatings[language] = {};
130+
}
131+
userQuoteRatings[language][quoteId] = rating;
130132

131133
await updateQuoteRatings(uid, userQuoteRatings);
132134

backend/src/api/controllers/result.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import { getDailyLeaderboard } from "../../utils/daily-leaderboards";
2727
import AutoRoleList from "../../constants/auto-roles";
2828
import * as UserDAL from "../../dal/user";
2929
import { buildMonkeyMail } from "../../utils/monkey-mail";
30-
import _ from "lodash";
3130
import * as WeeklyXpLeaderboard from "../../services/weekly-xp-leaderboard";
3231
import { UAParser } from "ua-parser-js";
3332
import { canFunboxGetPb } from "../../utils/pb";
@@ -244,7 +243,7 @@ export async function addResult(
244243
Logger.warning("Object hash check is disabled, skipping hash check");
245244
}
246245

247-
if (completedEvent.funbox.length !== _.uniq(completedEvent.funbox).length) {
246+
if (new Set(completedEvent.funbox).size !== completedEvent.funbox.length) {
248247
throw new MonkeyError(400, "Duplicate funboxes");
249248
}
250249

@@ -759,11 +758,12 @@ async function calculateXp(
759758
}
760759

761760
if (funboxBonusConfiguration > 0 && resultFunboxes.length !== 0) {
762-
const funboxModifier = _.sumBy(resultFunboxes, (funboxName) => {
761+
const funboxModifier = resultFunboxes.reduce((sum, funboxName) => {
763762
const funbox = getFunbox(funboxName);
764763
const difficultyLevel = funbox?.difficultyLevel ?? 0;
765-
return Math.max(difficultyLevel * funboxBonusConfiguration, 0);
766-
});
764+
return sum + Math.max(difficultyLevel * funboxBonusConfiguration, 0);
765+
}, 0);
766+
767767
if (funboxModifier > 0) {
768768
modifier += funboxModifier;
769769
breakdown.funbox = Math.round(baseXp * funboxModifier);

0 commit comments

Comments
 (0)