From 89372b9a15fa99a6052c0e84bff2f96c19f0334a Mon Sep 17 00:00:00 2001 From: Danny Rorabaugh Date: Thu, 5 Oct 2023 17:44:01 -0400 Subject: [PATCH] Cinch up TS linting for test files too --- .vscode/settings.json | 1 + package.json | 1 + src/components/App/App.test.tsx | 18 ++++--- .../AppBar/tests/AppBarComponent.test.tsx | 10 ++-- .../DataEntryTable/tests/index.test.tsx | 50 ++++++++++--------- .../LoginPage/tests/LoginComponent.test.tsx | 27 ++++++---- .../SignUpPage/tests/SignUpComponent.test.tsx | 29 +++++++---- .../ProjectSettings/tests/index.test.tsx | 4 +- .../TreeView/tests/SemanticDomainMock.ts | 2 + .../TreeView/tests/TreeSearch.test.tsx | 2 +- .../UserSettings/tests/UserSettings.test.tsx | 2 +- .../Redux/tests/MergeDupsReducer.test.tsx | 1 + src/utilities/testUtilities.tsx | 6 +-- 13 files changed, 90 insertions(+), 63 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 509e6f0f60..afe282d1ee 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -71,6 +71,7 @@ "piptools", "Prenoun", "Preverb", + "recaptcha", "reportgenerator", "sched", "sillsdev", diff --git a/package.json b/package.json index 51b04f1671..face60b4c5 100644 --- a/package.json +++ b/package.json @@ -151,6 +151,7 @@ "import/newline-after-import": "warn", "import/no-duplicates": "warn", "import/no-named-as-default": "off", + "import/no-named-as-default-member": "warn", "import/order": [ "warn", { diff --git a/src/components/App/App.test.tsx b/src/components/App/App.test.tsx index c53bf846be..488de0d03a 100644 --- a/src/components/App/App.test.tsx +++ b/src/components/App/App.test.tsx @@ -1,6 +1,6 @@ import "jest-canvas-mock"; import { Provider } from "react-redux"; -import renderer from "react-test-renderer"; +import { act, create } from "react-test-renderer"; import configureMockStore from "redux-mock-store"; import thunk from "redux-thunk"; @@ -9,9 +9,13 @@ import "tests/reactI18nextMock"; import { defaultState } from "components/App/DefaultState"; import App from "components/App/component"; -jest.mock("@matt-block/react-recaptcha-v2", () => () => ( -
Recaptcha
-)); +jest.mock( + "@matt-block/react-recaptcha-v2", + () => + function MockRecaptcha() { + return
Recaptcha
; + } +); jest.mock("components/AnnouncementBanner/AnnouncementBanner", () => "div"); const createMockStore = configureMockStore([thunk]); @@ -23,9 +27,9 @@ global.innerHeight = 100; global.analytics = { track: jest.fn() } as any; describe("App", () => { - it("renders without crashing", () => { - renderer.act(() => { - renderer.create( + it("renders without crashing", async () => { + await act(async () => { + create( diff --git a/src/components/AppBar/tests/AppBarComponent.test.tsx b/src/components/AppBar/tests/AppBarComponent.test.tsx index a156888354..b58fc64f49 100644 --- a/src/components/AppBar/tests/AppBarComponent.test.tsx +++ b/src/components/AppBar/tests/AppBarComponent.test.tsx @@ -1,6 +1,6 @@ import { Provider } from "react-redux"; import { MemoryRouter } from "react-router-dom"; -import renderer from "react-test-renderer"; +import { act, create } from "react-test-renderer"; import configureMockStore from "redux-mock-store"; import "tests/reactI18nextMock"; @@ -18,8 +18,6 @@ jest.mock("backend", () => ({ const mockStore = configureMockStore()(defaultState); -let testRenderer: renderer.ReactTestRenderer; - function setMockFunctions() { mockGetUser.mockResolvedValue(mockUser); } @@ -30,9 +28,9 @@ beforeAll(() => { }); describe("AppBar", () => { - it("renders", () => { - renderer.act(() => { - testRenderer = renderer.create( + it("renders", async () => { + await act(async () => { + create( diff --git a/src/components/DataEntry/DataEntryTable/tests/index.test.tsx b/src/components/DataEntry/DataEntryTable/tests/index.test.tsx index 25e680c564..d21f21aa4d 100644 --- a/src/components/DataEntry/DataEntryTable/tests/index.test.tsx +++ b/src/components/DataEntry/DataEntryTable/tests/index.test.tsx @@ -1,6 +1,11 @@ import { ReactElement } from "react"; import { Provider } from "react-redux"; -import renderer from "react-test-renderer"; +import { + ReactTestInstance, + ReactTestRenderer, + act, + create, +} from "react-test-renderer"; import configureMockStore from "redux-mock-store"; import "tests/reactI18nextMock"; @@ -17,7 +22,6 @@ import DataEntryTable, { updateEntryGloss, } from "components/DataEntry/DataEntryTable"; import NewEntry from "components/DataEntry/DataEntryTable/NewEntry"; -import { RecentEntryProps } from "components/DataEntry/DataEntryTable/RecentEntry"; import { newProject } from "types/project"; import { newSemanticDomain, @@ -57,10 +61,10 @@ jest.mock("utilities/utilities"); jest.spyOn(window, "alert").mockImplementation(() => {}); -let testRenderer: renderer.ReactTestRenderer; -let testHandle: renderer.ReactTestInstance; +let testRenderer: ReactTestRenderer; +let testHandle: ReactTestInstance; -function MockRecentEntry(props: RecentEntryProps): ReactElement { +function MockRecentEntry(): ReactElement { return
; } @@ -97,8 +101,8 @@ beforeEach(() => { }); const renderTable = async (): Promise => { - await renderer.act(async () => { - testRenderer = renderer.create( + await act(async () => { + testRenderer = create( => { } mockCreateWord.mockResolvedValueOnce(word); mockGetWord.mockResolvedValueOnce(word); - await renderer.act(async () => { + await act(async () => { await testRenderer.root.findByType(NewEntry).props.addNewEntry(); }); return word.id; @@ -140,7 +144,7 @@ describe("DataEntryTable", () => { it("hides questions", async () => { expect(mockHideQuestions).not.toBeCalled(); testHandle = testRenderer.root.findByProps({ id: exitButtonId }); - await renderer.act(async () => await testHandle.props.onClick()); + await act(async () => await testHandle.props.onClick()); expect(mockHideQuestions).toBeCalled(); }); @@ -149,9 +153,9 @@ describe("DataEntryTable", () => { testHandle = testRenderer.root.findByType(NewEntry); expect(testHandle).not.toBeNull; // Set newVern but not newGloss. - await renderer.act(async () => testHandle.props.setNewVern("hasVern")); + await act(async () => testHandle.props.setNewVern("hasVern")); testHandle = testRenderer.root.findByProps({ id: exitButtonId }); - await renderer.act(async () => await testHandle.props.onClick()); + await act(async () => await testHandle.props.onClick()); expect(mockCreateWord).toBeCalledTimes(1); }); @@ -159,16 +163,16 @@ describe("DataEntryTable", () => { testHandle = testRenderer.root.findByType(NewEntry); expect(testHandle).not.toBeNull; // Set newGloss but not newVern. - await renderer.act(async () => testHandle.props.setNewGloss("hasGloss")); + await act(async () => testHandle.props.setNewGloss("hasGloss")); testHandle = testRenderer.root.findByProps({ id: exitButtonId }); - await renderer.act(async () => await testHandle.props.onClick()); + await act(async () => await testHandle.props.onClick()); expect(mockCreateWord).not.toBeCalled(); }); it("opens the domain tree", async () => { expect(mockOpenTree).not.toBeCalled(); testHandle = testRenderer.root.findByProps({ id: exitButtonId }); - await renderer.act(async () => await testHandle.props.onClick()); + await act(async () => await testHandle.props.onClick()); expect(mockOpenTree).toBeCalledTimes(1); }); }); @@ -293,7 +297,7 @@ describe("DataEntryTable", () => { mockGetFrontierWords.mockResolvedValue([word]); await renderTable(); testHandle = testRenderer.root.findByType(NewEntry); - await renderer.act(async () => { + await act(async () => { await testHandle.props.setNewGloss(firstGlossText(word.senses[0])); await testHandle.props.updateWordWithNewGloss(word.id); }); @@ -309,7 +313,7 @@ describe("DataEntryTable", () => { mockGetFrontierWords.mockResolvedValue([word]); await renderTable(); testHandle = testRenderer.root.findByType(NewEntry); - await renderer.act(async () => { + await act(async () => { await testHandle.props.setNewGloss(firstGlossText(word.senses[0])); await testHandle.props.updateWordWithNewGloss(word.id); }); @@ -319,7 +323,7 @@ describe("DataEntryTable", () => { it("updates word in backend if gloss doesn't exist", async () => { await renderTable(); testHandle = testRenderer.root.findByType(NewEntry); - await renderer.act(async () => { + await act(async () => { await testHandle.props.setNewGloss("differentGloss"); await testHandle.props.updateWordWithNewGloss(mockMultiWord.id); }); @@ -333,7 +337,7 @@ describe("DataEntryTable", () => { it("checks for duplicate and, if so, updates it", async () => { testHandle = testRenderer.root.findByType(NewEntry); mockGetDuplicateId.mockResolvedValueOnce(true); - await renderer.act(async () => { + await act(async () => { await testHandle.props.addNewEntry(); }); expect(mockUpdateDuplicate).toBeCalledTimes(1); @@ -357,7 +361,7 @@ describe("DataEntryTable", () => { // Verify that the number of recent entries increases by the correct amount expect(testRenderer.root.findAllByType(MockRecentEntry)).toHaveLength(0); - await renderer.act(async () => { + await act(async () => { await testRenderer.root.findByType(NewEntry).props.addNewEntry(); }); expect(testRenderer.root.findAllByType(MockRecentEntry)).toHaveLength( @@ -372,14 +376,14 @@ describe("DataEntryTable", () => { const vern = "vern"; const glossDef = "gloss"; const noteText = "note"; - renderer.act(() => { + act(() => { testHandle.props.setNewVern(vern); testHandle.props.setNewGloss(glossDef); testHandle.props.setNewNote(noteText); }); // Trigger the function to add a new entry - await renderer.act(async () => { + await act(async () => { try { await testHandle.props.addNewEntry(); } catch { @@ -409,7 +413,7 @@ describe("DataEntryTable", () => { it("removes a recent entry", async () => { await addRecentEntry(); const recentEntry = testRenderer.root.findByType(MockRecentEntry); - await renderer.act(async () => { + await act(async () => { await recentEntry.props.removeEntry(); }); expect(testRenderer.root.findAllByType(MockRecentEntry)).toHaveLength(0); @@ -432,7 +436,7 @@ describe("DataEntryTable", () => { // Update the vernacular const newVern = "not the vern generated in addRecentEntry"; - await renderer.act(async () => { + await act(async () => { await recentEntry.props.updateVern(newVern); }); diff --git a/src/components/Login/LoginPage/tests/LoginComponent.test.tsx b/src/components/Login/LoginPage/tests/LoginComponent.test.tsx index 872177118f..2fbfd09627 100644 --- a/src/components/Login/LoginPage/tests/LoginComponent.test.tsx +++ b/src/components/Login/LoginPage/tests/LoginComponent.test.tsx @@ -1,28 +1,37 @@ -import renderer from "react-test-renderer"; +import { + ReactTestInstance, + ReactTestRenderer, + act, + create, +} from "react-test-renderer"; import "tests/reactI18nextMock"; import Login from "components/Login/LoginPage/LoginComponent"; -jest.mock("@matt-block/react-recaptcha-v2", () => () => ( -
Recaptcha
-)); +jest.mock( + "@matt-block/react-recaptcha-v2", + () => + function MockRecaptcha() { + return
Recaptcha
; + } +); jest.mock("backend", () => ({ getBannerText: () => Promise.resolve(""), })); jest.mock("browserRouter"); const LOGOUT = jest.fn(); -let loginMaster: renderer.ReactTestRenderer; -let loginHandle: renderer.ReactTestInstance; +let loginMaster: ReactTestRenderer; +let loginHandle: ReactTestInstance; const DATA = "stuff"; const MOCK_EVENT = { preventDefault: jest.fn(), target: { value: DATA } }; describe("Testing login component", () => { - beforeEach(() => { - renderer.act(() => { - loginMaster = renderer.create(); + beforeEach(async () => { + await act(async () => { + loginMaster = create(); }); loginHandle = loginMaster.root.findByType(Login); LOGOUT.mockClear(); diff --git a/src/components/Login/SignUpPage/tests/SignUpComponent.test.tsx b/src/components/Login/SignUpPage/tests/SignUpComponent.test.tsx index 6ab05dc941..cb092f7566 100644 --- a/src/components/Login/SignUpPage/tests/SignUpComponent.test.tsx +++ b/src/components/Login/SignUpPage/tests/SignUpComponent.test.tsx @@ -1,27 +1,34 @@ -import renderer from "react-test-renderer"; +import { + ReactTestInstance, + ReactTestRenderer, + act, + create, +} from "react-test-renderer"; import "tests/reactI18nextMock"; import SignUp from "components/Login/SignUpPage/SignUpComponent"; -jest.mock("@matt-block/react-recaptcha-v2", () => () => ( -
Recaptcha
-)); +jest.mock( + "@matt-block/react-recaptcha-v2", + () => + function MockRecaptcha() { + return
Recaptcha
; + } +); jest.mock("browserRouter"); const mockReset = jest.fn(); -let signUpMaster: renderer.ReactTestRenderer; -let signUpHandle: renderer.ReactTestInstance; +let signUpMaster: ReactTestRenderer; +let signUpHandle: ReactTestInstance; const DATA = "stuff"; const MOCK_EVENT = { preventDefault: jest.fn(), target: { value: DATA } }; describe("Testing sign up component", () => { - beforeEach(() => { - renderer.act(() => { - signUpMaster = renderer.create( - - ); + beforeEach(async () => { + await act(async () => { + signUpMaster = create(); }); signUpHandle = signUpMaster.root.findByType(SignUp); mockReset.mockClear(); diff --git a/src/components/ProjectSettings/tests/index.test.tsx b/src/components/ProjectSettings/tests/index.test.tsx index 8b50056682..7147ac151d 100644 --- a/src/components/ProjectSettings/tests/index.test.tsx +++ b/src/components/ProjectSettings/tests/index.test.tsx @@ -1,7 +1,7 @@ import "@testing-library/jest-dom"; import { act, cleanup, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import mediaQuery from "css-mediaquery"; +import { match } from "css-mediaquery"; import { Provider } from "react-redux"; import configureMockStore from "redux-mock-store"; @@ -73,7 +73,7 @@ const createMatchMedia = ( ): ((query: string) => MediaQueryList) => { return (query: string) => ({ - matches: mediaQuery.match(query, { width }), + matches: match(query, { width }), addListener: jest.fn(), removeListener: jest.fn(), }) as any; diff --git a/src/components/TreeView/tests/SemanticDomainMock.ts b/src/components/TreeView/tests/SemanticDomainMock.ts index 052be6725a..e79f5a5657 100644 --- a/src/components/TreeView/tests/SemanticDomainMock.ts +++ b/src/components/TreeView/tests/SemanticDomainMock.ts @@ -4,6 +4,7 @@ import { semDomFromTreeNode, } from "types/semanticDomain"; +/* eslint-disable @typescript-eslint/no-duplicate-enum-values */ export enum mapIds { "head" = "Sem", "parent" = "1", @@ -17,6 +18,7 @@ export enum mapIds { "depth4" = "1.2.1.1", "depth5" = "1.2.1.1.1", } +/* eslint-enable @typescript-eslint/no-duplicate-enum-values */ const nodeMap: TreeNodeMap = {}; diff --git a/src/components/TreeView/tests/TreeSearch.test.tsx b/src/components/TreeView/tests/TreeSearch.test.tsx index a42852237f..73e2edde19 100644 --- a/src/components/TreeView/tests/TreeSearch.test.tsx +++ b/src/components/TreeView/tests/TreeSearch.test.tsx @@ -18,7 +18,7 @@ import domMap, { mapIds } from "components/TreeView/tests/SemanticDomainMock"; import { newSemanticDomainTreeNode } from "types/semanticDomain"; // Handles -const MOCK_ANIMATE = jest.fn((_domain: SemanticDomainTreeNode) => { +const MOCK_ANIMATE = jest.fn(() => { console.log("MockAnimateCalled"); return Promise.resolve(); }); diff --git a/src/components/UserSettings/tests/UserSettings.test.tsx b/src/components/UserSettings/tests/UserSettings.test.tsx index c9f6c9dad7..849eec1d00 100644 --- a/src/components/UserSettings/tests/UserSettings.test.tsx +++ b/src/components/UserSettings/tests/UserSettings.test.tsx @@ -48,7 +48,7 @@ const setupMocks = (): void => { mockGetAvatar.mockReturnValue(""); mockGetCurrentUser.mockReturnValue(mockUser()); mockIsEmailTaken.mockResolvedValue(false); - mockSetUser.mockImplementation(async (user?: User) => {}); + mockSetUser.mockImplementation(async () => {}); mockUpdateUser.mockImplementation((user: User) => user); }; diff --git a/src/goals/MergeDuplicates/Redux/tests/MergeDupsReducer.test.tsx b/src/goals/MergeDuplicates/Redux/tests/MergeDupsReducer.test.tsx index 67ad92c75d..c2cef9ebf8 100644 --- a/src/goals/MergeDuplicates/Redux/tests/MergeDupsReducer.test.tsx +++ b/src/goals/MergeDuplicates/Redux/tests/MergeDupsReducer.test.tsx @@ -20,6 +20,7 @@ import { Hash } from "types/hash"; import { newFlag, testWordList } from "types/word"; jest.mock("uuid"); +// eslint-disable-next-line @typescript-eslint/no-var-requires const mockUuid = require("uuid") as { v4: jest.Mock }; let uuidIndex = 0; diff --git a/src/utilities/testUtilities.tsx b/src/utilities/testUtilities.tsx index 46093b4b0b..dde3275f03 100644 --- a/src/utilities/testUtilities.tsx +++ b/src/utilities/testUtilities.tsx @@ -1,5 +1,5 @@ import { render } from "@testing-library/react"; -import React, { PropsWithChildren } from "react"; +import { PropsWithChildren, ReactElement } from "react"; import { Provider } from "react-redux"; import { PersistGate } from "redux-persist/integration/react"; @@ -22,7 +22,7 @@ interface ExtendedRenderOptions extends Omit { } export function renderWithProviders( - ui: React.ReactElement, + ui: ReactElement, { preloadedState = { ...defaultState, @@ -33,7 +33,7 @@ export function renderWithProviders( ...renderOptions }: ExtendedRenderOptions = {} ) { - function Wrapper({ children }: PropsWithChildren<{}>): JSX.Element { + function Wrapper({ children }: PropsWithChildren): JSX.Element { return ( {children}