1
0
mirror of https://github.com/matrix-org/matrix-react-sdk.git synced 2025-07-31 13:44:28 +03:00

Apply prettier formatting

This commit is contained in:
Michael Weimann
2022-12-12 12:24:14 +01:00
parent 1cac306093
commit 526645c791
1576 changed files with 65385 additions and 62478 deletions

View File

@ -26,17 +26,17 @@ import { REPEATABLE_DATE } from "../test-utils";
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");
expect(formatSeconds(-((60 * 60 * 3) + (60 * 31) + (0)))).toBe("-03:31:00");
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");
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");
expect(formatSeconds(-((60 * 60 * 0) + (60 * 31) + (0)))).toBe("-31:00");
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");
expect(formatSeconds(-(60 * 60 * 0 + 60 * 31 + 0))).toBe("-31:00");
});
});
@ -44,7 +44,7 @@ describe("formatRelativeTime", () => {
let dateSpy;
beforeAll(() => {
dateSpy = jest
.spyOn(global.Date, 'now')
.spyOn(global.Date, "now")
// Tuesday, 2 November 2021 11:18:03 UTC
.mockImplementation(() => 1635851883000);
});
@ -81,24 +81,24 @@ describe("formatRelativeTime", () => {
});
});
describe('formatDuration()', () => {
describe("formatDuration()", () => {
type TestCase = [string, string, number];
const MINUTE_MS = 60000;
const HOUR_MS = MINUTE_MS * 60;
it.each<TestCase>([
['rounds up to nearest day when more than 24h - 40 hours', '2d', 40 * HOUR_MS],
['rounds down to nearest day when more than 24h - 26 hours', '1d', 26 * HOUR_MS],
['24 hours', '1d', 24 * HOUR_MS],
['rounds to nearest hour when less than 24h - 23h', '23h', 23 * HOUR_MS],
['rounds to nearest hour when less than 24h - 6h and 10min', '6h', 6 * HOUR_MS + 10 * MINUTE_MS],
['rounds to nearest hours when less than 24h', '2h', 2 * HOUR_MS + 124234],
['rounds to nearest minute when less than 1h - 59 minutes', '59m', 59 * MINUTE_MS],
['rounds to nearest minute when less than 1h - 1 minute', '1m', MINUTE_MS],
['rounds to nearest second when less than 1min - 59 seconds', '59s', 59000],
['rounds to 0 seconds when less than a second - 123ms', '0s', 123],
])('%s formats to %s', (_description, expectedResult, input) => {
["rounds up to nearest day when more than 24h - 40 hours", "2d", 40 * HOUR_MS],
["rounds down to nearest day when more than 24h - 26 hours", "1d", 26 * HOUR_MS],
["24 hours", "1d", 24 * HOUR_MS],
["rounds to nearest hour when less than 24h - 23h", "23h", 23 * HOUR_MS],
["rounds to nearest hour when less than 24h - 6h and 10min", "6h", 6 * HOUR_MS + 10 * MINUTE_MS],
["rounds to nearest hours when less than 24h", "2h", 2 * HOUR_MS + 124234],
["rounds to nearest minute when less than 1h - 59 minutes", "59m", 59 * MINUTE_MS],
["rounds to nearest minute when less than 1h - 1 minute", "1m", MINUTE_MS],
["rounds to nearest second when less than 1min - 59 seconds", "59s", 59000],
["rounds to 0 seconds when less than a second - 123ms", "0s", 123],
])("%s formats to %s", (_description, expectedResult, input) => {
expect(formatDuration(input)).toEqual(expectedResult);
});
});
@ -109,12 +109,12 @@ describe("formatPreciseDuration", () => {
const DAY_MS = HOUR_MS * 24;
it.each<[string, string, number]>([
['3 days, 6 hours, 48 minutes, 59 seconds', '3d 6h 48m 59s', 3 * DAY_MS + 6 * HOUR_MS + 48 * MINUTE_MS + 59000],
['6 hours, 48 minutes, 59 seconds', '6h 48m 59s', 6 * HOUR_MS + 48 * MINUTE_MS + 59000],
['48 minutes, 59 seconds', '48m 59s', 48 * MINUTE_MS + 59000],
['59 seconds', '59s', 59000],
['0 seconds', '0s', 0],
])('%s formats to %s', (_description, expectedResult, input) => {
["3 days, 6 hours, 48 minutes, 59 seconds", "3d 6h 48m 59s", 3 * DAY_MS + 6 * HOUR_MS + 48 * MINUTE_MS + 59000],
["6 hours, 48 minutes, 59 seconds", "6h 48m 59s", 6 * HOUR_MS + 48 * MINUTE_MS + 59000],
["48 minutes, 59 seconds", "48m 59s", 48 * MINUTE_MS + 59000],
["59 seconds", "59s", 59000],
["0 seconds", "0s", 0],
])("%s formats to %s", (_description, expectedResult, input) => {
expect(formatPreciseDuration(input)).toEqual(expectedResult);
});
});

View File

@ -41,9 +41,9 @@ import {
} from "../../src/utils/EventUtils";
import { getMockClientWithEventEmitter, makeBeaconInfoEvent, makePollStartEvent, stubClient } from "../test-utils";
describe('EventUtils', () => {
const userId = '@user:server';
const roomId = '!room:server';
describe("EventUtils", () => {
const userId = "@user:server";
const roomId = "!room:server";
const mockClient = getMockClientWithEventEmitter({
getUserId: jest.fn().mockReturnValue(userId),
});
@ -52,7 +52,7 @@ describe('EventUtils', () => {
mockClient.getUserId.mockClear().mockReturnValue(userId);
});
afterAll(() => {
jest.spyOn(MatrixClientPeg, 'get').mockRestore();
jest.spyOn(MatrixClientPeg, "get").mockRestore();
});
// setup events
@ -70,7 +70,7 @@ describe('EventUtils', () => {
const stateEvent = new MatrixEvent({
type: EventType.RoomTopic,
state_key: '',
state_key: "",
});
const beaconInfoEvent = makeBeaconInfoEvent(userId, roomId);
@ -84,13 +84,13 @@ describe('EventUtils', () => {
sender: userId,
});
const pollStartEvent = makePollStartEvent('What?', userId);
const pollStartEvent = makePollStartEvent("What?", userId);
const notDecryptedEvent = new MatrixEvent({
type: EventType.RoomMessage,
sender: userId,
content: {
msgtype: 'm.bad.encrypted',
msgtype: "m.bad.encrypted",
},
});
@ -115,7 +115,7 @@ describe('EventUtils', () => {
sender: userId,
content: {
msgtype: MsgType.Text,
body: '',
body: "",
},
});
@ -133,54 +133,54 @@ describe('EventUtils', () => {
sender: userId,
content: {
msgtype: MsgType.Text,
body: 'Hello',
body: "Hello",
},
});
const bobsTextMessage = new MatrixEvent({
type: EventType.RoomMessage,
sender: '@bob:server',
sender: "@bob:server",
content: {
msgtype: MsgType.Text,
body: 'Hello from Bob',
body: "Hello from Bob",
},
});
describe('isContentActionable()', () => {
describe("isContentActionable()", () => {
type TestCase = [string, MatrixEvent];
it.each<TestCase>([
['unsent event', unsentEvent],
['redacted event', redactedEvent],
['state event', stateEvent],
['undecrypted event', notDecryptedEvent],
['room member event', roomMemberEvent],
['event without msgtype', noMsgType],
['event without content body property', noContentBody],
])('returns false for %s', (_description, event) => {
["unsent event", unsentEvent],
["redacted event", redactedEvent],
["state event", stateEvent],
["undecrypted event", notDecryptedEvent],
["room member event", roomMemberEvent],
["event without msgtype", noMsgType],
["event without content body property", noContentBody],
])("returns false for %s", (_description, event) => {
expect(isContentActionable(event)).toBe(false);
});
it.each<TestCase>([
['sticker event', stickerEvent],
['poll start event', pollStartEvent],
['event with empty content body', emptyContentBody],
['event with a content body', niceTextMessage],
['beacon_info event', beaconInfoEvent],
])('returns true for %s', (_description, event) => {
["sticker event", stickerEvent],
["poll start event", pollStartEvent],
["event with empty content body", emptyContentBody],
["event with a content body", niceTextMessage],
["beacon_info event", beaconInfoEvent],
])("returns true for %s", (_description, event) => {
expect(isContentActionable(event)).toBe(true);
});
});
describe('editable content helpers', () => {
describe("editable content helpers", () => {
const replaceRelationEvent = new MatrixEvent({
type: EventType.RoomMessage,
sender: userId,
content: {
msgtype: MsgType.Text,
body: 'Hello',
['m.relates_to']: {
body: "Hello",
["m.relates_to"]: {
rel_type: RelationType.Replace,
event_id: '1',
event_id: "1",
},
},
});
@ -190,10 +190,10 @@ describe('EventUtils', () => {
sender: userId,
content: {
msgtype: MsgType.Text,
body: 'Hello',
['m.relates_to']: {
body: "Hello",
["m.relates_to"]: {
rel_type: RelationType.Reference,
event_id: '1',
event_id: "1",
},
},
});
@ -203,79 +203,79 @@ describe('EventUtils', () => {
sender: userId,
content: {
msgtype: MsgType.Emote,
body: '🧪',
body: "🧪",
},
});
type TestCase = [string, MatrixEvent];
const uneditableCases: TestCase[] = [
['redacted event', redactedEvent],
['state event', stateEvent],
['event that is not room message', roomMemberEvent],
['event without msgtype', noMsgType],
['event without content body property', noContentBody],
['event with empty content body property', emptyContentBody],
['event with non-string body', objectContentBody],
['event not sent by current user', bobsTextMessage],
['event with a replace relation', replaceRelationEvent],
["redacted event", redactedEvent],
["state event", stateEvent],
["event that is not room message", roomMemberEvent],
["event without msgtype", noMsgType],
["event without content body property", noContentBody],
["event with empty content body property", emptyContentBody],
["event with non-string body", objectContentBody],
["event not sent by current user", bobsTextMessage],
["event with a replace relation", replaceRelationEvent],
];
const editableCases: TestCase[] = [
['event with reference relation', referenceRelationEvent],
['emote event', emoteEvent],
['poll start event', pollStartEvent],
['event with a content body', niceTextMessage],
["event with reference relation", referenceRelationEvent],
["emote event", emoteEvent],
["poll start event", pollStartEvent],
["event with a content body", niceTextMessage],
];
describe('canEditContent()', () => {
it.each<TestCase>(uneditableCases)('returns false for %s', (_description, event) => {
describe("canEditContent()", () => {
it.each<TestCase>(uneditableCases)("returns false for %s", (_description, event) => {
expect(canEditContent(event)).toBe(false);
});
it.each<TestCase>(editableCases)('returns true for %s', (_description, event) => {
it.each<TestCase>(editableCases)("returns true for %s", (_description, event) => {
expect(canEditContent(event)).toBe(true);
});
});
describe('canEditOwnContent()', () => {
it.each<TestCase>(uneditableCases)('returns false for %s', (_description, event) => {
describe("canEditOwnContent()", () => {
it.each<TestCase>(uneditableCases)("returns false for %s", (_description, event) => {
expect(canEditOwnEvent(event)).toBe(false);
});
it.each<TestCase>(editableCases)('returns true for %s', (_description, event) => {
it.each<TestCase>(editableCases)("returns true for %s", (_description, event) => {
expect(canEditOwnEvent(event)).toBe(true);
});
});
});
describe('isVoiceMessage()', () => {
it('returns true for an event with msc2516.voice content', () => {
describe("isVoiceMessage()", () => {
it("returns true for an event with msc2516.voice content", () => {
const event = new MatrixEvent({
type: EventType.RoomMessage,
content: {
['org.matrix.msc2516.voice']: {},
["org.matrix.msc2516.voice"]: {},
},
});
expect(isVoiceMessage(event)).toBe(true);
});
it('returns true for an event with msc3245.voice content', () => {
it("returns true for an event with msc3245.voice content", () => {
const event = new MatrixEvent({
type: EventType.RoomMessage,
content: {
['org.matrix.msc3245.voice']: {},
["org.matrix.msc3245.voice"]: {},
},
});
expect(isVoiceMessage(event)).toBe(true);
});
it('returns false for an event with voice content', () => {
it("returns false for an event with voice content", () => {
const event = new MatrixEvent({
type: EventType.RoomMessage,
content: {
body: 'hello',
body: "hello",
},
});
@ -283,20 +283,20 @@ describe('EventUtils', () => {
});
});
describe('isLocationEvent()', () => {
it('returns true for an event with m.location stable type', () => {
describe("isLocationEvent()", () => {
it("returns true for an event with m.location stable type", () => {
const event = new MatrixEvent({
type: M_LOCATION.altName,
});
expect(isLocationEvent(event)).toBe(true);
});
it('returns true for an event with m.location unstable prefixed type', () => {
it("returns true for an event with m.location unstable prefixed type", () => {
const event = new MatrixEvent({
type: M_LOCATION.name,
});
expect(isLocationEvent(event)).toBe(true);
});
it('returns true for a room message with stable m.location msgtype', () => {
it("returns true for a room message with stable m.location msgtype", () => {
const event = new MatrixEvent({
type: EventType.RoomMessage,
content: {
@ -305,7 +305,7 @@ describe('EventUtils', () => {
});
expect(isLocationEvent(event)).toBe(true);
});
it('returns true for a room message with unstable m.location msgtype', () => {
it("returns true for a room message with unstable m.location msgtype", () => {
const event = new MatrixEvent({
type: EventType.RoomMessage,
content: {
@ -314,32 +314,31 @@ describe('EventUtils', () => {
});
expect(isLocationEvent(event)).toBe(true);
});
it('returns false for a non location event', () => {
it("returns false for a non location event", () => {
const event = new MatrixEvent({
type: EventType.RoomMessage,
content: {
body: 'Hello',
body: "Hello",
},
});
expect(isLocationEvent(event)).toBe(false);
});
});
describe('canCancel()', () => {
it.each([
[EventStatus.QUEUED],
[EventStatus.NOT_SENT],
[EventStatus.ENCRYPTING],
])('return true for status %s', (status) => {
expect(canCancel(status)).toBe(true);
});
describe("canCancel()", () => {
it.each([[EventStatus.QUEUED], [EventStatus.NOT_SENT], [EventStatus.ENCRYPTING]])(
"return true for status %s",
(status) => {
expect(canCancel(status)).toBe(true);
},
);
it.each([
[EventStatus.SENDING],
[EventStatus.CANCELLED],
[EventStatus.SENT],
['invalid-status' as unknown as EventStatus],
])('return false for status %s', (status) => {
["invalid-status" as unknown as EventStatus],
])("return false for status %s", (status) => {
expect(canCancel(status)).toBe(false);
});
});
@ -358,16 +357,16 @@ describe('EventUtils', () => {
event_id: NORMAL_EVENT,
type: EventType.RoomMessage,
content: {
"body": "Classic event",
"msgtype": MsgType.Text,
body: "Classic event",
msgtype: MsgType.Text,
},
},
[THREAD_ROOT]: {
event_id: THREAD_ROOT,
type: EventType.RoomMessage,
content: {
"body": "Thread root",
"msgtype": "m.text",
body: "Thread root",
msgtype: "m.text",
},
unsigned: {
"m.relations": {
@ -434,10 +433,12 @@ describe('EventUtils', () => {
describe("findEditableEvent", () => {
it("should not explode when given empty events array", () => {
expect(findEditableEvent({
events: [],
isForward: true,
})).toBeUndefined();
expect(
findEditableEvent({
events: [],
isForward: true,
}),
).toBeUndefined();
});
});
});

View File

@ -16,17 +16,17 @@ limitations under the License.
import { FixedRollingArray } from "../../src/utils/FixedRollingArray";
describe('FixedRollingArray', () => {
it('should seed the array with the given value', () => {
describe("FixedRollingArray", () => {
it("should seed the array with the given value", () => {
const seed = "test";
const width = 24;
const array = new FixedRollingArray(width, seed);
expect(array.value.length).toBe(width);
expect(array.value.every(v => v === seed)).toBe(true);
expect(array.value.every((v) => v === seed)).toBe(true);
});
it('should insert at the correct end', () => {
it("should insert at the correct end", () => {
const seed = "test";
const value = "changed";
const width = 24;
@ -37,7 +37,7 @@ describe('FixedRollingArray', () => {
expect(array.value[0]).toBe(value);
});
it('should roll over', () => {
it("should roll over", () => {
const seed = -1;
const width = 24;
const array = new FixedRollingArray(width, seed);

View File

@ -25,43 +25,43 @@ function getRandomValues<T extends ArrayBufferView>(buf: T): T {
return nodeCrypto.randomFillSync(buf);
}
const TEST_VECTORS=[
const TEST_VECTORS = [
[
"plain",
"password",
"-----BEGIN MEGOLM SESSION DATA-----\n" +
"AXNhbHRzYWx0c2FsdHNhbHSIiIiIiIiIiIiIiIiIiIiIAAAACmIRUW2OjZ3L2l6j9h0lHlV3M2dx\n" +
"cissyYBxjsfsAndErh065A8=\n" +
"-----END MEGOLM SESSION DATA-----",
"AXNhbHRzYWx0c2FsdHNhbHSIiIiIiIiIiIiIiIiIiIiIAAAACmIRUW2OjZ3L2l6j9h0lHlV3M2dx\n" +
"cissyYBxjsfsAndErh065A8=\n" +
"-----END MEGOLM SESSION DATA-----",
],
[
"Hello, World",
"betterpassword",
"-----BEGIN MEGOLM SESSION DATA-----\n" +
"AW1vcmVzYWx0bW9yZXNhbHT//////////wAAAAAAAAAAAAAD6KyBpe1Niv5M5NPm4ZATsJo5nghk\n" +
"KYu63a0YQ5DRhUWEKk7CcMkrKnAUiZny\n" +
"-----END MEGOLM SESSION DATA-----",
"AW1vcmVzYWx0bW9yZXNhbHT//////////wAAAAAAAAAAAAAD6KyBpe1Niv5M5NPm4ZATsJo5nghk\n" +
"KYu63a0YQ5DRhUWEKk7CcMkrKnAUiZny\n" +
"-----END MEGOLM SESSION DATA-----",
],
[
"alphanumericallyalphanumericallyalphanumericallyalphanumerically",
"SWORDFISH",
"-----BEGIN MEGOLM SESSION DATA-----\n" +
"AXllc3NhbHR5Z29vZG5lc3P//////////wAAAAAAAAAAAAAD6OIW+Je7gwvjd4kYrb+49gKCfExw\n" +
"MgJBMD4mrhLkmgAngwR1pHjbWXaoGybtiAYr0moQ93GrBQsCzPbvl82rZhaXO3iH5uHo/RCEpOqp\n" +
"Pgg29363BGR+/Ripq/VCLKGNbw==\n" +
"-----END MEGOLM SESSION DATA-----",
"AXllc3NhbHR5Z29vZG5lc3P//////////wAAAAAAAAAAAAAD6OIW+Je7gwvjd4kYrb+49gKCfExw\n" +
"MgJBMD4mrhLkmgAngwR1pHjbWXaoGybtiAYr0moQ93GrBQsCzPbvl82rZhaXO3iH5uHo/RCEpOqp\n" +
"Pgg29363BGR+/Ripq/VCLKGNbw==\n" +
"-----END MEGOLM SESSION DATA-----",
],
[
"alphanumericallyalphanumericallyalphanumericallyalphanumerically",
"passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" +
"passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" +
"passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" +
"passwordpasswordpasswordpasswordpassword",
"passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" +
"passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" +
"passwordpasswordpasswordpasswordpassword",
"-----BEGIN MEGOLM SESSION DATA-----\n" +
"Af//////////////////////////////////////////AAAD6IAZJy7IQ7Y0idqSw/bmpngEEVVh\n" +
"gsH+8ptgqxw6ZVWQnohr8JsuwH9SwGtiebZuBu5smPCO+RFVWH2cQYslZijXv/BEH/txvhUrrtCd\n" +
"bWnSXS9oymiqwUIGs08sXI33ZA==\n" +
"-----END MEGOLM SESSION DATA-----",
"Af//////////////////////////////////////////AAAD6IAZJy7IQ7Y0idqSw/bmpngEEVVh\n" +
"gsH+8ptgqxw6ZVWQnohr8JsuwH9SwGtiebZuBu5smPCO+RFVWH2cQYslZijXv/BEH/txvhUrrtCd\n" +
"bWnSXS9oymiqwUIGs08sXI33ZA==\n" +
"-----END MEGOLM SESSION DATA-----",
],
];
@ -69,7 +69,7 @@ function stringToArray(s: string): ArrayBufferLike {
return new TextEncoder().encode(s).buffer;
}
describe('MegolmExportEncryption', function() {
describe("MegolmExportEncryption", function () {
let MegolmExportEncryption;
beforeEach(() => {
@ -87,76 +87,78 @@ describe('MegolmExportEncryption', function() {
window.crypto = undefined;
});
describe('decrypt', function() {
it('should handle missing header', function() {
const input=stringToArray(`-----`);
return MegolmExportEncryption.decryptMegolmKeyFile(input, '')
.then((res) => {
throw new Error('expected to throw');
}, (error) => {
expect(error.message).toEqual('Header line not found');
});
describe("decrypt", function () {
it("should handle missing header", function () {
const input = stringToArray(`-----`);
return MegolmExportEncryption.decryptMegolmKeyFile(input, "").then(
(res) => {
throw new Error("expected to throw");
},
(error) => {
expect(error.message).toEqual("Header line not found");
},
);
});
it('should handle missing trailer', function() {
const input=stringToArray(`-----BEGIN MEGOLM SESSION DATA-----
it("should handle missing trailer", function () {
const input = stringToArray(`-----BEGIN MEGOLM SESSION DATA-----
-----`);
return MegolmExportEncryption.decryptMegolmKeyFile(input, '')
.then((res) => {
throw new Error('expected to throw');
}, (error) => {
expect(error.message).toEqual('Trailer line not found');
});
return MegolmExportEncryption.decryptMegolmKeyFile(input, "").then(
(res) => {
throw new Error("expected to throw");
},
(error) => {
expect(error.message).toEqual("Trailer line not found");
},
);
});
it('should handle a too-short body', function() {
const input=stringToArray(`-----BEGIN MEGOLM SESSION DATA-----
it("should handle a too-short body", function () {
const input = stringToArray(`-----BEGIN MEGOLM SESSION DATA-----
AXNhbHRzYWx0c2FsdHNhbHSIiIiIiIiIiIiIiIiIiIiIAAAACmIRUW2OjZ3L2l6j9h0lHlV3M2dx
cissyYBxjsfsAn
-----END MEGOLM SESSION DATA-----
`);
return MegolmExportEncryption.decryptMegolmKeyFile(input, '')
.then((res) => {
throw new Error('expected to throw');
}, (error) => {
expect(error.message).toEqual('Invalid file: too short');
});
return MegolmExportEncryption.decryptMegolmKeyFile(input, "").then(
(res) => {
throw new Error("expected to throw");
},
(error) => {
expect(error.message).toEqual("Invalid file: too short");
},
);
});
// TODO find a subtlecrypto shim which doesn't break this test
it.skip('should decrypt a range of inputs', function() {
it.skip("should decrypt a range of inputs", function () {
function next(i) {
if (i >= TEST_VECTORS.length) {
return;
}
const [plain, password, input] = TEST_VECTORS[i];
return MegolmExportEncryption.decryptMegolmKeyFile(
stringToArray(input), password,
).then((decrypted) => {
return MegolmExportEncryption.decryptMegolmKeyFile(stringToArray(input), password).then((decrypted) => {
expect(decrypted).toEqual(plain);
return next(i+1);
return next(i + 1);
});
}
return next(0);
});
});
describe('encrypt', function() {
it('should round-trip', function() {
const input = 'words words many words in plain text here'.repeat(100);
describe("encrypt", function () {
it("should round-trip", function () {
const input = "words words many words in plain text here".repeat(100);
const password = 'my super secret passphrase';
const password = "my super secret passphrase";
return MegolmExportEncryption.encryptMegolmKeyFile(
input, password, { kdf_rounds: 1000 },
).then((ciphertext) => {
return MegolmExportEncryption.decryptMegolmKeyFile(
ciphertext, password,
);
}).then((plaintext) => {
expect(plaintext).toEqual(input);
});
return MegolmExportEncryption.encryptMegolmKeyFile(input, password, { kdf_rounds: 1000 })
.then((ciphertext) => {
return MegolmExportEncryption.decryptMegolmKeyFile(ciphertext, password);
})
.then((plaintext) => {
expect(plaintext).toEqual(input);
});
});
});
});

View File

@ -14,32 +14,32 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { mocked } from 'jest-mock';
import { MatrixClient } from 'matrix-js-sdk/src/matrix';
import { mocked } from "jest-mock";
import { MatrixClient } from "matrix-js-sdk/src/matrix";
import { MatrixClientPeg } from '../../src/MatrixClientPeg';
import Modal, { ModalManager } from '../../src/Modal';
import SettingsStore from '../../src/settings/SettingsStore';
import MultiInviter, { CompletionStates } from '../../src/utils/MultiInviter';
import * as TestUtilsMatrix from '../test-utils';
import { MatrixClientPeg } from "../../src/MatrixClientPeg";
import Modal, { ModalManager } from "../../src/Modal";
import SettingsStore from "../../src/settings/SettingsStore";
import MultiInviter, { CompletionStates } from "../../src/utils/MultiInviter";
import * as TestUtilsMatrix from "../test-utils";
const ROOMID = '!room:server';
const ROOMID = "!room:server";
const MXID1 = '@user1:server';
const MXID2 = '@user2:server';
const MXID3 = '@user3:server';
const MXID1 = "@user1:server";
const MXID2 = "@user2:server";
const MXID3 = "@user3:server";
const MXID_PROFILE_STATES = {
[MXID1]: Promise.resolve({}),
[MXID2]: Promise.reject({ errcode: 'M_FORBIDDEN' }),
[MXID3]: Promise.reject({ errcode: 'M_NOT_FOUND' }),
[MXID2]: Promise.reject({ errcode: "M_FORBIDDEN" }),
[MXID3]: Promise.reject({ errcode: "M_NOT_FOUND" }),
};
jest.mock('../../src/Modal', () => ({
jest.mock("../../src/Modal", () => ({
createDialog: jest.fn(),
}));
jest.mock('../../src/settings/SettingsStore', () => ({
jest.mock("../../src/settings/SettingsStore", () => ({
getValue: jest.fn(),
monitorSetting: jest.fn(),
watchSetting: jest.fn(),
@ -48,30 +48,28 @@ jest.mock('../../src/settings/SettingsStore', () => ({
const mockPromptBeforeInviteUnknownUsers = (value: boolean) => {
mocked(SettingsStore.getValue).mockImplementation(
(settingName: string, roomId: string = null, _excludeDefault = false): any => {
if (settingName === 'promptBeforeInviteUnknownUsers' && roomId === ROOMID) {
if (settingName === "promptBeforeInviteUnknownUsers" && roomId === ROOMID) {
return value;
}
},
);
};
const mockCreateTrackedDialog = (callbackName: 'onInviteAnyways'|'onGiveUp') => {
mocked(Modal.createDialog).mockImplementation(
(...rest: Parameters<ModalManager['createDialog']>): any => {
rest[1][callbackName]();
},
);
const mockCreateTrackedDialog = (callbackName: "onInviteAnyways" | "onGiveUp") => {
mocked(Modal.createDialog).mockImplementation((...rest: Parameters<ModalManager["createDialog"]>): any => {
rest[1][callbackName]();
});
};
const expectAllInvitedResult = (result: CompletionStates) => {
expect(result).toEqual({
[MXID1]: 'invited',
[MXID2]: 'invited',
[MXID3]: 'invited',
[MXID1]: "invited",
[MXID2]: "invited",
[MXID3]: "invited",
});
};
describe('MultiInviter', () => {
describe("MultiInviter", () => {
let client: jest.Mocked<MatrixClient>;
let inviter: MultiInviter;
@ -92,11 +90,11 @@ describe('MultiInviter', () => {
inviter = new MultiInviter(ROOMID);
});
describe('invite', () => {
describe('with promptBeforeInviteUnknownUsers = false', () => {
describe("invite", () => {
describe("with promptBeforeInviteUnknownUsers = false", () => {
beforeEach(() => mockPromptBeforeInviteUnknownUsers(false));
it('should invite all users', async () => {
it("should invite all users", async () => {
const result = await inviter.invite([MXID1, MXID2, MXID3]);
expect(client.invite).toHaveBeenCalledTimes(3);
@ -108,13 +106,13 @@ describe('MultiInviter', () => {
});
});
describe('with promptBeforeInviteUnknownUsers = true and', () => {
describe("with promptBeforeInviteUnknownUsers = true and", () => {
beforeEach(() => mockPromptBeforeInviteUnknownUsers(true));
describe('confirming the unknown user dialog', () => {
beforeEach(() => mockCreateTrackedDialog('onInviteAnyways'));
describe("confirming the unknown user dialog", () => {
beforeEach(() => mockCreateTrackedDialog("onInviteAnyways"));
it('should invite all users', async () => {
it("should invite all users", async () => {
const result = await inviter.invite([MXID1, MXID2, MXID3]);
expect(client.invite).toHaveBeenCalledTimes(3);
@ -126,10 +124,10 @@ describe('MultiInviter', () => {
});
});
describe('declining the unknown user dialog', () => {
beforeEach(() => mockCreateTrackedDialog('onGiveUp'));
describe("declining the unknown user dialog", () => {
beforeEach(() => mockCreateTrackedDialog("onGiveUp"));
it('should only invite existing users', async () => {
it("should only invite existing users", async () => {
const result = await inviter.invite([MXID1, MXID2, MXID3]);
expect(client.invite).toHaveBeenCalledTimes(1);

View File

@ -14,13 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {
MatrixClient,
Room,
} from 'matrix-js-sdk/src/matrix';
import { MatrixClient, Room } from "matrix-js-sdk/src/matrix";
import { shieldStatusForRoom } from '../../src/utils/ShieldUtils';
import DMRoomMap from '../../src/utils/DMRoomMap';
import { shieldStatusForRoom } from "../../src/utils/ShieldUtils";
import DMRoomMap from "../../src/utils/DMRoomMap";
function mkClient(selfTrust = false) {
return {
@ -30,13 +27,13 @@ function mkClient(selfTrust = false) {
wasCrossSigningVerified: () => userId[1] == "T" || userId[1] == "W",
}),
checkDeviceTrust: (userId, deviceId) => ({
isVerified: () => userId === "@self:localhost" ? selfTrust : userId[2] == "T",
isVerified: () => (userId === "@self:localhost" ? selfTrust : userId[2] == "T"),
}),
getStoredDevicesForUser: (userId) => ["DEVICE"],
} as unknown as MatrixClient;
}
describe("mkClient self-test", function() {
describe("mkClient self-test", function () {
test.each([true, false])("behaves well for self-trust=%s", (v) => {
const client = mkClient(v);
expect(client.checkDeviceTrust("@self:localhost", "DEVICE").isVerified()).toBe(v);
@ -46,8 +43,8 @@ describe("mkClient self-test", function() {
["@TT:h", true],
["@TF:h", true],
["@FT:h", false],
["@FF:h", false]],
)("behaves well for user trust %s", (userId, trust) => {
["@FF:h", false],
])("behaves well for user trust %s", (userId, trust) => {
expect(mkClient().checkUserTrust(userId).isCrossSigningVerified()).toBe(trust);
});
@ -55,28 +52,30 @@ describe("mkClient self-test", function() {
["@TT:h", true],
["@TF:h", false],
["@FT:h", true],
["@FF:h", false]],
)("behaves well for device trust %s", (userId, trust) => {
["@FF:h", false],
])("behaves well for device trust %s", (userId, trust) => {
expect(mkClient().checkDeviceTrust(userId, "device").isVerified()).toBe(trust);
});
});
describe("shieldStatusForMembership self-trust behaviour", function() {
describe("shieldStatusForMembership self-trust behaviour", function () {
beforeAll(() => {
const mockInstance = {
getUserIdForRoomId: (roomId) => roomId === "DM" ? "@any:h" : null,
getUserIdForRoomId: (roomId) => (roomId === "DM" ? "@any:h" : null),
} as unknown as DMRoomMap;
jest.spyOn(DMRoomMap, 'shared').mockReturnValue(mockInstance);
jest.spyOn(DMRoomMap, "shared").mockReturnValue(mockInstance);
});
afterAll(() => {
jest.spyOn(DMRoomMap, 'shared').mockRestore();
jest.spyOn(DMRoomMap, "shared").mockRestore();
});
it.each(
[[true, true], [true, false],
[false, true], [false, false]],
)("2 unverified: returns 'normal', self-trust = %s, DM = %s", async (trusted, dm) => {
it.each([
[true, true],
[true, false],
[false, true],
[false, false],
])("2 unverified: returns 'normal', self-trust = %s, DM = %s", async (trusted, dm) => {
const client = mkClient(trusted);
const room = {
roomId: dm ? "DM" : "other",
@ -86,10 +85,12 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
expect(status).toEqual("normal");
});
it.each(
[["verified", true, true], ["verified", true, false],
["verified", false, true], ["warning", false, false]],
)("2 verified: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => {
it.each([
["verified", true, true],
["verified", true, false],
["verified", false, true],
["warning", false, false],
])("2 verified: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => {
const client = mkClient(trusted);
const room = {
roomId: dm ? "DM" : "other",
@ -99,10 +100,12 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
expect(status).toEqual(result);
});
it.each(
[["normal", true, true], ["normal", true, false],
["normal", false, true], ["warning", false, false]],
)("2 mixed: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => {
it.each([
["normal", true, true],
["normal", true, false],
["normal", false, true],
["warning", false, false],
])("2 mixed: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => {
const client = mkClient(trusted);
const room = {
roomId: dm ? "DM" : "other",
@ -112,10 +115,12 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
expect(status).toEqual(result);
});
it.each(
[["verified", true, true], ["verified", true, false],
["warning", false, true], ["warning", false, false]],
)("0 others: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => {
it.each([
["verified", true, true],
["verified", true, false],
["warning", false, true],
["warning", false, false],
])("0 others: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => {
const client = mkClient(trusted);
const room = {
roomId: dm ? "DM" : "other",
@ -125,10 +130,12 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
expect(status).toEqual(result);
});
it.each(
[["verified", true, true], ["verified", true, false],
["verified", false, true], ["verified", false, false]],
)("1 verified: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => {
it.each([
["verified", true, true],
["verified", true, false],
["verified", false, true],
["verified", false, false],
])("1 verified: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => {
const client = mkClient(trusted);
const room = {
roomId: dm ? "DM" : "other",
@ -138,10 +145,12 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
expect(status).toEqual(result);
});
it.each(
[["normal", true, true], ["normal", true, false],
["normal", false, true], ["normal", false, false]],
)("1 unverified: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => {
it.each([
["normal", true, true],
["normal", true, false],
["normal", false, true],
["normal", false, false],
])("1 unverified: returns '%s', self-trust = %s, DM = %s", async (result, trusted, dm) => {
const client = mkClient(trusted);
const room = {
roomId: dm ? "DM" : "other",
@ -152,17 +161,18 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
});
});
describe("shieldStatusForMembership other-trust behaviour", function() {
describe("shieldStatusForMembership other-trust behaviour", function () {
beforeAll(() => {
const mockInstance = {
getUserIdForRoomId: (roomId) => roomId === "DM" ? "@any:h" : null,
getUserIdForRoomId: (roomId) => (roomId === "DM" ? "@any:h" : null),
} as unknown as DMRoomMap;
jest.spyOn(DMRoomMap, 'shared').mockReturnValue(mockInstance);
jest.spyOn(DMRoomMap, "shared").mockReturnValue(mockInstance);
});
it.each(
[["warning", true], ["warning", false]],
)("1 verified/untrusted: returns '%s', DM = %s", async (result, dm) => {
it.each([
["warning", true],
["warning", false],
])("1 verified/untrusted: returns '%s', DM = %s", async (result, dm) => {
const client = mkClient(true);
const room = {
roomId: dm ? "DM" : "other",
@ -172,9 +182,10 @@ describe("shieldStatusForMembership other-trust behaviour", function() {
expect(status).toEqual(result);
});
it.each(
[["warning", true], ["warning", false]],
)("2 verified/untrusted: returns '%s', DM = %s", async (result, dm) => {
it.each([
["warning", true],
["warning", false],
])("2 verified/untrusted: returns '%s', DM = %s", async (result, dm) => {
const client = mkClient(true);
const room = {
roomId: dm ? "DM" : "other",
@ -184,9 +195,10 @@ describe("shieldStatusForMembership other-trust behaviour", function() {
expect(status).toEqual(result);
});
it.each(
[["normal", true], ["normal", false]],
)("2 unverified/untrusted: returns '%s', DM = %s", async (result, dm) => {
it.each([
["normal", true],
["normal", false],
])("2 unverified/untrusted: returns '%s', DM = %s", async (result, dm) => {
const client = mkClient(true);
const room = {
roomId: dm ? "DM" : "other",
@ -196,9 +208,10 @@ describe("shieldStatusForMembership other-trust behaviour", function() {
expect(status).toEqual(result);
});
it.each(
[["warning", true], ["warning", false]],
)("2 was verified: returns '%s', DM = %s", async (result, dm) => {
it.each([
["warning", true],
["warning", false],
])("2 was verified: returns '%s', DM = %s", async (result, dm) => {
const client = mkClient(true);
const room = {
roomId: dm ? "DM" : "other",

View File

@ -16,12 +16,12 @@ limitations under the License.
import { Singleflight } from "../../src/utils/Singleflight";
describe('Singleflight', () => {
describe("Singleflight", () => {
afterEach(() => {
Singleflight.forgetAll();
});
it('should throw for bad context variables', () => {
it("should throw for bad context variables", () => {
const permutations: [Object, string][] = [
[null, null],
[{}, null],
@ -38,7 +38,7 @@ describe('Singleflight', () => {
}
});
it('should execute the function once', () => {
it("should execute the function once", () => {
const instance = {};
const key = "test";
const val = {}; // unique object for reference check
@ -52,7 +52,7 @@ describe('Singleflight', () => {
expect(fn.mock.calls.length).toBe(1);
});
it('should execute the function once, even with new contexts', () => {
it("should execute the function once, even with new contexts", () => {
const instance = {};
const key = "test";
const val = {}; // unique object for reference check
@ -67,7 +67,7 @@ describe('Singleflight', () => {
expect(fn.mock.calls.length).toBe(1);
});
it('should execute the function twice if the result was forgotten', () => {
it("should execute the function twice if the result was forgotten", () => {
const instance = {};
const key = "test";
const val = {}; // unique object for reference check
@ -82,7 +82,7 @@ describe('Singleflight', () => {
expect(fn.mock.calls.length).toBe(2);
});
it('should execute the function twice if the instance was forgotten', () => {
it("should execute the function twice if the instance was forgotten", () => {
const instance = {};
const key = "test";
const val = {}; // unique object for reference check
@ -97,7 +97,7 @@ describe('Singleflight', () => {
expect(fn.mock.calls.length).toBe(2);
});
it('should execute the function twice if everything was forgotten', () => {
it("should execute the function twice if everything was forgotten", () => {
const instance = {};
const key = "test";
const val = {}; // unique object for reference check
@ -112,4 +112,3 @@ describe('Singleflight', () => {
expect(fn.mock.calls.length).toBe(2);
});
});

View File

@ -16,15 +16,15 @@ limitations under the License.
import { SnakedObject, snakeToCamel } from "../../src/utils/SnakedObject";
describe('snakeToCamel', () => {
it('should convert snake_case to camelCase in simple scenarios', () => {
describe("snakeToCamel", () => {
it("should convert snake_case to camelCase in simple scenarios", () => {
expect(snakeToCamel("snake_case")).toBe("snakeCase");
expect(snakeToCamel("snake_case_but_longer")).toBe("snakeCaseButLonger");
expect(snakeToCamel("numbered_123")).toBe("numbered123"); // not a thing we would see normally
});
// Not really something we expect to see, but it's defined behaviour of the function
it('should not camelCase a trailing or leading underscore', () => {
it("should not camelCase a trailing or leading underscore", () => {
expect(snakeToCamel("_snake")).toBe("_snake");
expect(snakeToCamel("snake_")).toBe("snake_");
expect(snakeToCamel("_snake_case")).toBe("_snakeCase");
@ -32,13 +32,13 @@ describe('snakeToCamel', () => {
});
// Another thing we don't really expect to see, but is "defined behaviour"
it('should be predictable with double underscores', () => {
it("should be predictable with double underscores", () => {
expect(snakeToCamel("__snake__")).toBe("_Snake_");
expect(snakeToCamel("snake__case")).toBe("snake_case");
});
});
describe('SnakedObject', () => {
describe("SnakedObject", () => {
/* eslint-disable camelcase*/
const input = {
snake_case: "woot",
@ -48,12 +48,12 @@ describe('SnakedObject', () => {
const snake = new SnakedObject(input);
/* eslint-enable camelcase*/
it('should prefer snake_case keys', () => {
it("should prefer snake_case keys", () => {
expect(snake.get("snake_case")).toBe(input.snake_case);
expect(snake.get("snake_case", "camelCase")).toBe(input.snake_case);
});
it('should fall back to camelCase keys when needed', () => {
it("should fall back to camelCase keys when needed", () => {
// @ts-ignore - we're deliberately supplying a key that doesn't exist
expect(snake.get("camel_case")).toBe(input.camelCase);

View File

@ -19,23 +19,23 @@ import WidgetUtils from "../../src/utils/WidgetUtils";
import { mockPlatformPeg } from "../test-utils";
describe("getLocalJitsiWrapperUrl", () => {
it('should generate jitsi URL (for defaults)', () => {
it("should generate jitsi URL (for defaults)", () => {
mockPlatformPeg();
expect(WidgetUtils.getLocalJitsiWrapperUrl()).toEqual(
'https://app.element.io/jitsi.html'
+ '#conferenceDomain=$domain'
+ '&conferenceId=$conferenceId'
+ '&isAudioOnly=$isAudioOnly'
+ '&isVideoChannel=$isVideoChannel'
+ '&displayName=$matrix_display_name'
+ '&avatarUrl=$matrix_avatar_url'
+ '&userId=$matrix_user_id'
+ '&roomId=$matrix_room_id'
+ '&theme=$theme'
+ '&roomName=$roomName'
+ '&supportsScreensharing=true'
+ '&language=$org.matrix.msc2873.client_language',
"https://app.element.io/jitsi.html" +
"#conferenceDomain=$domain" +
"&conferenceId=$conferenceId" +
"&isAudioOnly=$isAudioOnly" +
"&isVideoChannel=$isVideoChannel" +
"&displayName=$matrix_display_name" +
"&avatarUrl=$matrix_avatar_url" +
"&userId=$matrix_user_id" +
"&roomId=$matrix_room_id" +
"&theme=$theme" +
"&roomName=$roomName" +
"&supportsScreensharing=true" +
"&language=$org.matrix.msc2873.client_language",
);
});
});

View File

@ -31,7 +31,7 @@ import {
concat,
} from "../../src/utils/arrays";
type TestParams = { input: number[], output: number[] };
type TestParams = { input: number[]; output: number[] };
type TestCase = [string, TestParams];
function expectSample(input: number[], expected: number[], smooth = false) {
@ -41,74 +41,70 @@ function expectSample(input: number[], expected: number[], smooth = false) {
expect(result).toEqual(expected);
}
describe('arrays', () => {
describe('arrayFastResample', () => {
describe("arrays", () => {
describe("arrayFastResample", () => {
const downsampleCases: TestCase[] = [
['Odd -> Even', { input: [1, 2, 3, 4, 5], output: [1, 4] }],
['Odd -> Odd', { input: [1, 2, 3, 4, 5], output: [1, 3, 5] }],
['Even -> Odd', { input: [1, 2, 3, 4], output: [1, 2, 3] }],
['Even -> Even', { input: [1, 2, 3, 4], output: [1, 3] }],
["Odd -> Even", { input: [1, 2, 3, 4, 5], output: [1, 4] }],
["Odd -> Odd", { input: [1, 2, 3, 4, 5], output: [1, 3, 5] }],
["Even -> Odd", { input: [1, 2, 3, 4], output: [1, 2, 3] }],
["Even -> Even", { input: [1, 2, 3, 4], output: [1, 3] }],
];
it.each(downsampleCases)('downsamples correctly from %s', (_d, { input, output }) =>
it.each(downsampleCases)("downsamples correctly from %s", (_d, { input, output }) =>
expectSample(input, output),
);
const upsampleCases: TestCase[] = [
['Odd -> Even', { input: [1, 2, 3], output: [1, 1, 2, 2, 3, 3] }],
['Odd -> Odd', { input: [1, 2, 3], output: [1, 1, 2, 2, 3] }],
['Even -> Odd', { input: [1, 2], output: [1, 1, 1, 2, 2] }],
['Even -> Even', { input: [1, 2], output: [1, 1, 1, 2, 2, 2] }],
["Odd -> Even", { input: [1, 2, 3], output: [1, 1, 2, 2, 3, 3] }],
["Odd -> Odd", { input: [1, 2, 3], output: [1, 1, 2, 2, 3] }],
["Even -> Odd", { input: [1, 2], output: [1, 1, 1, 2, 2] }],
["Even -> Even", { input: [1, 2], output: [1, 1, 1, 2, 2, 2] }],
];
it.each(upsampleCases)('upsamples correctly from %s', (_d, { input, output }) =>
expectSample(input, output),
);
it.each(upsampleCases)("upsamples correctly from %s", (_d, { input, output }) => expectSample(input, output));
const maintainSampleCases: TestCase[] = [
['Odd', { input: [1, 2, 3], output: [1, 2, 3] }], // Odd
['Even', { input: [1, 2], output: [1, 2] }], // Even
["Odd", { input: [1, 2, 3], output: [1, 2, 3] }], // Odd
["Even", { input: [1, 2], output: [1, 2] }], // Even
];
it.each(maintainSampleCases)('maintains samples for %s', (_d, { input, output }) =>
it.each(maintainSampleCases)("maintains samples for %s", (_d, { input, output }) =>
expectSample(input, output),
);
});
describe('arraySmoothingResample', () => {
describe("arraySmoothingResample", () => {
// Dev note: these aren't great samples, but they demonstrate the bare minimum. Ideally
// we'd be feeding a thousand values in and seeing what a curve of 250 values looks like,
// but that's not really feasible to manually verify accuracy.
const downsampleCases: TestCase[] = [
['Odd -> Even', { input: [4, 4, 1, 4, 4, 1, 4, 4, 1], output: [3, 3, 3, 3] }],
['Odd -> Odd', { input: [4, 4, 1, 4, 4, 1, 4, 4, 1], output: [3, 3, 3] }],
['Even -> Odd', { input: [4, 4, 1, 4, 4, 1, 4, 4], output: [3, 3, 3] }],
['Even -> Even', { input: [4, 4, 1, 4, 4, 1, 4, 4], output: [3, 3] }],
["Odd -> Even", { input: [4, 4, 1, 4, 4, 1, 4, 4, 1], output: [3, 3, 3, 3] }],
["Odd -> Odd", { input: [4, 4, 1, 4, 4, 1, 4, 4, 1], output: [3, 3, 3] }],
["Even -> Odd", { input: [4, 4, 1, 4, 4, 1, 4, 4], output: [3, 3, 3] }],
["Even -> Even", { input: [4, 4, 1, 4, 4, 1, 4, 4], output: [3, 3] }],
];
it.each(downsampleCases)('downsamples correctly from %s', (_d, { input, output }) =>
it.each(downsampleCases)("downsamples correctly from %s", (_d, { input, output }) =>
expectSample(input, output, true),
);
const upsampleCases: TestCase[] = [
['Odd -> Even', { input: [2, 0, 2], output: [2, 2, 0, 0, 2, 2] }],
['Odd -> Odd', { input: [2, 0, 2], output: [2, 2, 0, 0, 2] }],
['Even -> Odd', { input: [2, 0], output: [2, 2, 2, 0, 0] }],
['Even -> Even', { input: [2, 0], output: [2, 2, 2, 0, 0, 0] }],
["Odd -> Even", { input: [2, 0, 2], output: [2, 2, 0, 0, 2, 2] }],
["Odd -> Odd", { input: [2, 0, 2], output: [2, 2, 0, 0, 2] }],
["Even -> Odd", { input: [2, 0], output: [2, 2, 2, 0, 0] }],
["Even -> Even", { input: [2, 0], output: [2, 2, 2, 0, 0, 0] }],
];
it.each(upsampleCases)('upsamples correctly from %s', (_d, { input, output }) =>
it.each(upsampleCases)("upsamples correctly from %s", (_d, { input, output }) =>
expectSample(input, output, true),
);
const maintainCases: TestCase[] = [
['Odd', { input: [2, 0, 2], output: [2, 0, 2] }],
['Even', { input: [2, 0], output: [2, 0] }],
["Odd", { input: [2, 0, 2], output: [2, 0, 2] }],
["Even", { input: [2, 0], output: [2, 0] }],
];
it.each(maintainCases)('maintains samples for %s', (_d, { input, output }) =>
expectSample(input, output),
);
it.each(maintainCases)("maintains samples for %s", (_d, { input, output }) => expectSample(input, output));
});
describe('arrayRescale', () => {
it('should rescale', () => {
describe("arrayRescale", () => {
it("should rescale", () => {
const input = [8, 9, 1, 0, 2, 7, 10];
const output = [80, 90, 10, 0, 20, 70, 100];
const result = arrayRescale(input, 0, 100);
@ -118,8 +114,8 @@ describe('arrays', () => {
});
});
describe('arrayTrimFill', () => {
it('should shrink arrays', () => {
describe("arrayTrimFill", () => {
it("should shrink arrays", () => {
const input = [1, 2, 3];
const output = [1, 2];
const seed = [4, 5, 6];
@ -129,7 +125,7 @@ describe('arrays', () => {
expect(result).toEqual(output);
});
it('should expand arrays', () => {
it("should expand arrays", () => {
const input = [1, 2, 3];
const output = [1, 2, 3, 4, 5];
const seed = [4, 5, 6];
@ -139,7 +135,7 @@ describe('arrays', () => {
expect(result).toEqual(output);
});
it('should keep arrays the same', () => {
it("should keep arrays the same", () => {
const input = [1, 2, 3];
const output = [1, 2, 3];
const seed = [4, 5, 6];
@ -150,8 +146,8 @@ describe('arrays', () => {
});
});
describe('arraySeed', () => {
it('should create an array of given length', () => {
describe("arraySeed", () => {
it("should create an array of given length", () => {
const val = 1;
const output = [val, val, val];
const result = arraySeed(val, output.length);
@ -159,7 +155,7 @@ describe('arrays', () => {
expect(result).toHaveLength(output.length);
expect(result).toEqual(output);
});
it('should maintain pointers', () => {
it("should maintain pointers", () => {
const val = {}; // this works because `{} !== {}`, which is what toEqual checks
const output = [val, val, val];
const result = arraySeed(val, output.length);
@ -169,8 +165,8 @@ describe('arrays', () => {
});
});
describe('arrayFastClone', () => {
it('should break pointer reference on source array', () => {
describe("arrayFastClone", () => {
it("should break pointer reference on source array", () => {
const val = {}; // we'll test to make sure the values maintain pointers too
const input = [val, val, val];
const result = arrayFastClone(input);
@ -181,29 +177,29 @@ describe('arrays', () => {
});
});
describe('arrayHasOrderChange', () => {
it('should flag true on B ordering difference', () => {
describe("arrayHasOrderChange", () => {
it("should flag true on B ordering difference", () => {
const a = [1, 2, 3];
const b = [3, 2, 1];
const result = arrayHasOrderChange(a, b);
expect(result).toBe(true);
});
it('should flag false on no ordering difference', () => {
it("should flag false on no ordering difference", () => {
const a = [1, 2, 3];
const b = [1, 2, 3];
const result = arrayHasOrderChange(a, b);
expect(result).toBe(false);
});
it('should flag true on A length > B length', () => {
it("should flag true on A length > B length", () => {
const a = [1, 2, 3, 4];
const b = [1, 2, 3];
const result = arrayHasOrderChange(a, b);
expect(result).toBe(true);
});
it('should flag true on A length < B length', () => {
it("should flag true on A length < B length", () => {
const a = [1, 2, 3];
const b = [1, 2, 3, 4];
const result = arrayHasOrderChange(a, b);
@ -211,36 +207,36 @@ describe('arrays', () => {
});
});
describe('arrayHasDiff', () => {
it('should flag true on A length > B length', () => {
describe("arrayHasDiff", () => {
it("should flag true on A length > B length", () => {
const a = [1, 2, 3, 4];
const b = [1, 2, 3];
const result = arrayHasDiff(a, b);
expect(result).toBe(true);
});
it('should flag true on A length < B length', () => {
it("should flag true on A length < B length", () => {
const a = [1, 2, 3];
const b = [1, 2, 3, 4];
const result = arrayHasDiff(a, b);
expect(result).toBe(true);
});
it('should flag true on element differences', () => {
it("should flag true on element differences", () => {
const a = [1, 2, 3];
const b = [4, 5, 6];
const result = arrayHasDiff(a, b);
expect(result).toBe(true);
});
it('should flag false if same but order different', () => {
it("should flag false if same but order different", () => {
const a = [1, 2, 3];
const b = [3, 1, 2];
const result = arrayHasDiff(a, b);
expect(result).toBe(false);
});
it('should flag false if same', () => {
it("should flag false if same", () => {
const a = [1, 2, 3];
const b = [1, 2, 3];
const result = arrayHasDiff(a, b);
@ -248,8 +244,8 @@ describe('arrays', () => {
});
});
describe('arrayDiff', () => {
it('should see added from A->B', () => {
describe("arrayDiff", () => {
it("should see added from A->B", () => {
const a = [1, 2, 3];
const b = [1, 2, 3, 4];
const result = arrayDiff(a, b);
@ -261,7 +257,7 @@ describe('arrays', () => {
expect(result.added).toEqual([4]);
});
it('should see removed from A->B', () => {
it("should see removed from A->B", () => {
const a = [1, 2, 3];
const b = [1, 2];
const result = arrayDiff(a, b);
@ -273,7 +269,7 @@ describe('arrays', () => {
expect(result.removed).toEqual([3]);
});
it('should see added and removed in the same set', () => {
it("should see added and removed in the same set", () => {
const a = [1, 2, 3];
const b = [1, 2, 4]; // note diff
const result = arrayDiff(a, b);
@ -287,8 +283,8 @@ describe('arrays', () => {
});
});
describe('arrayIntersection', () => {
it('should return the intersection', () => {
describe("arrayIntersection", () => {
it("should return the intersection", () => {
const a = [1, 2, 3];
const b = [1, 2, 4]; // note diff
const result = arrayIntersection(a, b);
@ -297,7 +293,7 @@ describe('arrays', () => {
expect(result).toEqual([1, 2]);
});
it('should return an empty array on no matches', () => {
it("should return an empty array on no matches", () => {
const a = [1, 2, 3];
const b = [4, 5, 6];
const result = arrayIntersection(a, b);
@ -306,8 +302,8 @@ describe('arrays', () => {
});
});
describe('arrayUnion', () => {
it('should union 3 arrays with deduplication', () => {
describe("arrayUnion", () => {
it("should union 3 arrays with deduplication", () => {
const a = [1, 2, 3];
const b = [1, 2, 4, 5]; // note missing 3
const c = [6, 7, 8, 9];
@ -317,7 +313,7 @@ describe('arrays', () => {
expect(result).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
});
it('should deduplicate a single array', () => {
it("should deduplicate a single array", () => {
// dev note: this is technically an edge case, but it is described behaviour if the
// function is only provided one array (it'll merge the array against itself)
const a = [1, 1, 2, 2, 3, 3];
@ -328,21 +324,35 @@ describe('arrays', () => {
});
});
describe('ArrayUtil', () => {
it('should maintain the pointer to the given array', () => {
describe("ArrayUtil", () => {
it("should maintain the pointer to the given array", () => {
const input = [1, 2, 3];
const result = new ArrayUtil(input);
expect(result.value).toBe(input);
});
it('should group appropriately', () => {
const input = [['a', 1], ['b', 2], ['c', 3], ['a', 4], ['a', 5], ['b', 6]];
it("should group appropriately", () => {
const input = [
["a", 1],
["b", 2],
["c", 3],
["a", 4],
["a", 5],
["b", 6],
];
const output = {
'a': [['a', 1], ['a', 4], ['a', 5]],
'b': [['b', 2], ['b', 6]],
'c': [['c', 3]],
a: [
["a", 1],
["a", 4],
["a", 5],
],
b: [
["b", 2],
["b", 6],
],
c: [["c", 3]],
};
const result = new ArrayUtil(input).groupBy(p => p[0]);
const result = new ArrayUtil(input).groupBy((p) => p[0]);
expect(result).toBeDefined();
expect(result.value).toBeDefined();
@ -351,25 +361,25 @@ describe('arrays', () => {
});
});
describe('GroupedArray', () => {
it('should maintain the pointer to the given map', () => {
describe("GroupedArray", () => {
it("should maintain the pointer to the given map", () => {
const input = new Map([
['a', [1, 2, 3]],
['b', [7, 8, 9]],
['c', [4, 5, 6]],
["a", [1, 2, 3]],
["b", [7, 8, 9]],
["c", [4, 5, 6]],
]);
const result = new GroupedArray(input);
expect(result.value).toBe(input);
});
it('should ordering by the provided key order', () => {
it("should ordering by the provided key order", () => {
const input = new Map([
['a', [1, 2, 3]],
['b', [7, 8, 9]], // note counting diff
['c', [4, 5, 6]],
["a", [1, 2, 3]],
["b", [7, 8, 9]], // note counting diff
["c", [4, 5, 6]],
]);
const output = [4, 5, 6, 1, 2, 3, 7, 8, 9];
const keyOrder = ['c', 'a', 'b']; // note weird order to cause the `output` to be strange
const keyOrder = ["c", "a", "b"]; // note weird order to cause the `output` to be strange
const result = new GroupedArray(input).orderBy(keyOrder);
expect(result).toBeDefined();
expect(result.value).toBeDefined();
@ -404,4 +414,3 @@ describe('arrays', () => {
});
});
});

View File

@ -19,10 +19,10 @@ import { Beacon } from "matrix-js-sdk/src/matrix";
import { Bounds, getBeaconBounds } from "../../../src/utils/beacon/bounds";
import { makeBeaconEvent, makeBeaconInfoEvent } from "../../test-utils";
describe('getBeaconBounds()', () => {
const userId = '@user:server';
const roomId = '!room:server';
const makeBeaconWithLocation = (latLon: {lat: number, lon: number}) => {
describe("getBeaconBounds()", () => {
const userId = "@user:server";
const roomId = "!room:server";
const makeBeaconWithLocation = (latLon: { lat: number; lon: number }) => {
const geoUri = `geo:${latLon.lat},${latLon.lon}`;
const beacon = new Beacon(makeBeaconInfoEvent(userId, roomId, { isLive: true }));
// @ts-ignore private prop, sets internal live property so addLocations works
@ -57,39 +57,45 @@ describe('getBeaconBounds()', () => {
const auckland = makeBeaconWithLocation(geo.auckland);
const lima = makeBeaconWithLocation(geo.lima);
it('should return undefined when there are no beacons', () => {
it("should return undefined when there are no beacons", () => {
expect(getBeaconBounds([])).toBeUndefined();
});
it('should return undefined when no beacons have locations', () => {
it("should return undefined when no beacons have locations", () => {
const beacon = new Beacon(makeBeaconInfoEvent(userId, roomId));
expect(getBeaconBounds([beacon])).toBeUndefined();
});
type TestCase = [string, Beacon[], Bounds];
it.each<TestCase>([
['one beacon', [london],
[
"one beacon",
[london],
{ north: geo.london.lat, south: geo.london.lat, east: geo.london.lon, west: geo.london.lon },
],
['beacons in the northern hemisphere, west of meridian',
[
"beacons in the northern hemisphere, west of meridian",
[london, reykjavik],
{ north: geo.reykjavik.lat, south: geo.london.lat, east: geo.london.lon, west: geo.reykjavik.lon },
],
['beacons in the northern hemisphere, both sides of meridian',
[
"beacons in the northern hemisphere, both sides of meridian",
[london, reykjavik, paris],
// reykjavik northmost and westmost, paris southmost and eastmost
{ north: geo.reykjavik.lat, south: geo.paris.lat, east: geo.paris.lon, west: geo.reykjavik.lon },
],
['beacons in the southern hemisphere',
[
"beacons in the southern hemisphere",
[auckland, lima],
// lima northmost and westmost, auckland southmost and eastmost
{ north: geo.lima.lat, south: geo.auckland.lat, east: geo.auckland.lon, west: geo.lima.lon },
],
['beacons in both hemispheres',
[
"beacons in both hemispheres",
[auckland, lima, paris],
{ north: geo.paris.lat, south: geo.auckland.lat, east: geo.auckland.lon, west: geo.lima.lon },
],
])('gets correct bounds for %s', (_description, beacons, expectedBounds) => {
])("gets correct bounds for %s", (_description, beacons, expectedBounds) => {
expect(getBeaconBounds(beacons)).toEqual(expectedBounds);
});
});

View File

@ -16,35 +16,31 @@ limitations under the License.
import { Beacon } from "matrix-js-sdk/src/matrix";
import {
msUntilExpiry,
sortBeaconsByLatestExpiry,
sortBeaconsByLatestCreation,
} from "../../../src/utils/beacon";
import { msUntilExpiry, sortBeaconsByLatestExpiry, sortBeaconsByLatestCreation } from "../../../src/utils/beacon";
import { makeBeaconInfoEvent } from "../../test-utils";
describe('beacon utils', () => {
describe("beacon utils", () => {
// 14.03.2022 16:15
const now = 1647270879403;
const HOUR_MS = 3600000;
beforeEach(() => {
jest.spyOn(global.Date, 'now').mockReturnValue(now);
jest.spyOn(global.Date, "now").mockReturnValue(now);
});
afterAll(() => {
jest.spyOn(global.Date, 'now').mockRestore();
jest.spyOn(global.Date, "now").mockRestore();
});
describe('msUntilExpiry', () => {
it('returns remaining duration', () => {
describe("msUntilExpiry", () => {
it("returns remaining duration", () => {
const start = now - HOUR_MS;
const durationMs = HOUR_MS * 3;
expect(msUntilExpiry(start, durationMs)).toEqual(HOUR_MS * 2);
});
it('returns 0 when expiry has already passed', () => {
it("returns 0 when expiry has already passed", () => {
// created 3h ago
const start = now - HOUR_MS * 3;
// 1h durations
@ -54,65 +50,49 @@ describe('beacon utils', () => {
});
});
describe('sortBeaconsByLatestExpiry()', () => {
const roomId = '!room:server';
const aliceId = '@alive:server';
describe("sortBeaconsByLatestExpiry()", () => {
const roomId = "!room:server";
const aliceId = "@alive:server";
// 12h old, 12h left
const beacon1 = new Beacon(makeBeaconInfoEvent(aliceId,
roomId,
{ timeout: HOUR_MS * 24, timestamp: now - 12 * HOUR_MS },
'$1',
));
const beacon1 = new Beacon(
makeBeaconInfoEvent(aliceId, roomId, { timeout: HOUR_MS * 24, timestamp: now - 12 * HOUR_MS }, "$1"),
);
// 10h left
const beacon2 = new Beacon(makeBeaconInfoEvent(aliceId,
roomId,
{ timeout: HOUR_MS * 10, timestamp: now },
'$2',
));
const beacon2 = new Beacon(
makeBeaconInfoEvent(aliceId, roomId, { timeout: HOUR_MS * 10, timestamp: now }, "$2"),
);
// 1ms left
const beacon3 = new Beacon(makeBeaconInfoEvent(aliceId,
roomId,
{ timeout: HOUR_MS + 1, timestamp: now - HOUR_MS },
'$3',
));
const beacon3 = new Beacon(
makeBeaconInfoEvent(aliceId, roomId, { timeout: HOUR_MS + 1, timestamp: now - HOUR_MS }, "$3"),
);
it('sorts beacons by descending expiry time', () => {
expect([beacon2, beacon3, beacon1].sort(sortBeaconsByLatestExpiry)).toEqual([
beacon1, beacon2, beacon3,
]);
it("sorts beacons by descending expiry time", () => {
expect([beacon2, beacon3, beacon1].sort(sortBeaconsByLatestExpiry)).toEqual([beacon1, beacon2, beacon3]);
});
});
describe('sortBeaconsByLatestCreation()', () => {
const roomId = '!room:server';
const aliceId = '@alive:server';
describe("sortBeaconsByLatestCreation()", () => {
const roomId = "!room:server";
const aliceId = "@alive:server";
// 12h old, 12h left
const beacon1 = new Beacon(makeBeaconInfoEvent(aliceId,
roomId,
{ timeout: HOUR_MS * 24, timestamp: now - 12 * HOUR_MS },
'$1',
));
const beacon1 = new Beacon(
makeBeaconInfoEvent(aliceId, roomId, { timeout: HOUR_MS * 24, timestamp: now - 12 * HOUR_MS }, "$1"),
);
// 10h left
const beacon2 = new Beacon(makeBeaconInfoEvent(aliceId,
roomId,
{ timeout: HOUR_MS * 10, timestamp: now },
'$2',
));
const beacon2 = new Beacon(
makeBeaconInfoEvent(aliceId, roomId, { timeout: HOUR_MS * 10, timestamp: now }, "$2"),
);
// 1ms left
const beacon3 = new Beacon(makeBeaconInfoEvent(aliceId,
roomId,
{ timeout: HOUR_MS + 1, timestamp: now - HOUR_MS },
'$3',
));
const beacon3 = new Beacon(
makeBeaconInfoEvent(aliceId, roomId, { timeout: HOUR_MS + 1, timestamp: now - HOUR_MS }, "$3"),
);
it('sorts beacons by descending creation time', () => {
expect([beacon1, beacon2, beacon3].sort(sortBeaconsByLatestCreation)).toEqual([
beacon2, beacon3, beacon1,
]);
it("sorts beacons by descending creation time", () => {
expect([beacon1, beacon2, beacon3].sort(sortBeaconsByLatestCreation)).toEqual([beacon2, beacon3, beacon1]);
});
});
});

View File

@ -24,13 +24,9 @@ import {
watchPosition,
} from "../../../src/utils/beacon";
import { getCurrentPosition } from "../../../src/utils/beacon/geolocation";
import {
makeGeolocationPosition,
mockGeolocation,
getMockGeolocationPositionError,
} from "../../test-utils";
import { makeGeolocationPosition, mockGeolocation, getMockGeolocationPositionError } from "../../test-utils";
describe('geolocation utilities', () => {
describe("geolocation utilities", () => {
let geolocation;
const defaultPosition = makeGeolocationPosition({});
@ -39,15 +35,15 @@ describe('geolocation utilities', () => {
beforeEach(() => {
geolocation = mockGeolocation();
jest.spyOn(Date, 'now').mockReturnValue(now);
jest.spyOn(Date, "now").mockReturnValue(now);
});
afterEach(() => {
jest.spyOn(Date, 'now').mockRestore();
jest.spyOn(logger, 'error').mockRestore();
jest.spyOn(Date, "now").mockRestore();
jest.spyOn(logger, "error").mockRestore();
});
describe('getGeoUri', () => {
describe("getGeoUri", () => {
it("Renders a URI with only lat and lon", () => {
const pos = {
latitude: 43.2,
@ -106,50 +102,51 @@ describe('geolocation utilities', () => {
});
});
describe('mapGeolocationError', () => {
describe("mapGeolocationError", () => {
beforeEach(() => {
// suppress expected errors from test log
jest.spyOn(logger, 'error').mockImplementation(() => { });
jest.spyOn(logger, "error").mockImplementation(() => {});
});
it('returns default for other error', () => {
const error = new Error('oh no..');
it("returns default for other error", () => {
const error = new Error("oh no..");
expect(mapGeolocationError(error)).toEqual(GeolocationError.Default);
});
it('returns unavailable for unavailable error', () => {
it("returns unavailable for unavailable error", () => {
const error = new Error(GeolocationError.Unavailable);
expect(mapGeolocationError(error)).toEqual(GeolocationError.Unavailable);
});
it('maps geo error permissiondenied correctly', () => {
const error = getMockGeolocationPositionError(1, 'message');
it("maps geo error permissiondenied correctly", () => {
const error = getMockGeolocationPositionError(1, "message");
expect(mapGeolocationError(error)).toEqual(GeolocationError.PermissionDenied);
});
it('maps geo position unavailable error correctly', () => {
const error = getMockGeolocationPositionError(2, 'message');
it("maps geo position unavailable error correctly", () => {
const error = getMockGeolocationPositionError(2, "message");
expect(mapGeolocationError(error)).toEqual(GeolocationError.PositionUnavailable);
});
it('maps geo timeout error correctly', () => {
const error = getMockGeolocationPositionError(3, 'message');
it("maps geo timeout error correctly", () => {
const error = getMockGeolocationPositionError(3, "message");
expect(mapGeolocationError(error)).toEqual(GeolocationError.Timeout);
});
});
describe('mapGeolocationPositionToTimedGeo()', () => {
it('maps geolocation position correctly', () => {
describe("mapGeolocationPositionToTimedGeo()", () => {
it("maps geolocation position correctly", () => {
expect(mapGeolocationPositionToTimedGeo(defaultPosition)).toEqual({
timestamp: now, geoUri: 'geo:54.001927,-8.253491;u=1',
timestamp: now,
geoUri: "geo:54.001927,-8.253491;u=1",
});
});
});
describe('watchPosition()', () => {
it('throws with unavailable error when geolocation is not available', () => {
describe("watchPosition()", () => {
it("throws with unavailable error when geolocation is not available", () => {
// suppress expected errors from test log
jest.spyOn(logger, 'error').mockImplementation(() => { });
jest.spyOn(logger, "error").mockImplementation(() => {});
// remove the mock we added
// @ts-ignore illegal assignment to readonly property
@ -161,7 +158,7 @@ describe('geolocation utilities', () => {
expect(() => watchPosition(positionHandler, errorHandler)).toThrow(GeolocationError.Unavailable);
});
it('sets up position handler with correct options', () => {
it("sets up position handler with correct options", () => {
const positionHandler = jest.fn();
const errorHandler = jest.fn();
watchPosition(positionHandler, errorHandler);
@ -173,7 +170,7 @@ describe('geolocation utilities', () => {
});
});
it('returns clearWatch function', () => {
it("returns clearWatch function", () => {
const watchId = 1;
geolocation.watchPosition.mockReturnValue(watchId);
const positionHandler = jest.fn();
@ -185,7 +182,7 @@ describe('geolocation utilities', () => {
expect(geolocation.clearWatch).toHaveBeenCalledWith(watchId);
});
it('calls position handler with position', () => {
it("calls position handler with position", () => {
const positionHandler = jest.fn();
const errorHandler = jest.fn();
watchPosition(positionHandler, errorHandler);
@ -193,11 +190,11 @@ describe('geolocation utilities', () => {
expect(positionHandler).toHaveBeenCalledWith(defaultPosition);
});
it('maps geolocation position error and calls error handler', () => {
it("maps geolocation position error and calls error handler", () => {
// suppress expected errors from test log
jest.spyOn(logger, 'error').mockImplementation(() => { });
geolocation.watchPosition.mockImplementation(
(_callback, error) => error(getMockGeolocationPositionError(1, 'message')),
jest.spyOn(logger, "error").mockImplementation(() => {});
geolocation.watchPosition.mockImplementation((_callback, error) =>
error(getMockGeolocationPositionError(1, "message")),
);
const positionHandler = jest.fn();
const errorHandler = jest.fn();
@ -207,10 +204,10 @@ describe('geolocation utilities', () => {
});
});
describe('getCurrentPosition()', () => {
it('throws with unavailable error when geolocation is not available', async () => {
describe("getCurrentPosition()", () => {
it("throws with unavailable error when geolocation is not available", async () => {
// suppress expected errors from test log
jest.spyOn(logger, 'error').mockImplementation(() => { });
jest.spyOn(logger, "error").mockImplementation(() => {});
// remove the mock we added
// @ts-ignore illegal assignment to readonly property
@ -219,17 +216,17 @@ describe('geolocation utilities', () => {
await expect(() => getCurrentPosition()).rejects.toThrow(GeolocationError.Unavailable);
});
it('throws with geolocation error when geolocation.getCurrentPosition fails', async () => {
it("throws with geolocation error when geolocation.getCurrentPosition fails", async () => {
// suppress expected errors from test log
jest.spyOn(logger, 'error').mockImplementation(() => { });
jest.spyOn(logger, "error").mockImplementation(() => {});
const timeoutError = getMockGeolocationPositionError(3, 'message');
const timeoutError = getMockGeolocationPositionError(3, "message");
geolocation.getCurrentPosition.mockImplementation((callback, error) => error(timeoutError));
await expect(() => getCurrentPosition()).rejects.toThrow(GeolocationError.Timeout);
});
it('resolves with current location', async () => {
it("resolves with current location", async () => {
geolocation.getCurrentPosition.mockImplementation((callback, error) => callback(defaultPosition));
const result = await getCurrentPosition();

View File

@ -19,28 +19,28 @@ import { EventType, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { shouldDisplayAsBeaconTile } from "../../../src/utils/beacon/timeline";
import { makeBeaconInfoEvent } from "../../test-utils";
describe('shouldDisplayAsBeaconTile', () => {
const userId = '@user:server';
const roomId = '!room:server';
describe("shouldDisplayAsBeaconTile", () => {
const userId = "@user:server";
const roomId = "!room:server";
const liveBeacon = makeBeaconInfoEvent(userId, roomId, { isLive: true });
const notLiveBeacon = makeBeaconInfoEvent(userId, roomId, { isLive: false });
const memberEvent = new MatrixEvent({ type: EventType.RoomMember });
const redactedBeacon = makeBeaconInfoEvent(userId, roomId, { isLive: false });
redactedBeacon.makeRedacted(redactedBeacon);
it('returns true for a beacon with live property set to true', () => {
it("returns true for a beacon with live property set to true", () => {
expect(shouldDisplayAsBeaconTile(liveBeacon)).toBe(true);
});
it('returns true for a redacted beacon', () => {
it("returns true for a redacted beacon", () => {
expect(shouldDisplayAsBeaconTile(redactedBeacon)).toBe(true);
});
it('returns false for a beacon with live property set to false', () => {
it("returns false for a beacon with live property set to false", () => {
expect(shouldDisplayAsBeaconTile(notLiveBeacon)).toBe(false);
});
it('returns false for a non beacon event', () => {
it("returns false for a non beacon event", () => {
expect(shouldDisplayAsBeaconTile(memberEvent)).toBe(false);
});
});

View File

@ -17,8 +17,8 @@ limitations under the License.
import { textToHtmlRainbow } from "../../src/utils/colour";
describe("textToHtmlRainbow", () => {
it('correctly transform text to html without splitting the emoji in two', () => {
expect(textToHtmlRainbow('🐻')).toBe('<font color="#ff00be">🐻</font>');
expect(textToHtmlRainbow('🐕‍🦺')).toBe('<font color="#ff00be">🐕‍🦺</font>');
it("correctly transform text to html without splitting the emoji in two", () => {
expect(textToHtmlRainbow("🐻")).toBe('<font color="#ff00be">🐻</font>');
expect(textToHtmlRainbow("🐕‍🦺")).toBe('<font color="#ff00be">🐕‍🦺</font>');
});
});

View File

@ -20,13 +20,15 @@ import { createVoiceMessageContent } from "../../src/utils/createVoiceMessageCon
describe("createVoiceMessageContent", () => {
it("should create a voice message content", () => {
expect(createVoiceMessageContent(
"mxc://example.com/file",
"ogg/opus",
23000,
42000,
{} as unknown as IEncryptedFile,
[1, 2, 3],
)).toMatchSnapshot();
expect(
createVoiceMessageContent(
"mxc://example.com/file",
"ogg/opus",
23000,
42000,
{} as unknown as IEncryptedFile,
[1, 2, 3],
),
).toMatchSnapshot();
});
});

View File

@ -18,15 +18,12 @@ import { MatrixEvent } from "matrix-js-sdk/src/matrix";
import BasePlatform from "../../../src/BasePlatform";
import { IConfigOptions } from "../../../src/IConfigOptions";
import {
getDeviceClientInformation,
recordClientInformation,
} from "../../../src/utils/device/clientInformation";
import { getDeviceClientInformation, recordClientInformation } from "../../../src/utils/device/clientInformation";
import { getMockClientWithEventEmitter } from "../../test-utils";
describe('recordClientInformation()', () => {
const deviceId = 'my-device-id';
const version = '1.2.3';
describe("recordClientInformation()", () => {
const deviceId = "my-device-id";
const version = "1.2.3";
const isElectron = window.electron;
const mockClient = getMockClientWithEventEmitter({
@ -35,8 +32,8 @@ describe('recordClientInformation()', () => {
});
const sdkConfig: IConfigOptions = {
brand: 'Test Brand',
element_call: { url: '', use_exclusively: false, brand: "Element Call" },
brand: "Test Brand",
element_call: { url: "", use_exclusively: false, brand: "Element Call" },
};
const platform = {
@ -53,45 +50,31 @@ describe('recordClientInformation()', () => {
window.electron = isElectron;
});
it('saves client information without url for electron clients', async () => {
it("saves client information without url for electron clients", async () => {
window.electron = true;
await recordClientInformation(
mockClient,
sdkConfig,
platform,
);
await recordClientInformation(mockClient, sdkConfig, platform);
expect(mockClient.setAccountData).toHaveBeenCalledWith(
`io.element.matrix_client_information.${deviceId}`,
{
name: sdkConfig.brand,
version,
url: undefined,
},
);
expect(mockClient.setAccountData).toHaveBeenCalledWith(`io.element.matrix_client_information.${deviceId}`, {
name: sdkConfig.brand,
version,
url: undefined,
});
});
it('saves client information with url for non-electron clients', async () => {
await recordClientInformation(
mockClient,
sdkConfig,
platform,
);
it("saves client information with url for non-electron clients", async () => {
await recordClientInformation(mockClient, sdkConfig, platform);
expect(mockClient.setAccountData).toHaveBeenCalledWith(
`io.element.matrix_client_information.${deviceId}`,
{
name: sdkConfig.brand,
version,
url: 'localhost',
},
);
expect(mockClient.setAccountData).toHaveBeenCalledWith(`io.element.matrix_client_information.${deviceId}`, {
name: sdkConfig.brand,
version,
url: "localhost",
});
});
});
describe('getDeviceClientInformation()', () => {
const deviceId = 'my-device-id';
describe("getDeviceClientInformation()", () => {
const deviceId = "my-device-id";
const mockClient = getMockClientWithEventEmitter({
getAccountData: jest.fn(),
@ -101,19 +84,17 @@ describe('getDeviceClientInformation()', () => {
jest.resetAllMocks();
});
it('returns an empty object when no event exists for the device', () => {
it("returns an empty object when no event exists for the device", () => {
expect(getDeviceClientInformation(mockClient, deviceId)).toEqual({});
expect(mockClient.getAccountData).toHaveBeenCalledWith(
`io.element.matrix_client_information.${deviceId}`,
);
expect(mockClient.getAccountData).toHaveBeenCalledWith(`io.element.matrix_client_information.${deviceId}`);
});
it('returns client information for the device', () => {
it("returns client information for the device", () => {
const eventContent = {
name: 'Element Web',
version: '1.2.3',
url: 'test.com',
name: "Element Web",
version: "1.2.3",
url: "test.com",
};
const event = new MatrixEvent({
type: `io.element.matrix_client_information.${deviceId}`,
@ -123,13 +104,13 @@ describe('getDeviceClientInformation()', () => {
expect(getDeviceClientInformation(mockClient, deviceId)).toEqual(eventContent);
});
it('excludes values with incorrect types', () => {
it("excludes values with incorrect types", () => {
const eventContent = {
extraField: 'hello',
name: 'Element Web',
extraField: "hello",
name: "Element Web",
// wrong format
version: { value: '1.2.3' },
url: 'test.com',
version: { value: "1.2.3" },
url: "test.com",
};
const event = new MatrixEvent({
type: `io.element.matrix_client_information.${deviceId}`,
@ -143,4 +124,3 @@ describe('getDeviceClientInformation()', () => {
});
});
});

View File

@ -26,7 +26,7 @@ const makeDeviceExtendedInfo = (
deviceType,
deviceModel,
deviceOperatingSystem,
client: clientName && [clientName, clientVersion].filter(Boolean).join(' '),
client: clientName && [clientName, clientVersion].filter(Boolean).join(" "),
});
/* eslint-disable max-len */
@ -66,7 +66,7 @@ const IOS_EXPECTED_RESULT = [
];
const DESKTOP_UA = [
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) ElementNightly/2022091301 Chrome/104.0.5112.102" +
" Electron/20.1.1 Safari/537.36",
" Electron/20.1.1 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) ElementNightly/2022091301 Chrome/104.0.5112.102 Electron/20.1.1 Safari/537.36",
];
const DESKTOP_EXPECTED_RESULT = [
@ -98,7 +98,6 @@ const WEB_EXPECTED_RESULT = [
makeDeviceExtendedInfo(DeviceType.Web, "Apple iPad", "iOS", "Mobile Safari", "8.0"),
makeDeviceExtendedInfo(DeviceType.Web, "Apple iPhone", "iOS", "Mobile Safari", "8.0"),
makeDeviceExtendedInfo(DeviceType.Web, "Samsung SM-G973U", "Android", "Chrome", "69.0.3497.100"),
];
const MISC_UA = [
@ -119,8 +118,8 @@ const MISC_EXPECTED_RESULT = [
];
/* eslint-disable max-len */
describe('parseUserAgent()', () => {
it('returns deviceType unknown when user agent is falsy', () => {
describe("parseUserAgent()", () => {
it("returns deviceType unknown when user agent is falsy", () => {
expect(parseUserAgent(undefined)).toEqual({
deviceType: DeviceType.Unknown,
});
@ -132,17 +131,15 @@ describe('parseUserAgent()', () => {
const testCases: TestCase[] = userAgents.map((userAgent, index) => [userAgent, results[index]]);
describe(platform, () => {
it.each(
testCases,
)('Parses user agent correctly - %s', (userAgent, expectedResult) => {
it.each(testCases)("Parses user agent correctly - %s", (userAgent, expectedResult) => {
expect(parseUserAgent(userAgent)).toEqual(expectedResult);
});
});
};
testPlatform('Android', ANDROID_UA, ANDROID_EXPECTED_RESULT);
testPlatform('iOS', IOS_UA, IOS_EXPECTED_RESULT);
testPlatform('Desktop', DESKTOP_UA, DESKTOP_EXPECTED_RESULT);
testPlatform('Web', WEB_UA, WEB_EXPECTED_RESULT);
testPlatform('Misc', MISC_UA, MISC_EXPECTED_RESULT);
testPlatform("Android", ANDROID_UA, ANDROID_EXPECTED_RESULT);
testPlatform("iOS", IOS_UA, IOS_EXPECTED_RESULT);
testPlatform("Desktop", DESKTOP_UA, DESKTOP_EXPECTED_RESULT);
testPlatform("Web", WEB_UA, WEB_EXPECTED_RESULT);
testPlatform("Misc", MISC_UA, MISC_EXPECTED_RESULT);
});

View File

@ -21,12 +21,12 @@ import {
snoozeBulkUnverifiedDeviceReminder,
} from "../../../src/utils/device/snoozeBulkUnverifiedDeviceReminder";
const SNOOZE_KEY = 'mx_snooze_bulk_unverified_device_nag';
const SNOOZE_KEY = "mx_snooze_bulk_unverified_device_nag";
describe('snooze bulk unverified device nag', () => {
const localStorageSetSpy = jest.spyOn(localStorage.__proto__, 'setItem');
const localStorageGetSpy = jest.spyOn(localStorage.__proto__, 'getItem');
const localStorageRemoveSpy = jest.spyOn(localStorage.__proto__, 'removeItem');
describe("snooze bulk unverified device nag", () => {
const localStorageSetSpy = jest.spyOn(localStorage.__proto__, "setItem");
const localStorageGetSpy = jest.spyOn(localStorage.__proto__, "getItem");
const localStorageRemoveSpy = jest.spyOn(localStorage.__proto__, "removeItem");
// 14.03.2022 16:15
const now = 1647270879403;
@ -36,61 +36,65 @@ describe('snooze bulk unverified device nag', () => {
localStorageGetSpy.mockClear().mockReturnValue(null);
localStorageRemoveSpy.mockClear().mockImplementation(() => {});
jest.spyOn(Date, 'now').mockReturnValue(now);
jest.spyOn(Date, "now").mockReturnValue(now);
});
afterAll(() => {
jest.restoreAllMocks();
});
describe('snoozeBulkUnverifiedDeviceReminder()', () => {
it('sets the current time in local storage', () => {
describe("snoozeBulkUnverifiedDeviceReminder()", () => {
it("sets the current time in local storage", () => {
snoozeBulkUnverifiedDeviceReminder();
expect(localStorageSetSpy).toHaveBeenCalledWith(SNOOZE_KEY, now.toString());
});
it('catches an error from localstorage', () => {
const loggerErrorSpy = jest.spyOn(logger, 'error');
localStorageSetSpy.mockImplementation(() => { throw new Error('oups'); });
it("catches an error from localstorage", () => {
const loggerErrorSpy = jest.spyOn(logger, "error");
localStorageSetSpy.mockImplementation(() => {
throw new Error("oups");
});
snoozeBulkUnverifiedDeviceReminder();
expect(loggerErrorSpy).toHaveBeenCalled();
});
});
describe('isBulkUnverifiedDeviceReminderSnoozed()', () => {
it('returns false when there is no snooze in storage', () => {
describe("isBulkUnverifiedDeviceReminderSnoozed()", () => {
it("returns false when there is no snooze in storage", () => {
const result = isBulkUnverifiedDeviceReminderSnoozed();
expect(localStorageGetSpy).toHaveBeenCalledWith(SNOOZE_KEY);
expect(result).toBe(false);
});
it('catches an error from localstorage and returns false', () => {
const loggerErrorSpy = jest.spyOn(logger, 'error');
localStorageGetSpy.mockImplementation(() => { throw new Error('oups'); });
it("catches an error from localstorage and returns false", () => {
const loggerErrorSpy = jest.spyOn(logger, "error");
localStorageGetSpy.mockImplementation(() => {
throw new Error("oups");
});
const result = isBulkUnverifiedDeviceReminderSnoozed();
expect(result).toBe(false);
expect(loggerErrorSpy).toHaveBeenCalled();
});
it('returns false when snooze timestamp in storage is not a number', () => {
localStorageGetSpy.mockReturnValue('test');
it("returns false when snooze timestamp in storage is not a number", () => {
localStorageGetSpy.mockReturnValue("test");
const result = isBulkUnverifiedDeviceReminderSnoozed();
expect(result).toBe(false);
});
it('returns false when snooze timestamp in storage is over a week ago', () => {
it("returns false when snooze timestamp in storage is over a week ago", () => {
const msDay = 1000 * 60 * 60 * 24;
// snoozed 8 days ago
localStorageGetSpy.mockReturnValue(now - (msDay * 8));
localStorageGetSpy.mockReturnValue(now - msDay * 8);
const result = isBulkUnverifiedDeviceReminderSnoozed();
expect(result).toBe(false);
});
it('returns true when snooze timestamp in storage is less than a week ago', () => {
it("returns true when snooze timestamp in storage is less than a week ago", () => {
const msDay = 1000 * 60 * 60 * 24;
// snoozed 8 days ago
localStorageGetSpy.mockReturnValue(now - (msDay * 6));
localStorageGetSpy.mockReturnValue(now - msDay * 6);
const result = isBulkUnverifiedDeviceReminderSnoozed();
expect(result).toBe(true);
});

View File

@ -158,18 +158,12 @@ describe("direct-messages", () => {
mocked(startDm).mockResolvedValue(room1.roomId);
});
it(
"should set the room into creating state and call waitForRoomReadyAndApplyAfterCreateCallbacks",
async () => {
const result = await dmModule.createRoomFromLocalRoom(mockClient, localRoom);
expect(result).toBe(room1.roomId);
expect(localRoom.state).toBe(LocalRoomState.CREATING);
expect(waitForRoomReadyAndApplyAfterCreateCallbacks).toHaveBeenCalledWith(
mockClient,
localRoom,
);
},
);
it("should set the room into creating state and call waitForRoomReadyAndApplyAfterCreateCallbacks", async () => {
const result = await dmModule.createRoomFromLocalRoom(mockClient, localRoom);
expect(result).toBe(room1.roomId);
expect(localRoom.state).toBe(LocalRoomState.CREATING);
expect(waitForRoomReadyAndApplyAfterCreateCallbacks).toHaveBeenCalledWith(mockClient, localRoom);
});
});
});
});

View File

@ -26,16 +26,16 @@ enum TestNumberEnum {
SecondKey = 20,
}
describe('enums', () => {
describe('getEnumValues', () => {
it('should work on string enums', () => {
describe("enums", () => {
describe("getEnumValues", () => {
it("should work on string enums", () => {
const result = getEnumValues(TestStringEnum);
expect(result).toBeDefined();
expect(result).toHaveLength(2);
expect(result).toEqual(['__first__', '__second__']);
expect(result).toEqual(["__first__", "__second__"]);
});
it('should work on number enums', () => {
it("should work on number enums", () => {
const result = getEnumValues(TestNumberEnum);
expect(result).toBeDefined();
expect(result).toHaveLength(2);
@ -43,23 +43,23 @@ describe('enums', () => {
});
});
describe('isEnumValue', () => {
it('should return true on values in a string enum', () => {
const result = isEnumValue(TestStringEnum, '__first__');
describe("isEnumValue", () => {
it("should return true on values in a string enum", () => {
const result = isEnumValue(TestStringEnum, "__first__");
expect(result).toBe(true);
});
it('should return false on values not in a string enum', () => {
const result = isEnumValue(TestStringEnum, 'not a value');
it("should return false on values not in a string enum", () => {
const result = isEnumValue(TestStringEnum, "not a value");
expect(result).toBe(false);
});
it('should return true on values in a number enum', () => {
it("should return true on values in a number enum", () => {
const result = isEnumValue(TestNumberEnum, 10);
expect(result).toBe(true);
});
it('should return false on values not in a number enum', () => {
it("should return false on values not in a number enum", () => {
const result = isEnumValue(TestStringEnum, 99);
expect(result).toBe(false);
});

View File

@ -29,22 +29,22 @@ import { MatrixClientPeg } from "../../src/MatrixClientPeg";
import { IExportOptions, ExportType, ExportFormat } from "../../src/utils/exportUtils/exportUtils";
import PlainTextExporter from "../../src/utils/exportUtils/PlainTextExport";
import HTMLExporter from "../../src/utils/exportUtils/HtmlExport";
import * as TestUtilsMatrix from '../test-utils';
import { stubClient } from '../test-utils';
import * as TestUtilsMatrix from "../test-utils";
import { stubClient } from "../test-utils";
let client: MatrixClient;
const MY_USER_ID = "@me:here";
function generateRoomId() {
return '!' + Math.random().toString().slice(2, 10) + ':domain';
return "!" + Math.random().toString().slice(2, 10) + ":domain";
}
interface ITestContent extends IContent {
expectedText: string;
}
describe('export', function() {
describe("export", function () {
stubClient();
client = MatrixClientPeg.get();
client.getUserId = () => {
@ -71,20 +71,20 @@ describe('export', function() {
sender: MY_USER_ID,
content: {},
unsigned: {
"age": 72,
"transaction_id": "m1212121212.23",
"redacted_because": {
"content": {},
"origin_server_ts": ts0 + i*1000,
"redacts": "$9999999999999999999999999999999999999999998",
"sender": "@me:here",
"type": EventType.RoomRedaction,
"unsigned": {
"age": 94,
"transaction_id": "m1111111111.1",
age: 72,
transaction_id: "m1212121212.23",
redacted_because: {
content: {},
origin_server_ts: ts0 + i * 1000,
redacts: "$9999999999999999999999999999999999999999998",
sender: "@me:here",
type: EventType.RoomRedaction,
unsigned: {
age: 94,
transaction_id: "m1111111111.1",
},
"event_id": "$9999999999999999999999999999999999999999998",
"room_id": mockRoom.roomId,
event_id: "$9999999999999999999999999999999999999999998",
room_id: mockRoom.roomId,
},
},
event_id: "$9999999999999999999999999999999999999999999",
@ -94,47 +94,47 @@ describe('export', function() {
function mkFileEvent() {
return new MatrixEvent({
"content": {
"body": "index.html",
"info": {
"mimetype": "text/html",
"size": 31613,
content: {
body: "index.html",
info: {
mimetype: "text/html",
size: 31613,
},
"msgtype": "m.file",
"url": "mxc://test.org",
msgtype: "m.file",
url: "mxc://test.org",
},
"origin_server_ts": 1628872988364,
"sender": MY_USER_ID,
"type": "m.room.message",
"unsigned": {
"age": 266,
"transaction_id": "m99999999.2",
origin_server_ts: 1628872988364,
sender: MY_USER_ID,
type: "m.room.message",
unsigned: {
age: 266,
transaction_id: "m99999999.2",
},
"event_id": "$99999999999999999999",
"room_id": mockRoom.roomId,
event_id: "$99999999999999999999",
room_id: mockRoom.roomId,
});
}
function mkImageEvent() {
return new MatrixEvent({
"content": {
"body": "image.png",
"info": {
"mimetype": "image/png",
"size": 31613,
content: {
body: "image.png",
info: {
mimetype: "image/png",
size: 31613,
},
"msgtype": "m.image",
"url": "mxc://test.org",
msgtype: "m.image",
url: "mxc://test.org",
},
"origin_server_ts": 1628872988364,
"sender": MY_USER_ID,
"type": "m.room.message",
"unsigned": {
"age": 266,
"transaction_id": "m99999999.2",
origin_server_ts: 1628872988364,
sender: MY_USER_ID,
type: "m.room.message",
unsigned: {
age: 266,
transaction_id: "m99999999.2",
},
"event_id": "$99999999999999999999",
"room_id": mockRoom.roomId,
event_id: "$99999999999999999999",
room_id: mockRoom.roomId,
});
}
@ -143,62 +143,74 @@ describe('export', function() {
let i: number;
// plain text
for (i = 0; i < 10; i++) {
matrixEvents.push(TestUtilsMatrix.mkMessage({
event: true, room: "!room:id", user: "@user:id",
ts: ts0 + i * 1000,
}));
matrixEvents.push(
TestUtilsMatrix.mkMessage({
event: true,
room: "!room:id",
user: "@user:id",
ts: ts0 + i * 1000,
}),
);
}
// reply events
for (i = 0; i < 10; i++) {
const eventId = "$" + Math.random() + "-" + Math.random();
matrixEvents.push(TestUtilsMatrix.mkEvent({
"content": {
"body": "> <@me:here> Hi\n\nTest",
"format": "org.matrix.custom.html",
"m.relates_to": {
"rel_type": RelationType.Reference,
"event_id": eventId,
"m.in_reply_to": {
matrixEvents.push(
TestUtilsMatrix.mkEvent({
content: {
"body": "> <@me:here> Hi\n\nTest",
"format": "org.matrix.custom.html",
"m.relates_to": {
"rel_type": RelationType.Reference,
"event_id": eventId,
"m.in_reply_to": {
event_id: eventId,
},
},
"msgtype": "m.text",
},
"msgtype": "m.text",
},
"user": "@me:here",
"type": "m.room.message",
"room": mockRoom.roomId,
"event": true,
}));
user: "@me:here",
type: "m.room.message",
room: mockRoom.roomId,
event: true,
}),
);
}
// membership events
for (i = 0; i < 10; i++) {
matrixEvents.push(TestUtilsMatrix.mkMembership({
event: true, room: "!room:id", user: "@user:id",
target: {
userId: "@user:id",
name: "Bob",
getAvatarUrl: () => {
return "avatar.jpeg";
},
getMxcAvatarUrl: () => 'mxc://avatar.url/image.png',
} as unknown as RoomMember,
ts: ts0 + i*1000,
mship: 'join',
prevMship: 'join',
name: 'A user',
}));
matrixEvents.push(
TestUtilsMatrix.mkMembership({
event: true,
room: "!room:id",
user: "@user:id",
target: {
userId: "@user:id",
name: "Bob",
getAvatarUrl: () => {
return "avatar.jpeg";
},
getMxcAvatarUrl: () => "mxc://avatar.url/image.png",
} as unknown as RoomMember,
ts: ts0 + i * 1000,
mship: "join",
prevMship: "join",
name: "A user",
}),
);
}
// emote
matrixEvents.push(TestUtilsMatrix.mkEvent({
"content": {
"body": "waves",
"msgtype": "m.emote",
},
"user": "@me:here",
"type": "m.room.message",
"room": mockRoom.roomId,
"event": true,
}));
matrixEvents.push(
TestUtilsMatrix.mkEvent({
content: {
body: "waves",
msgtype: "m.emote",
},
user: "@me:here",
type: "m.room.message",
room: mockRoom.roomId,
event: true,
}),
);
// redacted events
for (i = 0; i < 10; i++) {
matrixEvents.push(mkRedactedEvent(i));
@ -208,7 +220,7 @@ describe('export', function() {
const events: MatrixEvent[] = mkEvents();
it('checks if the export format is valid', function() {
it("checks if the export format is valid", function () {
function isValidFormat(format: string): boolean {
const options: string[] = Object.values(ExportFormat);
return options.includes(format);
@ -219,51 +231,60 @@ describe('export', function() {
expect(isValidFormat("Pdf")).toBeFalsy();
});
it("checks if the icons' html corresponds to export regex", function() {
it("checks if the icons' html corresponds to export regex", function () {
const exporter = new HTMLExporter(mockRoom, ExportType.Beginning, mockExportOptions, null);
const fileRegex = /<span class="mx_MFileBody_info_icon">.*?<\/span>/;
expect(fileRegex.test(
renderToString(exporter.getEventTile(mkFileEvent(), true))),
).toBeTruthy();
expect(fileRegex.test(renderToString(exporter.getEventTile(mkFileEvent(), true)))).toBeTruthy();
});
it("should export images if attachments are enabled", () => {
const exporter = new HTMLExporter(mockRoom, ExportType.Beginning, {
numberOfMessages: 5,
maxSize: 100 * 1024 * 1024,
attachmentsIncluded: true,
}, null);
const exporter = new HTMLExporter(
mockRoom,
ExportType.Beginning,
{
numberOfMessages: 5,
maxSize: 100 * 1024 * 1024,
attachmentsIncluded: true,
},
null,
);
const imageRegex = /<img.+ src="mxc:\/\/test.org" alt="image.png"\/>/;
expect(imageRegex.test(
renderToString(exporter.getEventTile(mkImageEvent(), true))),
).toBeTruthy();
expect(imageRegex.test(renderToString(exporter.getEventTile(mkImageEvent(), true)))).toBeTruthy();
});
const invalidExportOptions: [string, IExportOptions][] = [
['numberOfMessages exceeds max', {
numberOfMessages: 10 ** 9,
maxSize: 1024 * 1024 * 1024,
attachmentsIncluded: false,
}],
['maxSize exceeds 8GB', {
numberOfMessages: -1,
maxSize: 8001 * 1024 * 1024,
attachmentsIncluded: false,
}],
['maxSize is less than 1mb', {
numberOfMessages: 0,
maxSize: 0,
attachmentsIncluded: false,
}],
[
"numberOfMessages exceeds max",
{
numberOfMessages: 10 ** 9,
maxSize: 1024 * 1024 * 1024,
attachmentsIncluded: false,
},
],
[
"maxSize exceeds 8GB",
{
numberOfMessages: -1,
maxSize: 8001 * 1024 * 1024,
attachmentsIncluded: false,
},
],
[
"maxSize is less than 1mb",
{
numberOfMessages: 0,
maxSize: 0,
attachmentsIncluded: false,
},
],
];
it.each(invalidExportOptions)('%s', (_d, options) => {
expect(
() =>
new PlainTextExporter(mockRoom, ExportType.Beginning, options, null),
).toThrowError("Invalid export options");
it.each(invalidExportOptions)("%s", (_d, options) => {
expect(() => new PlainTextExporter(mockRoom, ExportType.Beginning, options, null)).toThrowError(
"Invalid export options",
);
});
it('tests the file extension splitter', function() {
it("tests the file extension splitter", function () {
const exporter = new PlainTextExporter(mockRoom, ExportType.Beginning, mockExportOptions, null);
const fileNameWithExtensions = {
"": ["", ""],
@ -277,28 +298,28 @@ describe('export', function() {
}
});
it('checks if the reply regex executes correctly', function() {
it("checks if the reply regex executes correctly", function () {
const eventContents: ITestContent[] = [
{
"msgtype": "m.text",
"body": "> <@me:here> Source\n\nReply",
"expectedText": "<@me:here \"Source\"> Reply",
msgtype: "m.text",
body: "> <@me:here> Source\n\nReply",
expectedText: '<@me:here "Source"> Reply',
},
{
"msgtype": "m.text",
msgtype: "m.text",
// if the reply format is invalid, then return the body
"body": "Invalid reply format",
"expectedText": "Invalid reply format",
body: "Invalid reply format",
expectedText: "Invalid reply format",
},
{
"msgtype": "m.text",
"body": "> <@me:here> The source is more than 32 characters\n\nReply",
"expectedText": "<@me:here \"The source is more than 32 chara...\"> Reply",
msgtype: "m.text",
body: "> <@me:here> The source is more than 32 characters\n\nReply",
expectedText: '<@me:here "The source is more than 32 chara..."> Reply',
},
{
"msgtype": "m.text",
"body": "> <@me:here> This\nsource\nhas\nnew\nlines\n\nReply",
"expectedText": "<@me:here \"This\"> Reply",
msgtype: "m.text",
body: "> <@me:here> This\nsource\nhas\nnew\nlines\n\nReply",
expectedText: '<@me:here "This"> Reply',
},
];
const exporter = new PlainTextExporter(mockRoom, ExportType.Beginning, mockExportOptions, null);
@ -307,11 +328,10 @@ describe('export', function() {
}
});
it("checks if the render to string doesn't throw any error for different types of events", function() {
it("checks if the render to string doesn't throw any error for different types of events", function () {
const exporter = new HTMLExporter(mockRoom, ExportType.Beginning, mockExportOptions, null);
for (const event of events) {
expect(renderToString(exporter.getEventTile(event, false))).toBeTruthy();
}
});
});

View File

@ -16,9 +16,9 @@ limitations under the License.
import { iterableDiff, iterableIntersection } from "../../src/utils/iterables";
describe('iterables', () => {
describe('iterableIntersection', () => {
it('should return the intersection', () => {
describe("iterables", () => {
describe("iterableIntersection", () => {
it("should return the intersection", () => {
const a = [1, 2, 3];
const b = [1, 2, 4]; // note diff
const result = iterableIntersection(a, b);
@ -27,7 +27,7 @@ describe('iterables', () => {
expect(result).toEqual([1, 2]);
});
it('should return an empty array on no matches', () => {
it("should return an empty array on no matches", () => {
const a = [1, 2, 3];
const b = [4, 5, 6];
const result = iterableIntersection(a, b);
@ -36,8 +36,8 @@ describe('iterables', () => {
});
});
describe('iterableDiff', () => {
it('should see added from A->B', () => {
describe("iterableDiff", () => {
it("should see added from A->B", () => {
const a = [1, 2, 3];
const b = [1, 2, 3, 4];
const result = iterableDiff(a, b);
@ -49,7 +49,7 @@ describe('iterables', () => {
expect(result.added).toEqual([4]);
});
it('should see removed from A->B', () => {
it("should see removed from A->B", () => {
const a = [1, 2, 3];
const b = [1, 2];
const result = iterableDiff(a, b);
@ -61,7 +61,7 @@ describe('iterables', () => {
expect(result.removed).toEqual([3]);
});
it('should see added and removed in the same set', () => {
it("should see added and removed in the same set", () => {
const a = [1, 2, 3];
const b = [1, 2, 4]; // note diff
const result = iterableDiff(a, b);

View File

@ -45,11 +45,14 @@ describe("leaveRoomBehaviour", () => {
room = mkRoom(client, "!1:example.org");
space = mkRoom(client, "!2:example.org");
space.isSpaceRoom.mockReturnValue(true);
client.getRoom.mockImplementation(roomId => {
client.getRoom.mockImplementation((roomId) => {
switch (roomId) {
case room.roomId: return room;
case space.roomId: return space;
default: return null;
case room.roomId:
return room;
case space.roomId:
return space;
default:
return null;
}
});
@ -62,16 +65,20 @@ describe("leaveRoomBehaviour", () => {
jest.restoreAllMocks();
});
const viewRoom = (room: Room) => defaultDispatcher.dispatch<ViewRoomPayload>({
action: Action.ViewRoom,
room_id: room.roomId,
metricsTrigger: undefined,
}, true);
const viewRoom = (room: Room) =>
defaultDispatcher.dispatch<ViewRoomPayload>(
{
action: Action.ViewRoom,
room_id: room.roomId,
metricsTrigger: undefined,
},
true,
);
const expectDispatch = async <T extends ActionPayload>(payload: T) => {
const dispatcherSpy = jest.fn();
const dispatcherRef = defaultDispatcher.register(dispatcherSpy);
await new Promise<void>(resolve => setImmediate(resolve)); // Flush the dispatcher
await new Promise<void>((resolve) => setImmediate(resolve)); // Flush the dispatcher
expect(dispatcherSpy).toHaveBeenCalledWith(payload);
defaultDispatcher.unregister(dispatcherRef);
};
@ -84,8 +91,8 @@ describe("leaveRoomBehaviour", () => {
});
it("returns to the parent space after leaving a room inside of a space that was being viewed", async () => {
jest.spyOn(SpaceStore.instance, "getCanonicalParent").mockImplementation(
roomId => roomId === room.roomId ? space : null,
jest.spyOn(SpaceStore.instance, "getCanonicalParent").mockImplementation((roomId) =>
roomId === room.roomId ? space : null,
);
viewRoom(room);
SpaceStore.instance.setActiveSpace(space.roomId, false);
@ -108,8 +115,8 @@ describe("leaveRoomBehaviour", () => {
it("returns to the parent space after leaving a subspace that was being viewed", async () => {
room.isSpaceRoom.mockReturnValue(true);
jest.spyOn(SpaceStore.instance, "getCanonicalParent").mockImplementation(
roomId => roomId === room.roomId ? space : null,
jest.spyOn(SpaceStore.instance, "getCanonicalParent").mockImplementation((roomId) =>
roomId === room.roomId ? space : null,
);
viewRoom(room);
SpaceStore.instance.setActiveSpace(room.roomId, false);

View File

@ -80,13 +80,15 @@ describe("isRoomReady", () => {
describe("and a RoomHistoryVisibility event", () => {
beforeEach(() => {
room1.currentState.setStateEvents([mkEvent({
user: userId1,
event: true,
type: EventType.RoomHistoryVisibility,
room: room1.roomId,
content: {},
})]);
room1.currentState.setStateEvents([
mkEvent({
user: userId1,
event: true,
type: EventType.RoomHistoryVisibility,
room: room1.roomId,
content: {},
}),
]);
});
it("it should return true", () => {
@ -104,13 +106,15 @@ describe("isRoomReady", () => {
describe("and a room encryption state event", () => {
beforeEach(() => {
room1.currentState.setStateEvents([mkEvent({
user: userId1,
event: true,
type: EventType.RoomEncryption,
room: room1.roomId,
content: {},
})]);
room1.currentState.setStateEvents([
mkEvent({
user: userId1,
event: true,
type: EventType.RoomEncryption,
room: room1.roomId,
content: {},
}),
]);
});
it("it should return true", () => {
@ -123,4 +127,3 @@ describe("isRoomReady", () => {
});
});
});

View File

@ -28,7 +28,7 @@ import { isSelfLocation } from "../../../src/utils/location";
describe("isSelfLocation", () => {
it("Returns true for a full m.asset event", () => {
const content = makeLocationContent("", '0', Date.now());
const content = makeLocationContent("", "0", Date.now());
expect(isSelfLocation(content)).toBe(true);
});
@ -62,11 +62,12 @@ describe("isSelfLocation", () => {
it("Returns false for an unknown asset type", () => {
const content = makeLocationContent(
undefined, /* text */
undefined /* text */,
"geo:foo",
0,
undefined, /* description */
"org.example.unknown" as unknown as LocationAssetType);
undefined /* description */,
"org.example.unknown" as unknown as LocationAssetType,
);
expect(isSelfLocation(content)).toBe(false);
});
});

View File

@ -17,12 +17,12 @@ limitations under the License.
import { locationEventGeoUri } from "../../../src/utils/location";
import { makeLegacyLocationEvent, makeLocationEvent } from "../../test-utils/location";
describe('locationEventGeoUri()', () => {
it('returns m.location uri when available', () => {
describe("locationEventGeoUri()", () => {
it("returns m.location uri when available", () => {
expect(locationEventGeoUri(makeLocationEvent("geo:51.5076,-0.1276"))).toEqual("geo:51.5076,-0.1276");
});
it('returns legacy uri when m.location content not found', () => {
it("returns legacy uri when m.location content not found", () => {
expect(locationEventGeoUri(makeLegacyLocationEvent("geo:51.5076,-0.1276"))).toEqual("geo:51.5076,-0.1276");
});
});

View File

@ -20,28 +20,26 @@ import { makeLegacyLocationEvent, makeLocationEvent } from "../../test-utils/loc
describe("createMapSiteLinkFromEvent", () => {
it("returns null if event does not contain geouri", () => {
expect(createMapSiteLinkFromEvent(mkMessage({
room: '1', user: '@sender:server', event: true,
}))).toBeNull();
expect(
createMapSiteLinkFromEvent(
mkMessage({
room: "1",
user: "@sender:server",
event: true,
}),
),
).toBeNull();
});
it("returns OpenStreetMap link if event contains m.location", () => {
expect(
createMapSiteLinkFromEvent(makeLocationEvent("geo:51.5076,-0.1276")),
).toEqual(
"https://www.openstreetmap.org/" +
"?mlat=51.5076&mlon=-0.1276" +
"#map=16/51.5076/-0.1276",
expect(createMapSiteLinkFromEvent(makeLocationEvent("geo:51.5076,-0.1276"))).toEqual(
"https://www.openstreetmap.org/" + "?mlat=51.5076&mlon=-0.1276" + "#map=16/51.5076/-0.1276",
);
});
it("returns OpenStreetMap link if event contains geo_uri", () => {
expect(
createMapSiteLinkFromEvent(makeLegacyLocationEvent("geo:51.5076,-0.1276")),
).toEqual(
"https://www.openstreetmap.org/" +
"?mlat=51.5076&mlon=-0.1276" +
"#map=16/51.5076/-0.1276",
expect(createMapSiteLinkFromEvent(makeLegacyLocationEvent("geo:51.5076,-0.1276"))).toEqual(
"https://www.openstreetmap.org/" + "?mlat=51.5076&mlon=-0.1276" + "#map=16/51.5076/-0.1276",
);
});
});

View File

@ -30,128 +30,110 @@ describe("parseGeoUri", () => {
// these, but it is permitted, and we will fail to parse in that case.
it("rfc5870 6.1 Simple 3-dimensional", () => {
expect(parseGeoUri("geo:48.2010,16.3695,183")).toEqual(
{
latitude: 48.2010,
longitude: 16.3695,
altitude: 183,
accuracy: undefined,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
},
);
expect(parseGeoUri("geo:48.2010,16.3695,183")).toEqual({
latitude: 48.201,
longitude: 16.3695,
altitude: 183,
accuracy: undefined,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
});
});
it("rfc5870 6.2 Explicit CRS and accuracy", () => {
expect(parseGeoUri("geo:48.198634,16.371648;crs=wgs84;u=40")).toEqual(
{
latitude: 48.198634,
longitude: 16.371648,
altitude: undefined,
accuracy: 40,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
},
);
expect(parseGeoUri("geo:48.198634,16.371648;crs=wgs84;u=40")).toEqual({
latitude: 48.198634,
longitude: 16.371648,
altitude: undefined,
accuracy: 40,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
});
});
it("rfc5870 6.4 Negative longitude and explicit CRS", () => {
expect(parseGeoUri("geo:90,-22.43;crs=WGS84")).toEqual(
{
latitude: 90,
longitude: -22.43,
altitude: undefined,
accuracy: undefined,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
},
);
expect(parseGeoUri("geo:90,-22.43;crs=WGS84")).toEqual({
latitude: 90,
longitude: -22.43,
altitude: undefined,
accuracy: undefined,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
});
});
it("rfc5870 6.4 Integer lat and lon", () => {
expect(parseGeoUri("geo:90,46")).toEqual(
{
latitude: 90,
longitude: 46,
altitude: undefined,
accuracy: undefined,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
},
);
expect(parseGeoUri("geo:90,46")).toEqual({
latitude: 90,
longitude: 46,
altitude: undefined,
accuracy: undefined,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
});
});
it("rfc5870 6.4 Percent-encoded param value", () => {
expect(parseGeoUri("geo:66,30;u=6.500;FOo=this%2dthat")).toEqual(
{
latitude: 66,
longitude: 30,
altitude: undefined,
accuracy: 6.500,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
},
);
expect(parseGeoUri("geo:66,30;u=6.500;FOo=this%2dthat")).toEqual({
latitude: 66,
longitude: 30,
altitude: undefined,
accuracy: 6.5,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
});
});
it("rfc5870 6.4 Unknown param", () => {
expect(parseGeoUri("geo:66.0,30;u=6.5;foo=this-that>")).toEqual(
{
latitude: 66.0,
longitude: 30,
altitude: undefined,
accuracy: 6.5,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
},
);
expect(parseGeoUri("geo:66.0,30;u=6.5;foo=this-that>")).toEqual({
latitude: 66.0,
longitude: 30,
altitude: undefined,
accuracy: 6.5,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
});
});
it("rfc5870 6.4 Multiple unknown params", () => {
expect(parseGeoUri("geo:70,20;foo=1.00;bar=white")).toEqual(
{
latitude: 70,
longitude: 20,
altitude: undefined,
accuracy: undefined,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
},
);
expect(parseGeoUri("geo:70,20;foo=1.00;bar=white")).toEqual({
latitude: 70,
longitude: 20,
altitude: undefined,
accuracy: undefined,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
});
});
it("Negative latitude", () => {
expect(parseGeoUri("geo:-7.5,20")).toEqual(
{
latitude: -7.5,
longitude: 20,
altitude: undefined,
accuracy: undefined,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
},
);
expect(parseGeoUri("geo:-7.5,20")).toEqual({
latitude: -7.5,
longitude: 20,
altitude: undefined,
accuracy: undefined,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
});
});
it("Zero altitude is not unknown", () => {
expect(parseGeoUri("geo:-7.5,-20,0")).toEqual(
{
latitude: -7.5,
longitude: -20,
altitude: 0,
accuracy: undefined,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
},
);
expect(parseGeoUri("geo:-7.5,-20,0")).toEqual({
latitude: -7.5,
longitude: -20,
altitude: 0,
accuracy: undefined,
altitudeAccuracy: undefined,
heading: undefined,
speed: undefined,
});
});
});

View File

@ -16,10 +16,14 @@ limitations under the License.
import { EnhancedMap, mapDiff } from "../../src/utils/maps";
describe('maps', () => {
describe('mapDiff', () => {
it('should indicate no differences when the pointers are the same', () => {
const a = new Map([[1, 1], [2, 2], [3, 3]]);
describe("maps", () => {
describe("mapDiff", () => {
it("should indicate no differences when the pointers are the same", () => {
const a = new Map([
[1, 1],
[2, 2],
[3, 3],
]);
const result = mapDiff(a, a);
expect(result).toBeDefined();
expect(result.added).toBeDefined();
@ -30,9 +34,17 @@ describe('maps', () => {
expect(result.changed).toHaveLength(0);
});
it('should indicate no differences when there are none', () => {
const a = new Map([[1, 1], [2, 2], [3, 3]]);
const b = new Map([[1, 1], [2, 2], [3, 3]]);
it("should indicate no differences when there are none", () => {
const a = new Map([
[1, 1],
[2, 2],
[3, 3],
]);
const b = new Map([
[1, 1],
[2, 2],
[3, 3],
]);
const result = mapDiff(a, b);
expect(result).toBeDefined();
expect(result.added).toBeDefined();
@ -43,9 +55,18 @@ describe('maps', () => {
expect(result.changed).toHaveLength(0);
});
it('should indicate added properties', () => {
const a = new Map([[1, 1], [2, 2], [3, 3]]);
const b = new Map([[1, 1], [2, 2], [3, 3], [4, 4]]);
it("should indicate added properties", () => {
const a = new Map([
[1, 1],
[2, 2],
[3, 3],
]);
const b = new Map([
[1, 1],
[2, 2],
[3, 3],
[4, 4],
]);
const result = mapDiff(a, b);
expect(result).toBeDefined();
expect(result.added).toBeDefined();
@ -57,9 +78,16 @@ describe('maps', () => {
expect(result.added).toEqual([4]);
});
it('should indicate removed properties', () => {
const a = new Map([[1, 1], [2, 2], [3, 3]]);
const b = new Map([[1, 1], [2, 2]]);
it("should indicate removed properties", () => {
const a = new Map([
[1, 1],
[2, 2],
[3, 3],
]);
const b = new Map([
[1, 1],
[2, 2],
]);
const result = mapDiff(a, b);
expect(result).toBeDefined();
expect(result.added).toBeDefined();
@ -71,9 +99,17 @@ describe('maps', () => {
expect(result.removed).toEqual([3]);
});
it('should indicate changed properties', () => {
const a = new Map([[1, 1], [2, 2], [3, 3]]);
const b = new Map([[1, 1], [2, 2], [3, 4]]); // note change
it("should indicate changed properties", () => {
const a = new Map([
[1, 1],
[2, 2],
[3, 3],
]);
const b = new Map([
[1, 1],
[2, 2],
[3, 4],
]); // note change
const result = mapDiff(a, b);
expect(result).toBeDefined();
expect(result.added).toBeDefined();
@ -85,9 +121,17 @@ describe('maps', () => {
expect(result.changed).toEqual([3]);
});
it('should indicate changed, added, and removed properties', () => {
const a = new Map([[1, 1], [2, 2], [3, 3]]);
const b = new Map([[1, 1], [2, 8], [4, 4]]); // note change
it("should indicate changed, added, and removed properties", () => {
const a = new Map([
[1, 1],
[2, 2],
[3, 3],
]);
const b = new Map([
[1, 1],
[2, 8],
[4, 4],
]); // note change
const result = mapDiff(a, b);
expect(result).toBeDefined();
expect(result.added).toBeDefined();
@ -101,7 +145,7 @@ describe('maps', () => {
expect(result.changed).toEqual([2]);
});
it('should indicate changes for difference in pointers', () => {
it("should indicate changes for difference in pointers", () => {
const a = new Map([[1, {}]]); // {} always creates a new object
const b = new Map([[1, {}]]);
const result = mapDiff(a, b);
@ -116,24 +160,24 @@ describe('maps', () => {
});
});
describe('EnhancedMap', () => {
describe("EnhancedMap", () => {
// Most of these tests will make sure it implements the Map<K, V> class
it('should be empty by default', () => {
it("should be empty by default", () => {
const result = new EnhancedMap();
expect(result.size).toBe(0);
});
it('should use the provided entries', () => {
it("should use the provided entries", () => {
const obj = { a: 1, b: 2 };
const result = new EnhancedMap(Object.entries(obj));
expect(result.size).toBe(2);
expect(result.get('a')).toBe(1);
expect(result.get('b')).toBe(2);
expect(result.get("a")).toBe(1);
expect(result.get("b")).toBe(2);
});
it('should create keys if they do not exist', () => {
const key = 'a';
it("should create keys if they do not exist", () => {
const key = "a";
const val = {}; // we'll check pointers
const result = new EnhancedMap<string, any>();
@ -155,27 +199,27 @@ describe('maps', () => {
expect(result.size).toBe(1);
});
it('should proxy remove to delete and return it', () => {
it("should proxy remove to delete and return it", () => {
const val = {};
const result = new EnhancedMap<string, any>();
result.set('a', val);
result.set("a", val);
expect(result.size).toBe(1);
const removed = result.remove('a');
const removed = result.remove("a");
expect(result.size).toBe(0);
expect(removed).toBeDefined();
expect(removed).toBe(val);
});
it('should support removing unknown keys', () => {
it("should support removing unknown keys", () => {
const val = {};
const result = new EnhancedMap<string, any>();
result.set('a', val);
result.set("a", val);
expect(result.size).toBe(1);
const removed = result.remove('not-a');
const removed = result.remove("not-a");
expect(result.size).toBe(1);
expect(removed).not.toBeDefined();
});

View File

@ -28,10 +28,7 @@ describe("requestMediaPermissions", () => {
const itShouldLogTheErrorAndShowTheNoMediaPermissionsModal = () => {
it("should log the error and show the »No media permissions« modal", () => {
expect(logger.log).toHaveBeenCalledWith(
"Failed to list userMedia devices",
error,
);
expect(logger.log).toHaveBeenCalledWith("Failed to list userMedia devices", error);
screen.getByText("No media permissions");
});
};
@ -91,11 +88,9 @@ describe("requestMediaPermissions", () => {
describe("when no device is available", () => {
beforeEach(async () => {
error.name = "NotFoundError";
mocked(navigator.mediaDevices.getUserMedia).mockImplementation(
async (): Promise<MediaStream> => {
throw error;
},
);
mocked(navigator.mediaDevices.getUserMedia).mockImplementation(async (): Promise<MediaStream> => {
throw error;
});
await requestMediaPermissions();
// required for the modal to settle
await flushPromises();

View File

@ -34,7 +34,7 @@ import { MatrixClientPeg } from "../../src/MatrixClientPeg";
jest.mock("../../src/settings/SettingsStore");
describe('notifications', () => {
describe("notifications", () => {
let accountDataStore = {};
let mockClient;
let accountDataEventKey;
@ -43,7 +43,7 @@ describe('notifications', () => {
jest.clearAllMocks();
mockClient = getMockClientWithEventEmitter({
isGuest: jest.fn().mockReturnValue(false),
getAccountData: jest.fn().mockImplementation(eventType => accountDataStore[eventType]),
getAccountData: jest.fn().mockImplementation((eventType) => accountDataStore[eventType]),
setAccountData: jest.fn().mockImplementation((eventType, content) => {
accountDataStore[eventType] = new MatrixEvent({
type: eventType,
@ -56,14 +56,14 @@ describe('notifications', () => {
mocked(SettingsStore).getValue.mockReturnValue(false);
});
describe('createLocalNotification', () => {
it('creates account data event', async () => {
describe("createLocalNotification", () => {
it("creates account data event", async () => {
await createLocalNotificationSettingsIfNeeded(mockClient);
const event = mockClient.getAccountData(accountDataEventKey);
expect(event?.getContent().is_silenced).toBe(true);
});
it('does not do anything for guests', async () => {
it("does not do anything for guests", async () => {
mockClient.isGuest.mockReset().mockReturnValue(true);
await createLocalNotificationSettingsIfNeeded(mockClient);
const event = mockClient.getAccountData(accountDataEventKey);
@ -71,7 +71,7 @@ describe('notifications', () => {
});
it.each(deviceNotificationSettingsKeys)(
'unsilenced for existing sessions when %s setting is truthy',
"unsilenced for existing sessions when %s setting is truthy",
async (settingKey) => {
mocked(SettingsStore).getValue.mockImplementation((key): any => {
return key === settingKey;
@ -80,7 +80,8 @@ describe('notifications', () => {
await createLocalNotificationSettingsIfNeeded(mockClient);
const event = mockClient.getAccountData(accountDataEventKey);
expect(event?.getContent().is_silenced).toBe(false);
});
},
);
it("does not override an existing account event data", async () => {
mockClient.setAccountData(accountDataEventKey, {
@ -93,11 +94,11 @@ describe('notifications', () => {
});
});
describe('localNotificationsAreSilenced', () => {
it('defaults to false when no setting exists', () => {
describe("localNotificationsAreSilenced", () => {
it("defaults to false when no setting exists", () => {
expect(localNotificationsAreSilenced(mockClient)).toBeFalsy();
});
it('checks the persisted value', () => {
it("checks the persisted value", () => {
mockClient.setAccountData(accountDataEventKey, { is_silenced: true });
expect(localNotificationsAreSilenced(mockClient)).toBeTruthy();

View File

@ -16,9 +16,9 @@ limitations under the License.
import { clamp, defaultNumber, percentageOf, percentageWithin, sum } from "../../src/utils/numbers";
describe('numbers', () => {
describe('defaultNumber', () => {
it('should use the default when the input is not a number', () => {
describe("numbers", () => {
describe("defaultNumber", () => {
it("should use the default when the input is not a number", () => {
const def = 42;
let result = defaultNumber(null, def);
@ -31,7 +31,7 @@ describe('numbers', () => {
expect(result).toBe(def);
});
it('should use the number when it is a number', () => {
it("should use the number when it is a number", () => {
const input = 24;
const def = 42;
const result = defaultNumber(input, def);
@ -39,8 +39,8 @@ describe('numbers', () => {
});
});
describe('clamp', () => {
it('should clamp high numbers', () => {
describe("clamp", () => {
it("should clamp high numbers", () => {
const input = 101;
const min = 0;
const max = 100;
@ -48,7 +48,7 @@ describe('numbers', () => {
expect(result).toBe(max);
});
it('should clamp low numbers', () => {
it("should clamp low numbers", () => {
const input = -1;
const min = 0;
const max = 100;
@ -56,7 +56,7 @@ describe('numbers', () => {
expect(result).toBe(min);
});
it('should not clamp numbers in range', () => {
it("should not clamp numbers in range", () => {
const input = 50;
const min = 0;
const max = 100;
@ -64,9 +64,9 @@ describe('numbers', () => {
expect(result).toBe(input);
});
it('should clamp floats', () => {
const min = -0.10;
const max = +0.10;
it("should clamp floats", () => {
const min = -0.1;
const max = +0.1;
let result = clamp(-1.2, min, max);
expect(result).toBe(min);
@ -79,83 +79,84 @@ describe('numbers', () => {
});
});
describe('sum', () => {
it('should sum', () => { // duh
describe("sum", () => {
it("should sum", () => {
// duh
const result = sum(1, 2, 1, 4);
expect(result).toBe(8);
});
});
describe('percentageWithin', () => {
it('should work within 0-100', () => {
describe("percentageWithin", () => {
it("should work within 0-100", () => {
const result = percentageWithin(0.4, 0, 100);
expect(result).toBe(40);
});
it('should work within 0-100 when pct > 1', () => {
it("should work within 0-100 when pct > 1", () => {
const result = percentageWithin(1.4, 0, 100);
expect(result).toBe(140);
});
it('should work within 0-100 when pct < 0', () => {
it("should work within 0-100 when pct < 0", () => {
const result = percentageWithin(-1.4, 0, 100);
expect(result).toBe(-140);
});
it('should work with ranges other than 0-100', () => {
it("should work with ranges other than 0-100", () => {
const result = percentageWithin(0.4, 10, 20);
expect(result).toBe(14);
});
it('should work with ranges other than 0-100 when pct > 1', () => {
it("should work with ranges other than 0-100 when pct > 1", () => {
const result = percentageWithin(1.4, 10, 20);
expect(result).toBe(24);
});
it('should work with ranges other than 0-100 when pct < 0', () => {
it("should work with ranges other than 0-100 when pct < 0", () => {
const result = percentageWithin(-1.4, 10, 20);
expect(result).toBe(-4);
});
it('should work with floats', () => {
it("should work with floats", () => {
const result = percentageWithin(0.4, 10.2, 20.4);
expect(result).toBe(14.28);
});
});
// These are the inverse of percentageWithin
describe('percentageOf', () => {
it('should work within 0-100', () => {
describe("percentageOf", () => {
it("should work within 0-100", () => {
const result = percentageOf(40, 0, 100);
expect(result).toBe(0.4);
});
it('should work within 0-100 when val > 100', () => {
it("should work within 0-100 when val > 100", () => {
const result = percentageOf(140, 0, 100);
expect(result).toBe(1.40);
expect(result).toBe(1.4);
});
it('should work within 0-100 when val < 0', () => {
it("should work within 0-100 when val < 0", () => {
const result = percentageOf(-140, 0, 100);
expect(result).toBe(-1.40);
expect(result).toBe(-1.4);
});
it('should work with ranges other than 0-100', () => {
it("should work with ranges other than 0-100", () => {
const result = percentageOf(14, 10, 20);
expect(result).toBe(0.4);
});
it('should work with ranges other than 0-100 when val > 100', () => {
it("should work with ranges other than 0-100 when val > 100", () => {
const result = percentageOf(24, 10, 20);
expect(result).toBe(1.4);
});
it('should work with ranges other than 0-100 when val < 0', () => {
it("should work with ranges other than 0-100 when val < 0", () => {
const result = percentageOf(-4, 10, 20);
expect(result).toBe(-1.4);
});
it('should work with floats', () => {
it("should work with floats", () => {
const result = percentageOf(14.28, 10.2, 20.4);
expect(result).toBe(0.4);
});

View File

@ -24,9 +24,9 @@ import {
objectWithOnly,
} from "../../src/utils/objects";
describe('objects', () => {
describe('objectExcluding', () => {
it('should exclude the given properties', () => {
describe("objects", () => {
describe("objectExcluding", () => {
it("should exclude the given properties", () => {
const input = { hello: "world", test: true };
const output = { hello: "world" };
const props = ["test", "doesnotexist"]; // we also make sure it doesn't explode on missing props
@ -36,8 +36,8 @@ describe('objects', () => {
});
});
describe('objectWithOnly', () => {
it('should exclusively use the given properties', () => {
describe("objectWithOnly", () => {
it("should exclusively use the given properties", () => {
const input = { hello: "world", test: true };
const output = { hello: "world" };
const props = ["hello", "doesnotexist"]; // we also make sure it doesn't explode on missing props
@ -47,8 +47,8 @@ describe('objects', () => {
});
});
describe('objectShallowClone', () => {
it('should create a new object', () => {
describe("objectShallowClone", () => {
it("should create a new object", () => {
const input = { test: 1 };
const result = objectShallowClone(input);
expect(result).toBeDefined();
@ -56,7 +56,7 @@ describe('objects', () => {
expect(result).toMatchObject(input);
});
it('should only clone the top level properties', () => {
it("should only clone the top level properties", () => {
const input = { a: 1, b: { c: 2 } };
const result = objectShallowClone(input);
expect(result).toBeDefined();
@ -64,7 +64,7 @@ describe('objects', () => {
expect(result.b).toBe(input.b);
});
it('should support custom clone functions', () => {
it("should support custom clone functions", () => {
const input = { a: 1, b: 2 };
const output = { a: 4, b: 8 };
const result = objectShallowClone(input, (k, v) => {
@ -78,35 +78,35 @@ describe('objects', () => {
});
});
describe('objectHasDiff', () => {
it('should return false for the same pointer', () => {
describe("objectHasDiff", () => {
it("should return false for the same pointer", () => {
const a = {};
const result = objectHasDiff(a, a);
expect(result).toBe(false);
});
it('should return true if keys for A > keys for B', () => {
it("should return true if keys for A > keys for B", () => {
const a = { a: 1, b: 2 };
const b = { a: 1 };
const result = objectHasDiff(a, b);
expect(result).toBe(true);
});
it('should return true if keys for A < keys for B', () => {
it("should return true if keys for A < keys for B", () => {
const a = { a: 1 };
const b = { a: 1, b: 2 };
const result = objectHasDiff(a, b);
expect(result).toBe(true);
});
it('should return false if the objects are the same but different pointers', () => {
it("should return false if the objects are the same but different pointers", () => {
const a = { a: 1, b: 2 };
const b = { a: 1, b: 2 };
const result = objectHasDiff(a, b);
expect(result).toBe(false);
});
it('should consider pointers when testing values', () => {
it("should consider pointers when testing values", () => {
const a = { a: {}, b: 2 }; // `{}` is shorthand for `new Object()`
const b = { a: {}, b: 2 };
const result = objectHasDiff(a, b);
@ -114,8 +114,8 @@ describe('objects', () => {
});
});
describe('objectDiff', () => {
it('should return empty sets for the same object', () => {
describe("objectDiff", () => {
it("should return empty sets for the same object", () => {
const a = { a: 1, b: 2 };
const b = { a: 1, b: 2 };
const result = objectDiff(a, b);
@ -128,7 +128,7 @@ describe('objects', () => {
expect(result.removed).toHaveLength(0);
});
it('should return empty sets for the same object pointer', () => {
it("should return empty sets for the same object pointer", () => {
const a = { a: 1, b: 2 };
const result = objectDiff(a, a);
expect(result).toBeDefined();
@ -140,7 +140,7 @@ describe('objects', () => {
expect(result.removed).toHaveLength(0);
});
it('should indicate when property changes are made', () => {
it("should indicate when property changes are made", () => {
const a = { a: 1, b: 2 };
const b = { a: 11, b: 2 };
const result = objectDiff(a, b);
@ -150,10 +150,10 @@ describe('objects', () => {
expect(result.changed).toHaveLength(1);
expect(result.added).toHaveLength(0);
expect(result.removed).toHaveLength(0);
expect(result.changed).toEqual(['a']);
expect(result.changed).toEqual(["a"]);
});
it('should indicate when properties are added', () => {
it("should indicate when properties are added", () => {
const a = { a: 1, b: 2 };
const b = { a: 1, b: 2, c: 3 };
const result = objectDiff(a, b);
@ -163,10 +163,10 @@ describe('objects', () => {
expect(result.changed).toHaveLength(0);
expect(result.added).toHaveLength(1);
expect(result.removed).toHaveLength(0);
expect(result.added).toEqual(['c']);
expect(result.added).toEqual(["c"]);
});
it('should indicate when properties are removed', () => {
it("should indicate when properties are removed", () => {
const a = { a: 1, b: 2 };
const b = { a: 1 };
const result = objectDiff(a, b);
@ -176,12 +176,12 @@ describe('objects', () => {
expect(result.changed).toHaveLength(0);
expect(result.added).toHaveLength(0);
expect(result.removed).toHaveLength(1);
expect(result.removed).toEqual(['b']);
expect(result.removed).toEqual(["b"]);
});
it('should indicate when multiple aspects change', () => {
it("should indicate when multiple aspects change", () => {
const a = { a: 1, b: 2, c: 3 };
const b: (typeof a | {d: number}) = { a: 1, b: 22, d: 4 };
const b: typeof a | { d: number } = { a: 1, b: 22, d: 4 };
const result = objectDiff(a, b);
expect(result.changed).toBeDefined();
expect(result.added).toBeDefined();
@ -189,14 +189,14 @@ describe('objects', () => {
expect(result.changed).toHaveLength(1);
expect(result.added).toHaveLength(1);
expect(result.removed).toHaveLength(1);
expect(result.changed).toEqual(['b']);
expect(result.removed).toEqual(['c']);
expect(result.added).toEqual(['d']);
expect(result.changed).toEqual(["b"]);
expect(result.removed).toEqual(["c"]);
expect(result.added).toEqual(["d"]);
});
});
describe('objectKeyChanges', () => {
it('should return an empty set if no properties changed', () => {
describe("objectKeyChanges", () => {
it("should return an empty set if no properties changed", () => {
const a = { a: 1, b: 2 };
const b = { a: 1, b: 2 };
const result = objectKeyChanges(a, b);
@ -204,25 +204,25 @@ describe('objects', () => {
expect(result).toHaveLength(0);
});
it('should return an empty set if no properties changed for the same pointer', () => {
it("should return an empty set if no properties changed for the same pointer", () => {
const a = { a: 1, b: 2 };
const result = objectKeyChanges(a, a);
expect(result).toBeDefined();
expect(result).toHaveLength(0);
});
it('should return properties which were changed, added, or removed', () => {
it("should return properties which were changed, added, or removed", () => {
const a = { a: 1, b: 2, c: 3 };
const b: (typeof a | {d: number}) = { a: 1, b: 22, d: 4 };
const b: typeof a | { d: number } = { a: 1, b: 22, d: 4 };
const result = objectKeyChanges(a, b);
expect(result).toBeDefined();
expect(result).toHaveLength(3);
expect(result).toEqual(['c', 'd', 'b']); // order isn't important, but the test cares
expect(result).toEqual(["c", "d", "b"]); // order isn't important, but the test cares
});
});
describe('objectClone', () => {
it('should deep clone an object', () => {
describe("objectClone", () => {
it("should deep clone an object", () => {
const a = {
hello: "world",
test: {

View File

@ -12,40 +12,37 @@ 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 {
Room,
RoomMember,
EventType,
MatrixEvent,
} from 'matrix-js-sdk/src/matrix';
import { Room, RoomMember, EventType, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { MatrixClientPeg } from '../../../src/MatrixClientPeg';
import { MatrixClientPeg } from "../../../src/MatrixClientPeg";
import {
makeRoomPermalink,
makeUserPermalink,
parsePermalink,
RoomPermalinkCreator,
} from "../../../src/utils/permalinks/Permalinks";
import { getMockClientWithEventEmitter } from '../../test-utils';
import { getMockClientWithEventEmitter } from "../../test-utils";
describe('Permalinks', function() {
const userId = '@test:example.com';
describe("Permalinks", function () {
const userId = "@test:example.com";
const mockClient = getMockClientWithEventEmitter({
getUserId: jest.fn().mockReturnValue(userId),
getRoom: jest.fn(),
});
mockClient.credentials = { userId };
const makeMemberWithPL = (roomId: Room['roomId'], userId: string, powerLevel: number): RoomMember => {
const makeMemberWithPL = (roomId: Room["roomId"], userId: string, powerLevel: number): RoomMember => {
const member = new RoomMember(roomId, userId);
member.powerLevel = powerLevel;
return member;
};
function mockRoom(
roomId: Room['roomId'], members: RoomMember[], serverACLContent?: { deny?: string[], allow?: string[]},
roomId: Room["roomId"],
members: RoomMember[],
serverACLContent?: { deny?: string[]; allow?: string[] },
): Room {
members.forEach(m => m.membership = "join");
members.forEach((m) => (m.membership = "join"));
const powerLevelsUsers = members.reduce((pl, member) => {
if (Number.isFinite(member.powerLevel)) {
pl[member.userId] = member.powerLevel;
@ -58,35 +55,38 @@ describe('Permalinks', function() {
const powerLevels = new MatrixEvent({
type: EventType.RoomPowerLevels,
room_id: roomId,
state_key: '',
state_key: "",
content: {
users: powerLevelsUsers, users_default: 0,
users: powerLevelsUsers,
users_default: 0,
},
});
const serverACL = serverACLContent ? new MatrixEvent({
type: EventType.RoomServerAcl,
room_id: roomId,
state_key: '',
content: serverACLContent,
}) : undefined;
const serverACL = serverACLContent
? new MatrixEvent({
type: EventType.RoomServerAcl,
room_id: roomId,
state_key: "",
content: serverACLContent,
})
: undefined;
const stateEvents = serverACL ? [powerLevels, serverACL] : [powerLevels];
room.currentState.setStateEvents(stateEvents);
jest.spyOn(room, 'getCanonicalAlias').mockReturnValue(null);
jest.spyOn(room, 'getJoinedMembers').mockReturnValue(members);
jest.spyOn(room, 'getMember').mockImplementation((userId) => members.find(m => m.userId === userId));
jest.spyOn(room, "getCanonicalAlias").mockReturnValue(null);
jest.spyOn(room, "getJoinedMembers").mockReturnValue(members);
jest.spyOn(room, "getMember").mockImplementation((userId) => members.find((m) => m.userId === userId));
return room;
}
beforeEach(function() {
beforeEach(function () {
jest.clearAllMocks();
});
afterAll(() => {
jest.spyOn(MatrixClientPeg, 'get').mockRestore();
jest.spyOn(MatrixClientPeg, "get").mockRestore();
});
it('should pick no candidate servers when the room has no members', function() {
it("should pick no candidate servers when the room has no members", function () {
const room = mockRoom("!fake:example.org", []);
const creator = new RoomPermalinkCreator(room);
creator.load();
@ -94,7 +94,7 @@ describe('Permalinks', function() {
expect(creator.serverCandidates.length).toBe(0);
});
it('should gracefully handle invalid MXIDs', () => {
it("should gracefully handle invalid MXIDs", () => {
const roomId = "!fake:example.org";
const alice50 = makeMemberWithPL(roomId, "@alice:pl_50:org", 50);
const room = mockRoom(roomId, [alice50]);
@ -103,16 +103,12 @@ describe('Permalinks', function() {
expect(creator.serverCandidates).toBeTruthy();
});
it('should pick a candidate server for the highest power level user in the room', function() {
it("should pick a candidate server for the highest power level user in the room", function () {
const roomId = "!fake:example.org";
const alice50 = makeMemberWithPL(roomId, "@alice:pl_50", 50);
const alice75 = makeMemberWithPL(roomId, "@alice:pl_75", 75);
const alice95 = makeMemberWithPL(roomId, "@alice:pl_95", 95);
const room = mockRoom("!fake:example.org", [
alice50,
alice75,
alice95,
]);
const room = mockRoom("!fake:example.org", [alice50, alice75, alice95]);
const creator = new RoomPermalinkCreator(room);
creator.load();
expect(creator.serverCandidates).toBeTruthy();
@ -121,7 +117,7 @@ describe('Permalinks', function() {
// we don't check the 2nd and 3rd servers because that is done by the next test
});
it('should change candidate server when highest power level user leaves the room', function() {
it("should change candidate server when highest power level user leaves the room", function () {
const roomId = "!fake:example.org";
const member95 = makeMemberWithPL(roomId, "@alice:pl_95", 95);
@ -143,7 +139,7 @@ describe('Permalinks', function() {
expect(creator.serverCandidates[0]).toBe("pl_95");
});
it('should pick candidate servers based on user population', function() {
it("should pick candidate servers based on user population", function () {
const roomId = "!fake:example.org";
const room = mockRoom(roomId, [
makeMemberWithPL(roomId, "@alice:first", 0),
@ -162,7 +158,7 @@ describe('Permalinks', function() {
expect(creator.serverCandidates[2]).toBe("third");
});
it('should pick prefer candidate servers with higher power levels', function() {
it("should pick prefer candidate servers with higher power levels", function () {
const roomId = "!fake:example.org";
const room = mockRoom(roomId, [
makeMemberWithPL(roomId, "@alice:first", 100),
@ -178,7 +174,7 @@ describe('Permalinks', function() {
expect(creator.serverCandidates[2]).toBe("third");
});
it('should pick a maximum of 3 candidate servers', function() {
it("should pick a maximum of 3 candidate servers", function () {
const roomId = "!fake:example.org";
const room = mockRoom(roomId, [
makeMemberWithPL(roomId, "@alice:alpha", 100),
@ -193,55 +189,45 @@ describe('Permalinks', function() {
expect(creator.serverCandidates.length).toBe(3);
});
it('should not consider IPv4 hosts', function() {
it("should not consider IPv4 hosts", function () {
const roomId = "!fake:example.org";
const room = mockRoom(roomId, [
makeMemberWithPL(roomId, "@alice:127.0.0.1", 100),
]);
const room = mockRoom(roomId, [makeMemberWithPL(roomId, "@alice:127.0.0.1", 100)]);
const creator = new RoomPermalinkCreator(room);
creator.load();
expect(creator.serverCandidates).toBeTruthy();
expect(creator.serverCandidates.length).toBe(0);
});
it('should not consider IPv6 hosts', function() {
it("should not consider IPv6 hosts", function () {
const roomId = "!fake:example.org";
const room = mockRoom(roomId, [
makeMemberWithPL(roomId, "@alice:[::1]", 100),
]);
const room = mockRoom(roomId, [makeMemberWithPL(roomId, "@alice:[::1]", 100)]);
const creator = new RoomPermalinkCreator(room);
creator.load();
expect(creator.serverCandidates).toBeTruthy();
expect(creator.serverCandidates.length).toBe(0);
});
it('should not consider IPv4 hostnames with ports', function() {
it("should not consider IPv4 hostnames with ports", function () {
const roomId = "!fake:example.org";
const room = mockRoom(roomId, [
makeMemberWithPL(roomId, "@alice:127.0.0.1:8448", 100),
]);
const room = mockRoom(roomId, [makeMemberWithPL(roomId, "@alice:127.0.0.1:8448", 100)]);
const creator = new RoomPermalinkCreator(room);
creator.load();
expect(creator.serverCandidates).toBeTruthy();
expect(creator.serverCandidates.length).toBe(0);
});
it('should not consider IPv6 hostnames with ports', function() {
it("should not consider IPv6 hostnames with ports", function () {
const roomId = "!fake:example.org";
const room = mockRoom(roomId, [
makeMemberWithPL(roomId, "@alice:[::1]:8448", 100),
]);
const room = mockRoom(roomId, [makeMemberWithPL(roomId, "@alice:[::1]:8448", 100)]);
const creator = new RoomPermalinkCreator(room);
creator.load();
expect(creator.serverCandidates).toBeTruthy();
expect(creator.serverCandidates.length).toBe(0);
});
it('should work with hostnames with ports', function() {
it("should work with hostnames with ports", function () {
const roomId = "!fake:example.org";
const room = mockRoom(roomId, [
makeMemberWithPL(roomId, "@alice:example.org:8448", 100),
]);
const room = mockRoom(roomId, [makeMemberWithPL(roomId, "@alice:example.org:8448", 100)]);
const creator = new RoomPermalinkCreator(room);
creator.load();
@ -250,45 +236,57 @@ describe('Permalinks', function() {
expect(creator.serverCandidates[0]).toBe("example.org:8448");
});
it('should not consider servers explicitly denied by ACLs', function() {
it("should not consider servers explicitly denied by ACLs", function () {
const roomId = "!fake:example.org";
const room = mockRoom(roomId, [
makeMemberWithPL(roomId, "@alice:evilcorp.com", 100),
makeMemberWithPL(roomId, "@bob:chat.evilcorp.com", 0),
], {
deny: ["evilcorp.com", "*.evilcorp.com"],
allow: ["*"],
});
const room = mockRoom(
roomId,
[
makeMemberWithPL(roomId, "@alice:evilcorp.com", 100),
makeMemberWithPL(roomId, "@bob:chat.evilcorp.com", 0),
],
{
deny: ["evilcorp.com", "*.evilcorp.com"],
allow: ["*"],
},
);
const creator = new RoomPermalinkCreator(room);
creator.load();
expect(creator.serverCandidates).toBeTruthy();
expect(creator.serverCandidates.length).toBe(0);
});
it('should not consider servers not allowed by ACLs', function() {
it("should not consider servers not allowed by ACLs", function () {
const roomId = "!fake:example.org";
const room = mockRoom(roomId, [
makeMemberWithPL(roomId, "@alice:evilcorp.com", 100),
makeMemberWithPL(roomId, "@bob:chat.evilcorp.com", 0),
], {
deny: [],
allow: [], // implies "ban everyone"
});
const room = mockRoom(
roomId,
[
makeMemberWithPL(roomId, "@alice:evilcorp.com", 100),
makeMemberWithPL(roomId, "@bob:chat.evilcorp.com", 0),
],
{
deny: [],
allow: [], // implies "ban everyone"
},
);
const creator = new RoomPermalinkCreator(room);
creator.load();
expect(creator.serverCandidates).toBeTruthy();
expect(creator.serverCandidates.length).toBe(0);
});
it('should consider servers not explicitly banned by ACLs', function() {
it("should consider servers not explicitly banned by ACLs", function () {
const roomId = "!fake:example.org";
const room = mockRoom(roomId, [
makeMemberWithPL(roomId, "@alice:evilcorp.com", 100),
makeMemberWithPL(roomId, "@bob:chat.evilcorp.com", 0),
], {
deny: ["*.evilcorp.com"], // evilcorp.com is still good though
allow: ["*"],
});
const room = mockRoom(
roomId,
[
makeMemberWithPL(roomId, "@alice:evilcorp.com", 100),
makeMemberWithPL(roomId, "@bob:chat.evilcorp.com", 0),
],
{
deny: ["*.evilcorp.com"], // evilcorp.com is still good though
allow: ["*"],
},
);
const creator = new RoomPermalinkCreator(room);
creator.load();
expect(creator.serverCandidates).toBeTruthy();
@ -296,15 +294,19 @@ describe('Permalinks', function() {
expect(creator.serverCandidates[0]).toEqual("evilcorp.com");
});
it('should consider servers not disallowed by ACLs', function() {
it("should consider servers not disallowed by ACLs", function () {
const roomId = "!fake:example.org";
const room = mockRoom("!fake:example.org", [
makeMemberWithPL(roomId, "@alice:evilcorp.com", 100),
makeMemberWithPL(roomId, "@bob:chat.evilcorp.com", 0),
], {
deny: [],
allow: ["evilcorp.com"], // implies "ban everyone else"
});
const room = mockRoom(
"!fake:example.org",
[
makeMemberWithPL(roomId, "@alice:evilcorp.com", 100),
makeMemberWithPL(roomId, "@bob:chat.evilcorp.com", 0),
],
{
deny: [],
allow: ["evilcorp.com"], // implies "ban everyone else"
},
);
const creator = new RoomPermalinkCreator(room);
creator.load();
expect(creator.serverCandidates).toBeTruthy();
@ -312,7 +314,7 @@ describe('Permalinks', function() {
expect(creator.serverCandidates[0]).toEqual("evilcorp.com");
});
it('should generate an event permalink for room IDs with no candidate servers', function() {
it("should generate an event permalink for room IDs with no candidate servers", function () {
const room = mockRoom("!somewhere:example.org", []);
const creator = new RoomPermalinkCreator(room);
creator.load();
@ -320,7 +322,7 @@ describe('Permalinks', function() {
expect(result).toBe("https://matrix.to/#/!somewhere:example.org/$something:example.com");
});
it('should generate an event permalink for room IDs with some candidate servers', function() {
it("should generate an event permalink for room IDs with some candidate servers", function () {
const roomId = "!somewhere:example.org";
const room = mockRoom(roomId, [
makeMemberWithPL(roomId, "@alice:first", 100),
@ -332,8 +334,8 @@ describe('Permalinks', function() {
expect(result).toBe("https://matrix.to/#/!somewhere:example.org/$something:example.com?via=first&via=second");
});
it('should generate a room permalink for room IDs with some candidate servers', function() {
mockClient.getRoom.mockImplementation((roomId: Room['roomId']) => {
it("should generate a room permalink for room IDs with some candidate servers", function () {
mockClient.getRoom.mockImplementation((roomId: Room["roomId"]) => {
return mockRoom(roomId, [
makeMemberWithPL(roomId, "@alice:first", 100),
makeMemberWithPL(roomId, "@bob:second", 0),
@ -343,14 +345,14 @@ describe('Permalinks', function() {
expect(result).toBe("https://matrix.to/#/!somewhere:example.org?via=first&via=second");
});
it('should generate a room permalink for room aliases with no candidate servers', function() {
it("should generate a room permalink for room aliases with no candidate servers", function () {
mockClient.getRoom.mockReturnValue(null);
const result = makeRoomPermalink("#somewhere:example.org");
expect(result).toBe("https://matrix.to/#/#somewhere:example.org");
});
it('should generate a room permalink for room aliases without candidate servers', function() {
mockClient.getRoom.mockImplementation((roomId: Room['roomId']) => {
it("should generate a room permalink for room aliases without candidate servers", function () {
mockClient.getRoom.mockImplementation((roomId: Room["roomId"]) => {
return mockRoom(roomId, [
makeMemberWithPL(roomId, "@alice:first", 100),
makeMemberWithPL(roomId, "@bob:second", 0),
@ -360,26 +362,27 @@ describe('Permalinks', function() {
expect(result).toBe("https://matrix.to/#/#somewhere:example.org");
});
it('should generate a user permalink', function() {
it("should generate a user permalink", function () {
const result = makeUserPermalink("@someone:example.org");
expect(result).toBe("https://matrix.to/#/@someone:example.org");
});
it('should correctly parse room permalinks with a via argument', () => {
it("should correctly parse room permalinks with a via argument", () => {
const result = parsePermalink("https://matrix.to/#/!room_id:server?via=some.org");
expect(result.roomIdOrAlias).toBe("!room_id:server");
expect(result.viaServers).toEqual(["some.org"]);
});
it('should correctly parse room permalink via arguments', () => {
it("should correctly parse room permalink via arguments", () => {
const result = parsePermalink("https://matrix.to/#/!room_id:server?via=foo.bar&via=bar.foo");
expect(result.roomIdOrAlias).toBe("!room_id:server");
expect(result.viaServers).toEqual(["foo.bar", "bar.foo"]);
});
it('should correctly parse event permalink via arguments', () => {
const result = parsePermalink("https://matrix.to/#/!room_id:server/$event_id/some_thing_here/foobar" +
"?via=m1.org&via=m2.org");
it("should correctly parse event permalink via arguments", () => {
const result = parsePermalink(
"https://matrix.to/#/!room_id:server/$event_id/some_thing_here/foobar" + "?via=m1.org&via=m2.org",
);
expect(result.eventId).toBe("$event_id/some_thing_here/foobar");
expect(result.roomIdOrAlias).toBe("!room_id:server");
expect(result.viaServers).toEqual(["m1.org", "m2.org"]);

View File

@ -44,11 +44,13 @@ describe("pillify", () => {
rule_id: ".m.rule.roomnotif",
default: true,
enabled: true,
conditions: [{
kind: ConditionKind.EventMatch,
key: "content.body",
pattern: "@room",
}],
conditions: [
{
kind: ConditionKind.EventMatch,
key: "content.body",
pattern: "@room",
},
],
actions: [
PushRuleActionName.Notify,
{

View File

@ -50,10 +50,7 @@ describe("getJoinedNonFunctionalMembers", () => {
describe("if there are only regular room members", () => {
beforeEach(() => {
mocked(room.getJoinedMembers).mockReturnValue([
roomMember1,
roomMember2,
]);
mocked(room.getJoinedMembers).mockReturnValue([roomMember1, roomMember2]);
mocked(getFunctionalMembers).mockReturnValue([]);
});
@ -67,9 +64,7 @@ describe("getJoinedNonFunctionalMembers", () => {
describe("if there are only functional room members", () => {
beforeEach(() => {
mocked(room.getJoinedMembers).mockReturnValue([]);
mocked(getFunctionalMembers).mockReturnValue([
"@functional:example.com",
]);
mocked(getFunctionalMembers).mockReturnValue(["@functional:example.com"]);
});
it("should return an empty list", () => {
@ -79,13 +74,8 @@ describe("getJoinedNonFunctionalMembers", () => {
describe("if there are some functional room members", () => {
beforeEach(() => {
mocked(room.getJoinedMembers).mockReturnValue([
roomMember1,
roomMember2,
]);
mocked(getFunctionalMembers).mockReturnValue([
roomMember1.userId,
]);
mocked(room.getJoinedMembers).mockReturnValue([roomMember1, roomMember2]);
mocked(getFunctionalMembers).mockReturnValue([roomMember1.userId]);
});
it("should only return the non-functional members", () => {

View File

@ -28,26 +28,30 @@ describe("getRoomFunctionalMembers", () => {
});
it("should return an empty array if functional members state event does not have a service_members field", () => {
room.currentState.setStateEvents([mkEvent({
event: true,
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name,
user: "@user:example.com)",
room: room.roomId,
skey: "",
content: {},
})]);
room.currentState.setStateEvents([
mkEvent({
event: true,
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name,
user: "@user:example.com)",
room: room.roomId,
skey: "",
content: {},
}),
]);
expect(getFunctionalMembers(room)).toHaveLength(0);
});
it("should return service_members field of the functional users state event", () => {
room.currentState.setStateEvents([mkEvent({
event: true,
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name,
user: "@user:example.com)",
room: room.roomId,
skey: "",
content: { service_members: ["@user:example.com"] },
})]);
room.currentState.setStateEvents([
mkEvent({
event: true,
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name,
user: "@user:example.com)",
room: room.roomId,
skey: "",
content: { service_members: ["@user:example.com"] },
}),
]);
expect(getFunctionalMembers(room)).toEqual(["@user:example.com"]);
});
});

View File

@ -16,37 +16,37 @@ limitations under the License.
import { setHasDiff } from "../../src/utils/sets";
describe('sets', () => {
describe('setHasDiff', () => {
it('should flag true on A length > B length', () => {
describe("sets", () => {
describe("setHasDiff", () => {
it("should flag true on A length > B length", () => {
const a = new Set([1, 2, 3, 4]);
const b = new Set([1, 2, 3]);
const result = setHasDiff(a, b);
expect(result).toBe(true);
});
it('should flag true on A length < B length', () => {
it("should flag true on A length < B length", () => {
const a = new Set([1, 2, 3]);
const b = new Set([1, 2, 3, 4]);
const result = setHasDiff(a, b);
expect(result).toBe(true);
});
it('should flag true on element differences', () => {
it("should flag true on element differences", () => {
const a = new Set([1, 2, 3]);
const b = new Set([4, 5, 6]);
const result = setHasDiff(a, b);
expect(result).toBe(true);
});
it('should flag false if same but order different', () => {
it("should flag false if same but order different", () => {
const a = new Set([1, 2, 3]);
const b = new Set([3, 1, 2]);
const result = setHasDiff(a, b);
expect(result).toBe(false);
});
it('should flag false if same', () => {
it("should flag false if same", () => {
const a = new Set([1, 2, 3]);
const b = new Set([1, 2, 3]);
const result = setHasDiff(a, b);

View File

@ -33,7 +33,7 @@ const moveLexicographicallyTest = (
zipped[index][1] = order;
});
const newOrders = sortBy(zipped, i => i[1]);
const newOrders = sortBy(zipped, (i) => i[1]);
expect(newOrders[toIndex][0]).toBe(fromIndex);
expect(ops).toHaveLength(expectedChanges);
};
@ -64,73 +64,33 @@ describe("stringOrderField", () => {
});
it("should work when all orders are undefined", () => {
moveLexicographicallyTest(
[undefined, undefined, undefined, undefined, undefined, undefined],
4,
1,
2,
);
moveLexicographicallyTest([undefined, undefined, undefined, undefined, undefined, undefined], 4, 1, 2);
});
it("should work when moving to end and all orders are undefined", () => {
moveLexicographicallyTest(
[undefined, undefined, undefined, undefined, undefined, undefined],
1,
4,
5,
);
moveLexicographicallyTest([undefined, undefined, undefined, undefined, undefined, undefined], 1, 4, 5);
});
it("should work when moving left and some orders are undefined", () => {
moveLexicographicallyTest(
["a", "c", "e", undefined, undefined, undefined],
5,
2,
1,
);
moveLexicographicallyTest(["a", "c", "e", undefined, undefined, undefined], 5, 2, 1);
moveLexicographicallyTest(
["a", "a", "e", undefined, undefined, undefined],
5,
1,
2,
);
moveLexicographicallyTest(["a", "a", "e", undefined, undefined, undefined], 5, 1, 2);
});
it("should work moving to the start when all is undefined", () => {
moveLexicographicallyTest(
[undefined, undefined, undefined, undefined],
2,
0,
1,
);
moveLexicographicallyTest([undefined, undefined, undefined, undefined], 2, 0, 1);
});
it("should work moving to the end when all is undefined", () => {
moveLexicographicallyTest(
[undefined, undefined, undefined, undefined],
1,
3,
4,
);
moveLexicographicallyTest([undefined, undefined, undefined, undefined], 1, 3, 4);
});
it("should work moving left when all is undefined", () => {
moveLexicographicallyTest(
[undefined, undefined, undefined, undefined, undefined, undefined],
4,
1,
2,
);
moveLexicographicallyTest([undefined, undefined, undefined, undefined, undefined, undefined], 4, 1, 2);
});
it("should work moving right when all is undefined", () => {
moveLexicographicallyTest(
[undefined, undefined, undefined, undefined],
1,
2,
3,
);
moveLexicographicallyTest([undefined, undefined, undefined, undefined], 1, 2, 3);
});
it("should work moving more right when all is undefined", () => {
@ -143,12 +103,7 @@ describe("stringOrderField", () => {
});
it("should work moving left when right is undefined", () => {
moveLexicographicallyTest(
["20", undefined, undefined, undefined, undefined, undefined],
4,
2,
2,
);
moveLexicographicallyTest(["20", undefined, undefined, undefined, undefined, undefined], 4, 2, 2);
});
it("should work moving right when right is undefined", () => {
@ -161,49 +116,23 @@ describe("stringOrderField", () => {
});
it("should work moving left when right is defined", () => {
moveLexicographicallyTest(
["10", "20", "30", "40", undefined, undefined],
3,
1,
1,
);
moveLexicographicallyTest(["10", "20", "30", "40", undefined, undefined], 3, 1, 1);
});
it("should work moving right when right is defined", () => {
moveLexicographicallyTest(
["10", "20", "30", "40", "50", undefined],
1,
3,
1,
);
moveLexicographicallyTest(["10", "20", "30", "40", "50", undefined], 1, 3, 1);
});
it("should work moving left when all is defined", () => {
moveLexicographicallyTest(
["11", "13", "15", "17", "19"],
2,
1,
1,
);
moveLexicographicallyTest(["11", "13", "15", "17", "19"], 2, 1, 1);
});
it("should work moving right when all is defined", () => {
moveLexicographicallyTest(
["11", "13", "15", "17", "19"],
1,
2,
1,
);
moveLexicographicallyTest(["11", "13", "15", "17", "19"], 1, 2, 1);
});
it("should work moving left into no left space", () => {
moveLexicographicallyTest(
["11", "12", "13", "14", "19"],
3,
1,
2,
2,
);
moveLexicographicallyTest(["11", "12", "13", "14", "19"], 3, 1, 2, 2);
moveLexicographicallyTest(
[
@ -223,13 +152,7 @@ describe("stringOrderField", () => {
});
it("should work moving right into no right space", () => {
moveLexicographicallyTest(
["15", "16", "17", "18", "19"],
1,
3,
3,
2,
);
moveLexicographicallyTest(["15", "16", "17", "18", "19"], 1, 3, 3, 2);
moveLexicographicallyTest(
[
@ -247,30 +170,13 @@ describe("stringOrderField", () => {
});
it("should work moving right into no left space", () => {
moveLexicographicallyTest(
["11", "12", "13", "14", "15", "16", undefined],
1,
3,
3,
);
moveLexicographicallyTest(["11", "12", "13", "14", "15", "16", undefined], 1, 3, 3);
moveLexicographicallyTest(
["0", "1", "2", "3", "4", "5"],
1,
3,
3,
1,
);
moveLexicographicallyTest(["0", "1", "2", "3", "4", "5"], 1, 3, 3, 1);
});
it("should work moving left into no right space", () => {
moveLexicographicallyTest(
["15", "16", "17", "18", "19"],
4,
3,
4,
2,
);
moveLexicographicallyTest(["15", "16", "17", "18", "19"], 4, 3, 4, 2);
moveLexicographicallyTest(
[
@ -288,4 +194,3 @@ describe("stringOrderField", () => {
});
});
});

View File

@ -14,18 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import { render } from '@testing-library/react';
import React from "react";
import { render } from "@testing-library/react";
import { tooltipifyLinks } from '../../src/utils/tooltipify';
import PlatformPeg from '../../src/PlatformPeg';
import BasePlatform from '../../src/BasePlatform';
import { tooltipifyLinks } from "../../src/utils/tooltipify";
import PlatformPeg from "../../src/PlatformPeg";
import BasePlatform from "../../src/BasePlatform";
describe('tooltipify', () => {
jest.spyOn(PlatformPeg, 'get')
.mockReturnValue({ needsUrlTooltips: () => true } as unknown as BasePlatform);
describe("tooltipify", () => {
jest.spyOn(PlatformPeg, "get").mockReturnValue({ needsUrlTooltips: () => true } as unknown as BasePlatform);
it('does nothing for empty element', () => {
it("does nothing for empty element", () => {
const { container: root } = render(<div />);
const originalHtml = root.outerHTML;
const containers: Element[] = [];
@ -34,8 +33,12 @@ describe('tooltipify', () => {
expect(root.outerHTML).toEqual(originalHtml);
});
it('wraps single anchor', () => {
const { container: root } = render(<div><a href="/foo">click</a></div>);
it("wraps single anchor", () => {
const { container: root } = render(
<div>
<a href="/foo">click</a>
</div>,
);
const containers: Element[] = [];
tooltipifyLinks([root], [], containers);
expect(containers).toHaveLength(1);
@ -45,8 +48,12 @@ describe('tooltipify', () => {
expect(tooltip).toBeDefined();
});
it('ignores node', () => {
const { container: root } = render(<div><a href="/foo">click</a></div>);
it("ignores node", () => {
const { container: root } = render(
<div>
<a href="/foo">click</a>
</div>,
);
const originalHtml = root.outerHTML;
const containers: Element[] = [];
tooltipifyLinks([root], [root.children[0]], containers);
@ -55,7 +62,11 @@ describe('tooltipify', () => {
});
it("does not re-wrap if called multiple times", () => {
const { container: root } = render(<div><a href="/foo">click</a></div>);
const { container: root } = render(
<div>
<a href="/foo">click</a>
</div>,
);
const containers: Element[] = [];
tooltipifyLinks([root], [], containers);
tooltipifyLinks([root], [], containers);

View File

@ -14,29 +14,30 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { validateNumberInRange } from '../../../src/utils/validate';
import { validateNumberInRange } from "../../../src/utils/validate";
describe('validateNumberInRange', () => {
const min = 1; const max = 10;
it('returns false when value is a not a number', () => {
expect(validateNumberInRange(min, max)('test' as unknown as number)).toEqual(false);
describe("validateNumberInRange", () => {
const min = 1;
const max = 10;
it("returns false when value is a not a number", () => {
expect(validateNumberInRange(min, max)("test" as unknown as number)).toEqual(false);
});
it('returns false when value is undefined', () => {
it("returns false when value is undefined", () => {
expect(validateNumberInRange(min, max)(undefined)).toEqual(false);
});
it('returns false when value is NaN', () => {
it("returns false when value is NaN", () => {
expect(validateNumberInRange(min, max)(NaN)).toEqual(false);
});
it('returns true when value is equal to min', () => {
it("returns true when value is equal to min", () => {
expect(validateNumberInRange(min, max)(min)).toEqual(true);
});
it('returns true when value is equal to max', () => {
it("returns true when value is equal to max", () => {
expect(validateNumberInRange(min, max)(max)).toEqual(true);
});
it('returns true when value is an int in range', () => {
it("returns true when value is an int in range", () => {
expect(validateNumberInRange(min, max)(2)).toEqual(true);
});
it('returns true when value is a float in range', () => {
it("returns true when value is a float in range", () => {
expect(validateNumberInRange(min, max)(2.2)).toEqual(true);
});
});