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,173 @@
import { describe, it, expect, beforeEach, vi } from "vitest";
import * as PresetController from "../../src/ts/controllers/preset-controller";
import { Preset } from "@monkeytype/schemas/presets";
import * as DB from "../../src/ts/db";
import { setConfig } from "../../src/ts/config/setters";
import { Config } from "../../src/ts/config/store";
import * as Lifecycle from "../../src/ts/config/lifecycle";
import * as ConfigUtils from "../../src/ts/config/utils";
import * as Persistence from "../../src/ts/config/persistence";
import * as Notifications from "../../src/ts/states/notifications";
import * as TestLogic from "../../src/ts/test/test-logic";
import * as TagController from "../../src/ts/controllers/tag-controller";
describe("PresetController", () => {
describe("apply", () => {
vi.mock("../../src/ts/test/test-logic", () => ({
restart: vi.fn(),
}));
vi.mock("../../src/ts/test/pace-caret", () => ({
//
}));
const dbGetSnapshotMock = vi.spyOn(DB, "getSnapshot");
const configApplyMock = vi.spyOn(Lifecycle, "applyConfig");
const configSaveFullConfigMock = vi.spyOn(
Persistence,
"saveFullConfigToLocalStorage",
);
const configGetConfigChangesMock = vi.spyOn(
ConfigUtils,
"getConfigChanges",
);
const notificationAddMock = vi.spyOn(
Notifications,
"showSuccessNotification",
);
const testRestartMock = vi.spyOn(TestLogic, "restart");
const tagControllerClearMock = vi.spyOn(TagController, "clear");
const tagControllerSetMock = vi.spyOn(TagController, "set");
const tagControllerSaveActiveMock = vi.spyOn(
TagController,
"saveActiveToLocalStorage",
);
beforeEach(() => {
[
dbGetSnapshotMock,
configApplyMock,
configSaveFullConfigMock,
configGetConfigChangesMock,
notificationAddMock,
testRestartMock,
tagControllerClearMock,
tagControllerSetMock,
tagControllerSaveActiveMock,
].forEach((it) => it.mockClear());
configApplyMock.mockResolvedValue();
});
it("should apply for full preset", async () => {
//GIVEN
const preset = givenPreset({ config: { punctuation: true } });
//WHEN
await PresetController.apply(preset._id);
//THEN
expect(configApplyMock).toHaveBeenCalledWith(preset.config);
expect(tagControllerClearMock).toHaveBeenCalled();
expect(testRestartMock).toHaveBeenCalled();
expect(notificationAddMock).toHaveBeenCalledWith("Preset applied", {
durationMs: 2000,
});
expect(configSaveFullConfigMock).toHaveBeenCalled();
});
it("should apply for full preset with tags", async () => {
//GIVEN
const preset = givenPreset({
config: { tags: ["tagOne", "tagTwo"] },
});
//WHEN
await PresetController.apply(preset._id);
//THEN
expect(tagControllerClearMock).toHaveBeenCalled();
expect(tagControllerSetMock).toHaveBeenNthCalledWith(
1,
"tagOne",
true,
false,
);
expect(tagControllerSetMock).toHaveBeenNthCalledWith(
2,
"tagTwo",
true,
false,
);
expect(tagControllerSaveActiveMock).toHaveBeenCalled();
});
it("should ignore unknown preset", async () => {
//WHEN
await PresetController.apply("unknown");
//THEN
expect(notificationAddMock).not.toHaveBeenCalled();
expect(configApplyMock).not.toHaveBeenCalled();
});
it("should apply for partial preset", async () => {
//GIVEN
const preset = givenPreset({
config: { punctuation: true },
settingGroups: ["test"],
});
setConfig("numbers", true);
const oldConfig = structuredClone(Config);
//WHEN
await PresetController.apply(preset._id);
//THEN
expect(configApplyMock).toHaveBeenCalledWith({
...oldConfig,
numbers: true,
punctuation: true,
});
expect(testRestartMock).toHaveBeenCalled();
expect(notificationAddMock).toHaveBeenCalledWith("Preset applied", {
durationMs: 2000,
});
expect(configSaveFullConfigMock).toHaveBeenCalled();
});
it("should apply for partial preset with tags", async () => {
//GIVEN
const preset = givenPreset({
config: { tags: ["tagOne", "tagTwo"] },
settingGroups: ["test", "behavior"],
});
//WHEN
await PresetController.apply(preset._id);
//THEN
expect(tagControllerClearMock).toHaveBeenCalled();
expect(tagControllerSetMock).toHaveBeenNthCalledWith(
1,
"tagOne",
true,
false,
);
expect(tagControllerSetMock).toHaveBeenNthCalledWith(
2,
"tagTwo",
true,
false,
);
expect(tagControllerSaveActiveMock).toHaveBeenCalled();
});
const givenPreset = (partialPreset: Partial<Preset>): Preset => {
const preset: Preset = {
_id: "1",
...partialPreset,
} as any;
dbGetSnapshotMock.mockReturnValue({ presets: [preset] } as any);
return preset;
};
});
});

