From 0e8a49ebb7e6826bc84ab79623bf9d13dcb57ffd Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Mon, 14 Nov 2016 16:00:24 +0000 Subject: [PATCH 1/2] Update EventTile to use WithMatrixClient instead of MatrixClientPeg --- src/components/views/rooms/EventTile.js | 51 ++++++++++++------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index f4167b32f6..375c00fed7 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -21,8 +21,8 @@ var classNames = require("classnames"); var Modal = require('../../../Modal'); var sdk = require('../../../index'); -var MatrixClientPeg = require('../../../MatrixClientPeg') var TextForEvent = require('../../../TextForEvent'); +import WithMatrixClient from '../../../wrappers/WithMatrixClient'; var ContextualMenu = require('../../structures/ContextualMenu'); var dispatcher = require("../../../dispatcher"); @@ -63,22 +63,13 @@ var MAX_READ_AVATARS = 5; // | '--------------------------------------' | // '----------------------------------------------------------' -module.exports = React.createClass({ +module.exports = WithMatrixClient(React.createClass({ displayName: 'EventTile', - statics: { - haveTileForEvent: function(e) { - if (e.isRedacted()) return false; - if (eventTileTypes[e.getType()] == undefined) return false; - if (eventTileTypes[e.getType()] == 'messages.TextualEvent') { - return TextForEvent.textForEvent(e) !== ''; - } else { - return true; - } - } - }, - propTypes: { + /* MatrixClient instance for sender verification etc */ + matrixClient: React.PropTypes.object.isRequired, + /* the MatrixEvent to show */ mxEvent: React.PropTypes.object.isRequired, @@ -153,7 +144,7 @@ module.exports = React.createClass({ componentDidMount: function() { this._suppressReadReceiptAnimation = false; - MatrixClientPeg.get().on("deviceVerificationChanged", + this.props.matrixClient.on("deviceVerificationChanged", this.onDeviceVerificationChanged); }, @@ -176,11 +167,9 @@ module.exports = React.createClass({ }, componentWillUnmount: function() { - var client = MatrixClientPeg.get(); - if (client) { - client.removeListener("deviceVerificationChanged", - this.onDeviceVerificationChanged); - } + var client = this.props.matrixClient; + client.removeListener("deviceVerificationChanged", + this.onDeviceVerificationChanged); }, onDeviceVerificationChanged: function(userId, device) { @@ -193,7 +182,7 @@ module.exports = React.createClass({ var verified = null; if (mxEvent.isEncrypted()) { - verified = MatrixClientPeg.get().isEventSenderVerified(mxEvent); + verified = this.props.matrixClient.isEventSenderVerified(mxEvent); } this.setState({ @@ -246,11 +235,11 @@ module.exports = React.createClass({ }, shouldHighlight: function() { - var actions = MatrixClientPeg.get().getPushActionsForEvent(this.props.mxEvent); + var actions = this.props.matrixClient.getPushActionsForEvent(this.props.mxEvent); if (!actions || !actions.tweaks) { return false; } // don't show self-highlights from another of our clients - if (this.props.mxEvent.getSender() === MatrixClientPeg.get().credentials.userId) + if (this.props.mxEvent.getSender() === this.props.matrixClient.credentials.userId) { return false; } @@ -387,7 +376,7 @@ module.exports = React.createClass({ throw new Error("Event type not supported"); } - var e2eEnabled = MatrixClientPeg.get().isRoomEncrypted(this.props.mxEvent.getRoomId()); + var e2eEnabled = this.props.matrixClient.isRoomEncrypted(this.props.mxEvent.getRoomId()); var isSending = (['sending', 'queued', 'encrypting'].indexOf(this.props.eventSendStatus) !== -1); var classes = classNames({ @@ -481,7 +470,7 @@ module.exports = React.createClass({ } if (this.props.tileShape === "notif") { - var room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId()); + var room = this.props.matrixClient.getRoom(this.props.mxEvent.getRoomId()); return (
@@ -554,4 +543,14 @@ module.exports = React.createClass({ ); } }, -}); +})); + +module.exports.haveTileForEvent = function(e) { + if (e.isRedacted()) return false; + if (eventTileTypes[e.getType()] == undefined) return false; + if (eventTileTypes[e.getType()] == 'messages.TextualEvent') { + return TextForEvent.textForEvent(e) !== ''; + } else { + return true; + } +}; From 22757cfcd3a2b769c2748ef9e21512ed7c34c8d2 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Mon, 14 Nov 2016 18:20:15 +0000 Subject: [PATCH 2/2] Inject MatrixClient into React context in tests Now that EventTile expects MatrixClient in the context, we had better provide it. --- .../structures/MessagePanel-test.js | 40 ++++++++++------ .../structures/TimelinePanel-test.js | 34 +++++++++++--- test/test-utils.js | 46 ++++++++++++------- 3 files changed, 83 insertions(+), 37 deletions(-) diff --git a/test/components/structures/MessagePanel-test.js b/test/components/structures/MessagePanel-test.js index d16371b368..a96d0ed5d1 100644 --- a/test/components/structures/MessagePanel-test.js +++ b/test/components/structures/MessagePanel-test.js @@ -20,30 +20,44 @@ var TestUtils = require('react-addons-test-utils'); var expect = require('expect'); var sdk = require('matrix-react-sdk'); -var MatrixClientPeg = require('MatrixClientPeg'); var MessagePanel = sdk.getComponent('structures.MessagePanel'); var test_utils = require('test-utils'); var mockclock = require('mock-clock'); +var client; + +// wrap MessagePanel with a component which provides the MatrixClient in the context. +const WrappedMessagePanel = React.createClass({ + childContextTypes: { + matrixClient: React.PropTypes.object, + }, + + getChildContext: function() { + return { + matrixClient: client, + }; + }, + + render: function() { + return ; + }, +}); + describe('MessagePanel', function () { - var sandbox; var clock = mockclock.clock(); var realSetTimeout = window.setTimeout; var events = mkEvents(); beforeEach(function() { test_utils.beforeEach(this); - sandbox = test_utils.stubClient(sandbox); - - var client = MatrixClientPeg.get(); + client = test_utils.createTestClient(); client.credentials = {userId: '@me:here'}; }); afterEach(function () { clock.uninstall(); - sandbox.restore(); }); function mkEvents() { @@ -61,7 +75,7 @@ describe('MessagePanel', function () { it('should show the events', function() { var res = TestUtils.renderIntoDocument( - + ); // just check we have the right number of tiles for now @@ -72,7 +86,7 @@ describe('MessagePanel', function () { it('should show the read-marker in the right place', function() { var res = TestUtils.renderIntoDocument( - ); @@ -96,7 +110,7 @@ describe('MessagePanel', function () { // first render with the RM in one place var mp = ReactDOM.render( - , parentDiv); @@ -112,7 +126,7 @@ describe('MessagePanel', function () { // now move the RM mp = ReactDOM.render( - , parentDiv); @@ -147,7 +161,7 @@ describe('MessagePanel', function () { // first render with the RM in one place var mp = ReactDOM.render( - , parentDiv); @@ -159,7 +173,7 @@ describe('MessagePanel', function () { // now move the RM mp = ReactDOM.render( - , parentDiv); @@ -175,7 +189,7 @@ describe('MessagePanel', function () { // and move the RM again mp = ReactDOM.render( - , parentDiv); diff --git a/test/components/structures/TimelinePanel-test.js b/test/components/structures/TimelinePanel-test.js index d8ded918f6..9c78a56359 100644 --- a/test/components/structures/TimelinePanel-test.js +++ b/test/components/structures/TimelinePanel-test.js @@ -33,6 +33,24 @@ var test_utils = require('test-utils'); var ROOM_ID = '!room:localhost'; var USER_ID = '@me:localhost'; +// wrap TimelinePanel with a component which provides the MatrixClient in the context. +const WrappedTimelinePanel = React.createClass({ + childContextTypes: { + matrixClient: React.PropTypes.object, + }, + + getChildContext: function() { + return { + matrixClient: peg.get(), + }; + }, + + render: function() { + return ; + }, +}); + + describe('TimelinePanel', function() { var sandbox; var timelineSet; @@ -105,11 +123,12 @@ describe('TimelinePanel', function() { } var scrollDefer; - var panel = ReactDOM.render( - {scrollDefer.resolve()}} + var rendered = ReactDOM.render( + {scrollDefer.resolve()}} />, parentDiv, ); + var panel = rendered.refs.panel; var scrollingDiv = ReactTestUtils.findRenderedDOMComponentWithClass( panel, "gm-scroll-view"); @@ -188,10 +207,11 @@ describe('TimelinePanel', function() { return q(true); }); - var panel = ReactDOM.render( - , + var rendered = ReactDOM.render( + , parentDiv ); + var panel = rendered.refs.panel; var messagePanel = ReactTestUtils.findRenderedComponentWithType( panel, sdk.getComponent('structures.MessagePanel')); @@ -236,14 +256,14 @@ describe('TimelinePanel', function() { console.log("added events to timeline"); var scrollDefer; - var panel = ReactDOM.render( - {scrollDefer.resolve()}} + var rendered = ReactDOM.render( + {scrollDefer.resolve()}} timelineCap={TIMELINE_CAP} />, parentDiv ); console.log("TimelinePanel rendered"); - + var panel = rendered.refs.panel; var messagePanel = ReactTestUtils.findRenderedComponentWithType( panel, sdk.getComponent('structures.MessagePanel')); var scrollingDiv = ReactTestUtils.findRenderedDOMComponentWithClass( diff --git a/test/test-utils.js b/test/test-utils.js index 1201daefe0..db405c2e1a 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -24,23 +24,49 @@ export function beforeEach(context) { * Stub out the MatrixClient, and configure the MatrixClientPeg object to * return it when get() is called. * + * TODO: once the components are updated to get their MatrixClients from + * the react context, we can get rid of this and just inject a test client + * via the context instead. + * * @returns {sinon.Sandbox}; remember to call sandbox.restore afterwards. */ export function stubClient() { var sandbox = sinon.sandbox.create(); - var client = { + var client = createTestClient(); + + // stub out the methods in MatrixClientPeg + // + // 'sandbox.restore()' doesn't work correctly on inherited methods, + // so we do this for each method + var methods = ['get', 'unset', 'replaceUsingCreds']; + for (var i = 0; i < methods.length; i++) { + sandbox.stub(peg, methods[i]); + } + // MatrixClientPeg.get() is called a /lot/, so implement it with our own + // fast stub function rather than a sinon stub + peg.get = function() { return client; }; + return sandbox; +} + +/** + * Create a stubbed-out MatrixClient + * + * @returns {object} MatrixClient stub + */ +export function createTestClient() { + return { getHomeserverUrl: sinon.stub(), getIdentityServerUrl: sinon.stub(), getPushActionsForEvent: sinon.stub(), - getRoom: sinon.stub().returns(this.mkStubRoom()), + getRoom: sinon.stub().returns(mkStubRoom()), getRooms: sinon.stub().returns([]), loginFlows: sinon.stub(), on: sinon.stub(), removeListener: sinon.stub(), isRoomEncrypted: sinon.stub().returns(false), - peekInRoom: sinon.stub().returns(q(this.mkStubRoom())), + peekInRoom: sinon.stub().returns(q(mkStubRoom())), paginateEventTimeline: sinon.stub().returns(q()), sendReadReceipt: sinon.stub().returns(q()), @@ -59,22 +85,8 @@ export function stubClient() { sendHtmlMessage: () => q({}), getSyncState: () => "SYNCING", }; - - // stub out the methods in MatrixClientPeg - // - // 'sandbox.restore()' doesn't work correctly on inherited methods, - // so we do this for each method - var methods = ['get', 'unset', 'replaceUsingCreds']; - for (var i = 0; i < methods.length; i++) { - sandbox.stub(peg, methods[i]); - } - // MatrixClientPeg.get() is called a /lot/, so implement it with our own - // fast stub function rather than a sinon stub - peg.get = function() { return client; }; - return sandbox; } - /** * Create an Event. * @param {Object} opts Values for the event.