mirror of
https://github.com/element-hq/element-web
synced 2024-11-23 17:56:01 +03:00
Merge branch 'develop' into johannes/find-myself
This commit is contained in:
commit
6ee6accfc6
16 changed files with 392 additions and 774 deletions
|
@ -152,7 +152,7 @@
|
|||
"@types/escape-html": "^1.0.1",
|
||||
"@types/file-saver": "^2.0.3",
|
||||
"@types/flux": "^3.1.9",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/fs-extra": "^11.0.0",
|
||||
"@types/geojson": "^7946.0.8",
|
||||
"@types/jest": "^29.2.1",
|
||||
"@types/katex": "^0.14.0",
|
||||
|
|
|
@ -146,7 +146,7 @@ export default class PasswordReset {
|
|||
err.message = _t("Failed to verify email address: make sure you clicked the link in the email");
|
||||
} else if (err.httpStatus === 404) {
|
||||
err.message = _t(
|
||||
"Your email address does not appear to be associated with a Matrix ID on this Homeserver.",
|
||||
"Your email address does not appear to be associated with a Matrix ID on this homeserver.",
|
||||
);
|
||||
} else if (err.httpStatus) {
|
||||
err.message += ` (Status ${err.httpStatus})`;
|
||||
|
|
|
@ -63,7 +63,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
|||
|
||||
inviteOption = (
|
||||
<IconizedContextMenuOption
|
||||
data-test-id="invite-option"
|
||||
data-testid="invite-option"
|
||||
className="mx_SpacePanel_contextMenu_inviteButton"
|
||||
iconClassName="mx_SpacePanel_iconInvite"
|
||||
label={_t("Invite")}
|
||||
|
@ -85,7 +85,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
|||
|
||||
settingsOption = (
|
||||
<IconizedContextMenuOption
|
||||
data-test-id="settings-option"
|
||||
data-testid="settings-option"
|
||||
iconClassName="mx_SpacePanel_iconSettings"
|
||||
label={_t("Settings")}
|
||||
onClick={onSettingsClick}
|
||||
|
@ -102,7 +102,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
|||
|
||||
leaveOption = (
|
||||
<IconizedContextMenuOption
|
||||
data-test-id="leave-option"
|
||||
data-testid="leave-option"
|
||||
iconClassName="mx_SpacePanel_iconLeave"
|
||||
className="mx_IconizedContextMenu_option_red"
|
||||
label={_t("Leave space")}
|
||||
|
@ -172,12 +172,12 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
|||
|
||||
newRoomSection = (
|
||||
<>
|
||||
<div data-test-id="add-to-space-header" className="mx_SpacePanel_contextMenu_separatorLabel">
|
||||
<div data-testid="add-to-space-header" className="mx_SpacePanel_contextMenu_separatorLabel">
|
||||
{_t("Add")}
|
||||
</div>
|
||||
{canAddRooms && (
|
||||
<IconizedContextMenuOption
|
||||
data-test-id="new-room-option"
|
||||
data-testid="new-room-option"
|
||||
iconClassName="mx_SpacePanel_iconPlus"
|
||||
label={_t("Room")}
|
||||
onClick={onNewRoomClick}
|
||||
|
@ -185,7 +185,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
|||
)}
|
||||
{canAddVideoRooms && (
|
||||
<IconizedContextMenuOption
|
||||
data-test-id="new-video-room-option"
|
||||
data-testid="new-video-room-option"
|
||||
iconClassName="mx_SpacePanel_iconPlus"
|
||||
label={_t("Video room")}
|
||||
onClick={onNewVideoRoomClick}
|
||||
|
@ -195,7 +195,7 @@ const SpaceContextMenu: React.FC<IProps> = ({ space, hideHeader, onFinished, ...
|
|||
)}
|
||||
{canAddSubSpaces && (
|
||||
<IconizedContextMenuOption
|
||||
data-test-id="new-subspace-option"
|
||||
data-testid="new-subspace-option"
|
||||
iconClassName="mx_SpacePanel_iconPlus"
|
||||
label={_t("Space")}
|
||||
onClick={onNewSubspaceClick}
|
||||
|
|
|
@ -191,16 +191,19 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
|
|||
public replaceEmoticon(caretPosition: DocumentPosition, regex: RegExp): number {
|
||||
const { model } = this.props;
|
||||
const range = model.startRange(caretPosition);
|
||||
// expand range max 8 characters backwards from caretPosition,
|
||||
// expand range max 9 characters backwards from caretPosition,
|
||||
// as a space to look for an emoticon
|
||||
let n = 8;
|
||||
let n = 9;
|
||||
range.expandBackwardsWhile((index, offset) => {
|
||||
const part = model.parts[index];
|
||||
n -= 1;
|
||||
return n >= 0 && [Type.Plain, Type.PillCandidate, Type.Newline].includes(part.type);
|
||||
});
|
||||
const emoticonMatch = regex.exec(range.text);
|
||||
if (emoticonMatch) {
|
||||
// ignore matches at start of proper substrings
|
||||
// so xd will not match if the string was "mixd 123456"
|
||||
// and we are lookinh at xd 123456 part of the string
|
||||
if (emoticonMatch && (n >= 0 || emoticonMatch.index !== 0)) {
|
||||
const query = emoticonMatch[1].replace("-", "");
|
||||
// try both exact match and lower-case, this means that xd won't match xD but :P will match :p
|
||||
const data = EMOTICON_TO_EMOJI.get(query) || EMOTICON_TO_EMOJI.get(query.toLowerCase());
|
||||
|
|
|
@ -73,7 +73,7 @@ const securityCardContent: Record<
|
|||
title: _t("Unverified session"),
|
||||
description: (
|
||||
<>
|
||||
<p>{_t(`This session doesn't support encryption, so it can't be verified.`)}</p>
|
||||
<p>{_t(`This session doesn't support encryption and thus can't be verified.`)}</p>
|
||||
<p>
|
||||
{_t(
|
||||
`You won't be able to participate in rooms where encryption is enabled when using this session.`,
|
||||
|
|
|
@ -117,7 +117,7 @@
|
|||
"%(brand)s was not given permission to send notifications - please try again": "%(brand)s was not given permission to send notifications - please try again",
|
||||
"Unable to enable Notifications": "Unable to enable Notifications",
|
||||
"This email address was not found": "This email address was not found",
|
||||
"Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Your email address does not appear to be associated with a Matrix ID on this Homeserver.",
|
||||
"Your email address does not appear to be associated with a Matrix ID on this homeserver.": "Your email address does not appear to be associated with a Matrix ID on this homeserver.",
|
||||
"United Kingdom": "United Kingdom",
|
||||
"United States": "United States",
|
||||
"Afghanistan": "Afghanistan",
|
||||
|
@ -1826,7 +1826,7 @@
|
|||
"Unverified sessions are sessions that have logged in with your credentials but have not been cross-verified.": "Unverified sessions are sessions that have logged in with your credentials but have not been cross-verified.",
|
||||
"You should make especially certain that you recognise these sessions as they could represent an unauthorised use of your account.": "You should make especially certain that you recognise these sessions as they could represent an unauthorised use of your account.",
|
||||
"Unverified session": "Unverified session",
|
||||
"This session doesn't support encryption, so it can't be verified.": "This session doesn't support encryption, so it can't be verified.",
|
||||
"This session doesn't support encryption and thus can't be verified.": "This session doesn't support encryption and thus can't be verified.",
|
||||
"You won't be able to participate in rooms where encryption is enabled when using this session.": "You won't be able to participate in rooms where encryption is enabled when using this session.",
|
||||
"For best security and privacy, it is recommended to use Matrix clients that support encryption.": "For best security and privacy, it is recommended to use Matrix clients that support encryption.",
|
||||
"Inactive sessions": "Inactive sessions",
|
||||
|
@ -1842,7 +1842,6 @@
|
|||
"Your current session is ready for secure messaging.": "Your current session is ready for secure messaging.",
|
||||
"This session is ready for secure messaging.": "This session is ready for secure messaging.",
|
||||
"Verified session": "Verified session",
|
||||
"This session doesn't support encryption and thus can't be verified.": "This session doesn't support encryption and thus can't be verified.",
|
||||
"Verify your current session for enhanced secure messaging.": "Verify your current session for enhanced secure messaging.",
|
||||
"Verify or sign out from this session for best security and reliability.": "Verify or sign out from this session for best security and reliability.",
|
||||
"Verify session": "Verify session",
|
||||
|
|
|
@ -62,12 +62,12 @@ interface IStickyRoom {
|
|||
*/
|
||||
export class Algorithm extends EventEmitter {
|
||||
private _cachedRooms: ITagMap = {};
|
||||
private _cachedStickyRooms: ITagMap = {}; // a clone of the _cachedRooms, with the sticky room
|
||||
private _stickyRoom: IStickyRoom = null;
|
||||
private _lastStickyRoom: IStickyRoom = null; // only not-null when changing the sticky room
|
||||
private sortAlgorithms: ITagSortingMap;
|
||||
private listAlgorithms: IListOrderingMap;
|
||||
private algorithms: IOrderingAlgorithmMap;
|
||||
private _cachedStickyRooms: ITagMap | null = {}; // a clone of the _cachedRooms, with the sticky room
|
||||
private _stickyRoom: IStickyRoom | null = null;
|
||||
private _lastStickyRoom: IStickyRoom | null = null; // only not-null when changing the sticky room
|
||||
private sortAlgorithms: ITagSortingMap | null = null;
|
||||
private listAlgorithms: IListOrderingMap | null = null;
|
||||
private algorithms: IOrderingAlgorithmMap | null = null;
|
||||
private rooms: Room[] = [];
|
||||
private roomIdsToTags: {
|
||||
[roomId: string]: TagID[];
|
||||
|
@ -86,7 +86,7 @@ export class Algorithm extends EventEmitter {
|
|||
CallStore.instance.off(CallStoreEvent.ActiveCalls, this.onActiveCalls);
|
||||
}
|
||||
|
||||
public get stickyRoom(): Room {
|
||||
public get stickyRoom(): Room | null {
|
||||
return this._stickyRoom ? this._stickyRoom.room : null;
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ export class Algorithm extends EventEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
public getTagSorting(tagId: TagID): SortAlgorithm {
|
||||
public getTagSorting(tagId: TagID): SortAlgorithm | null {
|
||||
if (!this.sortAlgorithms) return null;
|
||||
return this.sortAlgorithms[tagId];
|
||||
}
|
||||
|
@ -132,6 +132,8 @@ export class Algorithm extends EventEmitter {
|
|||
public setTagSorting(tagId: TagID, sort: SortAlgorithm): void {
|
||||
if (!tagId) throw new Error("Tag ID must be defined");
|
||||
if (!sort) throw new Error("Algorithm must be defined");
|
||||
if (!this.sortAlgorithms) throw new Error("this.sortAlgorithms must be defined before calling setTagSorting");
|
||||
if (!this.algorithms) throw new Error("this.algorithms must be defined before calling setTagSorting");
|
||||
this.sortAlgorithms[tagId] = sort;
|
||||
|
||||
const algorithm: OrderingAlgorithm = this.algorithms[tagId];
|
||||
|
@ -141,7 +143,7 @@ export class Algorithm extends EventEmitter {
|
|||
this.recalculateActiveCallRooms(tagId);
|
||||
}
|
||||
|
||||
public getListOrdering(tagId: TagID): ListAlgorithm {
|
||||
public getListOrdering(tagId: TagID): ListAlgorithm | null {
|
||||
if (!this.listAlgorithms) return null;
|
||||
return this.listAlgorithms[tagId];
|
||||
}
|
||||
|
@ -149,6 +151,9 @@ export class Algorithm extends EventEmitter {
|
|||
public setListOrdering(tagId: TagID, order: ListAlgorithm): void {
|
||||
if (!tagId) throw new Error("Tag ID must be defined");
|
||||
if (!order) throw new Error("Algorithm must be defined");
|
||||
if (!this.sortAlgorithms) throw new Error("this.sortAlgorithms must be defined before calling setListOrdering");
|
||||
if (!this.listAlgorithms) throw new Error("this.listAlgorithms must be defined before calling setListOrdering");
|
||||
if (!this.algorithms) throw new Error("this.algorithms must be defined before calling setListOrdering");
|
||||
this.listAlgorithms[tagId] = order;
|
||||
|
||||
const algorithm = getListAlgorithmInstance(order, tagId, this.sortAlgorithms[tagId]);
|
||||
|
@ -160,12 +165,12 @@ export class Algorithm extends EventEmitter {
|
|||
this.recalculateActiveCallRooms(tagId);
|
||||
}
|
||||
|
||||
private updateStickyRoom(val: Room): void {
|
||||
private updateStickyRoom(val: Room | null): void {
|
||||
this.doUpdateStickyRoom(val);
|
||||
this._lastStickyRoom = null; // clear to indicate we're done changing
|
||||
}
|
||||
|
||||
private doUpdateStickyRoom(val: Room): void {
|
||||
private doUpdateStickyRoom(val: Room | null): void {
|
||||
if (val?.isSpaceRoom() && val.getMyMembership() !== "invite") {
|
||||
// no-op sticky rooms for spaces - they're effectively virtual rooms
|
||||
val = null;
|
||||
|
@ -237,6 +242,10 @@ export class Algorithm extends EventEmitter {
|
|||
// Lie to the algorithm and remove the room from it's field of view
|
||||
this.handleRoomUpdate(val, RoomUpdateCause.RoomRemoved);
|
||||
|
||||
// handleRoomUpdate may have modified this._stickyRoom. Convince the
|
||||
// compiler of this fact.
|
||||
this._stickyRoom = this.stickyRoomMightBeModified();
|
||||
|
||||
// Check for tag & position changes while we're here. We also check the room to ensure
|
||||
// it is still the same room.
|
||||
if (this._stickyRoom) {
|
||||
|
@ -284,6 +293,13 @@ export class Algorithm extends EventEmitter {
|
|||
this.emit(LIST_UPDATED_EVENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hack to prevent Typescript claiming this._stickyRoom is always null.
|
||||
*/
|
||||
private stickyRoomMightBeModified(): IStickyRoom | null {
|
||||
return this._stickyRoom;
|
||||
}
|
||||
|
||||
private onActiveCalls = (): void => {
|
||||
// In case we're unsticking a room, sort it back into natural order
|
||||
this.recalculateStickyRoom();
|
||||
|
@ -310,7 +326,7 @@ export class Algorithm extends EventEmitter {
|
|||
* the call.
|
||||
* @param updatedTag The tag that was updated, if possible.
|
||||
*/
|
||||
protected recalculateStickyRoom(updatedTag: TagID = null): void {
|
||||
protected recalculateStickyRoom(updatedTag: TagID | null = null): void {
|
||||
// 🐉 Here be dragons.
|
||||
// This function does far too much for what it should, and is called by many places.
|
||||
// Not only is this responsible for ensuring the sticky room is held in place at all
|
||||
|
@ -336,14 +352,16 @@ export class Algorithm extends EventEmitter {
|
|||
if (updatedTag) {
|
||||
// Update the tag indicated by the caller, if possible. This is mostly to ensure
|
||||
// our cache is up to date.
|
||||
if (this._cachedStickyRooms) {
|
||||
this._cachedStickyRooms[updatedTag] = [...this.cachedRooms[updatedTag]]; // shallow clone
|
||||
}
|
||||
}
|
||||
|
||||
// Now try to insert the sticky room, if we need to.
|
||||
// We need to if there's no updated tag (we regenned the whole cache) or if the tag
|
||||
// we might have updated from the cache is also our sticky room.
|
||||
const sticky = this._stickyRoom;
|
||||
if (!updatedTag || updatedTag === sticky.tag) {
|
||||
if (sticky && (!updatedTag || updatedTag === sticky.tag) && this._cachedStickyRooms) {
|
||||
this._cachedStickyRooms[sticky.tag].splice(sticky.position, 0, sticky.room);
|
||||
}
|
||||
|
||||
|
@ -362,7 +380,7 @@ export class Algorithm extends EventEmitter {
|
|||
*
|
||||
* @param updatedTag The tag that was updated, if possible.
|
||||
*/
|
||||
protected recalculateActiveCallRooms(updatedTag: TagID = null): void {
|
||||
protected recalculateActiveCallRooms(updatedTag: TagID | null = null): void {
|
||||
if (!updatedTag) {
|
||||
// Assume all tags need updating
|
||||
// We're not modifying the map here, so can safely rely on the cached values
|
||||
|
@ -379,7 +397,7 @@ export class Algorithm extends EventEmitter {
|
|||
if (CallStore.instance.activeCalls.size) {
|
||||
// We operate on the sticky rooms map
|
||||
if (!this._cachedStickyRooms) this.initCachedStickyRooms();
|
||||
const rooms = this._cachedStickyRooms[updatedTag];
|
||||
const rooms = this._cachedStickyRooms![updatedTag];
|
||||
|
||||
const activeRoomIds = new Set([...CallStore.instance.activeCalls].map((call) => call.roomId));
|
||||
const activeRooms: Room[] = [];
|
||||
|
@ -390,7 +408,7 @@ export class Algorithm extends EventEmitter {
|
|||
}
|
||||
|
||||
// Stick rooms with active calls to the top
|
||||
this._cachedStickyRooms[updatedTag] = [...activeRooms, ...inactiveRooms];
|
||||
this._cachedStickyRooms![updatedTag] = [...activeRooms, ...inactiveRooms];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -638,7 +656,7 @@ export class Algorithm extends EventEmitter {
|
|||
}
|
||||
|
||||
// Like above, update the reference to the sticky room if we need to
|
||||
if (hasTags && isSticky) {
|
||||
if (hasTags && isSticky && this._stickyRoom) {
|
||||
// Go directly in and set the sticky room's new reference, being careful not
|
||||
// to trigger a sticky room update ourselves.
|
||||
this._stickyRoom.room = room;
|
||||
|
|
|
@ -113,10 +113,10 @@ describe("RoomNotifs test", () => {
|
|||
event: true,
|
||||
type: "m.room.create",
|
||||
room: ROOM_ID,
|
||||
user: client.getUserId()!,
|
||||
user: "@zoe:localhost",
|
||||
content: {
|
||||
...(predecessorId ? { predecessor: { room_id: predecessorId, event_id: "$someevent" } } : {}),
|
||||
creator: client.getUserId(),
|
||||
creator: "@zoe:localhost",
|
||||
room_version: "5",
|
||||
},
|
||||
ts: Date.now(),
|
||||
|
@ -128,7 +128,7 @@ describe("RoomNotifs test", () => {
|
|||
event: true,
|
||||
type: EventType.RoomPredecessor,
|
||||
room: ROOM_ID,
|
||||
user: client.getUserId()!,
|
||||
user: "@zoe:localhost",
|
||||
skey: "",
|
||||
content: {
|
||||
predecessor_room_id: predecessorId,
|
||||
|
|
|
@ -15,16 +15,14 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from "react";
|
||||
// eslint-disable-next-line deprecate/import
|
||||
import { mount } from "enzyme";
|
||||
import { Room } from "matrix-js-sdk/src/matrix";
|
||||
import { mocked } from "jest-mock";
|
||||
import { act } from "react-dom/test-utils";
|
||||
import { MatrixClient, Room } from "matrix-js-sdk/src/matrix";
|
||||
import { Mocked, mocked } from "jest-mock";
|
||||
import "focus-visible"; // to fix context menus
|
||||
import { prettyDOM, render, RenderResult, screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
|
||||
import SpaceContextMenu from "../../../../src/components/views/context_menus/SpaceContextMenu";
|
||||
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
||||
import { findByTestId } from "../../../test-utils";
|
||||
import {
|
||||
shouldShowSpaceSettings,
|
||||
showCreateNewRoom,
|
||||
|
@ -55,9 +53,11 @@ jest.mock("../../../../src/utils/leave-behaviour", () => ({
|
|||
|
||||
describe("<SpaceContextMenu />", () => {
|
||||
const userId = "@test:server";
|
||||
|
||||
const mockClient = {
|
||||
getUserId: jest.fn().mockReturnValue(userId),
|
||||
};
|
||||
} as unknown as Mocked<MatrixClient>;
|
||||
|
||||
const makeMockSpace = (props = {}) =>
|
||||
({
|
||||
name: "test space",
|
||||
|
@ -70,17 +70,18 @@ describe("<SpaceContextMenu />", () => {
|
|||
getMyMembership: jest.fn(),
|
||||
...props,
|
||||
} as unknown as Room);
|
||||
|
||||
const defaultProps = {
|
||||
space: makeMockSpace(),
|
||||
onFinished: jest.fn(),
|
||||
};
|
||||
const getComponent = (props = {}) =>
|
||||
mount(<SpaceContextMenu {...defaultProps} {...props} />, {
|
||||
wrappingComponent: MatrixClientContext.Provider,
|
||||
wrappingComponentProps: {
|
||||
value: mockClient,
|
||||
},
|
||||
});
|
||||
|
||||
const renderComponent = (props = {}): RenderResult =>
|
||||
render(
|
||||
<MatrixClientContext.Provider value={mockClient}>
|
||||
<SpaceContextMenu {...defaultProps} {...props} />
|
||||
</MatrixClientContext.Provider>,
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
|
@ -88,134 +89,135 @@ describe("<SpaceContextMenu />", () => {
|
|||
});
|
||||
|
||||
it("renders menu correctly", () => {
|
||||
const component = getComponent();
|
||||
expect(component).toMatchSnapshot();
|
||||
const { baseElement } = renderComponent();
|
||||
expect(prettyDOM(baseElement)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders invite option when space is public", () => {
|
||||
const space = makeMockSpace({
|
||||
getJoinRule: jest.fn().mockReturnValue("public"),
|
||||
});
|
||||
const component = getComponent({ space });
|
||||
expect(findByTestId(component, "invite-option").length).toBeTruthy();
|
||||
renderComponent({ space });
|
||||
expect(screen.getByTestId("invite-option")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders invite option when user is has invite rights for space", () => {
|
||||
const space = makeMockSpace({
|
||||
canInvite: jest.fn().mockReturnValue(true),
|
||||
});
|
||||
const component = getComponent({ space });
|
||||
renderComponent({ space });
|
||||
expect(space.canInvite).toHaveBeenCalledWith(userId);
|
||||
expect(findByTestId(component, "invite-option").length).toBeTruthy();
|
||||
expect(screen.getByTestId("invite-option")).toBeInTheDocument();
|
||||
});
|
||||
it("opens invite dialog when invite option is clicked", () => {
|
||||
|
||||
it("opens invite dialog when invite option is clicked", async () => {
|
||||
const space = makeMockSpace({
|
||||
getJoinRule: jest.fn().mockReturnValue("public"),
|
||||
});
|
||||
const onFinished = jest.fn();
|
||||
const component = getComponent({ space, onFinished });
|
||||
renderComponent({ space, onFinished });
|
||||
|
||||
act(() => {
|
||||
findByTestId(component, "invite-option").at(0).simulate("click");
|
||||
});
|
||||
await userEvent.click(screen.getByTestId("invite-option"));
|
||||
|
||||
expect(showSpaceInvite).toHaveBeenCalledWith(space);
|
||||
expect(onFinished).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("renders space settings option when user has rights", () => {
|
||||
mocked(shouldShowSpaceSettings).mockReturnValue(true);
|
||||
const component = getComponent();
|
||||
renderComponent();
|
||||
expect(shouldShowSpaceSettings).toHaveBeenCalledWith(defaultProps.space);
|
||||
expect(findByTestId(component, "settings-option").length).toBeTruthy();
|
||||
expect(screen.getByTestId("settings-option")).toBeInTheDocument();
|
||||
});
|
||||
it("opens space settings when space settings option is clicked", () => {
|
||||
|
||||
it("opens space settings when space settings option is clicked", async () => {
|
||||
mocked(shouldShowSpaceSettings).mockReturnValue(true);
|
||||
const onFinished = jest.fn();
|
||||
const component = getComponent({ onFinished });
|
||||
renderComponent({ onFinished });
|
||||
|
||||
act(() => {
|
||||
findByTestId(component, "settings-option").at(0).simulate("click");
|
||||
});
|
||||
await userEvent.click(screen.getByTestId("settings-option"));
|
||||
|
||||
expect(showSpaceSettings).toHaveBeenCalledWith(defaultProps.space);
|
||||
expect(onFinished).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("renders leave option when user does not have rights to see space settings", () => {
|
||||
const component = getComponent();
|
||||
expect(findByTestId(component, "leave-option").length).toBeTruthy();
|
||||
renderComponent();
|
||||
expect(screen.getByTestId("leave-option")).toBeInTheDocument();
|
||||
});
|
||||
it("leaves space when leave option is clicked", () => {
|
||||
|
||||
it("leaves space when leave option is clicked", async () => {
|
||||
const onFinished = jest.fn();
|
||||
const component = getComponent({ onFinished });
|
||||
act(() => {
|
||||
findByTestId(component, "leave-option").at(0).simulate("click");
|
||||
});
|
||||
renderComponent({ onFinished });
|
||||
await userEvent.click(screen.getByTestId("leave-option"));
|
||||
expect(leaveSpace).toHaveBeenCalledWith(defaultProps.space);
|
||||
expect(onFinished).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("add children section", () => {
|
||||
const space = makeMockSpace();
|
||||
|
||||
beforeEach(() => {
|
||||
// set space to allow adding children to space
|
||||
mocked(space.currentState.maySendStateEvent).mockReturnValue(true);
|
||||
mocked(shouldShowComponent).mockReturnValue(true);
|
||||
});
|
||||
|
||||
it("does not render section when user does not have permission to add children", () => {
|
||||
mocked(space.currentState.maySendStateEvent).mockReturnValue(false);
|
||||
const component = getComponent({ space });
|
||||
renderComponent({ space });
|
||||
|
||||
expect(findByTestId(component, "add-to-space-header").length).toBeFalsy();
|
||||
expect(findByTestId(component, "new-room-option").length).toBeFalsy();
|
||||
expect(findByTestId(component, "new-subspace-option").length).toBeFalsy();
|
||||
expect(screen.queryByTestId("add-to-space-header")).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId("new-room-option")).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId("new-subspace-option")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not render section when UIComponent customisations disable room and space creation", () => {
|
||||
mocked(shouldShowComponent).mockReturnValue(false);
|
||||
const component = getComponent({ space });
|
||||
renderComponent({ space });
|
||||
|
||||
expect(shouldShowComponent).toHaveBeenCalledWith(UIComponent.CreateRooms);
|
||||
expect(shouldShowComponent).toHaveBeenCalledWith(UIComponent.CreateSpaces);
|
||||
|
||||
expect(findByTestId(component, "add-to-space-header").length).toBeFalsy();
|
||||
expect(findByTestId(component, "new-room-option").length).toBeFalsy();
|
||||
expect(findByTestId(component, "new-subspace-option").length).toBeFalsy();
|
||||
expect(screen.queryByTestId("add-to-space-header")).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId("new-room-option")).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId("new-subspace-option")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders section with add room button when UIComponent customisation allows CreateRoom", () => {
|
||||
// only allow CreateRoom
|
||||
mocked(shouldShowComponent).mockImplementation((feature) => feature === UIComponent.CreateRooms);
|
||||
const component = getComponent({ space });
|
||||
renderComponent({ space });
|
||||
|
||||
expect(findByTestId(component, "add-to-space-header").length).toBeTruthy();
|
||||
expect(findByTestId(component, "new-room-option").length).toBeTruthy();
|
||||
expect(findByTestId(component, "new-subspace-option").length).toBeFalsy();
|
||||
expect(screen.getByTestId("add-to-space-header")).toBeInTheDocument();
|
||||
expect(screen.getByTestId("new-room-option")).toBeInTheDocument();
|
||||
expect(screen.queryByTestId("new-subspace-option")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders section with add space button when UIComponent customisation allows CreateSpace", () => {
|
||||
// only allow CreateSpaces
|
||||
mocked(shouldShowComponent).mockImplementation((feature) => feature === UIComponent.CreateSpaces);
|
||||
const component = getComponent({ space });
|
||||
renderComponent({ space });
|
||||
|
||||
expect(findByTestId(component, "add-to-space-header").length).toBeTruthy();
|
||||
expect(findByTestId(component, "new-room-option").length).toBeFalsy();
|
||||
expect(findByTestId(component, "new-subspace-option").length).toBeTruthy();
|
||||
expect(screen.getByTestId("add-to-space-header")).toBeInTheDocument();
|
||||
expect(screen.queryByTestId("new-room-option")).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId("new-subspace-option")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("opens create room dialog on add room button click", () => {
|
||||
it("opens create room dialog on add room button click", async () => {
|
||||
const onFinished = jest.fn();
|
||||
const component = getComponent({ space, onFinished });
|
||||
renderComponent({ space, onFinished });
|
||||
|
||||
act(() => {
|
||||
findByTestId(component, "new-room-option").at(0).simulate("click");
|
||||
});
|
||||
await userEvent.click(screen.getByTestId("new-room-option"));
|
||||
expect(showCreateNewRoom).toHaveBeenCalledWith(space);
|
||||
expect(onFinished).toHaveBeenCalled();
|
||||
});
|
||||
it("opens create space dialog on add space button click", () => {
|
||||
const onFinished = jest.fn();
|
||||
const component = getComponent({ space, onFinished });
|
||||
|
||||
act(() => {
|
||||
findByTestId(component, "new-subspace-option").at(0).simulate("click");
|
||||
});
|
||||
it("opens create space dialog on add space button click", async () => {
|
||||
const onFinished = jest.fn();
|
||||
renderComponent({ space, onFinished });
|
||||
|
||||
await userEvent.click(screen.getByTestId("new-subspace-option"));
|
||||
expect(showCreateNewSubspace).toHaveBeenCalledWith(space);
|
||||
expect(onFinished).toHaveBeenCalled();
|
||||
});
|
||||
|
|
|
@ -1,500 +1,98 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<SpaceContextMenu /> renders menu correctly 1`] = `
|
||||
<SpaceContextMenu
|
||||
onFinished={[MockFunction]}
|
||||
space={
|
||||
{
|
||||
"canInvite": [MockFunction] {
|
||||
"calls": [
|
||||
[
|
||||
"@test:server",
|
||||
],
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
"client": {
|
||||
"getUserId": [MockFunction] {
|
||||
"calls": [
|
||||
[],
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"type": "return",
|
||||
"value": "@test:server",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"currentState": {
|
||||
"maySendStateEvent": [MockFunction] {
|
||||
"calls": [
|
||||
[
|
||||
"m.space.child",
|
||||
"@test:server",
|
||||
],
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
"getJoinRule": [MockFunction] {
|
||||
"calls": [
|
||||
[],
|
||||
],
|
||||
"results": [
|
||||
{
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
},
|
||||
"getMyMembership": [MockFunction],
|
||||
"name": "test space",
|
||||
}
|
||||
}
|
||||
>
|
||||
<IconizedContextMenu
|
||||
className="mx_SpacePanel_contextMenu"
|
||||
compact={true}
|
||||
onFinished={[MockFunction]}
|
||||
>
|
||||
<ContextMenu
|
||||
chevronFace="none"
|
||||
hasBackground={true}
|
||||
managed={true}
|
||||
onFinished={[MockFunction]}
|
||||
>
|
||||
<Portal
|
||||
containerInfo={
|
||||
<div
|
||||
id="mx_ContextualMenu_Container"
|
||||
>
|
||||
<div
|
||||
class="mx_ContextualMenu_wrapper"
|
||||
>
|
||||
<div
|
||||
class="mx_ContextualMenu_background"
|
||||
/>
|
||||
<div
|
||||
class="mx_ContextualMenu"
|
||||
role="menu"
|
||||
>
|
||||
<div
|
||||
class="mx_IconizedContextMenu mx_SpacePanel_contextMenu mx_IconizedContextMenu_compact"
|
||||
>
|
||||
<div
|
||||
class="mx_SpacePanel_contextMenu_header"
|
||||
>
|
||||
test space
|
||||
</div>
|
||||
<div
|
||||
class="mx_IconizedContextMenu_optionList"
|
||||
>
|
||||
<div
|
||||
aria-label="Space home"
|
||||
class="mx_AccessibleButton mx_IconizedContextMenu_item focus-visible"
|
||||
data-focus-visible-added=""
|
||||
role="menuitem"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_icon mx_SpacePanel_iconHome"
|
||||
/>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_label"
|
||||
>
|
||||
Space home
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Explore rooms"
|
||||
class="mx_AccessibleButton mx_IconizedContextMenu_item"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_icon mx_SpacePanel_iconExplore"
|
||||
/>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_label"
|
||||
>
|
||||
Explore rooms
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Preferences"
|
||||
class="mx_AccessibleButton mx_IconizedContextMenu_item"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_icon mx_SpacePanel_iconPreferences"
|
||||
/>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_label"
|
||||
>
|
||||
Preferences
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Leave space"
|
||||
class="mx_AccessibleButton mx_IconizedContextMenu_option_red mx_IconizedContextMenu_item"
|
||||
data-test-id="leave-option"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_icon mx_SpacePanel_iconLeave"
|
||||
/>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_label"
|
||||
>
|
||||
Leave space
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<RovingTabIndexProvider
|
||||
handleHomeEnd={true}
|
||||
handleUpDown={true}
|
||||
onKeyDown={[Function]}
|
||||
>
|
||||
<div
|
||||
className="mx_ContextualMenu_wrapper"
|
||||
onClick={[Function]}
|
||||
onContextMenu={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
style={
|
||||
{
|
||||
"bottom": undefined,
|
||||
"right": undefined,
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="mx_ContextualMenu_background"
|
||||
onClick={[Function]}
|
||||
onContextMenu={[Function]}
|
||||
style={{}}
|
||||
/>
|
||||
<div
|
||||
className="mx_ContextualMenu"
|
||||
role="menu"
|
||||
style={{}}
|
||||
>
|
||||
<div
|
||||
className="mx_IconizedContextMenu mx_SpacePanel_contextMenu mx_IconizedContextMenu_compact"
|
||||
>
|
||||
<div
|
||||
className="mx_SpacePanel_contextMenu_header"
|
||||
>
|
||||
test space
|
||||
</div>
|
||||
<IconizedContextMenuOptionList
|
||||
first={true}
|
||||
>
|
||||
<div
|
||||
className="mx_IconizedContextMenu_optionList"
|
||||
>
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_SpacePanel_iconHome"
|
||||
label="Space home"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<MenuItem
|
||||
className="mx_IconizedContextMenu_item"
|
||||
label="Space home"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<RovingAccessibleButton
|
||||
aria-label="Space home"
|
||||
className="mx_IconizedContextMenu_item"
|
||||
onClick={[Function]}
|
||||
role="menuitem"
|
||||
>
|
||||
<AccessibleButton
|
||||
aria-label="Space home"
|
||||
className="mx_IconizedContextMenu_item"
|
||||
element="div"
|
||||
inputRef={
|
||||
{
|
||||
"current": <div
|
||||
aria-label="Space home"
|
||||
class="mx_AccessibleButton mx_IconizedContextMenu_item focus-visible"
|
||||
data-focus-visible-added=""
|
||||
role="menuitem"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_icon mx_SpacePanel_iconHome"
|
||||
/>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_label"
|
||||
>
|
||||
Space home
|
||||
</span>
|
||||
</div>,
|
||||
}
|
||||
}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
role="menuitem"
|
||||
tabIndex={0}
|
||||
>
|
||||
<div
|
||||
aria-label="Space home"
|
||||
className="mx_AccessibleButton mx_IconizedContextMenu_item"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
role="menuitem"
|
||||
tabIndex={0}
|
||||
>
|
||||
<span
|
||||
className="mx_IconizedContextMenu_icon mx_SpacePanel_iconHome"
|
||||
/>
|
||||
<span
|
||||
className="mx_IconizedContextMenu_label"
|
||||
>
|
||||
Space home
|
||||
</span>
|
||||
</div>
|
||||
</AccessibleButton>
|
||||
</RovingAccessibleButton>
|
||||
</MenuItem>
|
||||
</IconizedContextMenuOption>
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_SpacePanel_iconExplore"
|
||||
label="Explore rooms"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<MenuItem
|
||||
className="mx_IconizedContextMenu_item"
|
||||
label="Explore rooms"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<RovingAccessibleButton
|
||||
aria-label="Explore rooms"
|
||||
className="mx_IconizedContextMenu_item"
|
||||
onClick={[Function]}
|
||||
role="menuitem"
|
||||
>
|
||||
<AccessibleButton
|
||||
aria-label="Explore rooms"
|
||||
className="mx_IconizedContextMenu_item"
|
||||
element="div"
|
||||
inputRef={
|
||||
{
|
||||
"current": <div
|
||||
aria-label="Explore rooms"
|
||||
class="mx_AccessibleButton mx_IconizedContextMenu_item"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_icon mx_SpacePanel_iconExplore"
|
||||
/>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_label"
|
||||
>
|
||||
Explore rooms
|
||||
</span>
|
||||
</div>,
|
||||
}
|
||||
}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
role="menuitem"
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div
|
||||
aria-label="Explore rooms"
|
||||
className="mx_AccessibleButton mx_IconizedContextMenu_item"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
role="menuitem"
|
||||
tabIndex={-1}
|
||||
>
|
||||
<span
|
||||
className="mx_IconizedContextMenu_icon mx_SpacePanel_iconExplore"
|
||||
/>
|
||||
<span
|
||||
className="mx_IconizedContextMenu_label"
|
||||
>
|
||||
Explore rooms
|
||||
</span>
|
||||
</div>
|
||||
</AccessibleButton>
|
||||
</RovingAccessibleButton>
|
||||
</MenuItem>
|
||||
</IconizedContextMenuOption>
|
||||
<IconizedContextMenuOption
|
||||
iconClassName="mx_SpacePanel_iconPreferences"
|
||||
label="Preferences"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<MenuItem
|
||||
className="mx_IconizedContextMenu_item"
|
||||
label="Preferences"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<RovingAccessibleButton
|
||||
aria-label="Preferences"
|
||||
className="mx_IconizedContextMenu_item"
|
||||
onClick={[Function]}
|
||||
role="menuitem"
|
||||
>
|
||||
<AccessibleButton
|
||||
aria-label="Preferences"
|
||||
className="mx_IconizedContextMenu_item"
|
||||
element="div"
|
||||
inputRef={
|
||||
{
|
||||
"current": <div
|
||||
aria-label="Preferences"
|
||||
class="mx_AccessibleButton mx_IconizedContextMenu_item"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_icon mx_SpacePanel_iconPreferences"
|
||||
/>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_label"
|
||||
>
|
||||
Preferences
|
||||
</span>
|
||||
</div>,
|
||||
}
|
||||
}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
role="menuitem"
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div
|
||||
aria-label="Preferences"
|
||||
className="mx_AccessibleButton mx_IconizedContextMenu_item"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
role="menuitem"
|
||||
tabIndex={-1}
|
||||
>
|
||||
<span
|
||||
className="mx_IconizedContextMenu_icon mx_SpacePanel_iconPreferences"
|
||||
/>
|
||||
<span
|
||||
className="mx_IconizedContextMenu_label"
|
||||
>
|
||||
Preferences
|
||||
</span>
|
||||
</div>
|
||||
</AccessibleButton>
|
||||
</RovingAccessibleButton>
|
||||
</MenuItem>
|
||||
</IconizedContextMenuOption>
|
||||
<IconizedContextMenuOption
|
||||
className="mx_IconizedContextMenu_option_red"
|
||||
data-test-id="leave-option"
|
||||
iconClassName="mx_SpacePanel_iconLeave"
|
||||
label="Leave space"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<MenuItem
|
||||
className="mx_IconizedContextMenu_option_red mx_IconizedContextMenu_item"
|
||||
data-test-id="leave-option"
|
||||
label="Leave space"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<RovingAccessibleButton
|
||||
aria-label="Leave space"
|
||||
className="mx_IconizedContextMenu_option_red mx_IconizedContextMenu_item"
|
||||
data-test-id="leave-option"
|
||||
onClick={[Function]}
|
||||
role="menuitem"
|
||||
>
|
||||
<AccessibleButton
|
||||
aria-label="Leave space"
|
||||
className="mx_IconizedContextMenu_option_red mx_IconizedContextMenu_item"
|
||||
data-test-id="leave-option"
|
||||
element="div"
|
||||
inputRef={
|
||||
{
|
||||
"current": <div
|
||||
aria-label="Leave space"
|
||||
class="mx_AccessibleButton mx_IconizedContextMenu_option_red mx_IconizedContextMenu_item"
|
||||
data-test-id="leave-option"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_icon mx_SpacePanel_iconLeave"
|
||||
/>
|
||||
<span
|
||||
class="mx_IconizedContextMenu_label"
|
||||
>
|
||||
Leave space
|
||||
</span>
|
||||
</div>,
|
||||
}
|
||||
}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
role="menuitem"
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div
|
||||
aria-label="Leave space"
|
||||
className="mx_AccessibleButton mx_IconizedContextMenu_option_red mx_IconizedContextMenu_item"
|
||||
data-test-id="leave-option"
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
role="menuitem"
|
||||
tabIndex={-1}
|
||||
>
|
||||
<span
|
||||
className="mx_IconizedContextMenu_icon mx_SpacePanel_iconLeave"
|
||||
/>
|
||||
<span
|
||||
className="mx_IconizedContextMenu_label"
|
||||
>
|
||||
Leave space
|
||||
</span>
|
||||
</div>
|
||||
</AccessibleButton>
|
||||
</RovingAccessibleButton>
|
||||
</MenuItem>
|
||||
</IconizedContextMenuOption>
|
||||
</div>
|
||||
</IconizedContextMenuOptionList>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</RovingTabIndexProvider>
|
||||
</Portal>
|
||||
</ContextMenu>
|
||||
</IconizedContextMenu>
|
||||
</SpaceContextMenu>
|
||||
"[36m<body>[39m
|
||||
[36m<div />[39m
|
||||
[36m<div[39m
|
||||
[33mid[39m=[32m"mx_ContextualMenu_Container"[39m
|
||||
[36m>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"mx_ContextualMenu_wrapper"[39m
|
||||
[36m>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"mx_ContextualMenu_background"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"mx_ContextualMenu"[39m
|
||||
[33mrole[39m=[32m"menu"[39m
|
||||
[36m>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"mx_IconizedContextMenu mx_SpacePanel_contextMenu mx_IconizedContextMenu_compact"[39m
|
||||
[36m>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"mx_SpacePanel_contextMenu_header"[39m
|
||||
[36m>[39m
|
||||
[0mtest space[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"mx_IconizedContextMenu_optionList"[39m
|
||||
[36m>[39m
|
||||
[36m<div[39m
|
||||
[33maria-label[39m=[32m"Space home"[39m
|
||||
[33mclass[39m=[32m"mx_AccessibleButton mx_IconizedContextMenu_item focus-visible"[39m
|
||||
[33mdata-focus-visible-added[39m=[32m""[39m
|
||||
[33mrole[39m=[32m"menuitem"[39m
|
||||
[33mtabindex[39m=[32m"0"[39m
|
||||
[36m>[39m
|
||||
[36m<span[39m
|
||||
[33mclass[39m=[32m"mx_IconizedContextMenu_icon mx_SpacePanel_iconHome"[39m
|
||||
[36m/>[39m
|
||||
[36m<span[39m
|
||||
[33mclass[39m=[32m"mx_IconizedContextMenu_label"[39m
|
||||
[36m>[39m
|
||||
[0mSpace home[0m
|
||||
[36m</span>[39m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33maria-label[39m=[32m"Explore rooms"[39m
|
||||
[33mclass[39m=[32m"mx_AccessibleButton mx_IconizedContextMenu_item"[39m
|
||||
[33mrole[39m=[32m"menuitem"[39m
|
||||
[33mtabindex[39m=[32m"-1"[39m
|
||||
[36m>[39m
|
||||
[36m<span[39m
|
||||
[33mclass[39m=[32m"mx_IconizedContextMenu_icon mx_SpacePanel_iconExplore"[39m
|
||||
[36m/>[39m
|
||||
[36m<span[39m
|
||||
[33mclass[39m=[32m"mx_IconizedContextMenu_label"[39m
|
||||
[36m>[39m
|
||||
[0mExplore rooms[0m
|
||||
[36m</span>[39m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33maria-label[39m=[32m"Preferences"[39m
|
||||
[33mclass[39m=[32m"mx_AccessibleButton mx_IconizedContextMenu_item"[39m
|
||||
[33mrole[39m=[32m"menuitem"[39m
|
||||
[33mtabindex[39m=[32m"-1"[39m
|
||||
[36m>[39m
|
||||
[36m<span[39m
|
||||
[33mclass[39m=[32m"mx_IconizedContextMenu_icon mx_SpacePanel_iconPreferences"[39m
|
||||
[36m/>[39m
|
||||
[36m<span[39m
|
||||
[33mclass[39m=[32m"mx_IconizedContextMenu_label"[39m
|
||||
[36m>[39m
|
||||
[0mPreferences[0m
|
||||
[36m</span>[39m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33maria-label[39m=[32m"Leave space"[39m
|
||||
[33mclass[39m=[32m"mx_AccessibleButton mx_IconizedContextMenu_option_red mx_IconizedContextMenu_item"[39m
|
||||
[33mdata-testid[39m=[32m"leave-option"[39m
|
||||
[33mrole[39m=[32m"menuitem"[39m
|
||||
[33mtabindex[39m=[32m"-1"[39m
|
||||
[36m>[39m
|
||||
[36m<span[39m
|
||||
[33mclass[39m=[32m"mx_IconizedContextMenu_icon mx_SpacePanel_iconLeave"[39m
|
||||
[36m/>[39m
|
||||
[36m<span[39m
|
||||
[33mclass[39m=[32m"mx_IconizedContextMenu_label"[39m
|
||||
[36m>[39m
|
||||
[0mLeave space[0m
|
||||
[36m</span>[39m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m</body>[39m"
|
||||
`;
|
||||
|
|
|
@ -14,10 +14,8 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import React from "react";
|
||||
// eslint-disable-next-line deprecate/import
|
||||
import { mount } from "enzyme";
|
||||
import { act } from "react-dom/test-utils";
|
||||
|
||||
import LabelledCheckbox from "../../../../src/components/views/elements/LabelledCheckbox";
|
||||
|
||||
|
@ -30,32 +28,18 @@ jest.mock("matrix-js-sdk/src/randomstring", () => {
|
|||
|
||||
describe("<LabelledCheckbox />", () => {
|
||||
type CompProps = React.ComponentProps<typeof LabelledCheckbox>;
|
||||
const getComponent = (props: CompProps) => mount(<LabelledCheckbox {...props} />);
|
||||
type CompClass = ReturnType<typeof getComponent>;
|
||||
const getComponent = (props: CompProps) => <LabelledCheckbox {...props} />;
|
||||
const getCheckbox = (): HTMLInputElement => screen.getByRole("checkbox");
|
||||
|
||||
const getCheckbox = (component: CompClass) => component.find(`input[type="checkbox"]`);
|
||||
const getLabel = (component: CompClass) => component.find(`.mx_LabelledCheckbox_label`);
|
||||
const getByline = (component: CompClass) => component.find(`.mx_LabelledCheckbox_byline`);
|
||||
|
||||
const isChecked = (checkbox: ReturnType<typeof getCheckbox>) => checkbox.is(`[checked=true]`);
|
||||
const isDisabled = (checkbox: ReturnType<typeof getCheckbox>) => checkbox.is(`[disabled=true]`);
|
||||
const getText = (span: ReturnType<typeof getLabel>) => (span.length > 0 ? span.at(0).text() : null);
|
||||
|
||||
test.each([null, "this is a byline"])("should render with byline of %p", (byline) => {
|
||||
it.each([undefined, "this is a byline"])("should render with byline of %p", (byline) => {
|
||||
const props: CompProps = {
|
||||
label: "Hello world",
|
||||
value: true,
|
||||
byline: byline,
|
||||
onChange: jest.fn(),
|
||||
};
|
||||
const component = getComponent(props);
|
||||
const checkbox = getCheckbox(component);
|
||||
|
||||
expect(component).toMatchSnapshot();
|
||||
expect(isChecked(checkbox)).toBe(true);
|
||||
expect(isDisabled(checkbox)).toBe(false);
|
||||
expect(getText(getLabel(component))).toBe(props.label);
|
||||
expect(getText(getByline(component))).toBe(byline);
|
||||
const renderResult = render(getComponent(props));
|
||||
expect(renderResult.asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should support unchecked by default", () => {
|
||||
|
@ -64,9 +48,8 @@ describe("<LabelledCheckbox />", () => {
|
|||
value: false,
|
||||
onChange: jest.fn(),
|
||||
};
|
||||
const component = getComponent(props);
|
||||
|
||||
expect(isChecked(getCheckbox(component))).toBe(false);
|
||||
render(getComponent(props));
|
||||
expect(getCheckbox()).not.toBeChecked();
|
||||
});
|
||||
|
||||
it("should be possible to disable the checkbox", () => {
|
||||
|
@ -76,9 +59,8 @@ describe("<LabelledCheckbox />", () => {
|
|||
disabled: true,
|
||||
onChange: jest.fn(),
|
||||
};
|
||||
const component = getComponent(props);
|
||||
|
||||
expect(isDisabled(getCheckbox(component))).toBe(true);
|
||||
render(getComponent(props));
|
||||
expect(getCheckbox()).toBeDisabled();
|
||||
});
|
||||
|
||||
it("should emit onChange calls", () => {
|
||||
|
@ -87,15 +69,11 @@ describe("<LabelledCheckbox />", () => {
|
|||
value: false,
|
||||
onChange: jest.fn(),
|
||||
};
|
||||
const component = getComponent(props);
|
||||
render(getComponent(props));
|
||||
|
||||
expect(props.onChange).not.toHaveBeenCalled();
|
||||
|
||||
act(() => {
|
||||
getCheckbox(component).simulate("change");
|
||||
});
|
||||
|
||||
expect(props.onChange).toHaveBeenCalledTimes(1);
|
||||
fireEvent.click(getCheckbox());
|
||||
expect(props.onChange).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
it("should react to value and disabled prop changes", () => {
|
||||
|
@ -104,16 +82,18 @@ describe("<LabelledCheckbox />", () => {
|
|||
value: false,
|
||||
onChange: jest.fn(),
|
||||
};
|
||||
const component = getComponent(props);
|
||||
let checkbox = getCheckbox(component);
|
||||
const { rerender } = render(getComponent(props));
|
||||
|
||||
expect(isChecked(checkbox)).toBe(false);
|
||||
expect(isDisabled(checkbox)).toBe(false);
|
||||
let checkbox = getCheckbox();
|
||||
expect(checkbox).not.toBeChecked();
|
||||
expect(checkbox).not.toBeDisabled();
|
||||
|
||||
component.setProps({ value: true, disabled: true });
|
||||
checkbox = getCheckbox(component); // refresh reference to checkbox
|
||||
props.disabled = true;
|
||||
props.value = true;
|
||||
rerender(getComponent(props));
|
||||
|
||||
expect(isChecked(checkbox)).toBe(true);
|
||||
expect(isDisabled(checkbox)).toBe(true);
|
||||
checkbox = getCheckbox();
|
||||
expect(checkbox).toBeChecked();
|
||||
expect(checkbox).toBeDisabled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,106 +1,82 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<LabelledCheckbox /> should render with byline of "this is a byline" 1`] = `
|
||||
<LabelledCheckbox
|
||||
byline="this is a byline"
|
||||
label="Hello world"
|
||||
onChange={[MockFunction]}
|
||||
value={true}
|
||||
>
|
||||
<DocumentFragment>
|
||||
<label
|
||||
className="mx_LabelledCheckbox"
|
||||
>
|
||||
<StyledCheckbox
|
||||
checked={true}
|
||||
className=""
|
||||
onChange={[Function]}
|
||||
class="mx_LabelledCheckbox"
|
||||
>
|
||||
<span
|
||||
className="mx_Checkbox mx_Checkbox_hasKind mx_Checkbox_kind_solid"
|
||||
class="mx_Checkbox mx_Checkbox_hasKind mx_Checkbox_kind_solid"
|
||||
>
|
||||
<input
|
||||
checked={true}
|
||||
checked=""
|
||||
id="checkbox_abdefghi"
|
||||
onChange={[Function]}
|
||||
type="checkbox"
|
||||
/>
|
||||
<label
|
||||
htmlFor="checkbox_abdefghi"
|
||||
for="checkbox_abdefghi"
|
||||
>
|
||||
<div
|
||||
className="mx_Checkbox_background"
|
||||
class="mx_Checkbox_background"
|
||||
>
|
||||
<div
|
||||
className="mx_Checkbox_checkmark"
|
||||
class="mx_Checkbox_checkmark"
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
</span>
|
||||
</StyledCheckbox>
|
||||
<div
|
||||
className="mx_LabelledCheckbox_labels"
|
||||
class="mx_LabelledCheckbox_labels"
|
||||
>
|
||||
<span
|
||||
className="mx_LabelledCheckbox_label"
|
||||
class="mx_LabelledCheckbox_label"
|
||||
>
|
||||
Hello world
|
||||
</span>
|
||||
<span
|
||||
className="mx_LabelledCheckbox_byline"
|
||||
class="mx_LabelledCheckbox_byline"
|
||||
>
|
||||
this is a byline
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</LabelledCheckbox>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<LabelledCheckbox /> should render with byline of null 1`] = `
|
||||
<LabelledCheckbox
|
||||
byline={null}
|
||||
label="Hello world"
|
||||
onChange={[MockFunction]}
|
||||
value={true}
|
||||
>
|
||||
exports[`<LabelledCheckbox /> should render with byline of undefined 1`] = `
|
||||
<DocumentFragment>
|
||||
<label
|
||||
className="mx_LabelledCheckbox"
|
||||
>
|
||||
<StyledCheckbox
|
||||
checked={true}
|
||||
className=""
|
||||
onChange={[Function]}
|
||||
class="mx_LabelledCheckbox"
|
||||
>
|
||||
<span
|
||||
className="mx_Checkbox mx_Checkbox_hasKind mx_Checkbox_kind_solid"
|
||||
class="mx_Checkbox mx_Checkbox_hasKind mx_Checkbox_kind_solid"
|
||||
>
|
||||
<input
|
||||
checked={true}
|
||||
checked=""
|
||||
id="checkbox_abdefghi"
|
||||
onChange={[Function]}
|
||||
type="checkbox"
|
||||
/>
|
||||
<label
|
||||
htmlFor="checkbox_abdefghi"
|
||||
for="checkbox_abdefghi"
|
||||
>
|
||||
<div
|
||||
className="mx_Checkbox_background"
|
||||
class="mx_Checkbox_background"
|
||||
>
|
||||
<div
|
||||
className="mx_Checkbox_checkmark"
|
||||
class="mx_Checkbox_checkmark"
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
</span>
|
||||
</StyledCheckbox>
|
||||
<div
|
||||
className="mx_LabelledCheckbox_labels"
|
||||
class="mx_LabelledCheckbox_labels"
|
||||
>
|
||||
<span
|
||||
className="mx_LabelledCheckbox_label"
|
||||
class="mx_LabelledCheckbox_label"
|
||||
>
|
||||
Hello world
|
||||
</span>
|
||||
</div>
|
||||
</label>
|
||||
</LabelledCheckbox>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
|
|
@ -24,34 +24,64 @@ import * as TestUtils from "../../../test-utils";
|
|||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||
import EditorModel from "../../../../src/editor/model";
|
||||
import { createPartCreator, createRenderer } from "../../../editor/mock";
|
||||
import SettingsStore from "../../../../src/settings/SettingsStore";
|
||||
|
||||
describe("BasicMessageComposer", () => {
|
||||
const renderer = createRenderer();
|
||||
const pc = createPartCreator();
|
||||
|
||||
beforeEach(() => {
|
||||
TestUtils.stubClient();
|
||||
});
|
||||
|
||||
it("should allow a user to paste a URL without it being mangled", () => {
|
||||
const model = new EditorModel([], pc, renderer);
|
||||
const client: MatrixClient = MatrixClientPeg.get();
|
||||
|
||||
const roomId = "!1234567890:domain";
|
||||
const userId = client.getSafeUserId();
|
||||
|
||||
const room = new Room(roomId, client, userId);
|
||||
|
||||
it("should allow a user to paste a URL without it being mangled", async () => {
|
||||
const model = new EditorModel([], pc, renderer);
|
||||
render(<BasicMessageComposer model={model} room={room} />);
|
||||
const testUrl = "https://element.io";
|
||||
const mockDataTransfer = generateMockDataTransferForString(testUrl);
|
||||
|
||||
render(<BasicMessageComposer model={model} room={room} />);
|
||||
userEvent.paste(mockDataTransfer);
|
||||
await userEvent.paste(mockDataTransfer);
|
||||
|
||||
expect(model.parts).toHaveLength(1);
|
||||
expect(model.parts[0].text).toBe(testUrl);
|
||||
expect(screen.getByText(testUrl)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should replaceEmoticons properly", async () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName: string) => {
|
||||
return settingName === "MessageComposerInput.autoReplaceEmoji";
|
||||
});
|
||||
userEvent.setup();
|
||||
const model = new EditorModel([], pc, renderer);
|
||||
render(<BasicMessageComposer model={model} room={room} />);
|
||||
|
||||
const tranformations = [
|
||||
{ before: "4:3 video", after: "4:3 video" },
|
||||
{ before: "regexp 12345678", after: "regexp 12345678" },
|
||||
{ before: "--:--)", after: "--:--)" },
|
||||
|
||||
{ before: "we <3 matrix", after: "we ❤️ matrix" },
|
||||
{ before: "hello world :-)", after: "hello world 🙂" },
|
||||
{ before: ":) hello world", after: "🙂 hello world" },
|
||||
{ before: ":D 4:3 video :)", after: "😄 4:3 video 🙂" },
|
||||
|
||||
{ before: ":-D", after: "😄" },
|
||||
{ before: ":D", after: "😄" },
|
||||
{ before: ":3", after: "😽" },
|
||||
];
|
||||
const input = screen.getByRole("textbox");
|
||||
|
||||
for (const { before, after } of tranformations) {
|
||||
await userEvent.clear(input);
|
||||
//add a space after the text to trigger the replacement
|
||||
await userEvent.type(input, before + " ");
|
||||
const transformedText = model.parts.map((part) => part.text).join("");
|
||||
expect(transformedText).toBe(after + " ");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function generateMockDataTransferForString(string: string): DataTransfer {
|
||||
|
|
|
@ -226,6 +226,7 @@ describe("<Notifications />", () => {
|
|||
setAccountData: jest.fn(),
|
||||
sendReadReceipt: jest.fn(),
|
||||
supportsThreads: jest.fn().mockReturnValue(true),
|
||||
isInitialSyncComplete: jest.fn().mockReturnValue(false),
|
||||
});
|
||||
mockClient.getPushRules.mockResolvedValue(pushRules);
|
||||
|
||||
|
|
|
@ -94,6 +94,8 @@ describe("RoomViewStore", function () {
|
|||
getDeviceId: jest.fn().mockReturnValue("ABC123"),
|
||||
sendStateEvent: jest.fn().mockResolvedValue({}),
|
||||
supportsThreads: jest.fn(),
|
||||
isInitialSyncComplete: jest.fn().mockResolvedValue(false),
|
||||
relations: jest.fn(),
|
||||
});
|
||||
const room = new Room(roomId, mockClient, userId);
|
||||
const room2 = new Room(roomId2, mockClient, userId);
|
||||
|
|
109
yarn.lock
109
yarn.lock
|
@ -2127,11 +2127,12 @@
|
|||
"@types/fbemitter" "*"
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/fs-extra@^9.0.13":
|
||||
version "9.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45"
|
||||
integrity sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==
|
||||
"@types/fs-extra@^11.0.0":
|
||||
version "11.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-11.0.1.tgz#f542ec47810532a8a252127e6e105f487e0a6ea5"
|
||||
integrity sha512-MxObHvNl4A69ofaTRU8DFqvgzzv8s9yRtaPPm5gud9HDNvpB3GPQFvNuTWAI59B9huVGV5jXYJwbCsmBsOGYWA==
|
||||
dependencies:
|
||||
"@types/jsonfile" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/geojson@*", "@types/geojson@^7946.0.10", "@types/geojson@^7946.0.8":
|
||||
|
@ -2200,6 +2201,13 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
||||
|
||||
"@types/jsonfile@*":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/jsonfile/-/jsonfile-6.1.1.tgz#ac84e9aefa74a2425a0fb3012bdea44f58970f1b"
|
||||
integrity sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/katex@^0.14.0":
|
||||
version "0.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.14.0.tgz#b84c0afc3218069a5ad64fe2a95321881021b5fe"
|
||||
|
@ -2417,14 +2425,15 @@
|
|||
integrity sha512-3NoqvZC2W5gAC5DZbTpCeJ251vGQmgcWIHQJGq2J240HY6ErQ9aWKkwfoKJlHLx+A83WPNTZ9+3cd2ILxbvr1w==
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^5.35.1":
|
||||
version "5.48.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.48.1.tgz#deee67e399f2cb6b4608c935777110e509d8018c"
|
||||
integrity sha512-9nY5K1Rp2ppmpb9s9S2aBiF3xo5uExCehMDmYmmFqqyxgenbHJ3qbarcLt4ITgaD6r/2ypdlcFRdcuVPnks+fQ==
|
||||
version "5.51.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.51.0.tgz#da3f2819633061ced84bb82c53bba45a6fe9963a"
|
||||
integrity sha512-wcAwhEWm1RgNd7dxD/o+nnLW8oH+6RK1OGnmbmkj/GGoDPV1WWMVP0FXYQBivKHdwM1pwii3bt//RC62EriIUQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.48.1"
|
||||
"@typescript-eslint/type-utils" "5.48.1"
|
||||
"@typescript-eslint/utils" "5.48.1"
|
||||
"@typescript-eslint/scope-manager" "5.51.0"
|
||||
"@typescript-eslint/type-utils" "5.51.0"
|
||||
"@typescript-eslint/utils" "5.51.0"
|
||||
debug "^4.3.4"
|
||||
grapheme-splitter "^1.0.4"
|
||||
ignore "^5.2.0"
|
||||
natural-compare-lite "^1.4.0"
|
||||
regexpp "^3.2.0"
|
||||
|
@ -2432,71 +2441,71 @@
|
|||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/parser@^5.6.0":
|
||||
version "5.48.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.48.1.tgz#d0125792dab7e232035434ab8ef0658154db2f10"
|
||||
integrity sha512-4yg+FJR/V1M9Xoq56SF9Iygqm+r5LMXvheo6DQ7/yUWynQ4YfCRnsKuRgqH4EQ5Ya76rVwlEpw4Xu+TgWQUcdA==
|
||||
version "5.51.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.51.0.tgz#2d74626652096d966ef107f44b9479f02f51f271"
|
||||
integrity sha512-fEV0R9gGmfpDeRzJXn+fGQKcl0inIeYobmmUWijZh9zA7bxJ8clPhV9up2ZQzATxAiFAECqPQyMDB4o4B81AaA==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.48.1"
|
||||
"@typescript-eslint/types" "5.48.1"
|
||||
"@typescript-eslint/typescript-estree" "5.48.1"
|
||||
"@typescript-eslint/scope-manager" "5.51.0"
|
||||
"@typescript-eslint/types" "5.51.0"
|
||||
"@typescript-eslint/typescript-estree" "5.51.0"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.48.1":
|
||||
version "5.48.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.48.1.tgz#39c71e4de639f5fe08b988005beaaf6d79f9d64d"
|
||||
integrity sha512-S035ueRrbxRMKvSTv9vJKIWgr86BD8s3RqoRZmsSh/s8HhIs90g6UlK8ZabUSjUZQkhVxt7nmZ63VJ9dcZhtDQ==
|
||||
"@typescript-eslint/scope-manager@5.51.0":
|
||||
version "5.51.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.51.0.tgz#ad3e3c2ecf762d9a4196c0fbfe19b142ac498990"
|
||||
integrity sha512-gNpxRdlx5qw3yaHA0SFuTjW4rxeYhpHxt491PEcKF8Z6zpq0kMhe0Tolxt0qjlojS+/wArSDlj/LtE69xUJphQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.48.1"
|
||||
"@typescript-eslint/visitor-keys" "5.48.1"
|
||||
"@typescript-eslint/types" "5.51.0"
|
||||
"@typescript-eslint/visitor-keys" "5.51.0"
|
||||
|
||||
"@typescript-eslint/type-utils@5.48.1":
|
||||
version "5.48.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.48.1.tgz#5d94ac0c269a81a91ad77c03407cea2caf481412"
|
||||
integrity sha512-Hyr8HU8Alcuva1ppmqSYtM/Gp0q4JOp1F+/JH5D1IZm/bUBrV0edoewQZiEc1r6I8L4JL21broddxK8HAcZiqQ==
|
||||
"@typescript-eslint/type-utils@5.51.0":
|
||||
version "5.51.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.51.0.tgz#7af48005531700b62a20963501d47dfb27095988"
|
||||
integrity sha512-QHC5KKyfV8sNSyHqfNa0UbTbJ6caB8uhcx2hYcWVvJAZYJRBo5HyyZfzMdRx8nvS+GyMg56fugMzzWnojREuQQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "5.48.1"
|
||||
"@typescript-eslint/utils" "5.48.1"
|
||||
"@typescript-eslint/typescript-estree" "5.51.0"
|
||||
"@typescript-eslint/utils" "5.51.0"
|
||||
debug "^4.3.4"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/types@5.48.1":
|
||||
version "5.48.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.48.1.tgz#efd1913a9aaf67caf8a6e6779fd53e14e8587e14"
|
||||
integrity sha512-xHyDLU6MSuEEdIlzrrAerCGS3T7AA/L8Hggd0RCYBi0w3JMvGYxlLlXHeg50JI9Tfg5MrtsfuNxbS/3zF1/ATg==
|
||||
"@typescript-eslint/types@5.51.0":
|
||||
version "5.51.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.51.0.tgz#e7c1622f46c7eea7e12bbf1edfb496d4dec37c90"
|
||||
integrity sha512-SqOn0ANn/v6hFn0kjvLwiDi4AzR++CBZz0NV5AnusT2/3y32jdc0G4woXPWHCumWtUXZKPAS27/9vziSsC9jnw==
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.48.1":
|
||||
version "5.48.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.1.tgz#9efa8ee2aa471c6ab62e649f6e64d8d121bc2056"
|
||||
integrity sha512-Hut+Osk5FYr+sgFh8J/FHjqX6HFcDzTlWLrFqGoK5kVUN3VBHF/QzZmAsIXCQ8T/W9nQNBTqalxi1P3LSqWnRA==
|
||||
"@typescript-eslint/typescript-estree@5.51.0":
|
||||
version "5.51.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.51.0.tgz#0ec8170d7247a892c2b21845b06c11eb0718f8de"
|
||||
integrity sha512-TSkNupHvNRkoH9FMA3w7TazVFcBPveAAmb7Sz+kArY6sLT86PA5Vx80cKlYmd8m3Ha2SwofM1KwraF24lM9FvA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.48.1"
|
||||
"@typescript-eslint/visitor-keys" "5.48.1"
|
||||
"@typescript-eslint/types" "5.51.0"
|
||||
"@typescript-eslint/visitor-keys" "5.51.0"
|
||||
debug "^4.3.4"
|
||||
globby "^11.1.0"
|
||||
is-glob "^4.0.3"
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/utils@5.48.1":
|
||||
version "5.48.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.48.1.tgz#20f2f4e88e9e2a0961cbebcb47a1f0f7da7ba7f9"
|
||||
integrity sha512-SmQuSrCGUOdmGMwivW14Z0Lj8dxG1mOFZ7soeJ0TQZEJcs3n5Ndgkg0A4bcMFzBELqLJ6GTHnEU+iIoaD6hFGA==
|
||||
"@typescript-eslint/utils@5.51.0":
|
||||
version "5.51.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.51.0.tgz#074f4fabd5b12afe9c8aa6fdee881c050f8b4d47"
|
||||
integrity sha512-76qs+5KWcaatmwtwsDJvBk4H76RJQBFe+Gext0EfJdC3Vd2kpY2Pf//OHHzHp84Ciw0/rYoGTDnIAr3uWhhJYw==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.9"
|
||||
"@types/semver" "^7.3.12"
|
||||
"@typescript-eslint/scope-manager" "5.48.1"
|
||||
"@typescript-eslint/types" "5.48.1"
|
||||
"@typescript-eslint/typescript-estree" "5.48.1"
|
||||
"@typescript-eslint/scope-manager" "5.51.0"
|
||||
"@typescript-eslint/types" "5.51.0"
|
||||
"@typescript-eslint/typescript-estree" "5.51.0"
|
||||
eslint-scope "^5.1.1"
|
||||
eslint-utils "^3.0.0"
|
||||
semver "^7.3.7"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.48.1":
|
||||
version "5.48.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.1.tgz#79fd4fb9996023ef86849bf6f904f33eb6c8fccb"
|
||||
integrity sha512-Ns0XBwmfuX7ZknznfXozgnydyR8F6ev/KEGePP4i74uL3ArsKbEhJ7raeKr1JSa997DBDwol/4a0Y+At82c9dA==
|
||||
"@typescript-eslint/visitor-keys@5.51.0":
|
||||
version "5.51.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.51.0.tgz#c0147dd9a36c0de758aaebd5b48cae1ec59eba87"
|
||||
integrity sha512-Oh2+eTdjHjOFjKA27sxESlA87YPSOJafGCR0md5oeMdh1ZcCfAGCIOL216uTBAkAIptvLIfKQhl7lHxMJet4GQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.48.1"
|
||||
"@typescript-eslint/types" "5.51.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@wojtekmaj/enzyme-adapter-react-17@^0.8.0":
|
||||
|
|
Loading…
Reference in a new issue