View File

@@ -0,0 +1,299 @@
import { describe, it, expect, beforeEach, vi } from "vitest";
import { Difficulty, Mode, Mode2 } from "@monkeytype/schemas/shared";
import { compressToURI } from "lz-ts";
import * as UpdateConfig from "../../src/ts/config/setters";
import * as Notifications from "../../src/ts/states/notifications";
import * as TestLogic from "../../src/ts/test/test-logic";
import * as TestState from "../../src/ts/test/test-state";
import * as Misc from "../../src/ts/utils/misc";
import { FunboxName } from "@monkeytype/schemas/configs";
import { CustomTextSettings } from "@monkeytype/schemas/results";
import { loadTestSettingsFromUrl } from "../../src/ts/controllers/url-handler";
//mock modules to avoid dependencies
vi.mock("../../src/ts/test/test-logic", () => ({
restart: vi.fn(),
}));
describe("url-handler", () => {
describe("loadTestSettingsFromUrl", () => {
const findGetParameterMock = vi.spyOn(Misc, "findGetParameter");
const setConfigMock = vi.spyOn(UpdateConfig, "setConfig");
const setSelectedQuoteIdMock = vi.spyOn(TestState, "setSelectedQuoteId");
const restartTestMock = vi.spyOn(TestLogic, "restart");
const notifySuccessMock = vi.spyOn(
Notifications,
"showSuccessNotification",
);
const notifyMock = vi.spyOn(Notifications, "showNoticeNotification");
beforeEach(() => {
[
setConfigMock,
findGetParameterMock,
setSelectedQuoteIdMock,
restartTestMock,
notifySuccessMock,
notifyMock,
].forEach((it) => it.mockClear());
findGetParameterMock.mockImplementation((override) => override);
});
it("handles null", () => {
//GIVEN
findGetParameterMock.mockReturnValue("null");
//WHEN
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).not.toHaveBeenCalled();
});
it("handles mode2 as number", () => {
//GIVEN
findGetParameterMock.mockReturnValue(
urlData({ mode: "time", mode2: 60 }),
);
//WHEN
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("mode", "time", {
nosave: true,
});
expect(setConfigMock).toHaveBeenCalledWith("time", 60, {
nosave: true,
});
expect(restartTestMock).toHaveBeenCalled();
});
it("sets time", () => {
//GIVEN
findGetParameterMock.mockReturnValue(
urlData({ mode: "time", mode2: "30" }),
);
//WHEN
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("mode", "time", {
nosave: true,
});
expect(setConfigMock).toHaveBeenCalledWith("time", 30, {
nosave: true,
});
expect(restartTestMock).toHaveBeenCalled();
});
it("sets word count", () => {
//GIVEN
findGetParameterMock.mockReturnValue(
urlData({ mode: "words", mode2: "50" }),
);
//WHEN
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("mode", "words", {
nosave: true,
});
expect(setConfigMock).toHaveBeenCalledWith("words", 50, {
nosave: true,
});
expect(restartTestMock).toHaveBeenCalled();
});
it("sets quote length", () => {
//GIVEN
findGetParameterMock.mockReturnValue(
urlData({ mode: "quote", mode2: "512" }),
);
//WHEN
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("mode", "quote", {
nosave: true,
});
expect(setConfigMock).toHaveBeenCalledWith("quoteLength", [-2]);
expect(setSelectedQuoteIdMock).toHaveBeenCalledWith(512);
expect(restartTestMock).toHaveBeenCalled();
});
it("sets punctuation", () => {
//GIVEN
findGetParameterMock.mockReturnValue(urlData({ punctuation: true }));
//WHEN
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("punctuation", true, {
nosave: true,
});
expect(restartTestMock).toHaveBeenCalled();
});
it("sets numbers", () => {
//GIVEN
findGetParameterMock.mockReturnValue(urlData({ numbers: false }));
//WHEN
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("numbers", false, {
nosave: true,
});
expect(restartTestMock).toHaveBeenCalled();
});
it("sets language", () => {
//GIVEN
findGetParameterMock.mockReturnValue(urlData({ language: "english" }));
//WHEN
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("language", "english", {
nosave: true,
});
expect(restartTestMock).toHaveBeenCalled();
});
it("sets difficulty", () => {
//GIVEN
findGetParameterMock.mockReturnValue(urlData({ difficulty: "master" }));
//WHEN
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith("difficulty", "master", {
nosave: true,
});
expect(restartTestMock).toHaveBeenCalled();
});
it("sets funbox", () => {
//GIVEN
findGetParameterMock.mockReturnValue(
urlData({ funbox: ["crt", "choo_choo"] }),
);
//WHEN
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith(
"funbox",
["crt", "choo_choo"],
{
nosave: true,
},
);
expect(restartTestMock).toHaveBeenCalled();
});
it("sets funbox legacy", () => {
//GIVEN
findGetParameterMock.mockReturnValue(
urlData({ funbox: "crt#choo_choo" }),
);
//WHEN
loadTestSettingsFromUrl("");
//THEN
expect(setConfigMock).toHaveBeenCalledWith(
"funbox",
["crt", "choo_choo"],
{
nosave: true,
},
);
expect(restartTestMock).toHaveBeenCalled();
});
it("adds notification", () => {
//GIVEN
findGetParameterMock.mockReturnValue(
urlData({
mode: "time",
mode2: "60",
customText: {
text: ["abcabc"],
limit: { value: 5, mode: "time" },
mode: "random",
pipeDelimiter: true,
},
punctuation: true,
numbers: true,
language: "english",
difficulty: "master",
funbox: ["ascii", "crt"],
}),
);
//WHEN
loadTestSettingsFromUrl("");
//THEN
expect(notifySuccessMock).toHaveBeenCalledWith(expect.anything(), {
durationMs: 10000,
useInnerHtml: true,
});
});
it("rejects invalid values", () => {
//GIVEN
findGetParameterMock.mockReturnValue(
urlData({
mode: "invalidMode",
mode2: "invalidMode2",
customText: {
text: "invalid",
limit: "invalid",
mode: "invalid",
pipeDelimiter: "invalid",
},
punctuation: "invalid",
numbers: "invalid",
language: "invalid",
difficulty: "invalid",
funbox: ["invalid"],
} as any),
);
//WHEN
loadTestSettingsFromUrl("");
//THEN
expect(notifyMock).toHaveBeenCalledWith(
`Failed to load test settings from URL: JSON does not match schema: "0" invalid enum value. expected 'time' | 'words' | 'quote' | 'custom' | 'zen', received 'invalidmode', "1" needs to be a number or a number represented as a string e.g. "10"., "2.mode" invalid enum value. expected 'repeat' | 'random' | 'shuffle', received 'invalid', "2.pipeDelimiter" expected boolean, received string, "2.limit" expected object, received string, "2.text" expected array, received string, "3" expected boolean, received string, "4" expected boolean, received string, "6" invalid enum value. expected 'normal' | 'expert' | 'master', received 'invalid', "7" invalid input`,
);
});
});
});
const urlData = (
data: Partial<{
mode: Mode | undefined;
mode2: Mode2<any> | number;
customText: CustomTextSettings;
punctuation: boolean;
numbers: boolean;
language: string;
difficulty: Difficulty;
funbox: FunboxName[] | string;
}>,
): string => {
return compressToURI(
JSON.stringify([
data.mode ?? null,
data.mode2 ?? null,
data.customText ?? null,
data.punctuation ?? null,
data.numbers ?? null,
data.language ?? null,
data.difficulty ?? null,
data.funbox ?? null,
]),
);
};