Skip to content

Commit 93f8e06

Browse files
authored
Merge branch 'master' into azerbaijani-quotes
2 parents c5bc700 + a4b6671 commit 93f8e06

File tree

22 files changed

+478
-246
lines changed

22 files changed

+478
-246
lines changed

frontend/__tests__/setup-tests.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { vi } from "vitest";
22
import $ from "jquery";
3-
import { ElementWithUtils } from "../src/ts/utils/dom";
3+
import { ElementsWithUtils, ElementWithUtils } from "../src/ts/utils/dom";
44

55
//@ts-expect-error add to global
66
global["$"] = $;
@@ -20,7 +20,7 @@ vi.mock("../src/ts/firebase", () => ({
2020
isAuthenticated: () => false,
2121
}));
2222

23-
vi.mock("../src/ts/utils/dom", () => {
23+
vi.mock("../src/ts/utils/dom", async (importOriginal) => {
2424
const createMockElement = (): ElementWithUtils => {
2525
return {
2626
disable: vi.fn().mockReturnThis(),
@@ -45,9 +45,9 @@ vi.mock("../src/ts/utils/dom", () => {
4545
setStyle: vi.fn().mockReturnThis(),
4646
getStyle: vi.fn().mockReturnValue({}),
4747
isFocused: vi.fn().mockReturnValue(false),
48-
qs: vi.fn().mockReturnValue(null),
48+
qs: vi.fn().mockImplementation(() => createMockElement()),
4949
qsr: vi.fn().mockImplementation(() => createMockElement()),
50-
qsa: vi.fn().mockReturnValue([]),
50+
qsa: vi.fn().mockImplementation(() => new ElementsWithUtils()),
5151
empty: vi.fn().mockReturnThis(),
5252
appendHtml: vi.fn().mockReturnThis(),
5353
append: vi.fn().mockReturnThis(),
@@ -71,10 +71,14 @@ vi.mock("../src/ts/utils/dom", () => {
7171
};
7272
};
7373

74+
const actual = await importOriginal();
75+
7476
return {
77+
//@ts-expect-error - mocking private method
78+
...actual,
7579
qsr: vi.fn().mockImplementation(() => createMockElement()),
7680
qs: vi.fn().mockImplementation(() => createMockElement()),
77-
qsa: vi.fn().mockReturnValue([]),
81+
qsa: vi.fn().mockImplementation(() => new ElementsWithUtils()),
7882
};
7983
});
8084

frontend/src/email-handler.html

Lines changed: 48 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@
167167
</div>
168168
</body>
169169
<script type="module">
170-
import $ from "jquery";
171170
import {
172171
applyActionCode,
173172
verifyPasswordResetCode,
@@ -179,6 +178,7 @@
179178
} from "firebase/auth";
180179
import { initializeApp } from "firebase/app";
181180
import { firebaseConfig } from "./ts/constants/firebase-config";
181+
import { qs, onDOMReady } from "./ts/utils/dom";
182182

183183
const app = initializeApp(firebaseConfig);
184184
const Auth = getAuth(app);
@@ -199,16 +199,16 @@
199199
.then((resp) => {
200200
// Email address has been verified.
201201

202-
$("main .preloader .icon").html(`<i class="fas fa-fw fa-check"></i>`);
203-
$("main .preloader .text").text(
202+
qs("main .preloader .icon")?.setHtml(`<i class="fas fa-fw fa-check"></i>`);
203+
qs("main .preloader .text")?.setText(
204204
`Your email address has been verified`,
205205
);
206-
$("main .preloader .subText").text(`You can now close this tab`);
206+
qs("main .preloader .subText")?.setText(`You can now close this tab`);
207207
})
208208
.catch((error) => {
209209
console.error(error);
210-
$("main .preloader .icon").html(`<i class="fas fa-fw fa-times"></i>`);
211-
$("main .preloader .text").text(
210+
qs("main .preloader .icon")?.setHtml(`<i class="fas fa-fw fa-times"></i>`);
211+
qs("main .preloader .text")?.setText(
212212
`Fatal error: ${error.message}. If this issue persists, please report it.`,
213213
);
214214
// Code is invalid or expired. Ask the user to verify their email address
@@ -217,14 +217,14 @@
217217
}
218218

219219
function showResetPassword() {
220-
$("main .preloader").addClass("hidden");
221-
$("main .resetPassword").removeClass("hidden");
222-
$("main .resetPassword input").trigger("focus");
220+
qs("main .preloader")?.hide();
221+
qs("main .resetPassword")?.show();
222+
qs("main .resetPassword input")?.focus();
223223
}
224224

225225
function hideResetPassword() {
226-
$("main .preloader").removeClass("hidden");
227-
$("main .resetPassword").addClass("hidden");
226+
qs("main .preloader")?.show();
227+
qs("main .resetPassword")?.hide();
228228
}
229229

230230
function handleResetPassword(actionCode, continueUrl) {
@@ -234,8 +234,8 @@
234234
.then((email) => {
235235
var accountEmail = email;
236236

237-
var newPassword = $("main .resetPassword .pwd").val();
238-
var newPasswordConfirm = $("main .resetPassword .pwd-confirm").val();
237+
var newPassword = qs<HTMLInputElement>("main .resetPassword .pwd")?.getValue();
238+
var newPasswordConfirm = qs<HTMLInputElement>("main .resetPassword .pwd-confirm")?.getValue();
239239

240240
if (newPassword !== newPasswordConfirm) {
241241
alert("Passwords do not match");
@@ -255,20 +255,20 @@
255255
confirmPasswordReset(Auth, actionCode, newPassword)
256256
.then((resp) => {
257257
// Password reset has been confirmed and new password updated.
258-
$("main .preloader .icon").html(
258+
qs("main .preloader .icon")?.setHtml(
259259
`<i class="fas fa-fw fa-check"></i>`,
260260
);
261-
$("main .preloader .text").text(`Your password has been changed`);
262-
$("main .preloader .subText").text(`You can now close this tab`);
261+
qs("main .preloader .text")?.setText(`Your password has been changed`);
262+
qs("main .preloader .subText")?.setText(`You can now close this tab`);
263263

264264
signInWithEmailAndPassword(Auth, accountEmail, newPassword);
265265
})
266266
.catch((error) => {
267267
console.error(error);
268-
$("main .preloader .icon").html(
268+
qs("main .preloader .icon")?.setHtml(
269269
`<i class="fas fa-fw fa-times"></i>`,
270270
);
271-
$("main .preloader .text").text(
271+
qs("main .preloader .text")?.setText(
272272
`Fatal error: ${error.message}. If this issue persists, please report it.`,
273273
);
274274
// Error occurred during confirmation. The code might have expired or the
@@ -277,12 +277,12 @@
277277
})
278278
.catch((error) => {
279279
console.error(error);
280-
$("main .preloader .icon").html(`<i class="fas fa-fw fa-times"></i>`);
281-
$("main .preloader .text").text(
280+
qs("main .preloader .icon")?.setHtml(`<i class="fas fa-fw fa-times"></i>`);
281+
qs("main .preloader .text")?.setText(
282282
`Fatal error: ${error.message}. If this issue persists, please report it.`,
283283
);
284284

285-
// $("main .preloader .subText").text(error);
285+
// qs("main .preloader .subText")?.setText(error);
286286

287287
// Invalid or expired action code. Ask user to try to reset the password
288288
// again.
@@ -303,15 +303,15 @@
303303
return applyActionCode(Auth, actionCode);
304304
})
305305
.then(() => {
306-
$("main .preloader .icon").html(`<i class="fas fa-fw fa-check"></i>`);
307-
$("main .preloader .text").text(`Your account email was reverted.`);
308-
$("main .preloader .subText").text(``);
306+
qs("main .preloader .icon")?.setHtml(`<i class="fas fa-fw fa-check"></i>`);
307+
qs("main .preloader .text")?.setText(`Your account email was reverted.`);
308+
qs("main .preloader .subText")?.setText(``);
309309

310-
$("main .preloader").append(`
310+
qs("main .preloader")?.appendHtml(`
311311
<br>
312312
In case you believe your account was compromised, please request a password reset email:
313313
`);
314-
$("main .preloader").append(`
314+
qs("main .preloader")?.appendHtml(`
315315
<br>
316316
<div class="button" onclick="sendPasswordReset('${restoredEmail}')">Send Password Reset Email</div>
317317
`);
@@ -325,22 +325,22 @@
325325
})
326326
.catch((error) => {
327327
console.error(error);
328-
$("main .preloader .icon").html(`<i class="fas fa-fw fa-times"></i>`);
329-
$("main .preloader .text").text(error.message);
328+
qs("main .preloader .icon")?.setHtml(`<i class="fas fa-fw fa-times"></i>`);
329+
qs("main .preloader .text")?.setText(error.message);
330330
});
331331
}
332332

333333
function sendPasswordReset(email) {
334334
sendPasswordResetEmail(Auth, email)
335335
.then(() => {
336-
$("main .preloader .icon").html(`<i class="fas fa-fw fa-check"></i>`);
337-
$("main .preloader .text").text(`Password reset email sent`);
338-
$("main .preloader .subText").text(`Please check your inbox`);
336+
qs("main .preloader .icon")?.setHtml(`<i class="fas fa-fw fa-check"></i>`);
337+
qs("main .preloader .text")?.setText(`Password reset email sent`);
338+
qs("main .preloader .subText")?.setText(`Please check your inbox`);
339339
})
340340
.catch((error) => {
341341
console.error(error);
342-
$("main .preloader .icon").html(`<i class="fas fa-fw fa-times"></i>`);
343-
$("main .preloader .text").text(error.message);
342+
qs("main .preloader .icon")?.setHtml(`<i class="fas fa-fw fa-times"></i>`);
343+
qs("main .preloader .text")?.setText(error.message);
344344
});
345345
}
346346

@@ -353,9 +353,7 @@
353353
return decodeURIComponent(results[2].replace(/\+/g, " "));
354354
}
355355

356-
document.addEventListener(
357-
"DOMContentLoaded",
358-
() => {
356+
onDOMReady(() => {
359357
try {
360358
// Get the action to complete.
361359
var mode = getParameterByName("mode");
@@ -376,26 +374,26 @@
376374
// var auth = firebase.auth();
377375

378376
if (!mode) {
379-
$("main .preloader .icon").html(
377+
qs("main .preloader .icon")?.setHtml(
380378
`<i class="fas fa-fw fa-times"></i>`,
381379
);
382-
$("main .preloader .text").text(`Mode parameter not found`);
380+
qs("main .preloader .text")?.setText(`Mode parameter not found`);
383381
return;
384382
}
385383

386384
if (!actionCode) {
387-
$("main .preloader .icon").html(
385+
qs("main .preloader .icon")?.setHtml(
388386
`<i class="fas fa-fw fa-times"></i>`,
389387
);
390-
$("main .preloader .text").text(`Action code parameter not found`);
388+
qs("main .preloader .text")?.setText(`Action code parameter not found`);
391389
return;
392390
}
393391

394392
// Handle the user management action.
395393
switch (mode) {
396394
case "resetPassword":
397395
// Display reset password handler and UI.
398-
$("#logo .text span").text("Reset Password");
396+
qs("#logo .text span")?.setText("Reset Password");
399397
document.title = "Reset Password | Monkeytype";
400398
showResetPassword();
401399
break;
@@ -404,38 +402,36 @@
404402
handleRecoverEmail(actionCode);
405403
break;
406404
case "verifyEmail":
407-
$("#logo .text span").text("Verify Email");
405+
qs("#logo .text span")?.setText("Verify Email");
408406
document.title = "Verify Email | Monkeytype";
409407
// Display email verification handler and UI.
410408
handleVerifyEmail(actionCode, continueUrl);
411409
break;
412410
default:
413-
$("main .preloader .icon").html(
411+
qs("main .preloader .icon")?.setHtml(
414412
`<i class="fas fa-fw fa-times"></i>`,
415413
);
416-
$("main .preloader .text").text(`Invalid mode`);
414+
qs("main .preloader .text")?.setText(`Invalid mode`);
417415
console.error("no mode found");
418416
// Error: invalid mode.
419417
}
420418

421-
$("main .resetPassword .button").on("click", () => {
419+
qs("main .resetPassword .button")?.on("click", () => {
422420
handleResetPassword(actionCode, continueUrl);
423421
});
424422

425-
$("main .resetPassword input").on("keypress", (e) => {
423+
qs("main .resetPassword input")?.on("keypress", (e) => {
426424
if (e.key === "Enter") handleResetPassword(actionCode, continueUrl);
427425
});
428426
} catch (e) {
429-
$("main .preloader .icon").html(`<i class="fas fa-fw fa-times"></i>`);
430-
$("main .preloader .text").text(
427+
qs("main .preloader .icon")?.setHtml(`<i class="fas fa-fw fa-times"></i>`);
428+
qs("main .preloader .text")?.setText(
431429
`Fatal error: ${e.message}. If this issue persists, please report it.`,
432430
);
433431
}
434-
},
435-
false,
436-
);
432+
});
437433

438-
document.querySelector("header").addEventListener("click", () => {
434+
qs("header")?.on("click", () => {
439435
window.location = "/";
440436
});
441437
</script>
Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import * as SupportPopup from "../modals/support";
22
import * as ContactModal from "../modals/contact";
3+
import { qs } from "../utils/dom";
34

4-
document
5-
.querySelector("#pageAbout #supportMeAboutButton")
6-
?.addEventListener("click", () => {
7-
SupportPopup.show();
8-
});
5+
qs("#pageAbout #supportMeAboutButton")?.on("click", () => {
6+
SupportPopup.show();
7+
});
98

10-
document
11-
.querySelector("#pageAbout #contactPopupButton2")
12-
?.addEventListener("click", () => {
13-
ContactModal.show();
14-
});
9+
qs("#pageAbout #contactPopupButton2")?.on("click", () => {
10+
ContactModal.show();
11+
});

frontend/src/ts/event-handlers/account.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,19 @@ import * as EditResultTagsModal from "../modals/edit-result-tags";
77
import * as AddFilterPresetModal from "../modals/new-filter-preset";
88
import { parseWithSchema as parseJsonWithSchema } from "@monkeytype/util/json";
99
import { z } from "zod";
10+
import { qs } from "../utils/dom";
1011

11-
const accountPage = document.querySelector("#pageAccount") as HTMLElement;
12+
const accountPage = qs("#pageAccount");
1213

13-
$(accountPage).on("click", ".pbsTime .showAllButton", () => {
14+
accountPage?.onChild("click", ".pbsTime .showAllButton", () => {
1415
PbTablesModal.show("time");
1516
});
1617

17-
$(accountPage).on("click", ".pbsWords .showAllButton", () => {
18+
accountPage?.onChild("click", ".pbsWords .showAllButton", () => {
1819
PbTablesModal.show("words");
1920
});
2021

21-
$(accountPage).on("click", ".editProfileButton", () => {
22+
accountPage?.onChild("click", ".editProfileButton", () => {
2223
if (!isAuthenticated()) {
2324
Notifications.add("You must be logged in to edit your profile", 0);
2425
return;
@@ -40,9 +41,10 @@ $(accountPage).on("click", ".editProfileButton", () => {
4041

4142
const TagsArraySchema = z.array(z.string());
4243

43-
$(accountPage).on("click", ".group.history .resultEditTagsButton", (e) => {
44-
const resultid = $(e.target).attr("data-result-id");
45-
const tags = $(e.target).attr("data-tags");
44+
accountPage?.onChild("click", ".group.history .resultEditTagsButton", (e) => {
45+
const targetButton = e.childTarget as HTMLElement;
46+
const resultid = targetButton?.getAttribute("data-result-id");
47+
const tags = targetButton?.getAttribute("data-tags");
4648

4749
EditResultTagsModal.show(
4850
resultid ?? "",
@@ -51,8 +53,6 @@ $(accountPage).on("click", ".group.history .resultEditTagsButton", (e) => {
5153
);
5254
});
5355

54-
$(accountPage)
55-
.find("button.createFilterPresetBtn")
56-
.on("click", () => {
57-
AddFilterPresetModal.show();
58-
});
56+
accountPage?.qs("button.createFilterPresetBtn")?.on("click", () => {
57+
AddFilterPresetModal.show();
58+
});

0 commit comments

Comments
 (0)