Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
b57c9c579c
5 changed files with 339 additions and 101 deletions
|
@ -175,4 +175,4 @@ class MatrixClientPeg {
|
||||||
if (!global.mxMatrixClientPeg) {
|
if (!global.mxMatrixClientPeg) {
|
||||||
global.mxMatrixClientPeg = new MatrixClientPeg();
|
global.mxMatrixClientPeg = new MatrixClientPeg();
|
||||||
}
|
}
|
||||||
module.exports = global.mxMatrixClientPeg;
|
export default global.mxMatrixClientPeg;
|
||||||
|
|
|
@ -42,6 +42,9 @@ module.exports = React.createClass({
|
||||||
// should the user be able to change the value? false by default.
|
// should the user be able to change the value? false by default.
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
|
|
||||||
|
// Optional key to pass as the second argument to `onChange`
|
||||||
|
powerLevelKey: PropTypes.string,
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
|
@ -84,17 +87,17 @@ module.exports = React.createClass({
|
||||||
onSelectChange: function(event) {
|
onSelectChange: function(event) {
|
||||||
this.setState({ custom: event.target.value === "SELECT_VALUE_CUSTOM" });
|
this.setState({ custom: event.target.value === "SELECT_VALUE_CUSTOM" });
|
||||||
if (event.target.value !== "SELECT_VALUE_CUSTOM") {
|
if (event.target.value !== "SELECT_VALUE_CUSTOM") {
|
||||||
this.props.onChange(event.target.value);
|
this.props.onChange(event.target.value, this.props.powerLevelKey);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onCustomBlur: function(event) {
|
onCustomBlur: function(event) {
|
||||||
this.props.onChange(parseInt(this.refs.custom.value));
|
this.props.onChange(parseInt(this.refs.custom.value), this.props.powerLevelKey);
|
||||||
},
|
},
|
||||||
|
|
||||||
onCustomKeyDown: function(event) {
|
onCustomKeyDown: function(event) {
|
||||||
if (event.key == "Enter") {
|
if (event.key == "Enter") {
|
||||||
this.props.onChange(parseInt(this.refs.custom.value));
|
this.props.onChange(parseInt(this.refs.custom.value), this.props.powerLevelKey);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,6 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
room: PropTypes.object.isRequired,
|
room: PropTypes.object.isRequired,
|
||||||
onSaveClick: PropTypes.func,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
|
@ -132,7 +131,8 @@ module.exports = React.createClass({
|
||||||
join_rule: this._yankValueFromEvent("m.room.join_rules", "join_rule"),
|
join_rule: this._yankValueFromEvent("m.room.join_rules", "join_rule"),
|
||||||
history_visibility: this._yankValueFromEvent("m.room.history_visibility", "history_visibility"),
|
history_visibility: this._yankValueFromEvent("m.room.history_visibility", "history_visibility"),
|
||||||
guest_access: this._yankValueFromEvent("m.room.guest_access", "guest_access"),
|
guest_access: this._yankValueFromEvent("m.room.guest_access", "guest_access"),
|
||||||
power_levels_changed: false,
|
powerLevels: this._yankContentFromEvent("m.room.power_levels", {}),
|
||||||
|
powerLevelsChanged: false,
|
||||||
tags_changed: false,
|
tags_changed: false,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
// isRoomPublished is loaded async in componentWillMount so when the component
|
// isRoomPublished is loaded async in componentWillMount so when the component
|
||||||
|
@ -151,7 +151,7 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
MatrixClientPeg.get().getRoomDirectoryVisibility(
|
MatrixClientPeg.get().getRoomDirectoryVisibility(
|
||||||
this.props.room.roomId,
|
this.props.room.roomId,
|
||||||
).done((result) => {
|
).done((result = {}) => {
|
||||||
this.setState({ isRoomPublished: result.visibility === "public" });
|
this.setState({ isRoomPublished: result.visibility === "public" });
|
||||||
this._originalIsRoomPublished = result.visibility === "public";
|
this._originalIsRoomPublished = result.visibility === "public";
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
|
@ -272,8 +272,8 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
|
|
||||||
// power levels
|
// power levels
|
||||||
const powerLevels = this._getPowerLevels();
|
const powerLevels = this.state.powerLevels;
|
||||||
if (powerLevels) {
|
if (this.state.powerLevelsChanged) {
|
||||||
promises.push(MatrixClientPeg.get().sendStateEvent(
|
promises.push(MatrixClientPeg.get().sendStateEvent(
|
||||||
roomId, "m.room.power_levels", powerLevels, "",
|
roomId, "m.room.power_levels", powerLevels, "",
|
||||||
));
|
));
|
||||||
|
@ -384,36 +384,32 @@ module.exports = React.createClass({
|
||||||
return strA !== strB;
|
return strA !== strB;
|
||||||
},
|
},
|
||||||
|
|
||||||
_getPowerLevels: function() {
|
onPowerLevelsChanged: function(value, powerLevelKey) {
|
||||||
if (!this.state.power_levels_changed) return undefined;
|
const powerLevels = Object.assign({}, this.state.powerLevels);
|
||||||
|
const eventsLevelPrefix = "event_levels_";
|
||||||
|
|
||||||
let powerLevels = this.props.room.currentState.getStateEvents('m.room.power_levels', '');
|
value = parseInt(value);
|
||||||
powerLevels = powerLevels ? powerLevels.getContent() : {};
|
|
||||||
|
|
||||||
for (const key of Object.keys(this.refs).filter((k) => k.startsWith("event_levels_"))) {
|
if (powerLevelKey.startsWith(eventsLevelPrefix)) {
|
||||||
const eventType = key.substring("event_levels_".length);
|
// deep copy "events" object, Object.assign itself won't deep copy
|
||||||
powerLevels.events[eventType] = parseInt(this.refs[key].getValue());
|
powerLevels["events"] = Object.assign({}, this.state.powerLevels["events"] || {});
|
||||||
|
powerLevels["events"][powerLevelKey.slice(eventsLevelPrefix.length)] = value;
|
||||||
|
} else {
|
||||||
|
powerLevels[powerLevelKey] = value;
|
||||||
}
|
}
|
||||||
|
this.setState({
|
||||||
const newPowerLevels = {
|
powerLevels,
|
||||||
ban: parseInt(this.refs.ban.getValue()),
|
powerLevelsChanged: true,
|
||||||
kick: parseInt(this.refs.kick.getValue()),
|
});
|
||||||
redact: parseInt(this.refs.redact.getValue()),
|
|
||||||
invite: parseInt(this.refs.invite.getValue()),
|
|
||||||
events_default: parseInt(this.refs.events_default.getValue()),
|
|
||||||
state_default: parseInt(this.refs.state_default.getValue()),
|
|
||||||
users_default: parseInt(this.refs.users_default.getValue()),
|
|
||||||
users: powerLevels.users,
|
|
||||||
events: powerLevels.events,
|
|
||||||
};
|
|
||||||
|
|
||||||
return newPowerLevels;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onPowerLevelsChanged: function() {
|
_yankContentFromEvent: function(stateEventType, defaultValue) {
|
||||||
this.setState({
|
// E.g.("m.room.name") would yank the content of "m.room.name"
|
||||||
power_levels_changed: true,
|
const event = this.props.room.currentState.getStateEvents(stateEventType, '');
|
||||||
});
|
if (!event) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
return event.getContent() || defaultValue;
|
||||||
},
|
},
|
||||||
|
|
||||||
_yankValueFromEvent: function(stateEventType, keyName, defaultValue) {
|
_yankValueFromEvent: function(stateEventType, keyName, defaultValue) {
|
||||||
|
@ -633,29 +629,61 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
const roomState = this.props.room.currentState;
|
const roomState = this.props.room.currentState;
|
||||||
const user_id = cli.credentials.userId;
|
const myUserId = cli.credentials.userId;
|
||||||
|
|
||||||
const power_level_event = roomState.getStateEvents('m.room.power_levels', '');
|
const powerLevels = this.state.powerLevels;
|
||||||
const power_levels = power_level_event ? power_level_event.getContent() : {};
|
const eventsLevels = powerLevels.events || {};
|
||||||
const events_levels = power_levels.events || {};
|
const userLevels = powerLevels.users || {};
|
||||||
const user_levels = power_levels.users || {};
|
|
||||||
|
|
||||||
const ban_level = parseIntWithDefault(power_levels.ban, 50);
|
const powerLevelDescriptors = {
|
||||||
const kick_level = parseIntWithDefault(power_levels.kick, 50);
|
users_default: {
|
||||||
const redact_level = parseIntWithDefault(power_levels.redact, 50);
|
desc: _t('The default role for new room members is'),
|
||||||
const invite_level = parseIntWithDefault(power_levels.invite, 50);
|
defaultValue: 0,
|
||||||
const send_level = parseIntWithDefault(power_levels.events_default, 0);
|
},
|
||||||
const state_level = power_level_event ? parseIntWithDefault(power_levels.state_default, 50) : 0;
|
events_default: {
|
||||||
const default_user_level = parseIntWithDefault(power_levels.users_default, 0);
|
desc: _t('To send messages, you must be a'),
|
||||||
|
defaultValue: 0,
|
||||||
|
},
|
||||||
|
invite: {
|
||||||
|
desc: _t('To invite users into the room, you must be a'),
|
||||||
|
defaultValue: 50,
|
||||||
|
},
|
||||||
|
state_default: {
|
||||||
|
desc: _t('To configure the room, you must be a'),
|
||||||
|
defaultValue: 50,
|
||||||
|
},
|
||||||
|
kick: {
|
||||||
|
desc: _t('To kick users, you must be a'),
|
||||||
|
defaultValue: 50,
|
||||||
|
},
|
||||||
|
ban: {
|
||||||
|
desc: _t('To ban users, you must be a'),
|
||||||
|
defaultValue: 50,
|
||||||
|
},
|
||||||
|
redact: {
|
||||||
|
desc: _t('To remove other users\' messages, you must be a'),
|
||||||
|
defaultValue: 50,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
this._populateDefaultPlEvents(events_levels, state_level, send_level);
|
const banLevel = parseIntWithDefault(powerLevels.ban, powerLevelDescriptors.ban.defaultValue);
|
||||||
|
const defaultUserLevel = parseIntWithDefault(
|
||||||
|
powerLevels.users_default,
|
||||||
|
powerLevelDescriptors.users_default.defaultValue,
|
||||||
|
);
|
||||||
|
|
||||||
let current_user_level = user_levels[user_id];
|
this._populateDefaultPlEvents(
|
||||||
if (current_user_level === undefined) {
|
eventsLevels,
|
||||||
current_user_level = default_user_level;
|
parseIntWithDefault(powerLevels.state_default, powerLevelDescriptors.state_default.defaultValue),
|
||||||
|
parseIntWithDefault(powerLevels.events_default, powerLevelDescriptors.events_default.defaultValue),
|
||||||
|
);
|
||||||
|
|
||||||
|
let currentUserLevel = userLevels[myUserId];
|
||||||
|
if (currentUserLevel === undefined) {
|
||||||
|
currentUserLevel = defaultUserLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
const can_change_levels = roomState.mayClientSendStateEvent("m.room.power_levels", cli);
|
const canChangeLevels = roomState.mayClientSendStateEvent("m.room.power_levels", cli);
|
||||||
|
|
||||||
const canSetTag = !cli.isGuest();
|
const canSetTag = !cli.isGuest();
|
||||||
|
|
||||||
|
@ -668,15 +696,16 @@ module.exports = React.createClass({
|
||||||
/>;
|
/>;
|
||||||
|
|
||||||
let userLevelsSection;
|
let userLevelsSection;
|
||||||
if (Object.keys(user_levels).length) {
|
if (Object.keys(userLevels).length) {
|
||||||
userLevelsSection =
|
userLevelsSection =
|
||||||
<div>
|
<div>
|
||||||
<h3>{ _t('Privileged Users') }</h3>
|
<h3>{ _t('Privileged Users') }</h3>
|
||||||
<ul className="mx_RoomSettings_userLevels">
|
<ul className="mx_RoomSettings_userLevels">
|
||||||
{ Object.keys(user_levels).map(function(user, i) {
|
{ Object.keys(userLevels).map(function(user, i) {
|
||||||
return (
|
return (
|
||||||
<li className="mx_RoomSettings_userLevel" key={user}>
|
<li className="mx_RoomSettings_userLevel" key={user}>
|
||||||
{ _t("%(user)s is a", {user: user}) } <PowerSelector value={user_levels[user]} disabled={true} />
|
{ _t("%(user)s is a", {user: user}) }
|
||||||
|
<PowerSelector value={userLevels[user]} disabled={true} />
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
}) }
|
}) }
|
||||||
|
@ -689,7 +718,7 @@ module.exports = React.createClass({
|
||||||
const banned = this.props.room.getMembersWithMembership("ban");
|
const banned = this.props.room.getMembersWithMembership("ban");
|
||||||
let bannedUsersSection;
|
let bannedUsersSection;
|
||||||
if (banned.length) {
|
if (banned.length) {
|
||||||
const canBanUsers = current_user_level >= ban_level;
|
const canBanUsers = currentUserLevel >= banLevel;
|
||||||
bannedUsersSection =
|
bannedUsersSection =
|
||||||
<div>
|
<div>
|
||||||
<h3>{ _t('Banned users') }</h3>
|
<h3>{ _t('Banned users') }</h3>
|
||||||
|
@ -711,13 +740,13 @@ module.exports = React.createClass({
|
||||||
if (this._yankValueFromEvent("m.room.create", "m.federate", true) === false) {
|
if (this._yankValueFromEvent("m.room.create", "m.federate", true) === false) {
|
||||||
unfederatableSection = (
|
unfederatableSection = (
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
<div className="mx_RoomSettings_powerLevel">
|
||||||
{ _t('This room is not accessible by remote Matrix servers') }.
|
{ _t('This room is not accessible by remote Matrix servers') }.
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let leaveButton = null;
|
let leaveButton = null;
|
||||||
const myMember = this.props.room.getMember(user_id);
|
const myMember = this.props.room.getMember(myUserId);
|
||||||
if (myMember) {
|
if (myMember) {
|
||||||
if (myMember.membership === "join") {
|
if (myMember.membership === "join") {
|
||||||
leaveButton = (
|
leaveButton = (
|
||||||
|
@ -800,6 +829,50 @@ module.exports = React.createClass({
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const powerSelectors = Object.keys(powerLevelDescriptors).map((key, index) => {
|
||||||
|
const descriptor = powerLevelDescriptors[key];
|
||||||
|
|
||||||
|
const value = parseIntWithDefault(powerLevels[key], descriptor.defaultValue);
|
||||||
|
return <div key={index} className="mx_RoomSettings_powerLevel">
|
||||||
|
<span className="mx_RoomSettings_powerLevelKey">
|
||||||
|
{ descriptor.desc }
|
||||||
|
</span>
|
||||||
|
<PowerSelector
|
||||||
|
value={value}
|
||||||
|
usersDefault={defaultUserLevel}
|
||||||
|
controlled={false}
|
||||||
|
disabled={!canChangeLevels || currentUserLevel < value}
|
||||||
|
powerLevelKey={key} // Will be sent as the second parameter to `onChange`
|
||||||
|
onChange={this.onPowerLevelsChanged}
|
||||||
|
/>
|
||||||
|
</div>;
|
||||||
|
});
|
||||||
|
|
||||||
|
const eventPowerSelectors = Object.keys(eventsLevels).map(function(eventType, i) {
|
||||||
|
let label = plEventsToLabels[eventType];
|
||||||
|
if (label) {
|
||||||
|
label = _t(label);
|
||||||
|
} else {
|
||||||
|
label = _t(
|
||||||
|
"To send events of type <eventType/>, you must be a", {},
|
||||||
|
{ 'eventType': <code>{ eventType }</code> },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="mx_RoomSettings_powerLevel" key={eventType}>
|
||||||
|
<span className="mx_RoomSettings_powerLevelKey">{ label } </span>
|
||||||
|
<PowerSelector
|
||||||
|
value={eventsLevels[eventType]}
|
||||||
|
usersDefault={defaultUserLevel}
|
||||||
|
controlled={false}
|
||||||
|
disabled={!canChangeLevels || currentUserLevel < eventsLevels[eventType]}
|
||||||
|
powerLevelKey={"event_levels_" + eventType}
|
||||||
|
onChange={self.onPowerLevelsChanged}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_RoomSettings">
|
<div className="mx_RoomSettings">
|
||||||
|
|
||||||
|
@ -899,49 +972,9 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
<h3>{ _t('Permissions') }</h3>
|
<h3>{ _t('Permissions') }</h3>
|
||||||
<div className="mx_RoomSettings_powerLevels mx_RoomSettings_settings">
|
<div className="mx_RoomSettings_powerLevels mx_RoomSettings_settings">
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
{ powerSelectors }
|
||||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('The default role for new room members is') } </span>
|
{ eventPowerSelectors }
|
||||||
<PowerSelector ref="users_default" value={default_user_level} usersDefault={default_user_level} controlled={false} disabled={!can_change_levels || current_user_level < default_user_level} onChange={this.onPowerLevelsChanged} />
|
{ unfederatableSection }
|
||||||
</div>
|
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
|
||||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To send messages, you must be a') } </span>
|
|
||||||
<PowerSelector ref="events_default" value={send_level} usersDefault={default_user_level} controlled={false} disabled={!can_change_levels || current_user_level < send_level} onChange={this.onPowerLevelsChanged} />
|
|
||||||
</div>
|
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
|
||||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To invite users into the room, you must be a') } </span>
|
|
||||||
<PowerSelector ref="invite" value={invite_level} usersDefault={default_user_level} controlled={false} disabled={!can_change_levels || current_user_level < invite_level} onChange={this.onPowerLevelsChanged} />
|
|
||||||
</div>
|
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
|
||||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To configure the room, you must be a') } </span>
|
|
||||||
<PowerSelector ref="state_default" value={state_level} usersDefault={default_user_level} controlled={false} disabled={!can_change_levels || current_user_level < state_level} onChange={this.onPowerLevelsChanged} />
|
|
||||||
</div>
|
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
|
||||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To kick users, you must be a') } </span>
|
|
||||||
<PowerSelector ref="kick" value={kick_level} usersDefault={default_user_level} controlled={false} disabled={!can_change_levels || current_user_level < kick_level} onChange={this.onPowerLevelsChanged} />
|
|
||||||
</div>
|
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
|
||||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To ban users, you must be a') } </span>
|
|
||||||
<PowerSelector ref="ban" value={ban_level} usersDefault={default_user_level} controlled={false} disabled={!can_change_levels || current_user_level < ban_level} onChange={this.onPowerLevelsChanged} />
|
|
||||||
</div>
|
|
||||||
<div className="mx_RoomSettings_powerLevel">
|
|
||||||
<span className="mx_RoomSettings_powerLevelKey">{ _t('To remove other users\' messages, you must be a') } </span>
|
|
||||||
<PowerSelector ref="redact" value={redact_level} usersDefault={default_user_level} controlled={false} disabled={!can_change_levels || current_user_level < redact_level} onChange={this.onPowerLevelsChanged} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{ Object.keys(events_levels).map(function(event_type, i) {
|
|
||||||
let label = plEventsToLabels[event_type];
|
|
||||||
if (label) label = _t(label);
|
|
||||||
else label = _t("To send events of type <eventType/>, you must be a", {}, { 'eventType': <code>{ event_type }</code> });
|
|
||||||
return (
|
|
||||||
<div className="mx_RoomSettings_powerLevel" key={event_type}>
|
|
||||||
<span className="mx_RoomSettings_powerLevelKey">{ label } </span>
|
|
||||||
<PowerSelector ref={"event_levels_"+event_type} value={events_levels[event_type]} usersDefault={default_user_level} onChange={self.onPowerLevelsChanged}
|
|
||||||
controlled={false} disabled={!can_change_levels || current_user_level < events_levels[event_type]} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}) }
|
|
||||||
|
|
||||||
{ unfederatableSection }
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ userLevelsSection }
|
{ userLevelsSection }
|
||||||
|
|
190
test/components/views/rooms/RoomSettings-test.js
Normal file
190
test/components/views/rooms/RoomSettings-test.js
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import expect, {createSpy} from 'expect';
|
||||||
|
import Promise from 'bluebird';
|
||||||
|
import * as testUtils from '../../../test-utils';
|
||||||
|
import sdk from 'matrix-react-sdk';
|
||||||
|
const WrappedRoomSettings = testUtils.wrapInMatrixClientContext(sdk.getComponent('views.rooms.RoomSettings'));
|
||||||
|
import MatrixClientPeg from '../../../../src/MatrixClientPeg';
|
||||||
|
import SettingsStore from '../../../../src/settings/SettingsStore';
|
||||||
|
|
||||||
|
|
||||||
|
describe('RoomSettings', () => {
|
||||||
|
let parentDiv = null;
|
||||||
|
let sandbox = null;
|
||||||
|
let client = null;
|
||||||
|
let roomSettings = null;
|
||||||
|
const room = testUtils.mkStubRoom('!DdJkzRliezrwpNebLk:matrix.org');
|
||||||
|
|
||||||
|
function expectSentStateEvent(roomId, eventType, expectedEventContent) {
|
||||||
|
let found = false;
|
||||||
|
for (const call of client.sendStateEvent.calls) {
|
||||||
|
const [
|
||||||
|
actualRoomId,
|
||||||
|
actualEventType,
|
||||||
|
actualEventContent,
|
||||||
|
] = call.arguments.slice(0, 3);
|
||||||
|
|
||||||
|
if (roomId === actualRoomId && actualEventType === eventType) {
|
||||||
|
expect(actualEventContent).toEqual(expectedEventContent);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(found).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(function(done) {
|
||||||
|
testUtils.beforeEach(this);
|
||||||
|
sandbox = testUtils.stubClient();
|
||||||
|
client = MatrixClientPeg.get();
|
||||||
|
client.credentials = {userId: '@me:domain.com'};
|
||||||
|
|
||||||
|
client.setRoomName = createSpy().andReturn(Promise.resolve());
|
||||||
|
client.setRoomTopic = createSpy().andReturn(Promise.resolve());
|
||||||
|
client.setRoomDirectoryVisibility = createSpy().andReturn(Promise.resolve());
|
||||||
|
|
||||||
|
// Covers any room state event (e.g. name, avatar, topic)
|
||||||
|
client.sendStateEvent = createSpy().andReturn(Promise.resolve());
|
||||||
|
|
||||||
|
// Covers room tagging
|
||||||
|
client.setRoomTag = createSpy().andReturn(Promise.resolve());
|
||||||
|
client.deleteRoomTag = createSpy().andReturn(Promise.resolve());
|
||||||
|
|
||||||
|
// Covers any setting in the SettingsStore
|
||||||
|
// (including local client settings not stored via matrix)
|
||||||
|
SettingsStore.setValue = createSpy().andReturn(Promise.resolve());
|
||||||
|
|
||||||
|
parentDiv = document.createElement('div');
|
||||||
|
document.body.appendChild(parentDiv);
|
||||||
|
|
||||||
|
const gatherWrappedRef = (r) => {roomSettings = r;};
|
||||||
|
|
||||||
|
// get use wrappedRef because we're using wrapInMatrixClientContext
|
||||||
|
ReactDOM.render(
|
||||||
|
<WrappedRoomSettings
|
||||||
|
wrappedRef={gatherWrappedRef}
|
||||||
|
room={room}
|
||||||
|
/>,
|
||||||
|
parentDiv,
|
||||||
|
done,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach((done) => {
|
||||||
|
if (parentDiv) {
|
||||||
|
ReactDOM.unmountComponentAtNode(parentDiv);
|
||||||
|
parentDiv.remove();
|
||||||
|
parentDiv = null;
|
||||||
|
}
|
||||||
|
sandbox.restore();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set when no setting is changed', (done) => {
|
||||||
|
roomSettings.save().then(() => {
|
||||||
|
expect(client.sendStateEvent).toNotHaveBeenCalled();
|
||||||
|
expect(client.setRoomTag).toNotHaveBeenCalled();
|
||||||
|
expect(client.deleteRoomTag).toNotHaveBeenCalled();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// XXX: Apparently we do call SettingsStore.setValue
|
||||||
|
xit('should not settings via the SettingsStore when no setting is changed', (done) => {
|
||||||
|
roomSettings.save().then(() => {
|
||||||
|
expect(SettingsStore.setValue).toNotHaveBeenCalled();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set room name when it has changed', (done) => {
|
||||||
|
const name = "My Room Name";
|
||||||
|
roomSettings.setName(name);
|
||||||
|
|
||||||
|
roomSettings.save().then(() => {
|
||||||
|
expect(client.setRoomName.calls[0].arguments.slice(0, 2))
|
||||||
|
.toEqual(['!DdJkzRliezrwpNebLk:matrix.org', name]);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set room topic when it has changed', (done) => {
|
||||||
|
const topic = "this is a topic";
|
||||||
|
roomSettings.setTopic(topic);
|
||||||
|
|
||||||
|
roomSettings.save().then(() => {
|
||||||
|
expect(client.setRoomTopic.calls[0].arguments.slice(0, 2))
|
||||||
|
.toEqual(['!DdJkzRliezrwpNebLk:matrix.org', topic]);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set history visibility when it has changed', (done) => {
|
||||||
|
const historyVisibility = "translucent";
|
||||||
|
roomSettings.setState({
|
||||||
|
history_visibility: historyVisibility,
|
||||||
|
});
|
||||||
|
|
||||||
|
roomSettings.save().then(() => {
|
||||||
|
expectSentStateEvent(
|
||||||
|
"!DdJkzRliezrwpNebLk:matrix.org",
|
||||||
|
"m.room.history_visibility", {history_visibility: historyVisibility},
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// XXX: Can't test this because we `getRoomDirectoryVisibility` in `componentWillMount`
|
||||||
|
xit('should set room directory publicity when set to true', (done) => {
|
||||||
|
const isRoomPublished = true;
|
||||||
|
roomSettings.setState({
|
||||||
|
isRoomPublished,
|
||||||
|
}, () => {
|
||||||
|
roomSettings.save().then(() => {
|
||||||
|
expect(client.setRoomDirectoryVisibility.calls[0].arguments.slice(0, 2))
|
||||||
|
.toEqual("!DdJkzRliezrwpNebLk:matrix.org", isRoomPublished ? "public" : "private");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set power levels when changed', (done) => {
|
||||||
|
roomSettings.onPowerLevelsChanged(42, "invite");
|
||||||
|
|
||||||
|
roomSettings.save().then(() => {
|
||||||
|
expectSentStateEvent(
|
||||||
|
"!DdJkzRliezrwpNebLk:matrix.org",
|
||||||
|
"m.room.power_levels", { invite: 42 },
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set event power levels when changed', (done) => {
|
||||||
|
roomSettings.onPowerLevelsChanged(42, "event_levels_m.room.message");
|
||||||
|
|
||||||
|
roomSettings.save().then(() => {
|
||||||
|
// We expect all state events to be set to the state_default (50)
|
||||||
|
// See powerLevelDescriptors in RoomSettings
|
||||||
|
expectSentStateEvent(
|
||||||
|
"!DdJkzRliezrwpNebLk:matrix.org",
|
||||||
|
"m.room.power_levels", {
|
||||||
|
events: {
|
||||||
|
'm.room.message': 42,
|
||||||
|
'm.room.avatar': 50,
|
||||||
|
'm.room.name': 50,
|
||||||
|
'm.room.canonical_alias': 50,
|
||||||
|
'm.room.history_visibility': 50,
|
||||||
|
'm.room.power_levels': 50,
|
||||||
|
'm.room.topic': 50,
|
||||||
|
'im.vector.modular.widgets': 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -68,6 +68,8 @@ export function createTestClient() {
|
||||||
return {
|
return {
|
||||||
getHomeserverUrl: sinon.stub(),
|
getHomeserverUrl: sinon.stub(),
|
||||||
getIdentityServerUrl: sinon.stub(),
|
getIdentityServerUrl: sinon.stub(),
|
||||||
|
getDomain: sinon.stub().returns("matrix.rog"),
|
||||||
|
getUserId: sinon.stub().returns("@userId:matrix.rog"),
|
||||||
|
|
||||||
getPushActionsForEvent: sinon.stub(),
|
getPushActionsForEvent: sinon.stub(),
|
||||||
getRoom: sinon.stub().returns(mkStubRoom()),
|
getRoom: sinon.stub().returns(mkStubRoom()),
|
||||||
|
@ -81,6 +83,7 @@ export function createTestClient() {
|
||||||
paginateEventTimeline: sinon.stub().returns(Promise.resolve()),
|
paginateEventTimeline: sinon.stub().returns(Promise.resolve()),
|
||||||
sendReadReceipt: sinon.stub().returns(Promise.resolve()),
|
sendReadReceipt: sinon.stub().returns(Promise.resolve()),
|
||||||
getRoomIdForAlias: sinon.stub().returns(Promise.resolve()),
|
getRoomIdForAlias: sinon.stub().returns(Promise.resolve()),
|
||||||
|
getRoomDirectoryVisibility: sinon.stub().returns(Promise.resolve()),
|
||||||
getProfileInfo: sinon.stub().returns(Promise.resolve({})),
|
getProfileInfo: sinon.stub().returns(Promise.resolve({})),
|
||||||
getAccountData: (type) => {
|
getAccountData: (type) => {
|
||||||
return mkEvent({
|
return mkEvent({
|
||||||
|
@ -244,6 +247,7 @@ export function mkStubRoom(roomId = null) {
|
||||||
roomId: roomId,
|
roomId: roomId,
|
||||||
getAvatarUrl: () => 'mxc://avatar.url/image.png',
|
getAvatarUrl: () => 'mxc://avatar.url/image.png',
|
||||||
}),
|
}),
|
||||||
|
getMembersWithMembership: sinon.stub().returns([]),
|
||||||
getJoinedMembers: sinon.stub().returns([]),
|
getJoinedMembers: sinon.stub().returns([]),
|
||||||
getPendingEvents: () => [],
|
getPendingEvents: () => [],
|
||||||
getLiveTimeline: () => stubTimeline,
|
getLiveTimeline: () => stubTimeline,
|
||||||
|
@ -252,8 +256,16 @@ export function mkStubRoom(roomId = null) {
|
||||||
hasMembershipState: () => null,
|
hasMembershipState: () => null,
|
||||||
currentState: {
|
currentState: {
|
||||||
getStateEvents: sinon.stub(),
|
getStateEvents: sinon.stub(),
|
||||||
|
mayClientSendStateEvent: sinon.stub().returns(true),
|
||||||
|
maySendStateEvent: sinon.stub().returns(true),
|
||||||
members: [],
|
members: [],
|
||||||
},
|
},
|
||||||
|
tags: {
|
||||||
|
"m.favourite": {
|
||||||
|
order: 0.5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setBlacklistUnverifiedDevices: sinon.stub(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +296,7 @@ export function wrapInMatrixClientContext(WrappedComponent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <WrappedComponent {...this.props} />;
|
return <WrappedComponent ref={this.props.wrappedRef} {...this.props} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Wrapper;
|
return Wrapper;
|
||||||
|
|
Loading…
Reference in a new issue