Update Jest to more recent release (#11409)

* Update Jest to more recent release

I want to use things like `jest.advanceTimersByTimeAsync`

* more jest updates

* add dep on types/prettier

* fix LegacyRoomHeader-test

* fix MatrixChat-test

* fix RoomView-test

* fix PollHistory-test

* update SidebarUserSettingsTab-test

* fix PipContainer-test

* fix UserOnboardingPage-test

* fix WidgetContextMenu-test.tsx

* Avoid `mockImplementation` for mock `matchMedia` impl

`mockImplementation` is (now) reset by `jest.resetAllMocks` and
`jest.restoreAllMocks`, which we don't really want here.

Fixes `theme-test`

* Move `mediaDevices` mock out of `setupManualMocks`

This doesn't work well in test suites with multiple tests, because the
`mockReturnValue` is reset for subsequent tests.

In any case, having it mocked out automagically is *magical*. Let's make it
opt-in.

* fix FormattingButtons-test.tsx

* fix DeviceListenerTest

* fix RoomTile-test
This commit is contained in:
Richard van der Hoff 2023-08-16 11:20:48 +01:00 committed by GitHub
parent f8e1c54768
commit 7a6d81c3b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 512 additions and 350 deletions

View file

@ -158,13 +158,14 @@
"@types/fs-extra": "^11.0.0", "@types/fs-extra": "^11.0.0",
"@types/geojson": "^7946.0.8", "@types/geojson": "^7946.0.8",
"@types/glob-to-regexp": "^0.4.1", "@types/glob-to-regexp": "^0.4.1",
"@types/jest": "29.2.6", "@types/jest": "29.5.3",
"@types/katex": "^0.16.0", "@types/katex": "^0.16.0",
"@types/lodash": "^4.14.168", "@types/lodash": "^4.14.168",
"@types/modernizr": "^3.5.3", "@types/modernizr": "^3.5.3",
"@types/node": "^16", "@types/node": "^16",
"@types/node-fetch": "^2.6.2", "@types/node-fetch": "^2.6.2",
"@types/pako": "^2.0.0", "@types/pako": "^2.0.0",
"@types/prettier": "^2.7.0",
"@types/qrcode": "^1.3.5", "@types/qrcode": "^1.3.5",
"@types/react": "17.0.58", "@types/react": "17.0.58",
"@types/react-beautiful-dnd": "^13.0.0", "@types/react-beautiful-dnd": "^13.0.0",
@ -202,10 +203,10 @@
"express": "^4.18.2", "express": "^4.18.2",
"fetch-mock-jest": "^1.5.1", "fetch-mock-jest": "^1.5.1",
"fs-extra": "^11.0.0", "fs-extra": "^11.0.0",
"jest": "29.3.1", "jest": "^29.6.2",
"jest-canvas-mock": "2.4.0", "jest-canvas-mock": "^2.5.2",
"jest-environment-jsdom": "^29.2.2", "jest-environment-jsdom": "^29.6.2",
"jest-mock": "^29.2.2", "jest-mock": "^29.6.2",
"jest-raw-loader": "^1.0.1", "jest-raw-loader": "^1.0.1",
"jsqr": "^1.4.0", "jsqr": "^1.4.0",
"mailhog": "^4.16.0", "mailhog": "^4.16.0",

View file

@ -61,17 +61,18 @@ describe("DeviceListener", () => {
let mockClient: Mocked<MatrixClient>; let mockClient: Mocked<MatrixClient>;
let mockCrypto: Mocked<CryptoApi>; let mockCrypto: Mocked<CryptoApi>;
// spy on various toasts' hide and show functions
// easier than mocking
jest.spyOn(SetupEncryptionToast, "showToast");
jest.spyOn(SetupEncryptionToast, "hideToast");
jest.spyOn(BulkUnverifiedSessionsToast, "showToast");
jest.spyOn(BulkUnverifiedSessionsToast, "hideToast");
jest.spyOn(UnverifiedSessionToast, "showToast");
jest.spyOn(UnverifiedSessionToast, "hideToast");
beforeEach(() => { beforeEach(() => {
jest.resetAllMocks(); jest.resetAllMocks();
// spy on various toasts' hide and show functions
// easier than mocking
jest.spyOn(SetupEncryptionToast, "showToast").mockReturnValue(undefined);
jest.spyOn(SetupEncryptionToast, "hideToast").mockReturnValue(undefined);
jest.spyOn(BulkUnverifiedSessionsToast, "showToast").mockReturnValue(undefined);
jest.spyOn(BulkUnverifiedSessionsToast, "hideToast").mockReturnValue(undefined);
jest.spyOn(UnverifiedSessionToast, "showToast").mockResolvedValue(undefined);
jest.spyOn(UnverifiedSessionToast, "hideToast").mockReturnValue(undefined);
mockPlatformPeg({ mockPlatformPeg({
getAppVersion: jest.fn().mockResolvedValue("1.2.3"), getAppVersion: jest.fn().mockResolvedValue("1.2.3"),
}); });

View file

@ -193,7 +193,7 @@ describe("<MatrixChat />", () => {
}); });
afterEach(() => { afterEach(() => {
jest.restoreAllMocks(); jest.clearAllMocks();
}); });
it("should render spinner while app is loading", () => { it("should render spinner while app is loading", () => {

View file

@ -136,7 +136,7 @@ describe("PipContainer", () => {
cleanup(); cleanup();
await Promise.all([CallStore.instance, WidgetMessagingStore.instance].map(resetAsyncStoreWithClient)); await Promise.all([CallStore.instance, WidgetMessagingStore.instance].map(resetAsyncStoreWithClient));
client.reEmitter.stopReEmitting(room, [RoomStateEvent.Events]); client.reEmitter.stopReEmitting(room, [RoomStateEvent.Events]);
jest.restoreAllMocks(); jest.clearAllMocks();
}); });
const renderPip = () => { const renderPip = () => {

View file

@ -104,7 +104,7 @@ describe("RoomView", () => {
afterEach(() => { afterEach(() => {
unmockPlatformPeg(); unmockPlatformPeg();
jest.restoreAllMocks(); jest.clearAllMocks();
}); });
const mountRoomView = async (ref?: RefObject<_RoomView>): Promise<RenderResult> => { const mountRoomView = async (ref?: RefObject<_RoomView>): Promise<RenderResult> => {

View file

@ -50,15 +50,17 @@ describe("<WidgetContextMenu />", () => {
avatar_url: undefined, avatar_url: undefined,
}; };
const mockClient = { let mockClient: MatrixClient;
getUserId: jest.fn().mockReturnValue(userId),
} as unknown as MatrixClient;
let onFinished: () => void; let onFinished: () => void;
beforeEach(() => { beforeEach(() => {
onFinished = jest.fn(); onFinished = jest.fn();
jest.spyOn(WidgetUtils, "canUserModifyWidgets").mockReturnValue(true); jest.spyOn(WidgetUtils, "canUserModifyWidgets").mockReturnValue(true);
mockClient = {
getUserId: jest.fn().mockReturnValue(userId),
} as unknown as MatrixClient;
}); });
afterEach(() => { afterEach(() => {

View file

@ -15,8 +15,8 @@ limitations under the License.
*/ */
import React from "react"; import React from "react";
import { fireEvent, render } from "@testing-library/react"; import { act, fireEvent, render } from "@testing-library/react";
import { Filter, EventTimeline, Room } from "matrix-js-sdk/src/matrix"; import { Filter, EventTimeline, Room, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { M_POLL_START } from "matrix-js-sdk/src/@types/polls"; import { M_POLL_START } from "matrix-js-sdk/src/@types/polls";
import { PollHistory } from "../../../../../src/components/views/polls/pollHistory/PollHistory"; import { PollHistory } from "../../../../../src/components/views/polls/pollHistory/PollHistory";
@ -194,7 +194,11 @@ describe("<PollHistory />", () => {
const fourtyDaysAgoTs = now - 60000 * 60 * 24 * 40; const fourtyDaysAgoTs = now - 60000 * 60 * 24 * 40;
const pollStart = makePollStartEvent("Question?", userId, undefined, { ts: fourtyDaysAgoTs, id: "1" }); const pollStart = makePollStartEvent("Question?", userId, undefined, { ts: fourtyDaysAgoTs, id: "1" });
jest.spyOn(liveTimeline, "getEvents").mockReset().mockReturnValueOnce([]).mockReturnValueOnce([pollStart]); jest.spyOn(liveTimeline, "getEvents")
.mockReset()
.mockReturnValueOnce([])
.mockReturnValueOnce([pollStart])
.mockReturnValue(undefined as unknown as MatrixEvent[]);
// mock three pages of timeline history // mock three pages of timeline history
jest.spyOn(liveTimeline, "getPaginationToken") jest.spyOn(liveTimeline, "getPaginationToken")
@ -203,7 +207,7 @@ describe("<PollHistory />", () => {
.mockReturnValueOnce("test-pagination-token-3"); .mockReturnValueOnce("test-pagination-token-3");
const { getByText } = getComponent(); const { getByText } = getComponent();
await flushPromises(); await act(flushPromises);
expect(mockClient.paginateEventTimeline).toHaveBeenCalledTimes(1); expect(mockClient.paginateEventTimeline).toHaveBeenCalledTimes(1);
@ -216,7 +220,7 @@ describe("<PollHistory />", () => {
// load more polls button still in UI, with loader // load more polls button still in UI, with loader
expect(getByText("Load more polls")).toMatchSnapshot(); expect(getByText("Load more polls")).toMatchSnapshot();
await flushPromises(); await act(flushPromises);
// no more spinner // no more spinner
expect(getByText("Load more polls")).toMatchSnapshot(); expect(getByText("Load more polls")).toMatchSnapshot();

View file

@ -28,6 +28,7 @@ import {
import { CallType } from "matrix-js-sdk/src/webrtc/call"; import { CallType } from "matrix-js-sdk/src/webrtc/call";
import { ClientWidgetApi, Widget } from "matrix-widget-api"; import { ClientWidgetApi, Widget } from "matrix-widget-api";
import EventEmitter from "events"; import EventEmitter from "events";
import { setupJestCanvasMock } from "jest-canvas-mock";
import type { MatrixClient, MatrixEvent, RoomMember } from "matrix-js-sdk/src/matrix"; import type { MatrixClient, MatrixEvent, RoomMember } from "matrix-js-sdk/src/matrix";
import type { MatrixCall } from "matrix-js-sdk/src/webrtc/call"; import type { MatrixCall } from "matrix-js-sdk/src/webrtc/call";
@ -73,6 +74,10 @@ describe("LegacyRoomHeader", () => {
let carol: RoomMember; let carol: RoomMember;
beforeEach(async () => { beforeEach(async () => {
// some of our tests rely on the jest canvas mock, and `afterEach` will have reset the mock, so we need to
// restore it.
setupJestCanvasMock();
mockPlatformPeg({ supportsJitsiScreensharing: () => true }); mockPlatformPeg({ supportsJitsiScreensharing: () => true });
stubClient(); stubClient();

View file

@ -154,7 +154,7 @@ describe("RoomTile", () => {
afterEach(() => { afterEach(() => {
// @ts-ignore // @ts-ignore
MessagePreviewStore.instance.previews = new Map<string, Map<TagID | TAG_ANY, MessagePreview | null>>(); MessagePreviewStore.instance.previews = new Map<string, Map<TagID | TAG_ANY, MessagePreview | null>>();
jest.restoreAllMocks(); jest.clearAllMocks();
}); });
describe("when message previews are not enabled", () => { describe("when message previews are not enabled", () => {

View file

@ -73,6 +73,10 @@ const classes = {
}; };
describe("FormattingButtons", () => { describe("FormattingButtons", () => {
beforeEach(() => {
openLinkModalSpy.mockReturnValue(undefined);
});
afterEach(() => { afterEach(() => {
jest.resetAllMocks(); jest.resetAllMocks();
}); });

View file

@ -28,7 +28,7 @@ describe("<SidebarUserSettingsTab />", () => {
beforeEach(() => { beforeEach(() => {
jest.spyOn(PosthogTrackers, "trackInteraction").mockClear(); jest.spyOn(PosthogTrackers, "trackInteraction").mockClear();
jest.spyOn(SettingsStore, "getValue").mockRestore(); jest.spyOn(SettingsStore, "getValue").mockRestore();
jest.spyOn(SettingsStore, "setValue").mockReset(); jest.spyOn(SettingsStore, "setValue").mockResolvedValue(undefined);
}); });
it("renders sidebar settings", () => { it("renders sidebar settings", () => {

View file

@ -24,12 +24,12 @@ import SdkConfig from "../../../../src/SdkConfig";
jest.mock("../../../../src/components/structures/EmbeddedPage", () => ({ jest.mock("../../../../src/components/structures/EmbeddedPage", () => ({
__esModule: true, __esModule: true,
default: jest.fn().mockImplementation(({ url }) => <div>{url}</div>), default: ({ url }: { url: string }) => <div>{url}</div>,
})); }));
jest.mock("../../../../src/components/structures/HomePage", () => ({ jest.mock("../../../../src/components/structures/HomePage", () => ({
__esModule: true, __esModule: true,
default: jest.fn().mockImplementation(() => <div>home page</div>), default: () => <div>home page</div>,
})); }));
describe("UserOnboardingPage", () => { describe("UserOnboardingPage", () => {

View file

@ -56,7 +56,8 @@ class MyClipboardEvent extends Event {}
window.ClipboardEvent = MyClipboardEvent as any; window.ClipboardEvent = MyClipboardEvent as any;
// matchMedia is not included in jsdom // matchMedia is not included in jsdom
const mockMatchMedia = jest.fn().mockImplementation((query) => ({ // TODO: Extract this to a function and have tests that need it opt into it.
const mockMatchMedia = (query: string) => ({
matches: false, matches: false,
media: query, media: query,
onchange: null, onchange: null,
@ -65,7 +66,7 @@ const mockMatchMedia = jest.fn().mockImplementation((query) => ({
addEventListener: jest.fn(), addEventListener: jest.fn(),
removeEventListener: jest.fn(), removeEventListener: jest.fn(),
dispatchEvent: jest.fn(), dispatchEvent: jest.fn(),
})); });
global.matchMedia = mockMatchMedia; global.matchMedia = mockMatchMedia;
// maplibre requires a createObjectURL mock // maplibre requires a createObjectURL mock

782
yarn.lock

File diff suppressed because it is too large Load diff