From 1fbf027a40cf135a72d7668423ea096f61c67178 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 17 Jun 2016 12:20:26 +0100 Subject: [PATCH 1/9] Some basic tests for RoomView --- test/components/structures/RoomView-test.js | 66 +++++++++++++++++++++ test/skinned-sdk.js | 1 + test/test-utils.js | 18 +++++- 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 test/components/structures/RoomView-test.js diff --git a/test/components/structures/RoomView-test.js b/test/components/structures/RoomView-test.js new file mode 100644 index 0000000000..0570ac0bbc --- /dev/null +++ b/test/components/structures/RoomView-test.js @@ -0,0 +1,66 @@ +var React = require('react'); +var expect = require('expect'); +var sinon = require('sinon'); +var ReactDOM = require("react-dom"); + +var sdk = require('matrix-react-sdk'); +var RoomView = sdk.getComponent('structures.RoomView'); +var peg = require('../../../src/MatrixClientPeg'); + +var test_utils = require('../../test-utils'); +var q = require('q'); + +var Skinner = require("../../../src/Skinner"); +var stubComponent = require('../../components/stub-component.js'); + +describe('RoomView', function () { + var sandbox; + + beforeEach(function() { + sandbox = test_utils.stubClient(); + + this.oldTimelinePanel = Skinner.getComponent('structures.TimelinePanel'); + Skinner.addComponent('structures.TimelinePanel', stubComponent()); + Skinner.addComponent('views.rooms.RoomHeader', stubComponent()); + + peg.get().credentials = { userId: "@test:example.com" }; + }); + + afterEach(function() { + sandbox.restore(); + Skinner.addComponent('structures.TimelinePanel', this.oldTimelinePanel); + }); + + it('resolves a room alias to a room id', function (done) { + peg.get().getRoomIdForAlias.returns(q({room_id: "!randomcharacters:aser.ver"})); + + var onRoomIdResolved = sinon.spy(); + + var parentDiv = document.createElement('div'); + ReactDOM.render(, parentDiv); + + process.nextTick(function() { + expect(onRoomIdResolved.called).toExist(); + ReactDOM.unmountComponentAtNode(parentDiv); + done(); + }); + }); + + it('joins by alias if given an alias', function (done) { + peg.get().getRoomIdForAlias.returns(q({room_id: "!randomcharacters:aser.ver"})); + peg.get().getProfileInfo.returns(q({displayname: "foo"})); + var parentDiv = document.createElement('div'); + var roomView = ReactDOM.render(, parentDiv); + + peg.get().joinRoom = sinon.spy(); + + process.nextTick(function() { + roomView.onJoinButtonClicked(); + process.nextTick(function() { + expect(peg.get().joinRoom.calledWith('#alias:ser.ver')).toExist(); + ReactDOM.unmountComponentAtNode(parentDiv); + done(); + }); + }); + }); +}); diff --git a/test/skinned-sdk.js b/test/skinned-sdk.js index 869902dcf6..8d34a9d208 100644 --- a/test/skinned-sdk.js +++ b/test/skinned-sdk.js @@ -22,6 +22,7 @@ var components = skin.components; components['structures.LeftPanel'] = stubComponent(); components['structures.RightPanel'] = stubComponent(); components['structures.RoomDirectory'] = stubComponent(); +components['rooms.SearchBar'] = stubComponent(); components['views.globals.MatrixToolbar'] = stubComponent(); components['views.globals.GuestWarningBar'] = stubComponent(); components['views.globals.NewVersionBar'] = stubComponent(); diff --git a/test/test-utils.js b/test/test-utils.js index 817af31d45..fc3aaace9f 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -34,13 +34,16 @@ module.exports.stubClient = function() { getIdentityServerUrl: sinon.stub(), getPushActionsForEvent: sinon.stub(), - getRoom: sinon.stub(), + getRoom: sinon.stub().returns(this.mkStubRoom()), + getRooms: sinon.stub().returns([]), loginFlows: sinon.stub(), on: sinon.stub(), removeListener: sinon.stub(), paginateEventTimeline: sinon.stub().returns(q()), sendReadReceipt: sinon.stub().returns(q()), + getRoomIdForAlias: sinon.stub().returns(q()), + getProfileInfo: sinon.stub().returns(q({})), }; // stub out the methods in MatrixClientPeg @@ -169,3 +172,16 @@ module.exports.mkMessage = function(opts) { }; return module.exports.mkEvent(opts); }; + +module.exports.mkStubRoom = function() { + return { + getReceiptsForEvent: sinon.stub().returns([]), + getMember: sinon.stub().returns({}), + getJoinedMembers: sinon.stub().returns([]), + currentState: { + getStateEvents: sinon.stub(), + members: [], + }, + }; +}; + From b0bf24c1369994aea662cf3b1eb34b5abb756e9a Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 17 Jun 2016 12:22:16 +0100 Subject: [PATCH 2/9] Comment --- test/components/structures/RoomView-test.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/components/structures/RoomView-test.js b/test/components/structures/RoomView-test.js index 0570ac0bbc..9c34383316 100644 --- a/test/components/structures/RoomView-test.js +++ b/test/components/structures/RoomView-test.js @@ -40,6 +40,9 @@ describe('RoomView', function () { ReactDOM.render(, parentDiv); process.nextTick(function() { + // These expect()s don't read very well and don't give very good failure + // messages, but expect's toHaveBeenCalled only takes an expect spy object, + // not a sinon spy object. expect(onRoomIdResolved.called).toExist(); ReactDOM.unmountComponentAtNode(parentDiv); done(); From d3a463e9acb403f415cca5d97e9c36f021c0950c Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 17 Jun 2016 12:23:45 +0100 Subject: [PATCH 3/9] restore the room header too --- test/components/structures/RoomView-test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/components/structures/RoomView-test.js b/test/components/structures/RoomView-test.js index 9c34383316..8e4fb0428b 100644 --- a/test/components/structures/RoomView-test.js +++ b/test/components/structures/RoomView-test.js @@ -20,6 +20,7 @@ describe('RoomView', function () { sandbox = test_utils.stubClient(); this.oldTimelinePanel = Skinner.getComponent('structures.TimelinePanel'); + this.oldRoomHeader = Skinner.getComponent('views.rooms.RoomHeader'); Skinner.addComponent('structures.TimelinePanel', stubComponent()); Skinner.addComponent('views.rooms.RoomHeader', stubComponent()); @@ -29,6 +30,7 @@ describe('RoomView', function () { afterEach(function() { sandbox.restore(); Skinner.addComponent('structures.TimelinePanel', this.oldTimelinePanel); + Skinner.addComponent('views.rooms.RoomHeader', this.oldRoomHeader); }); it('resolves a room alias to a room id', function (done) { From 3b5378fa53a5a1f83820e59d36ad55d24046c49d Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 17 Jun 2016 15:17:45 +0100 Subject: [PATCH 4/9] Show canonical alias in URL bar Use https://github.com/matrix-org/matrix-js-sdk/pull/140 to get the canonical alias, because that's a thing now. --- src/components/structures/MatrixChat.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 9899f66cc5..9fd15f2d2f 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -33,7 +33,6 @@ var PostRegistration = require("./login/PostRegistration"); var Modal = require("../../Modal"); var Tinter = require("../../Tinter"); var sdk = require('../../index'); -var MatrixTools = require('../../MatrixTools'); var linkifyMatrix = require("../../linkify-matrix"); var KeyCode = require('../../KeyCode'); @@ -539,7 +538,7 @@ module.exports = React.createClass({ var presentedId = roomAlias || roomId; var room = MatrixClientPeg.get().getRoom(roomId); if (room) { - var theAlias = MatrixTools.getCanonicalAliasForRoom(room); + var theAlias = room.getCanonicalAlias(); if (theAlias) presentedId = theAlias; // No need to do this given RoomView triggers it itself... @@ -631,7 +630,7 @@ module.exports = React.createClass({ var presentedId = self.state.currentRoomId; var room = MatrixClientPeg.get().getRoom(self.state.currentRoomId); if (room) { - var theAlias = MatrixTools.getCanonicalAliasForRoom(room); + var theAlias = room.getCanonicalAlias(); if (theAlias) presentedId = theAlias; } From b2f0ed09ab2ec0833c022f549d1a7dbba906ae0a Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 17 Jun 2016 15:46:31 +0100 Subject: [PATCH 5/9] Sort alphabetically (and name consistently) --- test/skinned-sdk.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/skinned-sdk.js b/test/skinned-sdk.js index 8d34a9d208..d4e178ef2c 100644 --- a/test/skinned-sdk.js +++ b/test/skinned-sdk.js @@ -22,7 +22,6 @@ var components = skin.components; components['structures.LeftPanel'] = stubComponent(); components['structures.RightPanel'] = stubComponent(); components['structures.RoomDirectory'] = stubComponent(); -components['rooms.SearchBar'] = stubComponent(); components['views.globals.MatrixToolbar'] = stubComponent(); components['views.globals.GuestWarningBar'] = stubComponent(); components['views.globals.NewVersionBar'] = stubComponent(); @@ -30,6 +29,7 @@ components['views.elements.Spinner'] = stubComponent({displayName: 'Spinner'}); components['views.messages.DateSeparator'] = stubComponent({displayName: 'DateSeparator'}); components['views.messages.MessageTimestamp'] = stubComponent({displayName: 'MessageTimestamp'}); components['views.messages.SenderProfile'] = stubComponent({displayName: 'SenderProfile'}); +components['views.rooms.SearchBar'] = stubComponent(); sdk.loadSkin(skin); From 53d92df6f82b3782674ad7e642579be5c0ecfb2c Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 17 Jun 2016 15:50:13 +0100 Subject: [PATCH 6/9] Set up / teardown container div in before/afterEach --- test/components/structures/RoomView-test.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/components/structures/RoomView-test.js b/test/components/structures/RoomView-test.js index 8e4fb0428b..858a0ad061 100644 --- a/test/components/structures/RoomView-test.js +++ b/test/components/structures/RoomView-test.js @@ -15,9 +15,11 @@ var stubComponent = require('../../components/stub-component.js'); describe('RoomView', function () { var sandbox; + var parentDiv; beforeEach(function() { sandbox = test_utils.stubClient(); + parentDiv = document.createElement('div'); this.oldTimelinePanel = Skinner.getComponent('structures.TimelinePanel'); this.oldRoomHeader = Skinner.getComponent('views.rooms.RoomHeader'); @@ -29,6 +31,9 @@ describe('RoomView', function () { afterEach(function() { sandbox.restore(); + + ReactDOM.unmountComponentAtNode(parentDiv); + Skinner.addComponent('structures.TimelinePanel', this.oldTimelinePanel); Skinner.addComponent('views.rooms.RoomHeader', this.oldRoomHeader); }); @@ -38,7 +43,6 @@ describe('RoomView', function () { var onRoomIdResolved = sinon.spy(); - var parentDiv = document.createElement('div'); ReactDOM.render(, parentDiv); process.nextTick(function() { @@ -46,7 +50,6 @@ describe('RoomView', function () { // messages, but expect's toHaveBeenCalled only takes an expect spy object, // not a sinon spy object. expect(onRoomIdResolved.called).toExist(); - ReactDOM.unmountComponentAtNode(parentDiv); done(); }); }); @@ -63,7 +66,6 @@ describe('RoomView', function () { roomView.onJoinButtonClicked(); process.nextTick(function() { expect(peg.get().joinRoom.calledWith('#alias:ser.ver')).toExist(); - ReactDOM.unmountComponentAtNode(parentDiv); done(); }); }); From ad00abe9c0075b5193c19ac85db288d9d127c7bf Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Thu, 9 Jun 2016 19:07:01 +0100 Subject: [PATCH 7/9] Support for making devices unverified Because its useful for testing Requires support from js-sdk, and (ideally) css from vector-web --- .../views/rooms/MemberDeviceInfo.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/MemberDeviceInfo.js b/src/components/views/rooms/MemberDeviceInfo.js index da53c744b2..ebc2ab1c32 100644 --- a/src/components/views/rooms/MemberDeviceInfo.js +++ b/src/components/views/rooms/MemberDeviceInfo.js @@ -25,8 +25,15 @@ module.exports = React.createClass({ }, onVerifyClick: function() { - MatrixClientPeg.get().setDeviceVerified(this.props.userId, - this.props.device.id); + MatrixClientPeg.get().setDeviceVerified( + this.props.userId, this.props.device.id, true + ); + }, + + onUnverifyClick: function() { + MatrixClientPeg.get().setDeviceVerified( + this.props.userId, this.props.device.id, false + ); }, render: function() { @@ -35,9 +42,15 @@ module.exports = React.createClass({ indicator = (
); + button = ( +
+ Unverify +
+ ); } else { button = ( -
Verify
From 6adce649ebe7672c376de3aa6163d4a2b37d5f28 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 17 Jun 2016 16:56:34 +0100 Subject: [PATCH 8/9] Use the first alias is there's no canonical alias --- src/MatrixTools.js | 20 ++++++-------------- src/components/structures/MatrixChat.js | 5 +++-- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/MatrixTools.js b/src/MatrixTools.js index 7fded4adea..372f17f69c 100644 --- a/src/MatrixTools.js +++ b/src/MatrixTools.js @@ -16,21 +16,13 @@ limitations under the License. module.exports = { /** - * Given a room object, return the canonical alias for it - * if there is one. Otherwise return null; + * Given a room object, return the alias we should use for it, + * if any. This could be the canonical alias if one exists, otherwise + * an alias selected arbitrarily but deterministically from the list + * of aliases. Otherwise return null; */ - getCanonicalAliasForRoom: function(room) { - var aliasEvents = room.currentState.getStateEvents( - "m.room.aliases" - ); - // Canonical aliases aren't implemented yet, so just return the first - for (var j = 0; j < aliasEvents.length; j++) { - var aliases = aliasEvents[j].getContent().aliases; - if (aliases && aliases.length) { - return aliases[0]; - } - } - return null; + getDisplayAliasForRoom: function(room) { + return room.getCanonicalAlias() || room.getAliases()[0]; }, /** diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 9fd15f2d2f..1973fedbcd 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -33,6 +33,7 @@ var PostRegistration = require("./login/PostRegistration"); var Modal = require("../../Modal"); var Tinter = require("../../Tinter"); var sdk = require('../../index'); +var MatrixTools = require('../../MatrixTools'); var linkifyMatrix = require("../../linkify-matrix"); var KeyCode = require('../../KeyCode'); @@ -538,7 +539,7 @@ module.exports = React.createClass({ var presentedId = roomAlias || roomId; var room = MatrixClientPeg.get().getRoom(roomId); if (room) { - var theAlias = room.getCanonicalAlias(); + var theAlias = MatrixTools.getDisplayAliasForRoom(room); if (theAlias) presentedId = theAlias; // No need to do this given RoomView triggers it itself... @@ -630,7 +631,7 @@ module.exports = React.createClass({ var presentedId = self.state.currentRoomId; var room = MatrixClientPeg.get().getRoom(self.state.currentRoomId); if (room) { - var theAlias = room.getCanonicalAlias(); + var theAlias = MatrixTools.getDisplayAliasForRoom(room); if (theAlias) presentedId = theAlias; } From f6835baa9cbaf8c1f83f340ed87559393df18e70 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 17 Jun 2016 17:09:52 +0100 Subject: [PATCH 9/9] UserSettings: fix the displayed version of the react-sdk --- src/components/structures/UserSettings.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 60f9898e35..7fcb81a60c 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -20,7 +20,7 @@ var MatrixClientPeg = require("../../MatrixClientPeg"); var Modal = require('../../Modal'); var dis = require("../../dispatcher"); var q = require('q'); -var version = require('../../../package.json').version; +var package_json = require('../../../package.json'); var UserSettingsStore = require('../../UserSettingsStore'); var GeminiScrollbar = require('react-gemini-scrollbar'); var Email = require('../../email'); @@ -37,6 +37,11 @@ const LABS_FEATURES = [ } ]; +// if this looks like a release, use the 'version' from package.json; else use +// the git sha. +const REACT_SDK_VERSION = + 'dist' in package_json ? package_json.version : package_json.gitHead || ""; + module.exports = React.createClass({ displayName: 'UserSettings', @@ -57,7 +62,6 @@ module.exports = React.createClass({ return { avatarUrl: null, threePids: [], - clientVersion: version, phase: "UserSettings.LOADING", // LOADING, DISPLAY email_add_pending: false, }; @@ -465,7 +469,7 @@ module.exports = React.createClass({ Identity Server is { MatrixClientPeg.get().getIdentityServerUrl() }
- matrix-react-sdk version: {this.state.clientVersion}
+ matrix-react-sdk version: {REACT_SDK_VERSION}
vector-web version: {this.props.version}