Skip to content

Commit

Permalink
Write more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
robintown committed Jan 15, 2025
1 parent eab2b9b commit dfabea6
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/stores/widgets/StopGapWidgetDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ export class StopGapWidgetDriver extends WidgetDriver {
if (room === null) return [];
const results: MatrixEvent[] = [];
const events = room.getLiveTimeline().getEvents(); // timelines are most recent last
for (let i = events.length - 1; i > 0; i--) {
for (let i = events.length - 1; i >= 0; i--) {
const ev = events[i];
if (results.length >= limit) break;
if (since !== undefined && ev.getId() === since) break;
Expand Down
69 changes: 68 additions & 1 deletion test/unit-tests/stores/widgets/StopGapWidget-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/

import { mocked, MockedObject } from "jest-mock";
import { mocked, MockedFunction, MockedObject } from "jest-mock";
import { last } from "lodash";
import {
MatrixEvent,
Expand All @@ -15,15 +15,20 @@ import {
EventTimeline,
EventType,
MatrixEventEvent,
RoomStateEvent,
RoomState,
} from "matrix-js-sdk/src/matrix";
import { ClientWidgetApi, WidgetApiFromWidgetAction } from "matrix-widget-api";
import { waitFor } from "jest-matrix-react";
import { Optional } from "matrix-events-sdk";

import { stubClient, mkRoom, mkEvent } from "../../../test-utils";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
import { StopGapWidget } from "../../../../src/stores/widgets/StopGapWidget";
import ActiveWidgetStore from "../../../../src/stores/ActiveWidgetStore";
import SettingsStore from "../../../../src/settings/SettingsStore";
import { SdkContextClass } from "../../../../src/contexts/SDKContext";
import { UPDATE_EVENT } from "../../../../src/stores/AsyncStore";

jest.mock("matrix-widget-api/lib/ClientWidgetApi");

Expand Down Expand Up @@ -53,6 +58,7 @@ describe("StopGapWidget", () => {
// Start messaging without an iframe, since ClientWidgetApi is mocked
widget.startMessaging(null as unknown as HTMLIFrameElement);
messaging = mocked(last(mocked(ClientWidgetApi).mock.instances)!);
messaging.feedStateUpdate.mockResolvedValue();
});

afterEach(() => {
Expand Down Expand Up @@ -84,6 +90,20 @@ describe("StopGapWidget", () => {
expect(messaging.feedToDevice).toHaveBeenCalledWith(event.getEffectiveEvent(), false);
});

it("feeds incoming state updates to the widget", () => {
const event = mkEvent({
event: true,
type: "org.example.foo",
skey: "",
user: "@alice:example.org",
content: { hello: "world" },
room: "!1:example.org",
});

client.emit(RoomStateEvent.Events, event, {} as unknown as RoomState, null);
expect(messaging.feedStateUpdate).toHaveBeenCalledWith(event.getEffectiveEvent());
});

describe("feed event", () => {
let event1: MatrixEvent;
let event2: MatrixEvent;
Expand Down Expand Up @@ -223,6 +243,7 @@ describe("StopGapWidget", () => {
});
});
});

describe("StopGapWidget with stickyPromise", () => {
let client: MockedObject<MatrixClient>;
let widget: StopGapWidget;
Expand Down Expand Up @@ -288,3 +309,49 @@ describe("StopGapWidget with stickyPromise", () => {
waitFor(() => expect(setPersistenceSpy).toHaveBeenCalled(), { interval: 5 });
});
});

describe("StopGapWidget as an account widget", () => {
let widget: StopGapWidget;
let messaging: MockedObject<ClientWidgetApi>;
let getRoomId: MockedFunction<() => Optional<string>>;

beforeEach(() => {
stubClient();
// I give up, getting the return type of spyOn right is hopeless
getRoomId = jest.spyOn(SdkContextClass.instance.roomViewStore, "getRoomId") as unknown as MockedFunction<
() => Optional<string>
>;
getRoomId.mockReturnValue("!1:example.org");

widget = new StopGapWidget({
app: {
id: "test",
creatorUserId: "@alice:example.org",
type: "example",
url: "https://example.org?user-id=$matrix_user_id&device-id=$org.matrix.msc3819.matrix_device_id&base-url=$org.matrix.msc4039.matrix_base_url&theme=$org.matrix.msc2873.client_theme",
roomId: "!1:example.org",
},
userId: "@alice:example.org",
creatorUserId: "@alice:example.org",
waitForIframeLoad: true,
userWidget: false,
});
// Start messaging without an iframe, since ClientWidgetApi is mocked
widget.startMessaging(null as unknown as HTMLIFrameElement);
messaging = mocked(last(mocked(ClientWidgetApi).mock.instances)!);
});

afterEach(() => {
widget.stopMessaging();
getRoomId.mockRestore();
});

it("updates viewed room", () => {
expect(messaging.setViewedRoomId).toHaveBeenCalledTimes(1);
expect(messaging.setViewedRoomId).toHaveBeenLastCalledWith("!1:example.org");
getRoomId.mockReturnValue("!2:example.org");
SdkContextClass.instance.roomViewStore.emit(UPDATE_EVENT);
expect(messaging.setViewedRoomId).toHaveBeenCalledTimes(2);
expect(messaging.setViewedRoomId).toHaveBeenLastCalledWith("!2:example.org");
});
});
106 changes: 105 additions & 1 deletion test/unit-tests/stores/widgets/StopGapWidgetDriver-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
MatrixEvent,
MsgType,
RelationType,
Room,
} from "matrix-js-sdk/src/matrix";
import {
Widget,
Expand All @@ -38,7 +39,7 @@ import {
import { SdkContextClass } from "../../../../src/contexts/SDKContext";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
import { StopGapWidgetDriver } from "../../../../src/stores/widgets/StopGapWidgetDriver";
import { stubClient } from "../../../test-utils";
import { mkEvent, stubClient } from "../../../test-utils";
import { ModuleRunner } from "../../../../src/modules/ModuleRunner";
import dis from "../../../../src/dispatcher/dispatcher";
import Modal from "../../../../src/Modal";
Expand Down Expand Up @@ -692,4 +693,107 @@ describe("StopGapWidgetDriver", () => {
await expect(file.text()).resolves.toEqual("test contents");
});
});

describe("readRoomTimeline", () => {
const event1 = mkEvent({
event: true,
id: "$event-id1",
type: "org.example.foo",
user: "@alice:example.org",
content: { hello: "world" },
room: "!1:example.org",
});
const event2 = mkEvent({
event: true,
id: "$event-id2",
type: "org.example.foo",
user: "@alice:example.org",
content: { hello: "world" },
room: "!1:example.org",
});
let driver: WidgetDriver;

beforeEach(() => {
driver = mkDefaultDriver();
client.getRoom.mockReturnValue({
getLiveTimeline: () => ({ getEvents: () => [event1, event2] }),
} as unknown as Room);
});

it("reads all events", async () => {
expect(
await driver.readRoomTimeline("!1:example.org", "org.example.foo", undefined, undefined, 10, undefined),
).toEqual([event2, event1].map((e) => e.getEffectiveEvent()));
});

it("reads up to a limit", async () => {
expect(
await driver.readRoomTimeline("!1:example.org", "org.example.foo", undefined, undefined, 1, undefined),
).toEqual([event2.getEffectiveEvent()]);
});

it("reads up to a specific event", async () => {
expect(
await driver.readRoomTimeline(
"!1:example.org",
"org.example.foo",
undefined,
undefined,
10,
event1.getId(),
),
).toEqual([event2.getEffectiveEvent()]);
});
});

describe("readRoomState", () => {
const event1 = mkEvent({
event: true,
id: "$event-id1",
type: "org.example.foo",
user: "@alice:example.org",
content: { hello: "world" },
skey: "1",
room: "!1:example.org",
});
const event2 = mkEvent({
event: true,
id: "$event-id2",
type: "org.example.foo",
user: "@alice:example.org",
content: { hello: "world" },
skey: "2",
room: "!1:example.org",
});
let driver: WidgetDriver;
let getStateEvents: jest.Mock;

beforeEach(() => {
driver = mkDefaultDriver();
getStateEvents = jest.fn();
client.getRoom.mockReturnValue({
getLiveTimeline: () => ({ getState: () => ({ getStateEvents }) }),
} as unknown as Room);
});

it("reads a specific state key", async () => {
getStateEvents.mockImplementation((eventType, stateKey) => {
if (eventType === "org.example.foo" && stateKey === "1") return event1;
return undefined;
});
expect(await driver.readRoomState("!1:example.org", "org.example.foo", "1")).toEqual([
event1.getEffectiveEvent(),
]);
});

it("reads all state keys", async () => {
getStateEvents.mockImplementation((eventType, stateKey) => {
if (eventType === "org.example.foo" && stateKey === undefined) return [event1, event2];
return [];
});
expect(await driver.readRoomState("!1:example.org", "org.example.foo", undefined)).toEqual(
[event1, event2].map((e) => e.getEffectiveEvent()),
);
});
});
});

0 comments on commit dfabea6

Please sign in to comment.