Skip to content

Commit

Permalink
[Typescript] Require function return type (#2685)
Browse files Browse the repository at this point in the history
  • Loading branch information
imnasnainaec authored Oct 12, 2023
1 parent 42cc273 commit d8789a5
Show file tree
Hide file tree
Showing 90 changed files with 380 additions and 296 deletions.
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@
"*.dic.js"
],
"rules": {
"@typescript-eslint/explicit-function-return-type": [
"warn",
{
"allowExpressions": true
}
],
"@typescript-eslint/no-empty-interface": "warn",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-inferrable-types": "warn",
Expand Down
3 changes: 2 additions & 1 deletion src/backend/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,12 @@ const wordApi = new Api.WordApi(config, BASE_PATH, axiosInstance);

// Backend controllers receiving a file via a "[FromForm] FileUpload fileUpload" param
// have the internal fields expanded by openapi-generator as params in our Api.
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function fileUpload(file: File) {
return { file, filePath: "", name: "" };
}

function defaultOptions() {
function defaultOptions(): object {
return { headers: authHeader() };
}

Expand Down
2 changes: 1 addition & 1 deletion src/backend/tests/localStorage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ afterAll(() => {
}
});

function expectAllEmpty() {
function expectAllEmpty(): void {
expect(LocalStorage.getAvatar()).toEqual("");
expect(LocalStorage.getClosedBanner()).toEqual("");
expect(LocalStorage.getCurrentUser()).toEqual(undefined);
Expand Down
5 changes: 3 additions & 2 deletions src/components/AnnouncementBanner/AnnouncementBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Box, IconButton, Toolbar, Typography } from "@mui/material";
import {
CSSProperties,
Fragment,
ReactElement,
useCallback,
useEffect,
useState,
Expand All @@ -17,7 +18,7 @@ import { useAppSelector } from "types/hooks";
import { Path } from "types/path";
import theme, { themeColors } from "types/theme";

export default function AnnouncementBanner() {
export default function AnnouncementBanner(): ReactElement {
const [banner, setBanner] = useState<string>("");
const [margins, setMargins] = useState<CSSProperties>({});

Expand All @@ -40,7 +41,7 @@ export default function AnnouncementBanner() {
});
}, [loc, calculateMargins]);

function closeBanner() {
function closeBanner(): void {
setClosedBanner(banner);
setBanner("");
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/App/AppLoggedIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export default function AppWithBar(): ReactElement {
}
}, [proj]);

const overrideThemeFont = (theme: Theme) =>
const overrideThemeFont = (theme: Theme): Theme =>
styleOverrides
? createTheme({
...theme,
Expand Down
10 changes: 8 additions & 2 deletions src/components/App/SignalRHub.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ import {
HubConnectionBuilder,
HubConnectionState,
} from "@microsoft/signalr";
import { Fragment, useCallback, useEffect, useState } from "react";
import {
Fragment,
ReactElement,
useCallback,
useEffect,
useState,
} from "react";

import { baseURL } from "backend";
import { getUserId } from "backend/localStorage";
Expand All @@ -16,7 +22,7 @@ import { StoreState } from "types";
import { useAppDispatch, useAppSelector } from "types/hooks";

/** A central hub for monitoring export status on SignalR */
export default function SignalRHub() {
export default function SignalRHub(): ReactElement {
const exportState = useAppSelector(
(state: StoreState) => state.exportProjectState
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/AppBar/tests/AppBarComponent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jest.mock("backend", () => ({

const mockStore = configureMockStore()(defaultState);

function setMockFunctions() {
function setMockFunctions(): void {
mockGetUser.mockResolvedValue(mockUser);
}

Expand Down
10 changes: 5 additions & 5 deletions src/components/AppBar/tests/ProjectButtons.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Button } from "@mui/material";
import { Provider } from "react-redux";
import renderer from "react-test-renderer";
import { ReactTestRenderer, act, create } from "react-test-renderer";
import configureMockStore from "redux-mock-store";

import "tests/reactI18nextMock";
Expand Down Expand Up @@ -30,15 +30,15 @@ const mockProjectId = "proj-id";
const mockProjectRoles: { [key: string]: string } = {};
mockProjectRoles[mockProjectId] = "non-empty-string";

let testRenderer: renderer.ReactTestRenderer;
let testRenderer: ReactTestRenderer;

const mockStore = configureMockStore()({
currentProjectState: { project: { name: "" } },
});

const renderProjectButtons = async (path = Path.Root) => {
await renderer.act(async () => {
testRenderer = renderer.create(
const renderProjectButtons = async (path = Path.Root): Promise<void> => {
await act(async () => {
testRenderer = create(
<Provider store={mockStore}>
<ProjectButtons currentTab={path} />
</Provider>
Expand Down
24 changes: 12 additions & 12 deletions src/components/AppBar/tests/UserMenu.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Button, MenuItem } from "@mui/material";
import { Provider } from "react-redux";
import renderer from "react-test-renderer";
import { act, create, ReactTestRenderer } from "react-test-renderer";
import configureMockStore from "redux-mock-store";

import "tests/reactI18nextMock";
Expand All @@ -21,7 +21,7 @@ jest.mock("react-router-dom", () => ({
useNavigate: jest.fn(),
}));

let testRenderer: renderer.ReactTestRenderer;
let testRenderer: ReactTestRenderer;

const mockStore = configureMockStore()();

Expand All @@ -30,7 +30,7 @@ const mockGetUserId = jest.fn();
const mockUser = newUser();
const mockUserId = "mockUserId";

function setMockFunctions() {
function setMockFunctions(): void {
mockGetUser.mockResolvedValue(mockUser);
mockGetUserId.mockReturnValue(mockUserId);
}
Expand All @@ -41,9 +41,9 @@ beforeEach(() => {
});

describe("UserMenu", () => {
it("renders without crashing", () => {
renderer.act(() => {
testRenderer = renderer.create(
it("renders without crashing", async () => {
await act(async () => {
testRenderer = create(
<Provider store={mockStore}>
<UserMenu currentTab={Path.Root} />
</Provider>
Expand All @@ -59,18 +59,18 @@ describe("UserMenu", () => {
expect(await getIsAdmin()).toBeTruthy();
});

it("UserMenuList has one more item for admins (Site Settings)", () => {
renderMenuList();
it("UserMenuList has one more item for admins (Site Settings)", async () => {
await renderMenuList();
const normalMenuItems = testRenderer.root.findAllByType(MenuItem).length;
renderMenuList(true);
await renderMenuList(true);
const adminMenuItems = testRenderer.root.findAllByType(MenuItem).length;
expect(adminMenuItems).toBe(normalMenuItems + 1);
});
});

function renderMenuList(isAdmin = false) {
renderer.act(() => {
testRenderer = renderer.create(
async function renderMenuList(isAdmin = false): Promise<void> {
await act(async () => {
testRenderer = create(
<Provider store={mockStore}>
<UserMenuList isAdmin={isAdmin} onSelect={jest.fn()} />
</Provider>
Expand Down
10 changes: 5 additions & 5 deletions src/components/Buttons/FileInputButton.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import { Button } from "@mui/material";
import { ButtonProps } from "@mui/material/Button";
import React, { ReactElement } from "react";
import { ReactElement, ReactNode } from "react";

interface BrowseProps {
updateFile: (file: File) => void;
accept?: string;
children?: React.ReactNode;
children?: ReactNode;
buttonProps?: ButtonProps;
}

// This button links to a set of functions
export default function FileInputButton(props: BrowseProps): ReactElement {
function updateFirstFile(files: FileList) {
function updateFirstFile(files: FileList): void {
const file = files[0];
if (file) {
props.updateFile(file);
}
}

return (
<React.Fragment>
<>
{/* The actual file input element is hidden... */}
<input
id="file-input"
Expand All @@ -38,6 +38,6 @@ export default function FileInputButton(props: BrowseProps): ReactElement {
{props.children}
</Button>
</label>
</React.Fragment>
</>
);
}
2 changes: 1 addition & 1 deletion src/components/Buttons/PartOfSpeechButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default function PartOfSpeech(props: PartOfSpeechProps): ReactElement {
catGroupText
);

const CatGroupButton = () => (
const CatGroupButton = (): ReactElement => (
<IconButtonWithTooltip
buttonId={props.buttonId}
icon={<Hexagon fontSize="small" sx={{ color }} />}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Delete } from "@mui/icons-material";
import { IconButton, Tooltip } from "@mui/material";
import React, { useState } from "react";
import { ReactElement, useState } from "react";
import { useTranslation } from "react-i18next";

import { CancelConfirmDialog } from "components/Dialogs";
Expand All @@ -18,11 +18,11 @@ interface DeleteEntryProps {
/**
* A delete button
*/
export default function DeleteEntry(props: DeleteEntryProps) {
export default function DeleteEntry(props: DeleteEntryProps): ReactElement {
const [open, setOpen] = useState<boolean>(false);
const { t } = useTranslation();

function handleClick() {
function handleClick(): void {
if (props.confirmId) {
setOpen(true);
} else {
Expand All @@ -31,7 +31,7 @@ export default function DeleteEntry(props: DeleteEntryProps) {
}

return (
<React.Fragment>
<>
<Tooltip title={t("addWords.deleteRow")} placement="top">
<IconButton
tabIndex={-1}
Expand All @@ -53,6 +53,6 @@ export default function DeleteEntry(props: DeleteEntryProps) {
buttonIdCancel="delete-word-cancel"
buttonIdConfirm="delete-word-confirm"
/>
</React.Fragment>
</>
);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AddComment, Comment } from "@mui/icons-material";
import { IconButton, Tooltip } from "@mui/material";
import React, { useState } from "react";
import { ReactElement, useState } from "react";
import { useTranslation } from "react-i18next";

import { EditTextDialog } from "components/Dialogs";
Expand All @@ -14,12 +14,12 @@ interface EntryNoteProps {
/**
* A note adding/editing button
*/
export default function EntryNote(props: EntryNoteProps) {
export default function EntryNote(props: EntryNoteProps): ReactElement {
const [noteOpen, setNoteOpen] = useState<boolean>(false);
const { t } = useTranslation();

return (
<React.Fragment>
<>
<Tooltip
title={props.noteText ? props.noteText : t("addWords.addNote")}
placement="top"
Expand All @@ -42,6 +42,6 @@ export default function EntryNote(props: EntryNoteProps) {
buttonIdConfirm="note-edit-confirm"
textFieldId="note-text-field"
/>
</React.Fragment>
</>
);
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
import { AddComment, Comment } from "@mui/icons-material";
import renderer from "react-test-renderer";
import {
ReactTestInstance,
ReactTestRenderer,
act,
create,
} from "react-test-renderer";

import "tests/reactI18nextMock";

import EntryNote from "components/DataEntry/DataEntryTable/EntryCellComponents/EntryNote";

const mockText = "Test text";

let testMaster: renderer.ReactTestRenderer;
let testHandle: renderer.ReactTestInstance;
let testMaster: ReactTestRenderer;
let testHandle: ReactTestInstance;

function renderWithText(text: string) {
renderer.act(() => {
testMaster = renderer.create(
async function renderWithText(text: string): Promise<void> {
await act(async () => {
testMaster = create(
<EntryNote noteText={text} updateNote={jest.fn()} buttonId="" />
);
});
testHandle = testMaster.root;
}

describe("DeleteEntry", () => {
it("renders without note", () => {
renderWithText("");
it("renders without note", async () => {
await renderWithText("");
expect(testHandle.findAllByType(AddComment).length).toBe(1);
expect(testHandle.findAllByType(Comment).length).toBe(0);
});

it("renders with note", () => {
renderWithText(mockText);
it("renders with note", async () => {
await renderWithText(mockText);
expect(testHandle.findAllByType(AddComment).length).toBe(0);
expect(testHandle.findAllByType(Comment).length).toBe(1);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ interface SenseListProps {
analysisLang: string;
}

export function SenseList(props: SenseListProps) {
export function SenseList(props: SenseListProps): ReactElement {
const { t } = useTranslation();

const hasPartsOfSpeech = !!props.selectedWord.senses.find(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ interface VernListProps {
analysisLang?: string;
}

export function VernList(props: VernListProps) {
export function VernList(props: VernListProps): ReactElement {
const { t } = useTranslation();

const hasPartsOfSpeech = !!props.vernacularWords.find((w) =>
Expand Down
Loading

0 comments on commit d8789a5

Please sign in to comment.