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