Add test coverage (#9928)

This commit is contained in:
Michael Weimann 2023-01-18 15:49:34 +01:00 committed by GitHub
parent baa120fff3
commit 6d354e3e10
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 301 additions and 29 deletions

View file

@ -14,11 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { Room } from "matrix-js-sdk/src/matrix";
import { MatrixClient, Room } from "matrix-js-sdk/src/matrix";
import { mocked } from "jest-mock";
import WidgetStore, { IApp } from "../../src/stores/WidgetStore";
import { Container, WidgetLayoutStore } from "../../src/stores/widgets/WidgetLayoutStore";
import { stubClient } from "../test-utils";
import defaultDispatcher from "../../src/dispatcher/dispatcher";
// setup test env values
const roomId = "!room:server";
@ -34,31 +36,54 @@ const mockRoom = <Room>{
},
};
const mockApps = [
<IApp>{ roomId: roomId, id: "1" },
<IApp>{ roomId: roomId, id: "2" },
<IApp>{ roomId: roomId, id: "3" },
<IApp>{ roomId: roomId, id: "4" },
];
// fake the WidgetStore.instance to just return an object with `getApps`
jest.spyOn(WidgetStore, "instance", "get").mockReturnValue(<WidgetStore>{ getApps: (_room) => mockApps });
describe("WidgetLayoutStore", () => {
// we need to init a client so it does not error, when asking for DeviceStorage handlers (SettingsStore.setValue("Widgets.layout"))
stubClient();
let client: MatrixClient;
let store: WidgetLayoutStore;
let roomUpdateListener: (event: string) => void;
let mockApps: IApp[];
const store = WidgetLayoutStore.instance;
beforeEach(() => {
mockApps = [
<IApp>{ roomId: roomId, id: "1" },
<IApp>{ roomId: roomId, id: "2" },
<IApp>{ roomId: roomId, id: "3" },
<IApp>{ roomId: roomId, id: "4" },
];
it("all widgets should be in the right container by default", async () => {
// fake the WidgetStore.instance to just return an object with `getApps`
jest.spyOn(WidgetStore, "instance", "get").mockReturnValue({
on: jest.fn(),
off: jest.fn(),
getApps: () => mockApps,
} as unknown as WidgetStore);
});
beforeAll(() => {
// we need to init a client so it does not error, when asking for DeviceStorage handlers (SettingsStore.setValue("Widgets.layout"))
client = stubClient();
roomUpdateListener = jest.fn();
// @ts-ignore bypass private ctor for tests
store = new WidgetLayoutStore();
store.addListener(`update_${roomId}`, roomUpdateListener);
});
afterAll(() => {
store.removeListener(`update_${roomId}`, roomUpdateListener);
});
it("all widgets should be in the right container by default", () => {
store.recalculateRoom(mockRoom);
expect(store.getContainerWidgets(mockRoom, Container.Right).length).toStrictEqual(mockApps.length);
});
it("add widget to top container", async () => {
store.recalculateRoom(mockRoom);
store.moveToContainer(mockRoom, mockApps[0], Container.Top);
expect(store.getContainerWidgets(mockRoom, Container.Top)).toStrictEqual([mockApps[0]]);
expect(store.getContainerHeight(mockRoom, Container.Top)).toBeNull();
});
it("add three widgets to top container", async () => {
store.recalculateRoom(mockRoom);
store.moveToContainer(mockRoom, mockApps[0], Container.Top);
@ -68,6 +93,7 @@ describe("WidgetLayoutStore", () => {
new Set([mockApps[0], mockApps[1], mockApps[2]]),
);
});
it("cannot add more than three widgets to top container", async () => {
store.recalculateRoom(mockRoom);
store.moveToContainer(mockRoom, mockApps[0], Container.Top);
@ -75,6 +101,7 @@ describe("WidgetLayoutStore", () => {
store.moveToContainer(mockRoom, mockApps[2], Container.Top);
expect(store.canAddToContainer(mockRoom, Container.Top)).toEqual(false);
});
it("remove pins when maximising (other widget)", async () => {
store.recalculateRoom(mockRoom);
store.moveToContainer(mockRoom, mockApps[0], Container.Top);
@ -87,6 +114,7 @@ describe("WidgetLayoutStore", () => {
);
expect(store.getContainerWidgets(mockRoom, Container.Center)).toEqual([mockApps[3]]);
});
it("remove pins when maximising (one of the pinned widgets)", async () => {
store.recalculateRoom(mockRoom);
store.moveToContainer(mockRoom, mockApps[0], Container.Top);
@ -99,6 +127,7 @@ describe("WidgetLayoutStore", () => {
new Set([mockApps[1], mockApps[2], mockApps[3]]),
);
});
it("remove maximised when pinning (other widget)", async () => {
store.recalculateRoom(mockRoom);
store.moveToContainer(mockRoom, mockApps[0], Container.Center);
@ -109,6 +138,7 @@ describe("WidgetLayoutStore", () => {
new Set([mockApps[2], mockApps[3], mockApps[0]]),
);
});
it("remove maximised when pinning (same widget)", async () => {
store.recalculateRoom(mockRoom);
store.moveToContainer(mockRoom, mockApps[0], Container.Center);
@ -119,4 +149,118 @@ describe("WidgetLayoutStore", () => {
new Set([mockApps[2], mockApps[3], mockApps[1]]),
);
});
it("should recalculate all rooms when the client is ready", async () => {
mocked(client.getVisibleRooms).mockReturnValue([mockRoom]);
await store.start();
expect(roomUpdateListener).toHaveBeenCalled();
expect(store.getContainerWidgets(mockRoom, Container.Top)).toEqual([mockApps[0]]);
expect(store.getContainerWidgets(mockRoom, Container.Center)).toEqual([]);
expect(store.getContainerWidgets(mockRoom, Container.Right)).toEqual([mockApps[1], mockApps[2], mockApps[3]]);
});
it("should clear the layout and emit an update if there are no longer apps in the room", () => {
store.recalculateRoom(mockRoom);
mocked(roomUpdateListener).mockClear();
jest.spyOn(WidgetStore, "instance", "get").mockReturnValue(<WidgetStore>(
({ getApps: (): IApp[] => [] } as unknown as WidgetStore)
));
store.recalculateRoom(mockRoom);
expect(roomUpdateListener).toHaveBeenCalled();
expect(store.getContainerWidgets(mockRoom, Container.Top)).toEqual([]);
expect(store.getContainerWidgets(mockRoom, Container.Center)).toEqual([]);
expect(store.getContainerWidgets(mockRoom, Container.Right)).toEqual([]);
});
it("should clear the layout if the client is not viable", () => {
store.recalculateRoom(mockRoom);
defaultDispatcher.dispatch(
{
action: "on_client_not_viable",
},
true,
);
expect(store.getContainerWidgets(mockRoom, Container.Top)).toEqual([]);
expect(store.getContainerWidgets(mockRoom, Container.Center)).toEqual([]);
expect(store.getContainerWidgets(mockRoom, Container.Right)).toEqual([]);
});
it("should return the expected resizer distributions", () => {
// this only works for top widgets
store.recalculateRoom(mockRoom);
store.moveToContainer(mockRoom, mockApps[0], Container.Top);
store.moveToContainer(mockRoom, mockApps[1], Container.Top);
expect(store.getResizerDistributions(mockRoom, Container.Top)).toEqual(["50.0%"]);
});
it("should set and return container height", () => {
store.recalculateRoom(mockRoom);
store.moveToContainer(mockRoom, mockApps[0], Container.Top);
store.moveToContainer(mockRoom, mockApps[1], Container.Top);
store.setContainerHeight(mockRoom, Container.Top, 23);
expect(store.getContainerHeight(mockRoom, Container.Top)).toBe(23);
});
it("should move a widget within a container", () => {
store.recalculateRoom(mockRoom);
store.moveToContainer(mockRoom, mockApps[0], Container.Top);
store.moveToContainer(mockRoom, mockApps[1], Container.Top);
store.moveToContainer(mockRoom, mockApps[2], Container.Top);
expect(store.getContainerWidgets(mockRoom, Container.Top)).toStrictEqual([
mockApps[0],
mockApps[1],
mockApps[2],
]);
store.moveWithinContainer(mockRoom, Container.Top, mockApps[0], 1);
expect(store.getContainerWidgets(mockRoom, Container.Top)).toStrictEqual([
mockApps[1],
mockApps[0],
mockApps[2],
]);
});
it("should copy the layout to the room", async () => {
await store.start();
store.recalculateRoom(mockRoom);
store.moveToContainer(mockRoom, mockApps[0], Container.Top);
store.copyLayoutToRoom(mockRoom);
expect(mocked(client.sendStateEvent).mock.calls).toMatchInlineSnapshot(`
[
[
"!room:server",
"io.element.widgets.layout",
{
"widgets": {
"1": {
"container": "top",
"height": 23,
"index": 2,
"width": 64,
},
"2": {
"container": "top",
"height": 23,
"index": 0,
"width": 10,
},
"3": {
"container": "top",
"height": 23,
"index": 1,
"width": 26,
},
"4": {
"container": "right",
},
},
},
"",
],
]
`);
});
});