mirror of https://github.com/vector-im/riot-web
				
				
				
			Support adding space-restricted joins on rooms not members of those spaces (#9017)
* Support adding space-restricted joins on rooms not members of those spaces * add react dependencies * Add snapshot test * Fix snapshot stability * Update snapshot * Increase coverage --------- Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>pull/28788/head^2
							parent
							
								
									bbab65a4cd
								
							
						
					
					
						commit
						771d7e95e7
					
				|  | @ -93,11 +93,13 @@ const ManageRestrictedJoinRuleDialog: React.FC<IProps> = ({ room, selected = [], | |||
|     const [query, setQuery] = useState(""); | ||||
|     const lcQuery = query.toLowerCase().trim(); | ||||
| 
 | ||||
|     const [spacesContainingRoom, otherEntries] = useMemo(() => { | ||||
|     const [spacesContainingRoom, otherJoinedSpaces, otherEntries] = useMemo(() => { | ||||
|         const parents = new Set<Room>(); | ||||
|         addAllParents(parents, room); | ||||
| 
 | ||||
|         return [ | ||||
|             Array.from(parents), | ||||
|             SpaceStore.instance.spacePanelSpaces.filter((s) => !parents.has(s)), | ||||
|             filterBoolean( | ||||
|                 selected.map((roomId) => { | ||||
|                     const room = cli.getRoom(roomId); | ||||
|  | @ -112,12 +114,13 @@ const ManageRestrictedJoinRuleDialog: React.FC<IProps> = ({ room, selected = [], | |||
|         ]; | ||||
|     }, [cli, selected, room]); | ||||
| 
 | ||||
|     const [filteredSpacesContainingRoom, filteredOtherEntries] = useMemo( | ||||
|     const [filteredSpacesContainingRoom, filteredOtherJoinedSpaces, filteredOtherEntries] = useMemo( | ||||
|         () => [ | ||||
|             spacesContainingRoom.filter((r) => r.name.toLowerCase().includes(lcQuery)), | ||||
|             otherJoinedSpaces.filter((r) => r.name.toLowerCase().includes(lcQuery)), | ||||
|             otherEntries.filter((r) => r.name.toLowerCase().includes(lcQuery)), | ||||
|         ], | ||||
|         [spacesContainingRoom, otherEntries, lcQuery], | ||||
|         [spacesContainingRoom, otherJoinedSpaces, otherEntries, lcQuery], | ||||
|     ); | ||||
| 
 | ||||
|     const onChange = (checked: boolean, room: Room): void => { | ||||
|  | @ -138,6 +141,8 @@ const ManageRestrictedJoinRuleDialog: React.FC<IProps> = ({ room, selected = [], | |||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     const totalResults = | ||||
|         filteredSpacesContainingRoom.length + filteredOtherJoinedSpaces.length + filteredOtherEntries.length; | ||||
|     return ( | ||||
|         <BaseDialog | ||||
|             title={_t("Select spaces")} | ||||
|  | @ -206,7 +211,25 @@ const ManageRestrictedJoinRuleDialog: React.FC<IProps> = ({ room, selected = [], | |||
|                         </div> | ||||
|                     ) : null} | ||||
| 
 | ||||
|                     {filteredSpacesContainingRoom.length + filteredOtherEntries.length < 1 ? ( | ||||
|                     {filteredOtherJoinedSpaces.length > 0 ? ( | ||||
|                         <div className="mx_ManageRestrictedJoinRuleDialog_section"> | ||||
|                             <h3>{_t("Other spaces you know")}</h3> | ||||
|                             {filteredOtherJoinedSpaces.map((space) => { | ||||
|                                 return ( | ||||
|                                     <Entry | ||||
|                                         key={space.roomId} | ||||
|                                         room={space} | ||||
|                                         checked={newSelected.has(space.roomId)} | ||||
|                                         onChange={(checked: boolean) => { | ||||
|                                             onChange(checked, space); | ||||
|                                         }} | ||||
|                                     /> | ||||
|                                 ); | ||||
|                             })} | ||||
|                         </div> | ||||
|                     ) : null} | ||||
| 
 | ||||
|                     {totalResults < 1 ? ( | ||||
|                         <span className="mx_ManageRestrictedJoinRuleDialog_noResults">{_t("No results")}</span> | ||||
|                     ) : undefined} | ||||
|                 </AutoHideScrollbar> | ||||
|  |  | |||
|  | @ -2970,6 +2970,7 @@ | |||
|     "Spaces you know that contain this room": "Spaces you know that contain this room", | ||||
|     "Other spaces or rooms you might not know": "Other spaces or rooms you might not know", | ||||
|     "These are likely ones other room admins are a part of.": "These are likely ones other room admins are a part of.", | ||||
|     "Other spaces you know": "Other spaces you know", | ||||
|     "Confirm by comparing the following with the User Settings in your other session:": "Confirm by comparing the following with the User Settings in your other session:", | ||||
|     "Confirm this user's session by comparing the following with their User Settings:": "Confirm this user's session by comparing the following with their User Settings:", | ||||
|     "Session name": "Session name", | ||||
|  |  | |||
|  | @ -0,0 +1,58 @@ | |||
| /* | ||||
| Copyright 2023 The Matrix.org Foundation C.I.C. | ||||
| 
 | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
| 
 | ||||
|     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| 
 | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
| 
 | ||||
| import React from "react"; | ||||
| import { render } from "@testing-library/react"; | ||||
| import { Room } from "matrix-js-sdk/src/matrix"; | ||||
| 
 | ||||
| import { getMockClientWithEventEmitter, mockClientMethodsUser } from "../../../test-utils"; | ||||
| import ManageRestrictedJoinRuleDialog from "../../../../src/components/views/dialogs/ManageRestrictedJoinRuleDialog"; | ||||
| import SpaceStore from "../../../../src/stores/spaces/SpaceStore"; | ||||
| import DMRoomMap from "../../../../src/utils/DMRoomMap"; | ||||
| 
 | ||||
| // Fake random strings to give a predictable snapshot
 | ||||
| jest.mock("matrix-js-sdk/src/randomstring", () => { | ||||
|     return { | ||||
|         randomString: () => "abdefghi", | ||||
|     }; | ||||
| }); | ||||
| 
 | ||||
| describe("<ManageRestrictedJoinRuleDialog />", () => { | ||||
|     const userId = "@alice:server.org"; | ||||
|     const mockClient = getMockClientWithEventEmitter({ | ||||
|         ...mockClientMethodsUser(userId), | ||||
|         getRoom: jest.fn(), | ||||
|     }); | ||||
|     const room = new Room("!roomId:server", mockClient, userId); | ||||
|     mockClient.getRoom.mockReturnValue(room); | ||||
|     DMRoomMap.makeShared(mockClient); | ||||
| 
 | ||||
|     const onFinished = jest.fn(); | ||||
|     const getComponent = (props = {}) => | ||||
|         render(<ManageRestrictedJoinRuleDialog room={room} onFinished={onFinished} {...props} />); | ||||
| 
 | ||||
|     it("should render empty state", () => { | ||||
|         expect(getComponent().asFragment()).toMatchSnapshot(); | ||||
|     }); | ||||
| 
 | ||||
|     it("should list spaces which are not parents of the room", () => { | ||||
|         const space1 = new Room("!space:server", mockClient, userId); | ||||
|         space1.name = "Other Space"; | ||||
|         jest.spyOn(SpaceStore.instance, "spacePanelSpaces", "get").mockReturnValue([space1]); | ||||
| 
 | ||||
|         expect(getComponent().asFragment()).toMatchSnapshot(); | ||||
|     }); | ||||
| }); | ||||
|  | @ -0,0 +1,263 @@ | |||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||||
| 
 | ||||
| exports[`<ManageRestrictedJoinRuleDialog /> should list spaces which are not parents of the room 1`] = ` | ||||
| <DocumentFragment> | ||||
|   <div | ||||
|     data-focus-guard="true" | ||||
|     style="width: 1px; height: 0px; padding: 0px; overflow: hidden; position: fixed; top: 1px; left: 1px;" | ||||
|     tabindex="0" | ||||
|   /> | ||||
|   <div | ||||
|     aria-labelledby="mx_BaseDialog_title" | ||||
|     class="mx_ManageRestrictedJoinRuleDialog" | ||||
|     data-focus-lock-disabled="false" | ||||
|     role="dialog" | ||||
|   > | ||||
|     <div | ||||
|       class="mx_Dialog_header mx_Dialog_headerWithCancel" | ||||
|     > | ||||
|       <h2 | ||||
|         class="mx_Heading_h3 mx_Dialog_title" | ||||
|         id="mx_BaseDialog_title" | ||||
|       > | ||||
|         Select spaces | ||||
|       </h2> | ||||
|       <div | ||||
|         aria-label="Close dialog" | ||||
|         class="mx_AccessibleButton mx_Dialog_cancelButton" | ||||
|         role="button" | ||||
|         tabindex="0" | ||||
|       /> | ||||
|     </div> | ||||
|     <p> | ||||
|       <span> | ||||
|         Decide which spaces can access this room. If a space is selected, its members can find and join  | ||||
|         <b> | ||||
|           !roomId:server | ||||
|         </b> | ||||
|         . | ||||
|       </span> | ||||
|     </p> | ||||
|     <div | ||||
|       class="mx_SearchBox mx_textinput" | ||||
|     > | ||||
|       <input | ||||
|         autocomplete="off" | ||||
|         class="mx_textinput_icon mx_textinput_search mx_textinput_icon mx_textinput_search" | ||||
|         data-testid="searchbox-input" | ||||
|         placeholder="Search spaces" | ||||
|         type="text" | ||||
|         value="" | ||||
|       /> | ||||
|       <div | ||||
|         class="mx_AccessibleButton mx_SearchBox_closeButton" | ||||
|         role="button" | ||||
|         tabindex="-1" | ||||
|       /> | ||||
|     </div> | ||||
|     <div | ||||
|       class="mx_AutoHideScrollbar mx_ManageRestrictedJoinRuleDialog_content" | ||||
|       tabindex="-1" | ||||
|     > | ||||
|       <div | ||||
|         class="mx_ManageRestrictedJoinRuleDialog_section" | ||||
|       > | ||||
|         <h3> | ||||
|           Other spaces you know | ||||
|         </h3> | ||||
|         <label | ||||
|           class="mx_ManageRestrictedJoinRuleDialog_entry" | ||||
|         > | ||||
|           <div> | ||||
|             <div> | ||||
|               <span | ||||
|                 class="mx_BaseAvatar" | ||||
|                 role="presentation" | ||||
|               > | ||||
|                 <span | ||||
|                   aria-hidden="true" | ||||
|                   class="mx_BaseAvatar_initial" | ||||
|                   style="font-size: 13px; width: 20px; line-height: 20px;" | ||||
|                 > | ||||
|                   O | ||||
|                 </span> | ||||
|                 <img | ||||
|                   alt="" | ||||
|                   aria-hidden="true" | ||||
|                   class="mx_BaseAvatar_image" | ||||
|                   data-testid="avatar-img" | ||||
|                   loading="lazy" | ||||
|                   src="data:image/png;base64,00" | ||||
|                   style="width: 20px; height: 20px;" | ||||
|                 /> | ||||
|               </span> | ||||
|               <span | ||||
|                 class="mx_ManageRestrictedJoinRuleDialog_entry_name" | ||||
|               > | ||||
|                 Other Space | ||||
|               </span> | ||||
|             </div> | ||||
|             <div | ||||
|               class="mx_ManageRestrictedJoinRuleDialog_entry_description" | ||||
|             > | ||||
|               0 members | ||||
|             </div> | ||||
|           </div> | ||||
|           <span | ||||
|             class="mx_Checkbox mx_Checkbox_hasKind mx_Checkbox_kind_solid" | ||||
|           > | ||||
|             <input | ||||
|               id="checkbox_abdefghi" | ||||
|               type="checkbox" | ||||
|             /> | ||||
|             <label | ||||
|               for="checkbox_abdefghi" | ||||
|             > | ||||
|               <div | ||||
|                 class="mx_Checkbox_background" | ||||
|               > | ||||
|                 <div | ||||
|                   class="mx_Checkbox_checkmark" | ||||
|                 /> | ||||
|               </div> | ||||
|             </label> | ||||
|           </span> | ||||
|         </label> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div | ||||
|       class="mx_ManageRestrictedJoinRuleDialog_footer" | ||||
|     > | ||||
|       <div | ||||
|         class="mx_ManageRestrictedJoinRuleDialog_section_info" | ||||
|       > | ||||
|         You're removing all spaces. Access will default to invite only | ||||
|       </div> | ||||
|       <div | ||||
|         class="mx_ManageRestrictedJoinRuleDialog_footer_buttons" | ||||
|       > | ||||
|         <div | ||||
|           class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary_outline" | ||||
|           role="button" | ||||
|           tabindex="0" | ||||
|         > | ||||
|           Cancel | ||||
|         </div> | ||||
|         <div | ||||
|           class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary" | ||||
|           role="button" | ||||
|           tabindex="0" | ||||
|         > | ||||
|           Confirm | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
|   <div | ||||
|     data-focus-guard="true" | ||||
|     style="width: 1px; height: 0px; padding: 0px; overflow: hidden; position: fixed; top: 1px; left: 1px;" | ||||
|     tabindex="0" | ||||
|   /> | ||||
| </DocumentFragment> | ||||
| `; | ||||
| 
 | ||||
| exports[`<ManageRestrictedJoinRuleDialog /> should render empty state 1`] = ` | ||||
| <DocumentFragment> | ||||
|   <div | ||||
|     data-focus-guard="true" | ||||
|     style="width: 1px; height: 0px; padding: 0px; overflow: hidden; position: fixed; top: 1px; left: 1px;" | ||||
|     tabindex="0" | ||||
|   /> | ||||
|   <div | ||||
|     aria-labelledby="mx_BaseDialog_title" | ||||
|     class="mx_ManageRestrictedJoinRuleDialog" | ||||
|     data-focus-lock-disabled="false" | ||||
|     role="dialog" | ||||
|   > | ||||
|     <div | ||||
|       class="mx_Dialog_header mx_Dialog_headerWithCancel" | ||||
|     > | ||||
|       <h2 | ||||
|         class="mx_Heading_h3 mx_Dialog_title" | ||||
|         id="mx_BaseDialog_title" | ||||
|       > | ||||
|         Select spaces | ||||
|       </h2> | ||||
|       <div | ||||
|         aria-label="Close dialog" | ||||
|         class="mx_AccessibleButton mx_Dialog_cancelButton" | ||||
|         role="button" | ||||
|         tabindex="0" | ||||
|       /> | ||||
|     </div> | ||||
|     <p> | ||||
|       <span> | ||||
|         Decide which spaces can access this room. If a space is selected, its members can find and join  | ||||
|         <b> | ||||
|           !roomId:server | ||||
|         </b> | ||||
|         . | ||||
|       </span> | ||||
|     </p> | ||||
|     <div | ||||
|       class="mx_SearchBox mx_textinput" | ||||
|     > | ||||
|       <input | ||||
|         autocomplete="off" | ||||
|         class="mx_textinput_icon mx_textinput_search mx_textinput_icon mx_textinput_search" | ||||
|         data-testid="searchbox-input" | ||||
|         placeholder="Search spaces" | ||||
|         type="text" | ||||
|         value="" | ||||
|       /> | ||||
|       <div | ||||
|         class="mx_AccessibleButton mx_SearchBox_closeButton" | ||||
|         role="button" | ||||
|         tabindex="-1" | ||||
|       /> | ||||
|     </div> | ||||
|     <div | ||||
|       class="mx_AutoHideScrollbar mx_ManageRestrictedJoinRuleDialog_content" | ||||
|       tabindex="-1" | ||||
|     > | ||||
|       <span | ||||
|         class="mx_ManageRestrictedJoinRuleDialog_noResults" | ||||
|       > | ||||
|         No results | ||||
|       </span> | ||||
|     </div> | ||||
|     <div | ||||
|       class="mx_ManageRestrictedJoinRuleDialog_footer" | ||||
|     > | ||||
|       <div | ||||
|         class="mx_ManageRestrictedJoinRuleDialog_section_info" | ||||
|       > | ||||
|         You're removing all spaces. Access will default to invite only | ||||
|       </div> | ||||
|       <div | ||||
|         class="mx_ManageRestrictedJoinRuleDialog_footer_buttons" | ||||
|       > | ||||
|         <div | ||||
|           class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary_outline" | ||||
|           role="button" | ||||
|           tabindex="0" | ||||
|         > | ||||
|           Cancel | ||||
|         </div> | ||||
|         <div | ||||
|           class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary" | ||||
|           role="button" | ||||
|           tabindex="0" | ||||
|         > | ||||
|           Confirm | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
|   <div | ||||
|     data-focus-guard="true" | ||||
|     style="width: 1px; height: 0px; padding: 0px; overflow: hidden; position: fixed; top: 1px; left: 1px;" | ||||
|     tabindex="0" | ||||
|   /> | ||||
| </DocumentFragment> | ||||
| `; | ||||
		Loading…
	
		Reference in New Issue
	
	 Travis Ralston
						Travis Ralston