1
0
mirror of https://github.com/matrix-org/matrix-react-sdk.git synced 2025-08-07 21:23:00 +03:00

Merge remote-tracking branch 'upstream/develop' into feature/call-event-tile

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
This commit is contained in:
Šimon Brandner
2021-07-02 13:14:14 +02:00
783 changed files with 12411 additions and 10244 deletions

View File

@@ -5,6 +5,6 @@ module.exports = {
// mocha defines a 'this'
rules: {
"babel/no-invalid-this": "off",
"@babel/no-invalid-this": "off",
},
};

View File

@@ -17,10 +17,10 @@ limitations under the License.
import { isKeyComboMatch, KeyCombo } from '../src/KeyBindingsManager';
function mockKeyEvent(key: string, modifiers?: {
ctrlKey?: boolean,
altKey?: boolean,
shiftKey?: boolean,
metaKey?: boolean
ctrlKey?: boolean;
altKey?: boolean;
shiftKey?: boolean;
metaKey?: boolean;
}): KeyboardEvent {
return {
key,

View File

@@ -15,7 +15,7 @@ limitations under the License.
*/
import ScalarAuthClient from '../src/ScalarAuthClient';
import {MatrixClientPeg} from '../src/MatrixClientPeg';
import { MatrixClientPeg } from '../src/MatrixClientPeg';
import { stubClient } from './test-utils';
describe('ScalarAuthClient', function() {

View File

@@ -18,7 +18,7 @@ import * as Matrix from 'matrix-js-sdk';
import { startTermsFlow, Service } from '../src/Terms';
import { stubClient } from './test-utils';
import {MatrixClientPeg} from '../src/MatrixClientPeg';
import { MatrixClientPeg } from '../src/MatrixClientPeg';
const POLICY_ONE = {
version: "six",

View File

@@ -102,7 +102,7 @@ describe("RovingTabIndex", () => {
{ button1 }
{ button2 }
<RovingTabIndexWrapper>
{({onFocus, isActive, ref}) =>
{({ onFocus, isActive, ref }) =>
<button onFocus={onFocus} tabIndex={isActive ? 0 : -1} ref={ref}>.</button>
}
</RovingTabIndexWrapper>
@@ -119,4 +119,3 @@ describe("RovingTabIndex", () => {
});
});

View File

@@ -31,7 +31,7 @@ const NONWORDOBJECTS = [
describe('QueryMatcher', function() {
it('Returns results by key', function() {
const qm = new QueryMatcher(OBJECTS, {keys: ["name"]});
const qm = new QueryMatcher(OBJECTS, { keys: ["name"] });
const results = qm.match('Geri');
expect(results.length).toBe(1);
@@ -39,7 +39,7 @@ describe('QueryMatcher', function() {
});
it('Returns results by prefix', function() {
const qm = new QueryMatcher(OBJECTS, {keys: ["name"]});
const qm = new QueryMatcher(OBJECTS, { keys: ["name"] });
const results = qm.match('Ge');
expect(results.length).toBe(1);
@@ -47,7 +47,7 @@ describe('QueryMatcher', function() {
});
it('Matches case-insensitive', function() {
const qm = new QueryMatcher(OBJECTS, {keys: ["name"]});
const qm = new QueryMatcher(OBJECTS, { keys: ["name"] });
const results = qm.match('geri');
expect(results.length).toBe(1);
@@ -55,7 +55,7 @@ describe('QueryMatcher', function() {
});
it('Matches ignoring accents', function() {
const qm = new QueryMatcher([{name: "Gëri", foo: 46}], {keys: ["name"]});
const qm = new QueryMatcher([{ name: "Gëri", foo: 46 }], { keys: ["name"] });
const results = qm.match('geri');
expect(results.length).toBe(1);
@@ -63,14 +63,13 @@ describe('QueryMatcher', function() {
});
it('Returns multiple results in order of search string appearance', function() {
const qm = new QueryMatcher(OBJECTS, {keys: ["name", "nick"]});
const qm = new QueryMatcher(OBJECTS, { keys: ["name", "nick"] });
const results = qm.match('or');
expect(results.length).toBe(2);
expect(results[0].name).toBe('Mel C');
expect(results[1].name).toBe('Victoria');
qm.setObjects(OBJECTS.slice().reverse());
const reverseResults = qm.match('or');
@@ -87,7 +86,7 @@ describe('QueryMatcher', function() {
{ name: "b", first: "miss", second: "hit", third: "miss" },
{ name: "c", first: "miss", second: "miss", third: "hit" },
];
const qm = new QueryMatcher(objects, {keys: ["second", "first", "third"]});
const qm = new QueryMatcher(objects, { keys: ["second", "first", "third"] });
const results = qm.match('hit');
expect(results.length).toBe(3);
@@ -95,7 +94,6 @@ describe('QueryMatcher', function() {
expect(results[1].name).toBe('a');
expect(results[2].name).toBe('c');
qm.setObjects(objects.slice().reverse());
const reverseResults = qm.match('hit');
@@ -109,14 +107,13 @@ describe('QueryMatcher', function() {
});
it('Returns results with search string in same place and key in same place in insertion order', function() {
const qm = new QueryMatcher(OBJECTS, {keys: ["name"]});
const qm = new QueryMatcher(OBJECTS, { keys: ["name"] });
const results = qm.match('Mel');
expect(results.length).toBe(2);
expect(results[0].name).toBe('Mel B');
expect(results[1].name).toBe('Mel C');
qm.setObjects(OBJECTS.slice().reverse());
const reverseResults = qm.match('Mel');
@@ -129,9 +126,9 @@ describe('QueryMatcher', function() {
it('Returns numeric results in correct order (input pos)', function() {
// regression test for depending on object iteration order
const qm = new QueryMatcher([
{name: "123456badger"},
{name: "123456"},
], {keys: ["name"]});
{ name: "123456badger" },
{ name: "123456" },
], { keys: ["name"] });
const results = qm.match('123456');
expect(results.length).toBe(2);
@@ -141,9 +138,9 @@ describe('QueryMatcher', function() {
it('Returns numeric results in correct order (query pos)', function() {
const qm = new QueryMatcher([
{name: "999999123456"},
{name: "123456badger"},
], {keys: ["name"]});
{ name: "999999123456" },
{ name: "123456badger" },
], { keys: ["name"] });
const results = qm.match('123456');
expect(results.length).toBe(2);

View File

@@ -19,7 +19,7 @@ import ReactDOM from 'react-dom';
import ReactTestUtils from 'react-dom/test-utils';
import MockHttpBackend from 'matrix-mock-request';
import {MatrixClientPeg} from '../../../src/MatrixClientPeg';
import { MatrixClientPeg } from '../../../src/MatrixClientPeg';
import sdk from '../../skinned-sdk';
import Matrix from 'matrix-js-sdk';

View File

@@ -1,6 +1,6 @@
/*
Copyright 2016 OpenMarket Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Copyright 2019, 2021 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -26,11 +26,11 @@ import { EventEmitter } from "events";
import sdk from '../../skinned-sdk';
const MessagePanel = sdk.getComponent('structures.MessagePanel');
import {MatrixClientPeg} from '../../../src/MatrixClientPeg';
import { MatrixClientPeg } from '../../../src/MatrixClientPeg';
import Matrix from 'matrix-js-sdk';
const test_utils = require('../../test-utils');
const mockclock = require('../../mock-clock');
const TestUtilsMatrix = require('../../test-utils');
import FakeTimers from '@sinonjs/fake-timers';
import Adapter from "@wojtekmaj/enzyme-adapter-react-17";
import { configure, mount } from "enzyme";
@@ -42,7 +42,7 @@ import DMRoomMap from "../../../src/utils/DMRoomMap";
configure({ adapter: new Adapter() });
let client;
const room = new Matrix.Room();
const room = new Matrix.Room("!roomId:server_name");
// wrap MessagePanel with a component which provides the MatrixClient in the context.
class WrappedMessagePanel extends React.Component {
@@ -72,14 +72,14 @@ class WrappedMessagePanel extends React.Component {
}
describe('MessagePanel', function() {
const clock = mockclock.clock();
let clock = null;
const realSetTimeout = window.setTimeout;
const events = mkEvents();
beforeEach(function() {
test_utils.stubClient();
TestUtilsMatrix.stubClient();
client = MatrixClientPeg.get();
client.credentials = {userId: '@me:here'};
client.credentials = { userId: '@me:here' };
// HACK: We assume all settings want to be disabled
SettingsStore.getValue = jest.fn((arg) => {
@@ -90,14 +90,17 @@ describe('MessagePanel', function() {
});
afterEach(function() {
clock.uninstall();
if (clock) {
clock.uninstall();
clock = null;
}
});
function mkEvents() {
const events = [];
const ts0 = Date.now();
for (let i = 0; i < 10; i++) {
events.push(test_utils.mkMessage(
events.push(TestUtilsMatrix.mkMessage(
{
event: true, room: "!room:id", user: "@user:id",
ts: ts0 + i * 1000,
@@ -111,7 +114,7 @@ describe('MessagePanel', function() {
const events = [];
const ts0 = Date.parse('09 May 2004 00:12:00 GMT');
for (let i = 0; i < 10; i++) {
events.push(test_utils.mkMessage(
events.push(TestUtilsMatrix.mkMessage(
{
event: true, room: "!room:id", user: "@user:id",
ts: ts0 + i * 1000,
@@ -120,7 +123,6 @@ describe('MessagePanel', function() {
return events;
}
// make a collection of events with some member events that should be collapsed
// with a MemberEventListSummary
function mkMelsEvents() {
@@ -128,13 +130,13 @@ describe('MessagePanel', function() {
const ts0 = Date.now();
let i = 0;
events.push(test_utils.mkMessage({
events.push(TestUtilsMatrix.mkMessage({
event: true, room: "!room:id", user: "@user:id",
ts: ts0 + ++i * 1000,
}));
for (i = 0; i < 10; i++) {
events.push(test_utils.mkMembership({
events.push(TestUtilsMatrix.mkMembership({
event: true, room: "!room:id", user: "@user:id",
target: {
userId: "@user:id",
@@ -151,7 +153,7 @@ describe('MessagePanel', function() {
}));
}
events.push(test_utils.mkMessage({
events.push(TestUtilsMatrix.mkMessage({
event: true, room: "!room:id", user: "@user:id",
ts: ts0 + ++i*1000,
}));
@@ -167,7 +169,7 @@ describe('MessagePanel', function() {
let i = 0;
for (i = 0; i < 10; i++) {
events.push(test_utils.mkMembership({
events.push(TestUtilsMatrix.mkMembership({
event: true, room: "!room:id", user: "@user:id",
target: {
userId: "@user:id",
@@ -189,8 +191,8 @@ describe('MessagePanel', function() {
// A list of room creation, encryption, and invite events.
function mkCreationEvents() {
const mkEvent = test_utils.mkEvent;
const mkMembership = test_utils.mkMembership;
const mkEvent = TestUtilsMatrix.mkEvent;
const mkMembership = TestUtilsMatrix.mkMembership;
const roomId = "!someroom";
const alice = "@alice:example.org";
const ts0 = Date.now();
@@ -363,8 +365,7 @@ describe('MessagePanel', function() {
it('shows a ghost read-marker when the read-marker moves', function(done) {
// fake the clock so that we can test the velocity animation.
clock.install();
clock.mockDate();
clock = FakeTimers.install();
const parentDiv = document.createElement('div');

View File

@@ -19,7 +19,7 @@ import ReactDOM from 'react-dom';
import ReactTestUtils from 'react-dom/test-utils';
import sdk from '../../../skinned-sdk';
import SdkConfig from '../../../../src/SdkConfig';
import {mkServerConfig} from "../../../test-utils";
import { mkServerConfig } from "../../../test-utils";
const Login = sdk.getComponent(
'structures.auth.Login',

View File

@@ -19,7 +19,7 @@ import ReactDOM from 'react-dom';
import ReactTestUtils from 'react-dom/test-utils';
import sdk from '../../../skinned-sdk';
import SdkConfig from '../../../../src/SdkConfig';
import {mkServerConfig} from "../../../test-utils";
import { mkServerConfig } from "../../../test-utils";
const Registration = sdk.getComponent(
'structures.auth.Registration',

View File

@@ -3,7 +3,7 @@
import React from 'react';
export default function({displayName = "StubComponent", render} = {}) {
export default function({ displayName = "StubComponent", render } = {}) {
if (!render) {
render = function() {
return <div>{ displayName }</div>;

View File

@@ -17,7 +17,7 @@ limitations under the License.
import React from 'react';
import TestRenderer from 'react-test-renderer';
import sdk from '../../../skinned-sdk';
import {MatrixClientPeg} from '../../../../src/MatrixClientPeg';
import { MatrixClientPeg } from '../../../../src/MatrixClientPeg';
import { stubClient } from '../../../test-utils';
const AccessSecretStorageDialog = sdk.getComponent("dialogs.security.AccessSecretStorageDialog");

View File

@@ -17,14 +17,14 @@ limitations under the License.
import "../../../skinned-sdk";
import React from "react";
import {configure, mount} from "enzyme";
import { configure, mount } from "enzyme";
import Adapter from "@wojtekmaj/enzyme-adapter-react-17";
import {act} from "react-dom/test-utils";
import { act } from "react-dom/test-utils";
import * as TestUtils from "../../../test-utils";
import {MatrixClientPeg} from "../../../../src/MatrixClientPeg";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
import DMRoomMap from "../../../../src/utils/DMRoomMap";
import {RoomPermalinkCreator} from "../../../../src/utils/permalinks/Permalinks";
import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks";
import ForwardDialog from "../../../../src/components/views/dialogs/ForwardDialog";
configure({ adapter: new Adapter() });

View File

@@ -20,10 +20,10 @@ import ReactTestUtils from 'react-dom/test-utils';
import MatrixReactTestUtils from 'matrix-react-test-utils';
import sdk from '../../../skinned-sdk';
import {MatrixClientPeg} from '../../../../src/MatrixClientPeg';
import { MatrixClientPeg } from '../../../../src/MatrixClientPeg';
import * as test_utils from '../../../test-utils';
import {sleep} from "../../../../src/utils/promise";
import * as TestUtilsMatrix from '../../../test-utils';
import { sleep } from "../../../../src/utils/promise";
const InteractiveAuthDialog = sdk.getComponent(
'views.dialogs.InteractiveAuthDialog',
@@ -33,7 +33,7 @@ describe('InteractiveAuthDialog', function() {
let parentDiv;
beforeEach(function() {
test_utils.stubClient();
TestUtilsMatrix.stubClient();
parentDiv = document.createElement('div');
document.body.appendChild(parentDiv);
});
@@ -45,11 +45,11 @@ describe('InteractiveAuthDialog', function() {
it('Should successfully complete a password flow', function() {
const onFinished = jest.fn();
const doRequest = jest.fn().mockResolvedValue({a: 1});
const doRequest = jest.fn().mockResolvedValue({ a: 1 });
// tell the stub matrixclient to return a real userid
const client = MatrixClientPeg.get();
client.credentials = {userId: "@user:id"};
client.credentials = { userId: "@user:id" };
const dlg = ReactDOM.render(
<InteractiveAuthDialog
@@ -57,7 +57,7 @@ describe('InteractiveAuthDialog', function() {
authData={{
session: "sess",
flows: [
{"stages": ["m.login.password"]},
{ "stages": ["m.login.password"] },
],
}}
makeRequest={doRequest}
@@ -105,7 +105,7 @@ describe('InteractiveAuthDialog', function() {
return sleep(1);
}).then(sleep(1)).then(() => {
expect(onFinished).toBeCalledTimes(1);
expect(onFinished).toBeCalledWith(true, {a: 1});
expect(onFinished).toBeCalledWith(true, { a: 1 });
});
});
});

View File

@@ -90,7 +90,7 @@ describe('MemberEventListSummary', function() {
it('renders expanded events if there are less than props.threshold', function() {
const events = generateEvents([
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
]);
const props = {
events: events,
@@ -112,8 +112,8 @@ describe('MemberEventListSummary', function() {
it('renders expanded events if there are less than props.threshold', function() {
const events = generateEvents([
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
]);
const props = {
events: events,
@@ -136,9 +136,9 @@ describe('MemberEventListSummary', function() {
it('renders collapsed events if events.length = props.threshold', function() {
const events = generateEvents([
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
]);
const props = {
events: events,
@@ -161,20 +161,20 @@ describe('MemberEventListSummary', function() {
it('truncates long join,leave repetitions', function() {
const events = generateEvents([
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
]);
const props = {
events: events,
@@ -203,20 +203,20 @@ describe('MemberEventListSummary', function() {
membership: "leave",
senderId: "@some_other_user:some.domain",
},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{
userId: "@user_1:some.domain",
prevMembership: "leave",
@@ -253,22 +253,22 @@ describe('MemberEventListSummary', function() {
membership: "leave",
senderId: "@some_other_user:some.domain",
},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{
userId: "@user_1:some.domain",
prevMembership: "leave",
membership: "ban",
senderId: "@some_other_user:some.domain",
},
{userId: "@user_1:some.domain", prevMembership: "ban", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{ userId: "@user_1:some.domain", prevMembership: "ban", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{
userId: "@user_1:some.domain",
prevMembership: "leave",
@@ -307,10 +307,10 @@ describe('MemberEventListSummary', function() {
membership: "leave",
senderId: "@some_other_user:some.domain",
},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{
userId: "@user_1:some.domain",
prevMembership: "leave",
@@ -324,10 +324,10 @@ describe('MemberEventListSummary', function() {
membership: "leave",
senderId: "@some_other_user:some.domain",
},
{userId: "@user_2:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_2:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"},
{ userId: "@user_2:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_2:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_2:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_2:some.domain", prevMembership: "join", membership: "leave" },
{
userId: "@user_2:some.domain",
prevMembership: "leave",
@@ -363,10 +363,10 @@ describe('MemberEventListSummary', function() {
membership: "leave",
senderId: "@some_other_user:some.domain",
},
{prevMembership: "leave", membership: "join"},
{prevMembership: "join", membership: "leave"},
{prevMembership: "leave", membership: "join"},
{prevMembership: "join", membership: "leave"},
{ prevMembership: "leave", membership: "join" },
{ prevMembership: "join", membership: "leave" },
{ prevMembership: "leave", membership: "join" },
{ prevMembership: "join", membership: "leave" },
{
prevMembership: "leave",
membership: "ban",
@@ -408,20 +408,20 @@ describe('MemberEventListSummary', function() {
membership: "leave",
senderId: "@some_other_user:some.domain",
},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_1:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_1:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
{
userId: "@user_1:some.domain",
prevMembership: "leave",
membership: "ban",
senderId: "@some_other_user:some.domain",
},
{userId: "@user_2:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"},
{userId: "@user_2:some.domain", prevMembership: "leave", membership: "join"},
{userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"},
{ userId: "@user_2:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_2:some.domain", prevMembership: "join", membership: "leave" },
{ userId: "@user_2:some.domain", prevMembership: "leave", membership: "join" },
{ userId: "@user_2:some.domain", prevMembership: "join", membership: "leave" },
]);
const props = {
events: events,
@@ -448,11 +448,11 @@ describe('MemberEventListSummary', function() {
it('correctly identifies transitions', function() {
const events = generateEvents([
// invited
{userId: "@user_1:some.domain", membership: "invite"},
{ userId: "@user_1:some.domain", membership: "invite" },
// banned
{userId: "@user_1:some.domain", membership: "ban"},
{ userId: "@user_1:some.domain", membership: "ban" },
// joined
{userId: "@user_1:some.domain", membership: "join"},
{ userId: "@user_1:some.domain", membership: "join" },
// invite_reject
{
userId: "@user_1:some.domain",
@@ -460,7 +460,7 @@ describe('MemberEventListSummary', function() {
membership: "leave",
},
// left
{userId: "@user_1:some.domain", prevMembership: "join", membership: "leave"},
{ userId: "@user_1:some.domain", prevMembership: "join", membership: "leave" },
// invite_withdrawal
{
userId: "@user_1:some.domain",
@@ -602,10 +602,10 @@ describe('MemberEventListSummary', function() {
it('handles a summary length = 2, with no "others"', function() {
const events = generateEvents([
{userId: "@user_1:some.domain", membership: "join"},
{userId: "@user_1:some.domain", membership: "join"},
{userId: "@user_2:some.domain", membership: "join"},
{userId: "@user_2:some.domain", membership: "join"},
{ userId: "@user_1:some.domain", membership: "join" },
{ userId: "@user_1:some.domain", membership: "join" },
{ userId: "@user_2:some.domain", membership: "join" },
{ userId: "@user_2:some.domain", membership: "join" },
]);
const props = {
events: events,
@@ -630,9 +630,9 @@ describe('MemberEventListSummary', function() {
it('handles a summary length = 2, with 1 "other"', function() {
const events = generateEvents([
{userId: "@user_1:some.domain", membership: "join"},
{userId: "@user_2:some.domain", membership: "join"},
{userId: "@user_3:some.domain", membership: "join"},
{ userId: "@user_1:some.domain", membership: "join" },
{ userId: "@user_2:some.domain", membership: "join" },
{ userId: "@user_3:some.domain", membership: "join" },
]);
const props = {
events: events,
@@ -657,7 +657,7 @@ describe('MemberEventListSummary', function() {
it('handles a summary length = 2, with many "others"', function() {
const events = generateEventsForUsers("@user_$:some.domain", 20, [
{membership: "join"},
{ membership: "join" },
]);
const props = {
events: events,

View File

@@ -19,7 +19,7 @@ import ReactDOM from "react-dom";
import ReactTestUtils from "react-dom/test-utils";
import MockHttpBackend from "matrix-mock-request";
import {MatrixClientPeg} from "../../../../src/MatrixClientPeg";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
import sdk from "../../../skinned-sdk";
import Matrix from "matrix-js-sdk";

View File

@@ -19,8 +19,8 @@ import Adapter from "@wojtekmaj/enzyme-adapter-react-17";
import { configure, mount } from "enzyme";
import sdk from "../../../skinned-sdk";
import {mkEvent, mkStubRoom} from "../../../test-utils";
import {MatrixClientPeg} from "../../../../src/MatrixClientPeg";
import { mkEvent, mkStubRoom } from "../../../test-utils";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
import * as languageHandler from "../../../../src/languageHandler";
const TextualBody = sdk.getComponent("views.messages.TextualBody");
@@ -343,4 +343,3 @@ describe("<TextualBody />", () => {
});
});

View File

@@ -1,21 +1,36 @@
/*
Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import ReactTestUtils from 'react-dom/test-utils';
import ReactDOM from 'react-dom';
import * as TestUtils from '../../../test-utils';
import {MatrixClientPeg} from '../../../../src/MatrixClientPeg';
import sdk from '../../../skinned-sdk';
import {Room, RoomMember, User} from 'matrix-js-sdk';
import { MatrixClientPeg } from '../../../../src/MatrixClientPeg';
import { Room } from 'matrix-js-sdk/src/models/room';
import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
import { User } from "matrix-js-sdk/src/models/user";
import { compare } from "../../../../src/utils/strings";
import MemberList from "../../../../src/components/views/rooms/MemberList";
function generateRoomId() {
return '!' + Math.random().toString().slice(2, 10) + ':domain';
}
describe('MemberList', () => {
function createRoom(opts) {
const room = new Room(generateRoomId(), null, client.getUserId());
@@ -97,13 +112,19 @@ describe('MemberList', () => {
memberListRoom.currentState.members[member.userId] = member;
}
const MemberList = sdk.getComponent('views.rooms.MemberList');
const WrappedMemberList = TestUtils.wrapInMatrixClientContext(MemberList);
const gatherWrappedRef = (r) => {
memberList = r;
};
root = ReactDOM.render(<WrappedMemberList roomId={memberListRoom.roomId}
wrappedRef={gatherWrappedRef} />, parentDiv);
root = ReactDOM.render(
(
<WrappedMemberList
roomId={memberListRoom.roomId}
wrappedRef={gatherWrappedRef}
/>
),
parentDiv,
);
});
afterEach((done) => {
@@ -213,8 +234,8 @@ describe('MemberList', () => {
});
// Bypass all the event listeners and skip to the good part
memberList._showPresence = enablePresence;
memberList._updateListNow();
memberList.showPresence = enablePresence;
memberList.updateListNow();
const tiles = ReactTestUtils.scryRenderedComponentsWithType(root, MemberTile);
expectOrderedByPresenceAndPowerLevel(tiles, enablePresence);
@@ -225,7 +246,7 @@ describe('MemberList', () => {
// Bypass all the event listeners and skip to the good part
memberList._showPresence = enablePresence;
memberList._updateListNow();
memberList.updateListNow();
const tiles = ReactTestUtils.scryRenderedComponentsWithType(root, MemberTile);
expectOrderedByPresenceAndPowerLevel(tiles, enablePresence);
@@ -254,8 +275,8 @@ describe('MemberList', () => {
});
// Bypass all the event listeners and skip to the good part
memberList._showPresence = enablePresence;
memberList._updateListNow();
memberList.showPresence = enablePresence;
memberList.updateListNow();
const tiles = ReactTestUtils.scryRenderedComponentsWithType(root, MemberTile);
expectOrderedByPresenceAndPowerLevel(tiles, enablePresence);
@@ -273,8 +294,8 @@ describe('MemberList', () => {
});
// Bypass all the event listeners and skip to the good part
memberList._showPresence = enablePresence;
memberList._updateListNow();
memberList.showPresence = enablePresence;
memberList.updateListNow();
const tiles = ReactTestUtils.scryRenderedComponentsWithType(root, MemberTile);
expectOrderedByPresenceAndPowerLevel(tiles, enablePresence);
@@ -291,4 +312,3 @@ describe('MemberList', () => {
});
});

View File

@@ -4,16 +4,15 @@ import ReactDOM from 'react-dom';
import * as TestUtils from '../../../test-utils';
import {MatrixClientPeg} from '../../../../src/MatrixClientPeg';
import { MatrixClientPeg } from '../../../../src/MatrixClientPeg';
import sdk from '../../../skinned-sdk';
import { DragDropContext } from 'react-beautiful-dnd';
import dis from '../../../../src/dispatcher/dispatcher';
import DMRoomMap from '../../../../src/utils/DMRoomMap';
import GroupStore from '../../../../src/stores/GroupStore';
import { MatrixClient, Room, RoomMember } from 'matrix-js-sdk';
import {DefaultTagID} from "../../../../src/stores/room-list/models";
import { DefaultTagID } from "../../../../src/stores/room-list/models";
import RoomListStore, { LISTS_UPDATE_EVENT, RoomListStoreClass } from "../../../../src/stores/room-list/RoomListStore";
import RoomListLayoutStore from "../../../../src/stores/room-list/RoomListLayoutStore";
@@ -56,7 +55,7 @@ describe('RoomList', () => {
TestUtils.stubClient();
client = MatrixClientPeg.get();
client.credentials = {userId: myUserId};
client.credentials = { userId: myUserId };
//revert this to prototype method as the test-utils monkey-patches this to return a hardcoded value
client.getUserId = MatrixClient.prototype.getUserId;
@@ -68,14 +67,12 @@ describe('RoomList', () => {
const RoomList = sdk.getComponent('views.rooms.RoomList');
const WrappedRoomList = TestUtils.wrapInMatrixClientContext(RoomList);
root = ReactDOM.render(
<DragDropContext>
<WrappedRoomList searchFilter="" onResize={() => {}} />
</DragDropContext>,
<WrappedRoomList searchFilter="" onResize={() => {}} />,
parentDiv,
);
ReactTestUtils.findRenderedComponentWithType(root, RoomList);
movingRoom = createRoom({name: 'Moving room'});
movingRoom = createRoom({ name: 'Moving room' });
expect(movingRoom.roomId).not.toBe(null);
// Mock joined member
@@ -86,7 +83,7 @@ describe('RoomList', () => {
[client.credentials.userId]: myMember,
}[userId]);
otherRoom = createRoom({name: 'Other room'});
otherRoom = createRoom({ name: 'Other room' });
myOtherMember = new RoomMember(otherRoom.roomId, myUserId);
myOtherMember.membership = 'join';
otherRoom.updateMyMembership('join');
@@ -98,10 +95,10 @@ describe('RoomList', () => {
client.getRooms = () => [
movingRoom,
otherRoom,
createRoom({tags: {'m.favourite': {order: 0.1}}, name: 'Some other room'}),
createRoom({tags: {'m.favourite': {order: 0.2}}, name: 'Some other room 2'}),
createRoom({tags: {'m.lowpriority': {}}, name: 'Some unimportant room'}),
createRoom({tags: {'custom.tag': {}}, name: 'Some room customly tagged'}),
createRoom({ tags: { 'm.favourite': { order: 0.1 } }, name: 'Some other room' }),
createRoom({ tags: { 'm.favourite': { order: 0.2 } }, name: 'Some other room 2' }),
createRoom({ tags: { 'm.lowpriority': {} }, name: 'Some unimportant room' }),
createRoom({ tags: { 'custom.tag': {} }, name: 'Some room customly tagged' }),
];
client.getVisibleRooms = client.getRooms;
@@ -141,7 +138,7 @@ describe('RoomList', () => {
let expectedRoomTile;
try {
const roomTiles = ReactTestUtils.scryRenderedComponentsWithType(containingSubList, RoomTile);
console.info({roomTiles: roomTiles.length});
console.info({ roomTiles: roomTiles.length });
expectedRoomTile = roomTiles.find((tile) => tile.props.room === room);
} catch (err) {
// truncate the error message because it's spammy
@@ -167,7 +164,7 @@ describe('RoomList', () => {
// Set up the room that will be moved such that it has the correct state for a room in
// the section for oldTagId
if (oldTagId === DefaultTagID.Favourite || oldTagId === DefaultTagID.LowPriority) {
movingRoom.tags = {[oldTagId]: {}};
movingRoom.tags = { [oldTagId]: {} };
} else if (oldTagId === DefaultTagID.DM) {
// Mock inverse m.direct
DMRoomMap.shared().roomToUser = {
@@ -175,13 +172,13 @@ describe('RoomList', () => {
};
}
dis.dispatch({action: 'MatrixActions.sync', prevState: null, state: 'PREPARED', matrixClient: client});
dis.dispatch({ action: 'MatrixActions.sync', prevState: null, state: 'PREPARED', matrixClient: client });
expectRoomInSubList(movingRoom, srcSubListTest);
dis.dispatch({action: 'RoomListActions.tagRoom.pending', request: {
dis.dispatch({ action: 'RoomListActions.tagRoom.pending', request: {
oldTagId, newTagId, room: movingRoom,
}});
} });
expectRoomInSubList(movingRoom, destSubListTest);
}
@@ -282,11 +279,11 @@ describe('RoomList', () => {
// We also have to mock the client's getGroup function for the room list to filter it.
// It's not smart enough to tell the difference between a real group and a template though.
client.getGroup = (groupId) => {
return {groupId};
return { groupId };
};
// Select tag
dis.dispatch({action: 'select_tag', tag: '+group:domain'}, true);
dis.dispatch({ action: 'select_tag', tag: '+group:domain' }, true);
}
beforeEach(() => {
@@ -312,4 +309,3 @@ describe('RoomList', () => {
});
});

View File

@@ -3,10 +3,9 @@ import React from 'react';
import ReactDOM from 'react-dom';
import * as testUtils from '../../../test-utils';
import sdk from '../../../skinned-sdk';
import {MatrixClientPeg} from '../../../../src/MatrixClientPeg';
import { MatrixClientPeg } from '../../../../src/MatrixClientPeg';
import SettingsStore from '../../../../src/settings/SettingsStore';
describe.skip('RoomSettings', () => {
const WrappedRoomSettings = testUtils.wrapInMatrixClientContext(sdk.getComponent('views.rooms.RoomSettings'));
@@ -36,7 +35,7 @@ describe.skip('RoomSettings', () => {
beforeEach(function(done) {
testUtils.stubClient();
client = MatrixClientPeg.get();
client.credentials = {userId: '@me:domain.com'};
client.credentials = { userId: '@me:domain.com' };
client.setRoomName = jest.fn().mockReturnValue(Promise.resolve());
client.setRoomTopic = jest.fn().mockReturnValue(Promise.resolve());
@@ -128,7 +127,7 @@ describe.skip('RoomSettings', () => {
roomSettings.save().then(() => {
expectSentStateEvent(
"!DdJkzRliezrwpNebLk:matrix.org",
"m.room.history_visibility", {history_visibility: historyVisibility},
"m.room.history_visibility", { history_visibility: historyVisibility },
);
done();
});

View File

@@ -18,18 +18,18 @@ import '../../../skinned-sdk'; // Must be first for skinning to work
import Adapter from "@wojtekmaj/enzyme-adapter-react-17";
import { configure, mount } from "enzyme";
import React from "react";
import {act} from "react-dom/test-utils";
import { act } from "react-dom/test-utils";
import SendMessageComposer, {
createMessageContent,
isQuickReaction,
} from "../../../../src/components/views/rooms/SendMessageComposer";
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
import EditorModel from "../../../../src/editor/model";
import {createPartCreator, createRenderer} from "../../../editor/mock";
import {createTestClient, mkEvent, mkStubRoom} from "../../../test-utils";
import { createPartCreator, createRenderer } from "../../../editor/mock";
import { createTestClient, mkEvent, mkStubRoom } from "../../../test-utils";
import BasicMessageComposer from "../../../../src/components/views/rooms/BasicMessageComposer";
import {MatrixClientPeg} from "../../../../src/MatrixClientPeg";
import {sleep} from "../../../../src/utils/promise";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
import { sleep } from "../../../../src/utils/promise";
import SpecPermalinkConstructor from "../../../../src/utils/permalinks/SpecPermalinkConstructor";
import defaultDispatcher from "../../../../src/dispatcher/dispatcher";
@@ -43,7 +43,7 @@ describe('<SendMessageComposer/>', () => {
it("sends plaintext messages correctly", () => {
const model = new EditorModel([], createPartCreator(), createRenderer());
model.update("hello world", "insertText", {offset: 11, atNodeEnd: true});
model.update("hello world", "insertText", { offset: 11, atNodeEnd: true });
const content = createMessageContent(model, permalinkCreator);
@@ -55,7 +55,7 @@ describe('<SendMessageComposer/>', () => {
it("sends markdown messages correctly", () => {
const model = new EditorModel([], createPartCreator(), createRenderer());
model.update("hello *world*", "insertText", {offset: 13, atNodeEnd: true});
model.update("hello *world*", "insertText", { offset: 13, atNodeEnd: true });
const content = createMessageContent(model, permalinkCreator);
@@ -69,7 +69,7 @@ describe('<SendMessageComposer/>', () => {
it("strips /me from messages and marks them as m.emote accordingly", () => {
const model = new EditorModel([], createPartCreator(), createRenderer());
model.update("/me blinks __quickly__", "insertText", {offset: 22, atNodeEnd: true});
model.update("/me blinks __quickly__", "insertText", { offset: 22, atNodeEnd: true });
const content = createMessageContent(model, permalinkCreator);
@@ -83,7 +83,7 @@ describe('<SendMessageComposer/>', () => {
it("allows sending double-slash escaped slash commands correctly", () => {
const model = new EditorModel([], createPartCreator(), createRenderer());
model.update("//dev/null is my favourite place", "insertText", {offset: 32, atNodeEnd: true});
model.update("//dev/null is my favourite place", "insertText", { offset: 32, atNodeEnd: true });
const content = createMessageContent(model, permalinkCreator);
@@ -147,7 +147,7 @@ describe('<SendMessageComposer/>', () => {
wrapper.update();
});
const key = wrapper.find(SendMessageComposer).instance()._editorStateKey;
const key = wrapper.find(SendMessageComposer).instance().editorStateKey;
expect(wrapper.text()).toBe("Test Text");
expect(localStorage.getItem(key)).toBeNull();
@@ -155,7 +155,7 @@ describe('<SendMessageComposer/>', () => {
// ensure the right state was persisted to localStorage
wrapper.unmount();
expect(JSON.parse(localStorage.getItem(key))).toStrictEqual({
parts: [{"type": "plain", "text": "Test Text"}],
parts: [{ "type": "plain", "text": "Test Text" }],
replyEventId: mockEvent.getId(),
});
@@ -188,7 +188,7 @@ describe('<SendMessageComposer/>', () => {
wrapper.update();
});
const key = wrapper.find(SendMessageComposer).instance()._editorStateKey;
const key = wrapper.find(SendMessageComposer).instance().editorStateKey;
expect(wrapper.text()).toBe("Hello World");
expect(localStorage.getItem(key)).toBeNull();
@@ -196,7 +196,7 @@ describe('<SendMessageComposer/>', () => {
// ensure the right state was persisted to localStorage
window.dispatchEvent(new Event('beforeunload'));
expect(JSON.parse(localStorage.getItem(key))).toStrictEqual({
parts: [{"type": "plain", "text": "Hello World"}],
parts: [{ "type": "plain", "text": "Hello World" }],
});
});
@@ -225,7 +225,7 @@ describe('<SendMessageComposer/>', () => {
expect(wrapper.text()).toBe("");
const str = sessionStorage.getItem(`mx_cider_history_${mockRoom.roomId}[0]`);
expect(JSON.parse(str)).toStrictEqual({
parts: [{"type": "plain", "text": "This is a message"}],
parts: [{ "type": "plain", "text": "This is a message" }],
replyEventId: mockEvent.getId(),
});
});
@@ -234,7 +234,7 @@ describe('<SendMessageComposer/>', () => {
describe("isQuickReaction", () => {
it("correctly detects quick reaction", () => {
const model = new EditorModel([], createPartCreator(), createRenderer());
model.update("+😊", "insertText", {offset: 3, atNodeEnd: true});
model.update("+😊", "insertText", { offset: 3, atNodeEnd: true });
const isReaction = isQuickReaction(model);
@@ -243,7 +243,7 @@ describe('<SendMessageComposer/>', () => {
it("correctly detects quick reaction with space", () => {
const model = new EditorModel([], createPartCreator(), createRenderer());
model.update("+ 😊", "insertText", {offset: 4, atNodeEnd: true});
model.update("+ 😊", "insertText", { offset: 4, atNodeEnd: true });
const isReaction = isQuickReaction(model);
@@ -255,10 +255,10 @@ describe('<SendMessageComposer/>', () => {
const model2 = new EditorModel([], createPartCreator(), createRenderer());
const model3 = new EditorModel([], createPartCreator(), createRenderer());
const model4 = new EditorModel([], createPartCreator(), createRenderer());
model.update("+😊hello", "insertText", {offset: 8, atNodeEnd: true});
model2.update(" +😊", "insertText", {offset: 4, atNodeEnd: true});
model3.update("+ 😊😊", "insertText", {offset: 6, atNodeEnd: true});
model4.update("+smiley", "insertText", {offset: 7, atNodeEnd: true});
model.update("+😊hello", "insertText", { offset: 8, atNodeEnd: true });
model2.update(" +😊", "insertText", { offset: 4, atNodeEnd: true });
model3.update("+ 😊😊", "insertText", { offset: 6, atNodeEnd: true });
model4.update("+smiley", "insertText", { offset: 7, atNodeEnd: true });
expect(isQuickReaction(model)).toBeFalsy();
expect(isQuickReaction(model2)).toBeFalsy();
@@ -268,4 +268,3 @@ describe('<SendMessageComposer/>', () => {
});
});

View File

@@ -1,6 +1,6 @@
import './skinned-sdk'; // Must be first for skinning to work
import {_waitForMember, canEncryptToAllUsers} from '../src/createRoom';
import {EventEmitter} from 'events';
import { _waitForMember, canEncryptToAllUsers } from '../src/createRoom';
import { EventEmitter } from 'events';
/* Shorter timeout, we've got tests to run */
const timeout = 30;
@@ -61,10 +61,9 @@ describe("canEncryptToAllUsers", () => {
done();
});
it("returns false if not all users have crypto", async (done) => {
const client = {
downloadKeys: async function(userIds) { return {...trueUser, ...falseUser}; },
downloadKeys: async function(userIds) { return { ...trueUser, ...falseUser }; },
};
const response = await canEncryptToAllUsers(client, ["@goodUser:localhost", "@badUser:localhost"]);
expect(response).toBe(false);

View File

@@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {getLineAndNodePosition} from "../../src/editor/caret";
import { getLineAndNodePosition } from "../../src/editor/caret";
import EditorModel from "../../src/editor/model";
import {createPartCreator} from "./mock";
import { createPartCreator } from "./mock";
describe('editor/caret: DOM position for caret', function() {
describe('basic text handling', function() {
@@ -25,8 +25,8 @@ describe('editor/caret: DOM position for caret', function() {
const model = new EditorModel([
pc.plain("hello"),
]);
const {offset, lineIndex, nodeIndex} =
getLineAndNodePosition(model, {index: 0, offset: 5});
const { offset, lineIndex, nodeIndex } =
getLineAndNodePosition(model, { index: 0, offset: 5 });
expect(lineIndex).toBe(0);
expect(nodeIndex).toBe(0);
expect(offset).toBe(5);
@@ -36,8 +36,8 @@ describe('editor/caret: DOM position for caret', function() {
const model = new EditorModel([
pc.plain("hello"),
]);
const {offset, lineIndex, nodeIndex} =
getLineAndNodePosition(model, {index: 0, offset: 0});
const { offset, lineIndex, nodeIndex } =
getLineAndNodePosition(model, { index: 0, offset: 0 });
expect(lineIndex).toBe(0);
expect(nodeIndex).toBe(0);
expect(offset).toBe(0);
@@ -47,8 +47,8 @@ describe('editor/caret: DOM position for caret', function() {
const model = new EditorModel([
pc.plain("hello"),
]);
const {offset, lineIndex, nodeIndex} =
getLineAndNodePosition(model, {index: 0, offset: 2});
const { offset, lineIndex, nodeIndex } =
getLineAndNodePosition(model, { index: 0, offset: 2 });
expect(lineIndex).toBe(0);
expect(nodeIndex).toBe(0);
expect(offset).toBe(2);
@@ -62,8 +62,8 @@ describe('editor/caret: DOM position for caret', function() {
pc.newline(),
pc.plain("world"),
]);
const {offset, lineIndex, nodeIndex} =
getLineAndNodePosition(model, {index: 2, offset: 5});
const { offset, lineIndex, nodeIndex } =
getLineAndNodePosition(model, { index: 2, offset: 5 });
expect(lineIndex).toBe(1);
expect(nodeIndex).toBe(0);
expect(offset).toBe(5);
@@ -75,8 +75,8 @@ describe('editor/caret: DOM position for caret', function() {
pc.newline(),
pc.plain("world"),
]);
const {offset, lineIndex, nodeIndex} =
getLineAndNodePosition(model, {index: 2, offset: 0});
const { offset, lineIndex, nodeIndex } =
getLineAndNodePosition(model, { index: 2, offset: 0 });
expect(lineIndex).toBe(1);
expect(nodeIndex).toBe(0);
expect(offset).toBe(0);
@@ -89,8 +89,8 @@ describe('editor/caret: DOM position for caret', function() {
pc.newline(),
pc.plain("world"),
]);
const {offset, lineIndex, nodeIndex} =
getLineAndNodePosition(model, {index: 1, offset: 1});
const { offset, lineIndex, nodeIndex } =
getLineAndNodePosition(model, { index: 1, offset: 1 });
expect(lineIndex).toBe(1);
expect(nodeIndex).toBe(-1);
expect(offset).toBe(0);
@@ -103,8 +103,8 @@ describe('editor/caret: DOM position for caret', function() {
pc.newline(),
pc.plain("world"),
]);
const {offset, lineIndex, nodeIndex} =
getLineAndNodePosition(model, {index: 3, offset: 0});
const { offset, lineIndex, nodeIndex } =
getLineAndNodePosition(model, { index: 3, offset: 0 });
expect(lineIndex).toBe(2);
expect(nodeIndex).toBe(0);
expect(offset).toBe(0);
@@ -118,8 +118,8 @@ describe('editor/caret: DOM position for caret', function() {
pc.userPill("Alice", "@alice:hs.tld"),
pc.plain("!"),
]);
const {offset, lineIndex, nodeIndex} =
getLineAndNodePosition(model, {index: 1, offset: 0});
const { offset, lineIndex, nodeIndex } =
getLineAndNodePosition(model, { index: 1, offset: 0 });
expect(lineIndex).toBe(0);
expect(nodeIndex).toBe(0);
expect(offset).toBe(5);
@@ -131,8 +131,8 @@ describe('editor/caret: DOM position for caret', function() {
pc.userPill("Alice", "@alice:hs.tld"),
pc.plain("!"),
]);
const {offset, lineIndex, nodeIndex} =
getLineAndNodePosition(model, {index: 1, offset: 2});
const { offset, lineIndex, nodeIndex } =
getLineAndNodePosition(model, { index: 1, offset: 2 });
expect(lineIndex).toBe(0);
expect(nodeIndex).toBe(2);
expect(offset).toBe(0);
@@ -142,8 +142,8 @@ describe('editor/caret: DOM position for caret', function() {
const model = new EditorModel([
pc.userPill("Alice", "@alice:hs.tld"),
]);
const {offset, lineIndex, nodeIndex} =
getLineAndNodePosition(model, {index: 0, offset: 0});
const { offset, lineIndex, nodeIndex } =
getLineAndNodePosition(model, { index: 0, offset: 0 });
expect(lineIndex).toBe(0);
//presumed nodes on line are (caret, pill, caret)
expect(nodeIndex).toBe(0);
@@ -154,8 +154,8 @@ describe('editor/caret: DOM position for caret', function() {
const model = new EditorModel([
pc.userPill("Alice", "@alice:hs.tld"),
]);
const {offset, lineIndex, nodeIndex} =
getLineAndNodePosition(model, {index: 0, offset: 1});
const { offset, lineIndex, nodeIndex } =
getLineAndNodePosition(model, { index: 0, offset: 1 });
expect(lineIndex).toBe(0);
//presumed nodes on line are (caret, pill, caret)
expect(nodeIndex).toBe(2);
@@ -167,8 +167,8 @@ describe('editor/caret: DOM position for caret', function() {
pc.userPill("Alice", "@alice:hs.tld"),
pc.userPill("Bob", "@bob:hs.tld"),
]);
const {offset, lineIndex, nodeIndex} =
getLineAndNodePosition(model, {index: 0, offset: 1});
const { offset, lineIndex, nodeIndex } =
getLineAndNodePosition(model, { index: 0, offset: 1 });
expect(lineIndex).toBe(0);
//presumed nodes on line are (caret, pill, caret, pill, caret)
expect(nodeIndex).toBe(2);
@@ -180,8 +180,8 @@ describe('editor/caret: DOM position for caret', function() {
pc.userPill("Alice", "@alice:hs.tld"),
pc.userPill("Bob", "@bob:hs.tld"),
]);
const {offset, lineIndex, nodeIndex} =
getLineAndNodePosition(model, {index: 1, offset: 0});
const { offset, lineIndex, nodeIndex } =
getLineAndNodePosition(model, { index: 1, offset: 0 });
expect(lineIndex).toBe(0);
//presumed nodes on line are (caret, pill, caret, pill, caret)
expect(nodeIndex).toBe(2);
@@ -193,8 +193,8 @@ describe('editor/caret: DOM position for caret', function() {
pc.userPill("Alice", "@alice:hs.tld"),
pc.userPill("Bob", "@bob:hs.tld"),
]);
const {offset, lineIndex, nodeIndex} =
getLineAndNodePosition(model, {index: 1, offset: 1});
const { offset, lineIndex, nodeIndex } =
getLineAndNodePosition(model, { index: 1, offset: 1 });
expect(lineIndex).toBe(0);
//presumed nodes on line are (caret, pill, caret, pill, caret)
expect(nodeIndex).toBe(4);

View File

@@ -15,8 +15,8 @@ limitations under the License.
*/
import '../skinned-sdk'; // Must be first for skinning to work
import {parseEvent} from "../../src/editor/deserialize";
import {createPartCreator} from "./mock";
import { parseEvent } from "../../src/editor/deserialize";
import { createPartCreator } from "./mock";
function htmlMessage(formattedBody, msgtype = "m.text") {
return {
@@ -71,22 +71,22 @@ describe('editor/deserialize', function() {
describe('text messages', function() {
it('test with newlines', function() {
const parts = normalize(parseEvent(textMessage("hello\nworld"), createPartCreator()));
expect(parts[0]).toStrictEqual({type: "plain", text: "hello"});
expect(parts[1]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[2]).toStrictEqual({type: "plain", text: "world"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "hello" });
expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[2]).toStrictEqual({ type: "plain", text: "world" });
expect(parts.length).toBe(3);
});
it('@room pill', function() {
const parts = normalize(parseEvent(textMessage("text message for @room"), createPartCreator()));
expect(parts.length).toBe(2);
expect(parts[0]).toStrictEqual({type: "plain", text: "text message for "});
expect(parts[1]).toStrictEqual({type: "at-room-pill", text: "@room"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "text message for " });
expect(parts[1]).toStrictEqual({ type: "at-room-pill", text: "@room" });
});
it('emote', function() {
const text = "says DON'T SHOUT!";
const parts = normalize(parseEvent(textMessage(text, "m.emote"), createPartCreator()));
expect(parts.length).toBe(1);
expect(parts[0]).toStrictEqual({type: "plain", text: "/me says DON'T SHOUT!"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "/me says DON'T SHOUT!" });
});
});
describe('html messages', function() {
@@ -94,159 +94,159 @@ describe('editor/deserialize', function() {
const html = "<strong>bold</strong> and <em>emphasized</em> text";
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(1);
expect(parts[0]).toStrictEqual({type: "plain", text: "**bold** and _emphasized_ text"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "**bold** and _emphasized_ text" });
});
it('hyperlink', function() {
const html = 'click <a href="http://example.com/">this</a>!';
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(1);
expect(parts[0]).toStrictEqual({type: "plain", text: "click [this](http://example.com/)!"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "click [this](http://example.com/)!" });
});
it('multiple lines with paragraphs', function() {
const html = '<p>hello</p><p>world</p>';
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(4);
expect(parts[0]).toStrictEqual({type: "plain", text: "hello"});
expect(parts[1]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[2]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[3]).toStrictEqual({type: "plain", text: "world"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "hello" });
expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[2]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[3]).toStrictEqual({ type: "plain", text: "world" });
});
it('multiple lines with line breaks', function() {
const html = 'hello<br>world';
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(3);
expect(parts[0]).toStrictEqual({type: "plain", text: "hello"});
expect(parts[1]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[2]).toStrictEqual({type: "plain", text: "world"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "hello" });
expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[2]).toStrictEqual({ type: "plain", text: "world" });
});
it('multiple lines mixing paragraphs and line breaks', function() {
const html = '<p>hello<br>warm</p><p>world</p>';
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(6);
expect(parts[0]).toStrictEqual({type: "plain", text: "hello"});
expect(parts[1]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[2]).toStrictEqual({type: "plain", text: "warm"});
expect(parts[3]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[4]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[5]).toStrictEqual({type: "plain", text: "world"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "hello" });
expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[2]).toStrictEqual({ type: "plain", text: "warm" });
expect(parts[3]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[4]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[5]).toStrictEqual({ type: "plain", text: "world" });
});
it('quote', function() {
const html = '<blockquote><p><em>wise</em><br><strong>words</strong></p></blockquote><p>indeed</p>';
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(6);
expect(parts[0]).toStrictEqual({type: "plain", text: "> _wise_"});
expect(parts[1]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[2]).toStrictEqual({type: "plain", text: "> **words**"});
expect(parts[3]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[4]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[5]).toStrictEqual({type: "plain", text: "indeed"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "> _wise_" });
expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[2]).toStrictEqual({ type: "plain", text: "> **words**" });
expect(parts[3]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[4]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[5]).toStrictEqual({ type: "plain", text: "indeed" });
});
it('user pill', function() {
const html = "Hi <a href=\"https://matrix.to/#/@alice:hs.tld\">Alice</a>!";
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(3);
expect(parts[0]).toStrictEqual({type: "plain", text: "Hi "});
expect(parts[1]).toStrictEqual({type: "user-pill", text: "Alice", resourceId: "@alice:hs.tld"});
expect(parts[2]).toStrictEqual({type: "plain", text: "!"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "Hi " });
expect(parts[1]).toStrictEqual({ type: "user-pill", text: "Alice", resourceId: "@alice:hs.tld" });
expect(parts[2]).toStrictEqual({ type: "plain", text: "!" });
});
it('user pill with displayname containing backslash', function() {
const html = "Hi <a href=\"https://matrix.to/#/@alice:hs.tld\">Alice\\</a>!";
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(3);
expect(parts[0]).toStrictEqual({type: "plain", text: "Hi "});
expect(parts[1]).toStrictEqual({type: "user-pill", text: "Alice\\", resourceId: "@alice:hs.tld"});
expect(parts[2]).toStrictEqual({type: "plain", text: "!"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "Hi " });
expect(parts[1]).toStrictEqual({ type: "user-pill", text: "Alice\\", resourceId: "@alice:hs.tld" });
expect(parts[2]).toStrictEqual({ type: "plain", text: "!" });
});
it('user pill with displayname containing opening square bracket', function() {
const html = "Hi <a href=\"https://matrix.to/#/@alice:hs.tld\">Alice[[</a>!";
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(3);
expect(parts[0]).toStrictEqual({type: "plain", text: "Hi "});
expect(parts[1]).toStrictEqual({type: "user-pill", text: "Alice[[", resourceId: "@alice:hs.tld"});
expect(parts[2]).toStrictEqual({type: "plain", text: "!"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "Hi " });
expect(parts[1]).toStrictEqual({ type: "user-pill", text: "Alice[[", resourceId: "@alice:hs.tld" });
expect(parts[2]).toStrictEqual({ type: "plain", text: "!" });
});
it('user pill with displayname containing closing square bracket', function() {
const html = "Hi <a href=\"https://matrix.to/#/@alice:hs.tld\">Alice]</a>!";
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(3);
expect(parts[0]).toStrictEqual({type: "plain", text: "Hi "});
expect(parts[1]).toStrictEqual({type: "user-pill", text: "Alice]", resourceId: "@alice:hs.tld"});
expect(parts[2]).toStrictEqual({type: "plain", text: "!"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "Hi " });
expect(parts[1]).toStrictEqual({ type: "user-pill", text: "Alice]", resourceId: "@alice:hs.tld" });
expect(parts[2]).toStrictEqual({ type: "plain", text: "!" });
});
it('room pill', function() {
const html = "Try <a href=\"https://matrix.to/#/#room:hs.tld\">#room:hs.tld</a>?";
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(3);
expect(parts[0]).toStrictEqual({type: "plain", text: "Try "});
expect(parts[1]).toStrictEqual({type: "room-pill", text: "#room:hs.tld", resourceId: "#room:hs.tld"});
expect(parts[2]).toStrictEqual({type: "plain", text: "?"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "Try " });
expect(parts[1]).toStrictEqual({ type: "room-pill", text: "#room:hs.tld", resourceId: "#room:hs.tld" });
expect(parts[2]).toStrictEqual({ type: "plain", text: "?" });
});
it('@room pill', function() {
const html = "<em>formatted</em> message for @room";
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(2);
expect(parts[0]).toStrictEqual({type: "plain", text: "_formatted_ message for "});
expect(parts[1]).toStrictEqual({type: "at-room-pill", text: "@room"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "_formatted_ message for " });
expect(parts[1]).toStrictEqual({ type: "at-room-pill", text: "@room" });
});
it('inline code', function() {
const html = "there is no place like <code>127.0.0.1</code>!";
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(1);
expect(parts[0]).toStrictEqual({type: "plain", text: "there is no place like `127.0.0.1`!"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "there is no place like `127.0.0.1`!" });
});
it('code block with no trailing text', function() {
const html = "<pre><code>0xDEADBEEF\n</code></pre>\n";
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
console.log(parts);
expect(parts.length).toBe(5);
expect(parts[0]).toStrictEqual({type: "plain", text: "```"});
expect(parts[1]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[2]).toStrictEqual({type: "plain", text: "0xDEADBEEF"});
expect(parts[3]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[4]).toStrictEqual({type: "plain", text: "```"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "```" });
expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[2]).toStrictEqual({ type: "plain", text: "0xDEADBEEF" });
expect(parts[3]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[4]).toStrictEqual({ type: "plain", text: "```" });
});
// failing likely because of https://github.com/vector-im/element-web/issues/10316
xit('code block with no trailing text and no newlines', function() {
const html = "<pre><code>0xDEADBEEF</code></pre>";
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(5);
expect(parts[0]).toStrictEqual({type: "plain", text: "```"});
expect(parts[1]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[2]).toStrictEqual({type: "plain", text: "0xDEADBEEF"});
expect(parts[3]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[4]).toStrictEqual({type: "plain", text: "```"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "```" });
expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[2]).toStrictEqual({ type: "plain", text: "0xDEADBEEF" });
expect(parts[3]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[4]).toStrictEqual({ type: "plain", text: "```" });
});
it('unordered lists', function() {
const html = "<ul><li>Oak</li><li>Spruce</li><li>Birch</li></ul>";
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(5);
expect(parts[0]).toStrictEqual({type: "plain", text: "- Oak"});
expect(parts[1]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[2]).toStrictEqual({type: "plain", text: "- Spruce"});
expect(parts[3]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[4]).toStrictEqual({type: "plain", text: "- Birch"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "- Oak" });
expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[2]).toStrictEqual({ type: "plain", text: "- Spruce" });
expect(parts[3]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[4]).toStrictEqual({ type: "plain", text: "- Birch" });
});
it('ordered lists', function() {
const html = "<ol><li>Start</li><li>Continue</li><li>Finish</li></ol>";
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(5);
expect(parts[0]).toStrictEqual({type: "plain", text: "1. Start"});
expect(parts[1]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[2]).toStrictEqual({type: "plain", text: "2. Continue"});
expect(parts[3]).toStrictEqual({type: "newline", text: "\n"});
expect(parts[4]).toStrictEqual({type: "plain", text: "3. Finish"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "1. Start" });
expect(parts[1]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[2]).toStrictEqual({ type: "plain", text: "2. Continue" });
expect(parts[3]).toStrictEqual({ type: "newline", text: "\n" });
expect(parts[4]).toStrictEqual({ type: "plain", text: "3. Finish" });
});
it('mx-reply is stripped', function() {
const html = "<mx-reply>foo</mx-reply>bar";
const parts = normalize(parseEvent(htmlMessage(html), createPartCreator()));
expect(parts.length).toBe(1);
expect(parts[0]).toStrictEqual({type: "plain", text: "bar"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "bar" });
});
it('emote', function() {
const html = "says <em>DON'T SHOUT</em>!";
const parts = normalize(parseEvent(htmlMessage(html, "m.emote"), createPartCreator()));
expect(parts.length).toBe(1);
expect(parts[0]).toStrictEqual({type: "plain", text: "/me says _DON'T SHOUT_!"});
expect(parts[0]).toStrictEqual({ type: "plain", text: "/me says _DON'T SHOUT_!" });
});
});
});

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {diffDeletion, diffAtCaret} from "../../src/editor/diff";
import { diffDeletion, diffAtCaret } from "../../src/editor/diff";
describe('editor/diff', function() {
describe('diffDeletion', function() {

View File

@@ -14,13 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import HistoryManager, {MAX_STEP_LENGTH} from "../../src/editor/history";
import HistoryManager, { MAX_STEP_LENGTH } from "../../src/editor/history";
describe('editor/history', function() {
it('push, then undo', function() {
const history = new HistoryManager();
const parts = ["hello"];
const model = {serializeParts: () => parts.slice()};
const model = { serializeParts: () => parts.slice() };
const caret1 = {};
const result1 = history.tryPush(model, caret1);
expect(result1).toEqual(true);
@@ -35,7 +35,7 @@ describe('editor/history', function() {
it('push, undo, then redo', function() {
const history = new HistoryManager();
const parts = ["hello"];
const model = {serializeParts: () => parts.slice()};
const model = { serializeParts: () => parts.slice() };
history.tryPush(model, {});
parts[0] = "hello world";
const caret2 = {};
@@ -51,7 +51,7 @@ describe('editor/history', function() {
it('push, undo, push, ensure you can`t redo', function() {
const history = new HistoryManager();
const parts = ["hello"];
const model = {serializeParts: () => parts.slice()};
const model = { serializeParts: () => parts.slice() };
history.tryPush(model, {});
parts[0] = "hello world";
history.tryPush(model, {});
@@ -63,10 +63,10 @@ describe('editor/history', function() {
it('not every keystroke stores a history step', function() {
const history = new HistoryManager();
const parts = ["hello"];
const model = {serializeParts: () => parts.slice()};
const model = { serializeParts: () => parts.slice() };
const firstCaret = {};
history.tryPush(model, firstCaret);
const diff = {added: "o"};
const diff = { added: "o" };
let keystrokeCount = 0;
do {
parts[0] = parts[0] + diff.added;
@@ -80,24 +80,24 @@ describe('editor/history', function() {
});
it('history step is added at word boundary', function() {
const history = new HistoryManager();
const model = {serializeParts: () => parts.slice()};
const model = { serializeParts: () => parts.slice() };
const parts = ["h"];
let diff = {added: "h"};
let diff = { added: "h" };
expect(history.tryPush(model, {}, "insertText", diff)).toEqual(false);
diff = {added: "i"};
diff = { added: "i" };
parts[0] = "hi";
expect(history.tryPush(model, {}, "insertText", diff)).toEqual(false);
diff = {added: " "};
diff = { added: " " };
parts[0] = "hi ";
const spaceCaret = {};
expect(history.tryPush(model, spaceCaret, "insertText", diff)).toEqual(true);
diff = {added: "y"};
diff = { added: "y" };
parts[0] = "hi y";
expect(history.tryPush(model, {}, "insertText", diff)).toEqual(false);
diff = {added: "o"};
diff = { added: "o" };
parts[0] = "hi yo";
expect(history.tryPush(model, {}, "insertText", diff)).toEqual(false);
diff = {added: "u"};
diff = { added: "u" };
parts[0] = "hi you";
expect(history.canUndo()).toEqual(true);
@@ -108,11 +108,11 @@ describe('editor/history', function() {
it('keystroke that didn\'t add a step can undo', function() {
const history = new HistoryManager();
const parts = ["hello"];
const model = {serializeParts: () => parts.slice()};
const model = { serializeParts: () => parts.slice() };
const firstCaret = {};
history.tryPush(model, {});
parts[0] = "helloo";
const result = history.tryPush(model, {}, "insertText", {added: "o"});
const result = history.tryPush(model, {}, "insertText", { added: "o" });
expect(result).toEqual(false);
expect(history.canUndo()).toEqual(true);
const undoState = history.undo(model);
@@ -122,11 +122,11 @@ describe('editor/history', function() {
it('undo after keystroke that didn\'t add a step is able to redo', function() {
const history = new HistoryManager();
const parts = ["hello"];
const model = {serializeParts: () => parts.slice()};
const model = { serializeParts: () => parts.slice() };
history.tryPush(model, {});
parts[0] = "helloo";
const caret = {last: true};
history.tryPush(model, caret, "insertText", {added: "o"});
const caret = { last: true };
history.tryPush(model, caret, "insertText", { added: "o" });
history.undo(model);
expect(history.canRedo()).toEqual(true);
const redoState = history.redo();
@@ -136,10 +136,10 @@ describe('editor/history', function() {
it('overwriting text always stores a step', function() {
const history = new HistoryManager();
const parts = ["hello"];
const model = {serializeParts: () => parts.slice()};
const model = { serializeParts: () => parts.slice() };
const firstCaret = {};
history.tryPush(model, firstCaret);
const diff = {at: 1, added: "a", removed: "e"};
const diff = { at: 1, added: "a", removed: "e" };
const result = history.tryPush(model, {}, "insertText", diff);
expect(result).toEqual(true);
});

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {PartCreator} from "../../src/editor/parts";
import { PartCreator } from "../../src/editor/parts";
class MockAutoComplete {
constructor(updateCallback, partCreator, completions) {
@@ -25,7 +25,7 @@ class MockAutoComplete {
}
close() {
this._updateCallback({close: true});
this._updateCallback({ close: true });
}
tryComplete(close = true) {
@@ -40,7 +40,7 @@ class MockAutoComplete {
} else {
pill = this._partCreator.roomPill(match.resourceId);
}
this._updateCallback({replaceParts: [pill], close});
this._updateCallback({ replaceParts: [pill], close });
}
}

View File

@@ -15,14 +15,14 @@ limitations under the License.
*/
import EditorModel from "../../src/editor/model";
import {createPartCreator, createRenderer} from "./mock";
import { createPartCreator, createRenderer } from "./mock";
describe('editor/model', function() {
describe('plain text manipulation', function() {
it('insert text into empty document', function() {
const renderer = createRenderer();
const model = new EditorModel([], createPartCreator(), renderer);
model.update("hello", "insertText", {offset: 5, atNodeEnd: true});
model.update("hello", "insertText", { offset: 5, atNodeEnd: true });
expect(renderer.count).toBe(1);
expect(renderer.caret.index).toBe(0);
expect(renderer.caret.offset).toBe(5);
@@ -34,7 +34,7 @@ describe('editor/model', function() {
const renderer = createRenderer();
const pc = createPartCreator();
const model = new EditorModel([pc.plain("hello")], pc, renderer);
model.update("hello world", "insertText", {offset: 11, atNodeEnd: true});
model.update("hello world", "insertText", { offset: 11, atNodeEnd: true });
expect(renderer.count).toBe(1);
expect(renderer.caret.index).toBe(0);
expect(renderer.caret.offset).toBe(11);
@@ -46,7 +46,7 @@ describe('editor/model', function() {
const renderer = createRenderer();
const pc = createPartCreator();
const model = new EditorModel([pc.plain("world")], pc, renderer);
model.update("hello world", "insertText", {offset: 6, atNodeEnd: false});
model.update("hello world", "insertText", { offset: 6, atNodeEnd: false });
expect(renderer.count).toBe(1);
expect(renderer.caret.index).toBe(0);
expect(renderer.caret.offset).toBe(6);
@@ -60,7 +60,7 @@ describe('editor/model', function() {
const renderer = createRenderer();
const pc = createPartCreator();
const model = new EditorModel([pc.plain("hello")], pc, renderer);
model.update("hello\n", "insertText", {offset: 6, atNodeEnd: true});
model.update("hello\n", "insertText", { offset: 6, atNodeEnd: true });
expect(renderer.count).toBe(1);
expect(renderer.caret.index).toBe(1);
expect(renderer.caret.offset).toBe(1);
@@ -74,7 +74,7 @@ describe('editor/model', function() {
const renderer = createRenderer();
const pc = createPartCreator();
const model = new EditorModel([pc.plain("hello")], pc, renderer);
model.update("hello\n\n\nworld!", "insertText", {offset: 14, atNodeEnd: true});
model.update("hello\n\n\nworld!", "insertText", { offset: 14, atNodeEnd: true });
expect(renderer.count).toBe(1);
expect(renderer.caret.index).toBe(4);
expect(renderer.caret.offset).toBe(6);
@@ -99,7 +99,7 @@ describe('editor/model', function() {
pc.newline(),
pc.plain("world"),
], pc, renderer);
model.update("hello\nwarm\nworld", "insertText", {offset: 10, atNodeEnd: true});
model.update("hello\nwarm\nworld", "insertText", { offset: 10, atNodeEnd: true });
console.log(model.serializeParts());
expect(renderer.count).toBe(1);
expect(renderer.caret.index).toBe(2);
@@ -125,7 +125,7 @@ describe('editor/model', function() {
pc.plain("try "),
pc.roomPill("#someroom"),
], pc, renderer);
model.update("try foo#someroom", "insertText", {offset: 7, atNodeEnd: false});
model.update("try foo#someroom", "insertText", { offset: 7, atNodeEnd: false });
expect(renderer.caret.index).toBe(0);
expect(renderer.caret.offset).toBe(7);
expect(model.parts.length).toBe(2);
@@ -142,7 +142,7 @@ describe('editor/model', function() {
pc.roomPill("#someroom"),
pc.plain("?"),
], pc, renderer);
model.update("try #some perhapsroom?", "insertText", {offset: 17, atNodeEnd: false});
model.update("try #some perhapsroom?", "insertText", { offset: 17, atNodeEnd: false });
expect(renderer.caret.index).toBe(2);
expect(renderer.caret.offset).toBe(8);
expect(model.parts.length).toBe(3);
@@ -157,7 +157,7 @@ describe('editor/model', function() {
const renderer = createRenderer();
const pc = createPartCreator();
const model = new EditorModel([pc.roomPill("#someroom")], pc, renderer);
model.update("#someroo", "deleteContentBackward", {offset: 8, atNodeEnd: true});
model.update("#someroo", "deleteContentBackward", { offset: 8, atNodeEnd: true });
expect(renderer.count).toBe(1);
expect(renderer.caret.index).toBe(-1);
expect(renderer.caret.offset).toBe(0);
@@ -167,7 +167,7 @@ describe('editor/model', function() {
const renderer = createRenderer();
const pc = createPartCreator();
const model = new EditorModel([pc.roomPill("#someroom")], pc, renderer);
model.update("someroom", "deleteContentForward", {offset: 0, atNodeEnd: false});
model.update("someroom", "deleteContentForward", { offset: 0, atNodeEnd: false });
expect(renderer.count).toBe(1);
expect(renderer.caret.index).toBe(-1);
expect(renderer.caret.offset).toBe(0);
@@ -177,10 +177,10 @@ describe('editor/model', function() {
describe('auto-complete', function() {
it('insert user pill', function() {
const renderer = createRenderer();
const pc = createPartCreator([{resourceId: "@alice", label: "Alice"}]);
const pc = createPartCreator([{ resourceId: "@alice", label: "Alice" }]);
const model = new EditorModel([pc.plain("hello ")], pc, renderer);
model.update("hello @a", "insertText", {offset: 8, atNodeEnd: true});
model.update("hello @a", "insertText", { offset: 8, atNodeEnd: true });
expect(renderer.count).toBe(1);
expect(renderer.caret.index).toBe(1);
@@ -205,10 +205,10 @@ describe('editor/model', function() {
it('insert room pill', function() {
const renderer = createRenderer();
const pc = createPartCreator([{resourceId: "#riot-dev"}]);
const pc = createPartCreator([{ resourceId: "#riot-dev" }]);
const model = new EditorModel([pc.plain("hello ")], pc, renderer);
model.update("hello #r", "insertText", {offset: 8, atNodeEnd: true});
model.update("hello #r", "insertText", { offset: 8, atNodeEnd: true });
expect(renderer.count).toBe(1);
expect(renderer.caret.index).toBe(1);
@@ -233,12 +233,12 @@ describe('editor/model', function() {
it('type after inserting pill', function() {
const renderer = createRenderer();
const pc = createPartCreator([{resourceId: "#riot-dev"}]);
const pc = createPartCreator([{ resourceId: "#riot-dev" }]);
const model = new EditorModel([pc.plain("hello ")], pc, renderer);
model.update("hello #r", "insertText", {offset: 8, atNodeEnd: true});
model.update("hello #r", "insertText", { offset: 8, atNodeEnd: true });
model.autoComplete.tryComplete(); // see MockAutoComplete
model.update("hello #riot-dev!!", "insertText", {offset: 17, atNodeEnd: true});
model.update("hello #riot-dev!!", "insertText", { offset: 17, atNodeEnd: true });
expect(renderer.count).toBe(3);
expect(renderer.caret.index).toBe(2);
@@ -254,10 +254,10 @@ describe('editor/model', function() {
it('pasting text does not trigger auto-complete', function() {
const renderer = createRenderer();
const pc = createPartCreator([{resourceId: "#define-room"}]);
const pc = createPartCreator([{ resourceId: "#define-room" }]);
const model = new EditorModel([pc.plain("try ")], pc, renderer);
model.update("try #define", "insertFromPaste", {offset: 11, atNodeEnd: true});
model.update("try #define", "insertFromPaste", { offset: 11, atNodeEnd: true });
expect(model.autoComplete).toBeFalsy();
expect(renderer.caret.index).toBe(0);
@@ -269,10 +269,10 @@ describe('editor/model', function() {
it('dropping text does not trigger auto-complete', function() {
const renderer = createRenderer();
const pc = createPartCreator([{resourceId: "#define-room"}]);
const pc = createPartCreator([{ resourceId: "#define-room" }]);
const model = new EditorModel([pc.plain("try ")], pc, renderer);
model.update("try #define", "insertFromDrop", {offset: 11, atNodeEnd: true});
model.update("try #define", "insertFromDrop", { offset: 11, atNodeEnd: true });
expect(model.autoComplete).toBeFalsy();
expect(renderer.caret.index).toBe(0);
@@ -284,17 +284,17 @@ describe('editor/model', function() {
it('insert room pill without splitting at the colon', () => {
const renderer = createRenderer();
const pc = createPartCreator([{resourceId: "#room:server"}]);
const pc = createPartCreator([{ resourceId: "#room:server" }]);
const model = new EditorModel([], pc, renderer);
model.update("#roo", "insertText", {offset: 4, atNodeEnd: true});
model.update("#roo", "insertText", { offset: 4, atNodeEnd: true });
expect(renderer.count).toBe(1);
expect(model.parts.length).toBe(1);
expect(model.parts[0].type).toBe("pill-candidate");
expect(model.parts[0].text).toBe("#roo");
model.update("#room:s", "insertText", {offset: 7, atNodeEnd: true});
model.update("#room:s", "insertText", { offset: 7, atNodeEnd: true });
expect(renderer.count).toBe(2);
expect(model.parts.length).toBe(1);
@@ -304,10 +304,10 @@ describe('editor/model', function() {
it('allow typing e-mail addresses without splitting at the @', () => {
const renderer = createRenderer();
const pc = createPartCreator([{resourceId: "@alice", label: "Alice"}]);
const pc = createPartCreator([{ resourceId: "@alice", label: "Alice" }]);
const model = new EditorModel([], pc, renderer);
model.update("foo@a", "insertText", {offset: 5, atNodeEnd: true});
model.update("foo@a", "insertText", { offset: 5, atNodeEnd: true });
expect(renderer.count).toBe(1);
expect(model.parts.length).toBe(1);

View File

@@ -15,10 +15,10 @@ limitations under the License.
*/
import EditorModel from "../../src/editor/model";
import {createPartCreator, createRenderer} from "./mock";
import {toggleInlineFormat} from "../../src/editor/operations";
import { createPartCreator, createRenderer } from "./mock";
import { toggleInlineFormat } from "../../src/editor/operations";
const SERIALIZED_NEWLINE = {"text": "\n", "type": "newline"};
const SERIALIZED_NEWLINE = { "text": "\n", "type": "newline" };
describe('editor/operations: formatting operations', () => {
describe('toggleInlineFormat', () => {
@@ -33,9 +33,9 @@ describe('editor/operations: formatting operations', () => {
model.positionForOffset(11, false)); // around "world"
expect(range.parts[0].text).toBe("world");
expect(model.serializeParts()).toEqual([{"text": "hello world!", "type": "plain"}]);
expect(model.serializeParts()).toEqual([{ "text": "hello world!", "type": "plain" }]);
toggleInlineFormat(range, "_");
expect(model.serializeParts()).toEqual([{"text": "hello _world_!", "type": "plain"}]);
expect(model.serializeParts()).toEqual([{ "text": "hello _world_!", "type": "plain" }]);
});
it('works for parts of words', () => {
@@ -49,9 +49,9 @@ describe('editor/operations: formatting operations', () => {
model.positionForOffset(10, false)); // around "orl"
expect(range.parts[0].text).toBe("orl");
expect(model.serializeParts()).toEqual([{"text": "hello world!", "type": "plain"}]);
expect(model.serializeParts()).toEqual([{ "text": "hello world!", "type": "plain" }]);
toggleInlineFormat(range, "*");
expect(model.serializeParts()).toEqual([{"text": "hello w*orl*d!", "type": "plain"}]);
expect(model.serializeParts()).toEqual([{ "text": "hello w*orl*d!", "type": "plain" }]);
});
it('works for around pills', () => {
@@ -68,15 +68,15 @@ describe('editor/operations: formatting operations', () => {
expect(range.parts.map(p => p.text).join("")).toBe("there @room, how are you");
expect(model.serializeParts()).toEqual([
{"text": "hello there ", "type": "plain"},
{"text": "@room", "type": "at-room-pill"},
{"text": ", how are you doing?", "type": "plain"},
{ "text": "hello there ", "type": "plain" },
{ "text": "@room", "type": "at-room-pill" },
{ "text": ", how are you doing?", "type": "plain" },
]);
toggleInlineFormat(range, "_");
expect(model.serializeParts()).toEqual([
{"text": "hello _there ", "type": "plain"},
{"text": "@room", "type": "at-room-pill"},
{"text": ", how are you_ doing?", "type": "plain"},
{ "text": "hello _there ", "type": "plain" },
{ "text": "@room", "type": "at-room-pill" },
{ "text": ", how are you_ doing?", "type": "plain" },
]);
});
@@ -94,15 +94,15 @@ describe('editor/operations: formatting operations', () => {
expect(range.parts.map(p => p.text).join("")).toBe("world,\nhow");
expect(model.serializeParts()).toEqual([
{"text": "hello world,", "type": "plain"},
{ "text": "hello world,", "type": "plain" },
SERIALIZED_NEWLINE,
{"text": "how are you doing?", "type": "plain"},
{ "text": "how are you doing?", "type": "plain" },
]);
toggleInlineFormat(range, "**");
expect(model.serializeParts()).toEqual([
{"text": "hello **world,", "type": "plain"},
{ "text": "hello **world,", "type": "plain" },
SERIALIZED_NEWLINE,
{"text": "how** are you doing?", "type": "plain"},
{ "text": "how** are you doing?", "type": "plain" },
]);
});
@@ -125,9 +125,9 @@ describe('editor/operations: formatting operations', () => {
expect(model.serializeParts()).toEqual([
SERIALIZED_NEWLINE,
SERIALIZED_NEWLINE,
{"text": "hello world,", "type": "plain"},
{ "text": "hello world,", "type": "plain" },
SERIALIZED_NEWLINE,
{"text": "how are you doing?", "type": "plain"},
{ "text": "how are you doing?", "type": "plain" },
SERIALIZED_NEWLINE,
SERIALIZED_NEWLINE,
]);
@@ -135,9 +135,9 @@ describe('editor/operations: formatting operations', () => {
expect(model.serializeParts()).toEqual([
SERIALIZED_NEWLINE,
SERIALIZED_NEWLINE,
{"text": "**hello world,", "type": "plain"},
{ "text": "**hello world,", "type": "plain" },
SERIALIZED_NEWLINE,
{"text": "how are you doing?**", "type": "plain"},
{ "text": "how are you doing?**", "type": "plain" },
SERIALIZED_NEWLINE,
SERIALIZED_NEWLINE,
]);
@@ -158,32 +158,32 @@ describe('editor/operations: formatting operations', () => {
let range = model.startRange(model.positionForOffset(0, true), model.getPositionAtEnd()); // select-all
expect(model.serializeParts()).toEqual([
{"text": "hello world,", "type": "plain"},
{ "text": "hello world,", "type": "plain" },
SERIALIZED_NEWLINE,
{"text": "how are you doing?", "type": "plain"},
{ "text": "how are you doing?", "type": "plain" },
SERIALIZED_NEWLINE,
SERIALIZED_NEWLINE,
{"text": "new paragraph", "type": "plain"},
{ "text": "new paragraph", "type": "plain" },
]);
toggleInlineFormat(range, "__");
expect(model.serializeParts()).toEqual([
{"text": "__hello world,", "type": "plain"},
{ "text": "__hello world,", "type": "plain" },
SERIALIZED_NEWLINE,
{"text": "how are you doing?__", "type": "plain"},
{ "text": "how are you doing?__", "type": "plain" },
SERIALIZED_NEWLINE,
SERIALIZED_NEWLINE,
{"text": "__new paragraph__", "type": "plain"},
{ "text": "__new paragraph__", "type": "plain" },
]);
range = model.startRange(model.positionForOffset(0, true), model.getPositionAtEnd()); // select-all
console.log("RANGE", range.parts);
toggleInlineFormat(range, "__");
expect(model.serializeParts()).toEqual([
{"text": "hello world,", "type": "plain"},
{ "text": "hello world,", "type": "plain" },
SERIALIZED_NEWLINE,
{"text": "how are you doing?", "type": "plain"},
{ "text": "how are you doing?", "type": "plain" },
SERIALIZED_NEWLINE,
SERIALIZED_NEWLINE,
{"text": "new paragraph", "type": "plain"},
{ "text": "new paragraph", "type": "plain" },
]);
});
});

View File

@@ -15,7 +15,7 @@ limitations under the License.
*/
import EditorModel from "../../src/editor/model";
import {createPartCreator} from "./mock";
import { createPartCreator } from "./mock";
function createRenderer() {
const render = (c) => {

View File

@@ -15,7 +15,7 @@ limitations under the License.
*/
import EditorModel from "../../src/editor/model";
import {createPartCreator, createRenderer} from "./mock";
import { createPartCreator, createRenderer } from "./mock";
const pillChannel = "#riot-dev:matrix.org";

View File

@@ -15,8 +15,8 @@ limitations under the License.
*/
import EditorModel from "../../src/editor/model";
import {htmlSerializeIfNeeded} from "../../src/editor/serialize";
import {createPartCreator} from "./mock";
import { htmlSerializeIfNeeded } from "../../src/editor/serialize";
import { createPartCreator } from "./mock";
describe('editor/serialize', function() {
it('user pill turns message into html', function() {

View File

@@ -11,7 +11,7 @@
"dependencies": {
"cheerio": "^1.0.0-rc.2",
"commander": "^2.19.0",
"puppeteer": "^1.14.0",
"puppeteer": "10.0.0",
"request": "^2.88.0",
"request-promise-native": "^1.0.7",
"uuid": "^3.3.2"

View File

@@ -27,5 +27,5 @@ module.exports.approveConsent = async function(consentUrl) {
const h = doc("input[name=h]").val();
const formAction = doc("form").attr("action");
const absAction = url.resolve(consentUrl, formAction);
await request.post(absAction).form({v, u, h});
await request.post(absAction).form({ v, u, h });
};

View File

@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
const {exec} = require('child_process');
const { exec } = require('child_process');
const request = require('request-promise-native');
const RestSession = require('./session');
const RestMultiSession = require('./multi');
@@ -26,7 +26,7 @@ function execAsync(command, options) {
if (error) {
reject(error);
} else {
resolve({stdout, stderr});
resolve({ stdout, stderr });
}
});
});
@@ -67,7 +67,7 @@ module.exports = class RestSessionCreator {
registerCmd,
].join(' && ');
await execAsync(allCmds, {cwd: this.cwd, encoding: 'utf-8'});
await execAsync(allCmds, { cwd: this.cwd, encoding: 'utf-8' });
}
async _authenticate(username, password) {
@@ -80,7 +80,7 @@ module.exports = class RestSessionCreator {
"password": password,
};
const url = `${this.hsUrl}/_matrix/client/r0/login`;
const responseBody = await request.post({url, json: true, body: requestBody});
const responseBody = await request.post({ url, json: true, body: requestBody });
return {
accessToken: responseBody.access_token,
homeServer: responseBody.home_server,

View File

@@ -17,7 +17,7 @@ limitations under the License.
const request = require('request-promise-native');
const Logger = require('../logger');
const RestRoom = require('./room');
const {approveConsent} = require('./consent');
const { approveConsent } = require('./consent');
module.exports = class RestSession {
constructor(credentials) {

View File

@@ -14,8 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
const {range} = require('./util');
const { range } = require('./util');
const signup = require('./usecases/signup');
const toastScenarios = require('./scenarios/toast');
const roomDirectoryScenarios = require('./scenarios/directory');

View File

@@ -15,23 +15,22 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
const join = require('../usecases/join');
const sendMessage = require('../usecases/send-message');
const {receiveMessage} = require('../usecases/timeline');
const {createRoom} = require('../usecases/create-room');
const {changeRoomSettings} = require('../usecases/room-settings');
const { receiveMessage } = require('../usecases/timeline');
const { createRoom } = require('../usecases/create-room');
const { changeRoomSettings } = require('../usecases/room-settings');
module.exports = async function roomDirectoryScenarios(alice, bob) {
console.log(" creating a public room and join through directory:");
const room = 'test';
await createRoom(alice, room);
await changeRoomSettings(alice, {directory: true, visibility: "public_no_guests", alias: "#test"});
await changeRoomSettings(alice, { directory: true, visibility: "public_no_guests", alias: "#test" });
await join(bob, room); //looks up room in directory
const bobMessage = "hi Alice!";
await sendMessage(bob, bobMessage);
await receiveMessage(alice, {sender: "bob", body: bobMessage});
await receiveMessage(alice, { sender: "bob", body: bobMessage });
const aliceMessage = "hi Bob, welcome!";
await sendMessage(alice, aliceMessage);
await receiveMessage(bob, {sender: "alice", body: aliceMessage});
await receiveMessage(bob, { sender: "alice", body: aliceMessage });
};

View File

@@ -17,19 +17,18 @@ limitations under the License.
const sendMessage = require('../usecases/send-message');
const acceptInvite = require('../usecases/accept-invite');
const {receiveMessage} = require('../usecases/timeline');
const {createDm} = require('../usecases/create-room');
const {checkRoomSettings} = require('../usecases/room-settings');
const {startSasVerification, acceptSasVerification} = require('../usecases/verify');
const { receiveMessage } = require('../usecases/timeline');
const { createDm } = require('../usecases/create-room');
const { checkRoomSettings } = require('../usecases/room-settings');
const { startSasVerification, acceptSasVerification } = require('../usecases/verify');
const { setupSecureBackup } = require('../usecases/security');
const assert = require('assert');
const { measureStart, measureStop } = require('../util');
module.exports = async function e2eEncryptionScenarios(alice, bob) {
console.log(" creating an e2e encrypted DM and join through invite:");
await createDm(bob, ['@alice:localhost']);
await checkRoomSettings(bob, {encryption: true}); // for sanity, should be e2e-by-default
await checkRoomSettings(bob, { encryption: true }); // for sanity, should be e2e-by-default
await acceptInvite(alice, 'bob');
// do sas verifcation
bob.log.step(`starts SAS verification with ${alice.username}`);
@@ -44,9 +43,9 @@ module.exports = async function e2eEncryptionScenarios(alice, bob) {
bob.log.done(`done (match for ${bobSas.join(", ")})`);
const aliceMessage = "Guess what I just heard?!";
await sendMessage(alice, aliceMessage);
await receiveMessage(bob, {sender: "alice", body: aliceMessage, encrypted: true});
await receiveMessage(bob, { sender: "alice", body: aliceMessage, encrypted: true });
const bobMessage = "You've got to tell me!";
await sendMessage(bob, bobMessage);
await receiveMessage(alice, {sender: "bob", body: bobMessage, encrypted: true});
await receiveMessage(alice, { sender: "bob", body: bobMessage, encrypted: true });
await setupSecureBackup(alice);
};

View File

@@ -15,17 +15,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
const {delay} = require('../util');
const { delay } = require('../util');
const join = require('../usecases/join');
const sendMessage = require('../usecases/send-message');
const {
checkTimelineContains,
scrollToTimelineTop,
} = require('../usecases/timeline');
const {createRoom} = require('../usecases/create-room');
const {getMembersInMemberlist} = require('../usecases/memberlist');
const {changeRoomSettings} = require('../usecases/room-settings');
const { createRoom } = require('../usecases/create-room');
const { getMembersInMemberlist } = require('../usecases/memberlist');
const { changeRoomSettings } = require('../usecases/room-settings');
const assert = require('assert');
module.exports = async function lazyLoadingScenarios(alice, bob, charlies) {
@@ -52,7 +51,7 @@ const charlyMsg2 = "how's it going??";
async function setupRoomWithBobAliceAndCharlies(alice, bob, charlies) {
await createRoom(bob, room);
await changeRoomSettings(bob, {directory: true, visibility: "public_no_guests", alias});
await changeRoomSettings(bob, { directory: true, visibility: "public_no_guests", alias });
// wait for alias to be set by server after clicking "save"
// so the charlies can join it.
await bob.delay(500);

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
const {assertNoToasts, acceptToast, rejectToast} = require("../usecases/toasts");
const { assertNoToasts, acceptToast, rejectToast } = require("../usecases/toasts");
module.exports = async function toastScenarios(alice, bob) {
console.log(" checking and clearing toasts:");

View File

@@ -18,7 +18,7 @@ limitations under the License.
const puppeteer = require('puppeteer');
const Logger = require('./logger');
const LogBuffer = require('./logbuffer');
const {delay} = require('./util');
const { delay } = require('./util');
const DEFAULT_TIMEOUT = 20000;
@@ -112,7 +112,7 @@ module.exports = class ElementSession {
async replaceInputText(input, text) {
// click 3 times to select all text
await input.click({clickCount: 3});
await input.click({ clickCount: 3 });
// waiting here solves not having selected all the text by the 3x click above,
// presumably because of the Field label animation.
await this.delay(300);
@@ -123,7 +123,7 @@ module.exports = class ElementSession {
}
query(selector, timeout = DEFAULT_TIMEOUT, hidden = false) {
return this.page.waitForSelector(selector, {visible: true, timeout, hidden});
return this.page.waitForSelector(selector, { visible: true, timeout, hidden });
}
async queryAll(selector) {

View File

@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
const {findSublist} = require("./create-room");
const { findSublist } = require("./create-room");
module.exports = async function acceptInvite(session, name) {
session.log.step(`accepts "${name}" invite`);
@@ -23,9 +23,9 @@ module.exports = async function acceptInvite(session, name) {
const invitesHandles = await inviteSublist.$$(".mx_RoomTile_name");
const invitesWithText = await Promise.all(invitesHandles.map(async (inviteHandle) => {
const text = await session.innerText(inviteHandle);
return {inviteHandle, text};
return { inviteHandle, text };
}));
const inviteHandle = invitesWithText.find(({inviteHandle, text}) => {
const inviteHandle = invitesWithText.find(({ inviteHandle, text }) => {
return text.trim() === name;
}).inviteHandle;

View File

@@ -84,4 +84,4 @@ async function createDm(session, invitees) {
await measureStop(session, "mx_CreateDM");
}
module.exports = {openRoomDirectory, findSublist, createRoom, createDm};
module.exports = { openRoomDirectory, findSublist, createRoom, createDm };

View File

@@ -15,10 +15,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
const {openRoomDirectory} = require('./create-room');
const { openRoomDirectory } = require('./create-room');
const { measureStart, measureStop } = require('../util');
module.exports = async function join(session, roomName) {
session.log.step(`joins room "${roomName}"`);
await measureStart(session, "mx_JoinRoom");

View File

@@ -16,7 +16,7 @@ limitations under the License.
*/
const assert = require('assert');
const {openRoomSummaryCard} = require("./rightpanel");
const { openRoomSummaryCard } = require("./rightpanel");
async function openMemberInfo(session, name) {
const membersAndNames = await getMembersInMemberlist(session);
@@ -49,7 +49,6 @@ module.exports.verifyDeviceForUser = async function(session, name, expectedDevic
const sasLabels = await Promise.all(sasLabelElements.map(e => session.innerText(e)));
console.log("my sas labels", sasLabels);
const dialogCodeFields = await session.queryAll(".mx_QuestionDialog code");
assert.equal(dialogCodeFields.length, 2);
const deviceId = await session.innerText(dialogCodeFields[0]);
@@ -71,7 +70,7 @@ async function getMembersInMemberlist(session) {
const memberNameElements = await session.queryAll(".mx_MemberList .mx_EntityTile_name");
return Promise.all(memberNameElements.map(async (el) => {
return {label: el, displayName: await session.innerText(el)};
return { label: el, displayName: await session.innerText(el) };
}));
}

View File

@@ -32,7 +32,11 @@ module.exports.goBackToRoomSummaryCard = async function(session) {
// Sometimes our tests have this opened to MemberInfo
await backButton.click();
} catch (e) {
break; // stop trying to go further back
// explicitly check for TimeoutError as this sometimes returned
// `Error: Node is detached from document` due to a re-render race or similar
if (e.name === "TimeoutError") {
break; // stop trying to go further back
}
}
}
};

View File

@@ -16,8 +16,8 @@ limitations under the License.
*/
const assert = require('assert');
const {openRoomSummaryCard} = require("./rightpanel");
const {acceptDialog} = require('./dialog');
const { openRoomSummaryCard } = require("./rightpanel");
const { acceptDialog } = require('./dialog');
async function setSettingsToggle(session, toggle, enabled) {
const className = await session.getElementProperty(toggle, "className");
@@ -57,13 +57,13 @@ async function findTabs(session) {
const tabLabels = await Promise.all(tabButtons.map(t => session.innerText(t)));
const securityTabButton = tabButtons[tabLabels.findIndex(l => l.toLowerCase().includes("security"))];
return {securityTabButton};
return { securityTabButton };
}
async function checkRoomSettings(session, expectedSettings) {
session.log.startGroup(`checks the room settings`);
const {securityTabButton} = await findTabs(session);
const { securityTabButton } = await findTabs(session);
const generalSwitches = await session.queryAll(".mx_RoomSettingsDialog .mx_ToggleSwitch");
const isDirectory = generalSwitches[0];
@@ -129,7 +129,7 @@ async function checkRoomSettings(session, expectedSettings) {
async function changeRoomSettings(session, settings) {
session.log.startGroup(`changes the room settings`);
const {securityTabButton} = await findTabs(session);
const { securityTabButton } = await findTabs(session);
const generalSwitches = await session.queryAll(".mx_RoomSettingsDialog .mx_ToggleSwitch");
const isDirectory = generalSwitches[0];
@@ -140,8 +140,6 @@ async function changeRoomSettings(session, settings) {
if (settings.alias) {
session.log.step(`sets alias to ${settings.alias}`);
const summary = await session.query(".mx_RoomSettingsDialog .mx_AliasSettings summary");
await summary.click();
const aliasField = await session.query(".mx_RoomSettingsDialog .mx_AliasSettings details input[type=text]");
await session.replaceInputText(aliasField, settings.alias.substring(1, settings.alias.lastIndexOf(":")));
const addButton = await session.query(".mx_RoomSettingsDialog .mx_AliasSettings details .mx_AccessibleButton");
@@ -190,4 +188,4 @@ async function changeRoomSettings(session, settings) {
session.log.endGroup();
}
module.exports = {checkRoomSettings, changeRoomSettings};
module.exports = { checkRoomSettings, changeRoomSettings };

View File

@@ -51,5 +51,5 @@ module.exports.getE2EDeviceFromSettings = async function(session) {
const closeButton = await session.query(".mx_UserSettingsDialog .mx_Dialog_cancelButton");
await closeButton.click();
session.log.done();
return {id, key};
return { id, key };
};

View File

@@ -69,7 +69,6 @@ module.exports.receiveMessage = async function(session, expectedMessage) {
session.log.done();
};
module.exports.checkTimelineContains = async function(session, expectedMessages, sendersDescription) {
session.log.step(`checks timeline contains ${expectedMessages.length} ` +
`given messages${sendersDescription ? ` from ${sendersDescription}`:""}`);

View File

@@ -40,8 +40,8 @@ async function acceptToast(session, expectedTitle) {
async function rejectToast(session, expectedTitle) {
await assertToast(session, expectedTitle);
const btn = await session.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger');
const btn = await session.query('.mx_Toast_buttons .mx_AccessibleButton_kind_danger_outline');
await btn.click();
}
module.exports = {assertNoToasts, assertToast, acceptToast, rejectToast};
module.exports = { assertNoToasts, assertToast, acceptToast, rejectToast };

View File

@@ -16,7 +16,7 @@ limitations under the License.
*/
const assert = require('assert');
const {openMemberInfo} = require("./memberlist");
const { openMemberInfo } = require("./memberlist");
async function startVerification(session, name) {
session.log.step("opens their opponent's profile and starts verification");

View File

@@ -133,7 +133,7 @@ async function writeLogs(sessions, dir) {
fs.writeFileSync(appHtmlName, documentHtml);
fs.writeFileSync(networkLogName, session.networkLogs());
fs.writeFileSync(consoleLogName, session.consoleLogs());
await session.page.screenshot({path: `${userLogDir}/screenshot.png`});
await session.page.screenshot({ path: `${userLogDir}/screenshot.png` });
}
return logs;
}

View File

@@ -7,12 +7,19 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-11.12.1.tgz#d90123f6c61fdf2f7cddd286ddae891586dd3488"
integrity sha512-sKDlqv6COJrR7ar0+GqqhrXQDzQlMcqMnF2iEU6m9hLo8kxozoAGUazwPyELHlRVmjsbvlnGXjnzyptSXVmceA==
agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
"@types/yauzl@^2.9.1":
version "2.9.1"
resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.1.tgz#d10f69f9f522eef3cf98e30afb684a1e1ec923af"
integrity sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==
dependencies:
es6-promisify "^5.0.0"
"@types/node" "*"
agent-base@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
dependencies:
debug "4"
ajv@^6.5.5:
version "6.10.0"
@@ -36,11 +43,6 @@ assert-plus@1.0.0, assert-plus@^1.0.0:
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
async-limiter@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
@@ -61,6 +63,11 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
bcrypt-pbkdf@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
@@ -68,6 +75,15 @@ bcrypt-pbkdf@^1.0.0:
dependencies:
tweetnacl "^0.14.3"
bl@^4.0.3:
version "4.1.0"
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
dependencies:
buffer "^5.5.0"
inherits "^2.0.4"
readable-stream "^3.4.0"
boolbase@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
@@ -86,10 +102,13 @@ buffer-crc32@~0.2.3:
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
buffer@^5.2.1, buffer@^5.5.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
dependencies:
base64-js "^1.3.1"
ieee754 "^1.1.13"
caseless@~0.12.0:
version "0.12.0"
@@ -108,6 +127,11 @@ cheerio@^1.0.0-rc.2:
lodash "^4.15.0"
parse5 "^3.0.1"
chownr@^1.1.1:
version "1.1.4"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828"
@@ -125,17 +149,7 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
concat-stream@^1.6.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
dependencies:
buffer-from "^1.0.0"
inherits "^2.0.3"
readable-stream "^2.2.2"
typedarray "^0.0.6"
core-util-is@1.0.2, core-util-is@~1.0.0:
core-util-is@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
@@ -162,21 +176,7 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
dependencies:
ms "2.0.0"
debug@^3.1.0:
version "3.2.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
dependencies:
ms "^2.1.1"
debug@^4.1.0:
debug@4, debug@4.3.1, debug@^4.1.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
@@ -188,6 +188,11 @@ delayed-stream@~1.0.0:
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
devtools-protocol@0.0.883894:
version "0.0.883894"
resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.883894.tgz#d403f2c75cd6d71c916aee8dde9258da988a4da9"
integrity sha512-33idhm54QJzf3Q7QofMgCvIVSd2o9H3kQPWaKT/fhoZh+digc+WSiMhbkeG3iN79WY4Hwr9G05NpbhEVrsOYAg==
dom-serializer@0, dom-serializer@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0"
@@ -232,37 +237,33 @@ ecc-jsbn@~0.1.1:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
end-of-stream@^1.1.0, end-of-stream@^1.4.1:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
dependencies:
once "^1.4.0"
entities@^1.1.1, entities@~1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
es6-promise@^4.0.3:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
es6-promisify@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
dependencies:
es6-promise "^4.0.3"
extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
extract-zip@^1.6.6:
version "1.7.0"
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927"
integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==
extract-zip@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
dependencies:
concat-stream "^1.6.2"
debug "^2.6.9"
mkdirp "^0.5.4"
debug "^4.1.1"
get-stream "^5.1.0"
yauzl "^2.10.0"
optionalDependencies:
"@types/yauzl" "^2.9.1"
extsprintf@1.3.0:
version "1.3.0"
@@ -291,6 +292,14 @@ fd-slicer@~1.1.0:
dependencies:
pend "~1.2.0"
find-up@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
dependencies:
locate-path "^5.0.0"
path-exists "^4.0.0"
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
@@ -305,11 +314,23 @@ form-data@~2.3.2:
combined-stream "^1.0.6"
mime-types "^2.1.12"
fs-constants@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
get-stream@^5.1.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
dependencies:
pump "^3.0.0"
getpass@^0.1.1:
version "0.1.7"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
@@ -363,13 +384,18 @@ http-signature@~1.2.0:
jsprim "^1.2.2"
sshpk "^1.7.0"
https-proxy-agent@^2.2.1:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
https-proxy-agent@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
dependencies:
agent-base "^4.3.0"
debug "^3.1.0"
agent-base "6"
debug "4"
ieee754@^1.1.13:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
inflight@^1.0.4:
version "1.0.6"
@@ -379,7 +405,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
inherits@2, inherits@^2.0.3, inherits@~2.0.3:
inherits@2, inherits@^2.0.3, inherits@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -394,11 +420,6 @@ is-typedarray@~1.0.0:
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
@@ -434,6 +455,13 @@ jsprim@^1.2.2:
json-schema "0.2.3"
verror "1.10.0"
locate-path@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
dependencies:
p-locate "^4.1.0"
lodash@^4.15.0, lodash@^4.17.11:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
@@ -451,11 +479,6 @@ mime-types@^2.1.12, mime-types@~2.1.19:
dependencies:
mime-db "~1.38.0"
mime@^2.0.3:
version "2.5.2"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe"
integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==
minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
@@ -468,27 +491,22 @@ minimist@^1.2.5:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
mkdirp@^0.5.4:
mkdirp@^0.5.1:
version "0.5.5"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
dependencies:
minimist "^1.2.5"
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
ms@^2.1.1:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
node-fetch@2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
nth-check@~1.0.1:
version "1.0.2"
@@ -502,13 +520,32 @@ oauth-sign@~0.9.0:
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
once@^1.3.0:
once@^1.3.0, once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
dependencies:
wrappy "1"
p-limit@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
dependencies:
p-try "^2.0.0"
p-locate@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
dependencies:
p-limit "^2.2.0"
p-try@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
parse5@^3.0.1:
version "3.0.3"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c"
@@ -516,6 +553,11 @@ parse5@^3.0.1:
dependencies:
"@types/node" "*"
path-exists@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
@@ -531,17 +573,19 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
process-nextick-args@~2.0.0:
pkg-dir@4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
dependencies:
find-up "^4.0.0"
progress@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.1.tgz#c9242169342b1c29d275889c95734621b1952e31"
integrity sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==
progress@^2.0.1:
version "2.0.3"
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
proxy-from-env@^1.0.0:
proxy-from-env@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
@@ -551,6 +595,14 @@ psl@^1.1.24, psl@^1.1.28:
resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184"
integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==
pump@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
dependencies:
end-of-stream "^1.1.0"
once "^1.3.1"
punycode@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
@@ -561,38 +613,29 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
puppeteer@^1.14.0:
version "1.20.0"
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-1.20.0.tgz#e3d267786f74e1d87cf2d15acc59177f471bbe38"
integrity sha512-bt48RDBy2eIwZPrkgbcwHtb51mj2nKvHOPMaSH2IsWiv7lOG9k9zhaRzpDZafrk05ajMc3cu+lSQYYOfH2DkVQ==
puppeteer@10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-10.0.0.tgz#1b597c956103e2d989ca17f41ba4693b20a3640c"
integrity sha512-AxHvCb9IWmmP3gMW+epxdj92Gglii+6Z4sb+W+zc2hTTu10HF0yg6hGXot5O74uYkVqG3lfDRLfnRpi6WOwi5A==
dependencies:
debug "^4.1.0"
extract-zip "^1.6.6"
https-proxy-agent "^2.2.1"
mime "^2.0.3"
progress "^2.0.1"
proxy-from-env "^1.0.0"
rimraf "^2.6.1"
ws "^6.1.0"
debug "4.3.1"
devtools-protocol "0.0.883894"
extract-zip "2.0.1"
https-proxy-agent "5.0.0"
node-fetch "2.6.1"
pkg-dir "4.2.0"
progress "2.0.1"
proxy-from-env "1.1.0"
rimraf "3.0.2"
tar-fs "2.0.0"
unbzip2-stream "1.3.3"
ws "7.4.6"
qs@~6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
readable-stream@^2.2.2:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
isarray "~1.0.0"
process-nextick-args "~2.0.0"
safe-buffer "~5.1.1"
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
readable-stream@^3.1.1:
version "3.2.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.2.0.tgz#de17f229864c120a9f56945756e4f32c4045245d"
@@ -602,6 +645,15 @@ readable-stream@^3.1.1:
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readable-stream@^3.4.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
dependencies:
inherits "^2.0.3"
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
request-promise-core@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346"
@@ -644,14 +696,14 @@ request@^2.88.0:
tunnel-agent "^0.6.0"
uuid "^3.3.2"
rimraf@^2.6.1:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
rimraf@3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
dependencies:
glob "^7.1.3"
safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
@@ -688,12 +740,31 @@ string_decoder@^1.1.1:
dependencies:
safe-buffer "~5.1.0"
string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
tar-fs@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad"
integrity sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==
dependencies:
safe-buffer "~5.1.0"
chownr "^1.1.1"
mkdirp "^0.5.1"
pump "^3.0.0"
tar-stream "^2.0.0"
tar-stream@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
dependencies:
bl "^4.0.3"
end-of-stream "^1.4.1"
fs-constants "^1.0.0"
inherits "^2.0.3"
readable-stream "^3.1.1"
through@^2.3.8:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
tough-cookie@^2.3.3:
version "2.5.0"
@@ -723,10 +794,13 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
unbzip2-stream@1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a"
integrity sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==
dependencies:
buffer "^5.2.1"
through "^2.3.8"
uri-js@^4.2.2:
version "4.2.2"
@@ -735,7 +809,7 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
util-deprecate@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
@@ -759,12 +833,10 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
ws@^6.1.0:
version "6.2.2"
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.2.tgz#dd5cdbd57a9979916097652d78f1cc5faea0c32e"
integrity sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==
dependencies:
async-limiter "~1.0.0"
ws@7.4.6:
version "7.4.6"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
yauzl@^2.10.0:
version "2.10.0"

View File

@@ -1,421 +0,0 @@
/*
Copyright (c) 2008-2015 Pivotal Labs
Copyright 2019 The Matrix.org Foundation C.I.C.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* This is jasmine's implementation of a mock clock, lifted from the depths of
* jasmine-core and exposed as a standalone module. The interface is just the
* same as that of jasmine.clock. For example:
*
* var mock_clock = require("../../mock-clock").clock();
* mock_clock.install();
* setTimeout(function() {
* timerCallback();
* }, 100);
*
* expect(timerCallback).not.toHaveBeenCalled();
* mock_clock.tick(101);
* expect(timerCallback).toHaveBeenCalled();
*
* mock_clock.uninstall();
*
*
* The reason for C&Ping jasmine's clock here is that jasmine itself is
* difficult to webpack, and we don't really want all of it. Sinon also has a
* mock-clock implementation, but again, it is difficult to webpack.
*/
const j$ = {};
j$.Clock = function() {
function Clock(global, delayedFunctionSchedulerFactory, mockDate) {
let self = this,
realTimingFunctions = {
setTimeout: global.setTimeout,
clearTimeout: global.clearTimeout,
setInterval: global.setInterval,
clearInterval: global.clearInterval,
},
fakeTimingFunctions = {
setTimeout: setTimeout,
clearTimeout: clearTimeout,
setInterval: setInterval,
clearInterval: clearInterval,
},
installed = false,
delayedFunctionScheduler,
timer;
self.install = function() {
if(!originalTimingFunctionsIntact()) {
throw new Error('Jasmine Clock was unable to install over custom global timer functions. Is the clock already installed?');
}
replace(global, fakeTimingFunctions);
timer = fakeTimingFunctions;
delayedFunctionScheduler = delayedFunctionSchedulerFactory();
installed = true;
return self;
};
self.uninstall = function() {
delayedFunctionScheduler = null;
mockDate.uninstall();
replace(global, realTimingFunctions);
timer = realTimingFunctions;
installed = false;
};
self.withMock = function(closure) {
this.install();
try {
closure();
} finally {
this.uninstall();
}
};
self.mockDate = function(initialDate) {
mockDate.install(initialDate);
};
self.setTimeout = function(fn, delay, params) {
if (legacyIE()) {
if (arguments.length > 2) {
throw new Error('IE < 9 cannot support extra params to setTimeout without a polyfill');
}
return timer.setTimeout(fn, delay);
}
return Function.prototype.apply.apply(timer.setTimeout, [global, arguments]);
};
self.setInterval = function(fn, delay, params) {
if (legacyIE()) {
if (arguments.length > 2) {
throw new Error('IE < 9 cannot support extra params to setInterval without a polyfill');
}
return timer.setInterval(fn, delay);
}
return Function.prototype.apply.apply(timer.setInterval, [global, arguments]);
};
self.clearTimeout = function(id) {
return Function.prototype.call.apply(timer.clearTimeout, [global, id]);
};
self.clearInterval = function(id) {
return Function.prototype.call.apply(timer.clearInterval, [global, id]);
};
self.tick = function(millis) {
if (installed) {
mockDate.tick(millis);
delayedFunctionScheduler.tick(millis);
} else {
throw new Error('Mock clock is not installed, use jasmine.clock().install()');
}
};
return self;
function originalTimingFunctionsIntact() {
return global.setTimeout === realTimingFunctions.setTimeout &&
global.clearTimeout === realTimingFunctions.clearTimeout &&
global.setInterval === realTimingFunctions.setInterval &&
global.clearInterval === realTimingFunctions.clearInterval;
}
function legacyIE() {
//if these methods are polyfilled, apply will be present
return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply;
}
function replace(dest, source) {
for (const prop in source) {
dest[prop] = source[prop];
}
}
function setTimeout(fn, delay) {
return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2));
}
function clearTimeout(id) {
return delayedFunctionScheduler.removeFunctionWithId(id);
}
function setInterval(fn, interval) {
return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true);
}
function clearInterval(id) {
return delayedFunctionScheduler.removeFunctionWithId(id);
}
function argSlice(argsObj, n) {
return Array.prototype.slice.call(argsObj, n);
}
}
return Clock;
}();
j$.DelayedFunctionScheduler = function() {
function DelayedFunctionScheduler() {
const self = this;
const scheduledLookup = [];
const scheduledFunctions = {};
let currentTime = 0;
let delayedFnCount = 0;
self.tick = function(millis) {
millis = millis || 0;
const endTime = currentTime + millis;
runScheduledFunctions(endTime);
currentTime = endTime;
};
self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) {
let f;
if (typeof(funcToCall) === 'string') {
/* jshint evil: true */
f = function() { return eval(funcToCall); };
/* jshint evil: false */
} else {
f = funcToCall;
}
millis = millis || 0;
timeoutKey = timeoutKey || ++delayedFnCount;
runAtMillis = runAtMillis || (currentTime + millis);
const funcToSchedule = {
runAtMillis: runAtMillis,
funcToCall: f,
recurring: recurring,
params: params,
timeoutKey: timeoutKey,
millis: millis,
};
if (runAtMillis in scheduledFunctions) {
scheduledFunctions[runAtMillis].push(funcToSchedule);
} else {
scheduledFunctions[runAtMillis] = [funcToSchedule];
scheduledLookup.push(runAtMillis);
scheduledLookup.sort(function(a, b) {
return a - b;
});
}
return timeoutKey;
};
self.removeFunctionWithId = function(timeoutKey) {
for (const runAtMillis in scheduledFunctions) {
const funcs = scheduledFunctions[runAtMillis];
const i = indexOfFirstToPass(funcs, function(func) {
return func.timeoutKey === timeoutKey;
});
if (i > -1) {
if (funcs.length === 1) {
delete scheduledFunctions[runAtMillis];
deleteFromLookup(runAtMillis);
} else {
funcs.splice(i, 1);
}
// intervals get rescheduled when executed, so there's never more
// than a single scheduled function with a given timeoutKey
break;
}
}
};
return self;
function indexOfFirstToPass(array, testFn) {
let index = -1;
for (let i = 0; i < array.length; ++i) {
if (testFn(array[i])) {
index = i;
break;
}
}
return index;
}
function deleteFromLookup(key) {
const value = Number(key);
const i = indexOfFirstToPass(scheduledLookup, function(millis) {
return millis === value;
});
if (i > -1) {
scheduledLookup.splice(i, 1);
}
}
function reschedule(scheduledFn) {
self.scheduleFunction(scheduledFn.funcToCall,
scheduledFn.millis,
scheduledFn.params,
true,
scheduledFn.timeoutKey,
scheduledFn.runAtMillis + scheduledFn.millis);
}
function forEachFunction(funcsToRun, callback) {
for (let i = 0; i < funcsToRun.length; ++i) {
callback(funcsToRun[i]);
}
}
function runScheduledFunctions(endTime) {
if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) {
return;
}
do {
currentTime = scheduledLookup.shift();
const funcsToRun = scheduledFunctions[currentTime];
delete scheduledFunctions[currentTime];
forEachFunction(funcsToRun, function(funcToRun) {
if (funcToRun.recurring) {
reschedule(funcToRun);
}
});
forEachFunction(funcsToRun, function(funcToRun) {
funcToRun.funcToCall.apply(null, funcToRun.params || []);
});
} while (scheduledLookup.length > 0 &&
// checking first if we're out of time prevents setTimeout(0)
// scheduled in a funcToRun from forcing an extra iteration
currentTime !== endTime &&
scheduledLookup[0] <= endTime);
}
}
return DelayedFunctionScheduler;
}();
j$.MockDate = function() {
function MockDate(global) {
const self = this;
let currentTime = 0;
if (!global || !global.Date) {
self.install = function() {};
self.tick = function() {};
self.uninstall = function() {};
return self;
}
const GlobalDate = global.Date;
self.install = function(mockDate) {
if (mockDate instanceof GlobalDate) {
currentTime = mockDate.getTime();
} else {
currentTime = new GlobalDate().getTime();
}
global.Date = FakeDate;
};
self.tick = function(millis) {
millis = millis || 0;
currentTime = currentTime + millis;
};
self.uninstall = function() {
currentTime = 0;
global.Date = GlobalDate;
};
createDateProperties();
return self;
function FakeDate() {
switch(arguments.length) {
case 0:
return new GlobalDate(currentTime);
case 1:
return new GlobalDate(arguments[0]);
case 2:
return new GlobalDate(arguments[0], arguments[1]);
case 3:
return new GlobalDate(arguments[0], arguments[1], arguments[2]);
case 4:
return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3]);
case 5:
return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3],
arguments[4]);
case 6:
return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3],
arguments[4], arguments[5]);
default:
return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3],
arguments[4], arguments[5], arguments[6]);
}
}
function createDateProperties() {
FakeDate.prototype = GlobalDate.prototype;
FakeDate.now = function() {
if (GlobalDate.now) {
return currentTime;
} else {
throw new Error('Browser does not support Date.now()');
}
};
FakeDate.toSource = GlobalDate.toSource;
FakeDate.toString = GlobalDate.toString;
FakeDate.parse = GlobalDate.parse;
FakeDate.UTC = GlobalDate.UTC;
}
}
return MockDate;
}();
const _clock = new j$.Clock(global, function() { return new j$.DelayedFunctionScheduler(); }, new j$.MockDate(global));
export function clock() {
return _clock;
}

View File

@@ -52,13 +52,12 @@ const USERNAME_RULE = {
rule_id: ".m.rule.contains_user_name",
};
describe("ContentRules", function() {
describe("parseContentRules", function() {
it("should handle there being no keyword rules", function() {
const rules = { 'global': { 'content': [
USERNAME_RULE,
]}};
] } };
const parsed = ContentRules.parseContentRules(rules);
expect(parsed.rules).toEqual([]);
expect(parsed.vectorState).toEqual(PushRuleVectorState.ON);
@@ -69,7 +68,7 @@ describe("ContentRules", function() {
const rules = { 'global': { 'content': [
NORMAL_RULE,
USERNAME_RULE,
]}};
] } };
const parsed = ContentRules.parseContentRules(rules);
expect(parsed.rules.length).toEqual(1);
@@ -82,7 +81,7 @@ describe("ContentRules", function() {
const rules = { 'global': { 'content': [
LOUD_RULE,
USERNAME_RULE,
]}};
] } };
const parsed = ContentRules.parseContentRules(rules);
expect(parsed.rules.length).toEqual(1);
@@ -96,7 +95,7 @@ describe("ContentRules", function() {
LOUD_RULE,
NORMAL_RULE,
USERNAME_RULE,
]}};
] } };
const parsed = ContentRules.parseContentRules(rules);
expect(parsed.rules.length).toEqual(1);

View File

@@ -18,12 +18,12 @@ components['structures.RightPanel'] = stubComponent();
components['structures.RoomDirectory'] = stubComponent();
components['views.globals.GuestWarningBar'] = stubComponent();
components['views.globals.NewVersionBar'] = stubComponent();
components['views.elements.Spinner'] = stubComponent({displayName: 'Spinner'});
components['views.messages.DateSeparator'] = stubComponent({displayName: 'DateSeparator'});
components['views.messages.MessageTimestamp'] = stubComponent({displayName: 'MessageTimestamp'});
components['views.messages.SenderProfile'] = stubComponent({displayName: 'SenderProfile'});
components['views.elements.Spinner'] = stubComponent({ displayName: 'Spinner' });
components['views.messages.DateSeparator'] = stubComponent({ displayName: 'DateSeparator' });
components['views.messages.MessageTimestamp'] = stubComponent({ displayName: 'MessageTimestamp' });
components['views.messages.SenderProfile'] = stubComponent({ displayName: 'SenderProfile' });
components['views.rooms.SearchBar'] = stubComponent();
sdk.loadSkin({components});
sdk.loadSkin({ components });
export default sdk;

View File

@@ -1,6 +1,6 @@
import RoomViewStore from '../../src/stores/RoomViewStore';
import {MatrixClientPeg as peg} from '../../src/MatrixClientPeg';
import { MatrixClientPeg as peg } from '../../src/MatrixClientPeg';
import * as testUtils from '../test-utils';
@@ -36,7 +36,7 @@ describe('RoomViewStore', function() {
}
});
peg.get().getRoomIdForAlias.mockResolvedValue({room_id: "!randomcharacters:aser.ver"});
peg.get().getRoomIdForAlias.mockResolvedValue({ room_id: "!randomcharacters:aser.ver" });
peg.get().joinRoom = async (roomAddress) => {
token.remove(); // stop RVS listener
expect(roomAddress).toBe("#somealias2:aser.ver");

View File

@@ -123,8 +123,15 @@ describe("SpaceStore", () => {
jest.runAllTimers();
client.getVisibleRooms.mockReturnValue(rooms = []);
getValue.mockImplementation(settingName => {
if (settingName === "feature_spaces") {
return true;
switch (settingName) {
case "feature_spaces":
return true;
case "feature_spaces.all_rooms":
return true;
case "feature_spaces.space_member_dms":
return true;
case "feature_spaces.space_dm_badges":
return false;
}
});
});

View File

@@ -1,11 +1,11 @@
import React from 'react';
import {MatrixClientPeg as peg} from '../src/MatrixClientPeg';
import { MatrixClientPeg as peg } from '../src/MatrixClientPeg';
import dis from '../src/dispatcher/dispatcher';
import {makeType} from "../src/utils/TypeUtils";
import {ValidatedServerConfig} from "../src/utils/AutoDiscoveryUtils";
import { makeType } from "../src/utils/TypeUtils";
import { ValidatedServerConfig } from "../src/utils/AutoDiscoveryUtils";
import ShallowRenderer from 'react-test-renderer/shallow';
import MatrixClientContext from "../src/contexts/MatrixClientContext";
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
export function getRenderer() {
// Old: ReactTestUtils.createRenderer();

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {TextEncoder} from "util";
import { TextEncoder } from "util";
import nodeCrypto from "crypto";
import { Crypto } from "@peculiar/webcrypto";
@@ -144,7 +144,7 @@ cissyYBxjsfsAn
const password = 'my super secret passphrase';
return MegolmExportEncryption.encryptMegolmKeyFile(
input, password, {kdf_rounds: 1000},
input, password, { kdf_rounds: 1000 },
).then((ciphertext) => {
return MegolmExportEncryption.decryptMegolmKeyFile(
ciphertext, password,

View File

@@ -54,7 +54,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
const client = mkClient(trusted);
const room = {
roomId: dm ? "DM" : "other",
getEncryptionTargetMembers: () => ["@self:localhost", "@FF1:h", "@FF2:h"].map((userId) => ({userId})),
getEncryptionTargetMembers: () => ["@self:localhost", "@FF1:h", "@FF2:h"].map((userId) => ({ userId })),
};
const status = await shieldStatusForRoom(client, room);
expect(status).toEqual("normal");
@@ -67,7 +67,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
const client = mkClient(trusted);
const room = {
roomId: dm ? "DM" : "other",
getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@TT2:h"].map((userId) => ({userId})),
getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@TT2:h"].map((userId) => ({ userId })),
};
const status = await shieldStatusForRoom(client, room);
expect(status).toEqual(result);
@@ -80,7 +80,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
const client = mkClient(trusted);
const room = {
roomId: dm ? "DM" : "other",
getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@FF2:h"].map((userId) => ({userId})),
getEncryptionTargetMembers: () => ["@self:localhost", "@TT1:h", "@FF2:h"].map((userId) => ({ userId })),
};
const status = await shieldStatusForRoom(client, room);
expect(status).toEqual(result);
@@ -93,7 +93,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
const client = mkClient(trusted);
const room = {
roomId: dm ? "DM" : "other",
getEncryptionTargetMembers: () => ["@self:localhost"].map((userId) => ({userId})),
getEncryptionTargetMembers: () => ["@self:localhost"].map((userId) => ({ userId })),
};
const status = await shieldStatusForRoom(client, room);
expect(status).toEqual(result);
@@ -106,7 +106,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
const client = mkClient(trusted);
const room = {
roomId: dm ? "DM" : "other",
getEncryptionTargetMembers: () => ["@self:localhost", "@TT:h"].map((userId) => ({userId})),
getEncryptionTargetMembers: () => ["@self:localhost", "@TT:h"].map((userId) => ({ userId })),
};
const status = await shieldStatusForRoom(client, room);
expect(status).toEqual(result);
@@ -119,7 +119,7 @@ describe("shieldStatusForMembership self-trust behaviour", function() {
const client = mkClient(trusted);
const room = {
roomId: dm ? "DM" : "other",
getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h"].map((userId) => ({userId})),
getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h"].map((userId) => ({ userId })),
};
const status = await shieldStatusForRoom(client, room);
expect(status).toEqual(result);
@@ -139,7 +139,7 @@ describe("shieldStatusForMembership other-trust behaviour", function() {
const client = mkClient(true);
const room = {
roomId: dm ? "DM" : "other",
getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h"].map((userId) => ({userId})),
getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h"].map((userId) => ({ userId })),
};
const status = await shieldStatusForRoom(client, room);
expect(status).toEqual(result);
@@ -151,7 +151,7 @@ describe("shieldStatusForMembership other-trust behaviour", function() {
const client = mkClient(true);
const room = {
roomId: dm ? "DM" : "other",
getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h", "@TT:h"].map((userId) => ({userId})),
getEncryptionTargetMembers: () => ["@self:localhost", "@TF:h", "@TT:h"].map((userId) => ({ userId })),
};
const status = await shieldStatusForRoom(client, room);
expect(status).toEqual(result);
@@ -163,7 +163,7 @@ describe("shieldStatusForMembership other-trust behaviour", function() {
const client = mkClient(true);
const room = {
roomId: dm ? "DM" : "other",
getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h", "@FT:h"].map((userId) => ({userId})),
getEncryptionTargetMembers: () => ["@self:localhost", "@FF:h", "@FT:h"].map((userId) => ({ userId })),
};
const status = await shieldStatusForRoom(client, room);
expect(status).toEqual(result);
@@ -175,7 +175,7 @@ describe("shieldStatusForMembership other-trust behaviour", function() {
const client = mkClient(true);
const room = {
roomId: dm ? "DM" : "other",
getEncryptionTargetMembers: () => ["@self:localhost", "@WF:h", "@FT:h"].map((userId) => ({userId})),
getEncryptionTargetMembers: () => ["@self:localhost", "@WF:h", "@FT:h"].map((userId) => ({ userId })),
};
const status = await shieldStatusForRoom(client, room);
expect(status).toEqual(result);

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {Singleflight} from "../../src/utils/Singleflight";
import { Singleflight } from "../../src/utils/Singleflight";
describe('Singleflight', () => {
afterEach(() => {

View File

@@ -29,7 +29,7 @@ import {
ArrayUtil,
GroupedArray,
} from "../../src/utils/arrays";
import {objectFromEntries} from "../../src/utils/objects";
import { objectFromEntries } from "../../src/utils/objects";
function expectSample(i: number, input: number[], expected: number[], smooth = false) {
console.log(`Resample case index: ${i}`); // for debugging test failures
@@ -43,26 +43,26 @@ describe('arrays', () => {
describe('arrayFastResample', () => {
it('should downsample', () => {
[
{input: [1, 2, 3, 4, 5], output: [1, 4]}, // Odd -> Even
{input: [1, 2, 3, 4, 5], output: [1, 3, 5]}, // Odd -> Odd
{input: [1, 2, 3, 4], output: [1, 2, 3]}, // Even -> Odd
{input: [1, 2, 3, 4], output: [1, 3]}, // Even -> Even
{ input: [1, 2, 3, 4, 5], output: [1, 4] }, // Odd -> Even
{ input: [1, 2, 3, 4, 5], output: [1, 3, 5] }, // Odd -> Odd
{ input: [1, 2, 3, 4], output: [1, 2, 3] }, // Even -> Odd
{ input: [1, 2, 3, 4], output: [1, 3] }, // Even -> Even
].forEach((c, i) => expectSample(i, c.input, c.output));
});
it('should upsample', () => {
[
{input: [1, 2, 3], output: [1, 1, 2, 2, 3, 3]}, // Odd -> Even
{input: [1, 2, 3], output: [1, 1, 2, 2, 3]}, // Odd -> Odd
{input: [1, 2], output: [1, 1, 1, 2, 2]}, // Even -> Odd
{input: [1, 2], output: [1, 1, 1, 2, 2, 2]}, // Even -> Even
{ input: [1, 2, 3], output: [1, 1, 2, 2, 3, 3] }, // Odd -> Even
{ input: [1, 2, 3], output: [1, 1, 2, 2, 3] }, // Odd -> Odd
{ input: [1, 2], output: [1, 1, 1, 2, 2] }, // Even -> Odd
{ input: [1, 2], output: [1, 1, 1, 2, 2, 2] }, // Even -> Even
].forEach((c, i) => expectSample(i, c.input, c.output));
});
it('should maintain sample', () => {
[
{input: [1, 2, 3], output: [1, 2, 3]}, // Odd
{input: [1, 2], output: [1, 2]}, // Even
{ input: [1, 2, 3], output: [1, 2, 3] }, // Odd
{ input: [1, 2], output: [1, 2] }, // Even
].forEach((c, i) => expectSample(i, c.input, c.output));
});
});
@@ -73,26 +73,26 @@ describe('arrays', () => {
// 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.
[
{input: [4, 4, 1, 4, 4, 1, 4, 4, 1], output: [3, 3, 3, 3]}, // Odd -> Even
{input: [4, 4, 1, 4, 4, 1, 4, 4, 1], output: [3, 3, 3]}, // Odd -> Odd
{input: [4, 4, 1, 4, 4, 1, 4, 4], output: [3, 3, 3]}, // Even -> Odd
{input: [4, 4, 1, 4, 4, 1, 4, 4], output: [3, 3]}, // Even -> Even
{ input: [4, 4, 1, 4, 4, 1, 4, 4, 1], output: [3, 3, 3, 3] }, // Odd -> Even
{ input: [4, 4, 1, 4, 4, 1, 4, 4, 1], output: [3, 3, 3] }, // Odd -> Odd
{ input: [4, 4, 1, 4, 4, 1, 4, 4], output: [3, 3, 3] }, // Even -> Odd
{ input: [4, 4, 1, 4, 4, 1, 4, 4], output: [3, 3] }, // Even -> Even
].forEach((c, i) => expectSample(i, c.input, c.output, true));
});
it('should upsample', () => {
[
{input: [2, 0, 2], output: [2, 2, 0, 0, 2, 2]}, // Odd -> Even
{input: [2, 0, 2], output: [2, 2, 0, 0, 2]}, // Odd -> Odd
{input: [2, 0], output: [2, 2, 2, 0, 0]}, // Even -> Odd
{input: [2, 0], output: [2, 2, 2, 0, 0, 0]}, // Even -> Even
{ input: [2, 0, 2], output: [2, 2, 0, 0, 2, 2] }, // Odd -> Even
{ input: [2, 0, 2], output: [2, 2, 0, 0, 2] }, // Odd -> Odd
{ input: [2, 0], output: [2, 2, 2, 0, 0] }, // Even -> Odd
{ input: [2, 0], output: [2, 2, 2, 0, 0, 0] }, // Even -> Even
].forEach((c, i) => expectSample(i, c.input, c.output, true));
});
it('should maintain sample', () => {
[
{input: [2, 0, 2], output: [2, 0, 2]}, // Odd
{input: [2, 0], output: [2, 0]}, // Even
{ input: [2, 0, 2], output: [2, 0, 2] }, // Odd
{ input: [2, 0], output: [2, 0] }, // Even
].forEach((c, i) => expectSample(i, c.input, c.output, true));
});
});

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {getEnumValues, isEnumValue} from "../../src/utils/enums";
import { getEnumValues, isEnumValue } from "../../src/utils/enums";
enum TestStringEnum {
First = "__first__",

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {iterableDiff, iterableUnion} from "../../src/utils/iterables";
import { iterableDiff, iterableUnion } from "../../src/utils/iterables";
describe('iterables', () => {
describe('iterableUnion', () => {

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {EnhancedMap, mapDiff, mapKeyChanges} from "../../src/utils/maps";
import { EnhancedMap, mapDiff, mapKeyChanges } from "../../src/utils/maps";
describe('maps', () => {
describe('mapDiff', () => {
@@ -187,7 +187,7 @@ describe('maps', () => {
});
it('should use the provided entries', () => {
const obj = {a: 1, b: 2};
const obj = { a: 1, b: 2 };
const result = new EnhancedMap(Object.entries(obj));
expect(result.size).toBe(2);
expect(result.get('a')).toBe(1);

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {clamp, defaultNumber, percentageOf, percentageWithin, sum} from "../../src/utils/numbers";
import { clamp, defaultNumber, percentageOf, percentageWithin, sum } from "../../src/utils/numbers";
describe('numbers', () => {
describe('defaultNumber', () => {

View File

@@ -28,8 +28,8 @@ import {
describe('objects', () => {
describe('objectExcluding', () => {
it('should exclude the given properties', () => {
const input = {hello: "world", test: true};
const output = {hello: "world"};
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
const result = objectExcluding(input, <any>props); // any is to test the missing prop
expect(result).toBeDefined();
@@ -39,8 +39,8 @@ describe('objects', () => {
describe('objectWithOnly', () => {
it('should exclusively use the given properties', () => {
const input = {hello: "world", test: true};
const output = {hello: "world"};
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
const result = objectWithOnly(input, <any>props); // any is to test the missing prop
expect(result).toBeDefined();
@@ -50,7 +50,7 @@ describe('objects', () => {
describe('objectShallowClone', () => {
it('should create a new object', () => {
const input = {test: 1};
const input = { test: 1 };
const result = objectShallowClone(input);
expect(result).toBeDefined();
expect(result).not.toBe(input);
@@ -58,7 +58,7 @@ describe('objects', () => {
});
it('should only clone the top level properties', () => {
const input = {a: 1, b: {c: 2}};
const input = { a: 1, b: { c: 2 } };
const result = objectShallowClone(input);
expect(result).toBeDefined();
expect(result).toMatchObject(input);
@@ -66,8 +66,8 @@ describe('objects', () => {
});
it('should support custom clone functions', () => {
const input = {a: 1, b: 2};
const output = {a: 4, b: 8};
const input = { a: 1, b: 2 };
const output = { a: 4, b: 8 };
const result = objectShallowClone(input, (k, v) => {
// XXX: inverted expectation for ease of assertion
expect(Object.keys(input)).toContain(k);
@@ -87,29 +87,29 @@ describe('objects', () => {
});
it('should return true if keys for A > keys for B', () => {
const a = {a: 1, b: 2};
const b = {a: 1};
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', () => {
const a = {a: 1};
const b = {a: 1, b: 2};
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', () => {
const a = {a: 1, b: 2};
const b = {a: 1, b: 2};
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', () => {
const a = {a: {}, b: 2}; // `{}` is shorthand for `new Object()`
const b = {a: {}, b: 2};
const a = { a: {}, b: 2 }; // `{}` is shorthand for `new Object()`
const b = { a: {}, b: 2 };
const result = objectHasDiff(a, b);
expect(result).toBe(true); // even though the keys are the same, the value pointers vary
});
@@ -117,8 +117,8 @@ describe('objects', () => {
describe('objectDiff', () => {
it('should return empty sets for the same object', () => {
const a = {a: 1, b: 2};
const b = {a: 1, b: 2};
const a = { a: 1, b: 2 };
const b = { a: 1, b: 2 };
const result = objectDiff(a, b);
expect(result).toBeDefined();
expect(result.changed).toBeDefined();
@@ -130,7 +130,7 @@ describe('objects', () => {
});
it('should return empty sets for the same object pointer', () => {
const a = {a: 1, b: 2};
const a = { a: 1, b: 2 };
const result = objectDiff(a, a);
expect(result).toBeDefined();
expect(result.changed).toBeDefined();
@@ -142,8 +142,8 @@ describe('objects', () => {
});
it('should indicate when property changes are made', () => {
const a = {a: 1, b: 2};
const b = {a: 11, b: 2};
const a = { a: 1, b: 2 };
const b = { a: 11, b: 2 };
const result = objectDiff(a, b);
expect(result.changed).toBeDefined();
expect(result.added).toBeDefined();
@@ -155,8 +155,8 @@ describe('objects', () => {
});
it('should indicate when properties are added', () => {
const a = {a: 1, b: 2};
const b = {a: 1, b: 2, c: 3};
const a = { a: 1, b: 2 };
const b = { a: 1, b: 2, c: 3 };
const result = objectDiff(a, b);
expect(result.changed).toBeDefined();
expect(result.added).toBeDefined();
@@ -168,8 +168,8 @@ describe('objects', () => {
});
it('should indicate when properties are removed', () => {
const a = {a: 1, b: 2};
const b = {a: 1};
const a = { a: 1, b: 2 };
const b = { a: 1 };
const result = objectDiff(a, b);
expect(result.changed).toBeDefined();
expect(result.added).toBeDefined();
@@ -181,8 +181,8 @@ describe('objects', () => {
});
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 a = { a: 1, b: 2, c: 3 };
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();
@@ -198,23 +198,23 @@ describe('objects', () => {
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 a = { a: 1, b: 2 };
const b = { a: 1, b: 2 };
const result = objectKeyChanges(a, b);
expect(result).toBeDefined();
expect(result).toHaveLength(0);
});
it('should return an empty set if no properties changed for the same pointer', () => {
const a = {a: 1, b: 2};
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', () => {
const a = {a: 1, b: 2, c: 3};
const b: (typeof a | {d: number}) = {a: 1, b: 22, d: 4};
const a = { a: 1, b: 2, c: 3 };
const b: (typeof a | {d: number}) = { a: 1, b: 22, d: 4 };
const result = objectKeyChanges(a, b);
expect(result).toBeDefined();
expect(result).toHaveLength(3);
@@ -245,14 +245,14 @@ describe('objects', () => {
describe('objectFromEntries', () => {
it('should create an object from an array of entries', () => {
const output = {a: 1, b: 2, c: 3};
const output = { a: 1, b: 2, c: 3 };
const result = objectFromEntries(Object.entries(output));
expect(result).toBeDefined();
expect(result).toMatchObject(output);
});
it('should maintain pointers in values', () => {
const output = {a: {}, b: 2, c: 3};
const output = { a: {}, b: 2, c: 3 };
const result = objectFromEntries(Object.entries(output));
expect(result).toBeDefined();
expect(result).toMatchObject(output);

View File

@@ -13,7 +13,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {MatrixClientPeg as peg} from '../../../src/MatrixClientPeg';
import { MatrixClientPeg as peg } from '../../../src/MatrixClientPeg';
import {
makeGroupPermalink,
makeRoomPermalink,
@@ -48,7 +48,7 @@ function mockRoom(roomId, members, serverACL) {
content = serverACL;
break;
case "m.room.power_levels":
content = {users: powerLevelsUsers, users_default: 0};
content = { users: powerLevelsUsers, users_default: 0 };
break;
}
if (content) {

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import {setHasDiff} from "../../src/utils/sets";
import { setHasDiff } from "../../src/utils/sets";
describe('sets', () => {
describe('setHasDiff', () => {

View File

@@ -0,0 +1,291 @@
/*
Copyright 2021 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { sortBy } from "lodash";
import { averageBetweenStrings, DEFAULT_ALPHABET } from "matrix-js-sdk/src/utils";
import { midPointsBetweenStrings, reorderLexicographically } from "../../src/utils/stringOrderField";
const moveLexicographicallyTest = (
orders: Array<string | undefined>,
fromIndex: number,
toIndex: number,
expectedChanges: number,
maxLength?: number,
): void => {
const ops = reorderLexicographically(orders, fromIndex, toIndex, maxLength);
const zipped: Array<[number, string | undefined]> = orders.map((o, i) => [i, o]);
ops.forEach(({ index, order }) => {
zipped[index][1] = order;
});
const newOrders = sortBy(zipped, i => i[1]);
expect(newOrders[toIndex][0]).toBe(fromIndex);
expect(ops).toHaveLength(expectedChanges);
};
describe("stringOrderField", () => {
describe("midPointsBetweenStrings", () => {
it("should work", () => {
expect(averageBetweenStrings("!!", "##")).toBe('""');
const midpoints = ["a", ...midPointsBetweenStrings("a", "e", 3, 1), "e"].sort();
expect(midpoints[0]).toBe("a");
expect(midpoints[4]).toBe("e");
expect(midPointsBetweenStrings(" ", "!'Tu:}", 1, 50)).toStrictEqual([" S:J\\~"]);
});
it("should return empty array when the request is not possible", () => {
expect(midPointsBetweenStrings("a", "e", 0, 1)).toStrictEqual([]);
expect(midPointsBetweenStrings("a", "e", 4, 1)).toStrictEqual([]);
});
});
describe("reorderLexicographically", () => {
it("should work when moving left", () => {
moveLexicographicallyTest(["a", "c", "e", "g", "i"], 2, 1, 1);
});
it("should work when moving right", () => {
moveLexicographicallyTest(["a", "c", "e", "g", "i"], 1, 2, 1);
});
it("should work when all orders are undefined", () => {
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,
);
});
it("should work when moving left and some orders are undefined", () => {
moveLexicographicallyTest(
["a", "c", "e", undefined, undefined, undefined],
5,
2,
1,
);
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,
);
});
it("should work moving to the end when all is undefined", () => {
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,
);
});
it("should work moving right when all is undefined", () => {
moveLexicographicallyTest(
[undefined, undefined, undefined, undefined],
1,
2,
3,
);
});
it("should work moving more right when all is undefined", () => {
moveLexicographicallyTest(
[undefined, undefined, undefined, undefined, undefined, /**/ undefined, undefined],
1,
4,
5,
);
});
it("should work moving left when right is undefined", () => {
moveLexicographicallyTest(
["20", undefined, undefined, undefined, undefined, undefined],
4,
2,
2,
);
});
it("should work moving right when right is undefined", () => {
moveLexicographicallyTest(
["50", undefined, undefined, undefined, undefined, /**/ undefined, undefined],
1,
4,
4,
);
});
it("should work moving left when right is defined", () => {
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,
);
});
it("should work moving left when all is defined", () => {
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,
);
});
it("should work moving left into no left space", () => {
moveLexicographicallyTest(
["11", "12", "13", "14", "19"],
3,
1,
2,
2,
);
moveLexicographicallyTest(
[
DEFAULT_ALPHABET.charAt(0),
// Target
DEFAULT_ALPHABET.charAt(1),
DEFAULT_ALPHABET.charAt(2),
DEFAULT_ALPHABET.charAt(3),
DEFAULT_ALPHABET.charAt(4),
DEFAULT_ALPHABET.charAt(5),
],
5,
1,
5,
1,
);
});
it("should work moving right into no right space", () => {
moveLexicographicallyTest(
["15", "16", "17", "18", "19"],
1,
3,
3,
2,
);
moveLexicographicallyTest(
[
DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 5),
DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 4),
DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 3),
DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 2),
DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 1),
],
1,
3,
3,
1,
);
});
it("should work moving right into no left space", () => {
moveLexicographicallyTest(
["11", "12", "13", "14", "15", "16", undefined],
1,
3,
3,
);
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(
[
DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 5),
DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 4),
DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 3),
DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 2),
DEFAULT_ALPHABET.charAt(DEFAULT_ALPHABET.length - 1),
],
4,
3,
4,
1,
);
});
});
});