diff --git a/test/components/views/elements/AppTile-test.tsx b/test/components/views/elements/AppTile-test.tsx index d10ca20bc2..7f035131a3 100644 --- a/test/components/views/elements/AppTile-test.tsx +++ b/test/components/views/elements/AppTile-test.tsx @@ -114,6 +114,10 @@ describe("AppTile", () => { await RightPanelStore.instance.onReady(); }); + beforeEach(() => { + jest.spyOn(SettingsStore, "getValue").mockRestore(); + }); + it("tracks live tiles correctly", () => { expect(AppTile.isLive("1", "r1")).toEqual(false); @@ -196,7 +200,7 @@ describe("AppTile", () => { it("distinguishes widgets with the same ID in different rooms", async () => { // Set up right panel state const realGetValue = SettingsStore.getValue; - SettingsStore.getValue = (name, roomId) => { + jest.spyOn(SettingsStore, 'getValue').mockImplementation((name, roomId) => { if (name === "RightPanel.phases") { if (roomId === "r1") { return { @@ -212,7 +216,7 @@ describe("AppTile", () => { return null; } return realGetValue(name, roomId); - }; + }); // Run initial render with room 1, and also running lifecycle methods const renderer = TestRenderer.create( @@ -232,7 +236,7 @@ describe("AppTile", () => { expect(AppTile.isLive("1", "r1")).toBe(true); expect(AppTile.isLive("1", "r2")).toBe(false); - SettingsStore.getValue = (name, roomId) => { + jest.spyOn(SettingsStore, "getValue").mockImplementation((name, roomId) => { if (name === "RightPanel.phases") { if (roomId === "r2") { return { @@ -248,7 +252,7 @@ describe("AppTile", () => { return null; } return realGetValue(name, roomId); - }; + }); // Wait for RPS room 2 updates to fire const rpsUpdated2 = waitForRps("r2"); // Switch to room 2 @@ -266,8 +270,6 @@ describe("AppTile", () => { expect(AppTile.isLive("1", "r1")).toBe(false); expect(AppTile.isLive("1", "r2")).toBe(true); - - SettingsStore.getValue = realGetValue; }); it("preserves non-persisted widget on container move", async () => { diff --git a/test/components/views/elements/PollCreateDialog-test.tsx b/test/components/views/elements/PollCreateDialog-test.tsx index 7ac68ccf3b..779b68e16b 100644 --- a/test/components/views/elements/PollCreateDialog-test.tsx +++ b/test/components/views/elements/PollCreateDialog-test.tsx @@ -26,16 +26,15 @@ import { M_TEXT, PollStartEvent, } from 'matrix-events-sdk'; -import { IContent, MatrixEvent } from 'matrix-js-sdk/src/models/event'; +import { MatrixEvent } from 'matrix-js-sdk/src/models/event'; import { - wrapInMatrixClientContext, findById, - stubClient, + getMockClientWithEventEmitter, } from '../../../test-utils'; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; -import _PollCreateDialog from "../../../../src/components/views/elements/PollCreateDialog"; -const PollCreateDialog = wrapInMatrixClientContext(_PollCreateDialog); +import PollCreateDialog from "../../../../src/components/views/elements/PollCreateDialog"; +import MatrixClientContext from '../../../../src/contexts/MatrixClientContext'; // Fake date to give a predictable snapshot const realDateNow = Date.now; @@ -51,9 +50,21 @@ afterAll(() => { }); describe("PollCreateDialog", () => { + const mockClient = getMockClientWithEventEmitter({ + sendEvent: jest.fn().mockResolvedValue({ event_id: '1' }), + }); + + beforeEach(() => { + mockClient.sendEvent.mockClear(); + }); + it("renders a blank poll", () => { const dialog = mount( , + { + wrappingComponent: MatrixClientContext.Provider, + wrappingComponentProps: { value: mockClient }, + }, ); expect(dialog.html()).toMatchSnapshot(); }); @@ -207,9 +218,6 @@ describe("PollCreateDialog", () => { }); it("displays a spinner after submitting", () => { - stubClient(); - MatrixClientPeg.get().sendEvent = jest.fn(() => Promise.resolve()); - const dialog = mount( , ); @@ -223,21 +231,6 @@ describe("PollCreateDialog", () => { }); it("sends a poll create event when submitted", () => { - stubClient(); - let sentEventContent: IContent = null; - MatrixClientPeg.get().sendEvent = jest.fn( - ( - _roomId: string, - _threadId: string, - eventType: string, - content: IContent, - ) => { - expect(M_POLL_START.matches(eventType)).toBeTruthy(); - sentEventContent = content; - return Promise.resolve(); - }, - ); - const dialog = mount( , ); @@ -246,6 +239,8 @@ describe("PollCreateDialog", () => { changeValue(dialog, "Option 2", "A2"); dialog.find("button").simulate("click"); + const [, , eventType, sentEventContent] = mockClient.sendEvent.mock.calls[0]; + expect(M_POLL_START.matches(eventType)).toBeTruthy(); expect(sentEventContent).toEqual( { [M_TEXT.name]: "Q\n1. A1\n2. A2", @@ -275,21 +270,6 @@ describe("PollCreateDialog", () => { }); it("sends a poll edit event when editing", () => { - stubClient(); - let sentEventContent: IContent = null; - MatrixClientPeg.get().sendEvent = jest.fn( - ( - _roomId: string, - _threadId: string, - eventType: string, - content: IContent, - ) => { - expect(M_POLL_START.matches(eventType)).toBeTruthy(); - sentEventContent = content; - return Promise.resolve(); - }, - ); - const previousEvent: MatrixEvent = new MatrixEvent( PollStartEvent.from( "Poll Q", @@ -312,6 +292,8 @@ describe("PollCreateDialog", () => { changeKind(dialog, M_POLL_KIND_UNDISCLOSED.name); dialog.find("button").simulate("click"); + const [, , eventType, sentEventContent] = mockClient.sendEvent.mock.calls[0]; + expect(M_POLL_START.matches(eventType)).toBeTruthy(); expect(sentEventContent).toEqual( { "m.new_content": { diff --git a/test/components/views/messages/DateSeparator-test.tsx b/test/components/views/messages/DateSeparator-test.tsx index 574a22289d..89987114b1 100644 --- a/test/components/views/messages/DateSeparator-test.tsx +++ b/test/components/views/messages/DateSeparator-test.tsx @@ -16,17 +16,18 @@ limitations under the License. import React from "react"; import { mount } from "enzyme"; +import { mocked } from "jest-mock"; import sdk from "../../../skinned-sdk"; -import * as TestUtils from "../../../test-utils"; import { formatFullDateNoTime } from "../../../../src/DateUtils"; import SettingsStore from "../../../../src/settings/SettingsStore"; import { UIFeature } from "../../../../src/settings/UIFeature"; +import MatrixClientContext from "../../../../src/contexts/MatrixClientContext"; +import { getMockClientWithEventEmitter } from "../../../test-utils"; jest.mock("../../../../src/settings/SettingsStore"); -const _DateSeparator = sdk.getComponent("views.messages.DateSeparator"); -const DateSeparator = TestUtils.wrapInMatrixClientContext(_DateSeparator); +const DateSeparator = sdk.getComponent("views.messages.DateSeparator"); describe("DateSeparator", () => { const HOUR_MS = 3600000; @@ -45,8 +46,12 @@ describe("DateSeparator", () => { } } + const mockClient = getMockClientWithEventEmitter({}); const getComponent = (props = {}) => - mount(); + mount(, { + wrappingComponent: MatrixClientContext.Provider, + wrappingComponentProps: { value: mockClient }, + }); type TestCase = [string, number, string]; const testCases: TestCase[] = [ @@ -106,7 +111,7 @@ describe("DateSeparator", () => { describe('when feature_jump_to_date is enabled', () => { beforeEach(() => { - (SettingsStore.getValue as jest.Mock) = jest.fn((arg) => { + mocked(SettingsStore).getValue.mockImplementation((arg) => { if (arg === "feature_jump_to_date") { return true; } diff --git a/test/components/views/messages/MLocationBody-test.tsx b/test/components/views/messages/MLocationBody-test.tsx index c9b4bb2f49..67c274ef9e 100644 --- a/test/components/views/messages/MLocationBody-test.tsx +++ b/test/components/views/messages/MLocationBody-test.tsx @@ -222,7 +222,7 @@ describe("MLocationBody", () => { describe("isSelfLocation", () => { it("Returns true for a full m.asset event", () => { - const content = makeLocationContent("", 0); + const content = makeLocationContent("", '0'); expect(isSelfLocation(content)).toBe(true); }); diff --git a/test/components/views/messages/MPollBody-test.tsx b/test/components/views/messages/MPollBody-test.tsx index 69cf16ab47..b2c39ece21 100644 --- a/test/components/views/messages/MPollBody-test.tsx +++ b/test/components/views/messages/MPollBody-test.tsx @@ -16,8 +16,7 @@ limitations under the License. import React from "react"; import { mount, ReactWrapper } from "enzyme"; -import { Callback, IContent, MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; -import { ISendEventResponse } from "matrix-js-sdk/src/@types/requests"; +import { MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; import { Relations } from "matrix-js-sdk/src/models/relations"; import { RelatedRelations } from "matrix-js-sdk/src/models/related-relations"; import { @@ -30,8 +29,8 @@ import { M_TEXT, POLL_ANSWER, } from "matrix-events-sdk"; +import { MockedObject } from "jest-mock"; -import * as TestUtils from "../../../test-utils"; import sdk from "../../../skinned-sdk"; import { UserVote, @@ -42,19 +41,26 @@ import { } from "../../../../src/components/views/messages/MPollBody"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import { IBodyProps } from "../../../../src/components/views/messages/IBodyProps"; +import { getMockClientWithEventEmitter } from "../../../test-utils"; +import MatrixClientContext from "../../../../src/contexts/MatrixClientContext"; const CHECKED = "mx_MPollBody_option_checked"; -const _MPollBody = sdk.getComponent("views.messages.MPollBody"); -const MPollBody = TestUtils.wrapInMatrixClientContext(_MPollBody); +const MPollBody = sdk.getComponent("views.messages.MPollBody"); -MatrixClientPeg.matrixClient = { - getUserId: () => "@me:example.com", - sendEvent: () => Promise.resolve({ "event_id": "fake_send_id" }), -}; -setRedactionAllowedForMeOnly(MatrixClientPeg.matrixClient); +const mockClient = getMockClientWithEventEmitter({ + getUserId: jest.fn().mockReturnValue("@me:example.com"), + sendEvent: jest.fn().mockReturnValue(Promise.resolve({ "event_id": "fake_send_id" })), + getRoom: jest.fn(), +}); + +setRedactionAllowedForMeOnly(mockClient); describe("MPollBody", () => { + beforeEach(() => { + mockClient.sendEvent.mockClear(); + }); + it("finds no votes if there are none", () => { expect( allVotes( @@ -110,13 +116,12 @@ describe("MPollBody", () => { ]), ]); - const matrixClient = TestUtils.createTestClient(); - setRedactionAllowedForMeOnly(matrixClient); + setRedactionAllowedForMeOnly(mockClient); expect( pollEndTs( { getRoomId: () => "$room" } as MatrixEvent, - matrixClient, + mockClient, endRelations, ), ).toBe(12); @@ -132,13 +137,12 @@ describe("MPollBody", () => { ]), ]); - const matrixClient = TestUtils.createTestClient(); - setRedactionAllowedForMeOnly(matrixClient); + setRedactionAllowedForMeOnly(mockClient); expect( pollEndTs( { getRoomId: () => "$room" } as MatrixEvent, - matrixClient, + mockClient, endRelations, ), ).toBe(13); @@ -460,7 +464,7 @@ describe("MPollBody", () => { const votes = []; const ends = []; const body = newMPollBody(votes, ends, answers); - expect(body.html()).toBe(""); + expect(body.html()).toBeNull(); }); it("renders the first 20 answers if 21 were given", () => { @@ -530,110 +534,47 @@ describe("MPollBody", () => { }); it("sends a vote event when I choose an option", () => { - const receivedEvents = []; - MatrixClientPeg.matrixClient.sendEvent = ( - roomId: string, - eventType: string, - content: IContent, - txnId?: string, - callback?: Callback, - ): Promise => { - receivedEvents.push({ roomId, eventType, content, txnId, callback }); - return Promise.resolve({ "event_id": "fake_tracked_send_id" }); - }; - const votes = []; const body = newMPollBody(votes); clickRadio(body, "wings"); - expect(receivedEvents).toEqual([ - expectedResponseEvent("wings"), - ]); + expect(mockClient.sendEvent).toHaveBeenCalledWith(...expectedResponseEventCall("wings")); }); it("sends only one vote event when I click several times", () => { - const receivedEvents = []; - MatrixClientPeg.matrixClient.sendEvent = ( - roomId: string, - eventType: string, - content: IContent, - txnId?: string, - callback?: Callback, - ): Promise => { - receivedEvents.push({ roomId, eventType, content, txnId, callback }); - return Promise.resolve({ "event_id": "fake_tracked_send_id" }); - }; - const votes = []; const body = newMPollBody(votes); clickRadio(body, "wings"); clickRadio(body, "wings"); clickRadio(body, "wings"); clickRadio(body, "wings"); - expect(receivedEvents).toEqual([ - expectedResponseEvent("wings"), - ]); + expect(mockClient.sendEvent).toHaveBeenCalledWith( + ...expectedResponseEventCall("wings"), + ); }); it("sends no vote event when I click what I already chose", () => { - const receivedEvents = []; - MatrixClientPeg.matrixClient.sendEvent = ( - roomId: string, - eventType: string, - content: IContent, - txnId?: string, - callback?: Callback, - ): Promise => { - receivedEvents.push({ roomId, eventType, content, txnId, callback }); - return Promise.resolve({ "event_id": "fake_tracked_send_id" }); - }; - const votes = [responseEvent("@me:example.com", "wings")]; const body = newMPollBody(votes); clickRadio(body, "wings"); clickRadio(body, "wings"); clickRadio(body, "wings"); clickRadio(body, "wings"); - expect(receivedEvents).toEqual([]); + expect(mockClient.sendEvent).not.toHaveBeenCalled(); }); it("sends several events when I click different options", () => { - const receivedEvents = []; - MatrixClientPeg.matrixClient.sendEvent = ( - roomId: string, - eventType: string, - content: IContent, - txnId?: string, - callback?: Callback, - ): Promise => { - receivedEvents.push({ roomId, eventType, content, txnId, callback }); - return Promise.resolve({ "event_id": "fake_tracked_send_id" }); - }; - const votes = []; const body = newMPollBody(votes); clickRadio(body, "wings"); clickRadio(body, "italian"); clickRadio(body, "poutine"); - expect(receivedEvents).toEqual([ - expectedResponseEvent("wings"), - expectedResponseEvent("italian"), - expectedResponseEvent("poutine"), - ]); + expect(mockClient.sendEvent).toHaveBeenCalledTimes(3); + expect(mockClient.sendEvent).toHaveBeenCalledWith(...expectedResponseEventCall("wings")); + expect(mockClient.sendEvent).toHaveBeenCalledWith(...expectedResponseEventCall("italian")); + expect(mockClient.sendEvent).toHaveBeenCalledWith(...expectedResponseEventCall("poutine")); }); it("sends no events when I click in an ended poll", () => { - const receivedEvents = []; - MatrixClientPeg.matrixClient.sendEvent = ( - roomId: string, - eventType: string, - content: IContent, - txnId?: string, - callback?: Callback, - ): Promise => { - receivedEvents.push({ roomId, eventType, content, txnId, callback }); - return Promise.resolve({ "event_id": "fake_tracked_send_id" }); - }; - const ends = [ endEvent("@me:example.com", 25), ]; @@ -645,7 +586,7 @@ describe("MPollBody", () => { clickEndedOption(body, "wings"); clickEndedOption(body, "italian"); clickEndedOption(body, "poutine"); - expect(receivedEvents).toEqual([]); + expect(mockClient.sendEvent).not.toHaveBeenCalled(); }); it("finds the top answer among several votes", () => { @@ -888,9 +829,8 @@ describe("MPollBody", () => { it("says poll is not ended if endRelations is undefined", () => { const pollEvent = new MatrixEvent(); - const matrixClient = TestUtils.createTestClient(); - setRedactionAllowedForMeOnly(matrixClient); - expect(isPollEnded(pollEvent, matrixClient, undefined)).toBe(false); + setRedactionAllowedForMeOnly(mockClient); + expect(isPollEnded(pollEvent, mockClient, undefined)).toBe(false); }); it("says poll is not ended if asking for relations returns undefined", () => { @@ -899,15 +839,15 @@ describe("MPollBody", () => { "room_id": "#myroom:example.com", "content": newPollStart([]), }); - MatrixClientPeg.matrixClient.getRoom = () => { + mockClient.getRoom.mockImplementation((_roomId) => { return { currentState: { maySendRedactionForEvent: (_evt: MatrixEvent, userId: string) => { return userId === "@me:example.com"; }, }, - }; - }; + } as unknown as Room; + }); const getRelationsForEvent = (eventId: string, relationType: string, eventType: string) => { expect(eventId).toBe("$mypoll"); @@ -1134,7 +1074,12 @@ function newMPollBodyFromEvent( } } } - />); + />, { + wrappingComponent: MatrixClientContext.Provider, + wrappingComponentProps: { + value: mockClient, + }, + }); } function clickRadio(wrapper: ReactWrapper, value: string) { @@ -1271,12 +1216,20 @@ function expectedResponseEvent(answer: string) { "rel_type": "m.reference", }, }, - "eventType": M_POLL_RESPONSE.name, "roomId": "#myroom:example.com", + "eventType": M_POLL_RESPONSE.name, "txnId": undefined, "callback": undefined, }; } +function expectedResponseEventCall(answer: string) { + const { + content, roomId, eventType, + } = expectedResponseEvent(answer); + return [ + roomId, eventType, content, + ]; +} function endEvent( sender = "@me:example.com", @@ -1309,8 +1262,7 @@ function runIsPollEnded(ends: MatrixEvent[]) { "content": newPollStart(), }); - const matrixClient = TestUtils.createTestClient(); - setRedactionAllowedForMeOnly(matrixClient); + setRedactionAllowedForMeOnly(mockClient); const getRelationsForEvent = (eventId: string, relationType: string, eventType: string) => { @@ -1320,7 +1272,7 @@ function runIsPollEnded(ends: MatrixEvent[]) { return newEndRelations(ends); }; - return isPollEnded(pollEvent, matrixClient, getRelationsForEvent); + return isPollEnded(pollEvent, mockClient, getRelationsForEvent); } function runFindTopAnswer(votes: MatrixEvent[], ends: MatrixEvent[]) { @@ -1347,8 +1299,8 @@ function runFindTopAnswer(votes: MatrixEvent[], ends: MatrixEvent[]) { return findTopAnswer(pollEvent, MatrixClientPeg.get(), getRelationsForEvent); } -function setRedactionAllowedForMeOnly(matrixClient: MatrixClient) { - matrixClient.getRoom = (_roomId: string) => { +function setRedactionAllowedForMeOnly(matrixClient: MockedObject) { + matrixClient.getRoom.mockImplementation((_roomId: string) => { return { currentState: { maySendRedactionForEvent: (_evt: MatrixEvent, userId: string) => { @@ -1356,7 +1308,7 @@ function setRedactionAllowedForMeOnly(matrixClient: MatrixClient) { }, }, } as Room; - }; + }); } let EVENT_ID = 0; diff --git a/test/components/views/messages/__snapshots__/DateSeparator-test.tsx.snap b/test/components/views/messages/__snapshots__/DateSeparator-test.tsx.snap index cc65b5cb1f..c1ce2c860c 100644 --- a/test/components/views/messages/__snapshots__/DateSeparator-test.tsx.snap +++ b/test/components/views/messages/__snapshots__/DateSeparator-test.tsx.snap @@ -1,116 +1,106 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`DateSeparator renders the date separator correctly 1`] = ` - - -

+

-
-
+ Today + +
+ +
`; exports[`DateSeparator when feature_jump_to_date is enabled renders the date separator correctly 1`] = ` - - -

+ -
- - -

-
-
+
+
+ + + +
+ +
`; diff --git a/test/components/views/messages/__snapshots__/MPollBody-test.tsx.snap b/test/components/views/messages/__snapshots__/MPollBody-test.tsx.snap index 6d080f7887..af37fefb7b 100644 --- a/test/components/views/messages/__snapshots__/MPollBody-test.tsx.snap +++ b/test/components/views/messages/__snapshots__/MPollBody-test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`MPollBody renders a finished poll 1`] = ` - - +

+ What should we order for the party? +

-

- What should we order for the party? -

-
- +
-
- Pizza -
-
- 0 votes -
+ Pizza +
+
+ 0 votes
- -
-
-
+
- -
-
-
- Poutine -
-
- 0 votes -
-
-
-
-
-
-
-
-
- -
-
-
- Italian -
-
- 2 votes -
-
-
-
-
-
-
-
-
- -
-
-
- Wings -
-
- 1 vote -
-
-
-
-
-
-
+ />
- Final result based on 3 votes + +
+
+
+ Poutine +
+
+ 0 votes +
+
+
+
+
+
+
+
+
+ +
+
+
+ Italian +
+
+ 2 votes +
+
+
+
+
+
+
+
+
+ +
+
+
+ Wings +
+
+ 1 vote +
+
+
+
+
+
+
- - +
+ Final result based on 3 votes +
+
+ `; exports[`MPollBody renders a finished poll with multiple winners 1`] = ` - - +

+ What should we order for the party? +

-

- What should we order for the party? -

-
- +
-
- Pizza -
-
- 2 votes -
+ Pizza +
+
+ 2 votes
- -
-
-
+
- -
-
-
- Poutine -
-
- 0 votes -
-
-
-
-
-
-
-
-
- -
-
-
- Italian -
-
- 0 votes -
-
-
-
-
-
-
-
-
- -
-
-
- Wings -
-
- 2 votes -
-
-
-
-
-
-
+ />
- Final result based on 4 votes + +
+
+
+ Poutine +
+
+ 0 votes +
+
+
+
+
+
+
+
+
+ +
+
+
+ Italian +
+
+ 0 votes +
+
+
+
+
+
+
+
+
+ +
+
+
+ Wings +
+
+ 2 votes +
+
+
+
+
+
+
- - +
+ Final result based on 4 votes +
+
+ `; exports[`MPollBody renders a finished poll with no votes 1`] = ` - - +

+ What should we order for the party? +

-

- What should we order for the party? -

-
- +
-
- Pizza -
-
- 0 votes -
+ Pizza +
+
+ 0 votes
- -
-
-
+
- -
-
-
- Poutine -
-
- 0 votes -
-
-
-
-
-
-
-
-
- -
-
-
- Italian -
-
- 0 votes -
-
-
-
-
-
-
-
-
- -
-
-
- Wings -
-
- 0 votes -
-
-
-
-
-
-
+ />
- Final result based on 0 votes + +
+
+
+ Poutine +
+
+ 0 votes +
+
+
+
+
+
+
+
+
+ +
+
+
+ Italian +
+
+ 0 votes +
+
+
+
+
+
+
+
+
+ +
+
+
+ Wings +
+
+ 0 votes +
+
+
+
+
+
+
- - +
+ Final result based on 0 votes +
+
+ `; exports[`MPollBody renders a poll that I have not voted in 1`] = ` - - +

+ What should we order for the party? +

-

- What should we order for the party? -

-
- + - -