Merge branch 'develop' of github.com:matrix-org/matrix-react-sdk into t3chguy/fix/18088
Conflicts: src/components/structures/LoggedInView.tsx src/stores/SpaceStore.tsx
This commit is contained in:
commit
a688e5b8b3
318 changed files with 7386 additions and 4032 deletions
129
test/TextForEvent-test.ts
Normal file
129
test/TextForEvent-test.ts
Normal file
|
@ -0,0 +1,129 @@
|
|||
import './skinned-sdk';
|
||||
|
||||
import { textForEvent } from "../src/TextForEvent";
|
||||
import { MatrixEvent } from "matrix-js-sdk";
|
||||
import SettingsStore from "../src/settings/SettingsStore";
|
||||
import { SettingLevel } from "../src/settings/SettingLevel";
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
function mockPinnedEvent(
|
||||
pinnedMessageIds?: string[],
|
||||
prevPinnedMessageIds?: string[],
|
||||
): MatrixEvent {
|
||||
return new MatrixEvent({
|
||||
type: "m.room.pinned_events",
|
||||
state_key: "",
|
||||
sender: "@foo:example.com",
|
||||
content: {
|
||||
pinned: pinnedMessageIds,
|
||||
},
|
||||
prev_content: {
|
||||
pinned: prevPinnedMessageIds,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Helper function that renders a component to a plain text string.
|
||||
// Once snapshots are introduced in tests, this function will no longer be necessary,
|
||||
// and should be replaced with snapshots.
|
||||
function renderComponent(component): string {
|
||||
const serializeObject = (object): string => {
|
||||
if (typeof object === 'string') {
|
||||
return object === ' ' ? '' : object;
|
||||
}
|
||||
|
||||
if (Array.isArray(object) && object.length === 1 && typeof object[0] === 'string') {
|
||||
return object[0];
|
||||
}
|
||||
|
||||
if (object['type'] !== undefined && typeof object['children'] !== undefined) {
|
||||
return serializeObject(object.children);
|
||||
}
|
||||
|
||||
if (!Array.isArray(object)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return object.map(child => {
|
||||
return serializeObject(child);
|
||||
}).join('');
|
||||
};
|
||||
|
||||
return serializeObject(component.toJSON());
|
||||
}
|
||||
|
||||
describe('TextForEvent', () => {
|
||||
describe("TextForPinnedEvent", () => {
|
||||
SettingsStore.setValue("feature_pinning", null, SettingLevel.DEVICE, true);
|
||||
|
||||
it("mentions message when a single message was pinned, with no previously pinned messages", () => {
|
||||
const event = mockPinnedEvent(['message-1']);
|
||||
const plainText = textForEvent(event);
|
||||
const component = renderer.create(textForEvent(event, true));
|
||||
|
||||
const expectedText = "@foo:example.com pinned a message to this room. See all pinned messages.";
|
||||
expect(plainText).toBe(expectedText);
|
||||
expect(renderComponent(component)).toBe(expectedText);
|
||||
});
|
||||
|
||||
it("mentions message when a single message was pinned, with multiple previously pinned messages", () => {
|
||||
const event = mockPinnedEvent(['message-1', 'message-2', 'message-3'], ['message-1', 'message-2']);
|
||||
const plainText = textForEvent(event);
|
||||
const component = renderer.create(textForEvent(event, true));
|
||||
|
||||
const expectedText = "@foo:example.com pinned a message to this room. See all pinned messages.";
|
||||
expect(plainText).toBe(expectedText);
|
||||
expect(renderComponent(component)).toBe(expectedText);
|
||||
});
|
||||
|
||||
it("mentions message when a single message was unpinned, with a single message previously pinned", () => {
|
||||
const event = mockPinnedEvent([], ['message-1']);
|
||||
const plainText = textForEvent(event);
|
||||
const component = renderer.create(textForEvent(event, true));
|
||||
|
||||
const expectedText = "@foo:example.com unpinned a message from this room. See all pinned messages.";
|
||||
expect(plainText).toBe(expectedText);
|
||||
expect(renderComponent(component)).toBe(expectedText);
|
||||
});
|
||||
|
||||
it("mentions message when a single message was unpinned, with multiple previously pinned messages", () => {
|
||||
const event = mockPinnedEvent(['message-2'], ['message-1', 'message-2']);
|
||||
const plainText = textForEvent(event);
|
||||
const component = renderer.create(textForEvent(event, true));
|
||||
|
||||
const expectedText = "@foo:example.com unpinned a message from this room. See all pinned messages.";
|
||||
expect(plainText).toBe(expectedText);
|
||||
expect(renderComponent(component)).toBe(expectedText);
|
||||
});
|
||||
|
||||
it("shows generic text when multiple messages were pinned", () => {
|
||||
const event = mockPinnedEvent(['message-1', 'message-2', 'message-3'], ['message-1']);
|
||||
const plainText = textForEvent(event);
|
||||
const component = renderer.create(textForEvent(event, true));
|
||||
|
||||
const expectedText = "@foo:example.com changed the pinned messages for the room.";
|
||||
expect(plainText).toBe(expectedText);
|
||||
expect(renderComponent(component)).toBe(expectedText);
|
||||
});
|
||||
|
||||
it("shows generic text when multiple messages were unpinned", () => {
|
||||
const event = mockPinnedEvent(['message-3'], ['message-1', 'message-2', 'message-3']);
|
||||
const plainText = textForEvent(event);
|
||||
const component = renderer.create(textForEvent(event, true));
|
||||
|
||||
const expectedText = "@foo:example.com changed the pinned messages for the room.";
|
||||
expect(plainText).toBe(expectedText);
|
||||
expect(renderComponent(component)).toBe(expectedText);
|
||||
});
|
||||
|
||||
it("shows generic text when one message was pinned, and another unpinned", () => {
|
||||
const event = mockPinnedEvent(['message-2'], ['message-1']);
|
||||
const plainText = textForEvent(event);
|
||||
const component = renderer.create(textForEvent(event, true));
|
||||
|
||||
const expectedText = "@foo:example.com changed the pinned messages for the room.";
|
||||
expect(plainText).toBe(expectedText);
|
||||
expect(renderComponent(component)).toBe(expectedText);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -46,7 +46,7 @@ describe('<SendMessageComposer/>', () => {
|
|||
const model = new EditorModel([], createPartCreator(), createRenderer());
|
||||
model.update("hello world", "insertText", { offset: 11, atNodeEnd: true });
|
||||
|
||||
const content = createMessageContent(model, permalinkCreator);
|
||||
const content = createMessageContent(model, null, false, permalinkCreator);
|
||||
|
||||
expect(content).toEqual({
|
||||
body: "hello world",
|
||||
|
@ -58,7 +58,7 @@ describe('<SendMessageComposer/>', () => {
|
|||
const model = new EditorModel([], createPartCreator(), createRenderer());
|
||||
model.update("hello *world*", "insertText", { offset: 13, atNodeEnd: true });
|
||||
|
||||
const content = createMessageContent(model, permalinkCreator);
|
||||
const content = createMessageContent(model, null, false, permalinkCreator);
|
||||
|
||||
expect(content).toEqual({
|
||||
body: "hello *world*",
|
||||
|
@ -72,7 +72,7 @@ describe('<SendMessageComposer/>', () => {
|
|||
const model = new EditorModel([], createPartCreator(), createRenderer());
|
||||
model.update("/me blinks __quickly__", "insertText", { offset: 22, atNodeEnd: true });
|
||||
|
||||
const content = createMessageContent(model, permalinkCreator);
|
||||
const content = createMessageContent(model, null, false, permalinkCreator);
|
||||
|
||||
expect(content).toEqual({
|
||||
body: "blinks __quickly__",
|
||||
|
@ -86,7 +86,7 @@ describe('<SendMessageComposer/>', () => {
|
|||
const model = new EditorModel([], createPartCreator(), createRenderer());
|
||||
model.update("//dev/null is my favourite place", "insertText", { offset: 32, atNodeEnd: true });
|
||||
|
||||
const content = createMessageContent(model, permalinkCreator);
|
||||
const content = createMessageContent(model, null, false, permalinkCreator);
|
||||
|
||||
expect(content).toEqual({
|
||||
body: "/dev/null is my favourite place",
|
||||
|
|
|
@ -561,7 +561,7 @@ describe("SpaceStore", () => {
|
|||
]);
|
||||
mkSpace(space3).getMyMembership.mockReturnValue("invite");
|
||||
await run();
|
||||
await store.setActiveSpace(null);
|
||||
store.setActiveSpace(null);
|
||||
expect(store.activeSpace).toBe(null);
|
||||
});
|
||||
afterEach(() => {
|
||||
|
@ -569,31 +569,31 @@ describe("SpaceStore", () => {
|
|||
});
|
||||
|
||||
it("switch to home space", async () => {
|
||||
await store.setActiveSpace(client.getRoom(space1));
|
||||
store.setActiveSpace(client.getRoom(space1));
|
||||
fn.mockClear();
|
||||
|
||||
await store.setActiveSpace(null);
|
||||
store.setActiveSpace(null);
|
||||
expect(fn).toHaveBeenCalledWith(UPDATE_SELECTED_SPACE, null);
|
||||
expect(store.activeSpace).toBe(null);
|
||||
});
|
||||
|
||||
it("switch to invited space", async () => {
|
||||
const space = client.getRoom(space3);
|
||||
await store.setActiveSpace(space);
|
||||
store.setActiveSpace(space);
|
||||
expect(fn).toHaveBeenCalledWith(UPDATE_SELECTED_SPACE, space);
|
||||
expect(store.activeSpace).toBe(space);
|
||||
});
|
||||
|
||||
it("switch to top level space", async () => {
|
||||
const space = client.getRoom(space1);
|
||||
await store.setActiveSpace(space);
|
||||
store.setActiveSpace(space);
|
||||
expect(fn).toHaveBeenCalledWith(UPDATE_SELECTED_SPACE, space);
|
||||
expect(store.activeSpace).toBe(space);
|
||||
});
|
||||
|
||||
it("switch to subspace", async () => {
|
||||
const space = client.getRoom(space2);
|
||||
await store.setActiveSpace(space);
|
||||
store.setActiveSpace(space);
|
||||
expect(fn).toHaveBeenCalledWith(UPDATE_SELECTED_SPACE, space);
|
||||
expect(store.activeSpace).toBe(space);
|
||||
});
|
||||
|
@ -601,7 +601,7 @@ describe("SpaceStore", () => {
|
|||
it("switch to unknown space is a nop", async () => {
|
||||
expect(store.activeSpace).toBe(null);
|
||||
const space = client.getRoom(room1); // not a space
|
||||
await store.setActiveSpace(space);
|
||||
store.setActiveSpace(space);
|
||||
expect(fn).not.toHaveBeenCalledWith(UPDATE_SELECTED_SPACE, space);
|
||||
expect(store.activeSpace).toBe(null);
|
||||
});
|
||||
|
@ -634,59 +634,59 @@ describe("SpaceStore", () => {
|
|||
};
|
||||
|
||||
it("last viewed room in target space is the current viewed and in both spaces", async () => {
|
||||
await store.setActiveSpace(client.getRoom(space1));
|
||||
store.setActiveSpace(client.getRoom(space1));
|
||||
viewRoom(room2);
|
||||
await store.setActiveSpace(client.getRoom(space2));
|
||||
store.setActiveSpace(client.getRoom(space2));
|
||||
viewRoom(room2);
|
||||
await store.setActiveSpace(client.getRoom(space1));
|
||||
store.setActiveSpace(client.getRoom(space1));
|
||||
expect(getCurrentRoom()).toBe(room2);
|
||||
});
|
||||
|
||||
it("last viewed room in target space is in the current space", async () => {
|
||||
await store.setActiveSpace(client.getRoom(space1));
|
||||
store.setActiveSpace(client.getRoom(space1));
|
||||
viewRoom(room2);
|
||||
await store.setActiveSpace(client.getRoom(space2));
|
||||
store.setActiveSpace(client.getRoom(space2));
|
||||
expect(getCurrentRoom()).toBe(space2);
|
||||
await store.setActiveSpace(client.getRoom(space1));
|
||||
store.setActiveSpace(client.getRoom(space1));
|
||||
expect(getCurrentRoom()).toBe(room2);
|
||||
});
|
||||
|
||||
it("last viewed room in target space is not in the current space", async () => {
|
||||
await store.setActiveSpace(client.getRoom(space1));
|
||||
store.setActiveSpace(client.getRoom(space1));
|
||||
viewRoom(room1);
|
||||
await store.setActiveSpace(client.getRoom(space2));
|
||||
store.setActiveSpace(client.getRoom(space2));
|
||||
viewRoom(room2);
|
||||
await store.setActiveSpace(client.getRoom(space1));
|
||||
store.setActiveSpace(client.getRoom(space1));
|
||||
expect(getCurrentRoom()).toBe(room1);
|
||||
});
|
||||
|
||||
it("last viewed room is target space is not known", async () => {
|
||||
await store.setActiveSpace(client.getRoom(space1));
|
||||
store.setActiveSpace(client.getRoom(space1));
|
||||
viewRoom(room1);
|
||||
localStorage.setItem(`mx_space_context_${space2}`, orphan2);
|
||||
await store.setActiveSpace(client.getRoom(space2));
|
||||
store.setActiveSpace(client.getRoom(space2));
|
||||
expect(getCurrentRoom()).toBe(space2);
|
||||
});
|
||||
|
||||
it("last viewed room is target space is no longer in that space", async () => {
|
||||
await store.setActiveSpace(client.getRoom(space1));
|
||||
store.setActiveSpace(client.getRoom(space1));
|
||||
viewRoom(room1);
|
||||
localStorage.setItem(`mx_space_context_${space2}`, room1);
|
||||
await store.setActiveSpace(client.getRoom(space2));
|
||||
store.setActiveSpace(client.getRoom(space2));
|
||||
expect(getCurrentRoom()).toBe(space2); // Space home instead of room1
|
||||
});
|
||||
|
||||
it("no last viewed room in target space", async () => {
|
||||
await store.setActiveSpace(client.getRoom(space1));
|
||||
store.setActiveSpace(client.getRoom(space1));
|
||||
viewRoom(room1);
|
||||
await store.setActiveSpace(client.getRoom(space2));
|
||||
store.setActiveSpace(client.getRoom(space2));
|
||||
expect(getCurrentRoom()).toBe(space2);
|
||||
});
|
||||
|
||||
it("no last viewed room in home space", async () => {
|
||||
await store.setActiveSpace(client.getRoom(space1));
|
||||
store.setActiveSpace(client.getRoom(space1));
|
||||
viewRoom(room1);
|
||||
await store.setActiveSpace(null);
|
||||
store.setActiveSpace(null);
|
||||
expect(getCurrentRoom()).toBeNull(); // Home
|
||||
});
|
||||
});
|
||||
|
@ -714,28 +714,28 @@ describe("SpaceStore", () => {
|
|||
|
||||
it("no switch required, room is in current space", async () => {
|
||||
viewRoom(room1);
|
||||
await store.setActiveSpace(client.getRoom(space1), false);
|
||||
store.setActiveSpace(client.getRoom(space1), false);
|
||||
viewRoom(room2);
|
||||
expect(store.activeSpace).toBe(client.getRoom(space1));
|
||||
});
|
||||
|
||||
it("switch to canonical parent space for room", async () => {
|
||||
viewRoom(room1);
|
||||
await store.setActiveSpace(client.getRoom(space2), false);
|
||||
store.setActiveSpace(client.getRoom(space2), false);
|
||||
viewRoom(room2);
|
||||
expect(store.activeSpace).toBe(client.getRoom(space2));
|
||||
});
|
||||
|
||||
it("switch to first containing space for room", async () => {
|
||||
viewRoom(room2);
|
||||
await store.setActiveSpace(client.getRoom(space2), false);
|
||||
store.setActiveSpace(client.getRoom(space2), false);
|
||||
viewRoom(room3);
|
||||
expect(store.activeSpace).toBe(client.getRoom(space1));
|
||||
});
|
||||
|
||||
it("switch to home for orphaned room", async () => {
|
||||
viewRoom(room1);
|
||||
await store.setActiveSpace(client.getRoom(space1), false);
|
||||
store.setActiveSpace(client.getRoom(space1), false);
|
||||
viewRoom(orphan1);
|
||||
expect(store.activeSpace).toBeNull();
|
||||
});
|
||||
|
@ -743,7 +743,7 @@ describe("SpaceStore", () => {
|
|||
it("when switching rooms in the all rooms home space don't switch to related space", async () => {
|
||||
await setShowAllRooms(true);
|
||||
viewRoom(room2);
|
||||
await store.setActiveSpace(null, false);
|
||||
store.setActiveSpace(null, false);
|
||||
viewRoom(room1);
|
||||
expect(store.activeSpace).toBeNull();
|
||||
});
|
||||
|
|
|
@ -56,7 +56,7 @@ describe("SpaceWatcher", () => {
|
|||
beforeEach(async () => {
|
||||
filter = null;
|
||||
store.removeAllListeners();
|
||||
await store.setActiveSpace(null);
|
||||
store.setActiveSpace(null);
|
||||
client.getVisibleRooms.mockReturnValue(rooms = []);
|
||||
|
||||
space1 = mkSpace(space1Id);
|
||||
|
@ -94,7 +94,7 @@ describe("SpaceWatcher", () => {
|
|||
await setShowAllRooms(true);
|
||||
new SpaceWatcher(mockRoomListStore);
|
||||
|
||||
await SpaceStore.instance.setActiveSpace(space1);
|
||||
SpaceStore.instance.setActiveSpace(space1);
|
||||
|
||||
expect(filter).toBeInstanceOf(SpaceFilterCondition);
|
||||
expect(filter["space"]).toBe(space1);
|
||||
|
@ -113,7 +113,7 @@ describe("SpaceWatcher", () => {
|
|||
await setShowAllRooms(false);
|
||||
new SpaceWatcher(mockRoomListStore);
|
||||
|
||||
await SpaceStore.instance.setActiveSpace(space1);
|
||||
SpaceStore.instance.setActiveSpace(space1);
|
||||
|
||||
expect(filter).toBeInstanceOf(SpaceFilterCondition);
|
||||
expect(filter["space"]).toBe(space1);
|
||||
|
@ -123,22 +123,22 @@ describe("SpaceWatcher", () => {
|
|||
await setShowAllRooms(true);
|
||||
new SpaceWatcher(mockRoomListStore);
|
||||
|
||||
await SpaceStore.instance.setActiveSpace(space1);
|
||||
SpaceStore.instance.setActiveSpace(space1);
|
||||
expect(filter).toBeInstanceOf(SpaceFilterCondition);
|
||||
expect(filter["space"]).toBe(space1);
|
||||
await SpaceStore.instance.setActiveSpace(null);
|
||||
SpaceStore.instance.setActiveSpace(null);
|
||||
|
||||
expect(filter).toBeNull();
|
||||
});
|
||||
|
||||
it("updates filter correctly for space -> home transition", async () => {
|
||||
await setShowAllRooms(false);
|
||||
await SpaceStore.instance.setActiveSpace(space1);
|
||||
SpaceStore.instance.setActiveSpace(space1);
|
||||
|
||||
new SpaceWatcher(mockRoomListStore);
|
||||
expect(filter).toBeInstanceOf(SpaceFilterCondition);
|
||||
expect(filter["space"]).toBe(space1);
|
||||
await SpaceStore.instance.setActiveSpace(null);
|
||||
SpaceStore.instance.setActiveSpace(null);
|
||||
|
||||
expect(filter).toBeInstanceOf(SpaceFilterCondition);
|
||||
expect(filter["space"]).toBe(null);
|
||||
|
@ -146,12 +146,12 @@ describe("SpaceWatcher", () => {
|
|||
|
||||
it("updates filter correctly for space -> space transition", async () => {
|
||||
await setShowAllRooms(false);
|
||||
await SpaceStore.instance.setActiveSpace(space1);
|
||||
SpaceStore.instance.setActiveSpace(space1);
|
||||
|
||||
new SpaceWatcher(mockRoomListStore);
|
||||
expect(filter).toBeInstanceOf(SpaceFilterCondition);
|
||||
expect(filter["space"]).toBe(space1);
|
||||
await SpaceStore.instance.setActiveSpace(space2);
|
||||
SpaceStore.instance.setActiveSpace(space2);
|
||||
|
||||
expect(filter).toBeInstanceOf(SpaceFilterCondition);
|
||||
expect(filter["space"]).toBe(space2);
|
||||
|
@ -159,7 +159,7 @@ describe("SpaceWatcher", () => {
|
|||
|
||||
it("doesn't change filter when changing showAllRooms mode to true", async () => {
|
||||
await setShowAllRooms(false);
|
||||
await SpaceStore.instance.setActiveSpace(space1);
|
||||
SpaceStore.instance.setActiveSpace(space1);
|
||||
|
||||
new SpaceWatcher(mockRoomListStore);
|
||||
expect(filter).toBeInstanceOf(SpaceFilterCondition);
|
||||
|
@ -172,7 +172,7 @@ describe("SpaceWatcher", () => {
|
|||
|
||||
it("doesn't change filter when changing showAllRooms mode to false", async () => {
|
||||
await setShowAllRooms(true);
|
||||
await SpaceStore.instance.setActiveSpace(space1);
|
||||
SpaceStore.instance.setActiveSpace(space1);
|
||||
|
||||
new SpaceWatcher(mockRoomListStore);
|
||||
expect(filter).toBeInstanceOf(SpaceFilterCondition);
|
||||
|
|
|
@ -85,9 +85,8 @@ export function createTestClient() {
|
|||
generateClientSecret: () => "t35tcl1Ent5ECr3T",
|
||||
isGuest: () => false,
|
||||
isCryptoEnabled: () => false,
|
||||
getSpaceSummary: jest.fn().mockReturnValue({
|
||||
getRoomHierarchy: jest.fn().mockReturnValue({
|
||||
rooms: [],
|
||||
events: [],
|
||||
}),
|
||||
|
||||
// Used by various internal bits we aren't concerned with (yet)
|
||||
|
|
31
test/utils/DateUtils-test.ts
Normal file
31
test/utils/DateUtils-test.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { formatSeconds } from "../../src/DateUtils";
|
||||
|
||||
describe("formatSeconds", () => {
|
||||
it("correctly formats time with hours", () => {
|
||||
expect(formatSeconds((60 * 60 * 3) + (60 * 31) + (55))).toBe("03:31:55");
|
||||
expect(formatSeconds((60 * 60 * 3) + (60 * 0) + (55))).toBe("03:00:55");
|
||||
expect(formatSeconds((60 * 60 * 3) + (60 * 31) + (0))).toBe("03:31:00");
|
||||
});
|
||||
|
||||
it("correctly formats time without hours", () => {
|
||||
expect(formatSeconds((60 * 60 * 0) + (60 * 31) + (55))).toBe("31:55");
|
||||
expect(formatSeconds((60 * 60 * 0) + (60 * 0) + (55))).toBe("00:55");
|
||||
expect(formatSeconds((60 * 60 * 0) + (60 * 31) + (0))).toBe("31:00");
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue