Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/__tests__/__integration__/dal/result.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ async function createDummyData(
charStats: [0, 0, 0, 0],
acc: 0,
mode: "time",
mode2: "10" as never,
mode2: "10",
quoteLength: 1,
timestamp,
restartCount: 0,
Expand Down
2 changes: 1 addition & 1 deletion backend/__tests__/__integration__/dal/user.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2137,7 +2137,7 @@ describe("UserDal", () => {
maxLength: 50,
lastResultTimestamp: 0,
hourOffset: -1,
} as any,
},
xp: 42,
inventory: {
badges: [{ id: 23 }, { id: 5 }],
Expand Down
2 changes: 1 addition & 1 deletion backend/__tests__/api/controllers/quotes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ describe("QuotesController", () => {

beforeEach(() => {
addQuoteMock.mockClear();
addQuoteMock.mockResolvedValue({} as any);
addQuoteMock.mockResolvedValue({});

verifyCaptchaMock.mockClear();
verifyCaptchaMock.mockResolvedValue(true);
Expand Down
3 changes: 1 addition & 2 deletions backend/__tests__/api/controllers/user.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import GeorgeQueue from "../../../src/queues/george-queue";
import * as DiscordUtils from "../../../src/utils/discord";
import * as Captcha from "../../../src/utils/captcha";
import * as FirebaseAdmin from "../../../src/init/firebase-admin";
import { FirebaseError } from "firebase-admin";
import * as ApeKeysDal from "../../../src/dal/ape-keys";
import * as LogDal from "../../../src/dal/logs";
import { ObjectId } from "mongodb";
Expand Down Expand Up @@ -1439,7 +1438,7 @@ describe("user controller test", () => {
});
it("should fail for unknown error", async () => {
//GIVEN
authUpdateEmailMock.mockRejectedValue({} as FirebaseError);
authUpdateEmailMock.mockRejectedValue({});

//WHEN
await mockApp
Expand Down
2 changes: 1 addition & 1 deletion backend/__tests__/middlewares/auth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ describe("middlewares/auth", () => {
throw error;
}
return "Next function called";
}) as unknown as NextFunction;
});
});

afterEach(() => {
Expand Down
4 changes: 2 additions & 2 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@
"@vitest/coverage-v8": "4.1.5",
"concurrently": "8.2.2",
"openapi3-ts": "2.0.2",
"oxlint": "1.68.0",
"oxlint-tsgolint": "0.23.0",
"oxlint": "1.73.0",
"oxlint-tsgolint": "0.24.0",
"readline-sync": "1.4.10",
"supertest": "7.1.4",
"testcontainers": "11.11.0",
Expand Down
2 changes: 1 addition & 1 deletion backend/src/api/controllers/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ function createResult(
charStats: [131, 0, 0, 0],
acc: random(80, 100),
language: "english",
mode: mode as Mode,
mode: mode,
mode2: mode2 as unknown as never,
timestamp: timestamp.valueOf(),
testDuration: testDuration,
Expand Down
2 changes: 1 addition & 1 deletion backend/src/api/controllers/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ function getRelevantUserInfo(user: UserDAL.DBUser): RelevantUserInfo {
"ips",
"testActivity",
"suspicious",
]) as RelevantUserInfo;
]);
}

export async function getUser(req: MonkeyRequest): Promise<GetUserResponse> {
Expand Down
5 changes: 1 addition & 4 deletions backend/src/api/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import { getLiveConfiguration } from "../../init/configuration";
import Logger from "../../utils/logger";
import { createExpressEndpoints, initServer } from "@ts-rest/express";
import { ZodIssue } from "zod";
import { MonkeyValidationError } from "@monkeytype/contracts/util/api";
import { authenticateTsRestRequest } from "../../middlewares/auth";
import { rateLimitRequest } from "../../middlewares/rate-limit";
import { verifyPermissions } from "../../middlewares/permission";
Expand Down Expand Up @@ -111,9 +110,7 @@ function applyTsRestApiRoutes(app: IRouter): void {
return;
}

res
.status(422)
.json({ message, validationErrors } as MonkeyValidationError);
res.status(422).json({ message, validationErrors });
},
globalMiddleware: [
authenticateTsRestRequest(),
Expand Down
2 changes: 2 additions & 0 deletions docs/LANGUAGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ The contents of the file should be as follows:
"joiningScript": boolean,
"orderedByFrequency": boolean,
"bcp47": string,
"preferredFont":string,
"words": string[]
}
```
Expand All @@ -34,6 +35,7 @@ It is recommended that you familiarize yourselves with JSON before adding a lang
For `bcp47` put your languages [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag).
If the words you're adding are ordered by frequency (most common words at the top, least at the bottom) set the value of `orderedByFrequency` to `true`, otherwise `false`.
Finally, add your list of words to the `words` field.
If the language is not rendered correctly, you can provide a `preferredFont`. The font needs to be one of monkeytypes fonts. Check the [fonts documentation](./FONTS.md).

Then, go to `packages/schemas/src/languages.ts` and add your new language name at the _end_ of the `LanguageSchema` enum. Make sure to end the line with a comma. Make sure to add all your language names if you have created multiple word lists of differing lengths in the same language.

Expand Down
6 changes: 3 additions & 3 deletions frontend/__tests__/components/common/AnimatedModal.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { render } from "@solidjs/testing-library";
import { describe, it, expect, vi, beforeEach } from "vitest";

import { AnimatedModal } from "../../../src/ts/components/common/AnimatedModal";
import { hideModal, ModalId, showModal } from "../../../src/ts/states/modals";
import { hideModal, showModal } from "../../../src/ts/states/modals";

describe("AnimatedModal", () => {
beforeEach(() => {
showModal("Support" as ModalId);
showModal("Support");
vi.clearAllMocks();

// Mock dialog methods that don't exist in jsdom
Expand Down Expand Up @@ -60,7 +60,7 @@ describe("AnimatedModal", () => {
});

it("doesnt render children if not open", () => {
hideModal("Support" as ModalId);
hideModal("Support");
const { modalDiv } = renderModal({});

expect(modalDiv).not.toBeInTheDocument();
Expand Down
83 changes: 71 additions & 12 deletions frontend/__tests__/components/ui/form/InputField.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,32 @@ import { describe, it, expect, vi } from "vitest";

import { InputField } from "../../../../src/ts/components/ui/form/InputField";

function makeField(name: string, value = ""): AnyFieldApi {
function makeField(
name: string,
value?: string | number | boolean,
): AnyFieldApi {
let current = value;
const meta = {
isValidating: false,
isTouched: false,
isValid: true,
isDefaultValue: true,
errors: [] as string[],
};
return {
name,
state: {
value,
meta: {
isValidating: false,
isTouched: false,
isValid: true,
isDefaultValue: true,
errors: [],
},
get state() {
return {
value: current,
meta,
};
},
options: {},
options: { default: value },
handleBlur: vi.fn(),
handleChange: vi.fn(),
handleChange: vi.fn((v: unknown) => {
current = v as typeof value;
}),
setValue: vi.fn(),
getMeta: () => ({ hasWarning: false, warnings: [] }),
} as unknown as AnyFieldApi;
}
Expand Down Expand Up @@ -61,6 +71,16 @@ describe("InputField", () => {
expect(field.handleChange).toHaveBeenCalledWith("test");
});

it("calls handleChange on input for number", async () => {
const field = makeField("name", 2.5);
render(() => <InputField field={() => field} type="number" />);

fireEvent.input(screen.getByRole("spinbutton"), {
target: { value: "1.25" },
});
expect(field.handleChange).toHaveBeenCalledWith(1.25);
});

it("calls handleBlur on blur", async () => {
const field = makeField("name");
render(() => <InputField field={() => field} />);
Expand Down Expand Up @@ -100,4 +120,43 @@ describe("InputField", () => {

expect(container.querySelector(".fa-circle-notch")).not.toBeInTheDocument();
});

it("resets to default value on blur when empty for type number", async () => {
const field = makeField("age", 25);
field.form = { options: { defaultValues: { age: 25 } } } as any;
render(() => (
<InputField
field={() => field}
type="number"
resetToDefaultIfEmptyOnBlur
/>
));

fireEvent.input(screen.getByRole("spinbutton"), {
target: { value: "" },
});
fireEvent.blur(screen.getByRole("spinbutton"));
expect(field.setValue).toHaveBeenCalledWith(25);
});

it("resets to default value on blur when empty for type string", async () => {
const field = makeField("name", "Alice");
field.form = { options: { defaultValues: { name: "Alice" } } } as any;
render(() => (
<InputField field={() => field} resetToDefaultIfEmptyOnBlur />
));

fireEvent.input(screen.getByRole("textbox"), {
target: { value: "" },
});
fireEvent.blur(screen.getByRole("textbox"));
expect(field.setValue).toHaveBeenCalledWith("Alice");
});

it("renders NaN as empty string for type number", async () => {
const field = makeField("value", NaN);
render(() => <InputField field={() => field} type="number" />);

expect(screen.getByRole("spinbutton").getAttribute("value")).toBeNull();
});
});
2 changes: 1 addition & 1 deletion frontend/__tests__/controllers/preset-controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ describe("PresetController", () => {
...partialPreset,
} as any;
dbGetSnapshotMock.mockReturnValue({} as any);
getPresetMock.mockReturnValue(preset as any);
getPresetMock.mockReturnValue(preset);
return preset;
};
});
Expand Down
9 changes: 5 additions & 4 deletions frontend/__tests__/root/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import * as ConfigValidation from "../../src/ts/config/validation";
import { configEvent } from "../../src/ts/events/config";
import * as ApeConfig from "../../src/ts/ape/config";
import * as Notifications from "../../src/ts/states/notifications";
import * as TestState from "../../src/ts/states/test";

const { replaceConfig, getConfig } = __testing;

describe("Config", () => {
Expand All @@ -41,6 +43,7 @@ describe("Config", () => {
);
const miscReloadAfterMock = vi.spyOn(Misc, "reloadAfter");
const miscTriggerResizeMock = vi.spyOn(Misc, "triggerResize");
const stateIsTestActiveMock = vi.spyOn(TestState, "isTestActive");

const mocks = [
canSetConfigWithCurrentFunboxesMock,
Expand All @@ -50,19 +53,17 @@ describe("Config", () => {
notificationAddMock,
miscReloadAfterMock,
miscTriggerResizeMock,
stateIsTestActiveMock,
];

beforeEach(async () => {
vi.useFakeTimers();
mocks.forEach((it) => it.mockClear());

vi.mock("../../src/ts/test/test-state", () => ({
isActive: true,
}));

isConfigValueValidMock.mockReturnValue(true);
canSetConfigWithCurrentFunboxesMock.mockReturnValue(true);
dbSaveConfigMock.mockResolvedValue();
stateIsTestActiveMock.mockReturnValue(true);

replaceConfig({});
});
Expand Down
6 changes: 3 additions & 3 deletions frontend/__tests__/test/events/data.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,10 @@ describe("data.ts", () => {
// simulate forceReleaseAllKeys passing indexed codes directly
logTestEvent("keyup", 1030, {
code: "NoCode0",
} as KeyupEventData);
});
logTestEvent("keyup", 1040, {
code: "NoCode1",
} as KeyupEventData);
});

const events = getAllTestEvents();
expect(events).toHaveLength(4);
Expand All @@ -239,7 +239,7 @@ describe("data.ts", () => {
it("rejects indexed NoCode keyup with no matching keydown", () => {
logTestEvent("keyup", 1010, {
code: "NoCode0",
} as KeyupEventData);
});

expect(getAllTestEvents()).toHaveLength(0);
});
Expand Down
4 changes: 2 additions & 2 deletions frontend/__tests__/test/events/stats.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ describe("stats.ts", () => {
charIndex: 3,
inputType: "deleteWordBackward",
inputValue: "=",
} as InputEventData);
});

// second Ctrl+Backspace: Firefox ate sentinel + "=" → goToPreviousWord;
// clearedNextWord marks word 1 (= wordIndex + 1) as abandoned
Expand All @@ -854,7 +854,7 @@ describe("stats.ts", () => {
inputType: "deleteWordBackward",
inputValue: "",
clearedNextWord: true,
} as InputEventData);
});

logTestEvent("timer", 5000, timer("end", 4));

Expand Down
4 changes: 2 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@
"madge": "8.0.0",
"magic-string": "0.30.17",
"normalize.css": "8.0.1",
"oxlint": "1.68.0",
"oxlint-tsgolint": "0.23.0",
"oxlint": "1.73.0",
"oxlint-tsgolint": "0.24.0",
"postcss": "8.5.15",
"sass": "1.70.0",
"solid-devtools": "0.34.5",
Expand Down
13 changes: 1 addition & 12 deletions frontend/src/html/pages/test.html
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@

<div id="compositionDisplay"></div>
<mount data-component="keymap"></mount>
<mount data-component="monkey"></mount>

<button
id="restartTestButton"
Expand All @@ -81,18 +82,6 @@
<div class="liveBurst hidden">1</div>
</div>
</div>
<div id="monkey" class="hidden">
<div class="up"></div>
<div class="left hidden"></div>
<div class="right hidden"></div>
<div class="both hidden"></div>
<div class="fast">
<div class="up"></div>
<div class="left hidden"></div>
<div class="right hidden"></div>
<div class="both hidden"></div>
</div>
</div>
<div id="premidTestMode" class="hidden"></div>
<div id="premidSecondsLeft" class="hidden"></div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/styles/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

@layer custom-styles {
@import "buttons", "ads", "test-activity", "animations", "caret",
"commandline", "core", "fonts", "inputs", "monkey", "popups", "scroll",
"test", "loading", "media-queries";
"commandline", "core", "fonts", "inputs", "popups", "scroll", "test",
"loading", "media-queries";

.chartCanvas {
width: 100% !important;
Expand Down
Loading
Loading