Inject MatrixClient into React context in tests

Now that EventTile expects MatrixClient in the context, we had better provide
it.
This commit is contained in:
Richard van der Hoff 2016-11-14 18:20:15 +00:00
parent 0e8a49ebb7
commit 22757cfcd3
3 changed files with 83 additions and 37 deletions

View file

@ -20,30 +20,44 @@ var TestUtils = require('react-addons-test-utils');
var expect = require('expect'); var expect = require('expect');
var sdk = require('matrix-react-sdk'); var sdk = require('matrix-react-sdk');
var MatrixClientPeg = require('MatrixClientPeg');
var MessagePanel = sdk.getComponent('structures.MessagePanel'); var MessagePanel = sdk.getComponent('structures.MessagePanel');
var test_utils = require('test-utils'); var test_utils = require('test-utils');
var mockclock = require('mock-clock'); 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 <MessagePanel {...this.props} />;
},
});
describe('MessagePanel', function () { describe('MessagePanel', function () {
var sandbox;
var clock = mockclock.clock(); var clock = mockclock.clock();
var realSetTimeout = window.setTimeout; var realSetTimeout = window.setTimeout;
var events = mkEvents(); var events = mkEvents();
beforeEach(function() { beforeEach(function() {
test_utils.beforeEach(this); test_utils.beforeEach(this);
sandbox = test_utils.stubClient(sandbox); client = test_utils.createTestClient();
var client = MatrixClientPeg.get();
client.credentials = {userId: '@me:here'}; client.credentials = {userId: '@me:here'};
}); });
afterEach(function () { afterEach(function () {
clock.uninstall(); clock.uninstall();
sandbox.restore();
}); });
function mkEvents() { function mkEvents() {
@ -61,7 +75,7 @@ describe('MessagePanel', function () {
it('should show the events', function() { it('should show the events', function() {
var res = TestUtils.renderIntoDocument( var res = TestUtils.renderIntoDocument(
<MessagePanel className="cls" events={events} /> <WrappedMessagePanel className="cls" events={events} />
); );
// just check we have the right number of tiles for now // 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() { it('should show the read-marker in the right place', function() {
var res = TestUtils.renderIntoDocument( var res = TestUtils.renderIntoDocument(
<MessagePanel className="cls" events={events} readMarkerEventId={events[4].getId()} <WrappedMessagePanel className="cls" events={events} readMarkerEventId={events[4].getId()}
readMarkerVisible={true} /> readMarkerVisible={true} />
); );
@ -96,7 +110,7 @@ describe('MessagePanel', function () {
// first render with the RM in one place // first render with the RM in one place
var mp = ReactDOM.render( var mp = ReactDOM.render(
<MessagePanel className="cls" events={events} readMarkerEventId={events[4].getId()} <WrappedMessagePanel className="cls" events={events} readMarkerEventId={events[4].getId()}
readMarkerVisible={true} readMarkerVisible={true}
/>, parentDiv); />, parentDiv);
@ -112,7 +126,7 @@ describe('MessagePanel', function () {
// now move the RM // now move the RM
mp = ReactDOM.render( mp = ReactDOM.render(
<MessagePanel className="cls" events={events} readMarkerEventId={events[6].getId()} <WrappedMessagePanel className="cls" events={events} readMarkerEventId={events[6].getId()}
readMarkerVisible={true} readMarkerVisible={true}
/>, parentDiv); />, parentDiv);
@ -147,7 +161,7 @@ describe('MessagePanel', function () {
// first render with the RM in one place // first render with the RM in one place
var mp = ReactDOM.render( var mp = ReactDOM.render(
<MessagePanel className="cls" events={events} readMarkerEventId={events[4].getId()} <WrappedMessagePanel className="cls" events={events} readMarkerEventId={events[4].getId()}
readMarkerVisible={true} readMarkerVisible={true}
/>, parentDiv); />, parentDiv);
@ -159,7 +173,7 @@ describe('MessagePanel', function () {
// now move the RM // now move the RM
mp = ReactDOM.render( mp = ReactDOM.render(
<MessagePanel className="cls" events={events} readMarkerEventId={events[6].getId()} <WrappedMessagePanel className="cls" events={events} readMarkerEventId={events[6].getId()}
readMarkerVisible={true} readMarkerVisible={true}
/>, parentDiv); />, parentDiv);
@ -175,7 +189,7 @@ describe('MessagePanel', function () {
// and move the RM again // and move the RM again
mp = ReactDOM.render( mp = ReactDOM.render(
<MessagePanel className="cls" events={events} readMarkerEventId={events[8].getId()} <WrappedMessagePanel className="cls" events={events} readMarkerEventId={events[8].getId()}
readMarkerVisible={true} readMarkerVisible={true}
/>, parentDiv); />, parentDiv);

View file

@ -33,6 +33,24 @@ var test_utils = require('test-utils');
var ROOM_ID = '!room:localhost'; var ROOM_ID = '!room:localhost';
var USER_ID = '@me: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 <TimelinePanel ref="panel" {...this.props} />;
},
});
describe('TimelinePanel', function() { describe('TimelinePanel', function() {
var sandbox; var sandbox;
var timelineSet; var timelineSet;
@ -105,11 +123,12 @@ describe('TimelinePanel', function() {
} }
var scrollDefer; var scrollDefer;
var panel = ReactDOM.render( var rendered = ReactDOM.render(
<TimelinePanel timelineSet={timelineSet} onScroll={() => {scrollDefer.resolve()}} <WrappedTimelinePanel timelineSet={timelineSet} onScroll={() => {scrollDefer.resolve()}}
/>, />,
parentDiv, parentDiv,
); );
var panel = rendered.refs.panel;
var scrollingDiv = ReactTestUtils.findRenderedDOMComponentWithClass( var scrollingDiv = ReactTestUtils.findRenderedDOMComponentWithClass(
panel, "gm-scroll-view"); panel, "gm-scroll-view");
@ -188,10 +207,11 @@ describe('TimelinePanel', function() {
return q(true); return q(true);
}); });
var panel = ReactDOM.render( var rendered = ReactDOM.render(
<TimelinePanel timelineSet={timelineSet}/>, <WrappedTimelinePanel timelineSet={timelineSet}/>,
parentDiv parentDiv
); );
var panel = rendered.refs.panel;
var messagePanel = ReactTestUtils.findRenderedComponentWithType( var messagePanel = ReactTestUtils.findRenderedComponentWithType(
panel, sdk.getComponent('structures.MessagePanel')); panel, sdk.getComponent('structures.MessagePanel'));
@ -236,14 +256,14 @@ describe('TimelinePanel', function() {
console.log("added events to timeline"); console.log("added events to timeline");
var scrollDefer; var scrollDefer;
var panel = ReactDOM.render( var rendered = ReactDOM.render(
<TimelinePanel timelineSet={timelineSet} onScroll={() => {scrollDefer.resolve()}} <WrappedTimelinePanel timelineSet={timelineSet} onScroll={() => {scrollDefer.resolve()}}
timelineCap={TIMELINE_CAP} timelineCap={TIMELINE_CAP}
/>, />,
parentDiv parentDiv
); );
console.log("TimelinePanel rendered"); console.log("TimelinePanel rendered");
var panel = rendered.refs.panel;
var messagePanel = ReactTestUtils.findRenderedComponentWithType( var messagePanel = ReactTestUtils.findRenderedComponentWithType(
panel, sdk.getComponent('structures.MessagePanel')); panel, sdk.getComponent('structures.MessagePanel'));
var scrollingDiv = ReactTestUtils.findRenderedDOMComponentWithClass( var scrollingDiv = ReactTestUtils.findRenderedDOMComponentWithClass(

View file

@ -24,23 +24,49 @@ export function beforeEach(context) {
* Stub out the MatrixClient, and configure the MatrixClientPeg object to * Stub out the MatrixClient, and configure the MatrixClientPeg object to
* return it when get() is called. * 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. * @returns {sinon.Sandbox}; remember to call sandbox.restore afterwards.
*/ */
export function stubClient() { export function stubClient() {
var sandbox = sinon.sandbox.create(); 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(), getHomeserverUrl: sinon.stub(),
getIdentityServerUrl: sinon.stub(), getIdentityServerUrl: sinon.stub(),
getPushActionsForEvent: sinon.stub(), getPushActionsForEvent: sinon.stub(),
getRoom: sinon.stub().returns(this.mkStubRoom()), getRoom: sinon.stub().returns(mkStubRoom()),
getRooms: sinon.stub().returns([]), getRooms: sinon.stub().returns([]),
loginFlows: sinon.stub(), loginFlows: sinon.stub(),
on: sinon.stub(), on: sinon.stub(),
removeListener: sinon.stub(), removeListener: sinon.stub(),
isRoomEncrypted: sinon.stub().returns(false), isRoomEncrypted: sinon.stub().returns(false),
peekInRoom: sinon.stub().returns(q(this.mkStubRoom())), peekInRoom: sinon.stub().returns(q(mkStubRoom())),
paginateEventTimeline: sinon.stub().returns(q()), paginateEventTimeline: sinon.stub().returns(q()),
sendReadReceipt: sinon.stub().returns(q()), sendReadReceipt: sinon.stub().returns(q()),
@ -59,22 +85,8 @@ export function stubClient() {
sendHtmlMessage: () => q({}), sendHtmlMessage: () => q({}),
getSyncState: () => "SYNCING", 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. * Create an Event.
* @param {Object} opts Values for the event. * @param {Object} opts Values for the event.