You've already forked matrix-react-sdk
mirror of
https://github.com/matrix-org/matrix-react-sdk.git
synced 2025-08-07 21:23:00 +03:00
Merge branch 'develop' into export-conversations
This commit is contained in:
@@ -136,18 +136,6 @@ describe("PosthogAnalytics", () => {
|
||||
expect(fakePosthog.capture.mock.calls[0][1]["foo"]).toEqual("bar");
|
||||
});
|
||||
|
||||
it("Should pass trackRoomEvent to posthog", async () => {
|
||||
analytics.setAnonymity(Anonymity.Pseudonymous);
|
||||
const roomId = "42";
|
||||
await analytics.trackRoomEvent<IRoomEvent>("jest_test_event", roomId, {
|
||||
foo: "bar",
|
||||
});
|
||||
expect(fakePosthog.capture.mock.calls[0][0]).toBe("jest_test_event");
|
||||
expect(fakePosthog.capture.mock.calls[0][1]["foo"]).toEqual("bar");
|
||||
expect(fakePosthog.capture.mock.calls[0][1]["hashedRoomId"])
|
||||
.toEqual("73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049");
|
||||
});
|
||||
|
||||
it("Should pass trackPseudonymousEvent() to posthog", async () => {
|
||||
analytics.setAnonymity(Anonymity.Pseudonymous);
|
||||
await analytics.trackPseudonymousEvent<ITestEvent>("jest_test_pseudo_event", {
|
||||
@@ -173,9 +161,6 @@ describe("PosthogAnalytics", () => {
|
||||
await analytics.trackAnonymousEvent<ITestEvent>("jest_test_event", {
|
||||
foo: "bar",
|
||||
});
|
||||
await analytics.trackRoomEvent<ITestRoomEvent>("room id", "foo", {
|
||||
foo: "bar",
|
||||
});
|
||||
await analytics.trackPageView(200);
|
||||
expect(fakePosthog.capture.mock.calls.length).toBe(0);
|
||||
});
|
||||
@@ -183,31 +168,25 @@ describe("PosthogAnalytics", () => {
|
||||
it("Should pseudonymise a location of a known screen", async () => {
|
||||
const location = await getRedactedCurrentLocation(
|
||||
"https://foo.bar", "#/register/some/pii", "/", Anonymity.Pseudonymous);
|
||||
expect(location).toBe(
|
||||
`https://foo.bar/#/register/\
|
||||
a6b46dd0d1ae5e86cbc8f37e75ceeb6760230c1ca4ffbcb0c97b96dd7d9c464b/\
|
||||
bd75b3e080945674c0351f75e0db33d1e90986fa07b318ea7edf776f5eef38d4`);
|
||||
expect(location).toBe("https://foo.bar/#/register/<redacted>");
|
||||
});
|
||||
|
||||
it("Should anonymise a location of a known screen", async () => {
|
||||
const location = await getRedactedCurrentLocation(
|
||||
"https://foo.bar", "#/register/some/pii", "/", Anonymity.Anonymous);
|
||||
expect(location).toBe("https://foo.bar/#/register/<redacted>/<redacted>");
|
||||
expect(location).toBe("https://foo.bar/#/register/<redacted>");
|
||||
});
|
||||
|
||||
it("Should pseudonymise a location of an unknown screen", async () => {
|
||||
const location = await getRedactedCurrentLocation(
|
||||
"https://foo.bar", "#/not_a_screen_name/some/pii", "/", Anonymity.Pseudonymous);
|
||||
expect(location).toBe(
|
||||
`https://foo.bar/#/<redacted_screen_name>/\
|
||||
a6b46dd0d1ae5e86cbc8f37e75ceeb6760230c1ca4ffbcb0c97b96dd7d9c464b/\
|
||||
bd75b3e080945674c0351f75e0db33d1e90986fa07b318ea7edf776f5eef38d4`);
|
||||
expect(location).toBe("https://foo.bar/#/<redacted_screen_name>/<redacted>");
|
||||
});
|
||||
|
||||
it("Should anonymise a location of an unknown screen", async () => {
|
||||
const location = await getRedactedCurrentLocation(
|
||||
"https://foo.bar", "#/not_a_screen_name/some/pii", "/", Anonymity.Anonymous);
|
||||
expect(location).toBe("https://foo.bar/#/<redacted_screen_name>/<redacted>/<redacted>");
|
||||
expect(location).toBe("https://foo.bar/#/<redacted_screen_name>/<redacted>");
|
||||
});
|
||||
|
||||
it("Should handle an empty hash", async () => {
|
||||
@@ -218,15 +197,28 @@ bd75b3e080945674c0351f75e0db33d1e90986fa07b318ea7edf776f5eef38d4`);
|
||||
|
||||
it("Should identify the user to posthog if pseudonymous", async () => {
|
||||
analytics.setAnonymity(Anonymity.Pseudonymous);
|
||||
await analytics.identifyUser("foo");
|
||||
expect(fakePosthog.identify.mock.calls[0][0])
|
||||
.toBe("2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae");
|
||||
class FakeClient {
|
||||
getAccountDataFromServer = jest.fn().mockResolvedValue(null);
|
||||
setAccountData = jest.fn().mockResolvedValue({});
|
||||
}
|
||||
await analytics.identifyUser(new FakeClient(), () => "analytics_id" );
|
||||
expect(fakePosthog.identify.mock.calls[0][0]).toBe("analytics_id");
|
||||
});
|
||||
|
||||
it("Should not identify the user to posthog if anonymous", async () => {
|
||||
analytics.setAnonymity(Anonymity.Anonymous);
|
||||
await analytics.identifyUser("foo");
|
||||
await analytics.identifyUser(null);
|
||||
expect(fakePosthog.identify.mock.calls.length).toBe(0);
|
||||
});
|
||||
|
||||
it("Should identify using the server's analytics id if present", async () => {
|
||||
analytics.setAnonymity(Anonymity.Pseudonymous);
|
||||
class FakeClient {
|
||||
getAccountDataFromServer = jest.fn().mockResolvedValue({ id: "existing_analytics_id" });
|
||||
setAccountData = jest.fn().mockResolvedValue({});
|
||||
}
|
||||
await analytics.identifyUser(new FakeClient(), () => "new_analytics_id" );
|
||||
expect(fakePosthog.identify.mock.calls[0][0]).toBe("existing_analytics_id");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
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);
|
||||
});
|
||||
});
|
||||
});
|
209
test/components/views/elements/ReplyThread-test.js
Normal file
209
test/components/views/elements/ReplyThread-test.js
Normal file
@@ -0,0 +1,209 @@
|
||||
import "../../../skinned-sdk";
|
||||
import * as testUtils from '../../../test-utils';
|
||||
import ReplyThread from '../../../../src/components/views/elements/ReplyThread';
|
||||
|
||||
describe("ReplyThread", () => {
|
||||
describe('getParentEventId', () => {
|
||||
it('retrieves relation reply from unedited event', () => {
|
||||
const originalEventWithRelation = testUtils.mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "> Reply to this message\n\n foo",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
"event_id": "$qkjmFBTEc0VvfVyzq1CJuh1QZi_xDIgNEFjZ4Pq34og",
|
||||
},
|
||||
},
|
||||
},
|
||||
user: "some_other_user",
|
||||
room: "room_id",
|
||||
});
|
||||
|
||||
expect(ReplyThread.getParentEventId(originalEventWithRelation))
|
||||
.toStrictEqual('$qkjmFBTEc0VvfVyzq1CJuh1QZi_xDIgNEFjZ4Pq34og');
|
||||
});
|
||||
|
||||
it('retrieves relation reply from original event when edited', () => {
|
||||
const originalEventWithRelation = testUtils.mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "> Reply to this message\n\n foo",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
"event_id": "$qkjmFBTEc0VvfVyzq1CJuh1QZi_xDIgNEFjZ4Pq34og",
|
||||
},
|
||||
},
|
||||
},
|
||||
user: "some_other_user",
|
||||
room: "room_id",
|
||||
});
|
||||
|
||||
const editEvent = testUtils.mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "> Reply to this message\n\n * foo bar",
|
||||
"m.new_content": {
|
||||
"msgtype": "m.text",
|
||||
"body": "foo bar",
|
||||
},
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.replace",
|
||||
"event_id": originalEventWithRelation.event_id,
|
||||
},
|
||||
},
|
||||
user: "some_other_user",
|
||||
room: "room_id",
|
||||
});
|
||||
|
||||
// The edit replaces the original event
|
||||
originalEventWithRelation.makeReplaced(editEvent);
|
||||
|
||||
// The relation should be pulled from the original event
|
||||
expect(ReplyThread.getParentEventId(originalEventWithRelation))
|
||||
.toStrictEqual('$qkjmFBTEc0VvfVyzq1CJuh1QZi_xDIgNEFjZ4Pq34og');
|
||||
});
|
||||
|
||||
it('retrieves relation reply from edit event when provided', () => {
|
||||
const originalEvent = testUtils.mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
msgtype: "m.text",
|
||||
body: "foo",
|
||||
},
|
||||
user: "some_other_user",
|
||||
room: "room_id",
|
||||
});
|
||||
|
||||
const editEvent = testUtils.mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "> Reply to this message\n\n * foo bar",
|
||||
"m.new_content": {
|
||||
"msgtype": "m.text",
|
||||
"body": "foo bar",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
"event_id": "$qkjmFBTEc0VvfVyzq1CJuh1QZi_xDIgNEFjZ4Pq34og",
|
||||
},
|
||||
},
|
||||
},
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.replace",
|
||||
"event_id": originalEvent.event_id,
|
||||
},
|
||||
},
|
||||
user: "some_other_user",
|
||||
room: "room_id",
|
||||
});
|
||||
|
||||
// The edit replaces the original event
|
||||
originalEvent.makeReplaced(editEvent);
|
||||
|
||||
// The relation should be pulled from the edit event
|
||||
expect(ReplyThread.getParentEventId(originalEvent))
|
||||
.toStrictEqual('$qkjmFBTEc0VvfVyzq1CJuh1QZi_xDIgNEFjZ4Pq34og');
|
||||
});
|
||||
|
||||
it('prefers relation reply from edit event over original event', () => {
|
||||
const originalEventWithRelation = testUtils.mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "> Reply to this message\n\n foo",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
"event_id": "$111",
|
||||
},
|
||||
},
|
||||
},
|
||||
user: "some_other_user",
|
||||
room: "room_id",
|
||||
});
|
||||
|
||||
const editEvent = testUtils.mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "> Reply to this message\n\n * foo bar",
|
||||
"m.new_content": {
|
||||
"msgtype": "m.text",
|
||||
"body": "foo bar",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
"event_id": "$999",
|
||||
},
|
||||
},
|
||||
},
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.replace",
|
||||
"event_id": originalEventWithRelation.event_id,
|
||||
},
|
||||
},
|
||||
user: "some_other_user",
|
||||
room: "room_id",
|
||||
});
|
||||
|
||||
// The edit replaces the original event
|
||||
originalEventWithRelation.makeReplaced(editEvent);
|
||||
|
||||
// The relation should be pulled from the edit event
|
||||
expect(ReplyThread.getParentEventId(originalEventWithRelation)).toStrictEqual('$999');
|
||||
});
|
||||
|
||||
it('able to clear relation reply from original event by providing empty relation field', () => {
|
||||
const originalEventWithRelation = testUtils.mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "> Reply to this message\n\n foo",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
"event_id": "$111",
|
||||
},
|
||||
},
|
||||
},
|
||||
user: "some_other_user",
|
||||
room: "room_id",
|
||||
});
|
||||
|
||||
const editEvent = testUtils.mkEvent({
|
||||
event: true,
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "> Reply to this message\n\n * foo bar",
|
||||
"m.new_content": {
|
||||
"msgtype": "m.text",
|
||||
"body": "foo bar",
|
||||
// Clear the relation from the original event
|
||||
"m.relates_to": {},
|
||||
},
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.replace",
|
||||
"event_id": originalEventWithRelation.event_id,
|
||||
},
|
||||
},
|
||||
user: "some_other_user",
|
||||
room: "room_id",
|
||||
});
|
||||
|
||||
// The edit replaces the original event
|
||||
originalEventWithRelation.makeReplaced(editEvent);
|
||||
|
||||
// The relation should be pulled from the edit event
|
||||
expect(ReplyThread.getParentEventId(originalEventWithRelation)).toStrictEqual(undefined);
|
||||
});
|
||||
});
|
||||
});
|
@@ -9,23 +9,16 @@ import sdk from '../../../skinned-sdk';
|
||||
|
||||
import dis from '../../../../src/dispatcher/dispatcher';
|
||||
import DMRoomMap from '../../../../src/utils/DMRoomMap';
|
||||
import GroupStore from '../../../../src/stores/GroupStore';
|
||||
|
||||
import { MatrixClient, Room, RoomMember } from 'matrix-js-sdk';
|
||||
import { DefaultTagID } from "../../../../src/stores/room-list/models";
|
||||
import RoomListStore, { LISTS_UPDATE_EVENT, RoomListStoreClass } from "../../../../src/stores/room-list/RoomListStore";
|
||||
import RoomListStore, { RoomListStoreClass } from "../../../../src/stores/room-list/RoomListStore";
|
||||
import RoomListLayoutStore from "../../../../src/stores/room-list/RoomListLayoutStore";
|
||||
|
||||
function generateRoomId() {
|
||||
return '!' + Math.random().toString().slice(2, 10) + ':domain';
|
||||
}
|
||||
|
||||
function waitForRoomListStoreUpdate() {
|
||||
return new Promise((resolve) => {
|
||||
RoomListStore.instance.once(LISTS_UPDATE_EVENT, () => resolve());
|
||||
});
|
||||
}
|
||||
|
||||
describe('RoomList', () => {
|
||||
function createRoom(opts) {
|
||||
const room = new Room(generateRoomId(), MatrixClientPeg.get(), client.getUserId(), {
|
||||
@@ -239,73 +232,6 @@ describe('RoomList', () => {
|
||||
});
|
||||
}
|
||||
|
||||
describe('when no tags are selected', () => {
|
||||
itDoesCorrectOptimisticUpdatesForDraggedRoomTiles();
|
||||
});
|
||||
|
||||
describe('when tags are selected', () => {
|
||||
function setupSelectedTag() {
|
||||
// Simulate a complete sync BEFORE dispatching anything else
|
||||
dis.dispatch({
|
||||
action: 'MatrixActions.sync',
|
||||
prevState: null,
|
||||
state: 'PREPARED',
|
||||
matrixClient: client,
|
||||
}, true);
|
||||
|
||||
// Simulate joined groups being received
|
||||
dis.dispatch({
|
||||
action: 'GroupActions.fetchJoinedGroups.success',
|
||||
result: {
|
||||
groups: ['+group:domain'],
|
||||
},
|
||||
}, true);
|
||||
|
||||
// Simulate receiving tag ordering account data
|
||||
dis.dispatch({
|
||||
action: 'MatrixActions.accountData',
|
||||
event_type: 'im.vector.web.tag_ordering',
|
||||
event_content: {
|
||||
tags: ['+group:domain'],
|
||||
},
|
||||
}, true);
|
||||
|
||||
// GroupStore is not flux, mock and notify
|
||||
GroupStore.getGroupRooms = (groupId) => {
|
||||
return [movingRoom];
|
||||
};
|
||||
GroupStore._notifyListeners();
|
||||
|
||||
// We also have to mock the client's getGroup function for the room list to filter it.
|
||||
// It's not smart enough to tell the difference between a real group and a template though.
|
||||
client.getGroup = (groupId) => {
|
||||
return { groupId };
|
||||
};
|
||||
|
||||
// Select tag
|
||||
dis.dispatch({ action: 'select_tag', tag: '+group:domain' }, true);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
setupSelectedTag();
|
||||
});
|
||||
|
||||
it('displays the correct rooms when the groups rooms are changed', async () => {
|
||||
GroupStore.getGroupRooms = (groupId) => {
|
||||
return [movingRoom, otherRoom];
|
||||
};
|
||||
GroupStore._notifyListeners();
|
||||
|
||||
await waitForRoomListStoreUpdate();
|
||||
|
||||
// XXX: Even though the store updated, it can take a bit before the update makes
|
||||
// it to the components. This gives it plenty of time to figure out what to do.
|
||||
await (new Promise(resolve => setTimeout(resolve, 500)));
|
||||
|
||||
expectRoomInSubList(otherRoom, (s) => s.props.tagId === DefaultTagID.Untagged);
|
||||
});
|
||||
|
||||
itDoesCorrectOptimisticUpdatesForDraggedRoomTiles();
|
||||
});
|
||||
itDoesCorrectOptimisticUpdatesForDraggedRoomTiles();
|
||||
});
|
||||
|
||||
|
@@ -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",
|
||||
|
@@ -43,6 +43,9 @@ module.exports = async function scenario(createSession, restCreator) {
|
||||
console.log("create REST users:");
|
||||
const charlies = await createRestUsers(restCreator);
|
||||
await lazyLoadingScenarios(alice, bob, charlies);
|
||||
// do spaces scenarios last as the rest of the tests may get confused by spaces
|
||||
// XXX: disabled for now as fails in CI but succeeds locally
|
||||
// await spacesScenarios(alice, bob);
|
||||
};
|
||||
|
||||
async function createRestUsers(restCreator) {
|
||||
|
32
test/end-to-end-tests/src/scenarios/spaces.js
Normal file
32
test/end-to-end-tests/src/scenarios/spaces.js
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
const { createSpace, inviteSpace } = require("../usecases/create-space");
|
||||
|
||||
module.exports = async function spacesScenarios(alice, bob) {
|
||||
console.log(" creating a space for spaces scenarios:");
|
||||
|
||||
await alice.delay(1000); // wait for dialogs to close
|
||||
await setupSpaceUsingAliceAndInviteBob(alice, bob);
|
||||
};
|
||||
|
||||
const space = "Test Space";
|
||||
|
||||
async function setupSpaceUsingAliceAndInviteBob(alice, bob) {
|
||||
await createSpace(alice, space);
|
||||
await inviteSpace(alice, space, "@bob:localhost");
|
||||
await bob.query(`.mx_SpaceButton[aria-label="${space}"]`); // assert invite received
|
||||
}
|
80
test/end-to-end-tests/src/usecases/create-space.js
Normal file
80
test/end-to-end-tests/src/usecases/create-space.js
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
async function openSpaceCreateMenu(session) {
|
||||
const spaceCreateButton = await session.query('.mx_SpaceButton_new');
|
||||
await spaceCreateButton.click();
|
||||
}
|
||||
|
||||
async function createSpace(session, name, isPublic = false) {
|
||||
session.log.step(`creates space "${name}"`);
|
||||
|
||||
await openSpaceCreateMenu(session);
|
||||
const className = isPublic ? ".mx_SpaceCreateMenuType_public" : ".mx_SpaceCreateMenuType_private";
|
||||
const visibilityButton = await session.query(className);
|
||||
await visibilityButton.click();
|
||||
|
||||
const nameInput = await session.query('input[name="spaceName"]');
|
||||
await session.replaceInputText(nameInput, name);
|
||||
|
||||
await session.delay(100);
|
||||
|
||||
const createButton = await session.query('.mx_SpaceCreateMenu_wrapper .mx_AccessibleButton_kind_primary');
|
||||
await createButton.click();
|
||||
|
||||
if (!isPublic) {
|
||||
const justMeButton = await session.query('.mx_SpaceRoomView_privateScope_justMeButton');
|
||||
await justMeButton.click();
|
||||
const continueButton = await session.query('.mx_AddExistingToSpace_footer .mx_AccessibleButton_kind_primary');
|
||||
await continueButton.click();
|
||||
} else {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
const continueButton = await session.query('.mx_SpaceRoomView_buttons .mx_AccessibleButton_kind_primary');
|
||||
await continueButton.click();
|
||||
}
|
||||
}
|
||||
|
||||
session.log.done();
|
||||
}
|
||||
|
||||
async function inviteSpace(session, spaceName, userId) {
|
||||
session.log.step(`invites "${userId}" to space "${spaceName}"`);
|
||||
|
||||
const spaceButton = await session.query(`.mx_SpaceButton[aria-label="${spaceName}"]`);
|
||||
await spaceButton.click({
|
||||
button: 'right',
|
||||
});
|
||||
|
||||
const inviteButton = await session.query('[aria-label="Invite people"]');
|
||||
await inviteButton.click();
|
||||
|
||||
try {
|
||||
const button = await session.query('.mx_SpacePublicShare_inviteButton');
|
||||
await button.click();
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
const inviteTextArea = await session.query(".mx_InviteDialog_editor input");
|
||||
await inviteTextArea.type(userId);
|
||||
const selectUserItem = await session.query(".mx_InviteDialog_roomTile");
|
||||
await selectUserItem.click();
|
||||
const confirmButton = await session.query(".mx_InviteDialog_goButton");
|
||||
await confirmButton.click();
|
||||
session.log.done();
|
||||
}
|
||||
|
||||
module.exports = { openSpaceCreateMenu, createSpace, inviteSpace };
|
@@ -161,8 +161,8 @@ async function changeRoomSettings(session, settings) {
|
||||
if (settings.visibility) {
|
||||
session.log.step(`sets visibility to ${settings.visibility}`);
|
||||
const radios = await session.queryAll(".mx_RoomSettingsDialog label");
|
||||
assert.equal(radios.length, 6);
|
||||
const [inviteOnlyRoom, publicRoom] = radios;
|
||||
assert.equal(radios.length, 7);
|
||||
const [inviteOnlyRoom,, publicRoom] = radios;
|
||||
|
||||
if (settings.visibility === "invite_only") {
|
||||
await inviteOnlyRoom.click();
|
||||
|
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// This needs to be executed before the SpaceStore gets imported but due to ES6 import hoisting we have to do this here.
|
||||
// SpaceStore reads the SettingsStore which needs the localStorage values set at init time.
|
||||
|
||||
localStorage.setItem("mx_labs_feature_feature_spaces", "true");
|
@@ -18,7 +18,6 @@ import { EventEmitter } from "events";
|
||||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
|
||||
import "./SpaceStore-setup"; // enable space lab
|
||||
import "../skinned-sdk"; // Must be first for skinning to work
|
||||
import SpaceStore, {
|
||||
UPDATE_HOME_BEHAVIOUR,
|
||||
@@ -276,10 +275,12 @@ describe("SpaceStore", () => {
|
||||
|
||||
describe("test fixture 1", () => {
|
||||
beforeEach(async () => {
|
||||
[fav1, fav2, fav3, dm1, dm2, dm3, orphan1, orphan2, invite1, invite2, room1].forEach(mkRoom);
|
||||
[fav1, fav2, fav3, dm1, dm2, dm3, orphan1, orphan2, invite1, invite2, room1, room2, room3]
|
||||
.forEach(mkRoom);
|
||||
mkSpace(space1, [fav1, room1]);
|
||||
mkSpace(space2, [fav1, fav2, fav3, room1]);
|
||||
mkSpace(space3, [invite2]);
|
||||
// client.getRoom.mockImplementation(roomId => rooms.find(room => room.roomId === roomId));
|
||||
|
||||
[fav1, fav2, fav3].forEach(roomId => {
|
||||
client.getRoom(roomId).tags = {
|
||||
@@ -329,6 +330,48 @@ describe("SpaceStore", () => {
|
||||
]);
|
||||
// dmPartner3 is not in any common spaces with you
|
||||
|
||||
// room 2 claims to be a child of space2 and is so via a valid m.space.parent
|
||||
const cliRoom2 = client.getRoom(room2);
|
||||
cliRoom2.currentState.getStateEvents.mockImplementation(testUtils.mockStateEventImplementation([
|
||||
mkEvent({
|
||||
event: true,
|
||||
type: EventType.SpaceParent,
|
||||
room: room2,
|
||||
user: client.getUserId(),
|
||||
skey: space2,
|
||||
content: { via: [], canonical: true },
|
||||
ts: Date.now(),
|
||||
}),
|
||||
]));
|
||||
const cliSpace2 = client.getRoom(space2);
|
||||
cliSpace2.currentState.maySendStateEvent.mockImplementation((evType: string, userId: string) => {
|
||||
if (evType === EventType.SpaceChild) {
|
||||
return userId === client.getUserId();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// room 3 claims to be a child of space3 but is not due to invalid m.space.parent (permissions)
|
||||
const cliRoom3 = client.getRoom(room3);
|
||||
cliRoom3.currentState.getStateEvents.mockImplementation(testUtils.mockStateEventImplementation([
|
||||
mkEvent({
|
||||
event: true,
|
||||
type: EventType.SpaceParent,
|
||||
room: room3,
|
||||
user: client.getUserId(),
|
||||
skey: space3,
|
||||
content: { via: [], canonical: true },
|
||||
ts: Date.now(),
|
||||
}),
|
||||
]));
|
||||
const cliSpace3 = client.getRoom(space3);
|
||||
cliSpace3.currentState.maySendStateEvent.mockImplementation((evType: string, userId: string) => {
|
||||
if (evType === EventType.SpaceChild) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
await run();
|
||||
});
|
||||
|
||||
@@ -445,6 +488,14 @@ describe("SpaceStore", () => {
|
||||
expect(store.getNotificationState(space2).rooms.map(r => r.roomId).includes(room1)).toBeTruthy();
|
||||
expect(store.getNotificationState(space3).rooms.map(r => r.roomId).includes(room1)).toBeFalsy();
|
||||
});
|
||||
|
||||
it("honours m.space.parent if sender has permission in parent space", () => {
|
||||
expect(store.getSpaceFilteredRoomIds(client.getRoom(space2)).has(room2)).toBeTruthy();
|
||||
});
|
||||
|
||||
it("does not honour m.space.parent if sender does not have permission in parent space", () => {
|
||||
expect(store.getSpaceFilteredRoomIds(client.getRoom(space3)).has(room3)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -562,7 +613,7 @@ describe("SpaceStore", () => {
|
||||
]);
|
||||
mkSpace(space3).getMyMembership.mockReturnValue("invite");
|
||||
await run();
|
||||
await store.setActiveSpace(null);
|
||||
store.setActiveSpace(null);
|
||||
expect(store.activeSpace).toBe(null);
|
||||
});
|
||||
afterEach(() => {
|
||||
@@ -570,31 +621,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);
|
||||
});
|
||||
@@ -602,7 +653,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);
|
||||
});
|
||||
@@ -635,59 +686,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
|
||||
});
|
||||
});
|
||||
@@ -715,28 +766,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();
|
||||
});
|
||||
@@ -744,7 +795,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();
|
||||
});
|
||||
|
@@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import "../SpaceStore-setup"; // enable space lab
|
||||
import "../../skinned-sdk"; // Must be first for skinning to work
|
||||
import { SpaceWatcher } from "../../../src/stores/room-list/SpaceWatcher";
|
||||
import type { RoomListStoreClass } from "../../../src/stores/room-list/RoomListStore";
|
||||
@@ -57,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);
|
||||
@@ -95,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);
|
||||
@@ -114,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);
|
||||
@@ -124,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);
|
||||
@@ -147,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);
|
||||
@@ -160,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);
|
||||
@@ -173,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");
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user