mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-15 20:54:59 +08:00
Add error to UI when group member list fails to load
Signed-off-by: J. Ryan Stinnett <jryans@gmail.com>
This commit is contained in:
parent
5fc25fd6ba
commit
22ff76e6b7
@ -32,7 +32,9 @@ export default React.createClass({
|
|||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
members: null,
|
members: null,
|
||||||
|
membersError: null,
|
||||||
invitedMembers: null,
|
invitedMembers: null,
|
||||||
|
invitedMembersError: null,
|
||||||
truncateAt: INITIAL_LOAD_NUM_MEMBERS,
|
truncateAt: INITIAL_LOAD_NUM_MEMBERS,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -50,6 +52,19 @@ export default React.createClass({
|
|||||||
GroupStore.registerListener(groupId, () => {
|
GroupStore.registerListener(groupId, () => {
|
||||||
this._fetchMembers();
|
this._fetchMembers();
|
||||||
});
|
});
|
||||||
|
GroupStore.on('error', (err, errorGroupId, stateKey) => {
|
||||||
|
if (this._unmounted || groupId !== errorGroupId) return;
|
||||||
|
if (stateKey === GroupStore.STATE_KEY.GroupMembers) {
|
||||||
|
this.setState({
|
||||||
|
membersError: err,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (stateKey === GroupStore.STATE_KEY.GroupInvitedMembers) {
|
||||||
|
this.setState({
|
||||||
|
invitedMembersError: err,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_fetchMembers: function() {
|
_fetchMembers: function() {
|
||||||
@ -83,7 +98,11 @@ export default React.createClass({
|
|||||||
this.setState({ searchQuery: ev.target.value });
|
this.setState({ searchQuery: ev.target.value });
|
||||||
},
|
},
|
||||||
|
|
||||||
makeGroupMemberTiles: function(query, memberList) {
|
makeGroupMemberTiles: function(query, memberList, memberListError) {
|
||||||
|
if (memberListError) {
|
||||||
|
return <div className="warning">{ _t("Failed to load group members") }</div>;
|
||||||
|
}
|
||||||
|
|
||||||
const GroupMemberTile = sdk.getComponent("groups.GroupMemberTile");
|
const GroupMemberTile = sdk.getComponent("groups.GroupMemberTile");
|
||||||
const TruncatedList = sdk.getComponent("elements.TruncatedList");
|
const TruncatedList = sdk.getComponent("elements.TruncatedList");
|
||||||
query = (query || "").toLowerCase();
|
query = (query || "").toLowerCase();
|
||||||
@ -153,15 +172,26 @@ export default React.createClass({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const joined = this.state.members ? <div className="mx_MemberList_joined">
|
const joined = this.state.members ? <div className="mx_MemberList_joined">
|
||||||
{ this.makeGroupMemberTiles(this.state.searchQuery, this.state.members) }
|
{
|
||||||
|
this.makeGroupMemberTiles(
|
||||||
|
this.state.searchQuery,
|
||||||
|
this.state.members,
|
||||||
|
this.state.membersError,
|
||||||
|
)
|
||||||
|
}
|
||||||
</div> : <div />;
|
</div> : <div />;
|
||||||
|
|
||||||
const invited = (this.state.invitedMembers && this.state.invitedMembers.length > 0) ?
|
const invited = (this.state.invitedMembers && this.state.invitedMembers.length > 0) ?
|
||||||
<div className="mx_MemberList_invited">
|
<div className="mx_MemberList_invited">
|
||||||
<h2>{ _t("Invited") }</h2>
|
<h2>{_t("Invited")}</h2>
|
||||||
{ this.makeGroupMemberTiles(this.state.searchQuery, this.state.invitedMembers) }
|
{
|
||||||
|
this.makeGroupMemberTiles(
|
||||||
|
this.state.searchQuery,
|
||||||
|
this.state.invitedMembers,
|
||||||
|
this.state.invitedMembersError,
|
||||||
|
)
|
||||||
|
}
|
||||||
</div> : <div />;
|
</div> : <div />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_MemberList">
|
<div className="mx_MemberList">
|
||||||
{ inputBox }
|
{ inputBox }
|
||||||
|
@ -1107,6 +1107,7 @@
|
|||||||
"Community %(groupId)s not found": "Community %(groupId)s not found",
|
"Community %(groupId)s not found": "Community %(groupId)s not found",
|
||||||
"This Home server does not support communities": "This Home server does not support communities",
|
"This Home server does not support communities": "This Home server does not support communities",
|
||||||
"Failed to load %(groupId)s": "Failed to load %(groupId)s",
|
"Failed to load %(groupId)s": "Failed to load %(groupId)s",
|
||||||
|
"Failed to load group members": "Failed to load group members",
|
||||||
"Couldn't load home page": "Couldn't load home page",
|
"Couldn't load home page": "Couldn't load home page",
|
||||||
"You are currently using Riot anonymously as a guest.": "You are currently using Riot anonymously as a guest.",
|
"You are currently using Riot anonymously as a guest.": "You are currently using Riot anonymously as a guest.",
|
||||||
"If you would like to create a Matrix account you can <a>register</a> now.": "If you would like to create a Matrix account you can <a>register</a> now.",
|
"If you would like to create a Matrix account you can <a>register</a> now.": "If you would like to create a Matrix account you can <a>register</a> now.",
|
||||||
|
@ -134,6 +134,8 @@
|
|||||||
"Failed to join room": "Failed to join room",
|
"Failed to join room": "Failed to join room",
|
||||||
"Failed to kick": "Failed to kick",
|
"Failed to kick": "Failed to kick",
|
||||||
"Failed to leave room": "Failed to leave room",
|
"Failed to leave room": "Failed to leave room",
|
||||||
|
"Failed to load %(groupId)s": "Failed to load %(groupId)s",
|
||||||
|
"Failed to load group members": "Failed to load group members",
|
||||||
"Failed to load timeline position": "Failed to load timeline position",
|
"Failed to load timeline position": "Failed to load timeline position",
|
||||||
"Failed to mute user": "Failed to mute user",
|
"Failed to mute user": "Failed to mute user",
|
||||||
"Failed to reject invite": "Failed to reject invite",
|
"Failed to reject invite": "Failed to reject invite",
|
||||||
|
149
test/components/views/groups/GroupMemberList-test.js
Normal file
149
test/components/views/groups/GroupMemberList-test.js
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 New Vector Ltd.
|
||||||
|
|
||||||
|
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 ReactDOM from "react-dom";
|
||||||
|
import ReactTestUtils from "react-dom/test-utils";
|
||||||
|
import expect from "expect";
|
||||||
|
|
||||||
|
import MockHttpBackend from "matrix-mock-request";
|
||||||
|
import MatrixClientPeg from "../../../../src/MatrixClientPeg";
|
||||||
|
import sdk from "matrix-react-sdk";
|
||||||
|
import Matrix from "matrix-js-sdk";
|
||||||
|
|
||||||
|
import * as TestUtils from "test-utils";
|
||||||
|
const { waitForUpdate } = TestUtils;
|
||||||
|
|
||||||
|
const GroupMemberList = sdk.getComponent("views.groups.GroupMemberList");
|
||||||
|
const WrappedGroupMemberList = TestUtils.wrapInMatrixClientContext(GroupMemberList);
|
||||||
|
|
||||||
|
describe("GroupMemberList", function() {
|
||||||
|
let root;
|
||||||
|
let rootElement;
|
||||||
|
let httpBackend;
|
||||||
|
let summaryResponse;
|
||||||
|
let groupId;
|
||||||
|
let groupIdEncoded;
|
||||||
|
|
||||||
|
// Summary response fields
|
||||||
|
const user = {
|
||||||
|
is_privileged: true, // can edit the group
|
||||||
|
is_public: true, // appear as a member to non-members
|
||||||
|
is_publicised: true, // display flair
|
||||||
|
};
|
||||||
|
const usersSection = {
|
||||||
|
roles: {},
|
||||||
|
total_user_count_estimate: 0,
|
||||||
|
users: [],
|
||||||
|
};
|
||||||
|
const roomsSection = {
|
||||||
|
categories: {},
|
||||||
|
rooms: [],
|
||||||
|
total_room_count_estimate: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Users response fields
|
||||||
|
const usersResponse = {
|
||||||
|
chunk: [
|
||||||
|
{
|
||||||
|
user_id: "@test:matrix.org",
|
||||||
|
displayname: "Test",
|
||||||
|
avatar_url: "mxc://matrix.org/oUxxDyzQOHdVDMxgwFzyCWEe",
|
||||||
|
is_public: true,
|
||||||
|
is_privileged: true,
|
||||||
|
attestation: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
TestUtils.beforeEach(this);
|
||||||
|
|
||||||
|
httpBackend = new MockHttpBackend();
|
||||||
|
|
||||||
|
Matrix.request(httpBackend.requestFn);
|
||||||
|
|
||||||
|
MatrixClientPeg.get = () => Matrix.createClient({
|
||||||
|
baseUrl: "https://my.home.server",
|
||||||
|
userId: "@me:here",
|
||||||
|
accessToken: "123456789",
|
||||||
|
});
|
||||||
|
|
||||||
|
summaryResponse = {
|
||||||
|
profile: {
|
||||||
|
avatar_url: "mxc://someavatarurl",
|
||||||
|
is_openly_joinable: true,
|
||||||
|
is_public: true,
|
||||||
|
long_description: "This is a <b>LONG</b> description.",
|
||||||
|
name: "The name of a community",
|
||||||
|
short_description: "This is a community",
|
||||||
|
},
|
||||||
|
user,
|
||||||
|
users_section: usersSection,
|
||||||
|
rooms_section: roomsSection,
|
||||||
|
};
|
||||||
|
|
||||||
|
groupId = "+" + Math.random().toString(16).slice(2) + ":domain";
|
||||||
|
groupIdEncoded = encodeURIComponent(groupId);
|
||||||
|
|
||||||
|
rootElement = document.createElement("div");
|
||||||
|
root = ReactDOM.render(<WrappedGroupMemberList groupId={groupId} />, rootElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
ReactDOM.unmountComponentAtNode(rootElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should show group member list after successful /users", function() {
|
||||||
|
const groupMemberList = ReactTestUtils.findRenderedComponentWithType(root, GroupMemberList);
|
||||||
|
const prom = waitForUpdate(groupMemberList, 4).then(() => {
|
||||||
|
ReactTestUtils.findRenderedDOMComponentWithClass(root, "mx_MemberList");
|
||||||
|
|
||||||
|
const memberList = ReactTestUtils.findRenderedDOMComponentWithClass(root, "mx_MemberList_joined");
|
||||||
|
const memberListElement = ReactDOM.findDOMNode(memberList);
|
||||||
|
expect(memberListElement).toExist();
|
||||||
|
expect(memberListElement.innerText).toBe("Test");
|
||||||
|
});
|
||||||
|
|
||||||
|
httpBackend.when("GET", "/groups/" + groupIdEncoded + "/summary").respond(200, summaryResponse);
|
||||||
|
httpBackend.when("GET", "/groups/" + groupIdEncoded + "/users").respond(200, usersResponse);
|
||||||
|
httpBackend.when("GET", "/groups/" + groupIdEncoded + "/invited_users").respond(200, { chunk: [] });
|
||||||
|
httpBackend.when("GET", "/groups/" + groupIdEncoded + "/rooms").respond(200, { chunk: [] });
|
||||||
|
|
||||||
|
httpBackend.flush(undefined, undefined, 0);
|
||||||
|
return prom;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should show error message after failed /users", function() {
|
||||||
|
const groupMemberList = ReactTestUtils.findRenderedComponentWithType(root, GroupMemberList);
|
||||||
|
const prom = waitForUpdate(groupMemberList, 4).then(() => {
|
||||||
|
ReactTestUtils.findRenderedDOMComponentWithClass(root, "mx_MemberList");
|
||||||
|
|
||||||
|
const memberList = ReactTestUtils.findRenderedDOMComponentWithClass(root, "mx_MemberList_joined");
|
||||||
|
const memberListElement = ReactDOM.findDOMNode(memberList);
|
||||||
|
expect(memberListElement).toExist();
|
||||||
|
expect(memberListElement.innerText).toBe("Failed to load group members");
|
||||||
|
});
|
||||||
|
|
||||||
|
httpBackend.when("GET", "/groups/" + groupIdEncoded + "/summary").respond(200, summaryResponse);
|
||||||
|
httpBackend.when("GET", "/groups/" + groupIdEncoded + "/users").respond(500, {});
|
||||||
|
httpBackend.when("GET", "/groups/" + groupIdEncoded + "/invited_users").respond(200, { chunk: [] });
|
||||||
|
httpBackend.when("GET", "/groups/" + groupIdEncoded + "/rooms").respond(200, { chunk: [] });
|
||||||
|
|
||||||
|
httpBackend.flush(undefined, undefined, 0);
|
||||||
|
return prom;
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user