Wrap inputs in fieldsets in Space visibility settings (#7350)
* use fieldset in space settings > visibility Signed-off-by: Kerry Archibald <kerrya@element.io> * add basic tests for space setttings visibility Signed-off-by: Kerry Archibald <kerrya@element.io> * i18n Signed-off-by: Kerry Archibald <kerrya@element.io> * fix toggle button placement Signed-off-by: Kerry Archibald <kerrya@element.io> * i18n Signed-off-by: Kerry Archibald <kerrya@element.io> * update settings separator color to quinary Signed-off-by: Kerry Archibald <kerrya@element.io>
This commit is contained in:
parent
92ee02fe02
commit
b1066a5699
10 changed files with 431 additions and 54 deletions
|
@ -38,7 +38,7 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
& + .mx_SettingsTab_subheading {
|
& + .mx_SettingsTab_subheading {
|
||||||
border-top: 1px solid $quinary-content;
|
border-top: 1px solid $menu-border-color;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
padding-top: 24px;
|
padding-top: 24px;
|
||||||
}
|
}
|
||||||
|
@ -60,15 +60,6 @@ limitations under the License.
|
||||||
margin-left: 26px;
|
margin-left: 26px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_SettingsTab_showAdvanced {
|
|
||||||
margin: 16px 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_SettingsFlag {
|
|
||||||
margin-top: 24px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_SpaceSettingsDialog_buttons {
|
.mx_SpaceSettingsDialog_buttons {
|
||||||
|
@ -86,6 +77,11 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_AccessibleButton_hasKind {
|
.mx_AccessibleButton_hasKind {
|
||||||
padding: 8px 22px;
|
padding: 8px 22px;
|
||||||
|
|
||||||
|
&.mx_SettingsTab_showAdvanced {
|
||||||
|
margin: 16px 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_TabbedView_tabLabel {
|
.mx_TabbedView_tabLabel {
|
||||||
|
|
|
@ -77,7 +77,7 @@ limitations under the License.
|
||||||
color: $secondary-content;
|
color: $secondary-content;
|
||||||
|
|
||||||
& + .mx_StyledRadioButton {
|
& + .mx_StyledRadioButton {
|
||||||
border-top: 1px solid $menu-border-color;
|
border-top: 1px solid $quinary-content;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,6 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_ProfileSettings_profileForm {
|
.mx_ProfileSettings_profileForm {
|
||||||
@mixin mx_Settings_fullWidthField;
|
@mixin mx_Settings_fullWidthField;
|
||||||
border-bottom: 1px solid $menu-border-color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_ProfileSettings_buttons {
|
.mx_ProfileSettings_buttons {
|
||||||
|
|
|
@ -98,3 +98,7 @@ limitations under the License.
|
||||||
.mx_SettingsTab a {
|
.mx_SettingsTab a {
|
||||||
color: $accent-alt;
|
color: $accent-alt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_SettingsTab_toggleWithDescription {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
|
@ -384,6 +384,7 @@ export default class AliasSettings extends React.Component<IProps, IState> {
|
||||||
return (
|
return (
|
||||||
<div className='mx_AliasSettings'>
|
<div className='mx_AliasSettings'>
|
||||||
<SettingsFieldset
|
<SettingsFieldset
|
||||||
|
data-test-id='published-address-fieldset'
|
||||||
legend={_t("Published Addresses")}
|
legend={_t("Published Addresses")}
|
||||||
description={<>
|
description={<>
|
||||||
{ isSpaceRoom
|
{ isSpaceRoom
|
||||||
|
@ -429,7 +430,9 @@ export default class AliasSettings extends React.Component<IProps, IState> {
|
||||||
placeholder={_t('New published address (e.g. #alias:server)')}
|
placeholder={_t('New published address (e.g. #alias:server)')}
|
||||||
/>
|
/>
|
||||||
</SettingsFieldset>
|
</SettingsFieldset>
|
||||||
<SettingsFieldset legend={_t("Local Addresses")}
|
<SettingsFieldset
|
||||||
|
data-test-id='local-address-fieldset'
|
||||||
|
legend={_t("Local Addresses")}
|
||||||
description={isSpaceRoom
|
description={isSpaceRoom
|
||||||
? _t("Set addresses for this space so users can find this space " +
|
? _t("Set addresses for this space so users can find this space " +
|
||||||
"through your homeserver (%(localDomain)s)", { localDomain })
|
"through your homeserver (%(localDomain)s)", { localDomain })
|
||||||
|
|
|
@ -28,6 +28,7 @@ import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
||||||
import { useLocalEcho } from "../../../hooks/useLocalEcho";
|
import { useLocalEcho } from "../../../hooks/useLocalEcho";
|
||||||
import JoinRuleSettings from "../settings/JoinRuleSettings";
|
import JoinRuleSettings from "../settings/JoinRuleSettings";
|
||||||
import { useRoomState } from "../../../hooks/useRoomState";
|
import { useRoomState } from "../../../hooks/useRoomState";
|
||||||
|
import SettingsFieldset from "../settings/SettingsFieldset";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
matrixClient: MatrixClient;
|
matrixClient: MatrixClient;
|
||||||
|
@ -67,12 +68,16 @@ const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space, closeSettingsFn
|
||||||
|
|
||||||
let advancedSection;
|
let advancedSection;
|
||||||
if (joinRule === JoinRule.Public) {
|
if (joinRule === JoinRule.Public) {
|
||||||
if (showAdvancedSection) {
|
advancedSection = <div>
|
||||||
advancedSection = <>
|
<AccessibleButton
|
||||||
<AccessibleButton onClick={toggleAdvancedSection} kind="link" className="mx_SettingsTab_showAdvanced">
|
data-test-id='toggle-guest-access-btn'
|
||||||
{ _t("Hide advanced") }
|
onClick={toggleAdvancedSection}
|
||||||
|
kind="link"
|
||||||
|
className="mx_SettingsTab_showAdvanced">
|
||||||
|
{ showAdvancedSection ? _t("Hide advanced") : _t("Show advanced") }
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
|
|
||||||
|
{ showAdvancedSection && <div className="mx_SettingsTab_toggleWithDescription">
|
||||||
<LabelledToggleSwitch
|
<LabelledToggleSwitch
|
||||||
value={guestAccessEnabled}
|
value={guestAccessEnabled}
|
||||||
onChange={setGuestAccessEnabled}
|
onChange={setGuestAccessEnabled}
|
||||||
|
@ -84,14 +89,9 @@ const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space, closeSettingsFn
|
||||||
<br />
|
<br />
|
||||||
{ _t("This may be useful for public spaces.") }
|
{ _t("This may be useful for public spaces.") }
|
||||||
</p>
|
</p>
|
||||||
</>;
|
</div>
|
||||||
} else {
|
|
||||||
advancedSection = <>
|
|
||||||
<AccessibleButton onClick={toggleAdvancedSection} kind="link" className="mx_SettingsTab_showAdvanced">
|
|
||||||
{ _t("Show advanced") }
|
|
||||||
</AccessibleButton>
|
|
||||||
</>;
|
|
||||||
}
|
}
|
||||||
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let addressesSection;
|
let addressesSection;
|
||||||
|
@ -111,23 +111,20 @@ const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space, closeSettingsFn
|
||||||
return <div className="mx_SettingsTab">
|
return <div className="mx_SettingsTab">
|
||||||
<div className="mx_SettingsTab_heading">{ _t("Visibility") }</div>
|
<div className="mx_SettingsTab_heading">{ _t("Visibility") }</div>
|
||||||
|
|
||||||
{ error && <div className="mx_SpaceRoomView_errorText">{ error }</div> }
|
{ error && <div data-test-id='space-settings-error' className="mx_SpaceRoomView_errorText">{ error }</div> }
|
||||||
|
|
||||||
<div className="mx_SettingsTab_section">
|
<SettingsFieldset
|
||||||
<div className="mx_SettingsTab_section_caption">
|
data-test-id='access-fieldset'
|
||||||
{ _t("Decide who can view and join %(spaceName)s.", { spaceName: space.name }) }
|
legend={_t("Access")}
|
||||||
</div>
|
description={_t("Decide who can view and join %(spaceName)s.", { spaceName: space.name })}
|
||||||
|
>
|
||||||
<div>
|
|
||||||
<JoinRuleSettings
|
<JoinRuleSettings
|
||||||
room={space}
|
room={space}
|
||||||
onError={() => setError(_t("Failed to update the visibility of this space"))}
|
onError={() => setError(_t("Failed to update the visibility of this space"))}
|
||||||
closeSettingsFn={closeSettingsFn}
|
closeSettingsFn={closeSettingsFn}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
{ advancedSection }
|
{ advancedSection }
|
||||||
|
<div className="mx_SettingsTab_toggleWithDescription">
|
||||||
<LabelledToggleSwitch
|
<LabelledToggleSwitch
|
||||||
value={historyVisibility === HistoryVisibility.WorldReadable}
|
value={historyVisibility === HistoryVisibility.WorldReadable}
|
||||||
onChange={(checked: boolean) => {
|
onChange={(checked: boolean) => {
|
||||||
|
@ -136,9 +133,12 @@ const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space, closeSettingsFn
|
||||||
disabled={!canSetHistoryVisibility}
|
disabled={!canSetHistoryVisibility}
|
||||||
label={_t("Preview Space")}
|
label={_t("Preview Space")}
|
||||||
/>
|
/>
|
||||||
<div>{ _t("Allow people to preview your space before they join.") }</div>
|
<p>
|
||||||
|
{ _t("Allow people to preview your space before they join.") }<br />
|
||||||
<b>{ _t("Recommended for public spaces.") }</b>
|
<b>{ _t("Recommended for public spaces.") }</b>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</SettingsFieldset>
|
||||||
|
|
||||||
{ addressesSection }
|
{ addressesSection }
|
||||||
</div>;
|
</div>;
|
||||||
|
|
|
@ -1143,11 +1143,12 @@
|
||||||
"Failed to update the guest access of this space": "Failed to update the guest access of this space",
|
"Failed to update the guest access of this space": "Failed to update the guest access of this space",
|
||||||
"Failed to update the history visibility of this space": "Failed to update the history visibility of this space",
|
"Failed to update the history visibility of this space": "Failed to update the history visibility of this space",
|
||||||
"Hide advanced": "Hide advanced",
|
"Hide advanced": "Hide advanced",
|
||||||
|
"Show advanced": "Show advanced",
|
||||||
"Enable guest access": "Enable guest access",
|
"Enable guest access": "Enable guest access",
|
||||||
"Guests can join a space without having an account.": "Guests can join a space without having an account.",
|
"Guests can join a space without having an account.": "Guests can join a space without having an account.",
|
||||||
"This may be useful for public spaces.": "This may be useful for public spaces.",
|
"This may be useful for public spaces.": "This may be useful for public spaces.",
|
||||||
"Show advanced": "Show advanced",
|
|
||||||
"Visibility": "Visibility",
|
"Visibility": "Visibility",
|
||||||
|
"Access": "Access",
|
||||||
"Decide who can view and join %(spaceName)s.": "Decide who can view and join %(spaceName)s.",
|
"Decide who can view and join %(spaceName)s.": "Decide who can view and join %(spaceName)s.",
|
||||||
"Failed to update the visibility of this space": "Failed to update the visibility of this space",
|
"Failed to update the visibility of this space": "Failed to update the visibility of this space",
|
||||||
"Preview Space": "Preview Space",
|
"Preview Space": "Preview Space",
|
||||||
|
@ -1580,7 +1581,6 @@
|
||||||
"Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>": "Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>",
|
"Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>": "Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>",
|
||||||
"To link to this room, please add an address.": "To link to this room, please add an address.",
|
"To link to this room, please add an address.": "To link to this room, please add an address.",
|
||||||
"Decide who can join %(roomName)s.": "Decide who can join %(roomName)s.",
|
"Decide who can join %(roomName)s.": "Decide who can join %(roomName)s.",
|
||||||
"Access": "Access",
|
|
||||||
"Failed to update the join rules": "Failed to update the join rules",
|
"Failed to update the join rules": "Failed to update the join rules",
|
||||||
"Unknown failure": "Unknown failure",
|
"Unknown failure": "Unknown failure",
|
||||||
"Are you sure you want to make this encrypted room public?": "Are you sure you want to make this encrypted room public?",
|
"Are you sure you want to make this encrypted room public?": "Are you sure you want to make this encrypted room public?",
|
||||||
|
|
236
test/components/views/spaces/SpaceSettingsVisibilityTab-test.tsx
Normal file
236
test/components/views/spaces/SpaceSettingsVisibilityTab-test.tsx
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
// skinned-sdk should be the first import in most tests
|
||||||
|
import '../../../skinned-sdk';
|
||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
renderIntoDocument,
|
||||||
|
Simulate,
|
||||||
|
} from 'react-dom/test-utils';
|
||||||
|
import { act } from "react-dom/test-utils";
|
||||||
|
import { EventType, MatrixClient, Room } from 'matrix-js-sdk';
|
||||||
|
import { GuestAccess, HistoryVisibility, JoinRule } from 'matrix-js-sdk/src/@types/partials';
|
||||||
|
|
||||||
|
import _SpaceSettingsVisibilityTab from "../../../../src/components/views/spaces/SpaceSettingsVisibilityTab";
|
||||||
|
import { createTestClient, mkEvent, wrapInMatrixClientContext } from '../../../test-utils';
|
||||||
|
import { mkSpace, mockStateEventImplementation } from '../../../utils/test-utils';
|
||||||
|
import { MatrixClientPeg } from '../../../../src/MatrixClientPeg';
|
||||||
|
|
||||||
|
const SpaceSettingsVisibilityTab = wrapInMatrixClientContext(_SpaceSettingsVisibilityTab);
|
||||||
|
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
describe('<SpaceSettingsVisibilityTab />', () => {
|
||||||
|
const mockMatrixClient = createTestClient() as MatrixClient;
|
||||||
|
|
||||||
|
const makeJoinEvent = (rule: JoinRule = JoinRule.Invite) => mkEvent({
|
||||||
|
type: EventType.RoomJoinRules, event: true, content: {
|
||||||
|
join_rule: rule,
|
||||||
|
},
|
||||||
|
} as any);
|
||||||
|
const makeGuestAccessEvent = (rule: GuestAccess = GuestAccess.CanJoin) => mkEvent({
|
||||||
|
type: EventType.RoomGuestAccess, event: true, content: {
|
||||||
|
guest_access: rule,
|
||||||
|
},
|
||||||
|
} as any);
|
||||||
|
const makeHistoryEvent = (rule: HistoryVisibility = HistoryVisibility.Shared) => mkEvent({
|
||||||
|
type: EventType.RoomHistoryVisibility, event: true, content: {
|
||||||
|
history_visibility: rule,
|
||||||
|
},
|
||||||
|
} as any);
|
||||||
|
|
||||||
|
const mockSpaceId = 'mock-space';
|
||||||
|
|
||||||
|
// TODO case for canonical
|
||||||
|
const makeMockSpace = (
|
||||||
|
client: MatrixClient,
|
||||||
|
joinRule: JoinRule = JoinRule.Invite,
|
||||||
|
guestRule: GuestAccess = GuestAccess.CanJoin,
|
||||||
|
historyRule: HistoryVisibility = HistoryVisibility.WorldReadable,
|
||||||
|
): Room => {
|
||||||
|
const events = [
|
||||||
|
makeJoinEvent(joinRule),
|
||||||
|
makeGuestAccessEvent(guestRule),
|
||||||
|
makeHistoryEvent(historyRule),
|
||||||
|
];
|
||||||
|
const space = mkSpace(client, mockSpaceId);
|
||||||
|
const getStateEvents = mockStateEventImplementation(events);
|
||||||
|
space.currentState.getStateEvents.mockImplementation(getStateEvents);
|
||||||
|
space.currentState.mayClientSendStateEvent.mockReturnValue(false);
|
||||||
|
const mockGetJoinRule = jest.fn().mockReturnValue(joinRule);
|
||||||
|
space.getJoinRule = mockGetJoinRule;
|
||||||
|
space.currentState.getJoinRule = mockGetJoinRule;
|
||||||
|
return space as unknown as Room;
|
||||||
|
};
|
||||||
|
const defaultProps = {
|
||||||
|
matrixClient: mockMatrixClient,
|
||||||
|
space: makeMockSpace(mockMatrixClient),
|
||||||
|
closeSettingsFn: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const getComponent = (props = {}) => {
|
||||||
|
const wrapper = renderIntoDocument<HTMLSpanElement>(
|
||||||
|
// wrap in element so renderIntoDocument can render functional component
|
||||||
|
<span>
|
||||||
|
<SpaceSettingsVisibilityTab {...defaultProps} {...props} />
|
||||||
|
</span>,
|
||||||
|
) as HTMLSpanElement;
|
||||||
|
return wrapper.children[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getByTestId = (container: Element, id: string) => container.querySelector(`[data-test-id=${id}]`);
|
||||||
|
const toggleGuestAccessSection = async (component) => {
|
||||||
|
const toggleButton = getByTestId(component, 'toggle-guest-access-btn');
|
||||||
|
await act(async () => {
|
||||||
|
Simulate.click(toggleButton);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const getGuestAccessToggle = component => component.querySelector('[aria-label="Enable guest access"');
|
||||||
|
const getHistoryVisibilityToggle = component => component.querySelector('[aria-label="Preview Space"');
|
||||||
|
const getErrorMessage = component => getByTestId(component, 'space-settings-error')?.textContent;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
(mockMatrixClient.sendStateEvent as jest.Mock).mockClear().mockResolvedValue({});
|
||||||
|
MatrixClientPeg.get = jest.fn().mockReturnValue(mockMatrixClient);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.runAllTimers();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders container', () => {
|
||||||
|
const component = getComponent();
|
||||||
|
expect(component).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('for a private space', () => {
|
||||||
|
const joinRule = JoinRule.Invite;
|
||||||
|
it('does not render addresses section', () => {
|
||||||
|
const space = makeMockSpace(mockMatrixClient, joinRule);
|
||||||
|
const component = getComponent({ space });
|
||||||
|
|
||||||
|
expect(getByTestId(component, 'published-address-fieldset')).toBeFalsy();
|
||||||
|
expect(getByTestId(component, 'local-address-fieldset')).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('for a public space', () => {
|
||||||
|
const joinRule = JoinRule.Public;
|
||||||
|
const guestRule = GuestAccess.CanJoin;
|
||||||
|
const historyRule = HistoryVisibility.Joined;
|
||||||
|
|
||||||
|
describe('Access', () => {
|
||||||
|
it('renders guest access section toggle', async () => {
|
||||||
|
const space = makeMockSpace(mockMatrixClient, joinRule, guestRule);
|
||||||
|
const component = getComponent({ space });
|
||||||
|
|
||||||
|
await toggleGuestAccessSection(component);
|
||||||
|
|
||||||
|
expect(getGuestAccessToggle(component)).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('send guest access event on toggle', async () => {
|
||||||
|
const space = makeMockSpace(mockMatrixClient, joinRule, guestRule);
|
||||||
|
|
||||||
|
const component = getComponent({ space });
|
||||||
|
await toggleGuestAccessSection(component);
|
||||||
|
const guestAccessInput = getGuestAccessToggle(component);
|
||||||
|
|
||||||
|
expect(guestAccessInput.getAttribute('aria-checked')).toEqual("true");
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
Simulate.click(guestAccessInput);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockMatrixClient.sendStateEvent).toHaveBeenCalledWith(
|
||||||
|
mockSpaceId,
|
||||||
|
EventType.RoomGuestAccess,
|
||||||
|
// toggled off
|
||||||
|
{ guest_access: GuestAccess.Forbidden },
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
|
||||||
|
// toggled off
|
||||||
|
expect(guestAccessInput.getAttribute('aria-checked')).toEqual("false");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders error message when update fails', async () => {
|
||||||
|
const space = makeMockSpace(mockMatrixClient, joinRule, guestRule);
|
||||||
|
(mockMatrixClient.sendStateEvent as jest.Mock).mockRejectedValue({});
|
||||||
|
const component = getComponent({ space });
|
||||||
|
await toggleGuestAccessSection(component);
|
||||||
|
await act(async () => {
|
||||||
|
Simulate.click(getGuestAccessToggle(component));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(getErrorMessage(component)).toEqual("Failed to update the guest access of this space");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('disables guest access toggle when setting guest access is not allowed', async () => {
|
||||||
|
const space = makeMockSpace(mockMatrixClient, joinRule, guestRule);
|
||||||
|
(space.currentState.maySendStateEvent as jest.Mock).mockReturnValue(false);
|
||||||
|
const component = getComponent({ space });
|
||||||
|
|
||||||
|
await toggleGuestAccessSection(component);
|
||||||
|
|
||||||
|
expect(getGuestAccessToggle(component).getAttribute('aria-disabled')).toEqual("true");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Preview', () => {
|
||||||
|
it('renders preview space toggle', () => {
|
||||||
|
const space = makeMockSpace(mockMatrixClient, joinRule, guestRule, historyRule);
|
||||||
|
const component = getComponent({ space });
|
||||||
|
|
||||||
|
// toggle off because space settings is != WorldReadable
|
||||||
|
expect(getHistoryVisibilityToggle(component).getAttribute('aria-checked')).toEqual("false");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates history visibility on toggle', async () => {
|
||||||
|
const space = makeMockSpace(mockMatrixClient, joinRule, guestRule, historyRule);
|
||||||
|
const component = getComponent({ space });
|
||||||
|
|
||||||
|
// toggle off because space settings is != WorldReadable
|
||||||
|
expect(getHistoryVisibilityToggle(component).getAttribute('aria-checked')).toEqual("false");
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
Simulate.click(getHistoryVisibilityToggle(component));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockMatrixClient.sendStateEvent).toHaveBeenCalledWith(
|
||||||
|
mockSpaceId,
|
||||||
|
EventType.RoomHistoryVisibility,
|
||||||
|
{ history_visibility: HistoryVisibility.WorldReadable },
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(getHistoryVisibilityToggle(component).getAttribute('aria-checked')).toEqual("true");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders error message when history update fails', async () => {
|
||||||
|
const space = makeMockSpace(mockMatrixClient, joinRule, guestRule, historyRule);
|
||||||
|
(mockMatrixClient.sendStateEvent as jest.Mock).mockRejectedValue({});
|
||||||
|
const component = getComponent({ space });
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
Simulate.click(getHistoryVisibilityToggle(component));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(getErrorMessage(component)).toEqual("Failed to update the history visibility of this space");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('disables room preview toggle when history visability changes are not allowed', () => {
|
||||||
|
const space = makeMockSpace(mockMatrixClient, joinRule, guestRule, historyRule);
|
||||||
|
(space.currentState.maySendStateEvent as jest.Mock).mockReturnValue(false);
|
||||||
|
const component = getComponent({ space });
|
||||||
|
expect(getHistoryVisibilityToggle(component).getAttribute('aria-disabled')).toEqual("true");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders addresses section', () => {
|
||||||
|
const space = makeMockSpace(mockMatrixClient, joinRule, guestRule);
|
||||||
|
const component = getComponent({ space });
|
||||||
|
|
||||||
|
expect(getByTestId(component, 'published-address-fieldset')).toBeTruthy();
|
||||||
|
expect(getByTestId(component, 'local-address-fieldset')).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,133 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`<SpaceSettingsVisibilityTab /> for a public space Access renders guest access section toggle 1`] = `
|
||||||
|
<div
|
||||||
|
aria-checked="true"
|
||||||
|
aria-disabled="false"
|
||||||
|
aria-label="Enable guest access"
|
||||||
|
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled"
|
||||||
|
role="switch"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_ToggleSwitch_ball"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`<SpaceSettingsVisibilityTab /> renders container 1`] = `
|
||||||
|
<div
|
||||||
|
class="mx_SettingsTab"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_SettingsTab_heading"
|
||||||
|
>
|
||||||
|
Visibility
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<fieldset
|
||||||
|
class="mx_SettingsFieldset"
|
||||||
|
data-test-id="access-fieldset"
|
||||||
|
>
|
||||||
|
<legend
|
||||||
|
class="mx_SettingsFieldset_legend"
|
||||||
|
>
|
||||||
|
Access
|
||||||
|
</legend>
|
||||||
|
<div
|
||||||
|
class="mx_SettingsFieldset_description"
|
||||||
|
>
|
||||||
|
Decide who can view and join mock-space.
|
||||||
|
</div>
|
||||||
|
<label
|
||||||
|
class="mx_StyledRadioButton mx_JoinRuleSettings_radioButton mx_StyledRadioButton_disabled mx_StyledRadioButton_checked"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-describedby="joinRule-invite-description"
|
||||||
|
checked=""
|
||||||
|
disabled=""
|
||||||
|
id="joinRule-invite"
|
||||||
|
name="joinRule"
|
||||||
|
type="radio"
|
||||||
|
value="invite"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<div />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_StyledRadioButton_content"
|
||||||
|
>
|
||||||
|
Private (invite only)
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_StyledRadioButton_spacer"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<span
|
||||||
|
id="joinRule-invite-description"
|
||||||
|
>
|
||||||
|
Only invited people can join.
|
||||||
|
</span>
|
||||||
|
<label
|
||||||
|
class="mx_StyledRadioButton mx_JoinRuleSettings_radioButton mx_StyledRadioButton_disabled"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-describedby="joinRule-public-description"
|
||||||
|
disabled=""
|
||||||
|
id="joinRule-public"
|
||||||
|
name="joinRule"
|
||||||
|
type="radio"
|
||||||
|
value="public"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<div />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_StyledRadioButton_content"
|
||||||
|
>
|
||||||
|
Public
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_StyledRadioButton_spacer"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<span
|
||||||
|
id="joinRule-public-description"
|
||||||
|
>
|
||||||
|
Anyone can find and join.
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
class="mx_SettingsTab_toggleWithDescription"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_SettingsFlag "
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="mx_SettingsFlag_label"
|
||||||
|
>
|
||||||
|
Preview Space
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
aria-checked="true"
|
||||||
|
aria-disabled="false"
|
||||||
|
aria-label="Preview Space"
|
||||||
|
class="mx_AccessibleButton mx_ToggleSwitch mx_ToggleSwitch_on mx_ToggleSwitch_enabled"
|
||||||
|
role="switch"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_ToggleSwitch_ball"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
Allow people to preview your space before they join.
|
||||||
|
<br />
|
||||||
|
<b>
|
||||||
|
Recommended for public spaces.
|
||||||
|
</b>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
`;
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||||
import EventEmitter from "events";
|
import EventEmitter from "events";
|
||||||
import ShallowRenderer from 'react-test-renderer/shallow';
|
import ShallowRenderer from 'react-test-renderer/shallow';
|
||||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
import { JoinRule } from 'matrix-js-sdk/src/@types/partials';
|
||||||
|
|
||||||
import { MatrixClientPeg as peg } from '../src/MatrixClientPeg';
|
import { MatrixClientPeg as peg } from '../src/MatrixClientPeg';
|
||||||
import dis from '../src/dispatcher/dispatcher';
|
import dis from '../src/dispatcher/dispatcher';
|
||||||
|
@ -88,6 +89,7 @@ export function createTestClient() {
|
||||||
setRoomAccountData: jest.fn(),
|
setRoomAccountData: jest.fn(),
|
||||||
sendTyping: jest.fn().mockResolvedValue({}),
|
sendTyping: jest.fn().mockResolvedValue({}),
|
||||||
sendMessage: () => jest.fn().mockResolvedValue({}),
|
sendMessage: () => jest.fn().mockResolvedValue({}),
|
||||||
|
sendStateEvent: jest.fn().mockResolvedValue(),
|
||||||
getSyncState: () => "SYNCING",
|
getSyncState: () => "SYNCING",
|
||||||
generateClientSecret: () => "t35tcl1Ent5ECr3T",
|
generateClientSecret: () => "t35tcl1Ent5ECr3T",
|
||||||
isGuest: () => false,
|
isGuest: () => false,
|
||||||
|
@ -113,6 +115,7 @@ export function createTestClient() {
|
||||||
registerWithIdentityServer: jest.fn().mockResolvedValue({}),
|
registerWithIdentityServer: jest.fn().mockResolvedValue({}),
|
||||||
getIdentityAccount: jest.fn().mockResolvedValue({}),
|
getIdentityAccount: jest.fn().mockResolvedValue({}),
|
||||||
getTerms: jest.fn().mockResolvedValueOnce(),
|
getTerms: jest.fn().mockResolvedValueOnce(),
|
||||||
|
doesServerSupportUnstableFeature: jest.fn().mockResolvedValue(),
|
||||||
getPushRules: jest.fn().mockResolvedValue(),
|
getPushRules: jest.fn().mockResolvedValue(),
|
||||||
getPushers: jest.fn().mockResolvedValue({ pushers: [] }),
|
getPushers: jest.fn().mockResolvedValue({ pushers: [] }),
|
||||||
getThreePids: jest.fn().mockResolvedValue({ threepids: [] }),
|
getThreePids: jest.fn().mockResolvedValue({ threepids: [] }),
|
||||||
|
@ -154,6 +157,7 @@ export function mkEvent(opts) {
|
||||||
"m.room.name", "m.room.topic", "m.room.create", "m.room.join_rules",
|
"m.room.name", "m.room.topic", "m.room.create", "m.room.join_rules",
|
||||||
"m.room.power_levels", "m.room.topic", "m.room.history_visibility",
|
"m.room.power_levels", "m.room.topic", "m.room.history_visibility",
|
||||||
"m.room.encryption", "m.room.member", "com.example.state",
|
"m.room.encryption", "m.room.member", "com.example.state",
|
||||||
|
"m.room.guest_access",
|
||||||
].indexOf(opts.type) !== -1) {
|
].indexOf(opts.type) !== -1) {
|
||||||
event.state_key = "";
|
event.state_key = "";
|
||||||
}
|
}
|
||||||
|
@ -281,6 +285,8 @@ export function mkStubRoom(roomId = null, name, client) {
|
||||||
maySendStateEvent: jest.fn().mockReturnValue(true),
|
maySendStateEvent: jest.fn().mockReturnValue(true),
|
||||||
maySendEvent: jest.fn().mockReturnValue(true),
|
maySendEvent: jest.fn().mockReturnValue(true),
|
||||||
members: [],
|
members: [],
|
||||||
|
getJoinRule: jest.fn().mockReturnValue(JoinRule.Invite),
|
||||||
|
on: jest.fn(),
|
||||||
},
|
},
|
||||||
tags: {},
|
tags: {},
|
||||||
setBlacklistUnverifiedDevices: jest.fn(),
|
setBlacklistUnverifiedDevices: jest.fn(),
|
||||||
|
|
Loading…
Reference in a new issue